static char *prompt;
static struct option const long_options[] = {
+ {"batch", no_argument, NULL, 'b'},
{"config", required_argument, NULL, 'c'},
{"net", required_argument, NULL, 'n'},
{"help", no_argument, NULL, 1},
} else {
printf("Usage: %s [options] command\n\n", program_name);
printf("Valid options are:\n"
+ " -b, --batch Don't ask for anything (non-interactive mode).\n"
" -c, --config=DIR Read configuration options from DIR.\n"
" -n, --net=NETNAME Connect to net NETNAME.\n"
" --pidfile=FILENAME Read control cookie from FILENAME.\n"
case 0: /* long option */
break;
+ case 'b':
+ tty = false;
+ break;
+
case 'c': /* config file */
confbase = xstrdup(optarg);
confbasegiven = true;
#ifdef SO_NOSIGPIPE
static const int one = 1;
- setsockopt(c, SOL_SOCKET, SO_NOSIGPIPE, (void *)&one, sizeof one);
+ setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&one, sizeof one);
#endif
char data[4096];
int nargc = 0;
char **nargv = xzalloc((optind + argc) * sizeof *nargv);
- nargv[nargc++] = c;
+ char *arg0 = c;
+#ifdef HAVE_MINGW
+ /*
+ Windows has no real concept of an "argv array". A command line is just one string.
+ The CRT of the new process will decode the command line string to generate argv before calling main(), and (by convention)
+ it uses quotes to handle spaces in arguments.
+ Therefore we need to quote all arguments that might contain spaces. No, execvp() won't do that for us (see MSDN).
+ If we don't do that, then execvp() will run fine but any spaces in the filename contained in arg0 will bleed
+ into the next arguments when the spawned process' CRT parses its command line, resulting in chaos.
+ */
+ xasprintf(&arg0, "\"%s\"", arg0);
+#endif
+ nargv[nargc++] = arg0;
for(int i = 1; i < optind; i++)
nargv[nargc++] = orig_argv[i];
for(int i = 1; i < argc; i++)
nargv[nargc++] = argv[i];
#ifdef HAVE_MINGW
- execvp(c, nargv);
- fprintf(stderr, "Error starting %s: %s\n", c, strerror(errno));
- return 1;
+ int status = spawnvp(_P_WAIT, c, nargv);
+ if (status == -1) {
+ fprintf(stderr, "Error starting %s: %s\n", c, strerror(errno));
+ return 1;
+ }
+ return status;
#else
pid_t pid = fork();
if(pid == -1) {
continue;
if(*value) {
fclose(f);
- return strdup(value);
+ return replace_name(value);
}
}
}
if(action < -1) {
- if(!found)
+ if(found) {
+ return 0;
+ } else {
fprintf(stderr, "No matching configuration variables found.\n");
- return 1;
+ return 1;
+ }
}
// Make sure we wrote everything...
return 0;
}
-bool check_id(const char *name) {
- if(!name || !*name)
- return false;
-
- for(int i = 0; i < strlen(name); i++) {
- if(!isalnum(name[i]) && name[i] != '_')
- return false;
- }
-
- return true;
-}
-
static bool try_bind(int port) {
struct addrinfo *ai = NULL;
struct addrinfo hint = {
program_name = argv[0];
orig_argv = argv;
orig_argc = argc;
+ tty = isatty(0) && isatty(1);
if(!parse_options(argc, argv))
return 1;
srand(time(NULL));
crypto_init();
- tty = isatty(0) && isatty(1);
-
if(optind >= argc)
return cmd_shell(argc, argv);