Clean up 'help'.
[umurmur.git] / src / main.c
index 36c5f88db63232928ba607e91518c4292a21aacc..1e22885389947ed03be9ea01508c7d36d236f0b4 100644 (file)
@@ -1,5 +1,5 @@
-/* Copyright (C) 2009-2010, Martin Johansson <martin@fatbob.nu>
-   Copyright (C) 2005-2010, Thorvald Natvig <thorvald@natvig.com>
+/* Copyright (C) 2009-2011, Martin Johansson <martin@fatbob.nu>
+   Copyright (C) 2005-2011, Thorvald Natvig <thorvald@natvig.com>
 
    All rights reserved.
 
@@ -29,7 +29,6 @@
    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-
 #include <stdio.h>
 #include <unistd.h>
 #include <sys/types.h>
@@ -59,17 +58,50 @@ char *bindaddr;
 
 void lockfile(const char *pidfile)
 {
-       int lfp;
+       int lfp, flags;
        char str[16];
-       
-       lfp = open(pidfile, O_RDWR|O_CREAT|O_EXCL, 0640);
+
+       /* Don't use O_TRUNC here -- we want to leave the PID file
+        * unmodified if we cannot lock it.
+        */
+       lfp = open(pidfile, O_WRONLY|O_CREAT, 0640);
        
        if (lfp < 0)
                Log_fatal("Cannot open PID-file %s for writing", pidfile);
+
+       /* Try to lock the file. */
+       if (lockf(lfp, F_TLOCK, 0) < 0) {
+               close(lfp);
+
+               if (errno == EACCES || errno == EAGAIN)
+                       Log_fatal("PID file is locked -- uMurmur already running?");
+
+               Log_fatal("Cannot lock PID file: %s", strerror(errno));
+       }
+
+       /* Now that we locked the file, erase its contents. */
+       if (ftruncate(lfp, 0) < 0) {
+               close(lfp);
+               Log_fatal("Cannot truncate PID file: %s", strerror(errno));
+       }
+
        snprintf(str,16,"%d\n", getpid());
        write(lfp, str, strlen(str)); /* record pid to lockfile */
-       close(lfp);
        Log_info("PID-file: %s", pidfile);
+
+       /* If uMurmur ever starts to fork()+exec(), we don't want it to
+        * leak the fd to the forked process though. Set the close-on-exec
+        * flag to prevent leakage.
+        */
+       flags = fcntl(lfp, F_GETFD, 0);
+       flags |= FD_CLOEXEC;
+       fcntl(lfp, F_SETFD, (long) flags);
+
+       /* Don't close(lfp) here!
+        * We want the fd to remain opened so the lock is held until the
+        * process exits.
+        */
+       lfp = -1;
 }
 
 /* Drops privileges (if configured to do so). */
@@ -130,8 +162,8 @@ void signal_handler(int sig)
 {
        switch(sig) {
        case SIGHUP:
-               /* XXX - do stuff? */
-               Log_info("HUP signal");
+               Log_info("HUP signal received.");
+               Log_reset();
                break;
        case SIGTERM:
                Log_info("TERM signal. Shutting down.");
@@ -185,16 +217,16 @@ void setscheduler()
 void printhelp()
 {
        printf("uMurmur version %s. Mumble protocol %d.%d.%d\n", UMURMUR_VERSION, PROTVER_MAJOR, PROTVER_MINOR, PROTVER_PATCH);
-       printf("Usage: umurmurd [-d] [-p <pidfile>] [-c <conf file>] [-h]\n");
-       printf("       -d             - Do not daemonize\n");
-       printf("       -p <pidfile>   - Write PID to this file\n");
-       printf("       -c <conf file> - Specify configuration file\n");
+       printf("Usage: umurmurd [-d] [-r] [-h] [-p <pidfile>] [-c <conf file>] [-a <addr>] [-b <port>]\n");
+       printf("       -d             - Do not daemonize - run in foreground.\n");
 #ifdef _POSIX_PRIORITY_SCHEDULING
        printf("       -r             - Run with realtime priority\n");
 #endif
+       printf("       -h             - Print this help\n");
+       printf("       -p <pidfile>   - Write PID to this file\n");
+       printf("       -c <conf file> - Specify configuration file (default %s)\n", DEFAULT_CONFIG);
        printf("       -a <address>   - Bind to IP address\n");
        printf("       -b <port>      - Bind to port\n");
-       printf("       -h             - Print this help\n");
        exit(0);
 }
 
@@ -244,28 +276,29 @@ int main(int argc, char **argv)
                        break;
                }
        }
-
-       /* Logging to terminal if not daemonizing, otherwise to syslog.
-        * Need to initialize logging before calling Conf_init()
-        */
-       if (!nodaemon)
-               Log_init(false);
-       else
-               Log_init(true);
        
        /* Initialize the config subsystem early;
-        * switch_user() will need to read some config variables.
+        * switch_user() will need to read some config variables as well as logging.
         */
        Conf_init(conffile);
-
+       
+       /* Logging to terminal if not daemonizing, otherwise to syslog or log file.
+        */
        if (!nodaemon) {
                daemonize();
+               Log_init(false);
                if (pidfile != NULL)
                        lockfile(pidfile);
 
                switch_user();
-       }
 
+               /* Reopen log file. If user switch results in access denied, we catch
+                * it early.
+                */
+               Log_reset(); 
+       }
+       else Log_init(true);
+       
        signal(SIGCHLD, SIG_IGN); /* ignore child */
        signal(SIGTSTP, SIG_IGN); /* ignore tty signals */
        signal(SIGTTOU, SIG_IGN);