diff options
author | Damien Miller <djm@cvs.openbsd.org> | 2010-12-15 00:49:28 +0000 |
---|---|---|
committer | Damien Miller <djm@cvs.openbsd.org> | 2010-12-15 00:49:28 +0000 |
commit | 149ccbb4ab3e10636597f3dbb65e0aeed63da190 (patch) | |
tree | bec620e4a97c104e589f80a953386bc00a8b7d60 /usr.bin | |
parent | 3b0e01e3cafd991de40576f3d96d06ddb46602a7 (diff) |
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 'usr.bin')
-rw-r--r-- | usr.bin/ssh/readpass.c | 27 |
1 files changed, 16 insertions, 11 deletions
diff --git a/usr.bin/ssh/readpass.c b/usr.bin/ssh/readpass.c index b8b88ff3085..3a661fa806f 100644 --- a/usr.bin/ssh/readpass.c +++ b/usr.bin/ssh/readpass.c @@ -1,4 +1,4 @@ -/* $OpenBSD: readpass.c,v 1.47 2006/08/03 03:34:42 deraadt Exp $ */ +/* $OpenBSD: readpass.c,v 1.48 2010/12/15 00:49:27 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -30,6 +30,7 @@ #include <fcntl.h> #include <paths.h> #include <readpassphrase.h> +#include <signal.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> @@ -46,11 +47,12 @@ static char * ssh_askpass(char *askpass, const char *msg) { - pid_t pid; + pid_t pid, ret; size_t len; char *pass; - int p[2], status, ret; + int p[2], status; char buf[1024]; + void (*osigchld)(int); if (fflush(stdout) != 0) error("ssh_askpass: fflush: %s", strerror(errno)); @@ -60,8 +62,10 @@ ssh_askpass(char *askpass, const char *msg) error("ssh_askpass: pipe: %s", strerror(errno)); return NULL; } + osigchld = signal(SIGCHLD, SIG_DFL); if ((pid = fork()) < 0) { error("ssh_askpass: fork: %s", strerror(errno)); + signal(SIGCHLD, osigchld); return NULL; } if (pid == 0) { @@ -74,23 +78,24 @@ ssh_askpass(char *askpass, const char *msg) } close(p[1]); - len = ret = 0; + len = 0; do { - ret = read(p[0], buf + len, sizeof(buf) - 1 - len); - if (ret == -1 && errno == EINTR) + ssize_t r = read(p[0], buf + len, sizeof(buf) - 1 - len); + + if (r == -1 && errno == EINTR) continue; - if (ret <= 0) + if (r <= 0) break; - len += ret; + len += r; } while (sizeof(buf) - 1 - len > 0); buf[len] = '\0'; close(p[0]); - while (waitpid(pid, &status, 0) < 0) + while ((ret = waitpid(pid, &status, 0)) < 0) if (errno != EINTR) break; - - if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { + signal(SIGCHLD, osigchld); + if (ret == -1 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) { memset(buf, 0, sizeof(buf)); return NULL; } |