Don't call exit_control() if we didn't do init_control().
[tinc] / src / tincd.c
index 2162364..9d2b03b 100644 (file)
@@ -1,9 +1,11 @@
 /*
     tincd.c -- the main file for tincd
     Copyright (C) 1998-2005 Ivo Timmermans
-                  2000-2010 Guus Sliepen <guus@tinc-vpn.org>
+                  2000-2011 Guus Sliepen <guus@tinc-vpn.org>
                   2008      Max Rijevski <maksuf@gmail.com>
                   2009      Michael Tokarev <mjt@tls.msk.ru>
+                  2010      Julien Muchembled <jm@jmuchemb.eu>
+                  2010      Timothy Redaelli <timothy@redaelli.eu>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
 char *program_name = NULL;
 
 /* If nonzero, display usage information and exit. */
-bool show_help = false;
+static bool show_help = false;
 
 /* If nonzero, print the version on standard output and exit.  */
-bool show_version = false;
+static bool show_version = false;
 
 /* If nonzero, use null ciphers and skip all key exchanges. */
 bool bypass_security = false;
 
 /* If nonzero, disable swapping for this process. */
-bool do_mlock = false;
+static bool do_mlock = false;
 
 /* If nonzero, chroot to netdir after startup. */
 static bool do_chroot = false;
@@ -90,7 +92,7 @@ char *logfilename = NULL;                     /* log file location */
 char *controlcookiename = NULL;
 char **g_argv;                                 /* a copy of the cmdline arguments */
 
-static int status;
+static int status = 1;
 
 static struct option const long_options[] = {
        {"config", required_argument, NULL, 'c'},
@@ -111,6 +113,7 @@ static struct option const long_options[] = {
 #ifdef HAVE_MINGW
 static struct WSAData wsa_state;
 CRITICAL_SECTION mutex;
+int main2(int argc, char **argv);
 #endif
 
 static void usage(bool status) {
@@ -127,6 +130,7 @@ static void usage(bool status) {
                                "      --logfile[=FILENAME]      Write log entries to a logfile.\n"
                                "      --controlcookie=FILENAME  Write control socket cookie to FILENAME.\n"
                                "      --bypass-security         Disables meta protocol security, for debugging.\n"
+                               "  -o [HOST.]KEY=VALUE           Set global/host configuration value.\n"
                                "  -R, --chroot                  chroot to NET dir at startup.\n"
                                "  -U, --user=USER               setuid to given USER at startup.\n"                            "      --help                    Display this help and exit.\n"
                                "      --version                 Output version information and exit.\n\n");
@@ -135,10 +139,14 @@ static void usage(bool status) {
 }
 
 static bool parse_options(int argc, char **argv) {
+       config_t *cfg;
        int r;
        int option_index = 0;
+       int lineno = 0;
 
-       while((r = getopt_long(argc, argv, "c:DLd::n:RU:", long_options, &option_index)) != EOF) {
+       cmdline_conf = list_alloc((list_action_t)free_config);
+
+       while((r = getopt_long(argc, argv, "c:DLd::n:o:RU:", long_options, &option_index)) != EOF) {
                switch (r) {
                        case 0:                         /* long option */
                                break;
@@ -168,7 +176,16 @@ static bool parse_options(int argc, char **argv) {
                                break;
 
                        case 'n':                               /* net name given */
-                               netname = xstrdup(optarg);
+                               /* netname "." is special: a "top-level name" */
+                               netname = strcmp(optarg, ".") != 0 ?
+                                               xstrdup(optarg) : NULL;
+                               break;
+
+                       case 'o':                               /* option */
+                               cfg = parse_config_line(optarg, NULL, ++lineno);
+                               if (!cfg)
+                                       return false;
+                               list_insert_tail(cmdline_conf, cfg);
                                break;
 
                        case 'R':                               /* chroot to NETNAME dir */
@@ -265,7 +282,7 @@ static void make_names(void) {
        }
 }
 
-static void free_names() {
+static void free_names(void) {
        if (identname) free(identname);
        if (netname) free(netname);
        if (controlcookiename) free(controlcookiename);
@@ -273,7 +290,7 @@ static void free_names() {
        if (confbase) free(confbase);
 }
 
-static bool drop_privs() {
+static bool drop_privs(void) {
 #ifdef HAVE_MINGW
        if (switchuser) {
                logger(LOG_ERR, "%s not supported on this platform", "-U");
@@ -322,12 +339,12 @@ static bool drop_privs() {
 }
 
 #ifdef HAVE_MINGW
-# define setpriority(level) SetPriorityClass(GetCurrentProcess(), level)
+# define setpriority(level) !SetPriorityClass(GetCurrentProcess(), (level))
 #else
 # define NORMAL_PRIORITY_CLASS 0
 # define BELOW_NORMAL_PRIORITY_CLASS 10
 # define HIGH_PRIORITY_CLASS -10
-# define setpriority(level) nice(level)
+# define setpriority(level) (setpriority(PRIO_PROCESS, 0, (level)))
 #endif
 
 int main(int argc, char **argv) {
@@ -341,7 +358,7 @@ int main(int argc, char **argv) {
        if(show_version) {
                printf("%s version %s (built %s %s, protocol %d)\n", PACKAGE,
                           VERSION, __DATE__, __TIME__, PROT_CURRENT);
-               printf("Copyright (C) 1998-2010 Ivo Timmermans, Guus Sliepen and others.\n"
+               printf("Copyright (C) 1998-2011 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"
                                "and you are welcome to redistribute it under certain conditions;\n"
@@ -417,10 +434,10 @@ int main2(int argc, char **argv) {
        /* Setup sockets and open device. */
 
        if(!setup_network())
-               goto end;
+               goto end_nonet;
 
        if(!init_control())
-               return 1;
+               goto end_nonet;
 
        /* Initiate all outgoing connections. */
 
@@ -428,16 +445,28 @@ int main2(int argc, char **argv) {
 
        /* Change process priority */
 
-        char *priority = 0;
+        char *priority = NULL;
 
         if(get_config_string(lookup_config(config_tree, "ProcessPriority"), &priority)) {
-                if(!strcasecmp(priority, "Normal"))
-                        setpriority(NORMAL_PRIORITY_CLASS);
-                else if(!strcasecmp(priority, "Low"))
-                        setpriority(BELOW_NORMAL_PRIORITY_CLASS);
-                else if(!strcasecmp(priority, "High"))
-                        setpriority(HIGH_PRIORITY_CLASS);
-                else {
+                if(!strcasecmp(priority, "Normal")) {
+                        if (setpriority(NORMAL_PRIORITY_CLASS) != 0) {
+                                logger(LOG_ERR, "System call `%s' failed: %s",
+                                       "setpriority", strerror(errno));
+                                goto end;
+                        }
+                } else if(!strcasecmp(priority, "Low")) {
+                        if (setpriority(BELOW_NORMAL_PRIORITY_CLASS) != 0) {
+                                       logger(LOG_ERR, "System call `%s' failed: %s",
+                                       "setpriority", strerror(errno));
+                                goto end;
+                        }
+                } else if(!strcasecmp(priority, "High")) {
+                        if (setpriority(HIGH_PRIORITY_CLASS) != 0) {
+                                logger(LOG_ERR, "System call `%s' failed: %s",
+                                       "setpriority", strerror(errno));
+                                goto end;
+                        }
+                } else {
                         logger(LOG_ERR, "Invalid priority `%s`!", priority);
                         goto end;
                 }
@@ -459,10 +488,11 @@ int main2(int argc, char **argv) {
        close_network_connections();
 
 end:
-       logger(LOG_NOTICE, "Terminating");
-
        exit_control();
 
+end_nonet:
+       logger(LOG_NOTICE, "Terminating");
+
        crypto_exit();
 
        exit_configuration(&config_tree);