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