smbtorture: Fix loading of --load-list.
[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         const char *load_list = NULL;
414         enum {OPT_LOADFILE=1000,OPT_UNCLIST,OPT_TIMELIMIT,OPT_DNS, OPT_LIST,
415               OPT_DANGEROUS,OPT_SMB_PORTS,OPT_ASYNC,OPT_NUMPROGS,
416               OPT_EXTRA_USER,};
417
418         struct poptOption long_options[] = {
419                 POPT_AUTOHELP
420                 {"format", 0, POPT_ARG_STRING, &ui_ops_name, 0, "Output format (one of: simple, subunit)", NULL },
421                 {"smb-ports",   'p', POPT_ARG_STRING, NULL,     OPT_SMB_PORTS,  "SMB ports",    NULL},
422                 {"basedir",       0, POPT_ARG_STRING, &basedir, 0, "base directory", "BASEDIR" },
423                 {"seed",          0, POPT_ARG_INT,  &torture_seed,      0,      "Seed to use for randomizer",   NULL},
424                 {"num-progs",     0, POPT_ARG_INT,  NULL,       OPT_NUMPROGS,   "num progs",    NULL},
425                 {"num-ops",       0, POPT_ARG_INT,  &torture_numops,    0,      "num ops",      NULL},
426                 {"entries",       0, POPT_ARG_INT,  &torture_entries,   0,      "entries",      NULL},
427                 {"loadfile",      0, POPT_ARG_STRING,   NULL,   OPT_LOADFILE,   "NBench load file to use",      NULL},
428                 {"list",          0, POPT_ARG_NONE, &list_tests, 0, "List available tests and exit", NULL },
429                 {"unclist",       0, POPT_ARG_STRING,   NULL,   OPT_UNCLIST,    "unclist",      NULL},
430                 {"timelimit",   't', POPT_ARG_INT,      NULL,   OPT_TIMELIMIT,  "Set time limit (in seconds)",  NULL},
431                 {"failures",    'f', POPT_ARG_INT,  &torture_failures,  0,      "failures",     NULL},
432                 {"parse-dns",   'D', POPT_ARG_STRING,   NULL,   OPT_DNS,        "parse-dns",    NULL},
433                 {"dangerous",   'X', POPT_ARG_NONE,     NULL,   OPT_DANGEROUS,
434                  "run dangerous tests (eg. wiping out password database)", NULL},
435                 {"load-module",  0,  POPT_ARG_STRING, &extra_module,     0, "load tests from DSO file",    "SOFILE"},
436                 {"shell",               0, POPT_ARG_NONE, &shell, true, "Run shell", NULL},
437                 {"target",              'T', POPT_ARG_STRING, &target, 0, "samba3|samba4|other", NULL},
438                 {"async",       'a', POPT_ARG_NONE,     NULL,   OPT_ASYNC,
439                  "run async tests", NULL},
440                 {"num-async",    0, POPT_ARG_INT,  &torture_numasync,  0,
441                  "number of simultaneous async requests", NULL},
442                 {"maximum-runtime", 0, POPT_ARG_INT, &max_runtime, 0, 
443                  "set maximum time for smbtorture to live", "seconds"},
444                 {"extra-user",   0, POPT_ARG_STRING, NULL, OPT_EXTRA_USER,
445                  "extra user credentials", NULL},
446                 {"load-list", 0, POPT_ARG_STRING, &load_list, 0,
447              "load a test id list from a text file", NULL},
448                 POPT_COMMON_SAMBA
449                 POPT_COMMON_CONNECTION
450                 POPT_COMMON_CREDENTIALS
451                 POPT_COMMON_VERSION
452                 { NULL }
453         };
454
455         setlinebuf(stdout);
456
457         /* we are never interested in SIGPIPE */
458         BlockSignals(true, SIGPIPE);
459
460         pc = poptGetContext("smbtorture", argc, (const char **) argv, long_options, 
461                             POPT_CONTEXT_KEEP_FIRST);
462
463         poptSetOtherOptionHelp(pc, "<binding>|<unc> TEST1 TEST2 ...");
464
465         while((opt = poptGetNextOpt(pc)) != -1) {
466                 switch (opt) {
467                 case OPT_LOADFILE:
468                         lp_set_cmdline(cmdline_lp_ctx, "torture:loadfile", poptGetOptArg(pc));
469                         break;
470                 case OPT_UNCLIST:
471                         lp_set_cmdline(cmdline_lp_ctx, "torture:unclist", poptGetOptArg(pc));
472                         break;
473                 case OPT_TIMELIMIT:
474                         lp_set_cmdline(cmdline_lp_ctx, "torture:timelimit", poptGetOptArg(pc));
475                         break;
476                 case OPT_NUMPROGS:
477                         lp_set_cmdline(cmdline_lp_ctx, "torture:nprocs", poptGetOptArg(pc));
478                         break;
479                 case OPT_DNS:
480                         parse_dns(cmdline_lp_ctx, poptGetOptArg(pc));
481                         break;
482                 case OPT_DANGEROUS:
483                         lp_set_cmdline(cmdline_lp_ctx, "torture:dangerous", "Yes");
484                         break;
485                 case OPT_ASYNC:
486                         lp_set_cmdline(cmdline_lp_ctx, "torture:async", "Yes");
487                         break;
488                 case OPT_SMB_PORTS:
489                         lp_set_cmdline(cmdline_lp_ctx, "smb ports", poptGetOptArg(pc));
490                         break;
491                 case OPT_EXTRA_USER:
492                         {
493                                 char *option = talloc_asprintf(NULL, "torture:extra_user%u",
494                                                                ++num_extra_users);
495                                 const char *value = poptGetOptArg(pc);
496                                 lp_set_cmdline(cmdline_lp_ctx, option, value);
497                                 talloc_free(option);
498                         }
499                         break;
500                 default:
501                         if (opt < 0) {
502                                 printf("bad command line option %d\n", opt);
503                                 exit(1);
504                         }
505                 }
506         }
507
508         if (load_list != NULL) {
509                 restricted = file_lines_load(load_list, &num_restricted, 0,
510                                                                          talloc_autofree_context());
511                 if (restricted == NULL) {
512                         printf("Unable to read load list file '%s'\n", load_list);
513                         exit(1);
514                 }
515         }
516
517         if (strcmp(target, "samba3") == 0) {
518                 lp_set_cmdline(cmdline_lp_ctx, "torture:samba3", "true");
519                 lp_set_cmdline(cmdline_lp_ctx, "torture:resume_key_support", "false");
520         } else if (strcmp(target, "samba4") == 0) {
521                 lp_set_cmdline(cmdline_lp_ctx, "torture:samba4", "true");
522         } else if (strcmp(target, "winxp") == 0) {
523                 lp_set_cmdline(cmdline_lp_ctx, "torture:winxp", "true");
524         } else if (strcmp(target, "w2k3") == 0) {
525                 lp_set_cmdline(cmdline_lp_ctx, "torture:w2k3", "true");
526         } else if (strcmp(target, "w2k8") == 0) {
527                 lp_set_cmdline(cmdline_lp_ctx, "torture:w2k8", "true");
528                 lp_set_cmdline(cmdline_lp_ctx,
529                     "torture:invalid_lock_range_support", "false");
530         } else if (strcmp(target, "win7") == 0) {
531                 lp_set_cmdline(cmdline_lp_ctx, "torture:win7", "true");
532                 lp_set_cmdline(cmdline_lp_ctx, "torture:cn_max_buffer_size",
533                     "0x00010000");
534                 lp_set_cmdline(cmdline_lp_ctx, "torture:resume_key_support", "false");
535                 lp_set_cmdline(cmdline_lp_ctx, "torture:rewind_support", "false");
536
537                 /* RAW-SEARCH for fails for inexplicable reasons against win7 */
538                 lp_set_cmdline(cmdline_lp_ctx, "torture:search_ea_support", "false");
539
540                 lp_set_cmdline(cmdline_lp_ctx, "torture:hide_on_access_denied",
541                     "true");
542         } else if (strcmp(target, "onefs") == 0) {
543                 lp_set_cmdline(cmdline_lp_ctx, "torture:onefs", "true");
544                 lp_set_cmdline(cmdline_lp_ctx, "torture:openx_deny_dos_support",
545                     "false");
546                 lp_set_cmdline(cmdline_lp_ctx, "torture:range_not_locked_on_file_close", "false");
547                 lp_set_cmdline(cmdline_lp_ctx, "torture:sacl_support", "false");
548                 lp_set_cmdline(cmdline_lp_ctx, "torture:ea_support", "false");
549                 lp_set_cmdline(cmdline_lp_ctx, "torture:smbexit_pdu_support",
550                     "false");
551                 lp_set_cmdline(cmdline_lp_ctx, "torture:smblock_pdu_support",
552                     "false");
553                 lp_set_cmdline(cmdline_lp_ctx, "torture:2_step_break_to_none",
554                     "true");
555                 lp_set_cmdline(cmdline_lp_ctx, "torture:deny_dos_support", "false");
556                 lp_set_cmdline(cmdline_lp_ctx, "torture:deny_fcb_support", "false");
557                 lp_set_cmdline(cmdline_lp_ctx, "torture:read_support", "false");
558                 lp_set_cmdline(cmdline_lp_ctx, "torture:writeclose_support", "false");
559                 lp_set_cmdline(cmdline_lp_ctx, "torture:resume_key_support", "false");
560                 lp_set_cmdline(cmdline_lp_ctx, "torture:rewind_support", "false");
561                 lp_set_cmdline(cmdline_lp_ctx, "torture:raw_search_search", "false");
562                 lp_set_cmdline(cmdline_lp_ctx, "torture:search_ea_size", "false");
563         }
564
565         if (max_runtime) {
566                 /* this will only work if nobody else uses alarm(),
567                    which means it won't work for some tests, but we
568                    can't use the event context method we use for smbd
569                    as so many tests create their own event
570                    context. This will at least catch most cases. */
571                 signal(SIGALRM, max_runtime_handler);
572                 alarm(max_runtime);
573         }
574
575         if (extra_module != NULL) {
576             init_module_fn fn = load_module(talloc_autofree_context(), poptGetOptArg(pc));
577
578                 if (fn == NULL) 
579                         d_printf("Unable to load module from %s\n", poptGetOptArg(pc));
580                 else {
581                         status = fn();
582                         if (NT_STATUS_IS_ERR(status)) {
583                                 d_printf("Error initializing module %s: %s\n", 
584                                         poptGetOptArg(pc), nt_errstr(status));
585                         }
586                 }
587         } else { 
588                 torture_init();
589         }
590
591         if (list_tests) {
592                 print_test_list();
593                 return 0;
594         }
595
596         if (torture_seed == 0) {
597                 torture_seed = time(NULL);
598         } 
599         printf("Using seed %d\n", torture_seed);
600         srandom(torture_seed);
601
602         argv_new = discard_const_p(char *, poptGetArgs(pc));
603
604         argc_new = argc;
605         for (i=0; i<argc; i++) {
606                 if (argv_new[i] == NULL) {
607                         argc_new = i;
608                         break;
609                 }
610         }
611
612         if (!strcmp(ui_ops_name, "simple")) {
613                 ui_ops = &std_ui_ops;
614         } else if (!strcmp(ui_ops_name, "subunit")) {
615                 ui_ops = &torture_subunit_ui_ops;
616         } else {
617                 printf("Unknown output format '%s'\n", ui_ops_name);
618                 exit(1);
619         }
620
621         results = torture_results_init(talloc_autofree_context(), ui_ops);
622
623         torture = torture_context_init(s4_event_context_init(talloc_autofree_context()),
624                                        results);
625         if (basedir != NULL) {
626                 if (basedir[0] != '/') {
627                         fprintf(stderr, "Please specify an absolute path to --basedir\n");
628                         return 1;
629                 }
630                 torture->outputdir = basedir;
631         } else {
632                 char *pwd = talloc_size(torture, PATH_MAX);
633                 if (!getcwd(pwd, PATH_MAX)) {
634                         fprintf(stderr, "Unable to determine current working directory\n");
635                         return 1;
636                 }
637                 torture->outputdir = pwd;
638         }
639
640         torture->lp_ctx = cmdline_lp_ctx;
641
642         gensec_init(cmdline_lp_ctx);
643
644         if (shell) {
645                 /* In shell mode, just ignore any remaining test names. */
646                 torture_shell(torture);
647         } else {
648
649                 /* At this point, we should just have a target string,
650                  * followed by a series of test names. Unless we are in
651                  * shell mode, in which case we don't need anythig more.
652                  */
653
654                 if (argc_new < 3) {
655                         printf("You must specify a test to run, or 'ALL'\n");
656                         usage(pc);
657                         exit(1);
658                 }
659
660                 /* Take the target name or binding. */
661                 if (!torture_parse_target(cmdline_lp_ctx, argv_new[1])) {
662                         usage(pc);
663                         exit(1);
664                 }
665
666                 for (i=2;i<argc_new;i++) {
667                         if (!torture_run_named_tests(torture, argv_new[i],
668                                     (const char **)restricted)) {
669                                 correct = false;
670                         }
671                 }
672         }
673
674         if (torture->results->returncode && correct) {
675                 return(0);
676         } else {
677                 return(1);
678         }
679 }