grab wtmp path from utmp.h
[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 *
8 * Redistribution and use in source and binary forms are permitted
9 * provided that the above copyright notice and this paragraph are
10 * duplicated in all such forms and that any documentation,
11 * advertising materials, and other materials related to such
12 * distribution and use acknowledge that the software was developed
13 * by the University of California, Berkeley. The name of the
14 * University may not be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
2482fd41 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
96c0abd0 19 *
96c0abd0
KB
20 */
21
22#ifndef lint
2482fd41 23static char sccsid[] = "@(#)popen.c 5.7 (Berkeley) %G%";
96c0abd0
KB
24#endif /* not lint */
25
5f3a5fe7 26#include <sys/types.h>
96c0abd0 27#include <sys/signal.h>
882508af 28#include <sys/wait.h>
96c0abd0
KB
29#include <stdio.h>
30
5f3a5fe7
KB
31/*
32 * Special version of popen which avoids call to shell. This insures noone
33 * may create a pipe to a hidden program as a side effect of a list or dir
34 * command.
35 */
882508af 36static int *pids;
96c0abd0
KB
37static int fds;
38
39FILE *
5256bbac 40ftpd_popen(program, type)
96c0abd0
KB
41 char *program, *type;
42{
5f3a5fe7 43 register char *cp;
96c0abd0 44 FILE *iop;
5f3a5fe7
KB
45 int argc, gargc, pdes[2], pid;
46 char **pop, *argv[100], *gargv[1000], *vv[2];
882508af 47 extern char **glob(), **copyblk(), *strtok(), *malloc();
96c0abd0
KB
48
49 if (*type != 'r' && *type != 'w' || type[1])
50 return(NULL);
51
52 if (!pids) {
53 if ((fds = getdtablesize()) <= 0)
54 return(NULL);
882508af 55 if ((pids = (int *)malloc((u_int)(fds * sizeof(int)))) == NULL)
96c0abd0 56 return(NULL);
882508af 57 bzero((char *)pids, fds * sizeof(int));
96c0abd0
KB
58 }
59 if (pipe(pdes) < 0)
60 return(NULL);
5f3a5fe7
KB
61
62 /* break up string into pieces */
63 for (argc = 0, cp = program;; cp = NULL)
64 if (!(argv[argc++] = strtok(cp, " \t\n")))
65 break;
66
67 /* glob each piece */
68 gargv[0] = argv[0];
69 for (gargc = argc = 1; argv[argc]; argc++) {
70 if (!(pop = glob(argv[argc]))) { /* globbing failed */
71 vv[0] = argv[argc];
72 vv[1] = NULL;
73 pop = copyblk(vv);
74 }
75 argv[argc] = (char *)pop; /* save to free later */
76 while (*pop && gargc < 1000)
77 gargv[gargc++] = *pop++;
78 }
79 gargv[gargc] = NULL;
80
81 iop = NULL;
96c0abd0
KB
82 switch(pid = vfork()) {
83 case -1: /* error */
84 (void)close(pdes[0]);
85 (void)close(pdes[1]);
97f47643 86 goto pfree;
96c0abd0
KB
87 /* NOTREACHED */
88 case 0: /* child */
89 if (*type == 'r') {
90 if (pdes[1] != 1) {
91 dup2(pdes[1], 1);
f8086b89 92 dup2(pdes[1], 2); /* stderr, too! */
96c0abd0
KB
93 (void)close(pdes[1]);
94 }
95 (void)close(pdes[0]);
96 } else {
97 if (pdes[0] != 0) {
98 dup2(pdes[0], 0);
99 (void)close(pdes[0]);
100 }
101 (void)close(pdes[1]);
102 }
5f3a5fe7
KB
103 execv(gargv[0], gargv);
104 _exit(1);
96c0abd0
KB
105 }
106 /* parent; assume fdopen can't fail... */
107 if (*type == 'r') {
108 iop = fdopen(pdes[0], type);
109 (void)close(pdes[1]);
110 } else {
111 iop = fdopen(pdes[1], type);
112 (void)close(pdes[0]);
113 }
114 pids[fileno(iop)] = pid;
5f3a5fe7 115
97f47643 116pfree: for (argc = 1; argv[argc] != NULL; argc++) {
5f3a5fe7 117 blkfree((char **)argv[argc]);
97f47643
KB
118 free((char *)argv[argc]);
119 }
96c0abd0
KB
120 return(iop);
121}
122
882508af 123ftpd_pclose(iop)
96c0abd0
KB
124 FILE *iop;
125{
126 register int fdes;
882508af
MK
127 int omask;
128 union wait stat_loc;
129 int pid;
96c0abd0
KB
130
131 /*
132 * pclose returns -1 if stream is not associated with a
133 * `popened' command, or, if already `pclosed'.
134 */
882508af 135 if (pids == 0 || pids[fdes = fileno(iop)] == 0)
96c0abd0
KB
136 return(-1);
137 (void)fclose(iop);
138 omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
5f3a5fe7 139 while ((pid = wait(&stat_loc)) != pids[fdes] && pid != -1);
96c0abd0
KB
140 (void)sigsetmask(omask);
141 pids[fdes] = 0;
882508af 142 return(pid == -1 ? -1 : stat_loc.w_status);
96c0abd0 143}