i3 - improved tiling WM


Run authentification in different process

Patch status: superseded

Patch by koebi

Long description:

This fixes #895

To apply this patch, use:
curl http://cr.i3wm.org/patch/214/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,6 +199,46 @@ static void clear_input(void) {
23
     redraw_screen();
24
     unlock_state = STATE_KEY_PRESSED;
25
 }
26
+static void child_cb(EV_P_ ev_child *child_watcher, int revents) {
27
+    if (child_watcher->rstatus == PAM_SUCCESS){
28
+        DEBUG("Authentication successfull\n");
29
+        clear_password_memory();
30
+
31
+        ev_child_stop(main_loop, child_watcher);
32
+        free(child_watcher);
33
+        
34
+        exit(0);
35
+    } else {
36
+
37
+        if (debug_mode)
38
+            fprintf(stderr, "Authentication failure\n");
39
+        
40
+        ev_child_stop(main_loop, child_watcher);
41
+        free(child_watcher);
42
+
43
+        pam_state = STATE_PAM_WRONG;
44
+        clear_input();
45
+        redraw_screen();
46
+
47
+        /* Clear this state after 2 seconds (unless the user enters another
48
+         * password during that time). */
49
+        ev_now_update(main_loop);
50
+        if ((clear_pam_wrong_timeout = calloc(sizeof(struct ev_timer), 1))) {
51
+            ev_timer_init(clear_pam_wrong_timeout, clear_pam_wrong, 2.0, 0.);
52
+            ev_timer_start(main_loop, clear_pam_wrong_timeout);
53
+        }
54
+
55
+        /* Cancel the clear_indicator_timeout, it would hide the unlock indicator
56
+         * too early. */
57
+        stop_clear_indicator_timeout();
58
+
59
+        /* beep on authentication failure, if enabled */
60
+        if (beep) {
61
+            xcb_bell(conn, 100);
62
+            xcb_flush(conn);
63
+        }
64
+    }
65
+}
66
 
67
 static void input_done(void) {
68
     if (clear_pam_wrong_timeout) {
69
@@ -208,36 +249,18 @@ static void input_done(void) {
70
 
71
     pam_state = STATE_PAM_VERIFY;
72
     redraw_screen();
73
-
74
-    if (pam_authenticate(pam_handle, 0) == PAM_SUCCESS) {
75
-        DEBUG("successfully authenticated\n");
76
-        clear_password_memory();
77
-        exit(0);
78
-    }
79
-
80
-    if (debug_mode)
81
-        fprintf(stderr, "Authentication failure\n");
82
-
83
-    pam_state = STATE_PAM_WRONG;
84
-    clear_input();
85
-    redraw_screen();
86
-
87
-    /* Clear this state after 2 seconds (unless the user enters another
88
-     * password during that time). */
89
-    ev_now_update(main_loop);
90
-    if ((clear_pam_wrong_timeout = calloc(sizeof(struct ev_timer), 1))) {
91
-        ev_timer_init(clear_pam_wrong_timeout, clear_pam_wrong, 2.0, 0.);
92
-        ev_timer_start(main_loop, clear_pam_wrong_timeout);
93
-    }
94
-
95
-    /* Cancel the clear_indicator_timeout, it would hide the unlock indicator
96
-     * too early. */
97
-    stop_clear_indicator_timeout();
98
-
99
-    /* beep on authentication failure, if enabled */
100
-    if (beep) {
101
-        xcb_bell(conn, 100);
102
-        xcb_flush(conn);
103
+    
104
+    /* fork to unblock pam_authenticate */
105
+    pid_t cpid;
106
+    cpid = fork();
107
+    struct ev_child *child_watcher = calloc(sizeof(struct ev_io), 1);
108
+    ev_child_init(child_watcher, child_cb, cpid, 0);
109
+    ev_child_set(child_watcher, cpid, 0);
110
+    ev_child_start (EV_DEFAULT_ child_watcher);
111
+    if (cpid == 0) {    
112
+        exit(pam_authenticate(pam_handle, 0));
113
+    } else if (cpid < 0) {
114
+        err(1, "Could not fork");
115
     }
116
 }
117