1*9781SMoriah.Waterland@Sun.COM /*
2*9781SMoriah.Waterland@Sun.COM * CDDL HEADER START
3*9781SMoriah.Waterland@Sun.COM *
4*9781SMoriah.Waterland@Sun.COM * The contents of this file are subject to the terms of the
5*9781SMoriah.Waterland@Sun.COM * Common Development and Distribution License (the "License").
6*9781SMoriah.Waterland@Sun.COM * You may not use this file except in compliance with the License.
7*9781SMoriah.Waterland@Sun.COM *
8*9781SMoriah.Waterland@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*9781SMoriah.Waterland@Sun.COM * or http://www.opensolaris.org/os/licensing.
10*9781SMoriah.Waterland@Sun.COM * See the License for the specific language governing permissions
11*9781SMoriah.Waterland@Sun.COM * and limitations under the License.
12*9781SMoriah.Waterland@Sun.COM *
13*9781SMoriah.Waterland@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
14*9781SMoriah.Waterland@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*9781SMoriah.Waterland@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
16*9781SMoriah.Waterland@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
17*9781SMoriah.Waterland@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
18*9781SMoriah.Waterland@Sun.COM *
19*9781SMoriah.Waterland@Sun.COM * CDDL HEADER END
20*9781SMoriah.Waterland@Sun.COM */
21*9781SMoriah.Waterland@Sun.COM
22*9781SMoriah.Waterland@Sun.COM /*
23*9781SMoriah.Waterland@Sun.COM * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24*9781SMoriah.Waterland@Sun.COM * Use is subject to license terms.
25*9781SMoriah.Waterland@Sun.COM */
26*9781SMoriah.Waterland@Sun.COM
27*9781SMoriah.Waterland@Sun.COM /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28*9781SMoriah.Waterland@Sun.COM /* All Rights Reserved */
29*9781SMoriah.Waterland@Sun.COM
30*9781SMoriah.Waterland@Sun.COM
31*9781SMoriah.Waterland@Sun.COM #include <stdio.h>
32*9781SMoriah.Waterland@Sun.COM #include <errno.h>
33*9781SMoriah.Waterland@Sun.COM #include <string.h>
34*9781SMoriah.Waterland@Sun.COM #include <stdlib.h>
35*9781SMoriah.Waterland@Sun.COM #include <unistd.h>
36*9781SMoriah.Waterland@Sun.COM #include <signal.h>
37*9781SMoriah.Waterland@Sun.COM #include <wait.h>
38*9781SMoriah.Waterland@Sun.COM #include <sys/types.h>
39*9781SMoriah.Waterland@Sun.COM #include <sys/stat.h>
40*9781SMoriah.Waterland@Sun.COM #include <fcntl.h>
41*9781SMoriah.Waterland@Sun.COM #include <pwd.h>
42*9781SMoriah.Waterland@Sun.COM #include <grp.h>
43*9781SMoriah.Waterland@Sun.COM #include "pkglib.h"
44*9781SMoriah.Waterland@Sun.COM #include "pkglibmsgs.h"
45*9781SMoriah.Waterland@Sun.COM #include "pkglocale.h"
46*9781SMoriah.Waterland@Sun.COM
47*9781SMoriah.Waterland@Sun.COM /* global environment inherited by this process */
48*9781SMoriah.Waterland@Sun.COM extern char **environ;
49*9781SMoriah.Waterland@Sun.COM
50*9781SMoriah.Waterland@Sun.COM /* dstream.c */
51*9781SMoriah.Waterland@Sun.COM extern int ds_curpartcnt;
52*9781SMoriah.Waterland@Sun.COM extern int ds_close(int pkgendflg);
53*9781SMoriah.Waterland@Sun.COM
54*9781SMoriah.Waterland@Sun.COM /*
55*9781SMoriah.Waterland@Sun.COM * global internal (private) variables
56*9781SMoriah.Waterland@Sun.COM */
57*9781SMoriah.Waterland@Sun.COM
58*9781SMoriah.Waterland@Sun.COM /* received signal count - bumped with hooked signals are caught */
59*9781SMoriah.Waterland@Sun.COM
60*9781SMoriah.Waterland@Sun.COM static int sig_received = 0;
61*9781SMoriah.Waterland@Sun.COM
62*9781SMoriah.Waterland@Sun.COM /*
63*9781SMoriah.Waterland@Sun.COM * Name: sig_trap
64*9781SMoriah.Waterland@Sun.COM * Description: hooked up to signal counts number of signals received
65*9781SMoriah.Waterland@Sun.COM * Arguments: a_signo - [RO, *RO] - (int)
66*9781SMoriah.Waterland@Sun.COM * Integer representing the signal received; see signal(3c)
67*9781SMoriah.Waterland@Sun.COM * Returns: <void>
68*9781SMoriah.Waterland@Sun.COM */
69*9781SMoriah.Waterland@Sun.COM
70*9781SMoriah.Waterland@Sun.COM static void
sig_trap(int a_signo)71*9781SMoriah.Waterland@Sun.COM sig_trap(int a_signo)
72*9781SMoriah.Waterland@Sun.COM {
73*9781SMoriah.Waterland@Sun.COM sig_received++;
74*9781SMoriah.Waterland@Sun.COM }
75*9781SMoriah.Waterland@Sun.COM
76*9781SMoriah.Waterland@Sun.COM /*
77*9781SMoriah.Waterland@Sun.COM * Name: pkgexecv
78*9781SMoriah.Waterland@Sun.COM * Description: Asynchronously execute a package command in a separate process
79*9781SMoriah.Waterland@Sun.COM * and return results - the subprocess MUST arm it's own SIGINT
80*9781SMoriah.Waterland@Sun.COM * and SIGHUP signals and must return a standard package command
81*9781SMoriah.Waterland@Sun.COM * exit code (see returns below)
82*9781SMoriah.Waterland@Sun.COM * Only another package command (such as pkginstall, pkgremove,
83*9781SMoriah.Waterland@Sun.COM * etc.) may be called via this interface. No files are closed
84*9781SMoriah.Waterland@Sun.COM * because open files are passed across to certain commands using
85*9781SMoriah.Waterland@Sun.COM * either implicit agreements between the two (yuk!) or by using
86*9781SMoriah.Waterland@Sun.COM * the '-p' option which passes a string of digits, some of which
87*9781SMoriah.Waterland@Sun.COM * represent open file descriptors passed through this interface!
88*9781SMoriah.Waterland@Sun.COM * Arguments: filein - [RO, *RO] - (char *)
89*9781SMoriah.Waterland@Sun.COM * Pointer to string representing the name of the file to
90*9781SMoriah.Waterland@Sun.COM * use for the package commands's stdin
91*9781SMoriah.Waterland@Sun.COM * == (char *)NULL or == "" - the current stdin
92*9781SMoriah.Waterland@Sun.COM * is used for the new package command process
93*9781SMoriah.Waterland@Sun.COM * fileout - [RO, *RO] - (char *)
94*9781SMoriah.Waterland@Sun.COM * Pointer to string representing the name of the file to
95*9781SMoriah.Waterland@Sun.COM * use for the package commands's stdout and stderr
96*9781SMoriah.Waterland@Sun.COM * == (char *)NULL or == "" - the current stdout/stderr
97*9781SMoriah.Waterland@Sun.COM * is used for the new package command process
98*9781SMoriah.Waterland@Sun.COM * uname - [RO, *RO] - (char *)
99*9781SMoriah.Waterland@Sun.COM * Pointer to string representing the user name to execute
100*9781SMoriah.Waterland@Sun.COM * the package command as - the user name is looked up
101*9781SMoriah.Waterland@Sun.COM * using the ncgrpw:cpwnam() interface
102*9781SMoriah.Waterland@Sun.COM * == (char *)NULL or == "" - the user name of the current
103*9781SMoriah.Waterland@Sun.COM * process is used for the new package command process
104*9781SMoriah.Waterland@Sun.COM * gname - [RO, *RO] - (char *)
105*9781SMoriah.Waterland@Sun.COM * Pointer to string representing the group name to execute
106*9781SMoriah.Waterland@Sun.COM * the package command as - the group name is looked up
107*9781SMoriah.Waterland@Sun.COM * using the ncgrpw:cgrnam() interface
108*9781SMoriah.Waterland@Sun.COM * == (char *)NULL or == "" - the group name of the current
109*9781SMoriah.Waterland@Sun.COM * process is used for the new package command process
110*9781SMoriah.Waterland@Sun.COM * arg - [RO, *RO] - (char **)
111*9781SMoriah.Waterland@Sun.COM * Pointer to array of character pointers representing the
112*9781SMoriah.Waterland@Sun.COM * arguments to pass to the package command - the array is
113*9781SMoriah.Waterland@Sun.COM * terminated with a pointer to (char *)NULL
114*9781SMoriah.Waterland@Sun.COM * Returns: int
115*9781SMoriah.Waterland@Sun.COM * == 99 - exec() of package command failed
116*9781SMoriah.Waterland@Sun.COM * == -1 - fork failed or other fatal error during
117*9781SMoriah.Waterland@Sun.COM * execution of the package command
118*9781SMoriah.Waterland@Sun.COM * otherwise - exit code from package command:
119*9781SMoriah.Waterland@Sun.COM * 0 - successful
120*9781SMoriah.Waterland@Sun.COM * 1 - package operation failed (fatal error)
121*9781SMoriah.Waterland@Sun.COM * 2 - non-fatal error (warning)
122*9781SMoriah.Waterland@Sun.COM * 3 - operation interrupted (including SIGINT/SIGHUP)
123*9781SMoriah.Waterland@Sun.COM * 4 - admin settings prevented operation
124*9781SMoriah.Waterland@Sun.COM * 5 - administration required and -n was specified
125*9781SMoriah.Waterland@Sun.COM * IN addition:
126*9781SMoriah.Waterland@Sun.COM * 10 is added to the return code if reboot after the
127*9781SMoriah.Waterland@Sun.COM * installation of all packages is required
128*9781SMoriah.Waterland@Sun.COM * 20 is added to the return code if immediate reboot
129*9781SMoriah.Waterland@Sun.COM * after installation of this package is required
130*9781SMoriah.Waterland@Sun.COM */
131*9781SMoriah.Waterland@Sun.COM
132*9781SMoriah.Waterland@Sun.COM int
pkgexecv(char * filein,char * fileout,char * uname,char * gname,char * arg[])133*9781SMoriah.Waterland@Sun.COM pkgexecv(char *filein, char *fileout, char *uname, char *gname, char *arg[])
134*9781SMoriah.Waterland@Sun.COM {
135*9781SMoriah.Waterland@Sun.COM int exit_no;
136*9781SMoriah.Waterland@Sun.COM int n;
137*9781SMoriah.Waterland@Sun.COM int status;
138*9781SMoriah.Waterland@Sun.COM pid_t pid;
139*9781SMoriah.Waterland@Sun.COM pid_t waitstat;
140*9781SMoriah.Waterland@Sun.COM struct group *grp;
141*9781SMoriah.Waterland@Sun.COM struct passwd *pwp;
142*9781SMoriah.Waterland@Sun.COM struct sigaction nact;
143*9781SMoriah.Waterland@Sun.COM struct sigaction oact;
144*9781SMoriah.Waterland@Sun.COM void (*funcSighup)();
145*9781SMoriah.Waterland@Sun.COM void (*funcSigint)();
146*9781SMoriah.Waterland@Sun.COM
147*9781SMoriah.Waterland@Sun.COM /* flush standard i/o before creating new process */
148*9781SMoriah.Waterland@Sun.COM
149*9781SMoriah.Waterland@Sun.COM (void) fflush(stdout);
150*9781SMoriah.Waterland@Sun.COM (void) fflush(stderr);
151*9781SMoriah.Waterland@Sun.COM
152*9781SMoriah.Waterland@Sun.COM /*
153*9781SMoriah.Waterland@Sun.COM * hold SIGINT/SIGHUP signals and reset signal received counter;
154*9781SMoriah.Waterland@Sun.COM * after the vfork() the parent and child need to setup their respective
155*9781SMoriah.Waterland@Sun.COM * interrupt handling and release the hold on the signals
156*9781SMoriah.Waterland@Sun.COM */
157*9781SMoriah.Waterland@Sun.COM
158*9781SMoriah.Waterland@Sun.COM (void) sighold(SIGINT);
159*9781SMoriah.Waterland@Sun.COM (void) sighold(SIGHUP);
160*9781SMoriah.Waterland@Sun.COM
161*9781SMoriah.Waterland@Sun.COM sig_received = 0;
162*9781SMoriah.Waterland@Sun.COM
163*9781SMoriah.Waterland@Sun.COM /*
164*9781SMoriah.Waterland@Sun.COM * create new process to execute command in;
165*9781SMoriah.Waterland@Sun.COM * vfork() is being used to avoid duplicating the parents
166*9781SMoriah.Waterland@Sun.COM * memory space - this means that the child process may
167*9781SMoriah.Waterland@Sun.COM * not modify any of the parents memory including the
168*9781SMoriah.Waterland@Sun.COM * standard i/o descriptors - all the child can do is
169*9781SMoriah.Waterland@Sun.COM * adjust interrupts and open files as a prelude to a
170*9781SMoriah.Waterland@Sun.COM * call to exec().
171*9781SMoriah.Waterland@Sun.COM */
172*9781SMoriah.Waterland@Sun.COM
173*9781SMoriah.Waterland@Sun.COM pid = vfork();
174*9781SMoriah.Waterland@Sun.COM
175*9781SMoriah.Waterland@Sun.COM if (pid < 0) {
176*9781SMoriah.Waterland@Sun.COM /*
177*9781SMoriah.Waterland@Sun.COM * *************************************************************
178*9781SMoriah.Waterland@Sun.COM * fork failed!
179*9781SMoriah.Waterland@Sun.COM * *************************************************************
180*9781SMoriah.Waterland@Sun.COM */
181*9781SMoriah.Waterland@Sun.COM
182*9781SMoriah.Waterland@Sun.COM progerr(pkg_gt(ERR_FORK_FAILED), errno, strerror(errno));
183*9781SMoriah.Waterland@Sun.COM
184*9781SMoriah.Waterland@Sun.COM /* release hold on signals */
185*9781SMoriah.Waterland@Sun.COM
186*9781SMoriah.Waterland@Sun.COM (void) sigrelse(SIGHUP);
187*9781SMoriah.Waterland@Sun.COM (void) sigrelse(SIGINT);
188*9781SMoriah.Waterland@Sun.COM
189*9781SMoriah.Waterland@Sun.COM return (-1);
190*9781SMoriah.Waterland@Sun.COM }
191*9781SMoriah.Waterland@Sun.COM
192*9781SMoriah.Waterland@Sun.COM if (pid > 0) {
193*9781SMoriah.Waterland@Sun.COM /*
194*9781SMoriah.Waterland@Sun.COM * *************************************************************
195*9781SMoriah.Waterland@Sun.COM * This is the forking (parent) process
196*9781SMoriah.Waterland@Sun.COM * *************************************************************
197*9781SMoriah.Waterland@Sun.COM */
198*9781SMoriah.Waterland@Sun.COM
199*9781SMoriah.Waterland@Sun.COM /* close datastream if any portion read */
200*9781SMoriah.Waterland@Sun.COM
201*9781SMoriah.Waterland@Sun.COM if (ds_curpartcnt >= 0) {
202*9781SMoriah.Waterland@Sun.COM if (ds_close(0) != 0) {
203*9781SMoriah.Waterland@Sun.COM /* kill child process */
204*9781SMoriah.Waterland@Sun.COM
205*9781SMoriah.Waterland@Sun.COM (void) sigsend(P_PID, pid, SIGKILL);
206*9781SMoriah.Waterland@Sun.COM
207*9781SMoriah.Waterland@Sun.COM /* release hold on signals */
208*9781SMoriah.Waterland@Sun.COM
209*9781SMoriah.Waterland@Sun.COM (void) sigrelse(SIGHUP);
210*9781SMoriah.Waterland@Sun.COM (void) sigrelse(SIGINT);
211*9781SMoriah.Waterland@Sun.COM
212*9781SMoriah.Waterland@Sun.COM return (-1);
213*9781SMoriah.Waterland@Sun.COM }
214*9781SMoriah.Waterland@Sun.COM }
215*9781SMoriah.Waterland@Sun.COM
216*9781SMoriah.Waterland@Sun.COM /*
217*9781SMoriah.Waterland@Sun.COM * setup signal handlers for SIGINT and SIGHUP and release hold
218*9781SMoriah.Waterland@Sun.COM */
219*9781SMoriah.Waterland@Sun.COM
220*9781SMoriah.Waterland@Sun.COM /* hook SIGINT to sig_trap() */
221*9781SMoriah.Waterland@Sun.COM
222*9781SMoriah.Waterland@Sun.COM nact.sa_handler = sig_trap;
223*9781SMoriah.Waterland@Sun.COM nact.sa_flags = SA_RESTART;
224*9781SMoriah.Waterland@Sun.COM (void) sigemptyset(&nact.sa_mask);
225*9781SMoriah.Waterland@Sun.COM
226*9781SMoriah.Waterland@Sun.COM if (sigaction(SIGINT, &nact, &oact) < 0) {
227*9781SMoriah.Waterland@Sun.COM funcSigint = SIG_DFL;
228*9781SMoriah.Waterland@Sun.COM } else {
229*9781SMoriah.Waterland@Sun.COM funcSigint = oact.sa_handler;
230*9781SMoriah.Waterland@Sun.COM }
231*9781SMoriah.Waterland@Sun.COM
232*9781SMoriah.Waterland@Sun.COM /* hook SIGHUP to sig_trap() */
233*9781SMoriah.Waterland@Sun.COM
234*9781SMoriah.Waterland@Sun.COM nact.sa_handler = sig_trap;
235*9781SMoriah.Waterland@Sun.COM nact.sa_flags = SA_RESTART;
236*9781SMoriah.Waterland@Sun.COM (void) sigemptyset(&nact.sa_mask);
237*9781SMoriah.Waterland@Sun.COM
238*9781SMoriah.Waterland@Sun.COM if (sigaction(SIGHUP, &nact, &oact) < 0) {
239*9781SMoriah.Waterland@Sun.COM funcSighup = SIG_DFL;
240*9781SMoriah.Waterland@Sun.COM } else {
241*9781SMoriah.Waterland@Sun.COM funcSighup = oact.sa_handler;
242*9781SMoriah.Waterland@Sun.COM }
243*9781SMoriah.Waterland@Sun.COM
244*9781SMoriah.Waterland@Sun.COM /* release hold on signals */
245*9781SMoriah.Waterland@Sun.COM
246*9781SMoriah.Waterland@Sun.COM (void) sigrelse(SIGHUP);
247*9781SMoriah.Waterland@Sun.COM (void) sigrelse(SIGINT);
248*9781SMoriah.Waterland@Sun.COM
249*9781SMoriah.Waterland@Sun.COM /*
250*9781SMoriah.Waterland@Sun.COM * wait for the process to exit, reap child exit status
251*9781SMoriah.Waterland@Sun.COM */
252*9781SMoriah.Waterland@Sun.COM
253*9781SMoriah.Waterland@Sun.COM for (;;) {
254*9781SMoriah.Waterland@Sun.COM status = 0;
255*9781SMoriah.Waterland@Sun.COM waitstat = waitpid(pid, (int *)&status, 0);
256*9781SMoriah.Waterland@Sun.COM if (waitstat < 0) {
257*9781SMoriah.Waterland@Sun.COM /* waitpid returned error */
258*9781SMoriah.Waterland@Sun.COM if (errno == EAGAIN) {
259*9781SMoriah.Waterland@Sun.COM /* try again */
260*9781SMoriah.Waterland@Sun.COM continue;
261*9781SMoriah.Waterland@Sun.COM }
262*9781SMoriah.Waterland@Sun.COM if (errno == EINTR) {
263*9781SMoriah.Waterland@Sun.COM continue;
264*9781SMoriah.Waterland@Sun.COM }
265*9781SMoriah.Waterland@Sun.COM /* error from waitpid: bail */
266*9781SMoriah.Waterland@Sun.COM break;
267*9781SMoriah.Waterland@Sun.COM } else if (waitstat == pid) {
268*9781SMoriah.Waterland@Sun.COM /* child exit status available */
269*9781SMoriah.Waterland@Sun.COM break;
270*9781SMoriah.Waterland@Sun.COM }
271*9781SMoriah.Waterland@Sun.COM }
272*9781SMoriah.Waterland@Sun.COM
273*9781SMoriah.Waterland@Sun.COM /*
274*9781SMoriah.Waterland@Sun.COM * reset signal handlers
275*9781SMoriah.Waterland@Sun.COM */
276*9781SMoriah.Waterland@Sun.COM
277*9781SMoriah.Waterland@Sun.COM /* reset SIGINT */
278*9781SMoriah.Waterland@Sun.COM
279*9781SMoriah.Waterland@Sun.COM nact.sa_handler = funcSigint;
280*9781SMoriah.Waterland@Sun.COM nact.sa_flags = SA_RESTART;
281*9781SMoriah.Waterland@Sun.COM (void) sigemptyset(&nact.sa_mask);
282*9781SMoriah.Waterland@Sun.COM
283*9781SMoriah.Waterland@Sun.COM (void) sigaction(SIGINT, &nact, (struct sigaction *)NULL);
284*9781SMoriah.Waterland@Sun.COM
285*9781SMoriah.Waterland@Sun.COM /* reset SIGHUP */
286*9781SMoriah.Waterland@Sun.COM
287*9781SMoriah.Waterland@Sun.COM nact.sa_handler = funcSighup;
288*9781SMoriah.Waterland@Sun.COM nact.sa_flags = SA_RESTART;
289*9781SMoriah.Waterland@Sun.COM (void) sigemptyset(&nact.sa_mask);
290*9781SMoriah.Waterland@Sun.COM
291*9781SMoriah.Waterland@Sun.COM (void) sigaction(SIGHUP, &nact, (struct sigaction *)NULL);
292*9781SMoriah.Waterland@Sun.COM
293*9781SMoriah.Waterland@Sun.COM /* error if child process does not match */
294*9781SMoriah.Waterland@Sun.COM
295*9781SMoriah.Waterland@Sun.COM if (waitstat != pid) {
296*9781SMoriah.Waterland@Sun.COM progerr(pkg_gt(ERR_WAIT_FAILED), pid, waitstat, status,
297*9781SMoriah.Waterland@Sun.COM errno, strerror(errno));
298*9781SMoriah.Waterland@Sun.COM return (-1);
299*9781SMoriah.Waterland@Sun.COM }
300*9781SMoriah.Waterland@Sun.COM
301*9781SMoriah.Waterland@Sun.COM /*
302*9781SMoriah.Waterland@Sun.COM * determine final exit code:
303*9781SMoriah.Waterland@Sun.COM * - if signal received, then return interrupted (3)
304*9781SMoriah.Waterland@Sun.COM * - if child exit status is available, return exit child status
305*9781SMoriah.Waterland@Sun.COM * - otherwise return error (-1)
306*9781SMoriah.Waterland@Sun.COM */
307*9781SMoriah.Waterland@Sun.COM
308*9781SMoriah.Waterland@Sun.COM if (sig_received != 0) {
309*9781SMoriah.Waterland@Sun.COM exit_no = 3; /* interrupted */
310*9781SMoriah.Waterland@Sun.COM } else if (WIFEXITED(status)) {
311*9781SMoriah.Waterland@Sun.COM exit_no = WEXITSTATUS(status);
312*9781SMoriah.Waterland@Sun.COM } else {
313*9781SMoriah.Waterland@Sun.COM exit_no = -1; /* exec() or other process error */
314*9781SMoriah.Waterland@Sun.COM }
315*9781SMoriah.Waterland@Sun.COM
316*9781SMoriah.Waterland@Sun.COM return (exit_no);
317*9781SMoriah.Waterland@Sun.COM }
318*9781SMoriah.Waterland@Sun.COM
319*9781SMoriah.Waterland@Sun.COM /*
320*9781SMoriah.Waterland@Sun.COM * *********************************************************************
321*9781SMoriah.Waterland@Sun.COM * This is the forked (child) process
322*9781SMoriah.Waterland@Sun.COM * *********************************************************************
323*9781SMoriah.Waterland@Sun.COM */
324*9781SMoriah.Waterland@Sun.COM
325*9781SMoriah.Waterland@Sun.COM /* reset all signals to default */
326*9781SMoriah.Waterland@Sun.COM
327*9781SMoriah.Waterland@Sun.COM for (n = 0; n < NSIG; n++) {
328*9781SMoriah.Waterland@Sun.COM (void) sigset(n, SIG_DFL);
329*9781SMoriah.Waterland@Sun.COM }
330*9781SMoriah.Waterland@Sun.COM
331*9781SMoriah.Waterland@Sun.COM /* release hold on signals held by parent before fork() */
332*9781SMoriah.Waterland@Sun.COM
333*9781SMoriah.Waterland@Sun.COM (void) sigrelse(SIGHUP);
334*9781SMoriah.Waterland@Sun.COM (void) sigrelse(SIGINT);
335*9781SMoriah.Waterland@Sun.COM
336*9781SMoriah.Waterland@Sun.COM /*
337*9781SMoriah.Waterland@Sun.COM * The caller wants to have stdin connected to filein.
338*9781SMoriah.Waterland@Sun.COM */
339*9781SMoriah.Waterland@Sun.COM
340*9781SMoriah.Waterland@Sun.COM if (filein && *filein) {
341*9781SMoriah.Waterland@Sun.COM /*
342*9781SMoriah.Waterland@Sun.COM * If input is supposed to be connected to /dev/tty
343*9781SMoriah.Waterland@Sun.COM */
344*9781SMoriah.Waterland@Sun.COM if (strncmp(filein, "/dev/tty", 8) == 0) {
345*9781SMoriah.Waterland@Sun.COM /*
346*9781SMoriah.Waterland@Sun.COM * If stdin is connected to a tty device.
347*9781SMoriah.Waterland@Sun.COM */
348*9781SMoriah.Waterland@Sun.COM if (isatty(STDIN_FILENO)) {
349*9781SMoriah.Waterland@Sun.COM /*
350*9781SMoriah.Waterland@Sun.COM * Reopen it to /dev/tty.
351*9781SMoriah.Waterland@Sun.COM */
352*9781SMoriah.Waterland@Sun.COM n = open(filein, O_RDONLY);
353*9781SMoriah.Waterland@Sun.COM if (n >= 0) {
354*9781SMoriah.Waterland@Sun.COM (void) dup2(n, STDIN_FILENO);
355*9781SMoriah.Waterland@Sun.COM }
356*9781SMoriah.Waterland@Sun.COM }
357*9781SMoriah.Waterland@Sun.COM } else {
358*9781SMoriah.Waterland@Sun.COM /*
359*9781SMoriah.Waterland@Sun.COM * If we did not want to be connected to /dev/tty, we
360*9781SMoriah.Waterland@Sun.COM * connect input to the requested file no questions.
361*9781SMoriah.Waterland@Sun.COM */
362*9781SMoriah.Waterland@Sun.COM n = open(filein, O_RDONLY);
363*9781SMoriah.Waterland@Sun.COM if (n >= 0) {
364*9781SMoriah.Waterland@Sun.COM (void) dup2(n, STDIN_FILENO);
365*9781SMoriah.Waterland@Sun.COM }
366*9781SMoriah.Waterland@Sun.COM }
367*9781SMoriah.Waterland@Sun.COM }
368*9781SMoriah.Waterland@Sun.COM
369*9781SMoriah.Waterland@Sun.COM /*
370*9781SMoriah.Waterland@Sun.COM * The caller wants to have stdout and stderr connected to fileout.
371*9781SMoriah.Waterland@Sun.COM * If "fileout" is "/dev/tty" then reconnect stdout to "/dev/tty"
372*9781SMoriah.Waterland@Sun.COM * only if /dev/tty is not already associated with "a tty".
373*9781SMoriah.Waterland@Sun.COM */
374*9781SMoriah.Waterland@Sun.COM
375*9781SMoriah.Waterland@Sun.COM if (fileout && *fileout) {
376*9781SMoriah.Waterland@Sun.COM /*
377*9781SMoriah.Waterland@Sun.COM * If output is supposed to be connected to /dev/tty
378*9781SMoriah.Waterland@Sun.COM */
379*9781SMoriah.Waterland@Sun.COM if (strncmp(fileout, "/dev/tty", 8) == 0) {
380*9781SMoriah.Waterland@Sun.COM /*
381*9781SMoriah.Waterland@Sun.COM * If stdout is connected to a tty device.
382*9781SMoriah.Waterland@Sun.COM */
383*9781SMoriah.Waterland@Sun.COM if (isatty(STDOUT_FILENO)) {
384*9781SMoriah.Waterland@Sun.COM /*
385*9781SMoriah.Waterland@Sun.COM * Reopen it to /dev/tty if /dev/tty available.
386*9781SMoriah.Waterland@Sun.COM */
387*9781SMoriah.Waterland@Sun.COM n = open(fileout, O_WRONLY);
388*9781SMoriah.Waterland@Sun.COM if (n >= 0) {
389*9781SMoriah.Waterland@Sun.COM /*
390*9781SMoriah.Waterland@Sun.COM * /dev/tty is available - close the
391*9781SMoriah.Waterland@Sun.COM * current standard output stream, and
392*9781SMoriah.Waterland@Sun.COM * reopen it on /dev/tty
393*9781SMoriah.Waterland@Sun.COM */
394*9781SMoriah.Waterland@Sun.COM (void) dup2(n, STDOUT_FILENO);
395*9781SMoriah.Waterland@Sun.COM }
396*9781SMoriah.Waterland@Sun.COM }
397*9781SMoriah.Waterland@Sun.COM /*
398*9781SMoriah.Waterland@Sun.COM * not connected to tty device - probably redirect to
399*9781SMoriah.Waterland@Sun.COM * file - preserve existing output device
400*9781SMoriah.Waterland@Sun.COM */
401*9781SMoriah.Waterland@Sun.COM } else {
402*9781SMoriah.Waterland@Sun.COM /*
403*9781SMoriah.Waterland@Sun.COM * If we did not want to be connected to /dev/tty, we
404*9781SMoriah.Waterland@Sun.COM * connect output to the requested file no questions.
405*9781SMoriah.Waterland@Sun.COM */
406*9781SMoriah.Waterland@Sun.COM /* LINTED O_CREAT without O_EXCL specified in call to */
407*9781SMoriah.Waterland@Sun.COM n = open(fileout, O_WRONLY|O_CREAT|O_APPEND, 0666);
408*9781SMoriah.Waterland@Sun.COM if (n >= 0) {
409*9781SMoriah.Waterland@Sun.COM (void) dup2(n, STDOUT_FILENO);
410*9781SMoriah.Waterland@Sun.COM }
411*9781SMoriah.Waterland@Sun.COM }
412*9781SMoriah.Waterland@Sun.COM
413*9781SMoriah.Waterland@Sun.COM /*
414*9781SMoriah.Waterland@Sun.COM * Dup stderr from stdout.
415*9781SMoriah.Waterland@Sun.COM */
416*9781SMoriah.Waterland@Sun.COM
417*9781SMoriah.Waterland@Sun.COM (void) dup2(STDOUT_FILENO, STDERR_FILENO);
418*9781SMoriah.Waterland@Sun.COM }
419*9781SMoriah.Waterland@Sun.COM
420*9781SMoriah.Waterland@Sun.COM /*
421*9781SMoriah.Waterland@Sun.COM * do NOT close all file descriptors except stdio
422*9781SMoriah.Waterland@Sun.COM * file descriptors are passed in to some subcommands
423*9781SMoriah.Waterland@Sun.COM * (see dstream:ds_getinfo() and dstream:ds_putinfo())
424*9781SMoriah.Waterland@Sun.COM */
425*9781SMoriah.Waterland@Sun.COM
426*9781SMoriah.Waterland@Sun.COM /* set group/user i.d. if requested */
427*9781SMoriah.Waterland@Sun.COM
428*9781SMoriah.Waterland@Sun.COM if (gname && *gname && (grp = cgrnam(gname)) != NULL) {
429*9781SMoriah.Waterland@Sun.COM if (setgid(grp->gr_gid) == -1) {
430*9781SMoriah.Waterland@Sun.COM progerr(pkg_gt(ERR_SETGID), grp->gr_gid);
431*9781SMoriah.Waterland@Sun.COM }
432*9781SMoriah.Waterland@Sun.COM }
433*9781SMoriah.Waterland@Sun.COM if (uname && *uname && (pwp = cpwnam(uname)) != NULL) {
434*9781SMoriah.Waterland@Sun.COM if (setuid(pwp->pw_uid) == -1) {
435*9781SMoriah.Waterland@Sun.COM progerr(pkg_gt(ERR_SETUID), pwp->pw_uid);
436*9781SMoriah.Waterland@Sun.COM }
437*9781SMoriah.Waterland@Sun.COM }
438*9781SMoriah.Waterland@Sun.COM
439*9781SMoriah.Waterland@Sun.COM /* execute target executable */
440*9781SMoriah.Waterland@Sun.COM
441*9781SMoriah.Waterland@Sun.COM (void) execve(arg[0], arg, environ);
442*9781SMoriah.Waterland@Sun.COM progerr(pkg_gt(ERR_EX_FAIL), arg[0], errno);
443*9781SMoriah.Waterland@Sun.COM _exit(99);
444*9781SMoriah.Waterland@Sun.COM /*NOTREACHED*/
445*9781SMoriah.Waterland@Sun.COM }
446