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