r26539: Remove unnecessary statics.
[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(torture->lp_ctx);
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(torture->lp_ctx);
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(torture->lp_ctx);
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                 free(cline);
504         }
505 }
506
507 /****************************************************************************
508   main program
509 ****************************************************************************/
510 int main(int argc,char *argv[])
511 {
512         int opt, i;
513         bool correct = true;
514         int max_runtime=0;
515         int argc_new;
516         struct torture_context *torture;
517         const struct torture_ui_ops *ui_ops;
518         char **argv_new;
519         poptContext pc;
520         const char *target = "other";
521         NTSTATUS status;
522         int shell = false;
523         const char *ui_ops_name = "simple";
524         const char *basedir = NULL;
525         const char *extra_module = NULL;
526         int list_tests = 0;
527         enum {OPT_LOADFILE=1000,OPT_UNCLIST,OPT_TIMELIMIT,OPT_DNS, OPT_LIST,
528               OPT_DANGEROUS,OPT_SMB_PORTS,OPT_ASYNC,OPT_NUMPROGS};
529         
530         struct poptOption long_options[] = {
531                 POPT_AUTOHELP
532                 {"format", 0, POPT_ARG_STRING, &ui_ops_name, 0, "Output format (one of: simple, subunit)", NULL },
533                 {"smb-ports",   'p', POPT_ARG_STRING, NULL,     OPT_SMB_PORTS,  "SMB ports",    NULL},
534                 {"basedir",       0, POPT_ARG_STRING, &basedir, 0, "base directory", "BASEDIR" },
535                 {"seed",          0, POPT_ARG_INT,  &torture_seed,      0,      "Seed to use for randomizer",   NULL},
536                 {"num-progs",     0, POPT_ARG_INT,  NULL,       OPT_NUMPROGS,   "num progs",    NULL},
537                 {"num-ops",       0, POPT_ARG_INT,  &torture_numops,    0,      "num ops",      NULL},
538                 {"entries",       0, POPT_ARG_INT,  &torture_entries,   0,      "entries",      NULL},
539                 {"loadfile",      0, POPT_ARG_STRING,   NULL,   OPT_LOADFILE,   "NBench load file to use",      NULL},
540                 {"list",          0, POPT_ARG_NONE, &list_tests, 0, "List available tests and exit", NULL },
541                 {"unclist",       0, POPT_ARG_STRING,   NULL,   OPT_UNCLIST,    "unclist",      NULL},
542                 {"timelimit",   't', POPT_ARG_INT,      NULL,   OPT_TIMELIMIT,  "Set time limit (in seconds)",  NULL},
543                 {"failures",    'f', POPT_ARG_INT,  &torture_failures,  0,      "failures",     NULL},
544                 {"parse-dns",   'D', POPT_ARG_STRING,   NULL,   OPT_DNS,        "parse-dns",    NULL},
545                 {"dangerous",   'X', POPT_ARG_NONE,     NULL,   OPT_DANGEROUS,
546                  "run dangerous tests (eg. wiping out password database)", NULL},
547                 {"load-module",  0,  POPT_ARG_STRING, &extra_module,     0, "load tests from DSO file",    "SOFILE"},
548                 {"shell",               0, POPT_ARG_NONE, &shell, true, "Run shell", NULL},
549                 {"target",              'T', POPT_ARG_STRING, &target, 0, "samba3|samba4|other", NULL},
550                 {"async",       'a', POPT_ARG_NONE,     NULL,   OPT_ASYNC,
551                  "run async tests", NULL},
552                 {"num-async",    0, POPT_ARG_INT,  &torture_numasync,  0,
553                  "number of simultaneous async requests", NULL},
554                 {"maximum-runtime", 0, POPT_ARG_INT, &max_runtime, 0, 
555                  "set maximum time for smbtorture to live", "seconds"},
556                 POPT_COMMON_SAMBA
557                 POPT_COMMON_CONNECTION
558                 POPT_COMMON_CREDENTIALS
559                 POPT_COMMON_VERSION
560                 { NULL }
561         };
562
563         setlinebuf(stdout);
564
565         /* we are never interested in SIGPIPE */
566         BlockSignals(true, SIGPIPE);
567
568         pc = poptGetContext("smbtorture", argc, (const char **) argv, long_options, 
569                             POPT_CONTEXT_KEEP_FIRST);
570
571         poptSetOtherOptionHelp(pc, "<binding>|<unc> TEST1 TEST2 ...");
572
573         while((opt = poptGetNextOpt(pc)) != -1) {
574                 switch (opt) {
575                 case OPT_LOADFILE:
576                         lp_set_cmdline(cmdline_lp_ctx, "torture:loadfile", poptGetOptArg(pc));
577                         break;
578                 case OPT_UNCLIST:
579                         lp_set_cmdline(cmdline_lp_ctx, "torture:unclist", poptGetOptArg(pc));
580                         break;
581                 case OPT_TIMELIMIT:
582                         lp_set_cmdline(cmdline_lp_ctx, "torture:timelimit", poptGetOptArg(pc));
583                         break;
584                 case OPT_NUMPROGS:
585                         lp_set_cmdline(cmdline_lp_ctx, "torture:nprocs", poptGetOptArg(pc));
586                         break;
587                 case OPT_DNS:
588                         parse_dns(cmdline_lp_ctx, poptGetOptArg(pc));
589                         break;
590                 case OPT_DANGEROUS:
591                         lp_set_cmdline(cmdline_lp_ctx, "torture:dangerous", "Yes");
592                         break;
593                 case OPT_ASYNC:
594                         lp_set_cmdline(cmdline_lp_ctx, "torture:async", "Yes");
595                         break;
596                 case OPT_SMB_PORTS:
597                         lp_set_cmdline(cmdline_lp_ctx, "smb ports", poptGetOptArg(pc));
598                         break;
599                 }
600         }
601
602         if (strcmp(target, "samba3") == 0) {
603                 lp_set_cmdline(cmdline_lp_ctx, "torture:samba3", "true");
604         } else if (strcmp(target, "samba4") == 0) {
605                 lp_set_cmdline(cmdline_lp_ctx, "torture:samba4", "true");
606         }
607
608         if (max_runtime) {
609                 /* this will only work if nobody else uses alarm(),
610                    which means it won't work for some tests, but we
611                    can't use the event context method we use for smbd
612                    as so many tests create their own event
613                    context. This will at least catch most cases. */
614                 signal(SIGALRM, max_runtime_handler);
615                 alarm(max_runtime);
616         }
617
618         ldb_global_init();
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(talloc_autofree_context(), 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 }