i3 - improved tiling WM


Run authentification in different process

Patch status: superseded

Patch by koebi

Long description:

This fixes #733

To apply this patch, use:
curl http://cr.i3wm.org/patch/211/raw.patch | git am

b/i3lock.c

14
@@ -22,6 +22,7 @@
15
 #include <string.h>
16
 #include <ev.h>
17
 #include <sys/mman.h>
18
+#include <sys/wait.h>
19
 #include <X11/XKBlib.h>
20
 #include <X11/extensions/XKBfile.h>
21
 #include <xkbcommon/xkbcommon.h>
22
@@ -198,25 +199,23 @@ static void clear_input(void) {
23
     redraw_screen();
24
     unlock_state = STATE_KEY_PRESSED;
25
 }
26
-
27
-static void input_done(void) {
28
-    if (clear_pam_wrong_timeout) {
29
-        ev_timer_stop(main_loop, clear_pam_wrong_timeout);
30
-        free(clear_pam_wrong_timeout);
31
-        clear_pam_wrong_timeout = NULL;
32
-    }
33
-
34
-    pam_state = STATE_PAM_VERIFY;
35
-    redraw_screen();
36
-
37
-    if (pam_authenticate(pam_handle, 0) == PAM_SUCCESS) {
38
-        DEBUG("successfully authenticated\n");
39
+static void my_pipe(EV_P_ ev_io *pipe_watcher, int revents){
40
+    int ret;
41
+    if (read(pipe_watcher->fd, &ret, sizeof(ret)) < 0)
42
+        err(1, "Could not read pipe");
43
+    if (ret == PAM_SUCCESS){
44
+        DEBUG("Authentication successfull\n");
45
         clear_password_memory();
46
         exit(0);
47
     }
48
-
49
     if (debug_mode)
50
         fprintf(stderr, "Authentication failure\n");
51
+    
52
+    ev_io_stop(main_loop, pipe_watcher);
53
+    close(pipe_watcher->fd);
54
+    free(pipe_watcher);
55
+    
56
+    waitpid((long)pipe_watcher->data, NULL, 0);
57
 
58
     pam_state = STATE_PAM_WRONG;
59
     clear_input();
60
@@ -241,6 +240,41 @@ static void input_done(void) {
61
     }
62
 }
63
 
64
+static void input_done(void) {
65
+    if (clear_pam_wrong_timeout) {
66
+        ev_timer_stop(main_loop, clear_pam_wrong_timeout);
67
+        free(clear_pam_wrong_timeout);
68
+        clear_pam_wrong_timeout = NULL;
69
+    }
70
+
71
+    pam_state = STATE_PAM_VERIFY;
72
+    redraw_screen();
73
+    
74
+    /* fork to unblock pam_authenticate
75
+     */
76
+    int pipefd[2];
77
+    if (pipe(pipefd) != 0)
78
+        err(1, "Could not create pipe");
79
+    pid_t cpid;
80
+    cpid = fork();
81
+    if (cpid == 0) {    
82
+        int ret = pam_authenticate(pam_handle, 0);
83
+        //we don't check return values, because we exit anyways
84
+        write(pipefd[1], &ret, sizeof(ret)); 
85
+        clear_password_memory();
86
+        exit(0);
87
+    } else if (cpid < 0) {
88
+        err(1, "Could not fork");
89
+    }
90
+    close(pipefd[1]);
91
+    
92
+    struct ev_io *pipe_watcher = calloc(sizeof(struct ev_io), 1);
93
+
94
+    ev_io_init(pipe_watcher, my_pipe, pipefd[0], EV_READ);
95
+    ev_io_start(main_loop, pipe_watcher);
96
+    pipe_watcher->data = (void *)(long)cpid;
97
+}
98
+
99
 /*
100
  * Called when the user releases a key. We need to leave the Mode_switch
101
  * state when the user releases the Mode_switch key.