Merge branch 'v4-0-test' of ssh://git.samba.org/data/git/samba into v4-0-gmake3
[bbaumbach/samba-autobuild/.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 "lib/util/dlinklist.h"
35 #include "librpc/rpc/dcerpc.h"
36 #include "param/param.h"
37
38 static bool run_matching(struct torture_context *torture,
39                                                  const char *prefix, 
40                                                  const char *expr,
41                                                  struct torture_suite *suite,
42                                                  bool *matched)
43 {
44         bool ret = true;
45
46         if (suite == NULL) {
47                 struct torture_suite *o;
48
49                 for (o = torture_root->children; o; o = o->next) {
50                         if (gen_fnmatch(expr, o->name) == 0) {
51                                 *matched = true;
52                                 reload_charcnv(torture->lp_ctx);
53                                 ret &= torture_run_suite(torture, o);
54                                 continue;
55                         }
56
57                         ret &= run_matching(torture, o->name, expr, o, matched);
58                 }
59         } else {
60                 char *name;
61                 struct torture_suite *c;
62                 struct torture_tcase *t;
63
64                 for (c = suite->children; c; c = c->next) {
65                         asprintf(&name, "%s-%s", prefix, c->name);
66
67                         if (gen_fnmatch(expr, name) == 0) {
68                                 *matched = true;
69                                 reload_charcnv(torture->lp_ctx);
70                                 torture->active_testname = talloc_strdup(torture, prefix);
71                                 ret &= torture_run_suite(torture, c);
72                                 free(name);
73                                 continue;
74                         }
75                         
76                         ret &= run_matching(torture, name, expr, c, matched);
77
78                         free(name);
79                 }
80
81                 for (t = suite->testcases; t; t = t->next) {
82                         asprintf(&name, "%s-%s", prefix, t->name);
83                         if (gen_fnmatch(expr, name) == 0) {
84                                 *matched = true;
85                                 reload_charcnv(torture->lp_ctx);
86                                 torture->active_testname = talloc_strdup(torture, prefix);
87                                 ret &= torture_run_tcase(torture, t);
88                                 talloc_free(torture->active_testname);
89                         }
90                         free(name);
91                 }
92         }
93
94         return ret;
95 }
96
97 #define MAX_COLS 80 /* FIXME: Determine this at run-time */
98
99 /****************************************************************************
100 run a specified test or "ALL"
101 ****************************************************************************/
102 static bool run_test(struct torture_context *torture, const char *name)
103 {
104         bool ret = true;
105         bool matched = false;
106         struct torture_suite *o;
107
108         if (strequal(name, "ALL")) {
109                 for (o = torture_root->children; o; o = o->next) {
110                         ret &= torture_run_suite(torture, o);
111                 }
112                 return ret;
113         }
114
115         ret = run_matching(torture, NULL, name, NULL, &matched);
116
117         if (!matched) {
118                 printf("Unknown torture operation '%s'\n", name);
119                 return false;
120         }
121
122         return ret;
123 }
124
125 static bool parse_target(struct loadparm_context *lp_ctx, const char *target)
126 {
127         char *host = NULL, *share = NULL;
128         struct dcerpc_binding *binding_struct;
129         NTSTATUS status;
130
131         /* see if its a RPC transport specifier */
132         if (!smbcli_parse_unc(target, NULL, &host, &share)) {
133                 status = dcerpc_parse_binding(talloc_autofree_context(), target, &binding_struct);
134                 if (NT_STATUS_IS_ERR(status)) {
135                         d_printf("Invalid option: %s is not a valid torture target (share or binding string)\n\n", target);
136                         return false;
137                 }
138                 lp_set_cmdline(lp_ctx, "torture:host", binding_struct->host);
139                 if (lp_parm_string(lp_ctx, NULL, "torture", "share") == NULL)
140                         lp_set_cmdline(lp_ctx, "torture:share", "IPC$");
141                 lp_set_cmdline(lp_ctx, "torture:binding", target);
142         } else {
143                 lp_set_cmdline(lp_ctx, "torture:host", host);
144                 lp_set_cmdline(lp_ctx, "torture:share", share);
145                 lp_set_cmdline(lp_ctx, "torture:binding", host);
146         }
147
148         return true;
149 }
150
151 static void parse_dns(struct loadparm_context *lp_ctx, const char *dns)
152 {
153         char *userdn, *basedn, *secret;
154         char *p, *d;
155
156         /* retrievieng the userdn */
157         p = strchr_m(dns, '#');
158         if (!p) {
159                 lp_set_cmdline(lp_ctx, "torture:ldap_userdn", "");
160                 lp_set_cmdline(lp_ctx, "torture:ldap_basedn", "");
161                 lp_set_cmdline(lp_ctx, "torture:ldap_secret", "");
162                 return;
163         }
164         userdn = strndup(dns, p - dns);
165         lp_set_cmdline(lp_ctx, "torture:ldap_userdn", userdn);
166
167         /* retrieve the basedn */
168         d = p + 1;
169         p = strchr_m(d, '#');
170         if (!p) {
171                 lp_set_cmdline(lp_ctx, "torture:ldap_basedn", "");
172                 lp_set_cmdline(lp_ctx, "torture:ldap_secret", "");
173                 return;
174         }
175         basedn = strndup(d, p - d);
176         lp_set_cmdline(lp_ctx, "torture:ldap_basedn", basedn);
177
178         /* retrieve the secret */
179         p = p + 1;
180         if (!p) {
181                 lp_set_cmdline(lp_ctx, "torture:ldap_secret", "");
182                 return;
183         }
184         secret = strdup(p);
185         lp_set_cmdline(lp_ctx, "torture:ldap_secret", secret);
186
187         printf ("%s - %s - %s\n", userdn, basedn, secret);
188
189 }
190
191 static void print_test_list(void)
192 {
193         struct torture_suite *o;
194         struct torture_suite *s;
195         struct torture_tcase *t;
196
197         if (torture_root == NULL)
198                 return;
199
200         for (o = torture_root->children; o; o = o->next) {
201                 for (s = o->children; s; s = s->next) {
202                         printf("%s-%s\n", o->name, s->name);
203                 }
204
205                 for (t = o->testcases; t; t = t->next) {
206                         printf("%s-%s\n", o->name, t->name);
207                 }
208         }
209 }
210
211 _NORETURN_ static void usage(poptContext pc)
212 {
213         struct torture_suite *o;
214         struct torture_suite *s;
215         struct torture_tcase *t;
216         int i;
217
218         poptPrintUsage(pc, stdout, 0);
219         printf("\n");
220
221         printf("The binding format is:\n\n");
222
223         printf("  TRANSPORT:host[flags]\n\n");
224
225         printf("  where TRANSPORT is either ncacn_np for SMB, ncacn_ip_tcp for RPC/TCP\n");
226         printf("  or ncalrpc for local connections.\n\n");
227
228         printf("  'host' is an IP or hostname or netbios name. If the binding string\n");
229         printf("  identifies the server side of an endpoint, 'host' may be an empty\n");
230         printf("  string.\n\n");
231
232         printf("  'flags' can include a SMB pipe name if using the ncacn_np transport or\n");
233         printf("  a TCP port number if using the ncacn_ip_tcp transport, otherwise they\n");
234         printf("  will be auto-determined.\n\n");
235
236         printf("  other recognised flags are:\n\n");
237
238         printf("    sign : enable ntlmssp signing\n");
239         printf("    seal : enable ntlmssp sealing\n");
240         printf("    connect : enable rpc connect level auth (auth, but no sign or seal)\n");
241         printf("    validate: enable the NDR validator\n");
242         printf("    print: enable debugging of the packets\n");
243         printf("    bigendian: use bigendian RPC\n");
244         printf("    padcheck: check reply data for non-zero pad bytes\n\n");
245
246         printf("  For example, these all connect to the samr pipe:\n\n");
247
248         printf("    ncacn_np:myserver\n");
249         printf("    ncacn_np:myserver[samr]\n");
250         printf("    ncacn_np:myserver[\\pipe\\samr]\n");
251         printf("    ncacn_np:myserver[/pipe/samr]\n");
252         printf("    ncacn_np:myserver[samr,sign,print]\n");
253         printf("    ncacn_np:myserver[\\pipe\\samr,sign,seal,bigendian]\n");
254         printf("    ncacn_np:myserver[/pipe/samr,seal,validate]\n");
255         printf("    ncacn_np:\n");
256         printf("    ncacn_np:[/pipe/samr]\n\n");
257
258         printf("    ncacn_ip_tcp:myserver\n");
259         printf("    ncacn_ip_tcp:myserver[1024]\n");
260         printf("    ncacn_ip_tcp:myserver[1024,sign,seal]\n\n");
261
262         printf("    ncalrpc:\n\n");
263
264         printf("The UNC format is:\n\n");
265
266         printf("  //server/share\n\n");
267
268         printf("Tests are:");
269
270         if (torture_root == NULL) {
271             printf("NO TESTS LOADED\n");
272             exit(1);
273         }
274
275         for (o = torture_root->children; o; o = o->next) {
276                 printf("\n%s (%s):\n  ", o->description, o->name);
277
278                 i = 0;
279                 for (s = o->children; s; s = s->next) {
280                         if (i + strlen(o->name) + strlen(s->name) >= (MAX_COLS - 3)) {
281                                 printf("\n  ");
282                                 i = 0;
283                         }
284                         i+=printf("%s-%s ", o->name, s->name);
285                 }
286
287                 for (t = o->testcases; t; t = t->next) {
288                         if (i + strlen(o->name) + strlen(t->name) >= (MAX_COLS - 3)) {
289                                 printf("\n  ");
290                                 i = 0;
291                         }
292                         i+=printf("%s-%s ", o->name, t->name);
293                 }
294
295                 if (i) printf("\n");
296         }
297
298         printf("\nThe default test is ALL.\n");
299
300         exit(1);
301 }
302
303 _NORETURN_ static void max_runtime_handler(int sig)
304 {
305         DEBUG(0,("maximum runtime exceeded for smbtorture - terminating\n"));
306         exit(1);
307 }
308
309 struct timeval last_suite_started;
310
311 static void simple_suite_start(struct torture_context *ctx,
312                                struct torture_suite *suite)
313 {
314         last_suite_started = timeval_current();
315         printf("Running %s\n", suite->name);
316 }
317
318 static void simple_suite_finish(struct torture_context *ctx,
319                                 struct torture_suite *suite)
320 {
321
322         printf("%s took %g secs\n\n", suite->name, 
323                    timeval_elapsed(&last_suite_started));
324 }
325
326 static void simple_test_result(struct torture_context *context, 
327                                enum torture_result res, const char *reason)
328 {
329         switch (res) {
330         case TORTURE_OK:
331                 if (reason)
332                         printf("OK: %s\n", reason);
333                 break;
334         case TORTURE_FAIL:
335                 printf("TEST %s FAILED! - %s\n", context->active_test->name, reason);
336                 break;
337         case TORTURE_ERROR:
338                 printf("ERROR IN TEST %s! - %s\n", context->active_test->name, reason); 
339                 break;
340         case TORTURE_SKIP:
341                 printf("SKIP: %s - %s\n", context->active_test->name, reason);
342                 break;
343         }
344 }
345
346 static void simple_comment(struct torture_context *test, 
347                            const char *comment)
348 {
349         printf("%s", comment);
350 }
351
352 static void simple_warning(struct torture_context *test, 
353                            const char *comment)
354 {
355         fprintf(stderr, "WARNING: %s\n", comment);
356 }
357
358 const static struct torture_ui_ops std_ui_ops = {
359         .comment = simple_comment,
360         .warning = simple_warning,
361         .suite_start = simple_suite_start,
362         .suite_finish = simple_suite_finish,
363         .test_result = simple_test_result
364 };
365
366 static void subunit_init(struct torture_context *ctx) 
367 {
368         /* FIXME: register segv and bus handler */
369 }
370
371 static void subunit_suite_start(struct torture_context *ctx,
372                                 struct torture_suite *suite)
373 {
374 }
375
376 static void subunit_test_start(struct torture_context *ctx, 
377                                struct torture_tcase *tcase,
378                                struct torture_test *test)
379 {
380         printf("test: %s\n", test->name);
381 }
382
383 static void subunit_test_result(struct torture_context *context, 
384                                 enum torture_result res, const char *reason)
385 {
386         switch (res) {
387         case TORTURE_OK:
388                 printf("success: %s", context->active_test->name);
389                 break;
390         case TORTURE_FAIL:
391                 printf("failure: %s", context->active_test->name);
392                 break;
393         case TORTURE_ERROR:
394                 printf("error: %s", context->active_test->name);
395                 break;
396         case TORTURE_SKIP:
397                 printf("skip: %s", context->active_test->name);
398                 break;
399         }
400         if (reason)
401                 printf(" [\n%s\n]", reason);
402         printf("\n");
403 }
404
405 static void subunit_comment(struct torture_context *test,
406                             const char *comment)
407 {
408         fprintf(stderr, "%s", comment);
409 }
410
411 static void subunit_warning(struct torture_context *test,
412                             const char *comment)
413 {
414         fprintf(stderr, "WARNING!: %s\n", comment);
415 }
416
417 const static struct torture_ui_ops subunit_ui_ops = {
418         .init = subunit_init,
419         .comment = subunit_comment,
420         .warning = subunit_warning,
421         .test_start = subunit_test_start,
422         .test_result = subunit_test_result,
423         .suite_start = subunit_suite_start
424 };
425
426 static void quiet_suite_start(struct torture_context *ctx,
427                               struct torture_suite *suite)
428 {
429         int i;
430         ctx->quiet = true;
431         for (i = 1; i < ctx->level; i++) putchar('\t');
432         printf("%s: ", suite->name);
433         fflush(stdout);
434 }
435
436 static void quiet_suite_finish(struct torture_context *ctx,
437                                struct torture_suite *suite)
438 {
439         putchar('\n');
440 }
441
442 static void quiet_test_result(struct torture_context *context, 
443                               enum torture_result res, const char *reason)
444 {
445         fflush(stdout);
446         switch (res) {
447         case TORTURE_OK: putchar('.'); break;
448         case TORTURE_FAIL: putchar('F'); break;
449         case TORTURE_ERROR: putchar('E'); break;
450         case TORTURE_SKIP: putchar('I'); break;
451         }
452 }
453
454 const static struct torture_ui_ops quiet_ui_ops = {
455         .suite_start = quiet_suite_start,
456         .suite_finish = quiet_suite_finish,
457         .test_result = quiet_test_result
458 };
459
460 void run_shell(struct torture_context *tctx)
461 {
462         char *cline;
463         int argc;
464         const char **argv;
465         int ret;
466
467         while (1) {
468                 cline = smb_readline("torture> ", NULL, NULL);
469
470                 if (cline == NULL)
471                         return;
472         
473                 ret = poptParseArgvString(cline, &argc, &argv);
474                 if (ret != 0) {
475                         fprintf(stderr, "Error parsing line\n");
476                         continue;
477                 }
478
479                 if (!strcmp(argv[0], "quit")) {
480                         return;
481                 } else if (!strcmp(argv[0], "set")) {
482                         if (argc < 3) {
483                                 fprintf(stderr, "Usage: set <variable> <value>\n");
484                         } else {
485                                 char *name = talloc_asprintf(NULL, "torture:%s", argv[1]);
486                                 lp_set_cmdline(tctx->lp_ctx, name, argv[2]);
487                                 talloc_free(name);
488                         }
489                 } else if (!strcmp(argv[0], "help")) {
490                         fprintf(stderr, "Available commands:\n"
491                                                         " help - This help command\n"
492                                                         " run - Run test\n"
493                                                         " set - Change variables\n"
494                                                         "\n");
495                 } else if (!strcmp(argv[0], "run")) {
496                         if (argc < 2) {
497                                 fprintf(stderr, "Usage: run TEST-NAME [OPTIONS...]\n");
498                         } else {
499                                 run_test(tctx, argv[1]);
500                         }
501                 }
502                 free(cline);
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         if (extra_module != NULL) {
618             init_module_fn fn = load_module(talloc_autofree_context(), poptGetOptArg(pc));
619
620             if (fn == NULL) 
621                 d_printf("Unable to load module from %s\n", poptGetOptArg(pc));
622             else {
623                 status = fn();
624                 if (NT_STATUS_IS_ERR(status)) {
625                     d_printf("Error initializing module %s: %s\n", 
626                              poptGetOptArg(pc), nt_errstr(status));
627                 }
628             }
629         } else { 
630                 torture_init();
631         }
632
633         if (list_tests) {
634                 print_test_list();
635                 return 0;
636         }
637
638         if (torture_seed == 0) {
639                 torture_seed = time(NULL);
640         } 
641         printf("Using seed %d\n", torture_seed);
642         srandom(torture_seed);
643
644         argv_new = discard_const_p(char *, poptGetArgs(pc));
645
646         argc_new = argc;
647         for (i=0; i<argc; i++) {
648                 if (argv_new[i] == NULL) {
649                         argc_new = i;
650                         break;
651                 }
652         }
653
654         if (!(argc_new >= 3 || (shell && argc_new >= 2))) {
655                 usage(pc);
656                 exit(1);
657         }
658
659         if (!parse_target(cmdline_lp_ctx, argv_new[1])) {
660                 usage(pc);
661                 exit(1);
662         }
663
664         if (!strcmp(ui_ops_name, "simple")) {
665                 ui_ops = &std_ui_ops;
666         } else if (!strcmp(ui_ops_name, "subunit")) {
667                 ui_ops = &subunit_ui_ops;
668         } else if (!strcmp(ui_ops_name, "quiet")) {
669                 ui_ops = &quiet_ui_ops;
670         } else {
671                 printf("Unknown output format '%s'\n", ui_ops_name);
672                 exit(1);
673         }
674
675         torture = torture_context_init(talloc_autofree_context(), ui_ops);
676         if (basedir != NULL) {
677                 if (basedir[0] != '/') {
678                         fprintf(stderr, "Please specify an absolute path to --basedir\n");
679                         return 1;
680                 }
681                 torture->outputdir = basedir;
682         } else {
683                 char *pwd = talloc_size(torture, PATH_MAX);
684                 if (!getcwd(pwd, PATH_MAX)) {
685                         fprintf(stderr, "Unable to determine current working directory\n");
686                         return 1;
687                 }
688                 torture->outputdir = pwd;
689         }
690
691         torture->lp_ctx = cmdline_lp_ctx;
692
693         if (argc_new == 0) {
694                 printf("You must specify a test to run, or 'ALL'\n");
695         } else if (shell) {
696                 run_shell(torture);
697         } else {
698                 for (i=2;i<argc_new;i++) {
699                         if (!run_test(torture, argv_new[i])) {
700                                 correct = false;
701                         }
702                 }
703         }
704
705         if (torture->returncode && correct) {
706                 return(0);
707         } else {
708                 return(1);
709         }
710 }