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
execute(char * path,...)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
myfork(void)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
join(pid_t p)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