added field name q_ruser; need to update NullAddress
[unix-history] / usr / src / libexec / ftpd / popen.c
CommitLineData
96c0abd0
KB
1/*
2 * Copyright (c) 1988 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software written by Ken Arnold and
6 * published in UNIX Review, Vol. 6, No. 8.
7 *
1343342a 8 * %sccs.include.redist.c%
96c0abd0 9 *
96c0abd0
KB
10 */
11
12#ifndef lint
1343342a 13static char sccsid[] = "@(#)popen.c 5.8 (Berkeley) %G%";
96c0abd0
KB
14#endif /* not lint */
15
5f3a5fe7 16#include <sys/types.h>
96c0abd0 17#include <sys/signal.h>
882508af 18#include <sys/wait.h>
96c0abd0
KB
19#include <stdio.h>
20
5f3a5fe7
KB
21/*
22 * Special version of popen which avoids call to shell. This insures noone
23 * may create a pipe to a hidden program as a side effect of a list or dir
24 * command.
25 */
882508af 26static int *pids;
96c0abd0
KB
27static int fds;
28
29FILE *
5256bbac 30ftpd_popen(program, type)
96c0abd0
KB
31 char *program, *type;
32{
5f3a5fe7 33 register char *cp;
96c0abd0 34 FILE *iop;
5f3a5fe7
KB
35 int argc, gargc, pdes[2], pid;
36 char **pop, *argv[100], *gargv[1000], *vv[2];
882508af 37 extern char **glob(), **copyblk(), *strtok(), *malloc();
96c0abd0
KB
38
39 if (*type != 'r' && *type != 'w' || type[1])
40 return(NULL);
41
42 if (!pids) {
43 if ((fds = getdtablesize()) <= 0)
44 return(NULL);
882508af 45 if ((pids = (int *)malloc((u_int)(fds * sizeof(int)))) == NULL)
96c0abd0 46 return(NULL);
882508af 47 bzero((char *)pids, fds * sizeof(int));
96c0abd0
KB
48 }
49 if (pipe(pdes) < 0)
50 return(NULL);
5f3a5fe7
KB
51
52 /* break up string into pieces */
53 for (argc = 0, cp = program;; cp = NULL)
54 if (!(argv[argc++] = strtok(cp, " \t\n")))
55 break;
56
57 /* glob each piece */
58 gargv[0] = argv[0];
59 for (gargc = argc = 1; argv[argc]; argc++) {
60 if (!(pop = glob(argv[argc]))) { /* globbing failed */
61 vv[0] = argv[argc];
62 vv[1] = NULL;
63 pop = copyblk(vv);
64 }
65 argv[argc] = (char *)pop; /* save to free later */
66 while (*pop && gargc < 1000)
67 gargv[gargc++] = *pop++;
68 }
69 gargv[gargc] = NULL;
70
71 iop = NULL;
96c0abd0
KB
72 switch(pid = vfork()) {
73 case -1: /* error */
74 (void)close(pdes[0]);
75 (void)close(pdes[1]);
97f47643 76 goto pfree;
96c0abd0
KB
77 /* NOTREACHED */
78 case 0: /* child */
79 if (*type == 'r') {
80 if (pdes[1] != 1) {
81 dup2(pdes[1], 1);
f8086b89 82 dup2(pdes[1], 2); /* stderr, too! */
96c0abd0
KB
83 (void)close(pdes[1]);
84 }
85 (void)close(pdes[0]);
86 } else {
87 if (pdes[0] != 0) {
88 dup2(pdes[0], 0);
89 (void)close(pdes[0]);
90 }
91 (void)close(pdes[1]);
92 }
5f3a5fe7
KB
93 execv(gargv[0], gargv);
94 _exit(1);
96c0abd0
KB
95 }
96 /* parent; assume fdopen can't fail... */
97 if (*type == 'r') {
98 iop = fdopen(pdes[0], type);
99 (void)close(pdes[1]);
100 } else {
101 iop = fdopen(pdes[1], type);
102 (void)close(pdes[0]);
103 }
104 pids[fileno(iop)] = pid;
5f3a5fe7 105
97f47643 106pfree: for (argc = 1; argv[argc] != NULL; argc++) {
5f3a5fe7 107 blkfree((char **)argv[argc]);
97f47643
KB
108 free((char *)argv[argc]);
109 }
96c0abd0
KB
110 return(iop);
111}
112
882508af 113ftpd_pclose(iop)
96c0abd0
KB
114 FILE *iop;
115{
116 register int fdes;
882508af
MK
117 int omask;
118 union wait stat_loc;
119 int pid;
96c0abd0
KB
120
121 /*
122 * pclose returns -1 if stream is not associated with a
123 * `popened' command, or, if already `pclosed'.
124 */
882508af 125 if (pids == 0 || pids[fdes = fileno(iop)] == 0)
96c0abd0
KB
126 return(-1);
127 (void)fclose(iop);
128 omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
5f3a5fe7 129 while ((pid = wait(&stat_loc)) != pids[fdes] && pid != -1);
96c0abd0
KB
130 (void)sigsetmask(omask);
131 pids[fdes] = 0;
882508af 132 return(pid == -1 ? -1 : stat_loc.w_status);
96c0abd0 133}