#include "utils.h"
#include "tincctl.h"
#include "top.h"
+#include "version.h"
#ifndef MSG_NOSIGNAL
#define MSG_NOSIGNAL 0
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},
static void version(void) {
printf("%s version %s (built %s %s, protocol %d.%d)\n", PACKAGE,
- VERSION, __DATE__, __TIME__, PROT_MAJOR, PROT_MINOR);
+ VERSION, BUILD_DATE, BUILD_TIME, PROT_MAJOR, PROT_MINOR);
printf("Copyright (C) 1998-2012 Ivo Timmermans, Guus Sliepen and others.\n"
"See the AUTHORS file for a complete list.\n\n"
"tinc comes with ABSOLUTELY NO WARRANTY. This is free software,\n"
} 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) {
break;
char node[4096];
+ char id[4096];
char from[4096];
char to[4096];
char subnet[4096];
switch(req) {
case REQ_DUMP_NODES: {
- int n = sscanf(line, "%*d %*d %s %s port %s %d %d %d %d %x %x %s %s %d %hd %hd %hd %ld", node, host, port, &cipher, &digest, &maclength, &compression, &options, &status_int, nexthop, via, &distance, &pmtu, &minmtu, &maxmtu, &last_state_change);
- if(n != 16) {
+ int n = sscanf(line, "%*d %*d %s %s %s port %s %d %d %d %d %x %x %s %s %d %hd %hd %hd %ld", node, id, host, port, &cipher, &digest, &maclength, &compression, &options, &status_int, nexthop, via, &distance, &pmtu, &minmtu, &maxmtu, &last_state_change);
+ if(n != 17) {
fprintf(stderr, "Unable to parse node dump from tincd: %s\n", line);
return 1;
}
} else {
if(only_reachable && !status.reachable)
continue;
- printf("%s at %s port %s cipher %d digest %d maclength %d compression %d options %x status %04x nexthop %s via %s distance %d pmtu %hd (min %hd max %hd)\n",
- node, host, port, cipher, digest, maclength, compression, options, status_int, nexthop, via, distance, pmtu, minmtu, maxmtu);
+ printf("%s id %s at %s port %s cipher %d digest %d maclength %d compression %d options %x status %04x nexthop %s via %s distance %d pmtu %hd (min %hd max %hd)\n",
+ node, id, host, port, cipher, digest, maclength, compression, options, status_int, nexthop, via, distance, pmtu, minmtu, maxmtu);
}
} break;
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);