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