d9e90eab40dce57e7433f3b178ae8324c79dac17
[samba.git] / source4 / torture / smbtorture.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB torture tester
4    Copyright (C) Andrew Tridgell 1997-2003
5    Copyright (C) Jelmer Vernooij 2006-2008
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "lib/cmdline/cmdline.h"
23 #include "system/time.h"
24 #include "system/wait.h"
25 #include "system/filesys.h"
26 #include "system/readline.h"
27 #include "../libcli/smbreadline/smbreadline.h"
28 #include "libcli/libcli.h"
29 #include "lib/events/events.h"
30
31 #include "torture/smbtorture.h"
32 #include "librpc/rpc/dcerpc.h"
33 #include "auth/gensec/gensec.h"
34 #include "param/param.h"
35 #include "lib/util/samba_modules.h"
36
37 #ifdef HAVE_READLINE_HISTORY_H
38 #include <readline/history.h>
39 #endif
40
41 static int use_fullname;
42
43 static char *prefix_name(TALLOC_CTX *mem_ctx, const char *prefix, const char *name)
44 {
45         if (prefix == NULL)
46                 return talloc_strdup(mem_ctx, name);
47         else
48                 return talloc_asprintf(mem_ctx, "%s.%s", prefix, name);
49 }
50
51 static void print_test_list(const struct torture_suite *suite, const char *prefix, const char *expr)
52 {
53         struct torture_suite *o;
54         struct torture_tcase *t;
55         struct torture_test *p;
56
57         for (o = suite->children; o; o = o->next) {
58                 char *name = prefix_name(NULL, prefix, o->name);
59                 print_test_list(o, name, expr);
60                 talloc_free(name);
61         }
62
63         for (t = suite->testcases; t; t = t->next) {
64                 for (p = t->tests; p; p = p->next) {
65                         char *name = talloc_asprintf(NULL, "%s.%s.%s", prefix, t->name, p->name);
66                         if (strncmp(name, expr, strlen(expr)) == 0) {
67                                 printf("%s\n", name);
68                         }
69                         talloc_free(name);
70                 }
71         }
72 }
73
74 static bool run_matching(struct torture_context *torture,
75                                                  const char *prefix, 
76                                                  const char *expr,
77                                                  const char **restricted,
78                                                  struct torture_suite *suite,
79                                                  bool *matched)
80 {
81         bool ret = true;
82         struct torture_suite *o;
83         struct torture_tcase *t;
84         struct torture_test *p;
85
86         for (o = suite->children; o; o = o->next) {
87                 char *name = NULL;
88                 name = prefix_name(torture, prefix, o->name);
89                 if (gen_fnmatch(expr, name) == 0) {
90                         *matched = true;
91                         reload_charcnv(torture->lp_ctx);
92                         if (use_fullname == 1) {
93                                 torture_subunit_prefix_reset(torture, prefix);
94                         }
95                         ret &= torture_run_suite_restricted(torture, o, restricted);
96                         if (use_fullname == 1) {
97                                 torture_subunit_prefix_reset(torture, NULL);
98                         }
99                         /*
100                          * torture_run_suite_restricted() already implements
101                          * recursion, so we're done with this child suite.
102                          */
103                         continue;
104                 }
105                 ret &= run_matching(torture, name, expr, restricted, o, matched);
106         }
107
108         for (t = suite->testcases; t; t = t->next) {
109                 char *tname = prefix_name(torture, prefix, t->name);
110                 if (gen_fnmatch(expr, tname) == 0) {
111                         *matched = true;
112                         reload_charcnv(torture->lp_ctx);
113                         if (use_fullname == 1) {
114                                 torture_subunit_prefix_reset(torture, prefix);
115                         }
116                         ret &= torture_run_tcase_restricted(torture, t, restricted);
117                         if (use_fullname == 1) {
118                                 torture_subunit_prefix_reset(torture, NULL);
119                         }
120                         /*
121                          * torture_run_tcase_restricted() already implements
122                          * recursion, so we're done for this tcase.
123                          */
124                         continue;
125                 }
126                 for (p = t->tests; p; p = p->next) {
127                         char *pname = prefix_name(torture, tname, p->name);
128                         if (gen_fnmatch(expr, pname) == 0) {
129                                 *matched = true;
130                                 reload_charcnv(torture->lp_ctx);
131                                 if (use_fullname == 1) {
132                                         torture_subunit_prefix_reset(torture,
133                                                                      tname);
134                                 }
135                                 ret &= torture_run_test_restricted(torture, t, p, restricted);
136                                 if (use_fullname == 1) {
137                                         torture_subunit_prefix_reset(torture,
138                                                                      NULL);
139                                 }
140                         }
141                 }
142         }
143
144         return ret;
145 }
146
147 #define MAX_COLS 80 /* FIXME: Determine this at run-time */
148
149 /****************************************************************************
150 run a specified test or "ALL"
151 ****************************************************************************/
152 bool torture_run_named_tests(struct torture_context *torture, const char *name,
153                             const char **restricted)
154 {
155         bool ret = true;
156         bool matched = false;
157         struct torture_suite *o;
158
159         torture_ui_report_time(torture);
160
161         if (strequal(name, "ALL")) {
162                 if (restricted != NULL) {
163                         printf("--load-list and ALL are incompatible\n");
164                         return false;
165                 }
166                 for (o = torture_root->children; o; o = o->next) {
167                         ret &= torture_run_suite(torture, o);
168                 }
169                 return ret;
170         }
171
172         ret = run_matching(torture, NULL, name, restricted, torture_root, &matched);
173
174         if (!matched) {
175                 printf("Unknown torture operation '%s'\n", name);
176                 return false;
177         }
178
179         return ret;
180 }
181
182 bool torture_parse_target(TALLOC_CTX *ctx,
183                                 struct loadparm_context *lp_ctx,
184                                 const char *target)
185 {
186         char *host = NULL, *share = NULL;
187         struct dcerpc_binding *binding_struct;
188         NTSTATUS status;
189
190         /* see if its a RPC transport specifier */
191         if (!smbcli_parse_unc(target, NULL, &host, &share)) {
192                 const char *h;
193
194                 status = dcerpc_parse_binding(ctx, target, &binding_struct);
195                 if (NT_STATUS_IS_ERR(status)) {
196                         d_printf("Invalid option: %s is not a valid torture target (share or binding string)\n\n", target);
197                         return false;
198                 }
199
200                 h = dcerpc_binding_get_string_option(binding_struct, "host");
201                 host = discard_const_p(char, h);
202                 if (host != NULL) {
203                         lpcfg_set_cmdline(lp_ctx, "torture:host", host);
204                 }
205
206                 if (lpcfg_parm_string(lp_ctx, NULL, "torture", "share") == NULL)
207                         lpcfg_set_cmdline(lp_ctx, "torture:share", "IPC$");
208                 lpcfg_set_cmdline(lp_ctx, "torture:binding", target);
209         } else {
210                 lpcfg_set_cmdline(lp_ctx, "torture:host", host);
211                 lpcfg_set_cmdline(lp_ctx, "torture:share", share);
212                 lpcfg_set_cmdline(lp_ctx, "torture:binding", host);
213         }
214
215         return true;
216 }
217
218 static void parse_dns(struct loadparm_context *lp_ctx, const char *dns)
219 {
220         char *userdn, *basedn, *secret;
221         char *p, *d;
222
223         /* retrieve the userdn */
224         p = strchr_m(dns, '#');
225         if (!p) {
226                 lpcfg_set_cmdline(lp_ctx, "torture:ldap_userdn", "");
227                 lpcfg_set_cmdline(lp_ctx, "torture:ldap_basedn", "");
228                 lpcfg_set_cmdline(lp_ctx, "torture:ldap_secret", "");
229                 return;
230         }
231         userdn = strndup(dns, p - dns);
232         lpcfg_set_cmdline(lp_ctx, "torture:ldap_userdn", userdn);
233
234         /* retrieve the basedn */
235         d = p + 1;
236         p = strchr_m(d, '#');
237         if (!p) {
238                 lpcfg_set_cmdline(lp_ctx, "torture:ldap_basedn", "");
239                 lpcfg_set_cmdline(lp_ctx, "torture:ldap_secret", "");
240                 return;
241         }
242         basedn = strndup(d, p - d);
243         lpcfg_set_cmdline(lp_ctx, "torture:ldap_basedn", basedn);
244
245         /* retrieve the secret */
246         p = p + 1;
247         if (!p) {
248                 lpcfg_set_cmdline(lp_ctx, "torture:ldap_secret", "");
249                 return;
250         }
251         secret = strdup(p);
252         lpcfg_set_cmdline(lp_ctx, "torture:ldap_secret", secret);
253
254         printf ("%s - %s - %s\n", userdn, basedn, secret);
255
256 }
257
258 /* Print the full test list, formatted into separate labelled test
259  * groups.
260  */
261 static void print_structured_testsuite_list(void)
262 {
263         struct torture_suite *o;
264         struct torture_suite *s;
265         struct torture_tcase *t;
266         int i;
267
268         if (torture_root == NULL) {
269             printf("NO TESTS LOADED\n");
270             return;
271         }
272
273         for (o = torture_root->children; o; o = o->next) {
274                 printf("\n%s (%s):\n  ", o->description, o->name);
275
276                 i = 0;
277                 for (s = o->children; s; s = s->next) {
278                         if (i + strlen(o->name) + strlen(s->name) >= (MAX_COLS - 3)) {
279                                 printf("\n  ");
280                                 i = 0;
281                         }
282                         i+=printf("%s.%s ", o->name, s->name);
283                 }
284
285                 for (t = o->testcases; t; t = t->next) {
286                         if (i + strlen(o->name) + strlen(t->name) >= (MAX_COLS - 3)) {
287                                 printf("\n  ");
288                                 i = 0;
289                         }
290                         i+=printf("%s.%s ", o->name, t->name);
291                 }
292
293                 if (i) printf("\n");
294         }
295
296         printf("\nThe default test is ALL.\n");
297 }
298
299 static void print_testsuite_list(void)
300 {
301         struct torture_suite *o;
302         struct torture_suite *s;
303         struct torture_tcase *t;
304
305         if (torture_root == NULL)
306                 return;
307
308         for (o = torture_root->children; o; o = o->next) {
309                 for (s = o->children; s; s = s->next) {
310                         printf("%s.%s\n", o->name, s->name);
311                 }
312
313                 for (t = o->testcases; t; t = t->next) {
314                         printf("%s.%s\n", o->name, t->name);
315                 }
316         }
317 }
318
319 void torture_print_testsuites(bool structured)
320 {
321         if (structured) {
322                 print_structured_testsuite_list();
323         } else {
324                 print_testsuite_list();
325         }
326 }
327
328 static void usage(poptContext pc)
329 {
330         poptPrintUsage(pc, stdout, 0);
331         printf("\n");
332
333         printf("The binding format is:\n\n");
334
335         printf("  TRANSPORT:host[flags]\n\n");
336
337         printf("  where TRANSPORT is either ncacn_np for SMB, ncacn_ip_tcp for RPC/TCP\n");
338         printf("  or ncalrpc for local connections.\n\n");
339
340         printf("  'host' is an IP or hostname or netbios name. If the binding string\n");
341         printf("  identifies the server side of an endpoint, 'host' may be an empty\n");
342         printf("  string.\n\n");
343
344         printf("  'flags' can include a SMB pipe name if using the ncacn_np transport or\n");
345         printf("  a TCP port number if using the ncacn_ip_tcp transport, otherwise they\n");
346         printf("  will be auto-determined.\n\n");
347
348         printf("  other recognised flags are:\n\n");
349
350         printf("    sign : enable ntlmssp signing\n");
351         printf("    seal : enable ntlmssp sealing\n");
352         printf("    connect : enable rpc connect level auth (auth, but no sign or seal)\n");
353         printf("    validate: enable the NDR validator\n");
354         printf("    print: enable debugging of the packets\n");
355         printf("    bigendian: use bigendian RPC\n");
356         printf("    padcheck: check reply data for non-zero pad bytes\n\n");
357
358         printf("  For example, these all connect to the samr pipe:\n\n");
359
360         printf("    ncacn_np:myserver\n");
361         printf("    ncacn_np:myserver[samr]\n");
362         printf("    ncacn_np:myserver[\\pipe\\samr]\n");
363         printf("    ncacn_np:myserver[/pipe/samr]\n");
364         printf("    ncacn_np:myserver[samr,sign,print]\n");
365         printf("    ncacn_np:myserver[\\pipe\\samr,sign,seal,bigendian]\n");
366         printf("    ncacn_np:myserver[/pipe/samr,seal,validate]\n");
367         printf("    ncacn_np:\n");
368         printf("    ncacn_np:[/pipe/samr]\n\n");
369
370         printf("    ncacn_ip_tcp:myserver\n");
371         printf("    ncacn_ip_tcp:myserver[1024]\n");
372         printf("    ncacn_ip_tcp:myserver[1024,sign,seal]\n\n");
373
374         printf("    ncalrpc:\n\n");
375
376         printf("The UNC format is:\n\n");
377
378         printf("  //server/share\n\n");
379
380         printf("Tests are:");
381
382         print_structured_testsuite_list();
383
384 }
385
386 _NORETURN_ static void max_runtime_handler(int sig)
387 {
388         DEBUG(0,("maximum runtime exceeded for smbtorture - terminating\n"));
389         exit(1);
390 }
391
392 /****************************************************************************
393   main program
394 ****************************************************************************/
395 int main(int argc, const char *argv[])
396 {
397         int opt, i;
398         bool correct = true;
399         int max_runtime=0;
400         int argc_new;
401         struct torture_context *torture;
402         struct torture_results *results;
403         const struct torture_ui_ops *ui_ops;
404         char **argv_new;
405         poptContext pc;
406         static const char *target = "other";
407         NTSTATUS status;
408         int shell = false;
409         static const char *ui_ops_name = "subunit";
410         const char *basedir = NULL;
411         char *outputdir;
412         const char *extra_module = NULL;
413         static int list_tests = 0, list_testsuites = 0;
414         int num_extra_users = 0;
415         const char **restricted = NULL;
416         int num_restricted = -1;
417         const char *load_list = NULL;
418         enum {OPT_LOADFILE=1000,OPT_UNCLIST,OPT_TIMELIMIT,OPT_DNS, OPT_LIST,
419               OPT_DANGEROUS,OPT_SMB_PORTS,OPT_ASYNC,OPT_NUMPROGS,
420               OPT_EXTRA_USER,};
421         TALLOC_CTX *mem_ctx = NULL;
422         struct loadparm_context *lp_ctx = NULL;
423         bool ok;
424
425         struct poptOption long_options[] = {
426                 POPT_AUTOHELP
427                 {"fullname",    0, POPT_ARG_NONE, &use_fullname, 0,
428                  "use full name for the test", NULL },
429                 {"format", 0, POPT_ARG_STRING, &ui_ops_name, 0, "Output format (one of: simple, subunit)", NULL },
430                 {"smb-ports",   'p', POPT_ARG_STRING, NULL,     OPT_SMB_PORTS,  "SMB ports",    NULL},
431                 {"basedir",       0, POPT_ARG_STRING, &basedir, 0, "base directory", "BASEDIR" },
432                 {"seed",          0, POPT_ARG_INT,  &torture_seed,      0,      "Seed to use for randomizer",   NULL},
433                 {"num-progs",     0, POPT_ARG_INT,  NULL,       OPT_NUMPROGS,   "num progs",    NULL},
434                 {"num-ops",       0, POPT_ARG_INT,  &torture_numops,    0,      "num ops",      NULL},
435                 {"entries",       0, POPT_ARG_INT,  &torture_entries,   0,      "entries",      NULL},
436                 {"loadfile",      0, POPT_ARG_STRING,   NULL,   OPT_LOADFILE,   "NBench load file to use",      NULL},
437                 {"list-suites",           0, POPT_ARG_NONE, &list_testsuites, 0, "List available testsuites and exit", NULL },
438                 {"list",          0, POPT_ARG_NONE, &list_tests, 0, "List available tests in specified suites and exit", NULL },
439                 {"unclist",       0, POPT_ARG_STRING,   NULL,   OPT_UNCLIST,    "unclist",      NULL},
440                 {"timelimit",   't', POPT_ARG_INT,      NULL,   OPT_TIMELIMIT,  "Set time limit (in seconds)",  NULL},
441                 {"failures",    'f', POPT_ARG_INT,  &torture_failures,  0,      "failures",     NULL},
442                 {"parse-dns",   'D', POPT_ARG_STRING,   NULL,   OPT_DNS,        "parse-dns",    NULL},
443                 {"dangerous",   'X', POPT_ARG_NONE,     NULL,   OPT_DANGEROUS,
444                  "run dangerous tests (eg. wiping out password database)", NULL},
445                 {"load-module",  0,  POPT_ARG_STRING, &extra_module,     0, "load tests from DSO file",    "SOFILE"},
446                 {"shell",               0, POPT_ARG_NONE, &shell, true, "Run shell", NULL},
447                 {"target",              'T', POPT_ARG_STRING, &target, 0, "samba3|samba4|other", NULL},
448                 {"async",       'a', POPT_ARG_NONE,     NULL,   OPT_ASYNC,
449                  "run async tests", NULL},
450                 {"num-async",    0, POPT_ARG_INT,  &torture_numasync,  0,
451                  "number of simultaneous async requests", NULL},
452                 {"maximum-runtime", 0, POPT_ARG_INT, &max_runtime, 0, 
453                  "set maximum time for smbtorture to live", "seconds"},
454                 {"extra-user",   0, POPT_ARG_STRING, NULL, OPT_EXTRA_USER,
455                  "extra user credentials", NULL},
456                 {"load-list", 0, POPT_ARG_STRING, &load_list, 0,
457              "load a test id list from a text file", NULL},
458                 POPT_COMMON_SAMBA
459                 POPT_COMMON_CONNECTION
460                 POPT_COMMON_CREDENTIALS
461                 POPT_COMMON_VERSION
462                 POPT_LEGACY_S4
463                 POPT_TABLEEND
464         };
465
466         setlinebuf(stdout);
467
468         mem_ctx = talloc_named_const(NULL, 0, "torture_ctx");
469         if (mem_ctx == NULL) {
470                 printf("Unable to allocate torture_ctx\n");
471                 exit(1);
472         }
473
474         printf("smbtorture %s\n", samba_version_string());
475
476         /* we are never interested in SIGPIPE */
477         BlockSignals(true, SIGPIPE);
478
479         ok = samba_cmdline_init(mem_ctx,
480                                 SAMBA_CMDLINE_CONFIG_CLIENT,
481                                 false /* require_smbconf */);
482         if (!ok) {
483                 DBG_ERR("Unable to init cmdline parser\n");
484                 TALLOC_FREE(mem_ctx);
485                 exit(1);
486         }
487
488         pc = samba_popt_get_context(getprogname(),
489                                     argc,
490                                     argv,
491                                     long_options,
492                                     POPT_CONTEXT_KEEP_FIRST);
493         if (pc == NULL) {
494                 DBG_ERR("Failed cmdline parser\n");
495                 TALLOC_FREE(mem_ctx);
496                 exit(1);
497         }
498
499         poptSetOtherOptionHelp(pc, "<binding>|<unc> TEST1 TEST2 ...");
500
501         lp_ctx = samba_cmdline_get_lp_ctx();
502
503         while((opt = poptGetNextOpt(pc)) != -1) {
504                 switch (opt) {
505                 case OPT_LOADFILE:
506                         lpcfg_set_cmdline(lp_ctx, "torture:loadfile", poptGetOptArg(pc));
507                         break;
508                 case OPT_UNCLIST:
509                         lpcfg_set_cmdline(lp_ctx, "torture:unclist", poptGetOptArg(pc));
510                         break;
511                 case OPT_TIMELIMIT:
512                         lpcfg_set_cmdline(lp_ctx, "torture:timelimit", poptGetOptArg(pc));
513                         break;
514                 case OPT_NUMPROGS:
515                         lpcfg_set_cmdline(lp_ctx, "torture:nprocs", poptGetOptArg(pc));
516                         break;
517                 case OPT_DNS:
518                         parse_dns(lp_ctx, poptGetOptArg(pc));
519                         break;
520                 case OPT_DANGEROUS:
521                         lpcfg_set_cmdline(lp_ctx, "torture:dangerous", "Yes");
522                         break;
523                 case OPT_ASYNC:
524                         lpcfg_set_cmdline(lp_ctx, "torture:async", "Yes");
525                         break;
526                 case OPT_SMB_PORTS:
527                         lpcfg_set_cmdline(lp_ctx, "smb ports", poptGetOptArg(pc));
528                         break;
529                 case OPT_EXTRA_USER:
530                         {
531                                 char *option = talloc_asprintf(mem_ctx,
532                                                 "torture:extra_user%u",
533                                                 ++num_extra_users);
534                                 const char *value = poptGetOptArg(pc);
535                                 if (option == NULL) {
536                                         printf("talloc fail\n");
537                                         talloc_free(mem_ctx);
538                                         exit(1);
539                                 }
540                                 lpcfg_set_cmdline(lp_ctx, option, value);
541                                 talloc_free(option);
542                         }
543                         break;
544                 default:
545                         if (opt < 0) {
546                                 printf("Invalid command line option %s (%d)\n",
547                                        poptBadOption(pc, 0),
548                                        opt);
549                                 talloc_free(mem_ctx);
550                                 exit(1);
551                         }
552                 }
553         }
554
555         if (load_list != NULL) {
556                 char **r;
557                 r = file_lines_load(load_list, &num_restricted, 0, mem_ctx);
558                 restricted = discard_const_p(const char *, r);
559                 if (restricted == NULL) {
560                         printf("Unable to read load list file '%s'\n", load_list);
561                         talloc_free(mem_ctx);
562                         exit(1);
563                 }
564         }
565
566         if (strcmp(target, "samba3") == 0) {
567                 lpcfg_set_cmdline(lp_ctx, "torture:samba3", "true");
568                 lpcfg_set_cmdline(lp_ctx, "torture:resume_key_support", "false");
569         } else if (strcmp(target, "samba4") == 0) {
570                 lpcfg_set_cmdline(lp_ctx, "torture:samba4", "true");
571         } else if (strcmp(target, "samba4-ntvfs") == 0) {
572                 lpcfg_set_cmdline(lp_ctx, "torture:samba4", "true");
573                 lpcfg_set_cmdline(lp_ctx, "torture:samba4-ntvfs", "true");
574         } else if (strcmp(target, "winxp") == 0) {
575                 lpcfg_set_cmdline(lp_ctx, "torture:winxp", "true");
576         } else if (strcmp(target, "w2k3") == 0) {
577                 lpcfg_set_cmdline(lp_ctx, "torture:w2k3", "true");
578         } else if (strcmp(target, "w2k8") == 0) {
579                 lpcfg_set_cmdline(lp_ctx, "torture:w2k8", "true");
580                 lpcfg_set_cmdline(lp_ctx,
581                     "torture:invalid_lock_range_support", "false");
582         } else if (strcmp(target, "w2k12") == 0) {
583                 lpcfg_set_cmdline(lp_ctx, "torture:w2k12", "true");
584         } else if (strcmp(target, "win7") == 0) {
585                 lpcfg_set_cmdline(lp_ctx, "torture:win7", "true");
586                 lpcfg_set_cmdline(lp_ctx, "torture:resume_key_support", "false");
587                 lpcfg_set_cmdline(lp_ctx, "torture:rewind_support", "false");
588
589                 /* RAW-SEARCH for fails for inexplicable reasons against win7 */
590                 lpcfg_set_cmdline(lp_ctx, "torture:search_ea_support", "false");
591
592                 lpcfg_set_cmdline(lp_ctx, "torture:hide_on_access_denied",
593                     "true");
594         } else if (strcmp(target, "onefs") == 0) {
595                 lpcfg_set_cmdline(lp_ctx, "torture:onefs", "true");
596                 lpcfg_set_cmdline(lp_ctx, "torture:openx_deny_dos_support",
597                     "false");
598                 lpcfg_set_cmdline(lp_ctx, "torture:range_not_locked_on_file_close", "false");
599                 lpcfg_set_cmdline(lp_ctx, "torture:sacl_support", "false");
600                 lpcfg_set_cmdline(lp_ctx, "torture:ea_support", "false");
601                 lpcfg_set_cmdline(lp_ctx, "torture:smbexit_pdu_support",
602                     "false");
603                 lpcfg_set_cmdline(lp_ctx, "torture:smblock_pdu_support",
604                     "false");
605                 lpcfg_set_cmdline(lp_ctx, "torture:2_step_break_to_none",
606                     "true");
607                 lpcfg_set_cmdline(lp_ctx, "torture:deny_dos_support", "false");
608                 lpcfg_set_cmdline(lp_ctx, "torture:deny_fcb_support", "false");
609                 lpcfg_set_cmdline(lp_ctx, "torture:read_support", "false");
610                 lpcfg_set_cmdline(lp_ctx, "torture:writeclose_support", "false");
611                 lpcfg_set_cmdline(lp_ctx, "torture:resume_key_support", "false");
612                 lpcfg_set_cmdline(lp_ctx, "torture:rewind_support", "false");
613                 lpcfg_set_cmdline(lp_ctx, "torture:raw_search_search", "false");
614                 lpcfg_set_cmdline(lp_ctx, "torture:search_ea_size", "false");
615         }
616
617         if (max_runtime) {
618                 /* this will only work if nobody else uses alarm(),
619                    which means it won't work for some tests, but we
620                    can't use the event context method we use for smbd
621                    as so many tests create their own event
622                    context. This will at least catch most cases. */
623                 signal(SIGALRM, max_runtime_handler);
624                 alarm(max_runtime);
625         }
626
627         if (extra_module != NULL) {
628                 init_module_fn fn = load_module(poptGetOptArg(pc), false, NULL);
629
630                 if (fn == NULL) 
631                         d_printf("Unable to load module from %s\n", poptGetOptArg(pc));
632                 else {
633                         status = fn(mem_ctx);
634                         if (NT_STATUS_IS_ERR(status)) {
635                                 d_printf("Error initializing module %s: %s\n", 
636                                         poptGetOptArg(pc), nt_errstr(status));
637                         }
638                 }
639         } else { 
640                 torture_init(mem_ctx);
641         }
642
643         if (list_testsuites) {
644                 print_testsuite_list();
645                 poptFreeContext(pc);
646                 talloc_free(mem_ctx);
647                 return 0;
648         }
649
650         argv_new = discard_const_p(char *, poptGetArgs(pc));
651
652         argc_new = argc;
653         for (i=0; i<argc; i++) {
654                 if (argv_new[i] == NULL) {
655                         argc_new = i;
656                         break;
657                 }
658         }
659
660         if (list_tests) {
661                 if (argc_new == 1) {
662                         print_test_list(torture_root, NULL, "");
663                 } else {
664                         for (i=1;i<argc_new;i++) {
665                                 print_test_list(torture_root, NULL, argv_new[i]);
666                         }
667                 }
668                 poptFreeContext(pc);
669                 talloc_free(mem_ctx);
670                 return 0;
671         }
672
673         if (torture_seed == 0) {
674                 torture_seed = time(NULL);
675         } 
676         printf("Using seed %d\n", torture_seed);
677         srandom(torture_seed);
678
679         if (!strcmp(ui_ops_name, "simple")) {
680                 ui_ops = &torture_simple_ui_ops;
681         } else if (!strcmp(ui_ops_name, "subunit")) {
682                 ui_ops = &torture_subunit_ui_ops;
683         } else {
684                 printf("Unknown output format '%s'\n", ui_ops_name);
685                 talloc_free(mem_ctx);
686                 exit(1);
687         }
688
689         results = torture_results_init(mem_ctx, ui_ops);
690
691         torture = torture_context_init(s4_event_context_init(mem_ctx),
692                                        results);
693         if (basedir != NULL) {
694                 if (basedir[0] != '/') {
695                         fprintf(stderr, "Please specify an absolute path to --basedir\n");
696                         poptFreeContext(pc);
697                         talloc_free(mem_ctx);
698                         return 1;
699                 }
700                 outputdir = talloc_asprintf(torture, "%s/smbtortureXXXXXX", basedir);
701         } else {
702                 char *pwd = talloc_size(torture, PATH_MAX);
703                 if (!getcwd(pwd, PATH_MAX)) {
704                         fprintf(stderr, "Unable to determine current working directory\n");
705                         poptFreeContext(pc);
706                         talloc_free(mem_ctx);
707                         return 1;
708                 }
709                 outputdir = talloc_asprintf(torture, "%s/smbtortureXXXXXX", pwd);
710         }
711         if (!outputdir) {
712                 fprintf(stderr, "Could not allocate per-run output dir\n");
713                 poptFreeContext(pc);
714                 talloc_free(mem_ctx);
715                 return 1;
716         }
717         torture->outputdir = mkdtemp(outputdir);
718         if (!torture->outputdir) {
719                 perror("Failed to make temp output dir");
720                 poptFreeContext(pc);
721                 talloc_free(mem_ctx);
722                 return 1;
723         }
724
725         torture->lp_ctx = lp_ctx;
726
727         gensec_init();
728
729         if (shell) {
730                 /* In shell mode, just ignore any remaining test names. */
731                 torture_shell(torture);
732         } else {
733
734                 /* At this point, we should just have a target string,
735                  * followed by a series of test names. Unless we are in
736                  * shell mode, in which case we don't need anything more.
737                  */
738
739                 if (argc_new < 3) {
740                         printf("You must specify a test to run, or 'ALL'\n");
741                         usage(pc);
742                         torture->results->returncode = 1;
743                 } else if (!torture_parse_target(torture,
744                                         lp_ctx, argv_new[1])) {
745                         /* Take the target name or binding. */
746                         usage(pc);
747                         torture->results->returncode = 1;
748                 } else {
749                         for (i=2;i<argc_new;i++) {
750                                 if (!torture_run_named_tests(torture, argv_new[i],
751                                             (const char **)restricted)) {
752                                         correct = false;
753                                 }
754                         }
755                 }
756         }
757
758         /* Now delete the temp dir we created */
759         torture_deltree_outputdir(torture);
760
761         if (torture->results->returncode && correct) {
762                 poptFreeContext(pc);
763                 talloc_free(mem_ctx);
764                 return(0);
765         } else {
766                 poptFreeContext(pc);
767                 talloc_free(mem_ctx);
768                 return(1);
769         }
770 }