i3 - improved tiling WM


Run authentification in different process

Patch status: superseded

Patch by koebi

Long description:

fixes #895

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