diff options
author | Damien Miller <djm@mindrot.org> | 2011-01-06 22:43:44 +1100 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2011-01-06 22:43:44 +1100 |
commit | 106079c06d308f6fb3b582607f590b2dcb4682b0 (patch) | |
tree | 99be677ace30c4fbec794652b18bbb2a0e2f3620 /readpass.c | |
parent | 05c8997b33cf391784d6a5f9f0d85d275dcf7ce5 (diff) |
- djm@cvs.openbsd.org 2010/12/15 00:49:27
[readpass.c]
fix ControlMaster=ask regression
reset SIGCHLD handler before fork (and restore it after) so we don't miss
the the askpass child's exit status. Correct test for exit status/signal to
account for waitpid() failure; with claudio@ ok claudio@ markus@
Diffstat (limited to 'readpass.c')
-rw-r--r-- | readpass.c | 27 |
1 files changed, 16 insertions, 11 deletions
diff --git a/readpass.c b/readpass.c index bd144c2e3..599c8ef9a 100644 --- a/readpass.c +++ b/readpass.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: readpass.c,v 1.47 2006/08/03 03:34:42 deraadt Exp $ */ | 1 | /* $OpenBSD: readpass.c,v 1.48 2010/12/15 00:49:27 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -33,6 +33,7 @@ | |||
33 | #ifdef HAVE_PATHS_H | 33 | #ifdef HAVE_PATHS_H |
34 | # include <paths.h> | 34 | # include <paths.h> |
35 | #endif | 35 | #endif |
36 | #include <signal.h> | ||
36 | #include <stdarg.h> | 37 | #include <stdarg.h> |
37 | #include <stdio.h> | 38 | #include <stdio.h> |
38 | #include <stdlib.h> | 39 | #include <stdlib.h> |
@@ -49,11 +50,12 @@ | |||
49 | static char * | 50 | static char * |
50 | ssh_askpass(char *askpass, const char *msg) | 51 | ssh_askpass(char *askpass, const char *msg) |
51 | { | 52 | { |
52 | pid_t pid; | 53 | pid_t pid, ret; |
53 | size_t len; | 54 | size_t len; |
54 | char *pass; | 55 | char *pass; |
55 | int p[2], status, ret; | 56 | int p[2], status; |
56 | char buf[1024]; | 57 | char buf[1024]; |
58 | void (*osigchld)(int); | ||
57 | 59 | ||
58 | if (fflush(stdout) != 0) | 60 | if (fflush(stdout) != 0) |
59 | error("ssh_askpass: fflush: %s", strerror(errno)); | 61 | error("ssh_askpass: fflush: %s", strerror(errno)); |
@@ -63,8 +65,10 @@ ssh_askpass(char *askpass, const char *msg) | |||
63 | error("ssh_askpass: pipe: %s", strerror(errno)); | 65 | error("ssh_askpass: pipe: %s", strerror(errno)); |
64 | return NULL; | 66 | return NULL; |
65 | } | 67 | } |
68 | osigchld = signal(SIGCHLD, SIG_DFL); | ||
66 | if ((pid = fork()) < 0) { | 69 | if ((pid = fork()) < 0) { |
67 | error("ssh_askpass: fork: %s", strerror(errno)); | 70 | error("ssh_askpass: fork: %s", strerror(errno)); |
71 | signal(SIGCHLD, osigchld); | ||
68 | return NULL; | 72 | return NULL; |
69 | } | 73 | } |
70 | if (pid == 0) { | 74 | if (pid == 0) { |
@@ -77,23 +81,24 @@ ssh_askpass(char *askpass, const char *msg) | |||
77 | } | 81 | } |
78 | close(p[1]); | 82 | close(p[1]); |
79 | 83 | ||
80 | len = ret = 0; | 84 | len = 0; |
81 | do { | 85 | do { |
82 | ret = read(p[0], buf + len, sizeof(buf) - 1 - len); | 86 | ssize_t r = read(p[0], buf + len, sizeof(buf) - 1 - len); |
83 | if (ret == -1 && errno == EINTR) | 87 | |
88 | if (r == -1 && errno == EINTR) | ||
84 | continue; | 89 | continue; |
85 | if (ret <= 0) | 90 | if (r <= 0) |
86 | break; | 91 | break; |
87 | len += ret; | 92 | len += r; |
88 | } while (sizeof(buf) - 1 - len > 0); | 93 | } while (sizeof(buf) - 1 - len > 0); |
89 | buf[len] = '\0'; | 94 | buf[len] = '\0'; |
90 | 95 | ||
91 | close(p[0]); | 96 | close(p[0]); |
92 | while (waitpid(pid, &status, 0) < 0) | 97 | while ((ret = waitpid(pid, &status, 0)) < 0) |
93 | if (errno != EINTR) | 98 | if (errno != EINTR) |
94 | break; | 99 | break; |
95 | 100 | signal(SIGCHLD, osigchld); | |
96 | if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { | 101 | if (ret == -1 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) { |
97 | memset(buf, 0, sizeof(buf)); | 102 | memset(buf, 0, sizeof(buf)); |
98 | return NULL; | 103 | return NULL; |
99 | } | 104 | } |