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