smbtorture: Report number of available tests in a testsuite using subunit.
[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 "lib/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
37 static bool run_matching(struct torture_context *torture,
38                                                  const char *prefix, 
39                                                  const char *expr,
40                                                  struct torture_suite *suite,
41                                                  bool *matched)
42 {
43         bool ret = true;
44
45         if (suite == NULL) {
46                 struct torture_suite *o;
47
48                 for (o = (torture_root == NULL?NULL:torture_root->children); o; o = o->next) {
49                         if (gen_fnmatch(expr, o->name) == 0) {
50                                 *matched = true;
51                                 reload_charcnv(torture->lp_ctx);
52                                 ret &= torture_run_suite(torture, o);
53                                 continue;
54                         }
55
56                         ret &= run_matching(torture, o->name, expr, o, matched);
57                 }
58         } else {
59                 char *name;
60                 struct torture_suite *c;
61                 struct torture_tcase *t;
62
63                 for (c = suite->children; c; c = c->next) {
64                         asprintf(&name, "%s-%s", prefix, c->name);
65
66                         if (gen_fnmatch(expr, name) == 0) {
67                                 *matched = true;
68                                 reload_charcnv(torture->lp_ctx);
69                                 torture->active_testname = talloc_strdup(torture, prefix);
70                                 ret &= torture_run_suite(torture, c);
71                                 free(name);
72                                 continue;
73                         }
74                         
75                         ret &= run_matching(torture, name, expr, c, matched);
76
77                         free(name);
78                 }
79
80                 for (t = suite->testcases; t; t = t->next) {
81                         asprintf(&name, "%s-%s", prefix, t->name);
82                         if (gen_fnmatch(expr, name) == 0) {
83                                 *matched = true;
84                                 reload_charcnv(torture->lp_ctx);
85                                 torture->active_testname = talloc_strdup(torture, prefix);
86                                 ret &= torture_run_tcase(torture, t);
87                                 talloc_free(torture->active_testname);
88                         }
89                         free(name);
90                 }
91         }
92
93         return ret;
94 }
95
96 #define MAX_COLS 80 /* FIXME: Determine this at run-time */
97
98 /****************************************************************************
99 run a specified test or "ALL"
100 ****************************************************************************/
101 static bool run_test(struct torture_context *torture, const char *name)
102 {
103         bool ret = true;
104         bool matched = false;
105         struct torture_suite *o;
106
107         if (strequal(name, "ALL")) {
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, NULL, &matched);
115
116         if (!matched) {
117                 printf("Unknown torture operation '%s'\n", name);
118                 return false;
119         }
120
121         return ret;
122 }
123
124 static bool 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                 lp_set_cmdline(lp_ctx, "torture:host", binding_struct->host);
138                 if (lp_parm_string(lp_ctx, NULL, "torture", "share") == NULL)
139                         lp_set_cmdline(lp_ctx, "torture:share", "IPC$");
140                 lp_set_cmdline(lp_ctx, "torture:binding", target);
141         } else {
142                 lp_set_cmdline(lp_ctx, "torture:host", host);
143                 lp_set_cmdline(lp_ctx, "torture:share", share);
144                 lp_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                 lp_set_cmdline(lp_ctx, "torture:ldap_userdn", "");
159                 lp_set_cmdline(lp_ctx, "torture:ldap_basedn", "");
160                 lp_set_cmdline(lp_ctx, "torture:ldap_secret", "");
161                 return;
162         }
163         userdn = strndup(dns, p - dns);
164         lp_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                 lp_set_cmdline(lp_ctx, "torture:ldap_basedn", "");
171                 lp_set_cmdline(lp_ctx, "torture:ldap_secret", "");
172                 return;
173         }
174         basedn = strndup(d, p - d);
175         lp_set_cmdline(lp_ctx, "torture:ldap_basedn", basedn);
176
177         /* retrieve the secret */
178         p = p + 1;
179         if (!p) {
180                 lp_set_cmdline(lp_ctx, "torture:ldap_secret", "");
181                 return;
182         }
183         secret = strdup(p);
184         lp_set_cmdline(lp_ctx, "torture:ldap_secret", secret);
185
186         printf ("%s - %s - %s\n", userdn, basedn, secret);
187
188 }
189
190 static void print_test_list(void)
191 {
192         struct torture_suite *o;
193         struct torture_suite *s;
194         struct torture_tcase *t;
195
196         if (torture_root == NULL)
197                 return;
198
199         for (o = torture_root->children; o; o = o->next) {
200                 for (s = o->children; s; s = s->next) {
201                         printf("%s-%s\n", o->name, s->name);
202                 }
203
204                 for (t = o->testcases; t; t = t->next) {
205                         printf("%s-%s\n", o->name, t->name);
206                 }
207         }
208 }
209
210 _NORETURN_ static void usage(poptContext pc)
211 {
212         struct torture_suite *o;
213         struct torture_suite *s;
214         struct torture_tcase *t;
215         int i;
216
217         poptPrintUsage(pc, stdout, 0);
218         printf("\n");
219
220         printf("The binding format is:\n\n");
221
222         printf("  TRANSPORT:host[flags]\n\n");
223
224         printf("  where TRANSPORT is either ncacn_np for SMB, ncacn_ip_tcp for RPC/TCP\n");
225         printf("  or ncalrpc for local connections.\n\n");
226
227         printf("  'host' is an IP or hostname or netbios name. If the binding string\n");
228         printf("  identifies the server side of an endpoint, 'host' may be an empty\n");
229         printf("  string.\n\n");
230
231         printf("  'flags' can include a SMB pipe name if using the ncacn_np transport or\n");
232         printf("  a TCP port number if using the ncacn_ip_tcp transport, otherwise they\n");
233         printf("  will be auto-determined.\n\n");
234
235         printf("  other recognised flags are:\n\n");
236
237         printf("    sign : enable ntlmssp signing\n");
238         printf("    seal : enable ntlmssp sealing\n");
239         printf("    connect : enable rpc connect level auth (auth, but no sign or seal)\n");
240         printf("    validate: enable the NDR validator\n");
241         printf("    print: enable debugging of the packets\n");
242         printf("    bigendian: use bigendian RPC\n");
243         printf("    padcheck: check reply data for non-zero pad bytes\n\n");
244
245         printf("  For example, these all connect to the samr pipe:\n\n");
246
247         printf("    ncacn_np:myserver\n");
248         printf("    ncacn_np:myserver[samr]\n");
249         printf("    ncacn_np:myserver[\\pipe\\samr]\n");
250         printf("    ncacn_np:myserver[/pipe/samr]\n");
251         printf("    ncacn_np:myserver[samr,sign,print]\n");
252         printf("    ncacn_np:myserver[\\pipe\\samr,sign,seal,bigendian]\n");
253         printf("    ncacn_np:myserver[/pipe/samr,seal,validate]\n");
254         printf("    ncacn_np:\n");
255         printf("    ncacn_np:[/pipe/samr]\n\n");
256
257         printf("    ncacn_ip_tcp:myserver\n");
258         printf("    ncacn_ip_tcp:myserver[1024]\n");
259         printf("    ncacn_ip_tcp:myserver[1024,sign,seal]\n\n");
260
261         printf("    ncalrpc:\n\n");
262
263         printf("The UNC format is:\n\n");
264
265         printf("  //server/share\n\n");
266
267         printf("Tests are:");
268
269         if (torture_root == NULL) {
270             printf("NO TESTS LOADED\n");
271             exit(1);
272         }
273
274         for (o = torture_root->children; o; o = o->next) {
275                 printf("\n%s (%s):\n  ", o->description, o->name);
276
277                 i = 0;
278                 for (s = o->children; s; s = s->next) {
279                         if (i + strlen(o->name) + strlen(s->name) >= (MAX_COLS - 3)) {
280                                 printf("\n  ");
281                                 i = 0;
282                         }
283                         i+=printf("%s-%s ", o->name, s->name);
284                 }
285
286                 for (t = o->testcases; t; t = t->next) {
287                         if (i + strlen(o->name) + strlen(t->name) >= (MAX_COLS - 3)) {
288                                 printf("\n  ");
289                                 i = 0;
290                         }
291                         i+=printf("%s-%s ", o->name, t->name);
292                 }
293
294                 if (i) printf("\n");
295         }
296
297         printf("\nThe default test is ALL.\n");
298
299         exit(1);
300 }
301
302 _NORETURN_ static void max_runtime_handler(int sig)
303 {
304         DEBUG(0,("maximum runtime exceeded for smbtorture - terminating\n"));
305         exit(1);
306 }
307
308 struct timeval last_suite_started;
309
310 static void simple_suite_start(struct torture_context *ctx,
311                                struct torture_suite *suite)
312 {
313         last_suite_started = timeval_current();
314         printf("Running %s\n", suite->name);
315 }
316
317 static void simple_suite_finish(struct torture_context *ctx,
318                                 struct torture_suite *suite)
319 {
320
321         printf("%s took %g secs\n\n", suite->name, 
322                    timeval_elapsed(&last_suite_started));
323 }
324
325 static void simple_test_result(struct torture_context *context, 
326                                enum torture_result res, const char *reason)
327 {
328         switch (res) {
329         case TORTURE_OK:
330                 if (reason)
331                         printf("OK: %s\n", reason);
332                 break;
333         case TORTURE_FAIL:
334                 printf("TEST %s FAILED! - %s\n", context->active_test->name, reason);
335                 break;
336         case TORTURE_ERROR:
337                 printf("ERROR IN TEST %s! - %s\n", context->active_test->name, reason); 
338                 break;
339         case TORTURE_SKIP:
340                 printf("SKIP: %s - %s\n", context->active_test->name, reason);
341                 break;
342         }
343 }
344
345 static void simple_comment(struct torture_context *test, 
346                            const char *comment)
347 {
348         printf("%s", comment);
349 }
350
351 static void simple_warning(struct torture_context *test, 
352                            const char *comment)
353 {
354         fprintf(stderr, "WARNING: %s\n", comment);
355 }
356
357 static void simple_progress(struct torture_context *test,
358         int offset, enum torture_progress_whence whence)
359 {
360 }
361
362 const static struct torture_ui_ops std_ui_ops = {
363         .comment = simple_comment,
364         .warning = simple_warning,
365         .suite_start = simple_suite_start,
366         .suite_finish = simple_suite_finish,
367         .test_result = simple_test_result,
368         .progress = simple_progress,
369 };
370
371
372 static void run_shell(struct torture_context *tctx)
373 {
374         char *cline;
375         int argc;
376         const char **argv;
377         int ret;
378
379         while (1) {
380                 cline = smb_readline("torture> ", NULL, NULL);
381
382                 if (cline == NULL)
383                         return;
384         
385                 ret = poptParseArgvString(cline, &argc, &argv);
386                 if (ret != 0) {
387                         fprintf(stderr, "Error parsing line\n");
388                         continue;
389                 }
390
391                 if (!strcmp(argv[0], "quit")) {
392                         return;
393                 } else if (!strcmp(argv[0], "set")) {
394                         if (argc < 3) {
395                                 fprintf(stderr, "Usage: set <variable> <value>\n");
396                         } else {
397                                 char *name = talloc_asprintf(NULL, "torture:%s", argv[1]);
398                                 lp_set_cmdline(tctx->lp_ctx, name, argv[2]);
399                                 talloc_free(name);
400                         }
401                 } else if (!strcmp(argv[0], "help")) {
402                         fprintf(stderr, "Available commands:\n"
403                                                         " help - This help command\n"
404                                                         " run - Run test\n"
405                                                         " set - Change variables\n"
406                                                         "\n");
407                 } else if (!strcmp(argv[0], "run")) {
408                         if (argc < 2) {
409                                 fprintf(stderr, "Usage: run TEST-NAME [OPTIONS...]\n");
410                         } else {
411                                 run_test(tctx, argv[1]);
412                         }
413                 }
414                 free(cline);
415         }
416 }
417
418 /****************************************************************************
419   main program
420 ****************************************************************************/
421 int main(int argc,char *argv[])
422 {
423         int opt, i;
424         bool correct = true;
425         int max_runtime=0;
426         int argc_new;
427         struct torture_context *torture;
428         struct torture_results *results;
429         const struct torture_ui_ops *ui_ops;
430         char **argv_new;
431         poptContext pc;
432         static const char *target = "other";
433         NTSTATUS status;
434         int shell = false;
435         static const char *ui_ops_name = "subunit";
436         const char *basedir = NULL;
437         const char *extra_module = NULL;
438         static int list_tests = 0;
439         int num_extra_users = 0;
440         enum {OPT_LOADFILE=1000,OPT_UNCLIST,OPT_TIMELIMIT,OPT_DNS, OPT_LIST,
441               OPT_DANGEROUS,OPT_SMB_PORTS,OPT_ASYNC,OPT_NUMPROGS,
442               OPT_EXTRA_USER,};
443
444         struct poptOption long_options[] = {
445                 POPT_AUTOHELP
446                 {"format", 0, POPT_ARG_STRING, &ui_ops_name, 0, "Output format (one of: simple, subunit)", NULL },
447                 {"smb-ports",   'p', POPT_ARG_STRING, NULL,     OPT_SMB_PORTS,  "SMB ports",    NULL},
448                 {"basedir",       0, POPT_ARG_STRING, &basedir, 0, "base directory", "BASEDIR" },
449                 {"seed",          0, POPT_ARG_INT,  &torture_seed,      0,      "Seed to use for randomizer",   NULL},
450                 {"num-progs",     0, POPT_ARG_INT,  NULL,       OPT_NUMPROGS,   "num progs",    NULL},
451                 {"num-ops",       0, POPT_ARG_INT,  &torture_numops,    0,      "num ops",      NULL},
452                 {"entries",       0, POPT_ARG_INT,  &torture_entries,   0,      "entries",      NULL},
453                 {"loadfile",      0, POPT_ARG_STRING,   NULL,   OPT_LOADFILE,   "NBench load file to use",      NULL},
454                 {"list",          0, POPT_ARG_NONE, &list_tests, 0, "List available tests and exit", NULL },
455                 {"unclist",       0, POPT_ARG_STRING,   NULL,   OPT_UNCLIST,    "unclist",      NULL},
456                 {"timelimit",   't', POPT_ARG_INT,      NULL,   OPT_TIMELIMIT,  "Set time limit (in seconds)",  NULL},
457                 {"failures",    'f', POPT_ARG_INT,  &torture_failures,  0,      "failures",     NULL},
458                 {"parse-dns",   'D', POPT_ARG_STRING,   NULL,   OPT_DNS,        "parse-dns",    NULL},
459                 {"dangerous",   'X', POPT_ARG_NONE,     NULL,   OPT_DANGEROUS,
460                  "run dangerous tests (eg. wiping out password database)", NULL},
461                 {"load-module",  0,  POPT_ARG_STRING, &extra_module,     0, "load tests from DSO file",    "SOFILE"},
462                 {"shell",               0, POPT_ARG_NONE, &shell, true, "Run shell", NULL},
463                 {"target",              'T', POPT_ARG_STRING, &target, 0, "samba3|samba4|other", NULL},
464                 {"async",       'a', POPT_ARG_NONE,     NULL,   OPT_ASYNC,
465                  "run async tests", NULL},
466                 {"num-async",    0, POPT_ARG_INT,  &torture_numasync,  0,
467                  "number of simultaneous async requests", NULL},
468                 {"maximum-runtime", 0, POPT_ARG_INT, &max_runtime, 0, 
469                  "set maximum time for smbtorture to live", "seconds"},
470                 {"extra-user",   0, POPT_ARG_STRING, NULL, OPT_EXTRA_USER,
471                  "extra user credentials", NULL},
472                 POPT_COMMON_SAMBA
473                 POPT_COMMON_CONNECTION
474                 POPT_COMMON_CREDENTIALS
475                 POPT_COMMON_VERSION
476                 { NULL }
477         };
478
479         setlinebuf(stdout);
480
481         /* we are never interested in SIGPIPE */
482         BlockSignals(true, SIGPIPE);
483
484         pc = poptGetContext("smbtorture", argc, (const char **) argv, long_options, 
485                             POPT_CONTEXT_KEEP_FIRST);
486
487         poptSetOtherOptionHelp(pc, "<binding>|<unc> TEST1 TEST2 ...");
488
489         while((opt = poptGetNextOpt(pc)) != -1) {
490                 switch (opt) {
491                 case OPT_LOADFILE:
492                         lp_set_cmdline(cmdline_lp_ctx, "torture:loadfile", poptGetOptArg(pc));
493                         break;
494                 case OPT_UNCLIST:
495                         lp_set_cmdline(cmdline_lp_ctx, "torture:unclist", poptGetOptArg(pc));
496                         break;
497                 case OPT_TIMELIMIT:
498                         lp_set_cmdline(cmdline_lp_ctx, "torture:timelimit", poptGetOptArg(pc));
499                         break;
500                 case OPT_NUMPROGS:
501                         lp_set_cmdline(cmdline_lp_ctx, "torture:nprocs", poptGetOptArg(pc));
502                         break;
503                 case OPT_DNS:
504                         parse_dns(cmdline_lp_ctx, poptGetOptArg(pc));
505                         break;
506                 case OPT_DANGEROUS:
507                         lp_set_cmdline(cmdline_lp_ctx, "torture:dangerous", "Yes");
508                         break;
509                 case OPT_ASYNC:
510                         lp_set_cmdline(cmdline_lp_ctx, "torture:async", "Yes");
511                         break;
512                 case OPT_SMB_PORTS:
513                         lp_set_cmdline(cmdline_lp_ctx, "smb ports", poptGetOptArg(pc));
514                         break;
515                 case OPT_EXTRA_USER:
516                         {
517                                 char *option = talloc_asprintf(NULL, "torture:extra_user%u",
518                                                                ++num_extra_users);
519                                 const char *value = poptGetOptArg(pc);
520                                 lp_set_cmdline(cmdline_lp_ctx, option, value);
521                                 talloc_free(option);
522                         }
523                         break;
524                 default:
525                         printf("bad command line option\n");
526                         exit(1);
527                 }
528         }
529
530         if (strcmp(target, "samba3") == 0) {
531                 lp_set_cmdline(cmdline_lp_ctx, "torture:samba3", "true");
532                 lp_set_cmdline(cmdline_lp_ctx, "torture:resume_key_support", "false");
533         } else if (strcmp(target, "samba4") == 0) {
534                 lp_set_cmdline(cmdline_lp_ctx, "torture:samba4", "true");
535         } else if (strcmp(target, "winxp") == 0) {
536                 lp_set_cmdline(cmdline_lp_ctx, "torture:winxp", "true");
537         } else if (strcmp(target, "w2k3") == 0) {
538                 lp_set_cmdline(cmdline_lp_ctx, "torture:w2k3", "true");
539         } else if (strcmp(target, "w2k8") == 0) {
540                 lp_set_cmdline(cmdline_lp_ctx, "torture:w2k8", "true");
541                 lp_set_cmdline(cmdline_lp_ctx,
542                     "torture:invalid_lock_range_support", "false");
543         } else if (strcmp(target, "win7") == 0) {
544                 lp_set_cmdline(cmdline_lp_ctx, "torture:win7", "true");
545                 lp_set_cmdline(cmdline_lp_ctx, "torture:cn_max_buffer_size",
546                     "0x00010000");
547                 lp_set_cmdline(cmdline_lp_ctx, "torture:resume_key_support", "false");
548                 lp_set_cmdline(cmdline_lp_ctx, "torture:rewind_support", "false");
549
550                 /* RAW-SEARCH for fails for inexplicable reasons against win7 */
551                 lp_set_cmdline(cmdline_lp_ctx, "torture:search_ea_support", "false");
552
553                 lp_set_cmdline(cmdline_lp_ctx, "torture:hide_on_access_denied",
554                     "true");
555         } else if (strcmp(target, "onefs") == 0) {
556                 lp_set_cmdline(cmdline_lp_ctx, "torture:onefs", "true");
557                 lp_set_cmdline(cmdline_lp_ctx, "torture:openx_deny_dos_support",
558                     "false");
559                 lp_set_cmdline(cmdline_lp_ctx, "torture:range_not_locked_on_file_close", "false");
560                 lp_set_cmdline(cmdline_lp_ctx, "torture:sacl_support", "false");
561                 lp_set_cmdline(cmdline_lp_ctx, "torture:ea_support", "false");
562                 lp_set_cmdline(cmdline_lp_ctx, "torture:smbexit_pdu_support",
563                     "false");
564                 lp_set_cmdline(cmdline_lp_ctx, "torture:smblock_pdu_support",
565                     "false");
566                 lp_set_cmdline(cmdline_lp_ctx, "torture:2_step_break_to_none",
567                     "true");
568                 lp_set_cmdline(cmdline_lp_ctx, "torture:deny_dos_support", "false");
569                 lp_set_cmdline(cmdline_lp_ctx, "torture:deny_fcb_support", "false");
570                 lp_set_cmdline(cmdline_lp_ctx, "torture:read_support", "false");
571                 lp_set_cmdline(cmdline_lp_ctx, "torture:writeclose_support", "false");
572                 lp_set_cmdline(cmdline_lp_ctx, "torture:resume_key_support", "false");
573                 lp_set_cmdline(cmdline_lp_ctx, "torture:rewind_support", "false");
574         }
575
576         if (max_runtime) {
577                 /* this will only work if nobody else uses alarm(),
578                    which means it won't work for some tests, but we
579                    can't use the event context method we use for smbd
580                    as so many tests create their own event
581                    context. This will at least catch most cases. */
582                 signal(SIGALRM, max_runtime_handler);
583                 alarm(max_runtime);
584         }
585
586         if (extra_module != NULL) {
587             init_module_fn fn = load_module(talloc_autofree_context(), poptGetOptArg(pc));
588
589             if (fn == NULL) 
590                 d_printf("Unable to load module from %s\n", poptGetOptArg(pc));
591             else {
592                 status = fn();
593                 if (NT_STATUS_IS_ERR(status)) {
594                     d_printf("Error initializing module %s: %s\n", 
595                              poptGetOptArg(pc), nt_errstr(status));
596                 }
597             }
598         } else { 
599                 torture_init();
600         }
601
602         if (list_tests) {
603                 print_test_list();
604                 return 0;
605         }
606
607         if (torture_seed == 0) {
608                 torture_seed = time(NULL);
609         } 
610         printf("Using seed %d\n", torture_seed);
611         srandom(torture_seed);
612
613         argv_new = discard_const_p(char *, poptGetArgs(pc));
614
615         argc_new = argc;
616         for (i=0; i<argc; i++) {
617                 if (argv_new[i] == NULL) {
618                         argc_new = i;
619                         break;
620                 }
621         }
622
623         if (!(argc_new >= 3 || (shell && argc_new >= 2))) {
624                 usage(pc);
625                 exit(1);
626         }
627
628         if (!parse_target(cmdline_lp_ctx, argv_new[1])) {
629                 usage(pc);
630                 exit(1);
631         }
632
633         if (!strcmp(ui_ops_name, "simple")) {
634                 ui_ops = &std_ui_ops;
635         } else if (!strcmp(ui_ops_name, "subunit")) {
636                 ui_ops = &torture_subunit_ui_ops;
637         } else {
638                 printf("Unknown output format '%s'\n", ui_ops_name);
639                 exit(1);
640         }
641
642         results = torture_results_init(talloc_autofree_context(), ui_ops);
643
644         torture = torture_context_init(s4_event_context_init(NULL), results);
645         if (basedir != NULL) {
646                 if (basedir[0] != '/') {
647                         fprintf(stderr, "Please specify an absolute path to --basedir\n");
648                         return 1;
649                 }
650                 torture->outputdir = basedir;
651         } else {
652                 char *pwd = talloc_size(torture, PATH_MAX);
653                 if (!getcwd(pwd, PATH_MAX)) {
654                         fprintf(stderr, "Unable to determine current working directory\n");
655                         return 1;
656                 }
657                 torture->outputdir = pwd;
658         }
659
660         torture->lp_ctx = cmdline_lp_ctx;
661
662         gensec_init(cmdline_lp_ctx);
663
664         if (argc_new == 0) {
665                 printf("You must specify a test to run, or 'ALL'\n");
666         } else if (shell) {
667                 run_shell(torture);
668         } else {
669                 for (i=2;i<argc_new;i++) {
670                         if (!run_test(torture, argv_new[i])) {
671                                 correct = false;
672                         }
673                 }
674         }
675
676         if (torture->results->returncode && correct) {
677                 return(0);
678         } else {
679                 return(1);
680         }
681 }