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