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