s3: piddir creation fix part 2.
[ira/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 #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, "samba4-ntvfs") == 0) {
552                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:samba4", "true");
553                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:samba4-ntvfs", "true");
554         } else if (strcmp(target, "winxp") == 0) {
555                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:winxp", "true");
556         } else if (strcmp(target, "w2k3") == 0) {
557                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:w2k3", "true");
558         } else if (strcmp(target, "w2k8") == 0) {
559                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:w2k8", "true");
560                 lpcfg_set_cmdline(cmdline_lp_ctx,
561                     "torture:invalid_lock_range_support", "false");
562         } else if (strcmp(target, "win7") == 0) {
563                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:win7", "true");
564                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:cn_max_buffer_size",
565                     "0x00010000");
566                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:resume_key_support", "false");
567                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:rewind_support", "false");
568
569                 /* RAW-SEARCH for fails for inexplicable reasons against win7 */
570                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:search_ea_support", "false");
571
572                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:hide_on_access_denied",
573                     "true");
574         } else if (strcmp(target, "onefs") == 0) {
575                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:onefs", "true");
576                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:openx_deny_dos_support",
577                     "false");
578                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:range_not_locked_on_file_close", "false");
579                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:sacl_support", "false");
580                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:ea_support", "false");
581                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:smbexit_pdu_support",
582                     "false");
583                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:smblock_pdu_support",
584                     "false");
585                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:2_step_break_to_none",
586                     "true");
587                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:deny_dos_support", "false");
588                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:deny_fcb_support", "false");
589                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:read_support", "false");
590                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:writeclose_support", "false");
591                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:resume_key_support", "false");
592                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:rewind_support", "false");
593                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:raw_search_search", "false");
594                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:search_ea_size", "false");
595         }
596
597         if (max_runtime) {
598                 /* this will only work if nobody else uses alarm(),
599                    which means it won't work for some tests, but we
600                    can't use the event context method we use for smbd
601                    as so many tests create their own event
602                    context. This will at least catch most cases. */
603                 signal(SIGALRM, max_runtime_handler);
604                 alarm(max_runtime);
605         }
606
607         if (extra_module != NULL) {
608                 init_module_fn fn = load_module(poptGetOptArg(pc), false, NULL);
609
610                 if (fn == NULL) 
611                         d_printf("Unable to load module from %s\n", poptGetOptArg(pc));
612                 else {
613                         status = fn();
614                         if (NT_STATUS_IS_ERR(status)) {
615                                 d_printf("Error initializing module %s: %s\n", 
616                                         poptGetOptArg(pc), nt_errstr(status));
617                         }
618                 }
619         } else { 
620                 torture_init();
621         }
622
623         if (list_testsuites) {
624                 print_testsuite_list();
625                 return 0;
626         }
627
628         argv_new = discard_const_p(char *, poptGetArgs(pc));
629
630         argc_new = argc;
631         for (i=0; i<argc; i++) {
632                 if (argv_new[i] == NULL) {
633                         argc_new = i;
634                         break;
635                 }
636         }
637
638         if (list_tests) {
639                 if (argc_new == 1) {
640                         print_test_list(torture_root, NULL, "");
641                 } else {
642                         for (i=1;i<argc_new;i++) {
643                                 print_test_list(torture_root, NULL, argv_new[i]);
644                         }
645                 }
646                 return 0;
647         }
648
649         if (torture_seed == 0) {
650                 torture_seed = time(NULL);
651         } 
652         printf("Using seed %d\n", torture_seed);
653         srandom(torture_seed);
654
655         if (!strcmp(ui_ops_name, "simple")) {
656                 ui_ops = &std_ui_ops;
657         } else if (!strcmp(ui_ops_name, "subunit")) {
658                 ui_ops = &torture_subunit_ui_ops;
659         } else {
660                 printf("Unknown output format '%s'\n", ui_ops_name);
661                 exit(1);
662         }
663
664         results = torture_results_init(talloc_autofree_context(), ui_ops);
665
666         torture = torture_context_init(s4_event_context_init(talloc_autofree_context()),
667                                        results);
668         if (basedir != NULL) {
669                 if (basedir[0] != '/') {
670                         fprintf(stderr, "Please specify an absolute path to --basedir\n");
671                         return 1;
672                 }
673                 outputdir = talloc_asprintf(torture, "%s/smbtortureXXXXXX", basedir);
674         } else {
675                 char *pwd = talloc_size(torture, PATH_MAX);
676                 if (!getcwd(pwd, PATH_MAX)) {
677                         fprintf(stderr, "Unable to determine current working directory\n");
678                         return 1;
679                 }
680                 outputdir = talloc_asprintf(torture, "%s/smbtortureXXXXXX", pwd);
681         }
682         if (!outputdir) {
683                 fprintf(stderr, "Could not allocate per-run output dir\n");
684                 return 1;
685         }
686         torture->outputdir = mkdtemp(outputdir);
687         if (!torture->outputdir) {
688                 perror("Failed to make temp output dir");
689         }
690
691         torture->lp_ctx = cmdline_lp_ctx;
692
693         gensec_init();
694
695         if (shell) {
696                 /* In shell mode, just ignore any remaining test names. */
697                 torture_shell(torture);
698         } else {
699
700                 /* At this point, we should just have a target string,
701                  * followed by a series of test names. Unless we are in
702                  * shell mode, in which case we don't need anythig more.
703                  */
704
705                 if (argc_new < 3) {
706                         printf("You must specify a test to run, or 'ALL'\n");
707                         usage(pc);
708                         torture->results->returncode = 1;
709                 } else if (!torture_parse_target(cmdline_lp_ctx, argv_new[1])) {
710                 /* Take the target name or binding. */
711                         usage(pc);
712                         torture->results->returncode = 1;
713                 } else {
714                         for (i=2;i<argc_new;i++) {
715                                 if (!torture_run_named_tests(torture, argv_new[i],
716                                             (const char **)restricted)) {
717                                         correct = false;
718                                 }
719                         }
720                 }
721         }
722
723         /* Now delete the temp dir we created */
724         torture_deltree_outputdir(torture);
725
726         if (torture->results->returncode && correct) {
727                 return(0);
728         } else {
729                 return(1);
730         }
731 }