system.c revision e8031f0a8ed0e45c6d8847c5e09424e66fd34a4b
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/* Copyright (c) 1988 AT&T */
/* All Rights Reserved */
#include "synonyms.h"
#include "mtlib.h"
#include <signal.h>
#include <stdlib.h>
#include <wait.h>
#include <unistd.h>
#include <memory.h>
#include <pthread.h>
#include <errno.h>
#include <synch.h>
#include <spawn.h>
#include "libc.h"
extern const char **environ;
/*
* Cancellation cleanup handler.
*/
static void
{
if (--sys_count == 0) { /* leaving system() */
/*
* There are no remaining threads in system(),
* so restore the several signal actions.
*/
}
}
int
{
pid_t w;
int status;
int error;
const char *shpath;
char *argvec[4];
static const char *shell = "sh";
return (0);
/* exec for user */
return (0);
/* exec for group */
return (0);
return (0);
}
return (1);
}
/*
* Initialize the posix_spawn() attributes structure.
*/
return (-1);
}
/*
* We are required to block SIGCHLD so that we don't cause
* the process's signal handler, if any, to be called.
* This doesn't really work for a multithreaded process
* because some other thread may receive the SIGCHLD.
*/
(void) sigemptyset(&mask);
/*
* Tell posix_spawn() to restore the signal mask in the child.
*/
if (error == 0)
/*
* We are required to set the disposition of SIGINT and SIGQUIT
* to be ignored for the duration of the system() operation.
*
* We allow more than one thread to call system() concurrently by
* keeping a count of such threads. The signal actions are set
* to SIG_IGN when the first thread calls system(). They are
* restored in cleanup() when the last thread exits system().
*
* However, system() is still MT-unsafe because sigaction() has
* a process-wide effect and some other thread may also be
* setting the signal actions for SIGINT or SIGQUIT.
*/
if (sys_count++ == 0) {
/*
* If the action for SIGCHLD is SIG_IGN, then set it to SIG_DFL
* so we can retrieve the status of the spawned-off shell.
* The execve() performed in posix_spawn() will set the action
* for SIGCHLD in the child process to SIG_DFL regardless,
* so this has no negative consequencies for the child.
*
* Note that this is not required by the SUSv3 standard.
* The standard permits this error:
* ECHILD The status of the child process created
* by system() is no longer available.
* So we could leave the action for SIGCHLD alone and
* still be standards-conforming, but this is the way
* the SunOS system() has always behaved (in fact it
* used to set the action to SIG_DFL unconditinally),
* so we retain this behavior here.
*/
}
}
/*
* If SIGINT and SIGQUIT were not already SIG_IGN, tell
* posix_spawn() to make them SIG_DFL in the child,
* else leave them as SIG_IGN in the child.
*/
(void) sigemptyset(&mask);
if (error == 0)
if (error == 0)
(void) posix_spawnattr_destroy(&attr);
if (error) {
status = -1;
} else {
/*
* system() is a cancellation point.
* Call waitpid_cancel() rather than _waitpid() to make
* sure that we actually perform the cancellation logic.
*/
do {
if (w == -1)
status = -1;
}
return (status);
}