Revert "Use git description as the tinc version."
[tinc] / src / tincctl.c
index 7a3195e..799da0a 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
@@ -85,7 +86,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"
@@ -485,7 +486,7 @@ bool recvline(int fd, char *line, size_t len) {
 
        while(!(newline = memchr(buffer, '\n', blen))) {
                int result = recv(fd, buffer + blen, sizeof buffer - blen, 0);
-               if(result == -1 && errno == EINTR)
+               if(result == -1 && sockerrno == EINTR)
                        continue;
                else if(result <= 0)
                        return false;
@@ -511,7 +512,7 @@ bool recvdata(int fd, char *data, size_t len) {
 
        while(blen < len) {
                int result = recv(fd, buffer + blen, sizeof buffer - blen, 0);
-               if(result == -1 && errno == EINTR)
+               if(result == -1 && sockerrno == EINTR)
                        continue;
                else if(result <= 0)
                        return false;
@@ -543,7 +544,7 @@ bool sendline(int fd, char *format, ...) {
 
        while(blen) {
                int result = send(fd, p, blen, MSG_NOSIGNAL);
-               if(result == -1 && errno == EINTR)
+               if(result == -1 && sockerrno == EINTR)
                        continue;
                else if(result <= 0)
                        return false;
@@ -723,7 +724,7 @@ bool connect_tincd(bool verbose) {
 
        if(getaddrinfo(host, port, &hints, &res) || !res) {
                if(verbose)
-                       fprintf(stderr, "Cannot resolve %s port %s: %s", host, port, strerror(errno));
+                       fprintf(stderr, "Cannot resolve %s port %s: %s", host, port, sockstrerror(sockerrno));
                return false;
        }
 
@@ -809,16 +810,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) {
@@ -985,6 +1001,8 @@ static int cmd_dump(int argc, char *argv[]) {
                char subnet[4096];
                char host[4096];
                char port[4096];
+               char local_host[4096];
+               char local_port[4096];
                char via[4096];
                char nexthop[4096];
                int cipher, digest, maclength, compression, distance, socket, weight;
@@ -1025,8 +1043,8 @@ static int cmd_dump(int argc, char *argv[]) {
                        } break;
 
                        case REQ_DUMP_EDGES: {
-                               int n = sscanf(line, "%*d %*d %s %s %s port %s %x %d", from, to, host, port, &options, &weight);
-                               if(n != 6) {
+                               int n = sscanf(line, "%*d %*d %s %s %s port %s %s port %s %x %d", from, to, host, port, local_host, local_port, &options, &weight);
+                               if(n != 8) {
                                        fprintf(stderr, "Unable to parse edge dump from tincd.\n");
                                        return 1;
                                }
@@ -1038,7 +1056,7 @@ static int cmd_dump(int argc, char *argv[]) {
                                        else if(do_graph == 2)
                                                printf(" %s -> %s [w = %f, weight = %f];\n", node1, node2, w, w);
                                } else {
-                                       printf("%s to %s at %s port %s options %x weight %d\n", from, to, host, port, options, weight);
+                                       printf("%s to %s at %s port %s local %s port %s options %x weight %d\n", from, to, host, port, local_host, local_port, options, weight);
                                }
                        } break;
 
@@ -1613,7 +1631,7 @@ static int cmd_config(int argc, char *argv[]) {
        if(action < -1) {
                if(!found)
                        fprintf(stderr, "No matching configuration variables found.\n");
-               return 0;
+               return 1;
        }
 
        // Make sure we wrote everything...
@@ -1626,7 +1644,7 @@ static int cmd_config(int argc, char *argv[]) {
        if(action < 0 && !removed) {
                remove(tmpfile);
                fprintf(stderr, "No configuration variables deleted.\n");
-               return *value != 0;
+               return 1;
        }
 
        // Replace the configuration file with the new one