5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * CDDL HEADER START
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * The contents of this file are subject to the terms of the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Common Development and Distribution License (the "License").
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * You may not use this file except in compliance with the License.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * or http://www.opensolaris.org/os/licensing.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * See the License for the specific language governing permissions
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * and limitations under the License.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * When distributing Covered Code, include this CDDL HEADER in each
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * If applicable, add the following below this CDDL HEADER, with the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * fields enclosed by brackets "[]" replaced with your own identifying
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * information: Portions Copyright [yyyy] [name of copyright owner]
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * CDDL HEADER END
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Use is subject to license terms.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/* All Rights Reserved */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <stdio.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <errno.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <string.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <stdlib.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <unistd.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <signal.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <wait.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <sys/types.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <sys/stat.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <fcntl.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <pwd.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <grp.h>
4656d4747c8743290bfbe910c64cd75eb4e4af8dGarrett D'Amore#include <note.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include "pkglib.h"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include "pkglibmsgs.h"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include "pkglocale.h"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/* global environment inherited by this process */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandextern char **environ;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/* dstream.c */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandextern int ds_curpartcnt;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandextern int ds_close(int pkgendflg);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * global internal (private) variables
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/* received signal count - bumped with hooked signals are caught */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic int sig_received = 0;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Name: sig_trap
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Description: hooked up to signal counts number of signals received
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Arguments: a_signo - [RO, *RO] - (int)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Integer representing the signal received; see signal(3c)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Returns: <void>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic void
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandsig_trap(int a_signo)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
4656d4747c8743290bfbe910c64cd75eb4e4af8dGarrett D'Amore _NOTE(ARGUNUSED(a_signo));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland sig_received++;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Name: pkgexecv
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Description: Asynchronously execute a package command in a separate process
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * and return results - the subprocess MUST arm it's own SIGINT
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * and SIGHUP signals and must return a standard package command
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * exit code (see returns below)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Only another package command (such as pkginstall, pkgremove,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * etc.) may be called via this interface. No files are closed
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * because open files are passed across to certain commands using
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * either implicit agreements between the two (yuk!) or by using
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * the '-p' option which passes a string of digits, some of which
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * represent open file descriptors passed through this interface!
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Arguments: filein - [RO, *RO] - (char *)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Pointer to string representing the name of the file to
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * use for the package commands's stdin
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * == (char *)NULL or == "" - the current stdin
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * is used for the new package command process
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * fileout - [RO, *RO] - (char *)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Pointer to string representing the name of the file to
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * use for the package commands's stdout and stderr
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * == (char *)NULL or == "" - the current stdout/stderr
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * is used for the new package command process
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * uname - [RO, *RO] - (char *)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Pointer to string representing the user name to execute
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * the package command as - the user name is looked up
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * using the ncgrpw:cpwnam() interface
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * == (char *)NULL or == "" - the user name of the current
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * process is used for the new package command process
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * gname - [RO, *RO] - (char *)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Pointer to string representing the group name to execute
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * the package command as - the group name is looked up
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * using the ncgrpw:cgrnam() interface
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * == (char *)NULL or == "" - the group name of the current
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * process is used for the new package command process
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * arg - [RO, *RO] - (char **)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Pointer to array of character pointers representing the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * arguments to pass to the package command - the array is
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * terminated with a pointer to (char *)NULL
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Returns: int
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * == 99 - exec() of package command failed
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * == -1 - fork failed or other fatal error during
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * execution of the package command
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * otherwise - exit code from package command:
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * 0 - successful
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * 1 - package operation failed (fatal error)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * 2 - non-fatal error (warning)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * 3 - operation interrupted (including SIGINT/SIGHUP)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * 4 - admin settings prevented operation
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * 5 - administration required and -n was specified
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * IN addition:
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * 10 is added to the return code if reboot after the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * installation of all packages is required
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * 20 is added to the return code if immediate reboot
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * after installation of this package is required
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandint
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandpkgexecv(char *filein, char *fileout, char *uname, char *gname, char *arg[])
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int exit_no;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int n;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int status;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland pid_t pid;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland pid_t waitstat;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland struct group *grp;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland struct passwd *pwp;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland struct sigaction nact;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland struct sigaction oact;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland void (*funcSighup)();
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland void (*funcSigint)();
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* flush standard i/o before creating new process */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) fflush(stdout);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) fflush(stderr);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * hold SIGINT/SIGHUP signals and reset signal received counter;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * after the vfork() the parent and child need to setup their respective
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * interrupt handling and release the hold on the signals
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) sighold(SIGINT);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) sighold(SIGHUP);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland sig_received = 0;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * create new process to execute command in;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * vfork() is being used to avoid duplicating the parents
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * memory space - this means that the child process may
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * not modify any of the parents memory including the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * standard i/o descriptors - all the child can do is
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * adjust interrupts and open files as a prelude to a
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * call to exec().
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland pid = vfork();
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (pid < 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * *************************************************************
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * fork failed!
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * *************************************************************
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(pkg_gt(ERR_FORK_FAILED), errno, strerror(errno));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* release hold on signals */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) sigrelse(SIGHUP);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) sigrelse(SIGINT);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (pid > 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * *************************************************************
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * This is the forking (parent) process
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * *************************************************************
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* close datastream if any portion read */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (ds_curpartcnt >= 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (ds_close(0) != 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* kill child process */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) sigsend(P_PID, pid, SIGKILL);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* release hold on signals */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) sigrelse(SIGHUP);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) sigrelse(SIGINT);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * setup signal handlers for SIGINT and SIGHUP and release hold
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* hook SIGINT to sig_trap() */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland nact.sa_handler = sig_trap;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland nact.sa_flags = SA_RESTART;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) sigemptyset(&nact.sa_mask);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (sigaction(SIGINT, &nact, &oact) < 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland funcSigint = SIG_DFL;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland funcSigint = oact.sa_handler;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* hook SIGHUP to sig_trap() */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland nact.sa_handler = sig_trap;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland nact.sa_flags = SA_RESTART;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) sigemptyset(&nact.sa_mask);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (sigaction(SIGHUP, &nact, &oact) < 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland funcSighup = SIG_DFL;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland funcSighup = oact.sa_handler;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* release hold on signals */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) sigrelse(SIGHUP);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) sigrelse(SIGINT);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * wait for the process to exit, reap child exit status
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland for (;;) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland status = 0;
4656d4747c8743290bfbe910c64cd75eb4e4af8dGarrett D'Amore waitstat = waitpid(pid, &status, 0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (waitstat < 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* waitpid returned error */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (errno == EAGAIN) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* try again */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland continue;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (errno == EINTR) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland continue;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* error from waitpid: bail */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland break;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else if (waitstat == pid) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* child exit status available */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland break;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * reset signal handlers
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* reset SIGINT */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland nact.sa_handler = funcSigint;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland nact.sa_flags = SA_RESTART;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) sigemptyset(&nact.sa_mask);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) sigaction(SIGINT, &nact, (struct sigaction *)NULL);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* reset SIGHUP */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland nact.sa_handler = funcSighup;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland nact.sa_flags = SA_RESTART;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) sigemptyset(&nact.sa_mask);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) sigaction(SIGHUP, &nact, (struct sigaction *)NULL);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* error if child process does not match */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (waitstat != pid) {
4656d4747c8743290bfbe910c64cd75eb4e4af8dGarrett D'Amore progerr(pkg_gt(ERR_WAIT_FAILED), pid, status,
4656d4747c8743290bfbe910c64cd75eb4e4af8dGarrett D'Amore errno, strerror(errno));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * determine final exit code:
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - if signal received, then return interrupted (3)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - if child exit status is available, return exit child status
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - otherwise return error (-1)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (sig_received != 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland exit_no = 3; /* interrupted */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else if (WIFEXITED(status)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland exit_no = WEXITSTATUS(status);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland exit_no = -1; /* exec() or other process error */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (exit_no);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * *********************************************************************
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * This is the forked (child) process
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * *********************************************************************
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* reset all signals to default */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland for (n = 0; n < NSIG; n++) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) sigset(n, SIG_DFL);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* release hold on signals held by parent before fork() */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) sigrelse(SIGHUP);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) sigrelse(SIGINT);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * The caller wants to have stdin connected to filein.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (filein && *filein) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * If input is supposed to be connected to /dev/tty
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (strncmp(filein, "/dev/tty", 8) == 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * If stdin is connected to a tty device.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (isatty(STDIN_FILENO)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Reopen it to /dev/tty.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland n = open(filein, O_RDONLY);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (n >= 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) dup2(n, STDIN_FILENO);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * If we did not want to be connected to /dev/tty, we
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * connect input to the requested file no questions.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland n = open(filein, O_RDONLY);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (n >= 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) dup2(n, STDIN_FILENO);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * The caller wants to have stdout and stderr connected to fileout.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * If "fileout" is "/dev/tty" then reconnect stdout to "/dev/tty"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * only if /dev/tty is not already associated with "a tty".
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (fileout && *fileout) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * If output is supposed to be connected to /dev/tty
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (strncmp(fileout, "/dev/tty", 8) == 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * If stdout is connected to a tty device.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (isatty(STDOUT_FILENO)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Reopen it to /dev/tty if /dev/tty available.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland n = open(fileout, O_WRONLY);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (n >= 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * /dev/tty is available - close the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * current standard output stream, and
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * reopen it on /dev/tty
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) dup2(n, STDOUT_FILENO);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * not connected to tty device - probably redirect to
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * file - preserve existing output device
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * If we did not want to be connected to /dev/tty, we
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * connect output to the requested file no questions.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* LINTED O_CREAT without O_EXCL specified in call to */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland n = open(fileout, O_WRONLY|O_CREAT|O_APPEND, 0666);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (n >= 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) dup2(n, STDOUT_FILENO);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Dup stderr from stdout.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) dup2(STDOUT_FILENO, STDERR_FILENO);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * do NOT close all file descriptors except stdio
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * file descriptors are passed in to some subcommands
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * (see dstream:ds_getinfo() and dstream:ds_putinfo())
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* set group/user i.d. if requested */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (gname && *gname && (grp = cgrnam(gname)) != NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (setgid(grp->gr_gid) == -1) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(pkg_gt(ERR_SETGID), grp->gr_gid);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (uname && *uname && (pwp = cpwnam(uname)) != NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (setuid(pwp->pw_uid) == -1) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(pkg_gt(ERR_SETUID), pwp->pw_uid);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* execute target executable */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) execve(arg[0], arg, environ);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(pkg_gt(ERR_EX_FAIL), arg[0], errno);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland _exit(99);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*NOTREACHED*/
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}