]> ruderich.org/simon Gitweb - wall-notify/wall-notify.git/blobdiff - src/wall-notify.c
fix -X option
[wall-notify/wall-notify.git] / src / wall-notify.c
index 40cdfe587870bc46f6ae5cbfc6b8c0308a74d70e..806204e09c975c27c6885b3785724c6e0662162e 100644 (file)
@@ -203,6 +203,44 @@ static int wait_for_write(int fd, int timeout) {
     return 1;
 }
 
+#ifdef USE_UTMPX
+static void drop_privileges(void) {
+    uid_t uid, ruid, euid, suid;
+    gid_t gid, rgid, egid, sgid;
+
+    uid = getuid();
+    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);
+    }
+
+    /* Verify all privileges were dropped. */
+    if (getresuid(&ruid, &euid, &suid) != 0) {
+        perror("getresuid");
+        exit(EXIT_FAILURE);
+    }
+    if (getresgid(&rgid, &egid, &sgid) != 0) {
+        perror("getresgid");
+        exit(EXIT_FAILURE);
+    }
+    if (uid == ruid && uid == euid && uid == suid
+            && gid == rgid && gid == egid && gid == sgid) {
+        /* Everything fine. */
+        return;
+    }
+
+    fprintf(stderr, "failed to drop privileges, aborting\n");
+    exit(EXIT_FAILURE);
+}
+#endif
+
 static void pass_buffer_to_program(const char *buffer, size_t length, char **argv) {
     int fds[2];
     FILE *fh;
@@ -229,6 +267,10 @@ static void pass_buffer_to_program(const char *buffer, size_t length, char **arg
     } else if (pid == 0) {
         /* child */
 
+#ifdef USE_UTMPX
+        drop_privileges();
+#endif
+
         close(fds[1]); /* write side */
 
         /* Pass read side as stdin to the program. */
@@ -317,12 +359,20 @@ static void *x11_event_loop_thread(void *unused) {
 #endif
 
 static void usage(const char *argv0) {
-    fprintf(stderr, "usage: %s <cmd args..>\n", argv0);
+    fprintf(stderr, "usage: %s [-X] <cmd args..>\n", argv0);
+    fprintf(stderr, "Pass wall messages to <cmd args..>.\n");
+    fprintf(stderr, "\n");
+    fprintf(stderr, "-X quit when the current X session terminates\n");
+#ifdef DONT_USE_X11
+    fprintf(stderr, "\n");
+    fprintf(stderr, "compiled without X11 support, -X disabled\n");
+#endif
     exit(EXIT_FAILURE);
 }
 
 
 int main(int argc, char **argv) {
+    int enable_x11;
     int ptm, pts;
     char *name;
     const char *argv0;
@@ -331,6 +381,20 @@ int main(int argc, char **argv) {
     /* Don't pass our argv[0] to the notification program. */
     argv++;
 
+    enable_x11 = 0;
+    if (argc > 1 && argv[0][0] == '-') {
+        if (!strcmp("-X", argv[0])) {
+            enable_x11 = 1;
+        } else {
+            if (strcmp("-h", argv[0])) {
+                fprintf(stderr, "%s: unknown option '%s'!\n\n", argv0, argv[0]);
+            }
+            usage(argv0);
+        }
+        argc--; /* for usage */
+        argv++;
+    }
+
     if (argc < 2) {
         usage(argv0);
     }
@@ -358,18 +422,21 @@ int main(int argc, char **argv) {
         exit(EXIT_FAILURE);
     }
 
-#ifndef DONT_USE_X11
     /* Start a thread which connects to X11. This way we die if the user logs
      * out of its X11 session. */
-    {
+    if (enable_x11) {
+#ifdef DONT_USE_X11
+        fprintf(stderr, "%s: option -X is disabled!\n\n", argv0);
+        usage(argv0);
+#else
         pthread_t tid;
 
         if (pthread_create(&tid, NULL, x11_event_loop_thread, NULL) != 0) {
             perror("pthread_create");
             exit(EXIT_FAILURE);
         }
-    }
 #endif
+    }
 
     /* Cleanup on signals. Necessary before login(). */
     setup_signals();