]> ruderich.org/simon Gitweb - wall-notify/wall-notify.git/blobdiff - src/wall-notify.c
remove superfluous braces in comment
[wall-notify/wall-notify.git] / src / wall-notify.c
index 9056af343a0be36ccd8ff9b7990bdc2055508816..e0d556db1386387e567bcb7967cb0fe9f1e213fb 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Receive wall messages and pass them to a notification program via stdin.
  *
- * Copyright (C) 2014  Simon Ruderich
+ * Copyright (C) 2014-2015  Simon Ruderich
  *
  * 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
 #endif
 
 
+static sig_atomic_t signaled = 0;
+
+
 static void sig_handler(int signal) {
     (void)signal;
+
+    signaled = 1;
 }
 static void setup_signals(void) {
     struct sigaction action;
@@ -67,6 +72,17 @@ static void setup_signals(void) {
     sigaction(SIGUSR2, &action, NULL);
 }
 
+static int set_cloexec(int fd) {
+    int flags = fcntl(fd, F_GETFD);
+    if (flags == -1) {
+        return 0;
+    }
+    if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) {
+        return 0;
+    }
+    return 1;
+}
+
 static int open_tty(int public) {
     int ptm;
     const char *name;
@@ -78,6 +94,9 @@ static int open_tty(int public) {
     if (grantpt(ptm) != 0) {
         return -1;
     }
+    if (!set_cloexec(ptm)) {
+        return -1;
+    }
 
     /* Prevent write access for other users so they can't use wall to send
      * messages to this program. */
@@ -150,11 +169,11 @@ static int set_utmpx(short type, int ptm) {
 static int login(int ptm) {
 #if defined(USE_UTEMPTER)
     int result = utempter_add_record(ptm, NULL);
-    /* Exit value of utempter_*() is not correct on all systems, e.g.
-     * FreeBSD() always returns 0. Checking the utmpx database manually is
-     * difficult because we don't know the exact values for ut_id and ut_line,
-     * therefore we only check the return value on systems known to return a
-     * useful value. */
+    /* Exit value of utempter_*() is not correct on all systems, e.g. FreeBSD
+     * always returns 0. Checking the utmpx database manually is difficult
+     * because we don't know the exact values for ut_id and ut_line, therefore
+     * we only check the return value on systems known to return a useful
+     * value. */
 # ifndef __linux
     result = 1;
 # endif
@@ -214,14 +233,14 @@ static void drop_privileges(void) {
     gid = getgid();
 
     /* Drop all privileges. */
-    if (setresuid(uid, uid, uid) != 0) {
-        perror("setresuid");
-        exit(EXIT_FAILURE);
-    }
     if (setresgid(gid, gid, gid) != 0) {
         perror("setresgid");
         exit(EXIT_FAILURE);
     }
+    if (setresuid(uid, uid, uid) != 0) {
+        perror("setresuid");
+        exit(EXIT_FAILURE);
+    }
 
     /* Verify all privileges were dropped. */
     if (getresuid(&ruid, &euid, &suid) != 0) {
@@ -318,7 +337,7 @@ static void handle_wall(int fd, char **argv) {
     ssize_t r;
 
     assert(SSIZE_MAX <= SIZE_MAX);
-    while ((r = read(fd, buffer, sizeof(buffer))) > 0) {
+    while (!signaled && (r = read(fd, buffer, sizeof(buffer))) > 0) {
         size_t space;
         ssize_t r2;
 
@@ -377,6 +396,7 @@ static void usage(const char *argv0) {
 
 int main(int argc, char **argv) {
     int option, enable_x11, mesg_yes;
+    const char *argv0;
     int ptm, pts;
     char *name;
 
@@ -386,6 +406,8 @@ int main(int argc, char **argv) {
     enable_x11 = 0;
     mesg_yes = 0;
 
+    argv0 = argv[0];
+
     /*
      * Glibc violates POSIX by default and skips over non-option arguments and
      * parses later arguments which look like options as well. But we want to
@@ -402,25 +424,25 @@ int main(int argc, char **argv) {
                 mesg_yes = 1;
                 break;
             case 'h':
-                usage(argv[0]);
+                usage(argv0);
                 break;
             case 'v':
                 printf("%s%s\n",
                        PACKAGE_STRING,
                        strlen(GIT_VERSION) ? " (Git " GIT_VERSION ")" : "");
-                exit(0);
+                exit(EXIT_SUCCESS);
                 break;
             default:
                 fprintf(stderr, "%s: unknown option '%s'!\n\n",
-                                argv[0], argv[optind - 1]);
-                usage(argv[0]);
+                                argv0, argv[optind - 1]);
+                usage(argv0);
                 break;
         }
     }
 
     /* No arguments remaining, abort. */
     if (!argv[optind]) {
-        usage(argv[0]);
+        usage(argv0);
     }
     /* Arguments for notification program. */
     argv += optind;
@@ -442,7 +464,7 @@ int main(int argc, char **argv) {
 
     /* We need to open the slave or reading from the master yields EOF after
      * the first wall write to it. */
-    pts = open(name, O_RDWR);
+    pts = open(name, O_RDWR | O_CLOEXEC);
     if (pts < 0) {
         perror(name);
         exit(EXIT_FAILURE);