smbtorture: Remove unused shell feature.
[amitay/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
46         if (suite == NULL) {
47                 struct torture_suite *o;
48
49                 for (o = (torture_root == NULL?NULL:torture_root->children); o; o = o->next) {
50                         if (gen_fnmatch(expr, o->name) == 0) {
51                                 *matched = true;
52                                 reload_charcnv(torture->lp_ctx);
53                                 ret &= torture_run_suite(torture, o);
54                                 continue;
55                         }
56
57                         ret &= run_matching(torture, o->name, expr, restricted, o, matched);
58                 }
59         } else {
60                 char *name;
61                 struct torture_suite *c;
62                 struct torture_tcase *t;
63
64                 for (c = suite->children; c; c = c->next) {
65                         asprintf(&name, "%s-%s", prefix, c->name);
66
67                         if (gen_fnmatch(expr, name) == 0) {
68                                 *matched = true;
69                                 reload_charcnv(torture->lp_ctx);
70                                 torture->active_testname = talloc_strdup(torture, prefix);
71                                 ret &= torture_run_suite(torture, c);
72                                 free(name);
73                                 continue;
74                         }
75                         
76                         ret &= run_matching(torture, name, expr, restricted, c, matched);
77
78                         free(name);
79                 }
80
81                 for (t = suite->testcases; t; t = t->next) {
82                         asprintf(&name, "%s-%s", prefix, t->name);
83                         if (gen_fnmatch(expr, name) == 0) {
84                                 *matched = true;
85                                 reload_charcnv(torture->lp_ctx);
86                                 torture->active_testname = talloc_strdup(torture, prefix);
87                                 ret &= torture_run_tcase(torture, t);
88                                 talloc_free(torture->active_testname);
89                         }
90                         free(name);
91                 }
92         }
93
94         return ret;
95 }
96
97 #define MAX_COLS 80 /* FIXME: Determine this at run-time */
98
99 /****************************************************************************
100 run a specified test or "ALL"
101 ****************************************************************************/
102 static bool run_test(struct torture_context *torture, const char *name,
103                                          char **restricted)
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, restricted, 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 static void simple_progress(struct torture_context *test,
360         int offset, enum torture_progress_whence whence)
361 {
362 }
363
364 const static struct torture_ui_ops std_ui_ops = {
365         .comment = simple_comment,
366         .warning = simple_warning,
367         .suite_start = simple_suite_start,
368         .suite_finish = simple_suite_finish,
369         .test_result = simple_test_result,
370         .progress = simple_progress,
371 };
372
373
374 /****************************************************************************
375   main program
376 ****************************************************************************/
377 int main(int argc,char *argv[])
378 {
379         int opt, i;
380         bool correct = true;
381         int max_runtime=0;
382         int argc_new;
383         struct torture_context *torture;
384         struct torture_results *results;
385         const struct torture_ui_ops *ui_ops;
386         char **argv_new;
387         poptContext pc;
388         static const char *target = "other";
389         NTSTATUS status;
390         static const char *ui_ops_name = "subunit";
391         const char *basedir = NULL;
392         const char *extra_module = NULL;
393         static int list_tests = 0;
394         int num_extra_users = 0;
395         char **restricted = NULL;
396         int num_restricted = -1;
397         enum {OPT_LOADFILE=1000,OPT_UNCLIST,OPT_TIMELIMIT,OPT_DNS, OPT_LIST,
398               OPT_DANGEROUS,OPT_SMB_PORTS,OPT_ASYNC,OPT_NUMPROGS,
399               OPT_EXTRA_USER,OPT_LOAD_LIST,};
400
401         struct poptOption long_options[] = {
402                 POPT_AUTOHELP
403                 {"format", 0, POPT_ARG_STRING, &ui_ops_name, 0, "Output format (one of: simple, subunit)", NULL },
404                 {"smb-ports",   'p', POPT_ARG_STRING, NULL,     OPT_SMB_PORTS,  "SMB ports",    NULL},
405                 {"basedir",       0, POPT_ARG_STRING, &basedir, 0, "base directory", "BASEDIR" },
406                 {"seed",          0, POPT_ARG_INT,  &torture_seed,      0,      "Seed to use for randomizer",   NULL},
407                 {"num-progs",     0, POPT_ARG_INT,  NULL,       OPT_NUMPROGS,   "num progs",    NULL},
408                 {"num-ops",       0, POPT_ARG_INT,  &torture_numops,    0,      "num ops",      NULL},
409                 {"entries",       0, POPT_ARG_INT,  &torture_entries,   0,      "entries",      NULL},
410                 {"loadfile",      0, POPT_ARG_STRING,   NULL,   OPT_LOADFILE,   "NBench load file to use",      NULL},
411                 {"list",          0, POPT_ARG_NONE, &list_tests, 0, "List available tests and exit", NULL },
412                 {"unclist",       0, POPT_ARG_STRING,   NULL,   OPT_UNCLIST,    "unclist",      NULL},
413                 {"timelimit",   't', POPT_ARG_INT,      NULL,   OPT_TIMELIMIT,  "Set time limit (in seconds)",  NULL},
414                 {"failures",    'f', POPT_ARG_INT,  &torture_failures,  0,      "failures",     NULL},
415                 {"parse-dns",   'D', POPT_ARG_STRING,   NULL,   OPT_DNS,        "parse-dns",    NULL},
416                 {"dangerous",   'X', POPT_ARG_NONE,     NULL,   OPT_DANGEROUS,
417                  "run dangerous tests (eg. wiping out password database)", NULL},
418                 {"load-module",  0,  POPT_ARG_STRING, &extra_module,     0, "load tests from DSO file",    "SOFILE"},
419                 {"target",              'T', POPT_ARG_STRING, &target, 0, "samba3|samba4|other", NULL},
420                 {"async",       'a', POPT_ARG_NONE,     NULL,   OPT_ASYNC,
421                  "run async tests", NULL},
422                 {"num-async",    0, POPT_ARG_INT,  &torture_numasync,  0,
423                  "number of simultaneous async requests", NULL},
424                 {"maximum-runtime", 0, POPT_ARG_INT, &max_runtime, 0, 
425                  "set maximum time for smbtorture to live", "seconds"},
426                 {"extra-user",   0, POPT_ARG_STRING, NULL, OPT_EXTRA_USER,
427                  "extra user credentials", NULL},
428                 {"load-list", 0, POPT_ARG_STRING, NULL, OPT_LOAD_LIST,
429              "load a test id list from a text file", NULL},
430                 POPT_COMMON_SAMBA
431                 POPT_COMMON_CONNECTION
432                 POPT_COMMON_CREDENTIALS
433                 POPT_COMMON_VERSION
434                 { NULL }
435         };
436
437         setlinebuf(stdout);
438
439         /* we are never interested in SIGPIPE */
440         BlockSignals(true, SIGPIPE);
441
442         pc = poptGetContext("smbtorture", argc, (const char **) argv, long_options, 
443                             POPT_CONTEXT_KEEP_FIRST);
444
445         poptSetOtherOptionHelp(pc, "<binding>|<unc> TEST1 TEST2 ...");
446
447         while((opt = poptGetNextOpt(pc)) != -1) {
448                 switch (opt) {
449                 case OPT_LOADFILE:
450                         lp_set_cmdline(cmdline_lp_ctx, "torture:loadfile", poptGetOptArg(pc));
451                         break;
452                 case OPT_UNCLIST:
453                         lp_set_cmdline(cmdline_lp_ctx, "torture:unclist", poptGetOptArg(pc));
454                         break;
455                 case OPT_TIMELIMIT:
456                         lp_set_cmdline(cmdline_lp_ctx, "torture:timelimit", poptGetOptArg(pc));
457                         break;
458                 case OPT_NUMPROGS:
459                         lp_set_cmdline(cmdline_lp_ctx, "torture:nprocs", poptGetOptArg(pc));
460                         break;
461                 case OPT_DNS:
462                         parse_dns(cmdline_lp_ctx, poptGetOptArg(pc));
463                         break;
464                 case OPT_DANGEROUS:
465                         lp_set_cmdline(cmdline_lp_ctx, "torture:dangerous", "Yes");
466                         break;
467                 case OPT_ASYNC:
468                         lp_set_cmdline(cmdline_lp_ctx, "torture:async", "Yes");
469                         break;
470                 case OPT_SMB_PORTS:
471                         lp_set_cmdline(cmdline_lp_ctx, "smb ports", poptGetOptArg(pc));
472                         break;
473                 case OPT_EXTRA_USER:
474                         {
475                                 char *option = talloc_asprintf(NULL, "torture:extra_user%u",
476                                                                ++num_extra_users);
477                                 const char *value = poptGetOptArg(pc);
478                                 lp_set_cmdline(cmdline_lp_ctx, option, value);
479                                 talloc_free(option);
480                         }
481                         break;
482                 case OPT_LOAD_LIST:
483                         restricted = file_lines_load(optarg, &num_restricted, 0,
484                                                                                  talloc_autofree_context());
485                         if (restricted == NULL) {
486                                 printf("Unable to read load list file '%s'\n", optarg);
487                                 exit(1);
488                         }
489                         break;
490                 default:
491                         printf("bad command line option\n");
492                         exit(1);
493                 }
494         }
495
496         if (strcmp(target, "samba3") == 0) {
497                 lp_set_cmdline(cmdline_lp_ctx, "torture:samba3", "true");
498                 lp_set_cmdline(cmdline_lp_ctx, "torture:resume_key_support", "false");
499         } else if (strcmp(target, "samba4") == 0) {
500                 lp_set_cmdline(cmdline_lp_ctx, "torture:samba4", "true");
501         } else if (strcmp(target, "winxp") == 0) {
502                 lp_set_cmdline(cmdline_lp_ctx, "torture:winxp", "true");
503         } else if (strcmp(target, "w2k3") == 0) {
504                 lp_set_cmdline(cmdline_lp_ctx, "torture:w2k3", "true");
505         } else if (strcmp(target, "w2k8") == 0) {
506                 lp_set_cmdline(cmdline_lp_ctx, "torture:w2k8", "true");
507                 lp_set_cmdline(cmdline_lp_ctx,
508                     "torture:invalid_lock_range_support", "false");
509         } else if (strcmp(target, "win7") == 0) {
510                 lp_set_cmdline(cmdline_lp_ctx, "torture:win7", "true");
511                 lp_set_cmdline(cmdline_lp_ctx, "torture:cn_max_buffer_size",
512                     "0x00010000");
513                 lp_set_cmdline(cmdline_lp_ctx, "torture:resume_key_support", "false");
514                 lp_set_cmdline(cmdline_lp_ctx, "torture:rewind_support", "false");
515
516                 /* RAW-SEARCH for fails for inexplicable reasons against win7 */
517                 lp_set_cmdline(cmdline_lp_ctx, "torture:search_ea_support", "false");
518
519                 lp_set_cmdline(cmdline_lp_ctx, "torture:hide_on_access_denied",
520                     "true");
521         } else if (strcmp(target, "onefs") == 0) {
522                 lp_set_cmdline(cmdline_lp_ctx, "torture:onefs", "true");
523                 lp_set_cmdline(cmdline_lp_ctx, "torture:openx_deny_dos_support",
524                     "false");
525                 lp_set_cmdline(cmdline_lp_ctx, "torture:range_not_locked_on_file_close", "false");
526                 lp_set_cmdline(cmdline_lp_ctx, "torture:sacl_support", "false");
527                 lp_set_cmdline(cmdline_lp_ctx, "torture:ea_support", "false");
528                 lp_set_cmdline(cmdline_lp_ctx, "torture:smbexit_pdu_support",
529                     "false");
530                 lp_set_cmdline(cmdline_lp_ctx, "torture:smblock_pdu_support",
531                     "false");
532                 lp_set_cmdline(cmdline_lp_ctx, "torture:2_step_break_to_none",
533                     "true");
534                 lp_set_cmdline(cmdline_lp_ctx, "torture:deny_dos_support", "false");
535                 lp_set_cmdline(cmdline_lp_ctx, "torture:deny_fcb_support", "false");
536                 lp_set_cmdline(cmdline_lp_ctx, "torture:read_support", "false");
537                 lp_set_cmdline(cmdline_lp_ctx, "torture:writeclose_support", "false");
538                 lp_set_cmdline(cmdline_lp_ctx, "torture:resume_key_support", "false");
539                 lp_set_cmdline(cmdline_lp_ctx, "torture:rewind_support", "false");
540         }
541
542         if (max_runtime) {
543                 /* this will only work if nobody else uses alarm(),
544                    which means it won't work for some tests, but we
545                    can't use the event context method we use for smbd
546                    as so many tests create their own event
547                    context. This will at least catch most cases. */
548                 signal(SIGALRM, max_runtime_handler);
549                 alarm(max_runtime);
550         }
551
552         if (extra_module != NULL) {
553             init_module_fn fn = load_module(talloc_autofree_context(), poptGetOptArg(pc));
554
555                 if (fn == NULL) 
556                         d_printf("Unable to load module from %s\n", poptGetOptArg(pc));
557                 else {
558                         status = fn();
559                         if (NT_STATUS_IS_ERR(status)) {
560                                 d_printf("Error initializing module %s: %s\n", 
561                                         poptGetOptArg(pc), nt_errstr(status));
562                         }
563                 }
564         } else { 
565                 torture_init();
566         }
567
568         if (list_tests) {
569                 print_test_list();
570                 return 0;
571         }
572
573         if (torture_seed == 0) {
574                 torture_seed = time(NULL);
575         } 
576         printf("Using seed %d\n", torture_seed);
577         srandom(torture_seed);
578
579         argv_new = discard_const_p(char *, poptGetArgs(pc));
580
581         argc_new = argc;
582         for (i=0; i<argc; i++) {
583                 if (argv_new[i] == NULL) {
584                         argc_new = i;
585                         break;
586                 }
587         }
588
589         if (!(argc_new >= 3)) {
590                 usage(pc);
591                 exit(1);
592         }
593
594         if (!parse_target(cmdline_lp_ctx, argv_new[1])) {
595                 usage(pc);
596                 exit(1);
597         }
598
599         if (!strcmp(ui_ops_name, "simple")) {
600                 ui_ops = &std_ui_ops;
601         } else if (!strcmp(ui_ops_name, "subunit")) {
602                 ui_ops = &torture_subunit_ui_ops;
603         } else {
604                 printf("Unknown output format '%s'\n", ui_ops_name);
605                 exit(1);
606         }
607
608         results = torture_results_init(talloc_autofree_context(), ui_ops);
609
610         torture = torture_context_init(s4_event_context_init(talloc_autofree_context()),
611                                        results);
612         if (basedir != NULL) {
613                 if (basedir[0] != '/') {
614                         fprintf(stderr, "Please specify an absolute path to --basedir\n");
615                         return 1;
616                 }
617                 torture->outputdir = basedir;
618         } else {
619                 char *pwd = talloc_size(torture, PATH_MAX);
620                 if (!getcwd(pwd, PATH_MAX)) {
621                         fprintf(stderr, "Unable to determine current working directory\n");
622                         return 1;
623                 }
624                 torture->outputdir = pwd;
625         }
626
627         torture->lp_ctx = cmdline_lp_ctx;
628
629         gensec_init(cmdline_lp_ctx);
630
631         if (argc_new == 0) {
632                 printf("You must specify a testsuite to run, or 'ALL'\n");
633         } else {
634                 for (i=2;i<argc_new;i++) {
635                         if (!run_test(torture, argv_new[i], restricted)) {
636                                 correct = false;
637                         }
638                 }
639         }
640
641         if (torture->results->returncode && correct) {
642                 return(0);
643         } else {
644                 return(1);
645         }
646 }