Fix wrong identifier in SO_NOSIGPIPE call.
[tinc] / src / tincctl.c
index 18fc05a..b15676c 100644 (file)
@@ -38,6 +38,7 @@
 #include "utils.h"
 #include "tincctl.h"
 #include "top.h"
+#include "version.h"
 
 #ifndef MSG_NOSIGNAL
 #define MSG_NOSIGNAL 0
@@ -74,6 +75,7 @@ char *scriptextension = "";
 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},
@@ -85,7 +87,7 @@ static struct option const long_options[] = {
 
 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"
@@ -99,6 +101,7 @@ static void usage(bool status) {
        } 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"
@@ -157,6 +160,10 @@ static bool parse_options(int argc, char **argv) {
                        case 0:   /* long option */
                                break;
 
+                       case 'b':
+                               tty = false;
+                               break;
+
                        case 'c': /* config file */
                                confbase = xstrdup(optarg);
                                confbasegiven = true;
@@ -756,7 +763,7 @@ bool connect_tincd(bool verbose) {
 
 #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];
@@ -809,16 +816,31 @@ static int cmd_start(int argc, char *argv[]) {
        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) {
@@ -1283,7 +1305,7 @@ char *get_my_name(bool verbose) {
                        continue;
                if(*value) {
                        fclose(f);
-                       return strdup(value);
+                       return replace_name(value);
                }
        }
 
@@ -1613,9 +1635,12 @@ static int cmd_config(int argc, char *argv[]) {
        }
 
        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...
@@ -1650,18 +1675,6 @@ static int cmd_config(int argc, char *argv[]) {
        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 = {
@@ -2423,6 +2436,7 @@ int main(int argc, char *argv[]) {
        program_name = argv[0];
        orig_argv = argv;
        orig_argc = argc;
+       tty = isatty(0) && isatty(1);
 
        if(!parse_options(argc, argv))
                return 1;
@@ -2453,8 +2467,6 @@ int main(int argc, char *argv[]) {
        srand(time(NULL));
        crypto_init();
 
-       tty = isatty(0) && isatty(1);
-
        if(optind >= argc)
                return cmd_shell(argc, argv);