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