fc50436933f8d20bc6ebb7a2a100a489ba776e8a
[sfrench/samba-autobuild/.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                 const char *h;
162
163                 status = dcerpc_parse_binding(talloc_autofree_context(), target, &binding_struct);
164                 if (NT_STATUS_IS_ERR(status)) {
165                         d_printf("Invalid option: %s is not a valid torture target (share or binding string)\n\n", target);
166                         return false;
167                 }
168
169                 h = dcerpc_binding_get_string_option(binding_struct, "host");
170                 host = discard_const_p(char, h);
171                 if (host != NULL) {
172                         lpcfg_set_cmdline(lp_ctx, "torture:host", host);
173                 }
174
175                 if (lpcfg_parm_string(lp_ctx, NULL, "torture", "share") == NULL)
176                         lpcfg_set_cmdline(lp_ctx, "torture:share", "IPC$");
177                 lpcfg_set_cmdline(lp_ctx, "torture:binding", target);
178         } else {
179                 lpcfg_set_cmdline(lp_ctx, "torture:host", host);
180                 lpcfg_set_cmdline(lp_ctx, "torture:share", share);
181                 lpcfg_set_cmdline(lp_ctx, "torture:binding", host);
182         }
183
184         return true;
185 }
186
187 static void parse_dns(struct loadparm_context *lp_ctx, const char *dns)
188 {
189         char *userdn, *basedn, *secret;
190         char *p, *d;
191
192         /* retrievieng the userdn */
193         p = strchr_m(dns, '#');
194         if (!p) {
195                 lpcfg_set_cmdline(lp_ctx, "torture:ldap_userdn", "");
196                 lpcfg_set_cmdline(lp_ctx, "torture:ldap_basedn", "");
197                 lpcfg_set_cmdline(lp_ctx, "torture:ldap_secret", "");
198                 return;
199         }
200         userdn = strndup(dns, p - dns);
201         lpcfg_set_cmdline(lp_ctx, "torture:ldap_userdn", userdn);
202
203         /* retrieve the basedn */
204         d = p + 1;
205         p = strchr_m(d, '#');
206         if (!p) {
207                 lpcfg_set_cmdline(lp_ctx, "torture:ldap_basedn", "");
208                 lpcfg_set_cmdline(lp_ctx, "torture:ldap_secret", "");
209                 return;
210         }
211         basedn = strndup(d, p - d);
212         lpcfg_set_cmdline(lp_ctx, "torture:ldap_basedn", basedn);
213
214         /* retrieve the secret */
215         p = p + 1;
216         if (!p) {
217                 lpcfg_set_cmdline(lp_ctx, "torture:ldap_secret", "");
218                 return;
219         }
220         secret = strdup(p);
221         lpcfg_set_cmdline(lp_ctx, "torture:ldap_secret", secret);
222
223         printf ("%s - %s - %s\n", userdn, basedn, secret);
224
225 }
226
227 /* Print the full test list, formatted into separate labelled test
228  * groups.
229  */
230 static void print_structured_testsuite_list(void)
231 {
232         struct torture_suite *o;
233         struct torture_suite *s;
234         struct torture_tcase *t;
235         int i;
236
237         if (torture_root == NULL) {
238             printf("NO TESTS LOADED\n");
239             return;
240         }
241
242         for (o = torture_root->children; o; o = o->next) {
243                 printf("\n%s (%s):\n  ", o->description, o->name);
244
245                 i = 0;
246                 for (s = o->children; s; s = s->next) {
247                         if (i + strlen(o->name) + strlen(s->name) >= (MAX_COLS - 3)) {
248                                 printf("\n  ");
249                                 i = 0;
250                         }
251                         i+=printf("%s.%s ", o->name, s->name);
252                 }
253
254                 for (t = o->testcases; t; t = t->next) {
255                         if (i + strlen(o->name) + strlen(t->name) >= (MAX_COLS - 3)) {
256                                 printf("\n  ");
257                                 i = 0;
258                         }
259                         i+=printf("%s.%s ", o->name, t->name);
260                 }
261
262                 if (i) printf("\n");
263         }
264
265         printf("\nThe default test is ALL.\n");
266 }
267
268 static void print_testsuite_list(void)
269 {
270         struct torture_suite *o;
271         struct torture_suite *s;
272         struct torture_tcase *t;
273
274         if (torture_root == NULL)
275                 return;
276
277         for (o = torture_root->children; o; o = o->next) {
278                 for (s = o->children; s; s = s->next) {
279                         printf("%s.%s\n", o->name, s->name);
280                 }
281
282                 for (t = o->testcases; t; t = t->next) {
283                         printf("%s.%s\n", o->name, t->name);
284                 }
285         }
286 }
287
288 void torture_print_testsuites(bool structured)
289 {
290         if (structured) {
291                 print_structured_testsuite_list();
292         } else {
293                 print_testsuite_list();
294         }
295 }
296
297 static void usage(poptContext pc)
298 {
299         poptPrintUsage(pc, stdout, 0);
300         printf("\n");
301
302         printf("The binding format is:\n\n");
303
304         printf("  TRANSPORT:host[flags]\n\n");
305
306         printf("  where TRANSPORT is either ncacn_np for SMB, ncacn_ip_tcp for RPC/TCP\n");
307         printf("  or ncalrpc for local connections.\n\n");
308
309         printf("  'host' is an IP or hostname or netbios name. If the binding string\n");
310         printf("  identifies the server side of an endpoint, 'host' may be an empty\n");
311         printf("  string.\n\n");
312
313         printf("  'flags' can include a SMB pipe name if using the ncacn_np transport or\n");
314         printf("  a TCP port number if using the ncacn_ip_tcp transport, otherwise they\n");
315         printf("  will be auto-determined.\n\n");
316
317         printf("  other recognised flags are:\n\n");
318
319         printf("    sign : enable ntlmssp signing\n");
320         printf("    seal : enable ntlmssp sealing\n");
321         printf("    connect : enable rpc connect level auth (auth, but no sign or seal)\n");
322         printf("    validate: enable the NDR validator\n");
323         printf("    print: enable debugging of the packets\n");
324         printf("    bigendian: use bigendian RPC\n");
325         printf("    padcheck: check reply data for non-zero pad bytes\n\n");
326
327         printf("  For example, these all connect to the samr pipe:\n\n");
328
329         printf("    ncacn_np:myserver\n");
330         printf("    ncacn_np:myserver[samr]\n");
331         printf("    ncacn_np:myserver[\\pipe\\samr]\n");
332         printf("    ncacn_np:myserver[/pipe/samr]\n");
333         printf("    ncacn_np:myserver[samr,sign,print]\n");
334         printf("    ncacn_np:myserver[\\pipe\\samr,sign,seal,bigendian]\n");
335         printf("    ncacn_np:myserver[/pipe/samr,seal,validate]\n");
336         printf("    ncacn_np:\n");
337         printf("    ncacn_np:[/pipe/samr]\n\n");
338
339         printf("    ncacn_ip_tcp:myserver\n");
340         printf("    ncacn_ip_tcp:myserver[1024]\n");
341         printf("    ncacn_ip_tcp:myserver[1024,sign,seal]\n\n");
342
343         printf("    ncalrpc:\n\n");
344
345         printf("The UNC format is:\n\n");
346
347         printf("  //server/share\n\n");
348
349         printf("Tests are:");
350
351         print_structured_testsuite_list();
352
353 }
354
355 _NORETURN_ static void max_runtime_handler(int sig)
356 {
357         DEBUG(0,("maximum runtime exceeded for smbtorture - terminating\n"));
358         exit(1);
359 }
360
361 /****************************************************************************
362   main program
363 ****************************************************************************/
364 int main(int argc, const char *argv[])
365 {
366         int opt, i;
367         bool correct = true;
368         int max_runtime=0;
369         int argc_new;
370         struct torture_context *torture;
371         struct torture_results *results;
372         const struct torture_ui_ops *ui_ops;
373         char **argv_new;
374         poptContext pc;
375         static const char *target = "other";
376         NTSTATUS status;
377         int shell = false;
378         static const char *ui_ops_name = "subunit";
379         const char *basedir = NULL;
380         char *outputdir;
381         const char *extra_module = NULL;
382         static int list_tests = 0, list_testsuites = 0;
383         int num_extra_users = 0;
384         const char **restricted = NULL;
385         int num_restricted = -1;
386         const char *load_list = NULL;
387         enum {OPT_LOADFILE=1000,OPT_UNCLIST,OPT_TIMELIMIT,OPT_DNS, OPT_LIST,
388               OPT_DANGEROUS,OPT_SMB_PORTS,OPT_ASYNC,OPT_NUMPROGS,
389               OPT_EXTRA_USER,};
390
391         struct poptOption long_options[] = {
392                 POPT_AUTOHELP
393                 {"format", 0, POPT_ARG_STRING, &ui_ops_name, 0, "Output format (one of: simple, subunit)", NULL },
394                 {"smb-ports",   'p', POPT_ARG_STRING, NULL,     OPT_SMB_PORTS,  "SMB ports",    NULL},
395                 {"basedir",       0, POPT_ARG_STRING, &basedir, 0, "base directory", "BASEDIR" },
396                 {"seed",          0, POPT_ARG_INT,  &torture_seed,      0,      "Seed to use for randomizer",   NULL},
397                 {"num-progs",     0, POPT_ARG_INT,  NULL,       OPT_NUMPROGS,   "num progs",    NULL},
398                 {"num-ops",       0, POPT_ARG_INT,  &torture_numops,    0,      "num ops",      NULL},
399                 {"entries",       0, POPT_ARG_INT,  &torture_entries,   0,      "entries",      NULL},
400                 {"loadfile",      0, POPT_ARG_STRING,   NULL,   OPT_LOADFILE,   "NBench load file to use",      NULL},
401                 {"list-suites",           0, POPT_ARG_NONE, &list_testsuites, 0, "List available testsuites and exit", NULL },
402                 {"list",          0, POPT_ARG_NONE, &list_tests, 0, "List available tests in specified suites and exit", NULL },
403                 {"unclist",       0, POPT_ARG_STRING,   NULL,   OPT_UNCLIST,    "unclist",      NULL},
404                 {"timelimit",   't', POPT_ARG_INT,      NULL,   OPT_TIMELIMIT,  "Set time limit (in seconds)",  NULL},
405                 {"failures",    'f', POPT_ARG_INT,  &torture_failures,  0,      "failures",     NULL},
406                 {"parse-dns",   'D', POPT_ARG_STRING,   NULL,   OPT_DNS,        "parse-dns",    NULL},
407                 {"dangerous",   'X', POPT_ARG_NONE,     NULL,   OPT_DANGEROUS,
408                  "run dangerous tests (eg. wiping out password database)", NULL},
409                 {"load-module",  0,  POPT_ARG_STRING, &extra_module,     0, "load tests from DSO file",    "SOFILE"},
410                 {"shell",               0, POPT_ARG_NONE, &shell, true, "Run shell", NULL},
411                 {"target",              'T', POPT_ARG_STRING, &target, 0, "samba3|samba4|other", NULL},
412                 {"async",       'a', POPT_ARG_NONE,     NULL,   OPT_ASYNC,
413                  "run async tests", NULL},
414                 {"num-async",    0, POPT_ARG_INT,  &torture_numasync,  0,
415                  "number of simultaneous async requests", NULL},
416                 {"maximum-runtime", 0, POPT_ARG_INT, &max_runtime, 0, 
417                  "set maximum time for smbtorture to live", "seconds"},
418                 {"extra-user",   0, POPT_ARG_STRING, NULL, OPT_EXTRA_USER,
419                  "extra user credentials", NULL},
420                 {"load-list", 0, POPT_ARG_STRING, &load_list, 0,
421              "load a test id list from a text file", NULL},
422                 POPT_COMMON_SAMBA
423                 POPT_COMMON_CONNECTION
424                 POPT_COMMON_CREDENTIALS
425                 POPT_COMMON_VERSION
426                 { NULL }
427         };
428
429         setlinebuf(stdout);
430
431         printf("smbtorture %s\n", samba_version_string());
432
433         /* we are never interested in SIGPIPE */
434         BlockSignals(true, SIGPIPE);
435
436         pc = poptGetContext("smbtorture", argc, argv, long_options,
437                             POPT_CONTEXT_KEEP_FIRST);
438
439         poptSetOtherOptionHelp(pc, "<binding>|<unc> TEST1 TEST2 ...");
440
441         while((opt = poptGetNextOpt(pc)) != -1) {
442                 switch (opt) {
443                 case OPT_LOADFILE:
444                         lpcfg_set_cmdline(cmdline_lp_ctx, "torture:loadfile", poptGetOptArg(pc));
445                         break;
446                 case OPT_UNCLIST:
447                         lpcfg_set_cmdline(cmdline_lp_ctx, "torture:unclist", poptGetOptArg(pc));
448                         break;
449                 case OPT_TIMELIMIT:
450                         lpcfg_set_cmdline(cmdline_lp_ctx, "torture:timelimit", poptGetOptArg(pc));
451                         break;
452                 case OPT_NUMPROGS:
453                         lpcfg_set_cmdline(cmdline_lp_ctx, "torture:nprocs", poptGetOptArg(pc));
454                         break;
455                 case OPT_DNS:
456                         parse_dns(cmdline_lp_ctx, poptGetOptArg(pc));
457                         break;
458                 case OPT_DANGEROUS:
459                         lpcfg_set_cmdline(cmdline_lp_ctx, "torture:dangerous", "Yes");
460                         break;
461                 case OPT_ASYNC:
462                         lpcfg_set_cmdline(cmdline_lp_ctx, "torture:async", "Yes");
463                         break;
464                 case OPT_SMB_PORTS:
465                         lpcfg_set_cmdline(cmdline_lp_ctx, "smb ports", poptGetOptArg(pc));
466                         break;
467                 case OPT_EXTRA_USER:
468                         {
469                                 char *option = talloc_asprintf(NULL, "torture:extra_user%u",
470                                                                ++num_extra_users);
471                                 const char *value = poptGetOptArg(pc);
472                                 lpcfg_set_cmdline(cmdline_lp_ctx, option, value);
473                                 talloc_free(option);
474                         }
475                         break;
476                 default:
477                         if (opt < 0) {
478                                 printf("bad command line option %d\n", opt);
479                                 exit(1);
480                         }
481                 }
482         }
483
484         if (load_list != NULL) {
485                 char **r;
486                 r = file_lines_load(load_list, &num_restricted, 0, talloc_autofree_context());
487                 restricted = discard_const_p(const char *, r);
488                 if (restricted == NULL) {
489                         printf("Unable to read load list file '%s'\n", load_list);
490                         exit(1);
491                 }
492         }
493
494         if (strcmp(target, "samba3") == 0) {
495                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:samba3", "true");
496                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:resume_key_support", "false");
497         } else if (strcmp(target, "samba4") == 0) {
498                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:samba4", "true");
499         } else if (strcmp(target, "samba4-ntvfs") == 0) {
500                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:samba4", "true");
501                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:samba4-ntvfs", "true");
502         } else if (strcmp(target, "winxp") == 0) {
503                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:winxp", "true");
504         } else if (strcmp(target, "w2k3") == 0) {
505                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:w2k3", "true");
506         } else if (strcmp(target, "w2k8") == 0) {
507                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:w2k8", "true");
508                 lpcfg_set_cmdline(cmdline_lp_ctx,
509                     "torture:invalid_lock_range_support", "false");
510         } else if (strcmp(target, "w2k12") == 0) {
511                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:w2k12", "true");
512         } else if (strcmp(target, "win7") == 0) {
513                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:win7", "true");
514                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:cn_max_buffer_size",
515                     "0x00010000");
516                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:resume_key_support", "false");
517                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:rewind_support", "false");
518
519                 /* RAW-SEARCH for fails for inexplicable reasons against win7 */
520                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:search_ea_support", "false");
521
522                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:hide_on_access_denied",
523                     "true");
524         } else if (strcmp(target, "onefs") == 0) {
525                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:onefs", "true");
526                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:openx_deny_dos_support",
527                     "false");
528                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:range_not_locked_on_file_close", "false");
529                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:sacl_support", "false");
530                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:ea_support", "false");
531                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:smbexit_pdu_support",
532                     "false");
533                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:smblock_pdu_support",
534                     "false");
535                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:2_step_break_to_none",
536                     "true");
537                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:deny_dos_support", "false");
538                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:deny_fcb_support", "false");
539                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:read_support", "false");
540                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:writeclose_support", "false");
541                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:resume_key_support", "false");
542                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:rewind_support", "false");
543                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:raw_search_search", "false");
544                 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:search_ea_size", "false");
545         }
546
547         if (max_runtime) {
548                 /* this will only work if nobody else uses alarm(),
549                    which means it won't work for some tests, but we
550                    can't use the event context method we use for smbd
551                    as so many tests create their own event
552                    context. This will at least catch most cases. */
553                 signal(SIGALRM, max_runtime_handler);
554                 alarm(max_runtime);
555         }
556
557         if (extra_module != NULL) {
558                 init_module_fn fn = load_module(poptGetOptArg(pc), false, NULL);
559
560                 if (fn == NULL) 
561                         d_printf("Unable to load module from %s\n", poptGetOptArg(pc));
562                 else {
563                         status = fn();
564                         if (NT_STATUS_IS_ERR(status)) {
565                                 d_printf("Error initializing module %s: %s\n", 
566                                         poptGetOptArg(pc), nt_errstr(status));
567                         }
568                 }
569         } else { 
570                 torture_init();
571         }
572
573         if (list_testsuites) {
574                 print_testsuite_list();
575                 return 0;
576         }
577
578         argv_new = discard_const_p(char *, poptGetArgs(pc));
579
580         argc_new = argc;
581         for (i=0; i<argc; i++) {
582                 if (argv_new[i] == NULL) {
583                         argc_new = i;
584                         break;
585                 }
586         }
587
588         if (list_tests) {
589                 if (argc_new == 1) {
590                         print_test_list(torture_root, NULL, "");
591                 } else {
592                         for (i=1;i<argc_new;i++) {
593                                 print_test_list(torture_root, NULL, argv_new[i]);
594                         }
595                 }
596                 return 0;
597         }
598
599         if (torture_seed == 0) {
600                 torture_seed = time(NULL);
601         } 
602         printf("Using seed %d\n", torture_seed);
603         srandom(torture_seed);
604
605         if (!strcmp(ui_ops_name, "simple")) {
606                 ui_ops = &torture_simple_ui_ops;
607         } else if (!strcmp(ui_ops_name, "subunit")) {
608                 ui_ops = &torture_subunit_ui_ops;
609         } else {
610                 printf("Unknown output format '%s'\n", ui_ops_name);
611                 exit(1);
612         }
613
614         results = torture_results_init(talloc_autofree_context(), ui_ops);
615
616         torture = torture_context_init(s4_event_context_init(talloc_autofree_context()),
617                                        results);
618         if (basedir != NULL) {
619                 if (basedir[0] != '/') {
620                         fprintf(stderr, "Please specify an absolute path to --basedir\n");
621                         return 1;
622                 }
623                 outputdir = talloc_asprintf(torture, "%s/smbtortureXXXXXX", basedir);
624         } else {
625                 char *pwd = talloc_size(torture, PATH_MAX);
626                 if (!getcwd(pwd, PATH_MAX)) {
627                         fprintf(stderr, "Unable to determine current working directory\n");
628                         return 1;
629                 }
630                 outputdir = talloc_asprintf(torture, "%s/smbtortureXXXXXX", pwd);
631         }
632         if (!outputdir) {
633                 fprintf(stderr, "Could not allocate per-run output dir\n");
634                 return 1;
635         }
636         torture->outputdir = mkdtemp(outputdir);
637         if (!torture->outputdir) {
638                 perror("Failed to make temp output dir");
639         }
640
641         torture->lp_ctx = cmdline_lp_ctx;
642
643         gensec_init();
644
645         if (shell) {
646                 /* In shell mode, just ignore any remaining test names. */
647                 torture_shell(torture);
648         } else {
649
650                 /* At this point, we should just have a target string,
651                  * followed by a series of test names. Unless we are in
652                  * shell mode, in which case we don't need anythig more.
653                  */
654
655                 if (argc_new < 3) {
656                         printf("You must specify a test to run, or 'ALL'\n");
657                         usage(pc);
658                         torture->results->returncode = 1;
659                 } else if (!torture_parse_target(cmdline_lp_ctx, argv_new[1])) {
660                 /* Take the target name or binding. */
661                         usage(pc);
662                         torture->results->returncode = 1;
663                 } else {
664                         for (i=2;i<argc_new;i++) {
665                                 if (!torture_run_named_tests(torture, argv_new[i],
666                                             (const char **)restricted)) {
667                                         correct = false;
668                                 }
669                         }
670                 }
671         }
672
673         /* Now delete the temp dir we created */
674         torture_deltree_outputdir(torture);
675
676         if (torture->results->returncode && correct) {
677                 return(0);
678         } else {
679                 return(1);
680         }
681 }