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