docs: fix type for client ldap sasl wrapping parameter
[Samba.git] / source4 / torture / smbtorture.c
blobcb0be97cafab56ce82cedc106549813b6ed2a4f9
1 /*
2 Unix SMB/CIFS implementation.
3 SMB torture tester
4 Copyright (C) Andrew Tridgell 1997-2003
5 Copyright (C) Jelmer Vernooij 2006-2008
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.
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.
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/>.
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"
31 #include "torture/smbtorture.h"
32 #include "librpc/rpc/dcerpc.h"
33 #include "auth/gensec/gensec.h"
34 #include "param/param.h"
35 #include "lib/util/samba_modules.h"
37 #if HAVE_READLINE_HISTORY_H
38 #include <readline/history.h>
39 #endif
41 static char *prefix_name(TALLOC_CTX *mem_ctx, const char *prefix, const char *name)
43 if (prefix == NULL)
44 return talloc_strdup(mem_ctx, name);
45 else
46 return talloc_asprintf(mem_ctx, "%s.%s", prefix, name);
49 static void print_test_list(const struct torture_suite *suite, const char *prefix, const char *expr)
51 struct torture_suite *o;
52 struct torture_tcase *t;
53 struct torture_test *p;
55 for (o = suite->children; o; o = o->next) {
56 char *name = prefix_name(NULL, prefix, o->name);
57 print_test_list(o, name, expr);
58 talloc_free(name);
61 for (t = suite->testcases; t; t = t->next) {
62 for (p = t->tests; p; p = p->next) {
63 char *name = talloc_asprintf(NULL, "%s.%s.%s", prefix, t->name, p->name);
64 if (strncmp(name, expr, strlen(expr)) == 0) {
65 printf("%s\n", name);
67 talloc_free(name);
72 static bool run_matching(struct torture_context *torture,
73 const char *prefix,
74 const char *expr,
75 const char **restricted,
76 struct torture_suite *suite,
77 bool *matched)
79 bool ret = true;
80 struct torture_suite *o;
81 struct torture_tcase *t;
82 struct torture_test *p;
84 for (o = suite->children; o; o = o->next) {
85 char *name = NULL;
86 name = prefix_name(torture, prefix, o->name);
87 if (gen_fnmatch(expr, name) == 0) {
88 *matched = true;
89 reload_charcnv(torture->lp_ctx);
90 if (restricted != NULL)
91 ret &= torture_run_suite_restricted(torture, o, restricted);
92 else
93 ret &= torture_run_suite(torture, o);
95 ret &= run_matching(torture, name, expr, restricted, o, matched);
98 for (t = suite->testcases; t; t = t->next) {
99 char *name = talloc_asprintf(torture, "%s.%s", prefix, t->name);
100 if (gen_fnmatch(expr, name) == 0) {
101 *matched = true;
102 reload_charcnv(torture->lp_ctx);
103 ret &= torture_run_tcase_restricted(torture, t, restricted);
105 for (p = t->tests; p; p = p->next) {
106 name = talloc_asprintf(torture, "%s.%s.%s", prefix, t->name, p->name);
107 if (gen_fnmatch(expr, name) == 0) {
108 *matched = true;
109 reload_charcnv(torture->lp_ctx);
110 ret &= torture_run_test_restricted(torture, t, p, restricted);
115 return ret;
118 #define MAX_COLS 80 /* FIXME: Determine this at run-time */
120 /****************************************************************************
121 run a specified test or "ALL"
122 ****************************************************************************/
123 bool torture_run_named_tests(struct torture_context *torture, const char *name,
124 const char **restricted)
126 bool ret = true;
127 bool matched = false;
128 struct torture_suite *o;
130 torture_ui_report_time(torture);
132 if (strequal(name, "ALL")) {
133 if (restricted != NULL) {
134 printf("--load-list and ALL are incompatible\n");
135 return false;
137 for (o = torture_root->children; o; o = o->next) {
138 ret &= torture_run_suite(torture, o);
140 return ret;
143 ret = run_matching(torture, NULL, name, restricted, torture_root, &matched);
145 if (!matched) {
146 printf("Unknown torture operation '%s'\n", name);
147 return false;
150 return ret;
153 bool torture_parse_target(struct loadparm_context *lp_ctx, const char *target)
155 char *host = NULL, *share = NULL;
156 struct dcerpc_binding *binding_struct;
157 NTSTATUS status;
159 /* see if its a RPC transport specifier */
160 if (!smbcli_parse_unc(target, NULL, &host, &share)) {
161 status = dcerpc_parse_binding(talloc_autofree_context(), target, &binding_struct);
162 if (NT_STATUS_IS_ERR(status)) {
163 d_printf("Invalid option: %s is not a valid torture target (share or binding string)\n\n", target);
164 return false;
166 lpcfg_set_cmdline(lp_ctx, "torture:host", binding_struct->host);
167 if (lpcfg_parm_string(lp_ctx, NULL, "torture", "share") == NULL)
168 lpcfg_set_cmdline(lp_ctx, "torture:share", "IPC$");
169 lpcfg_set_cmdline(lp_ctx, "torture:binding", target);
170 } else {
171 lpcfg_set_cmdline(lp_ctx, "torture:host", host);
172 lpcfg_set_cmdline(lp_ctx, "torture:share", share);
173 lpcfg_set_cmdline(lp_ctx, "torture:binding", host);
176 return true;
179 static void parse_dns(struct loadparm_context *lp_ctx, const char *dns)
181 char *userdn, *basedn, *secret;
182 char *p, *d;
184 /* retrievieng the userdn */
185 p = strchr_m(dns, '#');
186 if (!p) {
187 lpcfg_set_cmdline(lp_ctx, "torture:ldap_userdn", "");
188 lpcfg_set_cmdline(lp_ctx, "torture:ldap_basedn", "");
189 lpcfg_set_cmdline(lp_ctx, "torture:ldap_secret", "");
190 return;
192 userdn = strndup(dns, p - dns);
193 lpcfg_set_cmdline(lp_ctx, "torture:ldap_userdn", userdn);
195 /* retrieve the basedn */
196 d = p + 1;
197 p = strchr_m(d, '#');
198 if (!p) {
199 lpcfg_set_cmdline(lp_ctx, "torture:ldap_basedn", "");
200 lpcfg_set_cmdline(lp_ctx, "torture:ldap_secret", "");
201 return;
203 basedn = strndup(d, p - d);
204 lpcfg_set_cmdline(lp_ctx, "torture:ldap_basedn", basedn);
206 /* retrieve the secret */
207 p = p + 1;
208 if (!p) {
209 lpcfg_set_cmdline(lp_ctx, "torture:ldap_secret", "");
210 return;
212 secret = strdup(p);
213 lpcfg_set_cmdline(lp_ctx, "torture:ldap_secret", secret);
215 printf ("%s - %s - %s\n", userdn, basedn, secret);
219 /* Print the full test list, formatted into separate labelled test
220 * groups.
222 static void print_structured_testsuite_list(void)
224 struct torture_suite *o;
225 struct torture_suite *s;
226 struct torture_tcase *t;
227 int i;
229 if (torture_root == NULL) {
230 printf("NO TESTS LOADED\n");
231 return;
234 for (o = torture_root->children; o; o = o->next) {
235 printf("\n%s (%s):\n ", o->description, o->name);
237 i = 0;
238 for (s = o->children; s; s = s->next) {
239 if (i + strlen(o->name) + strlen(s->name) >= (MAX_COLS - 3)) {
240 printf("\n ");
241 i = 0;
243 i+=printf("%s.%s ", o->name, s->name);
246 for (t = o->testcases; t; t = t->next) {
247 if (i + strlen(o->name) + strlen(t->name) >= (MAX_COLS - 3)) {
248 printf("\n ");
249 i = 0;
251 i+=printf("%s.%s ", o->name, t->name);
254 if (i) printf("\n");
257 printf("\nThe default test is ALL.\n");
260 static void print_testsuite_list(void)
262 struct torture_suite *o;
263 struct torture_suite *s;
264 struct torture_tcase *t;
266 if (torture_root == NULL)
267 return;
269 for (o = torture_root->children; o; o = o->next) {
270 for (s = o->children; s; s = s->next) {
271 printf("%s.%s\n", o->name, s->name);
274 for (t = o->testcases; t; t = t->next) {
275 printf("%s.%s\n", o->name, t->name);
280 void torture_print_testsuites(bool structured)
282 if (structured) {
283 print_structured_testsuite_list();
284 } else {
285 print_testsuite_list();
289 static void usage(poptContext pc)
291 poptPrintUsage(pc, stdout, 0);
292 printf("\n");
294 printf("The binding format is:\n\n");
296 printf(" TRANSPORT:host[flags]\n\n");
298 printf(" where TRANSPORT is either ncacn_np for SMB, ncacn_ip_tcp for RPC/TCP\n");
299 printf(" or ncalrpc for local connections.\n\n");
301 printf(" 'host' is an IP or hostname or netbios name. If the binding string\n");
302 printf(" identifies the server side of an endpoint, 'host' may be an empty\n");
303 printf(" string.\n\n");
305 printf(" 'flags' can include a SMB pipe name if using the ncacn_np transport or\n");
306 printf(" a TCP port number if using the ncacn_ip_tcp transport, otherwise they\n");
307 printf(" will be auto-determined.\n\n");
309 printf(" other recognised flags are:\n\n");
311 printf(" sign : enable ntlmssp signing\n");
312 printf(" seal : enable ntlmssp sealing\n");
313 printf(" connect : enable rpc connect level auth (auth, but no sign or seal)\n");
314 printf(" validate: enable the NDR validator\n");
315 printf(" print: enable debugging of the packets\n");
316 printf(" bigendian: use bigendian RPC\n");
317 printf(" padcheck: check reply data for non-zero pad bytes\n\n");
319 printf(" For example, these all connect to the samr pipe:\n\n");
321 printf(" ncacn_np:myserver\n");
322 printf(" ncacn_np:myserver[samr]\n");
323 printf(" ncacn_np:myserver[\\pipe\\samr]\n");
324 printf(" ncacn_np:myserver[/pipe/samr]\n");
325 printf(" ncacn_np:myserver[samr,sign,print]\n");
326 printf(" ncacn_np:myserver[\\pipe\\samr,sign,seal,bigendian]\n");
327 printf(" ncacn_np:myserver[/pipe/samr,seal,validate]\n");
328 printf(" ncacn_np:\n");
329 printf(" ncacn_np:[/pipe/samr]\n\n");
331 printf(" ncacn_ip_tcp:myserver\n");
332 printf(" ncacn_ip_tcp:myserver[1024]\n");
333 printf(" ncacn_ip_tcp:myserver[1024,sign,seal]\n\n");
335 printf(" ncalrpc:\n\n");
337 printf("The UNC format is:\n\n");
339 printf(" //server/share\n\n");
341 printf("Tests are:");
343 print_structured_testsuite_list();
347 _NORETURN_ static void max_runtime_handler(int sig)
349 DEBUG(0,("maximum runtime exceeded for smbtorture - terminating\n"));
350 exit(1);
353 /****************************************************************************
354 main program
355 ****************************************************************************/
356 int main(int argc,char *argv[])
358 int opt, i;
359 bool correct = true;
360 int max_runtime=0;
361 int argc_new;
362 struct torture_context *torture;
363 struct torture_results *results;
364 const struct torture_ui_ops *ui_ops;
365 char **argv_new;
366 poptContext pc;
367 static const char *target = "other";
368 NTSTATUS status;
369 int shell = false;
370 static const char *ui_ops_name = "subunit";
371 const char *basedir = NULL;
372 char *outputdir;
373 const char *extra_module = NULL;
374 static int list_tests = 0, list_testsuites = 0;
375 int num_extra_users = 0;
376 char **restricted = NULL;
377 int num_restricted = -1;
378 const char *load_list = NULL;
379 enum {OPT_LOADFILE=1000,OPT_UNCLIST,OPT_TIMELIMIT,OPT_DNS, OPT_LIST,
380 OPT_DANGEROUS,OPT_SMB_PORTS,OPT_ASYNC,OPT_NUMPROGS,
381 OPT_EXTRA_USER,};
383 struct poptOption long_options[] = {
384 POPT_AUTOHELP
385 {"format", 0, POPT_ARG_STRING, &ui_ops_name, 0, "Output format (one of: simple, subunit)", NULL },
386 {"smb-ports", 'p', POPT_ARG_STRING, NULL, OPT_SMB_PORTS, "SMB ports", NULL},
387 {"basedir", 0, POPT_ARG_STRING, &basedir, 0, "base directory", "BASEDIR" },
388 {"seed", 0, POPT_ARG_INT, &torture_seed, 0, "Seed to use for randomizer", NULL},
389 {"num-progs", 0, POPT_ARG_INT, NULL, OPT_NUMPROGS, "num progs", NULL},
390 {"num-ops", 0, POPT_ARG_INT, &torture_numops, 0, "num ops", NULL},
391 {"entries", 0, POPT_ARG_INT, &torture_entries, 0, "entries", NULL},
392 {"loadfile", 0, POPT_ARG_STRING, NULL, OPT_LOADFILE, "NBench load file to use", NULL},
393 {"list-suites", 0, POPT_ARG_NONE, &list_testsuites, 0, "List available testsuites and exit", NULL },
394 {"list", 0, POPT_ARG_NONE, &list_tests, 0, "List available tests in specified suites and exit", NULL },
395 {"unclist", 0, POPT_ARG_STRING, NULL, OPT_UNCLIST, "unclist", NULL},
396 {"timelimit", 't', POPT_ARG_INT, NULL, OPT_TIMELIMIT, "Set time limit (in seconds)", NULL},
397 {"failures", 'f', POPT_ARG_INT, &torture_failures, 0, "failures", NULL},
398 {"parse-dns", 'D', POPT_ARG_STRING, NULL, OPT_DNS, "parse-dns", NULL},
399 {"dangerous", 'X', POPT_ARG_NONE, NULL, OPT_DANGEROUS,
400 "run dangerous tests (eg. wiping out password database)", NULL},
401 {"load-module", 0, POPT_ARG_STRING, &extra_module, 0, "load tests from DSO file", "SOFILE"},
402 {"shell", 0, POPT_ARG_NONE, &shell, true, "Run shell", NULL},
403 {"target", 'T', POPT_ARG_STRING, &target, 0, "samba3|samba4|other", NULL},
404 {"async", 'a', POPT_ARG_NONE, NULL, OPT_ASYNC,
405 "run async tests", NULL},
406 {"num-async", 0, POPT_ARG_INT, &torture_numasync, 0,
407 "number of simultaneous async requests", NULL},
408 {"maximum-runtime", 0, POPT_ARG_INT, &max_runtime, 0,
409 "set maximum time for smbtorture to live", "seconds"},
410 {"extra-user", 0, POPT_ARG_STRING, NULL, OPT_EXTRA_USER,
411 "extra user credentials", NULL},
412 {"load-list", 0, POPT_ARG_STRING, &load_list, 0,
413 "load a test id list from a text file", NULL},
414 POPT_COMMON_SAMBA
415 POPT_COMMON_CONNECTION
416 POPT_COMMON_CREDENTIALS
417 POPT_COMMON_VERSION
418 { NULL }
421 setlinebuf(stdout);
423 printf("smbtorture %s\n", samba_version_string());
425 /* we are never interested in SIGPIPE */
426 BlockSignals(true, SIGPIPE);
428 pc = poptGetContext("smbtorture", argc, (const char **) argv, long_options,
429 POPT_CONTEXT_KEEP_FIRST);
431 poptSetOtherOptionHelp(pc, "<binding>|<unc> TEST1 TEST2 ...");
433 while((opt = poptGetNextOpt(pc)) != -1) {
434 switch (opt) {
435 case OPT_LOADFILE:
436 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:loadfile", poptGetOptArg(pc));
437 break;
438 case OPT_UNCLIST:
439 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:unclist", poptGetOptArg(pc));
440 break;
441 case OPT_TIMELIMIT:
442 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:timelimit", poptGetOptArg(pc));
443 break;
444 case OPT_NUMPROGS:
445 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:nprocs", poptGetOptArg(pc));
446 break;
447 case OPT_DNS:
448 parse_dns(cmdline_lp_ctx, poptGetOptArg(pc));
449 break;
450 case OPT_DANGEROUS:
451 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:dangerous", "Yes");
452 break;
453 case OPT_ASYNC:
454 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:async", "Yes");
455 break;
456 case OPT_SMB_PORTS:
457 lpcfg_set_cmdline(cmdline_lp_ctx, "smb ports", poptGetOptArg(pc));
458 break;
459 case OPT_EXTRA_USER:
461 char *option = talloc_asprintf(NULL, "torture:extra_user%u",
462 ++num_extra_users);
463 const char *value = poptGetOptArg(pc);
464 lpcfg_set_cmdline(cmdline_lp_ctx, option, value);
465 talloc_free(option);
467 break;
468 default:
469 if (opt < 0) {
470 printf("bad command line option %d\n", opt);
471 exit(1);
476 if (load_list != NULL) {
477 restricted = file_lines_load(load_list, &num_restricted, 0,
478 talloc_autofree_context());
479 if (restricted == NULL) {
480 printf("Unable to read load list file '%s'\n", load_list);
481 exit(1);
485 if (strcmp(target, "samba3") == 0) {
486 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:samba3", "true");
487 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:resume_key_support", "false");
488 } else if (strcmp(target, "samba4") == 0) {
489 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:samba4", "true");
490 } else if (strcmp(target, "samba4-ntvfs") == 0) {
491 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:samba4", "true");
492 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:samba4-ntvfs", "true");
493 } else if (strcmp(target, "winxp") == 0) {
494 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:winxp", "true");
495 } else if (strcmp(target, "w2k3") == 0) {
496 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:w2k3", "true");
497 } else if (strcmp(target, "w2k8") == 0) {
498 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:w2k8", "true");
499 lpcfg_set_cmdline(cmdline_lp_ctx,
500 "torture:invalid_lock_range_support", "false");
501 } else if (strcmp(target, "w2k12") == 0) {
502 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:w2k12", "true");
503 } else if (strcmp(target, "win7") == 0) {
504 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:win7", "true");
505 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:cn_max_buffer_size",
506 "0x00010000");
507 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:resume_key_support", "false");
508 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:rewind_support", "false");
510 /* RAW-SEARCH for fails for inexplicable reasons against win7 */
511 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:search_ea_support", "false");
513 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:hide_on_access_denied",
514 "true");
515 } else if (strcmp(target, "onefs") == 0) {
516 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:onefs", "true");
517 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:openx_deny_dos_support",
518 "false");
519 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:range_not_locked_on_file_close", "false");
520 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:sacl_support", "false");
521 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:ea_support", "false");
522 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:smbexit_pdu_support",
523 "false");
524 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:smblock_pdu_support",
525 "false");
526 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:2_step_break_to_none",
527 "true");
528 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:deny_dos_support", "false");
529 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:deny_fcb_support", "false");
530 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:read_support", "false");
531 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:writeclose_support", "false");
532 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:resume_key_support", "false");
533 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:rewind_support", "false");
534 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:raw_search_search", "false");
535 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:search_ea_size", "false");
538 if (max_runtime) {
539 /* this will only work if nobody else uses alarm(),
540 which means it won't work for some tests, but we
541 can't use the event context method we use for smbd
542 as so many tests create their own event
543 context. This will at least catch most cases. */
544 signal(SIGALRM, max_runtime_handler);
545 alarm(max_runtime);
548 if (extra_module != NULL) {
549 init_module_fn fn = load_module(poptGetOptArg(pc), false, NULL);
551 if (fn == NULL)
552 d_printf("Unable to load module from %s\n", poptGetOptArg(pc));
553 else {
554 status = fn();
555 if (NT_STATUS_IS_ERR(status)) {
556 d_printf("Error initializing module %s: %s\n",
557 poptGetOptArg(pc), nt_errstr(status));
560 } else {
561 torture_init();
564 if (list_testsuites) {
565 print_testsuite_list();
566 return 0;
569 argv_new = discard_const_p(char *, poptGetArgs(pc));
571 argc_new = argc;
572 for (i=0; i<argc; i++) {
573 if (argv_new[i] == NULL) {
574 argc_new = i;
575 break;
579 if (list_tests) {
580 if (argc_new == 1) {
581 print_test_list(torture_root, NULL, "");
582 } else {
583 for (i=1;i<argc_new;i++) {
584 print_test_list(torture_root, NULL, argv_new[i]);
587 return 0;
590 if (torture_seed == 0) {
591 torture_seed = time(NULL);
593 printf("Using seed %d\n", torture_seed);
594 srandom(torture_seed);
596 if (!strcmp(ui_ops_name, "simple")) {
597 ui_ops = &torture_simple_ui_ops;
598 } else if (!strcmp(ui_ops_name, "subunit")) {
599 ui_ops = &torture_subunit_ui_ops;
600 } else {
601 printf("Unknown output format '%s'\n", ui_ops_name);
602 exit(1);
605 results = torture_results_init(talloc_autofree_context(), ui_ops);
607 torture = torture_context_init(s4_event_context_init(talloc_autofree_context()),
608 results);
609 if (basedir != NULL) {
610 if (basedir[0] != '/') {
611 fprintf(stderr, "Please specify an absolute path to --basedir\n");
612 return 1;
614 outputdir = talloc_asprintf(torture, "%s/smbtortureXXXXXX", basedir);
615 } else {
616 char *pwd = talloc_size(torture, PATH_MAX);
617 if (!getcwd(pwd, PATH_MAX)) {
618 fprintf(stderr, "Unable to determine current working directory\n");
619 return 1;
621 outputdir = talloc_asprintf(torture, "%s/smbtortureXXXXXX", pwd);
623 if (!outputdir) {
624 fprintf(stderr, "Could not allocate per-run output dir\n");
625 return 1;
627 torture->outputdir = mkdtemp(outputdir);
628 if (!torture->outputdir) {
629 perror("Failed to make temp output dir");
632 torture->lp_ctx = cmdline_lp_ctx;
634 gensec_init();
636 if (shell) {
637 /* In shell mode, just ignore any remaining test names. */
638 torture_shell(torture);
639 } else {
641 /* At this point, we should just have a target string,
642 * followed by a series of test names. Unless we are in
643 * shell mode, in which case we don't need anythig more.
646 if (argc_new < 3) {
647 printf("You must specify a test to run, or 'ALL'\n");
648 usage(pc);
649 torture->results->returncode = 1;
650 } else if (!torture_parse_target(cmdline_lp_ctx, argv_new[1])) {
651 /* Take the target name or binding. */
652 usage(pc);
653 torture->results->returncode = 1;
654 } else {
655 for (i=2;i<argc_new;i++) {
656 if (!torture_run_named_tests(torture, argv_new[i],
657 (const char **)restricted)) {
658 correct = false;
664 /* Now delete the temp dir we created */
665 torture_deltree_outputdir(torture);
667 if (torture->results->returncode && correct) {
668 return(0);
669 } else {
670 return(1);