smbtorture: Add "target" command to interactive shell.
[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 #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                         torture->active_testname = name;
62                         if (restricted != NULL)
63                                 ret &= torture_run_suite_restricted(torture, o, restricted);
64                         else
65                                 ret &= torture_run_suite(torture, o);
66                 }
67                 ret &= run_matching(torture, name, expr, restricted, o, matched);
68         }
69
70         for (t = suite->testcases; t; t = t->next) {
71                 char *name = talloc_asprintf(torture, "%s-%s", prefix, t->name);
72                 if (gen_fnmatch(expr, name) == 0) {
73                         *matched = true;
74                         reload_charcnv(torture->lp_ctx);
75                         torture->active_testname = name;
76                         ret &= torture_run_tcase(torture, t);
77                 }
78                 for (p = t->tests; p; p = p->next) {
79                         name = talloc_asprintf(torture, "%s-%s-%s", prefix, t->name, p->name);
80                         if (gen_fnmatch(expr, name) == 0) {
81                                 *matched = true;
82                                 reload_charcnv(torture->lp_ctx);
83                                 torture->active_testname = name;
84                                 ret &= torture_run_test(torture, t, p);
85                         }
86                 }
87         }
88
89         return ret;
90 }
91
92 #define MAX_COLS 80 /* FIXME: Determine this at run-time */
93
94 /****************************************************************************
95 run a specified test or "ALL"
96 ****************************************************************************/
97 bool torture_run_named_tests(struct torture_context *torture, const char *name,
98                             const char **restricted)
99 {
100         bool ret = true;
101         bool matched = false;
102         struct torture_suite *o;
103
104         if (strequal(name, "ALL")) {
105                 if (restricted != NULL) {
106                         printf("--load-list and ALL are incompatible\n");
107                         return false;
108                 }
109                 for (o = torture_root->children; o; o = o->next) {
110                         ret &= torture_run_suite(torture, o);
111                 }
112                 return ret;
113         }
114
115         ret = run_matching(torture, NULL, name, restricted, torture_root, &matched);
116
117         if (!matched) {
118                 printf("Unknown torture operation '%s'\n", name);
119                 return false;
120         }
121
122         return ret;
123 }
124
125 bool torture_parse_target(struct loadparm_context *lp_ctx, const char *target)
126 {
127         char *host = NULL, *share = NULL;
128         struct dcerpc_binding *binding_struct;
129         NTSTATUS status;
130
131         /* see if its a RPC transport specifier */
132         if (!smbcli_parse_unc(target, NULL, &host, &share)) {
133                 status = dcerpc_parse_binding(talloc_autofree_context(), target, &binding_struct);
134                 if (NT_STATUS_IS_ERR(status)) {
135                         d_printf("Invalid option: %s is not a valid torture target (share or binding string)\n\n", target);
136                         return false;
137                 }
138                 lp_set_cmdline(lp_ctx, "torture:host", binding_struct->host);
139                 if (lp_parm_string(lp_ctx, NULL, "torture", "share") == NULL)
140                         lp_set_cmdline(lp_ctx, "torture:share", "IPC$");
141                 lp_set_cmdline(lp_ctx, "torture:binding", target);
142         } else {
143                 lp_set_cmdline(lp_ctx, "torture:host", host);
144                 lp_set_cmdline(lp_ctx, "torture:share", share);
145                 lp_set_cmdline(lp_ctx, "torture:binding", host);
146         }
147
148         return true;
149 }
150
151 static void parse_dns(struct loadparm_context *lp_ctx, const char *dns)
152 {
153         char *userdn, *basedn, *secret;
154         char *p, *d;
155
156         /* retrievieng the userdn */
157         p = strchr_m(dns, '#');
158         if (!p) {
159                 lp_set_cmdline(lp_ctx, "torture:ldap_userdn", "");
160                 lp_set_cmdline(lp_ctx, "torture:ldap_basedn", "");
161                 lp_set_cmdline(lp_ctx, "torture:ldap_secret", "");
162                 return;
163         }
164         userdn = strndup(dns, p - dns);
165         lp_set_cmdline(lp_ctx, "torture:ldap_userdn", userdn);
166
167         /* retrieve the basedn */
168         d = p + 1;
169         p = strchr_m(d, '#');
170         if (!p) {
171                 lp_set_cmdline(lp_ctx, "torture:ldap_basedn", "");
172                 lp_set_cmdline(lp_ctx, "torture:ldap_secret", "");
173                 return;
174         }
175         basedn = strndup(d, p - d);
176         lp_set_cmdline(lp_ctx, "torture:ldap_basedn", basedn);
177
178         /* retrieve the secret */
179         p = p + 1;
180         if (!p) {
181                 lp_set_cmdline(lp_ctx, "torture:ldap_secret", "");
182                 return;
183         }
184         secret = strdup(p);
185         lp_set_cmdline(lp_ctx, "torture:ldap_secret", secret);
186
187         printf ("%s - %s - %s\n", userdn, basedn, secret);
188
189 }
190
191 /* Print the full test list, formatted into separate labelled test
192  * groups.
193  */
194 static void print_structured_test_list(void)
195 {
196         struct torture_suite *o;
197         struct torture_suite *s;
198         struct torture_tcase *t;
199         int i;
200
201         if (torture_root == NULL) {
202             printf("NO TESTS LOADED\n");
203             return;
204         }
205
206         for (o = torture_root->children; o; o = o->next) {
207                 printf("\n%s (%s):\n  ", o->description, o->name);
208
209                 i = 0;
210                 for (s = o->children; s; s = s->next) {
211                         if (i + strlen(o->name) + strlen(s->name) >= (MAX_COLS - 3)) {
212                                 printf("\n  ");
213                                 i = 0;
214                         }
215                         i+=printf("%s-%s ", o->name, s->name);
216                 }
217
218                 for (t = o->testcases; t; t = t->next) {
219                         if (i + strlen(o->name) + strlen(t->name) >= (MAX_COLS - 3)) {
220                                 printf("\n  ");
221                                 i = 0;
222                         }
223                         i+=printf("%s-%s ", o->name, t->name);
224                 }
225
226                 if (i) printf("\n");
227         }
228
229         printf("\nThe default test is ALL.\n");
230 }
231
232 static void print_test_list(void)
233 {
234         struct torture_suite *o;
235         struct torture_suite *s;
236         struct torture_tcase *t;
237
238         if (torture_root == NULL)
239                 return;
240
241         for (o = torture_root->children; o; o = o->next) {
242                 for (s = o->children; s; s = s->next) {
243                         printf("%s-%s\n", o->name, s->name);
244                 }
245
246                 for (t = o->testcases; t; t = t->next) {
247                         printf("%s-%s\n", o->name, t->name);
248                 }
249         }
250 }
251
252 void torture_print_tests(bool structured)
253 {
254         if (structured) {
255                 print_structured_test_list();
256         } else {
257                 print_test_list();
258         }
259 }
260
261 _NORETURN_ static void usage(poptContext pc)
262 {
263         poptPrintUsage(pc, stdout, 0);
264         printf("\n");
265
266         printf("The binding format is:\n\n");
267
268         printf("  TRANSPORT:host[flags]\n\n");
269
270         printf("  where TRANSPORT is either ncacn_np for SMB, ncacn_ip_tcp for RPC/TCP\n");
271         printf("  or ncalrpc for local connections.\n\n");
272
273         printf("  'host' is an IP or hostname or netbios name. If the binding string\n");
274         printf("  identifies the server side of an endpoint, 'host' may be an empty\n");
275         printf("  string.\n\n");
276
277         printf("  'flags' can include a SMB pipe name if using the ncacn_np transport or\n");
278         printf("  a TCP port number if using the ncacn_ip_tcp transport, otherwise they\n");
279         printf("  will be auto-determined.\n\n");
280
281         printf("  other recognised flags are:\n\n");
282
283         printf("    sign : enable ntlmssp signing\n");
284         printf("    seal : enable ntlmssp sealing\n");
285         printf("    connect : enable rpc connect level auth (auth, but no sign or seal)\n");
286         printf("    validate: enable the NDR validator\n");
287         printf("    print: enable debugging of the packets\n");
288         printf("    bigendian: use bigendian RPC\n");
289         printf("    padcheck: check reply data for non-zero pad bytes\n\n");
290
291         printf("  For example, these all connect to the samr pipe:\n\n");
292
293         printf("    ncacn_np:myserver\n");
294         printf("    ncacn_np:myserver[samr]\n");
295         printf("    ncacn_np:myserver[\\pipe\\samr]\n");
296         printf("    ncacn_np:myserver[/pipe/samr]\n");
297         printf("    ncacn_np:myserver[samr,sign,print]\n");
298         printf("    ncacn_np:myserver[\\pipe\\samr,sign,seal,bigendian]\n");
299         printf("    ncacn_np:myserver[/pipe/samr,seal,validate]\n");
300         printf("    ncacn_np:\n");
301         printf("    ncacn_np:[/pipe/samr]\n\n");
302
303         printf("    ncacn_ip_tcp:myserver\n");
304         printf("    ncacn_ip_tcp:myserver[1024]\n");
305         printf("    ncacn_ip_tcp:myserver[1024,sign,seal]\n\n");
306
307         printf("    ncalrpc:\n\n");
308
309         printf("The UNC format is:\n\n");
310
311         printf("  //server/share\n\n");
312
313         printf("Tests are:");
314
315         print_structured_test_list();
316
317         exit(1);
318 }
319
320 _NORETURN_ static void max_runtime_handler(int sig)
321 {
322         DEBUG(0,("maximum runtime exceeded for smbtorture - terminating\n"));
323         exit(1);
324 }
325
326 struct timeval last_suite_started;
327
328 static void simple_suite_start(struct torture_context *ctx,
329                                struct torture_suite *suite)
330 {
331         last_suite_started = timeval_current();
332         printf("Running %s\n", suite->name);
333 }
334
335 static void simple_suite_finish(struct torture_context *ctx,
336                                 struct torture_suite *suite)
337 {
338
339         printf("%s took %g secs\n\n", suite->name, 
340                    timeval_elapsed(&last_suite_started));
341 }
342
343 static void simple_test_result(struct torture_context *context, 
344                                enum torture_result res, const char *reason)
345 {
346         switch (res) {
347         case TORTURE_OK:
348                 if (reason)
349                         printf("OK: %s\n", reason);
350                 break;
351         case TORTURE_FAIL:
352                 printf("TEST %s FAILED! - %s\n", context->active_test->name, reason);
353                 break;
354         case TORTURE_ERROR:
355                 printf("ERROR IN TEST %s! - %s\n", context->active_test->name, reason); 
356                 break;
357         case TORTURE_SKIP:
358                 printf("SKIP: %s - %s\n", context->active_test->name, reason);
359                 break;
360         }
361 }
362
363 static void simple_comment(struct torture_context *test, 
364                            const char *comment)
365 {
366         printf("%s", comment);
367 }
368
369 static void simple_warning(struct torture_context *test, 
370                            const char *comment)
371 {
372         fprintf(stderr, "WARNING: %s\n", comment);
373 }
374
375 static void simple_progress(struct torture_context *test,
376         int offset, enum torture_progress_whence whence)
377 {
378 }
379
380 const static struct torture_ui_ops std_ui_ops = {
381         .comment = simple_comment,
382         .warning = simple_warning,
383         .suite_start = simple_suite_start,
384         .suite_finish = simple_suite_finish,
385         .test_result = simple_test_result,
386         .progress = simple_progress,
387 };
388
389 /****************************************************************************
390   main program
391 ****************************************************************************/
392 int main(int argc,char *argv[])
393 {
394         int opt, i;
395         bool correct = true;
396         int max_runtime=0;
397         int argc_new;
398         struct torture_context *torture;
399         struct torture_results *results;
400         const struct torture_ui_ops *ui_ops;
401         char **argv_new;
402         poptContext pc;
403         static const char *target = "other";
404         NTSTATUS status;
405         int shell = false;
406         static const char *ui_ops_name = "subunit";
407         const char *basedir = NULL;
408         const char *extra_module = NULL;
409         static int list_tests = 0;
410         int num_extra_users = 0;
411         char **restricted = NULL;
412         int num_restricted = -1;
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,OPT_LOAD_LIST,};
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, NULL, OPT_LOAD_LIST,
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                         lp_set_cmdline(cmdline_lp_ctx, "torture:loadfile", poptGetOptArg(pc));
468                         break;
469                 case OPT_UNCLIST:
470                         lp_set_cmdline(cmdline_lp_ctx, "torture:unclist", poptGetOptArg(pc));
471                         break;
472                 case OPT_TIMELIMIT:
473                         lp_set_cmdline(cmdline_lp_ctx, "torture:timelimit", poptGetOptArg(pc));
474                         break;
475                 case OPT_NUMPROGS:
476                         lp_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                         lp_set_cmdline(cmdline_lp_ctx, "torture:dangerous", "Yes");
483                         break;
484                 case OPT_ASYNC:
485                         lp_set_cmdline(cmdline_lp_ctx, "torture:async", "Yes");
486                         break;
487                 case OPT_SMB_PORTS:
488                         lp_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                                 lp_set_cmdline(cmdline_lp_ctx, option, value);
496                                 talloc_free(option);
497                         }
498                         break;
499                 case OPT_LOAD_LIST:
500                         restricted = file_lines_load(optarg, &num_restricted, 0,
501                                                                                  talloc_autofree_context());
502                         if (restricted == NULL) {
503                                 printf("Unable to read load list file '%s'\n", optarg);
504                                 exit(1);
505                         }
506                         break;
507                 default:
508                         if (opt < 0) {
509                                 printf("bad command line option %d\n", opt);
510                                 exit(1);
511                         }
512                 }
513         }
514
515         if (strcmp(target, "samba3") == 0) {
516                 lp_set_cmdline(cmdline_lp_ctx, "torture:samba3", "true");
517                 lp_set_cmdline(cmdline_lp_ctx, "torture:resume_key_support", "false");
518         } else if (strcmp(target, "samba4") == 0) {
519                 lp_set_cmdline(cmdline_lp_ctx, "torture:samba4", "true");
520         } else if (strcmp(target, "winxp") == 0) {
521                 lp_set_cmdline(cmdline_lp_ctx, "torture:winxp", "true");
522         } else if (strcmp(target, "w2k3") == 0) {
523                 lp_set_cmdline(cmdline_lp_ctx, "torture:w2k3", "true");
524         } else if (strcmp(target, "w2k8") == 0) {
525                 lp_set_cmdline(cmdline_lp_ctx, "torture:w2k8", "true");
526                 lp_set_cmdline(cmdline_lp_ctx,
527                     "torture:invalid_lock_range_support", "false");
528         } else if (strcmp(target, "win7") == 0) {
529                 lp_set_cmdline(cmdline_lp_ctx, "torture:win7", "true");
530                 lp_set_cmdline(cmdline_lp_ctx, "torture:cn_max_buffer_size",
531                     "0x00010000");
532                 lp_set_cmdline(cmdline_lp_ctx, "torture:resume_key_support", "false");
533                 lp_set_cmdline(cmdline_lp_ctx, "torture:rewind_support", "false");
534
535                 /* RAW-SEARCH for fails for inexplicable reasons against win7 */
536                 lp_set_cmdline(cmdline_lp_ctx, "torture:search_ea_support", "false");
537
538                 lp_set_cmdline(cmdline_lp_ctx, "torture:hide_on_access_denied",
539                     "true");
540         } else if (strcmp(target, "onefs") == 0) {
541                 lp_set_cmdline(cmdline_lp_ctx, "torture:onefs", "true");
542                 lp_set_cmdline(cmdline_lp_ctx, "torture:openx_deny_dos_support",
543                     "false");
544                 lp_set_cmdline(cmdline_lp_ctx, "torture:range_not_locked_on_file_close", "false");
545                 lp_set_cmdline(cmdline_lp_ctx, "torture:sacl_support", "false");
546                 lp_set_cmdline(cmdline_lp_ctx, "torture:ea_support", "false");
547                 lp_set_cmdline(cmdline_lp_ctx, "torture:smbexit_pdu_support",
548                     "false");
549                 lp_set_cmdline(cmdline_lp_ctx, "torture:smblock_pdu_support",
550                     "false");
551                 lp_set_cmdline(cmdline_lp_ctx, "torture:2_step_break_to_none",
552                     "true");
553                 lp_set_cmdline(cmdline_lp_ctx, "torture:deny_dos_support", "false");
554                 lp_set_cmdline(cmdline_lp_ctx, "torture:deny_fcb_support", "false");
555                 lp_set_cmdline(cmdline_lp_ctx, "torture:read_support", "false");
556                 lp_set_cmdline(cmdline_lp_ctx, "torture:writeclose_support", "false");
557                 lp_set_cmdline(cmdline_lp_ctx, "torture:resume_key_support", "false");
558                 lp_set_cmdline(cmdline_lp_ctx, "torture:rewind_support", "false");
559                 lp_set_cmdline(cmdline_lp_ctx, "torture:raw_search_search", "false");
560                 lp_set_cmdline(cmdline_lp_ctx, "torture:search_ea_size", "false");
561         }
562
563         if (max_runtime) {
564                 /* this will only work if nobody else uses alarm(),
565                    which means it won't work for some tests, but we
566                    can't use the event context method we use for smbd
567                    as so many tests create their own event
568                    context. This will at least catch most cases. */
569                 signal(SIGALRM, max_runtime_handler);
570                 alarm(max_runtime);
571         }
572
573         if (extra_module != NULL) {
574             init_module_fn fn = load_module(talloc_autofree_context(), poptGetOptArg(pc));
575
576                 if (fn == NULL) 
577                         d_printf("Unable to load module from %s\n", poptGetOptArg(pc));
578                 else {
579                         status = fn();
580                         if (NT_STATUS_IS_ERR(status)) {
581                                 d_printf("Error initializing module %s: %s\n", 
582                                         poptGetOptArg(pc), nt_errstr(status));
583                         }
584                 }
585         } else { 
586                 torture_init();
587         }
588
589         if (list_tests) {
590                 print_test_list();
591                 return 0;
592         }
593
594         if (torture_seed == 0) {
595                 torture_seed = time(NULL);
596         } 
597         printf("Using seed %d\n", torture_seed);
598         srandom(torture_seed);
599
600         argv_new = discard_const_p(char *, poptGetArgs(pc));
601
602         argc_new = argc;
603         for (i=0; i<argc; i++) {
604                 if (argv_new[i] == NULL) {
605                         argc_new = i;
606                         break;
607                 }
608         }
609
610         if (!strcmp(ui_ops_name, "simple")) {
611                 ui_ops = &std_ui_ops;
612         } else if (!strcmp(ui_ops_name, "subunit")) {
613                 ui_ops = &torture_subunit_ui_ops;
614         } else {
615                 printf("Unknown output format '%s'\n", ui_ops_name);
616                 exit(1);
617         }
618
619         results = torture_results_init(talloc_autofree_context(), ui_ops);
620
621         torture = torture_context_init(s4_event_context_init(talloc_autofree_context()),
622                                        results);
623         if (basedir != NULL) {
624                 if (basedir[0] != '/') {
625                         fprintf(stderr, "Please specify an absolute path to --basedir\n");
626                         return 1;
627                 }
628                 torture->outputdir = basedir;
629         } else {
630                 char *pwd = talloc_size(torture, PATH_MAX);
631                 if (!getcwd(pwd, PATH_MAX)) {
632                         fprintf(stderr, "Unable to determine current working directory\n");
633                         return 1;
634                 }
635                 torture->outputdir = pwd;
636         }
637
638         torture->lp_ctx = cmdline_lp_ctx;
639
640         gensec_init(cmdline_lp_ctx);
641
642         // At this point, we should just have a target string,
643         // followed by a series of test names. Unless we are in
644         // shell mode, in which case we don't need anythig more.
645
646         if (argc_new > 1) {
647                 // Take the target name or binding.
648                 if (!torture_parse_target(cmdline_lp_ctx, argv_new[1])) {
649                         usage(pc);
650                         exit(1);
651                 }
652
653                 argc_new--;
654         }
655
656         if (shell) {
657                 // In shell mode, just ignore any remaining test names.
658                 torture_shell(torture);
659         } else if (argc_new == 1) {
660                 printf("You must specify a test to run, or 'ALL'\n");
661                 usage(pc);
662                 exit(1);
663         } else {
664                 for (i=1;i<argc_new;i++) {
665                         if (!torture_run_named_tests(torture, argv_new[i],
666                                     (const char **)restricted)) {
667                                 correct = false;
668                         }
669                 }
670         }
671
672         if (torture->results->returncode && correct) {
673                 return(0);
674         } else {
675                 return(1);
676         }
677 }