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