/*
- * Copyright (c) 1980 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1980, 1993
+ * The Regents of the University of California. All rights reserved.
*
* %sccs.include.redist.c%
*/
#ifndef lint
-static char sccsid[] = "@(#)popen.c 5.15 (Berkeley) %G%";
+static char sccsid[] = "@(#)popen.c 8.1 (Berkeley) %G%";
#endif /* not lint */
#include "rcv.h"
-#include <sys/signal.h>
#include <sys/wait.h>
+#include <fcntl.h>
+#include "extern.h"
#define READ 0
#define WRITE 1
-static int *pid;
struct fp {
FILE *fp;
int pipe;
+ int pid;
struct fp *link;
};
static struct fp *fp_head;
+struct child {
+ int pid;
+ char done;
+ char free;
+ union wait status;
+ struct child *link;
+};
+static struct child *child;
+static struct child *findchild __P((int));
+static void delchild __P((struct child *));
+
FILE *
Fopen(file, mode)
char *file, *mode;
{
FILE *fp;
- if ((fp = fopen(file, mode)) != NULL)
- register_file(fp, 0);
+ if ((fp = fopen(file, mode)) != NULL) {
+ register_file(fp, 0, 0);
+ (void) fcntl(fileno(fp), F_SETFD, 1);
+ }
return fp;
}
FILE *
Fdopen(fd, mode)
+ int fd;
char *mode;
{
FILE *fp;
- if ((fp = fdopen(fd, mode)) != NULL)
- register_file(fp, 0);
+ if ((fp = fdopen(fd, mode)) != NULL) {
+ register_file(fp, 0, 0);
+ (void) fcntl(fileno(fp), F_SETFD, 1);
+ }
return fp;
}
+int
Fclose(fp)
FILE *fp;
{
{
int p[2];
int myside, hisside, fd0, fd1;
+ int pid;
FILE *fp;
- if (pid == 0)
- pid = (int *) malloc((unsigned) sizeof (int) * getdtablesize());
if (pipe(p) < 0)
return NULL;
+ (void) fcntl(p[READ], F_SETFD, 1);
+ (void) fcntl(p[WRITE], F_SETFD, 1);
if (*mode == 'r') {
myside = p[READ];
fd0 = -1;
hisside = fd0 = p[READ];
fd1 = -1;
}
- if ((pid[myside] = start_command(cmd, 0, fd0, fd1, NOSTR)) < 0) {
+ if ((pid = start_command(cmd, 0, fd0, fd1, NOSTR, NOSTR, NOSTR)) < 0) {
close(p[READ]);
close(p[WRITE]);
return NULL;
}
(void) close(hisside);
if ((fp = fdopen(myside, mode)) != NULL)
- register_file(fp, 1);
+ register_file(fp, 1, pid);
return fp;
}
+int
Pclose(ptr)
FILE *ptr;
{
int i;
int omask;
- i = fileno(ptr);
+ i = file_pid(ptr);
unregister_file(ptr);
(void) fclose(ptr);
omask = sigblock(sigmask(SIGINT)|sigmask(SIGHUP));
- i = wait_child(pid[i]);
+ i = wait_child(i);
sigsetmask(omask);
return i;
}
+void
close_all_files()
{
(void) Fclose(fp_head->fp);
}
-register_file(fp, pipe)
+void
+register_file(fp, pipe, pid)
FILE *fp;
+ int pipe, pid;
{
struct fp *fpp;
panic("Out of memory");
fpp->fp = fp;
fpp->pipe = pipe;
+ fpp->pid = pid;
fpp->link = fp_head;
fp_head = fpp;
}
+void
unregister_file(fp)
FILE *fp;
{
free((char *) p);
return;
}
- /* XXX
- * Ignore this for now; there may still be uncaught
- * duplicate closes.
panic("Invalid file pointer");
- */
+}
+
+file_pid(fp)
+ FILE *fp;
+{
+ struct fp *p;
+
+ for (p = fp_head; p; p = p->link)
+ if (p->fp == fp)
+ return (p->pid);
+ panic("Invalid file pointer");
+ /*NOTREACHED*/
}
/*
* SIGINT is enabled unless it's in the mask.
*/
/*VARARGS4*/
+int
run_command(cmd, mask, infd, outfd, a0, a1, a2)
char *cmd;
int mask, infd, outfd;
}
/*VARARGS4*/
+int
start_command(cmd, mask, infd, outfd, a0, a1, a2)
char *cmd;
int mask, infd, outfd;
return pid;
}
+void
prepare_child(mask, infd, outfd)
int mask, infd, outfd;
{
int i;
+ /*
+ * All file descriptors other than 0, 1, and 2 are supposed to be
+ * close-on-exec.
+ */
if (infd >= 0)
dup2(infd, 0);
if (outfd >= 0)
dup2(outfd, 1);
- for (i = getdtablesize(); --i > 2;)
- close(i);
for (i = 1; i <= NSIG; i++)
if (mask & sigmask(i))
(void) signal(i, SIG_IGN);
(void) sigsetmask(0);
}
+int
wait_command(pid)
int pid;
{
return 0;
}
-struct child {
- int pid;
- char done;
- char free;
- union wait status;
- struct child *link;
-};
-static struct child *child;
-
-struct child *
+static struct child *
findchild(pid)
int pid;
{
return *cpp;
}
+static void
delchild(cp)
register struct child *cp;
{
free((char *) cp);
}
-sigchild()
+void
+sigchild(signo)
+ int signo;
{
int pid;
union wait status;
register struct child *cp;
- while ((pid = wait3(&status, WNOHANG, (struct timeval *)0)) > 0) {
+ while ((pid =
+ wait3((int *)&status, WNOHANG, (struct rusage *)0)) > 0) {
cp = findchild(pid);
if (cp->free)
delchild(cp);
/*
* Wait for a specific child to die.
*/
+int
wait_child(pid)
int pid;
{
/*
* Mark a child as don't care.
*/
+void
free_child(pid)
int pid;
{