smbtorture: Add list command to smbtorture shell.
[abartlet/samba.git/.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/popt_common.h"
23 #include "system/time.h"
24 #include "system/wait.h"
25 #include "system/filesys.h"
26 #include "system/readline.h"
27 #include "lib/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
36
37 static bool run_matching(struct torture_context *torture,
38                                                  const char *prefix, 
39                                                  const char *expr,
40                                                  char **restricted,
41                                                  struct torture_suite *suite,
42                                                  bool *matched)
43 {
44         bool ret = true;
45         struct torture_suite *o;
46         struct torture_tcase *t;
47         struct torture_test *p;
48
49         for (o = suite->children; o; o = o->next) {
50                 char *name = NULL;
51                 if (prefix == NULL)
52                         name = talloc_strdup(torture, o->name);
53                 else
54                         name = talloc_asprintf(torture, "%s-%s", prefix, o->name);
55                 if (gen_fnmatch(expr, name) == 0) {
56                         *matched = true;
57                         reload_charcnv(torture->lp_ctx);
58                         torture->active_testname = name;
59                         if (restricted != NULL)
60                                 ret &= torture_run_suite_restricted(torture, o, restricted);
61                         else
62                                 ret &= torture_run_suite(torture, o);
63                 }
64                 ret &= run_matching(torture, name, expr, restricted, o, matched);
65         }
66
67         for (t = suite->testcases; t; t = t->next) {
68                 char *name = talloc_asprintf(torture, "%s-%s", prefix, t->name);
69                 if (gen_fnmatch(expr, name) == 0) {
70                         *matched = true;
71                         reload_charcnv(torture->lp_ctx);
72                         torture->active_testname = name;
73                         ret &= torture_run_tcase(torture, t);
74                 }
75                 for (p = t->tests; p; p = p->next) {
76                         name = talloc_asprintf(torture, "%s-%s-%s", prefix, t->name, p->name);
77                         if (gen_fnmatch(expr, name) == 0) {
78                                 *matched = true;
79                                 reload_charcnv(torture->lp_ctx);
80                                 torture->active_testname = name;
81                                 ret &= torture_run_test(torture, t, p);
82                         }
83                 }
84         }
85
86         return ret;
87 }
88
89 #define MAX_COLS 80 /* FIXME: Determine this at run-time */
90
91 /****************************************************************************
92 run a specified test or "ALL"
93 ****************************************************************************/
94 static bool run_test(struct torture_context *torture, const char *name,
95                                          char **restricted)
96 {
97         bool ret = true;
98         bool matched = false;
99         struct torture_suite *o;
100
101         if (strequal(name, "ALL")) {
102                 if (restricted != NULL) {
103                         printf("--load-list and ALL are incompatible\n");
104                         return false;
105                 }
106                 for (o = torture_root->children; o; o = o->next) {
107                         ret &= torture_run_suite(torture, o);
108                 }
109                 return ret;
110         }
111
112         ret = run_matching(torture, NULL, name, restricted, torture_root, &matched);
113
114         if (!matched) {
115                 printf("Unknown torture operation '%s'\n", name);
116                 return false;
117         }
118
119         return ret;
120 }
121
122 static bool parse_target(struct loadparm_context *lp_ctx, const char *target)
123 {
124         char *host = NULL, *share = NULL;
125         struct dcerpc_binding *binding_struct;
126         NTSTATUS status;
127
128         /* see if its a RPC transport specifier */
129         if (!smbcli_parse_unc(target, NULL, &host, &share)) {
130                 status = dcerpc_parse_binding(talloc_autofree_context(), target, &binding_struct);
131                 if (NT_STATUS_IS_ERR(status)) {
132                         d_printf("Invalid option: %s is not a valid torture target (share or binding string)\n\n", target);
133                         return false;
134                 }
135                 lp_set_cmdline(lp_ctx, "torture:host", binding_struct->host);
136                 if (lp_parm_string(lp_ctx, NULL, "torture", "share") == NULL)
137                         lp_set_cmdline(lp_ctx, "torture:share", "IPC$");
138                 lp_set_cmdline(lp_ctx, "torture:binding", target);
139         } else {
140                 lp_set_cmdline(lp_ctx, "torture:host", host);
141                 lp_set_cmdline(lp_ctx, "torture:share", share);
142                 lp_set_cmdline(lp_ctx, "torture:binding", host);
143         }
144
145         return true;
146 }
147
148 static void parse_dns(struct loadparm_context *lp_ctx, const char *dns)
149 {
150         char *userdn, *basedn, *secret;
151         char *p, *d;
152
153         /* retrievieng the userdn */
154         p = strchr_m(dns, '#');
155         if (!p) {
156                 lp_set_cmdline(lp_ctx, "torture:ldap_userdn", "");
157                 lp_set_cmdline(lp_ctx, "torture:ldap_basedn", "");
158                 lp_set_cmdline(lp_ctx, "torture:ldap_secret", "");
159                 return;
160         }
161         userdn = strndup(dns, p - dns);
162         lp_set_cmdline(lp_ctx, "torture:ldap_userdn", userdn);
163
164         /* retrieve the basedn */
165         d = p + 1;
166         p = strchr_m(d, '#');
167         if (!p) {
168                 lp_set_cmdline(lp_ctx, "torture:ldap_basedn", "");
169                 lp_set_cmdline(lp_ctx, "torture:ldap_secret", "");
170                 return;
171         }
172         basedn = strndup(d, p - d);
173         lp_set_cmdline(lp_ctx, "torture:ldap_basedn", basedn);
174
175         /* retrieve the secret */
176         p = p + 1;
177         if (!p) {
178                 lp_set_cmdline(lp_ctx, "torture:ldap_secret", "");
179                 return;
180         }
181         secret = strdup(p);
182         lp_set_cmdline(lp_ctx, "torture:ldap_secret", secret);
183
184         printf ("%s - %s - %s\n", userdn, basedn, secret);
185
186 }
187
188 /* Print the full test list, formatted into separate labelled test
189  * groups.
190  */
191 static void print_structured_test_list(void)
192 {
193         struct torture_suite *o;
194         struct torture_suite *s;
195         struct torture_tcase *t;
196         int i;
197
198         if (torture_root == NULL) {
199             printf("NO TESTS LOADED\n");
200             return;
201         }
202
203         for (o = torture_root->children; o; o = o->next) {
204                 printf("\n%s (%s):\n  ", o->description, o->name);
205
206                 i = 0;
207                 for (s = o->children; s; s = s->next) {
208                         if (i + strlen(o->name) + strlen(s->name) >= (MAX_COLS - 3)) {
209                                 printf("\n  ");
210                                 i = 0;
211                         }
212                         i+=printf("%s-%s ", o->name, s->name);
213                 }
214
215                 for (t = o->testcases; t; t = t->next) {
216                         if (i + strlen(o->name) + strlen(t->name) >= (MAX_COLS - 3)) {
217                                 printf("\n  ");
218                                 i = 0;
219                         }
220                         i+=printf("%s-%s ", o->name, t->name);
221                 }
222
223                 if (i) printf("\n");
224         }
225
226         printf("\nThe default test is ALL.\n");
227 }
228
229 static void print_test_list(void)
230 {
231         struct torture_suite *o;
232         struct torture_suite *s;
233         struct torture_tcase *t;
234
235         if (torture_root == NULL)
236                 return;
237
238         for (o = torture_root->children; o; o = o->next) {
239                 for (s = o->children; s; s = s->next) {
240                         printf("%s-%s\n", o->name, s->name);
241                 }
242
243                 for (t = o->testcases; t; t = t->next) {
244                         printf("%s-%s\n", o->name, t->name);
245                 }
246         }
247 }
248
249 _NORETURN_ static void usage(poptContext pc)
250 {
251         poptPrintUsage(pc, stdout, 0);
252         printf("\n");
253
254         printf("The binding format is:\n\n");
255
256         printf("  TRANSPORT:host[flags]\n\n");
257
258         printf("  where TRANSPORT is either ncacn_np for SMB, ncacn_ip_tcp for RPC/TCP\n");
259         printf("  or ncalrpc for local connections.\n\n");
260
261         printf("  'host' is an IP or hostname or netbios name. If the binding string\n");
262         printf("  identifies the server side of an endpoint, 'host' may be an empty\n");
263         printf("  string.\n\n");
264
265         printf("  'flags' can include a SMB pipe name if using the ncacn_np transport or\n");
266         printf("  a TCP port number if using the ncacn_ip_tcp transport, otherwise they\n");
267         printf("  will be auto-determined.\n\n");
268
269         printf("  other recognised flags are:\n\n");
270
271         printf("    sign : enable ntlmssp signing\n");
272         printf("    seal : enable ntlmssp sealing\n");
273         printf("    connect : enable rpc connect level auth (auth, but no sign or seal)\n");
274         printf("    validate: enable the NDR validator\n");
275         printf("    print: enable debugging of the packets\n");
276         printf("    bigendian: use bigendian RPC\n");
277         printf("    padcheck: check reply data for non-zero pad bytes\n\n");
278
279         printf("  For example, these all connect to the samr pipe:\n\n");
280
281         printf("    ncacn_np:myserver\n");
282         printf("    ncacn_np:myserver[samr]\n");
283         printf("    ncacn_np:myserver[\\pipe\\samr]\n");
284         printf("    ncacn_np:myserver[/pipe/samr]\n");
285         printf("    ncacn_np:myserver[samr,sign,print]\n");
286         printf("    ncacn_np:myserver[\\pipe\\samr,sign,seal,bigendian]\n");
287         printf("    ncacn_np:myserver[/pipe/samr,seal,validate]\n");
288         printf("    ncacn_np:\n");
289         printf("    ncacn_np:[/pipe/samr]\n\n");
290
291         printf("    ncacn_ip_tcp:myserver\n");
292         printf("    ncacn_ip_tcp:myserver[1024]\n");
293         printf("    ncacn_ip_tcp:myserver[1024,sign,seal]\n\n");
294
295         printf("    ncalrpc:\n\n");
296
297         printf("The UNC format is:\n\n");
298
299         printf("  //server/share\n\n");
300
301         printf("Tests are:");
302
303         print_structured_test_list();
304
305         exit(1);
306 }
307
308 _NORETURN_ static void max_runtime_handler(int sig)
309 {
310         DEBUG(0,("maximum runtime exceeded for smbtorture - terminating\n"));
311         exit(1);
312 }
313
314 struct timeval last_suite_started;
315
316 static void simple_suite_start(struct torture_context *ctx,
317                                struct torture_suite *suite)
318 {
319         last_suite_started = timeval_current();
320         printf("Running %s\n", suite->name);
321 }
322
323 static void simple_suite_finish(struct torture_context *ctx,
324                                 struct torture_suite *suite)
325 {
326
327         printf("%s took %g secs\n\n", suite->name, 
328                    timeval_elapsed(&last_suite_started));
329 }
330
331 static void simple_test_result(struct torture_context *context, 
332                                enum torture_result res, const char *reason)
333 {
334         switch (res) {
335         case TORTURE_OK:
336                 if (reason)
337                         printf("OK: %s\n", reason);
338                 break;
339         case TORTURE_FAIL:
340                 printf("TEST %s FAILED! - %s\n", context->active_test->name, reason);
341                 break;
342         case TORTURE_ERROR:
343                 printf("ERROR IN TEST %s! - %s\n", context->active_test->name, reason); 
344                 break;
345         case TORTURE_SKIP:
346                 printf("SKIP: %s - %s\n", context->active_test->name, reason);
347                 break;
348         }
349 }
350
351 static void simple_comment(struct torture_context *test, 
352                            const char *comment)
353 {
354         printf("%s", comment);
355 }
356
357 static void simple_warning(struct torture_context *test, 
358                            const char *comment)
359 {
360         fprintf(stderr, "WARNING: %s\n", comment);
361 }
362
363 static void simple_progress(struct torture_context *test,
364         int offset, enum torture_progress_whence whence)
365 {
366 }
367
368 const static struct torture_ui_ops std_ui_ops = {
369         .comment = simple_comment,
370         .warning = simple_warning,
371         .suite_start = simple_suite_start,
372         .suite_finish = simple_suite_finish,
373         .test_result = simple_test_result,
374         .progress = simple_progress,
375 };
376
377 static void run_shell(struct torture_context *tctx)
378 {
379         char *cline;
380         int argc;
381         const char **argv;
382         int ret;
383
384         while (1) {
385                 cline = smb_readline("torture> ", NULL, NULL);
386
387                 if (cline == NULL)
388                         return;
389         
390                 ret = poptParseArgvString(cline, &argc, &argv);
391                 if (ret != 0) {
392                         fprintf(stderr, "Error parsing line\n");
393                         continue;
394                 }
395
396                 if (!strcmp(argv[0], "quit")) {
397                         return;
398                 } else if (!strcmp(argv[0], "list")) {
399                         print_structured_test_list();
400                 } else if (!strcmp(argv[0], "set")) {
401                         if (argc < 3) {
402                                 fprintf(stderr, "Usage: set <variable> <value>\n");
403                         } else {
404                                 char *name = talloc_asprintf(NULL, "torture:%s", argv[1]);
405                                 lp_set_cmdline(tctx->lp_ctx, name, argv[2]);
406                                 talloc_free(name);
407                         }
408                 } else if (!strcmp(argv[0], "help")) {
409                         fprintf(stderr, "Available commands:\n"
410                                                         " help - This help command\n"
411                                                         " list - List the available\n"
412                                                         " run - Run test\n"
413                                                         " set - Change variables\n"
414                                                         "\n");
415                 } else if (!strcmp(argv[0], "run")) {
416                         if (argc < 2) {
417                                 fprintf(stderr, "Usage: run TEST-NAME [OPTIONS...]\n");
418                         } else {
419                                 run_test(tctx, argv[1]);
420                         }
421                 }
422                 free(cline);
423         }
424 }
425
426 /****************************************************************************
427   main program
428 ****************************************************************************/
429 int main(int argc,char *argv[])
430 {
431         int opt, i;
432         bool correct = true;
433         int max_runtime=0;
434         int argc_new;
435         struct torture_context *torture;
436         struct torture_results *results;
437         const struct torture_ui_ops *ui_ops;
438         char **argv_new;
439         poptContext pc;
440         static const char *target = "other";
441         NTSTATUS status;
442         static const char *ui_ops_name = "subunit";
443         const char *basedir = NULL;
444         const char *extra_module = NULL;
445         static int list_tests = 0;
446         int num_extra_users = 0;
447         char **restricted = NULL;
448         int num_restricted = -1;
449         enum {OPT_LOADFILE=1000,OPT_UNCLIST,OPT_TIMELIMIT,OPT_DNS, OPT_LIST,
450               OPT_DANGEROUS,OPT_SMB_PORTS,OPT_ASYNC,OPT_NUMPROGS,
451               OPT_EXTRA_USER,OPT_LOAD_LIST,};
452
453         struct poptOption long_options[] = {
454                 POPT_AUTOHELP
455                 {"format", 0, POPT_ARG_STRING, &ui_ops_name, 0, "Output format (one of: simple, subunit)", NULL },
456                 {"smb-ports",   'p', POPT_ARG_STRING, NULL,     OPT_SMB_PORTS,  "SMB ports",    NULL},
457                 {"basedir",       0, POPT_ARG_STRING, &basedir, 0, "base directory", "BASEDIR" },
458                 {"seed",          0, POPT_ARG_INT,  &torture_seed,      0,      "Seed to use for randomizer",   NULL},
459                 {"num-progs",     0, POPT_ARG_INT,  NULL,       OPT_NUMPROGS,   "num progs",    NULL},
460                 {"num-ops",       0, POPT_ARG_INT,  &torture_numops,    0,      "num ops",      NULL},
461                 {"entries",       0, POPT_ARG_INT,  &torture_entries,   0,      "entries",      NULL},
462                 {"loadfile",      0, POPT_ARG_STRING,   NULL,   OPT_LOADFILE,   "NBench load file to use",      NULL},
463                 {"list",          0, POPT_ARG_NONE, &list_tests, 0, "List available tests and exit", NULL },
464                 {"unclist",       0, POPT_ARG_STRING,   NULL,   OPT_UNCLIST,    "unclist",      NULL},
465                 {"timelimit",   't', POPT_ARG_INT,      NULL,   OPT_TIMELIMIT,  "Set time limit (in seconds)",  NULL},
466                 {"failures",    'f', POPT_ARG_INT,  &torture_failures,  0,      "failures",     NULL},
467                 {"parse-dns",   'D', POPT_ARG_STRING,   NULL,   OPT_DNS,        "parse-dns",    NULL},
468                 {"dangerous",   'X', POPT_ARG_NONE,     NULL,   OPT_DANGEROUS,
469                  "run dangerous tests (eg. wiping out password database)", NULL},
470                 {"load-module",  0,  POPT_ARG_STRING, &extra_module,     0, "load tests from DSO file",    "SOFILE"},
471                 {"target",              'T', POPT_ARG_STRING, &target, 0, "samba3|samba4|other", NULL},
472                 {"async",       'a', POPT_ARG_NONE,     NULL,   OPT_ASYNC,
473                  "run async tests", NULL},
474                 {"num-async",    0, POPT_ARG_INT,  &torture_numasync,  0,
475                  "number of simultaneous async requests", NULL},
476                 {"maximum-runtime", 0, POPT_ARG_INT, &max_runtime, 0, 
477                  "set maximum time for smbtorture to live", "seconds"},
478                 {"extra-user",   0, POPT_ARG_STRING, NULL, OPT_EXTRA_USER,
479                  "extra user credentials", NULL},
480                 {"load-list", 0, POPT_ARG_STRING, NULL, OPT_LOAD_LIST,
481              "load a test id list from a text file", NULL},
482                 POPT_COMMON_SAMBA
483                 POPT_COMMON_CONNECTION
484                 POPT_COMMON_CREDENTIALS
485                 POPT_COMMON_VERSION
486                 { NULL }
487         };
488
489         setlinebuf(stdout);
490
491         /* we are never interested in SIGPIPE */
492         BlockSignals(true, SIGPIPE);
493
494         pc = poptGetContext("smbtorture", argc, (const char **) argv, long_options, 
495                             POPT_CONTEXT_KEEP_FIRST);
496
497         poptSetOtherOptionHelp(pc, "<binding>|<unc> TEST1 TEST2 ...");
498
499         while((opt = poptGetNextOpt(pc)) != -1) {
500                 switch (opt) {
501                 case OPT_LOADFILE:
502                         lp_set_cmdline(cmdline_lp_ctx, "torture:loadfile", poptGetOptArg(pc));
503                         break;
504                 case OPT_UNCLIST:
505                         lp_set_cmdline(cmdline_lp_ctx, "torture:unclist", poptGetOptArg(pc));
506                         break;
507                 case OPT_TIMELIMIT:
508                         lp_set_cmdline(cmdline_lp_ctx, "torture:timelimit", poptGetOptArg(pc));
509                         break;
510                 case OPT_NUMPROGS:
511                         lp_set_cmdline(cmdline_lp_ctx, "torture:nprocs", poptGetOptArg(pc));
512                         break;
513                 case OPT_DNS:
514                         parse_dns(cmdline_lp_ctx, poptGetOptArg(pc));
515                         break;
516                 case OPT_DANGEROUS:
517                         lp_set_cmdline(cmdline_lp_ctx, "torture:dangerous", "Yes");
518                         break;
519                 case OPT_ASYNC:
520                         lp_set_cmdline(cmdline_lp_ctx, "torture:async", "Yes");
521                         break;
522                 case OPT_SMB_PORTS:
523                         lp_set_cmdline(cmdline_lp_ctx, "smb ports", poptGetOptArg(pc));
524                         break;
525                 case OPT_EXTRA_USER:
526                         {
527                                 char *option = talloc_asprintf(NULL, "torture:extra_user%u",
528                                                                ++num_extra_users);
529                                 const char *value = poptGetOptArg(pc);
530                                 lp_set_cmdline(cmdline_lp_ctx, option, value);
531                                 talloc_free(option);
532                         }
533                         break;
534                 case OPT_LOAD_LIST:
535                         restricted = file_lines_load(optarg, &num_restricted, 0,
536                                                                                  talloc_autofree_context());
537                         if (restricted == NULL) {
538                                 printf("Unable to read load list file '%s'\n", optarg);
539                                 exit(1);
540                         }
541                         break;
542                 default:
543                         if (opt < 0) {
544                                 printf("bad command line option %d\n", opt);
545                                 exit(1);
546                         }
547                 }
548         }
549
550         if (strcmp(target, "samba3") == 0) {
551                 lp_set_cmdline(cmdline_lp_ctx, "torture:samba3", "true");
552                 lp_set_cmdline(cmdline_lp_ctx, "torture:resume_key_support", "false");
553         } else if (strcmp(target, "samba4") == 0) {
554                 lp_set_cmdline(cmdline_lp_ctx, "torture:samba4", "true");
555         } else if (strcmp(target, "winxp") == 0) {
556                 lp_set_cmdline(cmdline_lp_ctx, "torture:winxp", "true");
557         } else if (strcmp(target, "w2k3") == 0) {
558                 lp_set_cmdline(cmdline_lp_ctx, "torture:w2k3", "true");
559         } else if (strcmp(target, "w2k8") == 0) {
560                 lp_set_cmdline(cmdline_lp_ctx, "torture:w2k8", "true");
561                 lp_set_cmdline(cmdline_lp_ctx,
562                     "torture:invalid_lock_range_support", "false");
563         } else if (strcmp(target, "win7") == 0) {
564                 lp_set_cmdline(cmdline_lp_ctx, "torture:win7", "true");
565                 lp_set_cmdline(cmdline_lp_ctx, "torture:cn_max_buffer_size",
566                     "0x00010000");
567                 lp_set_cmdline(cmdline_lp_ctx, "torture:resume_key_support", "false");
568                 lp_set_cmdline(cmdline_lp_ctx, "torture:rewind_support", "false");
569
570                 /* RAW-SEARCH for fails for inexplicable reasons against win7 */
571                 lp_set_cmdline(cmdline_lp_ctx, "torture:search_ea_support", "false");
572
573                 lp_set_cmdline(cmdline_lp_ctx, "torture:hide_on_access_denied",
574                     "true");
575         } else if (strcmp(target, "onefs") == 0) {
576                 lp_set_cmdline(cmdline_lp_ctx, "torture:onefs", "true");
577                 lp_set_cmdline(cmdline_lp_ctx, "torture:openx_deny_dos_support",
578                     "false");
579                 lp_set_cmdline(cmdline_lp_ctx, "torture:range_not_locked_on_file_close", "false");
580                 lp_set_cmdline(cmdline_lp_ctx, "torture:sacl_support", "false");
581                 lp_set_cmdline(cmdline_lp_ctx, "torture:ea_support", "false");
582                 lp_set_cmdline(cmdline_lp_ctx, "torture:smbexit_pdu_support",
583                     "false");
584                 lp_set_cmdline(cmdline_lp_ctx, "torture:smblock_pdu_support",
585                     "false");
586                 lp_set_cmdline(cmdline_lp_ctx, "torture:2_step_break_to_none",
587                     "true");
588                 lp_set_cmdline(cmdline_lp_ctx, "torture:deny_dos_support", "false");
589                 lp_set_cmdline(cmdline_lp_ctx, "torture:deny_fcb_support", "false");
590                 lp_set_cmdline(cmdline_lp_ctx, "torture:read_support", "false");
591                 lp_set_cmdline(cmdline_lp_ctx, "torture:writeclose_support", "false");
592                 lp_set_cmdline(cmdline_lp_ctx, "torture:resume_key_support", "false");
593                 lp_set_cmdline(cmdline_lp_ctx, "torture:rewind_support", "false");
594                 lp_set_cmdline(cmdline_lp_ctx, "torture:raw_search_search", "false");
595                 lp_set_cmdline(cmdline_lp_ctx, "torture:search_ea_size", "false");
596         }
597
598         if (max_runtime) {
599                 /* this will only work if nobody else uses alarm(),
600                    which means it won't work for some tests, but we
601                    can't use the event context method we use for smbd
602                    as so many tests create their own event
603                    context. This will at least catch most cases. */
604                 signal(SIGALRM, max_runtime_handler);
605                 alarm(max_runtime);
606         }
607
608         if (extra_module != NULL) {
609             init_module_fn fn = load_module(talloc_autofree_context(), poptGetOptArg(pc));
610
611                 if (fn == NULL) 
612                         d_printf("Unable to load module from %s\n", poptGetOptArg(pc));
613                 else {
614                         status = fn();
615                         if (NT_STATUS_IS_ERR(status)) {
616                                 d_printf("Error initializing module %s: %s\n", 
617                                         poptGetOptArg(pc), nt_errstr(status));
618                         }
619                 }
620         } else { 
621                 torture_init();
622         }
623
624         if (list_tests) {
625                 print_test_list();
626                 return 0;
627         }
628
629         if (torture_seed == 0) {
630                 torture_seed = time(NULL);
631         } 
632         printf("Using seed %d\n", torture_seed);
633         srandom(torture_seed);
634
635         argv_new = discard_const_p(char *, poptGetArgs(pc));
636
637         argc_new = argc;
638         for (i=0; i<argc; i++) {
639                 if (argv_new[i] == NULL) {
640                         argc_new = i;
641                         break;
642                 }
643         }
644
645         if (!(argc_new >= 3)) {
646                 usage(pc);
647                 exit(1);
648         }
649
650         if (!parse_target(cmdline_lp_ctx, argv_new[1])) {
651                 usage(pc);
652                 exit(1);
653         }
654
655         if (!strcmp(ui_ops_name, "simple")) {
656                 ui_ops = &std_ui_ops;
657         } else if (!strcmp(ui_ops_name, "subunit")) {
658                 ui_ops = &torture_subunit_ui_ops;
659         } else {
660                 printf("Unknown output format '%s'\n", ui_ops_name);
661                 exit(1);
662         }
663
664         results = torture_results_init(talloc_autofree_context(), ui_ops);
665
666         torture = torture_context_init(s4_event_context_init(talloc_autofree_context()),
667                                        results);
668         if (basedir != NULL) {
669                 if (basedir[0] != '/') {
670                         fprintf(stderr, "Please specify an absolute path to --basedir\n");
671                         return 1;
672                 }
673                 torture->outputdir = basedir;
674         } else {
675                 char *pwd = talloc_size(torture, PATH_MAX);
676                 if (!getcwd(pwd, PATH_MAX)) {
677                         fprintf(stderr, "Unable to determine current working directory\n");
678                         return 1;
679                 }
680                 torture->outputdir = pwd;
681         }
682
683         torture->lp_ctx = cmdline_lp_ctx;
684
685         gensec_init(cmdline_lp_ctx);
686
687         if (argc_new == 0) {
688                 printf("You must specify a testsuite to run, or 'ALL'\n");
689         } else {
690                 for (i=2;i<argc_new;i++) {
691                         if (!run_test(torture, argv_new[i], restricted)) {
692                                 correct = false;
693                         }
694                 }
695         }
696
697         if (torture->results->returncode && correct) {
698                 return(0);
699         } else {
700                 return(1);
701         }
702 }