1 /* 2 * Copyright (c) 1980, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #ifndef lint 35 static char sccsid[] = "from: @(#)popen.c 8.1 (Berkeley) 6/6/93"; 36 static char rcsid[] = "$Id: popen.c,v 1.3 1994/06/29 05:09:38 deraadt Exp $"; 37 #endif /* not lint */ 38 39 #include "rcv.h" 40 #include <sys/wait.h> 41 #include <fcntl.h> 42 #include "extern.h" 43 44 #define READ 0 45 #define WRITE 1 46 47 struct fp { 48 FILE *fp; 49 int pipe; 50 int pid; 51 struct fp *link; 52 }; 53 static struct fp *fp_head; 54 55 struct child { 56 int pid; 57 char done; 58 char free; 59 union wait status; 60 struct child *link; 61 }; 62 static struct child *child; 63 static struct child *findchild __P((int)); 64 static void delchild __P((struct child *)); 65 66 FILE * 67 Fopen(file, mode) 68 char *file, *mode; 69 { 70 FILE *fp; 71 72 if ((fp = fopen(file, mode)) != NULL) { 73 register_file(fp, 0, 0); 74 (void) fcntl(fileno(fp), F_SETFD, 1); 75 } 76 return fp; 77 } 78 79 FILE * 80 Fdopen(fd, mode) 81 int fd; 82 char *mode; 83 { 84 FILE *fp; 85 86 if ((fp = fdopen(fd, mode)) != NULL) { 87 register_file(fp, 0, 0); 88 (void) fcntl(fileno(fp), F_SETFD, 1); 89 } 90 return fp; 91 } 92 93 int 94 Fclose(fp) 95 FILE *fp; 96 { 97 unregister_file(fp); 98 return fclose(fp); 99 } 100 101 FILE * 102 Popen(cmd, mode) 103 char *cmd; 104 char *mode; 105 { 106 int p[2]; 107 int myside, hisside, fd0, fd1; 108 int pid; 109 FILE *fp; 110 111 if (pipe(p) < 0) 112 return NULL; 113 (void) fcntl(p[READ], F_SETFD, 1); 114 (void) fcntl(p[WRITE], F_SETFD, 1); 115 if (*mode == 'r') { 116 myside = p[READ]; 117 fd0 = -1; 118 hisside = fd1 = p[WRITE]; 119 } else { 120 myside = p[WRITE]; 121 hisside = fd0 = p[READ]; 122 fd1 = -1; 123 } 124 if ((pid = start_command(cmd, 0, fd0, fd1, NOSTR, NOSTR, NOSTR)) < 0) { 125 close(p[READ]); 126 close(p[WRITE]); 127 return NULL; 128 } 129 (void) close(hisside); 130 if ((fp = fdopen(myside, mode)) != NULL) 131 register_file(fp, 1, pid); 132 return fp; 133 } 134 135 int 136 Pclose(ptr) 137 FILE *ptr; 138 { 139 int i; 140 int omask; 141 142 i = file_pid(ptr); 143 unregister_file(ptr); 144 (void) fclose(ptr); 145 omask = sigblock(sigmask(SIGINT)|sigmask(SIGHUP)); 146 i = wait_child(i); 147 sigsetmask(omask); 148 return i; 149 } 150 151 void 152 close_all_files() 153 { 154 155 while (fp_head) 156 if (fp_head->pipe) 157 (void) Pclose(fp_head->fp); 158 else 159 (void) Fclose(fp_head->fp); 160 } 161 162 void 163 register_file(fp, pipe, pid) 164 FILE *fp; 165 int pipe, pid; 166 { 167 struct fp *fpp; 168 169 if ((fpp = (struct fp *) malloc(sizeof *fpp)) == NULL) 170 panic("Out of memory"); 171 fpp->fp = fp; 172 fpp->pipe = pipe; 173 fpp->pid = pid; 174 fpp->link = fp_head; 175 fp_head = fpp; 176 } 177 178 void 179 unregister_file(fp) 180 FILE *fp; 181 { 182 struct fp **pp, *p; 183 184 for (pp = &fp_head; p = *pp; pp = &p->link) 185 if (p->fp == fp) { 186 *pp = p->link; 187 free((char *) p); 188 return; 189 } 190 panic("Invalid file pointer"); 191 } 192 193 file_pid(fp) 194 FILE *fp; 195 { 196 struct fp *p; 197 198 for (p = fp_head; p; p = p->link) 199 if (p->fp == fp) 200 return (p->pid); 201 panic("Invalid file pointer"); 202 /*NOTREACHED*/ 203 } 204 205 /* 206 * Run a command without a shell, with optional arguments and splicing 207 * of stdin and stdout. The command name can be a sequence of words. 208 * Signals must be handled by the caller. 209 * "Mask" contains the signals to ignore in the new process. 210 * SIGINT is enabled unless it's in the mask. 211 */ 212 /*VARARGS4*/ 213 int 214 run_command(cmd, mask, infd, outfd, a0, a1, a2) 215 char *cmd; 216 int mask, infd, outfd; 217 char *a0, *a1, *a2; 218 { 219 int pid; 220 221 if ((pid = start_command(cmd, mask, infd, outfd, a0, a1, a2)) < 0) 222 return -1; 223 return wait_command(pid); 224 } 225 226 /*VARARGS4*/ 227 int 228 start_command(cmd, mask, infd, outfd, a0, a1, a2) 229 char *cmd; 230 int mask, infd, outfd; 231 char *a0, *a1, *a2; 232 { 233 int pid; 234 235 if ((pid = vfork()) < 0) { 236 perror("fork"); 237 return -1; 238 } 239 if (pid == 0) { 240 char *argv[100]; 241 int i = getrawlist(cmd, argv, sizeof argv / sizeof *argv); 242 243 if ((argv[i++] = a0) != NOSTR && 244 (argv[i++] = a1) != NOSTR && 245 (argv[i++] = a2) != NOSTR) 246 argv[i] = NOSTR; 247 prepare_child(mask, infd, outfd); 248 execvp(argv[0], argv); 249 perror(argv[0]); 250 _exit(1); 251 } 252 return pid; 253 } 254 255 void 256 prepare_child(mask, infd, outfd) 257 int mask, infd, outfd; 258 { 259 int i; 260 261 /* 262 * All file descriptors other than 0, 1, and 2 are supposed to be 263 * close-on-exec. 264 */ 265 if (infd >= 0) 266 dup2(infd, 0); 267 if (outfd >= 0) 268 dup2(outfd, 1); 269 for (i = 1; i <= NSIG; i++) 270 if (mask & sigmask(i)) 271 (void) signal(i, SIG_IGN); 272 if ((mask & sigmask(SIGINT)) == 0) 273 (void) signal(SIGINT, SIG_DFL); 274 (void) sigsetmask(0); 275 } 276 277 int 278 wait_command(pid) 279 int pid; 280 { 281 282 if (wait_child(pid) < 0) { 283 printf("Fatal error in process.\n"); 284 return -1; 285 } 286 return 0; 287 } 288 289 static struct child * 290 findchild(pid) 291 int pid; 292 { 293 register struct child **cpp; 294 295 for (cpp = &child; *cpp != NULL && (*cpp)->pid != pid; 296 cpp = &(*cpp)->link) 297 ; 298 if (*cpp == NULL) { 299 *cpp = (struct child *) malloc(sizeof (struct child)); 300 (*cpp)->pid = pid; 301 (*cpp)->done = (*cpp)->free = 0; 302 (*cpp)->link = NULL; 303 } 304 return *cpp; 305 } 306 307 static void 308 delchild(cp) 309 register struct child *cp; 310 { 311 register struct child **cpp; 312 313 for (cpp = &child; *cpp != cp; cpp = &(*cpp)->link) 314 ; 315 *cpp = cp->link; 316 free((char *) cp); 317 } 318 319 void 320 sigchild(signo) 321 int signo; 322 { 323 int pid; 324 union wait status; 325 register struct child *cp; 326 327 while ((pid = 328 wait3((int *)&status, WNOHANG, (struct rusage *)0)) > 0) { 329 cp = findchild(pid); 330 if (cp->free) 331 delchild(cp); 332 else { 333 cp->done = 1; 334 cp->status = status; 335 } 336 } 337 } 338 339 union wait wait_status; 340 341 /* 342 * Wait for a specific child to die. 343 */ 344 int 345 wait_child(pid) 346 int pid; 347 { 348 int mask = sigblock(sigmask(SIGCHLD)); 349 register struct child *cp = findchild(pid); 350 351 while (!cp->done) 352 sigpause(mask); 353 wait_status = cp->status; 354 delchild(cp); 355 sigsetmask(mask); 356 return wait_status.w_status ? -1 : 0; 357 } 358 359 /* 360 * Mark a child as don't care. 361 */ 362 void 363 free_child(pid) 364 int pid; 365 { 366 int mask = sigblock(sigmask(SIGCHLD)); 367 register struct child *cp = findchild(pid); 368 369 if (cp->done) 370 delchild(cp); 371 else 372 cp->free = 1; 373 sigsetmask(mask); 374 } 375