version 1.1, 1995/10/18 08:45:39 |
version 1.2, 1996/06/11 12:53:47 |
|
|
|
/* $OpenBSD$ */ |
|
/* $NetBSD: popen.c,v 1.4 1996/06/08 19:48:35 christos Exp $ */ |
|
|
/* |
/* |
* Copyright (c) 1980, 1993 |
* Copyright (c) 1980, 1993 |
* The Regents of the University of California. All rights reserved. |
* The Regents of the University of California. All rights reserved. |
|
|
*/ |
*/ |
|
|
#ifndef lint |
#ifndef lint |
static char sccsid[] = "from: @(#)popen.c 8.1 (Berkeley) 6/6/93"; |
#if 0 |
static char rcsid[] = "$Id$"; |
static char sccsid[] = "@(#)popen.c 8.1 (Berkeley) 6/6/93"; |
|
#else |
|
static char rcsid[] = "$OpenBSD$"; |
|
#endif |
#endif /* not lint */ |
#endif /* not lint */ |
|
|
#include "rcv.h" |
#include "rcv.h" |
|
|
static struct child *child; |
static struct child *child; |
static struct child *findchild __P((int)); |
static struct child *findchild __P((int)); |
static void delchild __P((struct child *)); |
static void delchild __P((struct child *)); |
|
static int file_pid __P((FILE *)); |
|
|
FILE * |
FILE * |
Fopen(file, mode) |
Fopen(file, mode) |
|
|
int p[2]; |
int p[2]; |
int myside, hisside, fd0, fd1; |
int myside, hisside, fd0, fd1; |
int pid; |
int pid; |
|
sigset_t nset; |
FILE *fp; |
FILE *fp; |
|
|
if (pipe(p) < 0) |
if (pipe(p) < 0) |
|
|
hisside = fd0 = p[READ]; |
hisside = fd0 = p[READ]; |
fd1 = -1; |
fd1 = -1; |
} |
} |
if ((pid = start_command(cmd, 0, fd0, fd1, NOSTR, NOSTR, NOSTR)) < 0) { |
sigemptyset(&nset); |
|
if ((pid = start_command(cmd, &nset, fd0, fd1, NOSTR, NOSTR, NOSTR)) < 0) { |
close(p[READ]); |
close(p[READ]); |
close(p[WRITE]); |
close(p[WRITE]); |
return NULL; |
return NULL; |
|
|
FILE *ptr; |
FILE *ptr; |
{ |
{ |
int i; |
int i; |
int omask; |
sigset_t nset, oset; |
|
|
i = file_pid(ptr); |
i = file_pid(ptr); |
unregister_file(ptr); |
unregister_file(ptr); |
(void) fclose(ptr); |
(void) fclose(ptr); |
omask = sigblock(sigmask(SIGINT)|sigmask(SIGHUP)); |
sigemptyset(&nset); |
|
sigaddset(&nset, SIGINT); |
|
sigaddset(&nset, SIGHUP); |
|
sigprocmask(SIG_BLOCK, &nset, &oset); |
i = wait_child(i); |
i = wait_child(i); |
sigsetmask(omask); |
sigprocmask(SIG_SETMASK, &oset, NULL); |
return i; |
return i; |
} |
} |
|
|
|
|
{ |
{ |
struct fp **pp, *p; |
struct fp **pp, *p; |
|
|
for (pp = &fp_head; p = *pp; pp = &p->link) |
for (pp = &fp_head; (p = *pp) != NULL; pp = &p->link) |
if (p->fp == fp) { |
if (p->fp == fp) { |
*pp = p->link; |
*pp = p->link; |
free((char *) p); |
free((char *) p); |
|
|
panic("Invalid file pointer"); |
panic("Invalid file pointer"); |
} |
} |
|
|
|
static int |
file_pid(fp) |
file_pid(fp) |
FILE *fp; |
FILE *fp; |
{ |
{ |
|
|
int |
int |
run_command(cmd, mask, infd, outfd, a0, a1, a2) |
run_command(cmd, mask, infd, outfd, a0, a1, a2) |
char *cmd; |
char *cmd; |
int mask, infd, outfd; |
sigset_t *mask; |
|
int infd, outfd; |
char *a0, *a1, *a2; |
char *a0, *a1, *a2; |
{ |
{ |
int pid; |
int pid; |
|
|
int |
int |
start_command(cmd, mask, infd, outfd, a0, a1, a2) |
start_command(cmd, mask, infd, outfd, a0, a1, a2) |
char *cmd; |
char *cmd; |
int mask, infd, outfd; |
sigset_t *mask; |
|
int infd, outfd; |
char *a0, *a1, *a2; |
char *a0, *a1, *a2; |
{ |
{ |
int pid; |
int pid; |
|
|
} |
} |
|
|
void |
void |
prepare_child(mask, infd, outfd) |
prepare_child(nset, infd, outfd) |
int mask, infd, outfd; |
sigset_t *nset; |
|
int infd, outfd; |
{ |
{ |
int i; |
int i; |
|
sigset_t fset; |
|
|
/* |
/* |
* All file descriptors other than 0, 1, and 2 are supposed to be |
* All file descriptors other than 0, 1, and 2 are supposed to be |
|
|
if (outfd >= 0) |
if (outfd >= 0) |
dup2(outfd, 1); |
dup2(outfd, 1); |
for (i = 1; i <= NSIG; i++) |
for (i = 1; i <= NSIG; i++) |
if (mask & sigmask(i)) |
if (sigismember(nset, i)) |
(void) signal(i, SIG_IGN); |
(void) signal(i, SIG_IGN); |
if ((mask & sigmask(SIGINT)) == 0) |
if (!sigismember(nset, SIGINT)) |
(void) signal(SIGINT, SIG_DFL); |
(void) signal(SIGINT, SIG_DFL); |
(void) sigsetmask(0); |
sigfillset(&fset); |
|
(void) sigprocmask(SIG_UNBLOCK, &fset, NULL); |
} |
} |
|
|
int |
int |
|
|
wait_child(pid) |
wait_child(pid) |
int pid; |
int pid; |
{ |
{ |
int mask = sigblock(sigmask(SIGCHLD)); |
sigset_t nset, oset; |
register struct child *cp = findchild(pid); |
register struct child *cp = findchild(pid); |
|
sigemptyset(&nset); |
|
sigaddset(&nset, SIGCHLD); |
|
sigprocmask(SIG_BLOCK, &nset, &oset); |
|
|
while (!cp->done) |
while (!cp->done) |
sigpause(mask); |
sigsuspend(&oset); |
wait_status = cp->status; |
wait_status = cp->status; |
delchild(cp); |
delchild(cp); |
sigsetmask(mask); |
sigprocmask(SIG_SETMASK, &oset, NULL); |
return wait_status.w_status ? -1 : 0; |
return wait_status.w_status ? -1 : 0; |
} |
} |
|
|
|
|
free_child(pid) |
free_child(pid) |
int pid; |
int pid; |
{ |
{ |
int mask = sigblock(sigmask(SIGCHLD)); |
sigset_t nset, oset; |
register struct child *cp = findchild(pid); |
register struct child *cp = findchild(pid); |
|
sigemptyset(&nset); |
|
sigaddset(&nset, SIGCHLD); |
|
sigprocmask(SIG_BLOCK, &nset, &oset); |
|
|
if (cp->done) |
if (cp->done) |
delchild(cp); |
delchild(cp); |
else |
else |
cp->free = 1; |
cp->free = 1; |
sigsetmask(mask); |
sigprocmask(SIG_SETMASK, &oset, NULL); |
} |
} |