version 1.54, 2019/06/28 13:35:04 |
version 1.55, 2019/11/12 22:34:20 |
|
|
|
|
return (allowed); |
return (allowed); |
} |
} |
|
|
|
struct notifier_ctx { |
|
pid_t pid; |
|
void (*osigchld)(int); |
|
}; |
|
|
|
struct notifier_ctx * |
|
notify_start(int force_askpass, const char *fmt, ...) |
|
{ |
|
va_list args; |
|
char *prompt = NULL; |
|
int devnull; |
|
pid_t pid; |
|
void (*osigchld)(int); |
|
const char *askpass; |
|
struct notifier_ctx *ret; |
|
|
|
va_start(args, fmt); |
|
xvasprintf(&prompt, fmt, args); |
|
va_end(args); |
|
|
|
if (fflush(NULL) != 0) |
|
error("%s: fflush: %s", __func__, strerror(errno)); |
|
if (!force_askpass && isatty(STDERR_FILENO)) { |
|
(void)write(STDERR_FILENO, "\r", 1); |
|
(void)write(STDERR_FILENO, prompt, strlen(prompt)); |
|
(void)write(STDERR_FILENO, "\r\n", 2); |
|
free(prompt); |
|
return NULL; |
|
} |
|
if (getenv("DISPLAY") == NULL || |
|
(askpass = getenv("SSH_ASKPASS")) == NULL || *askpass == '\0') { |
|
debug3("%s: cannot notify", __func__); |
|
free(prompt); |
|
return NULL; |
|
} |
|
osigchld = signal(SIGCHLD, SIG_DFL); |
|
if ((pid = fork()) == -1) { |
|
error("%s: fork: %s", __func__, strerror(errno)); |
|
signal(SIGCHLD, osigchld); |
|
free(prompt); |
|
return NULL; |
|
} |
|
if (pid == 0) { |
|
if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) |
|
fatal("%s: open %s", __func__, strerror(errno)); |
|
if (dup2(devnull, STDIN_FILENO) == -1 || |
|
dup2(devnull, STDOUT_FILENO) == -1) |
|
fatal("%s: dup2: %s", __func__, strerror(errno)); |
|
closefrom(STDERR_FILENO + 1); |
|
setenv("SSH_ASKPASS_PROMPT", "none", 1); /* hint to UI */ |
|
execlp(askpass, askpass, prompt, (char *)NULL); |
|
fatal("%s: exec(%s): %s", __func__, askpass, strerror(errno)); |
|
/* NOTREACHED */ |
|
} |
|
if ((ret = calloc(1, sizeof(*ret))) == NULL) { |
|
kill(pid, SIGTERM); |
|
fatal("%s: calloc failed", __func__); |
|
} |
|
ret->pid = pid; |
|
ret->osigchld = osigchld; |
|
free(prompt); |
|
return ret; |
|
} |
|
|
|
void |
|
notify_complete(struct notifier_ctx *ctx) |
|
{ |
|
int ret; |
|
|
|
if (ctx == NULL || ctx->pid <= 0) { |
|
free(ctx); |
|
return; |
|
} |
|
kill(ctx->pid, SIGTERM); |
|
while ((ret = waitpid(ctx->pid, NULL, 0)) == -1) { |
|
if (errno != EINTR) |
|
break; |
|
} |
|
if (ret == -1) |
|
fatal("%s: waitpid: %s", __func__, strerror(errno)); |
|
signal(SIGCHLD, ctx->osigchld); |
|
free(ctx); |
|
} |