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