If some signal arrives to the parent between these two points
then it is possible to have dirty entries in utmp.
---
 utmp.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/utmp.c b/utmp.c
index c893ae1..6cdc5d2 100644
--- a/utmp.c
+++ b/utmp.c
@@ -6,6 +6,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <signal.h>
 
 #include <sys/types.h>
 #include <unistd.h>
@@ -40,6 +41,7 @@ main(int argc, char *argv[])
        int status;
        uid_t uid;
        extern void addutmp(void), delutmp(void);
+       sigset_t set;
 
        egid = getegid();
        gid = getgid();
@@ -54,8 +56,12 @@ main(int argc, char *argv[])
        setenv("SHELL", pass->pw_shell, 0);
        setenv("HOME", pass->pw_dir, 0);
 
+       sigfillset(&set);
+       sigprocmask(SIG_BLOCK, &set, NULL);
+
        switch (fork()) {
        case 0:
+               sigprocmask(SIG_UNBLOCK, &set, NULL);
                argv[0] = getenv("SHELL");
                execv(argv[0], argv);
                die("error executing shell:%s", strerror(errno));
@@ -63,10 +69,13 @@ main(int argc, char *argv[])
                die("error spawning child:%s", strerror(errno));
        default:
                addutmp();
-               if (wait(&status) == -1) {
-                       fprintf(stderr, "error waiting child:%s\n",
-                               strerror(errno));
-               }
+               signal(SIGINT, SIG_IGN);
+               signal(SIGTERM, SIG_IGN);
+               signal(SIGHUP, SIG_IGN);
+               sigprocmask(SIG_UNBLOCK, &set, NULL);
+
+               if (wait(&status) == -1)
+                       perror("error waiting child");
                delutmp();
        }
        return 0;
-- 
1.9.3


Reply via email to