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 /* 32 * cscope - interactive C symbol cross-reference 33 * 34 * process execution functions 35 */ 36 37 #include "global.h" 38 #include <sys/types.h> 39 #include <sys/wait.h> 40 #include <stdarg.h> 41 #include <unistd.h> 42 #include <stdlib.h> 43 #include <stdio.h> 44 #include <libgen.h> 45 46 #define getdtablesize() _NFILE 47 48 #define MAXARGS 100 /* maximum number of arguments to executed command */ 49 50 pid_t childpid; /* child's process ID */ 51 52 static SIGTYPE (*oldsigquit)(); /* old value of quit signal */ 53 static SIGTYPE (*oldsigtstp)(); /* old value of terminal stop signal */ 54 55 static pid_t myfork(void); 56 static int join(pid_t p); 57 58 /* 59 * execute forks and executes a program or shell script, waits for it to 60 * finish, and returns its exit code. 61 */ 62 63 /*VARARGS0*/ 64 int 65 execute(char *path, ...) 66 { 67 va_list ap; 68 char *args[MAXARGS + 1]; 69 int exitcode; 70 int i; 71 char msg[MSGLEN + 1]; 72 pid_t p; 73 74 /* fork and exec the program or shell script */ 75 exitcurses(); 76 if ((p = myfork()) == 0) { 77 78 /* close all files except stdin, stdout, and stderr */ 79 for (i = 3; i < getdtablesize() && close(i) == 0; ++i) { 80 ; 81 } 82 /* execute the program or shell script */ 83 va_start(ap, path); 84 for (i = 0; i < MAXARGS && 85 (args[i] = va_arg(ap, char *)) != NULL; ++i) { 86 } 87 va_end(ap); 88 args[i] = NULL; /* in case MAXARGS reached */ 89 args[0] = basename(args[0]); 90 (void) execvp(path, args); /* returns only on failure */ 91 (void) sprintf(msg, "\ncscope: cannot execute %s", path); 92 (void) perror(msg); /* display the reason */ 93 askforreturn(); /* wait until the user sees the message */ 94 exit(1); /* exit the child */ 95 } else { 96 exitcode = join(p); /* parent */ 97 } 98 if (noacttimeout) { 99 (void) fprintf(stderr, 100 "cscope: no activity time out--exiting\n"); 101 myexit(SIGALRM); 102 } 103 entercurses(); 104 return (exitcode); 105 } 106 107 /* myfork acts like fork but also handles signals */ 108 109 static pid_t 110 myfork(void) 111 { 112 pid_t p; /* process number */ 113 114 oldsigtstp = signal(SIGTSTP, SIG_DFL); 115 /* the parent ignores the interrupt and quit signals */ 116 if ((p = fork()) > 0) { 117 childpid = p; 118 oldsigquit = signal(SIGQUIT, SIG_IGN); 119 } 120 /* so they can be used to stop the child */ 121 else if (p == 0) { 122 (void) signal(SIGINT, SIG_DFL); 123 (void) signal(SIGQUIT, SIG_DFL); 124 (void) signal(SIGHUP, SIG_DFL); /* restore hangup default */ 125 } 126 /* check for fork failure */ 127 if (p == -1) { 128 myperror("Cannot fork"); 129 } 130 return (p); 131 } 132 133 /* join is the compliment of fork */ 134 135 static int 136 join(pid_t p) 137 { 138 int status; 139 pid_t w; 140 141 /* wait for the correct child to exit */ 142 do { 143 w = wait(&status); 144 } while (p != -1 && w != p); 145 childpid = 0; 146 147 /* restore signal handling */ 148 (void) signal(SIGQUIT, oldsigquit); 149 (void) signal(SIGTSTP, oldsigtstp); 150 /* return the child's exit code */ 151 return (status >> 8); 152 } 153