1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* Copyright (c) 1988 AT&T */ 23 /* All Rights Reserved */ 24 25 26 /* 27 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 28 * Use is subject to license terms. 29 */ 30 31 #pragma ident "%Z%%M% %I% %E% SMI" 32 33 /* 34 * cscope - interactive C symbol cross-reference 35 * 36 * process execution functions 37 */ 38 39 #include "global.h" 40 #include <sys/types.h> 41 #include <sys/wait.h> 42 #include <stdarg.h> 43 #include <unistd.h> 44 #include <stdlib.h> 45 #include <stdio.h> 46 #include <libgen.h> 47 48 #define getdtablesize() _NFILE 49 50 #define MAXARGS 100 /* maximum number of arguments to executed command */ 51 52 pid_t childpid; /* child's process ID */ 53 54 static SIGTYPE (*oldsigquit)(); /* old value of quit signal */ 55 static SIGTYPE (*oldsigtstp)(); /* old value of terminal stop signal */ 56 57 static pid_t myfork(void); 58 static int join(pid_t p); 59 60 /* 61 * execute forks and executes a program or shell script, waits for it to 62 * finish, and returns its exit code. 63 */ 64 65 /*VARARGS0*/ 66 int 67 execute(char *path, ...) 68 { 69 va_list ap; 70 char *args[MAXARGS + 1]; 71 int exitcode; 72 int i; 73 char msg[MSGLEN + 1]; 74 pid_t p; 75 76 /* fork and exec the program or shell script */ 77 exitcurses(); 78 if ((p = myfork()) == 0) { 79 80 /* close all files except stdin, stdout, and stderr */ 81 for (i = 3; i < getdtablesize() && close(i) == 0; ++i) { 82 ; 83 } 84 /* execute the program or shell script */ 85 va_start(ap, path); 86 for (i = 0; i < MAXARGS && 87 (args[i] = va_arg(ap, char *)) != NULL; ++i) { 88 } 89 va_end(ap); 90 args[i] = NULL; /* in case MAXARGS reached */ 91 args[0] = basename(args[0]); 92 (void) execvp(path, args); /* returns only on failure */ 93 (void) sprintf(msg, "\ncscope: cannot execute %s", path); 94 (void) perror(msg); /* display the reason */ 95 askforreturn(); /* wait until the user sees the message */ 96 exit(1); /* exit the child */ 97 } else { 98 exitcode = join(p); /* parent */ 99 } 100 if (noacttimeout) { 101 (void) fprintf(stderr, 102 "cscope: no activity time out--exiting\n"); 103 myexit(SIGALRM); 104 } 105 entercurses(); 106 return (exitcode); 107 } 108 109 /* myfork acts like fork but also handles signals */ 110 111 static pid_t 112 myfork(void) 113 { 114 pid_t p; /* process number */ 115 116 oldsigtstp = signal(SIGTSTP, SIG_DFL); 117 /* the parent ignores the interrupt and quit signals */ 118 if ((p = fork()) > 0) { 119 childpid = p; 120 oldsigquit = signal(SIGQUIT, SIG_IGN); 121 } 122 /* so they can be used to stop the child */ 123 else if (p == 0) { 124 (void) signal(SIGINT, SIG_DFL); 125 (void) signal(SIGQUIT, SIG_DFL); 126 (void) signal(SIGHUP, SIG_DFL); /* restore hangup default */ 127 } 128 /* check for fork failure */ 129 if (p == -1) { 130 myperror("Cannot fork"); 131 } 132 return (p); 133 } 134 135 /* join is the compliment of fork */ 136 137 static int 138 join(pid_t p) 139 { 140 int status; 141 pid_t w; 142 143 /* wait for the correct child to exit */ 144 do { 145 w = wait(&status); 146 } while (p != -1 && w != p); 147 childpid = 0; 148 149 /* restore signal handling */ 150 (void) signal(SIGQUIT, oldsigquit); 151 (void) signal(SIGTSTP, oldsigtstp); 152 /* return the child's exit code */ 153 return (status >> 8); 154 } 155