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