lib/util: consolidate module loading into common code
[samba.git] / source4 / torture / smbtorture.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB torture tester
4    Copyright (C) Andrew Tridgell 1997-2003
5    Copyright (C) Jelmer Vernooij 2006-2008
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "lib/cmdline/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 #include "lib/util/samba_modules.h"
36
37 #if HAVE_READLINE_HISTORY_H
38 #include <readline/history.h>
39 #endif
40
41 static char *prefix_name(TALLOC_CTX *mem_ctx, const char *prefix, const char *name)
42 {
43         if (prefix == NULL)
44                 return talloc_strdup(mem_ctx, name);
45         else
46                 return talloc_asprintf(mem_ctx, "%s.%s", prefix, name);
47 }
48
49 static void print_test_list(const struct torture_suite *suite, const char *prefix, const char *expr)
50 {
51         struct torture_suite *o;
52         struct torture_tcase *t;
53         struct torture_test *p;
54
55         for (o = suite->children; o; o = o->next) {
56                 char *name = prefix_name(NULL, prefix, o->name);
57                 print_test_list(o, name, expr);
58                 talloc_free(name);
59         }
60
61         for (t = suite->testcases; t; t = t->next) {
62                 for (p = t->tests; p; p = p->next) {
63                         char *name = talloc_asprintf(NULL, "%s.%s.%s", prefix, t->name, p->name);
64                         if (strncmp(name, expr, strlen(expr)) == 0) {
65                                 printf("%s\n", name);
66                         }
67                         talloc_free(name);
68                 }
69         }
70 }
71
72 static bool run_matching(struct torture_context *torture,
73                                                  const char *prefix, 
74                                                  const char *expr,
75                                                  const char **restricted,
76                                                  struct torture_suite *suite,
77                                                  bool *matched)
78 {
79         bool ret = true;
80         struct torture_suite *o;
81         struct torture_tcase *t;
82         struct torture_test *p;
83
84         for (o = suite->children; o; o = o->next) {
85                 char *name = NULL;
86                 name = prefix_name(torture, prefix, o->name);
87                 if (gen_fnmatch(expr, name) == 0) {
88                         *matched = true;
89                         reload_charcnv(torture->lp_ctx);
90                         if (restricted != NULL)
91                                 ret &= torture_run_suite_restricted(torture, o, restricted);
92                         else
93                                 ret &= torture_run_suite(torture, o);
94                 }
95                 ret &= run_matching(torture, name, expr, restricted, o, matched);
96         }
97
98         for (t = suite->testcases; t; t = t->next) {
99                 char *name = talloc_asprintf(torture, "%s.%s", prefix, t->name);
100                 if (gen_fnmatch(expr, name) == 0) {
101                         *matched = true;
102                         reload_charcnv(torture->lp_ctx);
103                         ret &= torture_run_tcase_restricted(torture, t, restricted);
104                 }
105                 for (p = t->tests; p; p = p->next) {
106                         name = talloc_asprintf(torture, "%s.%s.%s", prefix, t->name, p->name);
107                         if (gen_fnmatch(expr, name) == 0) {
108                                 *matched = true;
109                                 reload_charcnv(torture->lp_ctx);
110                                 ret &= torture_run_test_restricted(torture, t, p, restricted);
111                         }
112                 }
113         }
114
115         return ret;
116 }
117
118 #define MAX_COLS 80 /* FIXME: Determine this at run-time */
119
120 /****************************************************************************
121 run a specified test or "ALL"
122 ****************************************************************************/
123 bool torture_run_named_tests(struct torture_context *torture, const char *name,
124                             const char **restricted)
125 {
126         bool ret = true;
127         bool matched = false;
128         struct torture_suite *o;
129
130         torture_ui_report_time(torture);
131
132         if (strequal(name, "ALL")) {
133                 if (restricted != NULL) {
134                         printf("--load-list and ALL are incompatible\n");
135                         return false;
136                 }
137                 for (o = torture_root->children; o; o = o->next) {
138                         ret &= torture_run_suite(torture, o);
139                 }
140                 return ret;
141         }
142
143         ret = run_matching(torture, NULL, name, restricted, torture_root, &matched);
144
145         if (!matched) {
146                 printf("Unknown torture operation '%s'\n", name);
147                 return false;
148         }
149
150         return ret;
151 }
152
153 bool torture_parse_target(struct loadparm_context *lp_ctx, const char *target)
154 {
155         char *host = NULL, *share = NULL;
156         struct dcerpc_binding *binding_struct;
157         NTSTATUS status;
158
159         /* see if its a RPC transport specifier */
160         if (!smbcli_parse_unc(target, NULL, &host, &share)) {
161                 status = dcerpc_parse_binding(talloc_autofree_context(), target, &binding_struct);
162                 if (NT_STATUS_IS_ERR(status)) {
163                         d_printf("Invalid option: %s is not a valid torture target (share or binding string)\n\n", target);
164                         return false;
165                 }
166                 lpcfg_set_cmdline(lp_ctx, "torture:host", binding_struct->host);
167                 if (lpcfg_parm_string(lp_ctx, NULL, "torture", "share") == NULL)
168                         lpcfg_set_cmdline(lp_ctx, "torture:share", "IPC$");
169                 lpcfg_set_cmdline(lp_ctx, "torture:binding", target);
170         } else {
171                 lpcfg_set_cmdline(lp_ctx, "torture:host", host);
172                 lpcfg_set_cmdline(lp_ctx, "torture:share", share);
173                 lpcfg_set_cmdline(lp_ctx, "torture:binding", host);
174         }
175
176         return true;
177 }
178
179 static void parse_dns(struct loadparm_context *lp_ctx, const char *dns)
180 {
181         char *userdn, *basedn, *secret;
182         char *p, *d;
183
184         /* retrievieng the userdn */
185         p = strchr_m(dns, '#');
186         if (!p) {
187                 lpcfg_set_cmdline(lp_ctx, "torture:ldap_userdn", "");
188                 lpcfg_set_cmdline(lp_ctx, "torture:ldap_basedn", "");
189                 lpcfg_set_cmdline(lp_ctx, "torture:ldap_secret", "");
190                 return;
191         }
192         userdn = strndup(dns, p - dns);
193         lpcfg_set_cmdline(lp_ctx, "torture:ldap_userdn", userdn);
194
195         /* retrieve the basedn */
196         d = p + 1;
197         p = strchr_m(d, '#');
198         if (!p) {
199                 lpcfg_set_cmdline(lp_ctx, "torture:ldap_basedn", "");
200                 lpcfg_set_cmdline(lp_ctx, "torture:ldap_secret", "");
201                 return;
202         }
203         basedn = strndup(d, p - d);
204         lpcfg_set_cmdline(lp_ctx, "torture:ldap_basedn", basedn);
205
206         /* retrieve the secret */
207         p = p + 1;
208         if (!p) {
209                 lpcfg_set_cmdline(lp_ctx, "torture:ldap_secret", "");
210                 return;
211         }
212         secret = strdup(p);
213         lpcfg_set_cmdline(lp_ctx, "torture:ldap_secret", secret);
214
215         printf ("%s - %s - %s\n", userdn, basedn, secret);
216
217 }
218
219 /* Print the full test list, formatted into separate labelled test
220  * groups.
221  */
222 static void print_structured_testsuite_list(void)
223 {
224         struct torture_suite *o;
225         struct torture_suite *s;
226         struct torture_tcase *t;
227         int i;
228
229         if (torture_root == NULL) {
230             printf("NO TESTS LOADED\n");
231             return;
232         }
233
234         for (o = torture_root->children; o; o = o->next) {
235                 printf("\n%s (%s):\n  ", o->description, o->name);
236
237                 i = 0;
238                 for (s = o->children; s; s = s->next) {
239                         if (i + strlen(o->name) + strlen(s->name) >= (MAX_COLS - 3)) {
240                                 printf("\n  ");
241                                 i = 0;
242                         }
243                         i+=printf("%s.%s ", o->name, s->name);
244                 }
245
246                 for (t = o->testcases; t; t = t->next) {
247                         if (i + strlen(o->name) + strlen(t->name) >= (MAX_COLS - 3)) {
248                                 printf("\n  ");
249                                 i = 0;
250                         }
251                         i+=printf("%s.%s ", o->name, t->name);
252                 }
253
254                 if (i) printf("\n");
255         }
256
257         printf("\nThe default test is ALL.\n");
258 }
259
260 static void print_testsuite_list(void)
261 {
262         struct torture_suite *o;
263         struct torture_suite *s;
264         struct torture_tcase *t;
265
266         if (torture_root == NULL)
267                 return;
268
269         for (o = torture_root->children; o; o = o->next) {
270                 for (s = o->children; s; s = s->next) {
271                         printf("%s.%s\n", o->name, s->name);
272                 }
273
274                 for (t = o->testcases; t; t = t->next) {
275                         printf("%s.%s\n", o->name, t->name);
276                 }
277         }
278 }
279
280 void torture_print_testsuites(bool structured)
281 {
282         if (structured) {
283                 print_structured_testsuite_list();
284         } else {
285                 print_testsuite_list();
286         }
287 }
288
289 static void usage(poptContext pc)
290 {
291         poptPrintUsage(pc, stdout, 0);
292         printf("\n");
293
294         printf("The binding format is:\n\n");
295
296         printf("  TRANSPORT:host[flags]\n\n");
297
298         printf("  where TRANSPORT is either ncacn_np for SMB, ncacn_ip_tcp for RPC/TCP\n");
299         printf("  or ncalrpc for local connections.\n\n");
300
301         printf("  'host' is an IP or hostname or netbios name. If the binding string\n");
302         printf("  identifies the server side of an endpoint, 'host' may be an empty\n");
303         printf("  string.\n\n");
304
305         printf("  'flags' can include a SMB pipe name if using the ncacn_np transport or\n");
306         printf("  a TCP port number if using the ncacn_ip_tcp transport, otherwise they\n");
307         printf("  will be auto-determined.\n\n");
308
309         printf("  other recognised flags are:\n\n");
310
311         printf("    sign : enable ntlmssp signing\n");
312         printf("    seal : enable ntlmssp sealing\n");
313         printf("    connect : enable rpc connect level auth (auth, but no sign or seal)\n");
314         printf("    validate: enable the NDR validator\n");
315         printf("    print: enable debugging of the packets\n");
316         printf("    bigendian: use bigendian RPC\n");
317         printf("    padcheck: check reply data for non-zero pad bytes\n\n");
318
319         printf("  For example, these all connect to the samr pipe:\n\n");
320
321         printf("    ncacn_np:myserver\n");
322         printf("    ncacn_np:myserver[samr]\n");
323         printf("    ncacn_np:myserver[\\pipe\\samr]\n");
324         printf("    ncacn_np:myserver[/pipe/samr]\n");
325         printf("    ncacn_np:myserver[samr,sign,print]\n");
326         printf("    ncacn_np:myserver[\\pipe\\samr,sign,seal,bigendian]\n");
327         printf("    ncacn_np:myserver[/pipe/samr,seal,validate]\n");
328         printf("    ncacn_np:\n");
329         printf("    ncacn_np:[/pipe/samr]\n\n");
330
331         printf("    ncacn_ip_tcp:myserver\n");
332         printf("    ncacn_ip_tcp:myserver[1024]\n");
333         printf("    ncacn_ip_tcp:myserver[1024,sign,seal]\n\n");
334
335         printf("    ncalrpc:\n\n");
336
337         printf("The UNC format is:\n\n");
338
339         printf("  //server/share\n\n");
340
341         printf("Tests are:");
342
343         print_structured_testsuite_list();
344
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                 if (argc_new == 1) {
637                         print_test_list(torture_root, NULL, "");
638                 } else {
639                         for (i=1;i<argc_new;i++) {
640                                 print_test_list(torture_root, NULL, argv_new[i]);
641                         }
642                 }
643                 return 0;
644         }
645
646         if (torture_seed == 0) {
647                 torture_seed = time(NULL);
648         } 
649         printf("Using seed %d\n", torture_seed);
650         srandom(torture_seed);
651
652         if (!strcmp(ui_ops_name, "simple")) {
653                 ui_ops = &std_ui_ops;
654         } else if (!strcmp(ui_ops_name, "subunit")) {
655                 ui_ops = &torture_subunit_ui_ops;
656         } else {
657                 printf("Unknown output format '%s'\n", ui_ops_name);
658                 exit(1);
659         }
660
661         results = torture_results_init(talloc_autofree_context(), ui_ops);
662
663         torture = torture_context_init(s4_event_context_init(talloc_autofree_context()),
664                                        results);
665         if (basedir != NULL) {
666                 if (basedir[0] != '/') {
667                         fprintf(stderr, "Please specify an absolute path to --basedir\n");
668                         return 1;
669                 }
670                 outputdir = talloc_asprintf(torture, "%s/smbtortureXXXXXX", basedir);
671         } else {
672                 char *pwd = talloc_size(torture, PATH_MAX);
673                 if (!getcwd(pwd, PATH_MAX)) {
674                         fprintf(stderr, "Unable to determine current working directory\n");
675                         return 1;
676                 }
677                 outputdir = talloc_asprintf(torture, "%s/smbtortureXXXXXX", pwd);
678         }
679         if (!outputdir) {
680                 fprintf(stderr, "Could not allocate per-run output dir\n");
681                 return 1;
682         }
683         torture->outputdir = mkdtemp(outputdir);
684         if (!torture->outputdir) {
685                 perror("Failed to make temp output dir");
686         }
687
688         torture->lp_ctx = cmdline_lp_ctx;
689
690         gensec_init();
691
692         if (shell) {
693                 /* In shell mode, just ignore any remaining test names. */
694                 torture_shell(torture);
695         } else {
696
697                 /* At this point, we should just have a target string,
698                  * followed by a series of test names. Unless we are in
699                  * shell mode, in which case we don't need anythig more.
700                  */
701
702                 if (argc_new < 3) {
703                         printf("You must specify a test to run, or 'ALL'\n");
704                         usage(pc);
705                         torture->results->returncode = 1;
706                 } else if (!torture_parse_target(cmdline_lp_ctx, argv_new[1])) {
707                 /* Take the target name or binding. */
708                         usage(pc);
709                         torture->results->returncode = 1;
710                 } else {
711                         for (i=2;i<argc_new;i++) {
712                                 if (!torture_run_named_tests(torture, argv_new[i],
713                                             (const char **)restricted)) {
714                                         correct = false;
715                                 }
716                         }
717                 }
718         }
719
720         /* Now delete the temp dir we created */
721         torture_deltree_outputdir(torture);
722
723         if (torture->results->returncode && correct) {
724                 return(0);
725         } else {
726                 return(1);
727         }
728 }