version 1.28, 2001/11/20 23:19:44 |
version 1.29, 2001/11/21 15:26:39 |
|
|
|
|
#ifndef lint |
#ifndef lint |
#if 0 |
#if 0 |
static char sccsid[] = "@(#)popen.c 8.1 (Berkeley) 6/6/93"; |
static const char sccsid[] = "@(#)popen.c 8.1 (Berkeley) 6/6/93"; |
#else |
#else |
static char rcsid[] = "$OpenBSD$"; |
static const char rcsid[] = "$OpenBSD$"; |
#endif |
#endif |
#endif /* not lint */ |
#endif /* not lint */ |
|
|
|
|
#include <sys/wait.h> |
#include <sys/wait.h> |
#include <fcntl.h> |
#include <fcntl.h> |
#include <errno.h> |
#include <errno.h> |
#ifdef __STDC__ |
|
#include <stdarg.h> |
#include <stdarg.h> |
#else |
|
#include <varargs.h> |
|
#endif |
|
#include "extern.h" |
#include "extern.h" |
|
|
#define READ 0 |
#define READ 0 |
|
|
struct fp { |
struct fp { |
FILE *fp; |
FILE *fp; |
int pipe; |
int pipe; |
int pid; |
pid_t pid; |
struct fp *link; |
struct fp *link; |
}; |
}; |
static struct fp *fp_head; |
static struct fp *fp_head; |
|
|
struct child { |
struct child { |
int pid; |
pid_t pid; |
char done; |
char done; |
char free; |
char free; |
int status; |
int status; |
struct child *link; |
struct child *link; |
}; |
}; |
static struct child *child, *child_freelist = NULL; |
static struct child *child, *child_freelist = NULL; |
static struct child *findchild __P((int, int)); |
|
static void delchild __P((struct child *)); |
|
static int file_pid __P((FILE *)); |
|
static int handle_spool_locks __P((int)); |
|
|
|
|
static struct child *findchild(pid_t, int); |
|
static void delchild(struct child *); |
|
static pid_t file_pid(FILE *); |
|
static int handle_spool_locks(int); |
|
|
FILE * |
FILE * |
Fopen(file, mode) |
Fopen(char *file, char *mode) |
char *file, *mode; |
|
{ |
{ |
FILE *fp; |
FILE *fp; |
|
|
|
|
} |
} |
|
|
FILE * |
FILE * |
Fdopen(fd, mode) |
Fdopen(int fd, char *mode) |
int fd; |
|
char *mode; |
|
{ |
{ |
FILE *fp; |
FILE *fp; |
|
|
|
|
} |
} |
|
|
int |
int |
Fclose(fp) |
Fclose(FILE *fp) |
FILE *fp; |
|
{ |
{ |
|
|
unregister_file(fp); |
unregister_file(fp); |
return(fclose(fp)); |
return(fclose(fp)); |
} |
} |
|
|
FILE * |
FILE * |
Popen(cmd, mode) |
Popen(char *cmd, char *mode) |
char *cmd; |
|
char *mode; |
|
{ |
{ |
int p[2]; |
int p[2]; |
int myside, hisside, fd0, fd1; |
int myside, hisside, fd0, fd1; |
int pid; |
pid_t pid; |
sigset_t nset; |
sigset_t nset; |
FILE *fp; |
FILE *fp; |
|
|
|
|
} |
} |
|
|
int |
int |
Pclose(ptr) |
Pclose(FILE *ptr) |
FILE *ptr; |
|
{ |
{ |
int i; |
int i; |
sigset_t nset, oset; |
sigset_t nset, oset; |
|
|
} |
} |
|
|
void |
void |
close_all_files() |
close_all_files(void) |
{ |
{ |
|
|
while (fp_head) |
while (fp_head) |
|
|
} |
} |
|
|
void |
void |
register_file(fp, pipe, pid) |
register_file(FILE *fp, int pipe, pid_t pid) |
FILE *fp; |
|
int pipe, pid; |
|
{ |
{ |
struct fp *fpp; |
struct fp *fpp; |
|
|
|
|
} |
} |
|
|
void |
void |
unregister_file(fp) |
unregister_file(FILE *fp) |
FILE *fp; |
|
{ |
{ |
struct fp **pp, *p; |
struct fp **pp, *p; |
|
|
|
|
errx(1, "Invalid file pointer"); |
errx(1, "Invalid file pointer"); |
} |
} |
|
|
static int |
static pid_t |
file_pid(fp) |
file_pid(FILE *fp) |
FILE *fp; |
|
{ |
{ |
struct fp *p; |
struct fp *p; |
|
|
|
|
* "nset" contains the signals to ignore in the new process. |
* "nset" contains the signals to ignore in the new process. |
* SIGINT is enabled unless it's in "nset". |
* SIGINT is enabled unless it's in "nset". |
*/ |
*/ |
int |
pid_t |
start_commandv(cmd, nset, infd, outfd, args) |
start_commandv(char *cmd, sigset_t *nset, int infd, int outfd, va_list args) |
char *cmd; |
|
sigset_t *nset; |
|
int infd, outfd; |
|
va_list args; |
|
{ |
{ |
int pid; |
pid_t pid; |
|
|
if ((pid = fork()) < 0) { |
if ((pid = fork()) < 0) { |
warn("fork"); |
warn("fork"); |
|
|
} |
} |
|
|
int |
int |
#ifdef __STDC__ |
|
run_command(char *cmd, sigset_t *nset, int infd, int outfd, ...) |
run_command(char *cmd, sigset_t *nset, int infd, int outfd, ...) |
#else |
|
run_command(cmd, nset, infd, outfd, va_alist) |
|
char *cmd; |
|
sigset_t *nset; |
|
int infd; |
|
int outfd; |
|
va_dcl |
|
#endif |
|
{ |
{ |
int pid; |
pid_t pid; |
va_list args; |
va_list args; |
|
|
#ifdef __STDC__ |
|
va_start(args, outfd); |
va_start(args, outfd); |
#else |
|
va_start(args); |
|
#endif |
|
pid = start_commandv(cmd, nset, infd, outfd, args); |
pid = start_commandv(cmd, nset, infd, outfd, args); |
va_end(args); |
va_end(args); |
if (pid < 0) |
if (pid < 0) |
|
|
} |
} |
|
|
int |
int |
#ifdef __STDC__ |
|
start_command(char *cmd, sigset_t *nset, int infd, int outfd, ...) |
start_command(char *cmd, sigset_t *nset, int infd, int outfd, ...) |
#else |
|
start_command(cmd, nset, infd, outfd, va_alist) |
|
char *cmd; |
|
sigset_t *nset; |
|
int infd; |
|
int outfd; |
|
va_dcl |
|
#endif |
|
{ |
{ |
va_list args; |
va_list args; |
int r; |
int r; |
|
|
#ifdef __STDC__ |
|
va_start(args, outfd); |
va_start(args, outfd); |
#else |
|
va_start(args); |
|
#endif |
|
r = start_commandv(cmd, nset, infd, outfd, args); |
r = start_commandv(cmd, nset, infd, outfd, args); |
va_end(args); |
va_end(args); |
return(r); |
return(r); |
} |
} |
|
|
void |
void |
prepare_child(nset, infd, outfd) |
prepare_child(sigset_t *nset, int infd, int outfd) |
sigset_t *nset; |
|
int infd, outfd; |
|
{ |
{ |
int i; |
int i; |
sigset_t eset; |
sigset_t eset; |
|
|
} |
} |
|
|
int |
int |
wait_command(pid) |
wait_command(pid_t pid) |
int pid; |
|
{ |
{ |
|
|
if (wait_child(pid) < 0) { |
if (wait_child(pid) < 0) { |
|
|
} |
} |
|
|
static struct child * |
static struct child * |
findchild(pid, dont_alloc) |
findchild(pid_t pid, int dont_alloc) |
int pid; |
|
int dont_alloc; |
|
{ |
{ |
struct child **cpp; |
struct child **cpp; |
|
|
|
|
} |
} |
|
|
static void |
static void |
delchild(cp) |
delchild(struct child *cp) |
struct child *cp; |
|
{ |
{ |
struct child **cpp; |
struct child **cpp; |
|
|
|
|
} |
} |
|
|
void |
void |
sigchild(signo) |
sigchild(int signo) |
int signo; |
|
{ |
{ |
int pid; |
pid_t pid; |
int status; |
int status; |
struct child *cp; |
struct child *cp; |
int save_errno = errno; |
int save_errno = errno; |
|
|
* Wait for a specific child to die. |
* Wait for a specific child to die. |
*/ |
*/ |
int |
int |
wait_child(pid) |
wait_child(pid_t pid) |
int pid; |
|
{ |
{ |
struct child *cp; |
struct child *cp; |
sigset_t nset, oset; |
sigset_t nset, oset; |
|
|
* Mark a child as don't care. |
* Mark a child as don't care. |
*/ |
*/ |
void |
void |
free_child(pid) |
free_child(pid_t pid) |
int pid; |
|
{ |
{ |
struct child *cp; |
struct child *cp; |
sigset_t nset, oset; |
sigset_t nset, oset; |
|
|
* Returns 1 for success, 0 for failure, -1 for bad usage. |
* Returns 1 for success, 0 for failure, -1 for bad usage. |
*/ |
*/ |
static int |
static int |
handle_spool_locks(action) |
handle_spool_locks(int action) |
int action; |
|
{ |
{ |
static FILE *lockfp = NULL; |
static FILE *lockfp = NULL; |
static int lock_pid; |
static pid_t lock_pid; |
|
|
if (action == 0) { |
if (action == 0) { |
/* Clear the lock */ |
/* Clear the lock */ |
|
|
} |
} |
|
|
int |
int |
spool_lock() |
spool_lock(void) |
{ |
{ |
|
|
return(handle_spool_locks(1)); |
return(handle_spool_locks(1)); |
} |
} |
|
|
int |
int |
spool_unlock() |
spool_unlock(void) |
{ |
{ |
|
|
return(handle_spool_locks(0)); |
return(handle_spool_locks(0)); |
} |
} |