83816e8be55a25dfaf7c57ab5d39d24429910264
[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
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 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 }
345
346 _NORETURN_ static void max_runtime_handler(int sig)
347 {
348         DEBUG(0,("maximum runtime exceeded for smbtorture - terminating\n"));
349         exit(1);
350 }
351
352 struct timeval last_suite_started;
353
354 static void simple_suite_start(struct torture_context *ctx,
355                                struct torture_suite *suite)
356 {
357         last_suite_started = timeval_current();
358         printf("Running %s\n", suite->name);
359 }
360
361 static void simple_suite_finish(struct torture_context *ctx,
362                                 struct torture_suite *suite)
363 {
364
365         printf("%s took %g secs\n\n", suite->name, 
366                    timeval_elapsed(&last_suite_started));
367 }
368
369 static void simple_test_result(struct torture_context *context, 
370                                enum torture_result res, const char *reason)
371 {
372         switch (res) {
373         case TORTURE_OK:
374                 if (reason)
375                         printf("OK: %s\n", reason);
376                 break;
377         case TORTURE_FAIL:
378                 printf("TEST %s FAILED! - %s\n", context->active_test->name, reason);
379                 break;
380         case TORTURE_ERROR:
381                 printf("ERROR IN TEST %s! - %s\n", context->active_test->name, reason); 
382                 break;
383         case TORTURE_SKIP:
384                 printf("SKIP: %s - %s\n", context->active_test->name, reason);
385                 break;
386         }
387 }
388
389 static void simple_comment(struct torture_context *test, 
390                            const char *comment)
391 {
392         printf("%s", comment);
393 }
394
395 static void simple_warning(struct torture_context *test, 
396                            const char *comment)
397 {
398         fprintf(stderr, "WARNING: %s\n", comment);
399 }
400
401 static void simple_progress(struct torture_context *test,
402         int offset, enum torture_progress_whence whence)
403 {
404 }
405
406 const static struct torture_ui_ops std_ui_ops = {
407         .comment = simple_comment,
408         .warning = simple_warning,
409         .suite_start = simple_suite_start,
410         .suite_finish = simple_suite_finish,
411         .test_result = simple_test_result,
412         .progress = simple_progress,
413 };
414
415 /****************************************************************************
416   main program
417 ****************************************************************************/
418 int main(int argc,char *argv[])
419 {
420         int opt, i;
421         bool correct = true;
422         int max_runtime=0;
423         int argc_new;
424         struct torture_context *torture;
425         struct torture_results *results;
426         const struct torture_ui_ops *ui_ops;
427         char **argv_new;
428         poptContext pc;
429         static const char *target = "other";
430         NTSTATUS status;
431         int shell = false;
432         static const char *ui_ops_name = "subunit";
433         const char *basedir = NULL;
434         char *outputdir;
435         const char *extra_module = NULL;
436         static int list_tests = 0, list_testsuites = 0;
437         int num_extra_users = 0;
438         char **restricted = NULL;
439         int num_restricted = -1;
440         const char *load_list = NULL;
441         enum {OPT_LOADFILE=1000,OPT_UNCLIST,OPT_TIMELIMIT,OPT_DNS, OPT_LIST,
442               OPT_DANGEROUS,OPT_SMB_PORTS,OPT_ASYNC,OPT_NUMPROGS,
443               OPT_EXTRA_USER,};
444
445         struct poptOption long_options[] = {
446                 POPT_AUTOHELP
447                 {"format", 0, POPT_ARG_STRING, &ui_ops_name, 0, "Output format (one of: simple, subunit)", NULL },
448                 {"smb-ports",   'p', POPT_ARG_STRING, NULL,     OPT_SMB_PORTS,  "SMB ports",    NULL},
449                 {"basedir",       0, POPT_ARG_STRING, &basedir, 0, "base directory", "BASEDIR" },
450                 {"seed",          0, POPT_ARG_INT,  &torture_seed,      0,      "Seed to use for randomizer",   NULL},
451                 {"num-progs",     0, POPT_ARG_INT,  NULL,       OPT_NUMPROGS,   "num progs",    NULL},
452                 {"num-ops",       0, POPT_ARG_INT,  &torture_numops,    0,      "num ops",      NULL},
453                 {"entries",       0, POPT_ARG_INT,  &torture_entries,   0,      "entries",      NULL},
454                 {"loadfile",      0, POPT_ARG_STRING,   NULL,   OPT_LOADFILE,   "NBench load file to use",      NULL},
455                 {"list-suites",           0, POPT_ARG_NONE, &list_testsuites, 0, "List available testsuites and exit", NULL },
456                 {"list",          0, POPT_ARG_NONE, &list_tests, 0, "List available tests in specified suites and exit", NULL },
457                 {"unclist",       0, POPT_ARG_STRING,   NULL,   OPT_UNCLIST,    "unclist",      NULL},
458                 {"timelimit",   't', POPT_ARG_INT,      NULL,   OPT_TIMELIMIT,  "Set time limit (in seconds)",  NULL},
459                 {"failures",    'f', POPT_ARG_INT,  &torture_failures,  0,      "failures",     NULL},
460                 {"parse-dns",   'D', POPT_ARG_STRING,   NULL,   OPT_DNS,        "parse-dns",    NULL},
461                 {"dangerous",   'X', POPT_ARG_NONE,     NULL,   OPT_DANGEROUS,
462                  "run dangerous tests (eg. wiping out password database)", NULL},
463                 {"load-module",  0,  POPT_ARG_STRING, &extra_module,     0, "load tests from DSO file",    "SOFILE"},
464                 {"shell",               0, POPT_ARG_NONE, &shell, true, "Run shell", NULL},
465                 {"target",              'T', POPT_ARG_STRING, &target, 0, "samba3|samba4|other", NULL},
466                 {"async",       'a', POPT_ARG_NONE,     NULL,   OPT_ASYNC,
467                  "run async tests", NULL},
468                 {"num-async",    0, POPT_ARG_INT,  &torture_numasync,  0,
469                  "number of simultaneous async requests", NULL},
470                 {"maximum-runtime", 0, POPT_ARG_INT, &max_runtime, 0, 
471                  "set maximum time for smbtorture to live", "seconds"},
472                 {"extra-user",   0, POPT_ARG_STRING, NULL, OPT_EXTRA_USER,
473                  "extra user credentials", NULL},
474                 {"load-list", 0, POPT_ARG_STRING, &load_list, 0,
475              "load a test id list from a text file", NULL},
476                 POPT_COMMON_SAMBA
477                 POPT_COMMON_CONNECTION
478                 POPT_COMMON_CREDENTIALS
479                 POPT_COMMON_VERSION
480                 { NULL }
481         };
482
483         setlinebuf(stdout);
484
485         /* we are never interested in SIGPIPE */
486         BlockSignals(true, SIGPIPE);
487
488         pc = poptGetContext("smbtorture", argc, (const char **) argv, long_options, 
489                             POPT_CONTEXT_KEEP_FIRST);
490
491         poptSetOtherOptionHelp(pc, "<binding>|<unc> TEST1 TEST2 ...");
492
493         while((opt = poptGetNextOpt(pc)) != -1) {
494                 switch (opt) {
495                 case OPT_LOADFILE:
496                         lpcfg_set_cmdline(cmdline_lp_ctx, "torture:loadfile", poptGetOptArg(pc));
497                         break;
498                 case OPT_UNCLIST:
499                         lpcfg_set_cmdline(cmdline_lp_ctx, "torture:unclist", poptGetOptArg(pc));
500                         break;
501                 case OPT_TIMELIMIT:
502                         lpcfg_set_cmdline(cmdline_lp_ctx, "torture:timelimit", poptGetOptArg(pc));
503                         break;
504                 case OPT_NUMPROGS:
505                         lpcfg_set_cmdline(cmdline_lp_ctx, "torture:nprocs", poptGetOptArg(pc));
506                         break;
507                 case OPT_DNS:
508                         parse_dns(cmdline_lp_ctx, poptGetOptArg(pc));
509                         break;
510                 case OPT_DANGEROUS:
511                         lpcfg_set_cmdline(cmdline_lp_ctx, "torture:dangerous", "Yes");
512                         break;
513                 case OPT_ASYNC:
514                         lpcfg_set_cmdline(cmdline_lp_ctx, "torture:async", "Yes");
515                         break;
516                 case OPT_SMB_PORTS:
517                         lpcfg_set_cmdline(cmdline_lp_ctx, "smb ports", poptGetOptArg(pc));
518                         break;
519                 case OPT_EXTRA_USER:
520                         {
521                                 char *option = talloc_asprintf(NULL, "torture:extra_user%u",
522                                                                ++num_extra_users);
523                                 const char *value = poptGetOptArg(pc);
524                                 lpcfg_set_cmdline(cmdline_lp_ctx, option, value);
525                                 talloc_free(option);
526                         }
527                         break;
528                 default:
529                         if (opt < 0) {
530                                 printf("bad command line option %d\n", opt);
531                                 exit(1);
532                         }
533                 }
534         }
535
536         if (load_list != NULL) {
537                 restricted = file_lines_load(load_list, &num_restricted, 0,
538                                                                          talloc_autofree_context());
539                 if (restricted == NULL) {
540                         printf("Unable to read load list file '%s'\n", load_list);
541                         exit(1);
542                 }
543         }
544
545         if (strcmp(target, "samba3") == 0) {
546                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:samba3", "true");
547                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:resume_key_support", "false");
548         } else if (strcmp(target, "samba4") == 0) {
549                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:samba4", "true");
550         } else if (strcmp(target, "winxp") == 0) {
551                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:winxp", "true");
552         } else if (strcmp(target, "w2k3") == 0) {
553                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:w2k3", "true");
554         } else if (strcmp(target, "w2k8") == 0) {
555                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:w2k8", "true");
556                 lpcfg_set_cmdline(cmdline_lp_ctx,
557                     "torture:invalid_lock_range_support", "false");
558         } else if (strcmp(target, "win7") == 0) {
559                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:win7", "true");
560                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:cn_max_buffer_size",
561                     "0x00010000");
562                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:resume_key_support", "false");
563                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:rewind_support", "false");
564
565                 /* RAW-SEARCH for fails for inexplicable reasons against win7 */
566                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:search_ea_support", "false");
567
568                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:hide_on_access_denied",
569                     "true");
570         } else if (strcmp(target, "onefs") == 0) {
571                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:onefs", "true");
572                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:openx_deny_dos_support",
573                     "false");
574                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:range_not_locked_on_file_close", "false");
575                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:sacl_support", "false");
576                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:ea_support", "false");
577                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:smbexit_pdu_support",
578                     "false");
579                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:smblock_pdu_support",
580                     "false");
581                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:2_step_break_to_none",
582                     "true");
583                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:deny_dos_support", "false");
584                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:deny_fcb_support", "false");
585                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:read_support", "false");
586                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:writeclose_support", "false");
587                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:resume_key_support", "false");
588                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:rewind_support", "false");
589                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:raw_search_search", "false");
590                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:search_ea_size", "false");
591         }
592
593         if (max_runtime) {
594                 /* this will only work if nobody else uses alarm(),
595                    which means it won't work for some tests, but we
596                    can't use the event context method we use for smbd
597                    as so many tests create their own event
598                    context. This will at least catch most cases. */
599                 signal(SIGALRM, max_runtime_handler);
600                 alarm(max_runtime);
601         }
602
603         if (extra_module != NULL) {
604             init_module_fn fn = load_module(talloc_autofree_context(), poptGetOptArg(pc));
605
606                 if (fn == NULL) 
607                         d_printf("Unable to load module from %s\n", poptGetOptArg(pc));
608                 else {
609                         status = fn();
610                         if (NT_STATUS_IS_ERR(status)) {
611                                 d_printf("Error initializing module %s: %s\n", 
612                                         poptGetOptArg(pc), nt_errstr(status));
613                         }
614                 }
615         } else { 
616                 torture_init();
617         }
618
619         if (list_testsuites) {
620                 print_testsuite_list();
621                 return 0;
622         }
623
624         argv_new = discard_const_p(char *, poptGetArgs(pc));
625
626         argc_new = argc;
627         for (i=0; i<argc; i++) {
628                 if (argv_new[i] == NULL) {
629                         argc_new = i;
630                         break;
631                 }
632         }
633
634         if (list_tests) {
635                 if (argc_new == 1) {
636                         print_test_list(torture_root, NULL, "");
637                 } else {
638                         for (i=1;i<argc_new;i++) {
639                                 print_test_list(torture_root, NULL, argv_new[i]);
640                         }
641                 }
642                 return 0;
643         }
644
645         if (torture_seed == 0) {
646                 torture_seed = time(NULL);
647         } 
648         printf("Using seed %d\n", torture_seed);
649         srandom(torture_seed);
650
651         if (!strcmp(ui_ops_name, "simple")) {
652                 ui_ops = &std_ui_ops;
653         } else if (!strcmp(ui_ops_name, "subunit")) {
654                 ui_ops = &torture_subunit_ui_ops;
655         } else {
656                 printf("Unknown output format '%s'\n", ui_ops_name);
657                 exit(1);
658         }
659
660         results = torture_results_init(talloc_autofree_context(), ui_ops);
661
662         torture = torture_context_init(s4_event_context_init(talloc_autofree_context()),
663                                        results);
664         if (basedir != NULL) {
665                 if (basedir[0] != '/') {
666                         fprintf(stderr, "Please specify an absolute path to --basedir\n");
667                         return 1;
668                 }
669                 outputdir = talloc_asprintf(torture, "%s/smbtortureXXXXXX", basedir);
670         } else {
671                 char *pwd = talloc_size(torture, PATH_MAX);
672                 if (!getcwd(pwd, PATH_MAX)) {
673                         fprintf(stderr, "Unable to determine current working directory\n");
674                         return 1;
675                 }
676                 outputdir = talloc_asprintf(torture, "%s/smbtortureXXXXXX", pwd);
677         }
678         if (!outputdir) {
679                 fprintf(stderr, "Could not allocate per-run output dir\n");
680                 return 1;
681         }
682         torture->outputdir = mkdtemp(outputdir);
683         if (!torture->outputdir) {
684                 perror("Failed to make temp output dir");
685         }
686
687         torture->lp_ctx = cmdline_lp_ctx;
688
689         gensec_init();
690
691         if (shell) {
692                 /* In shell mode, just ignore any remaining test names. */
693                 torture_shell(torture);
694         } else {
695
696                 /* At this point, we should just have a target string,
697                  * followed by a series of test names. Unless we are in
698                  * shell mode, in which case we don't need anythig more.
699                  */
700
701                 if (argc_new < 3) {
702                         printf("You must specify a test to run, or 'ALL'\n");
703                         usage(pc);
704                         torture->results->returncode = 1;
705                 } else if (!torture_parse_target(cmdline_lp_ctx, argv_new[1])) {
706                 /* Take the target name or binding. */
707                         usage(pc);
708                         torture->results->returncode = 1;
709                 } else {
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
719         /* Now delete the temp dir we created */
720         torture_deltree_outputdir(torture);
721
722         if (torture->results->returncode && correct) {
723                 return(0);
724         } else {
725                 return(1);
726         }
727 }