spawn.c revision f9f6ed06923c6f348695de4d5185b4013adc4b6b
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (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 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include "lint.h"
#include "thr_uberdata.h"
#include <sys/libc_kernel.h>
#include <alloca.h>
#include <spawn.h>
#define ALL_POSIX_SPAWN_FLAGS \
(POSIX_SPAWN_RESETIDS | \
typedef struct {
int sa_psflags; /* POSIX_SPAWN_* flags */
int sa_priority;
int sa_schedpolicy;
} spawn_attr_t;
typedef struct file_attr {
char *fa_path; /* copied pathname for open() */
int fa_oflag; /* oflag for open() */
int fa_filedes; /* file descriptor for open()/close() */
int fa_newfiledes; /* new file descriptor for dup2() */
} file_attr_t;
static int
{
int sig;
}
}
}
return (errno);
}
return (errno);
}
return (errno);
return (errno);
}
return (0);
}
static int
{
int fd;
do {
case FA_OPEN:
if (fd < 0)
return (errno);
return (errno);
}
break;
case FA_CLOSE:
return (errno);
break;
case FA_DUP2:
fap->fa_newfiledes);
if (fd < 0)
return (errno);
break;
}
return (0);
}
static int
{
int flags = 0;
flags |= FORK_NOSIGCHLD;
flags |= FORK_WAITPID;
}
return (flags);
}
/*
* set_error() / get_error() are used to guarantee that the local variable
* 'error' is set correctly in memory on return from vfork() in the parent.
*/
static int
{
}
static int
{
return (*errp);
}
/*
* For MT safety, do not invoke the dynamic linker after calling vfork().
* If some other thread was in the dynamic linker when this thread's parent
* called vfork() then the dynamic linker's lock would still be held here
* (with a defunct owner) and we would deadlock ourself if we invoked it.
*
* Therefore, all of the functions we call here after returning from
* vforkx() in the child are not and must never be exported from libc
* as global symbols. To do so would risk invoking the dynamic linker.
*/
int
const char *path,
const posix_spawnattr_t *attrp,
char *const argv[],
char *const envp[])
{
int error; /* this will be set by the child */
return (EINVAL);
case 0: /* child */
break;
case -1: /* parent, failure */
return (errno);
default: /* parent, success */
/*
* We don't get here until the child exec()s or exit()s
*/
}
_exit(127);
return (0); /* not reached */
}
/*
*/
extern int libc__xpg4;
static const char *
{
char *s;
char c;
if (cnt > 0) {
*s++ = c;
cnt--;
}
}
*s++ = '/';
cnt--;
}
*s++ = c;
cnt--;
}
*s = '\0';
}
/* ARGSUSED */
int
const char *file,
const posix_spawnattr_t *attrp,
char *const argv[],
char *const envp[])
{
int xpg4 = libc__xpg4;
int error; /* this will be set by the child */
const char *cp;
char **newargs;
int argc;
int i;
static const char *shell = "sh";
return (EINVAL);
if (*file == '\0')
return (EACCES);
/*
* We may need to invoke the shell with a slightly modified
* argv[] array. To do this we need to preallocate the array.
* We must call alloca() before calling vfork() because doing
* it after vfork() (in the child) would corrupt the parent.
*/
continue;
case 0: /* child */
break;
case -1: /* parent, failure */
return (errno);
default: /* parent, success */
/*
* We don't get here until the child exec()s or exit()s
*/
}
/*
* XPG4: pathstr is equivalent to _CS_PATH, except that
* with a colon when not root. Keep these paths in sync
* with _CS_PATH in confstr.c. Note that pathstr must end
* with a colon when not root so that when file doesn't
* contain '/', the last call to execat() will result in an
* attempt to execv file from the current directory.
*/
if (!xpg4)
else
} else {
if (!xpg4)
else
}
}
do {
/*
* 4025035 and 4038378
* if a filename begins with a "-" prepend "./" so that
* the shell can't interpret it as an option
*/
if (*path == '-') {
char *s;
for (s = path; *s != '\0'; s++)
continue;
for (; s >= path; s--)
*(s + 2) = *s;
path[0] = '.';
}
for (i = 1; i <= argc; i++)
_exit(127);
}
} while (cp);
return (0); /* not reached */
}
int
{
return (0);
}
int
{
do {
}
return (0);
}
static void
{
} else {
}
}
int
int filedes,
const char *path,
int oflag,
{
if (filedes < 0)
return (EBADF);
return (ENOMEM);
return (ENOMEM);
}
return (0);
}
int
int filedes)
{
if (filedes < 0)
return (EBADF);
return (ENOMEM);
return (0);
}
int
int filedes,
int newfiledes)
{
if (filedes < 0 || newfiledes < 0)
return (EBADF);
return (ENOMEM);
return (0);
}
int
{
return (ENOMEM);
/*
* Add default stuff here?
*/
return (0);
}
int
{
return (EINVAL);
/*
* deallocate stuff here?
*/
return (0);
}
int
short flags)
{
(flags & ~ALL_POSIX_SPAWN_FLAGS))
return (EINVAL);
return (0);
}
int
const posix_spawnattr_t *attr,
short *flags)
{
return (EINVAL);
return (0);
}
int
{
return (EINVAL);
return (0);
}
int
const posix_spawnattr_t *attr,
{
return (EINVAL);
return (0);
}
int
const struct sched_param *schedparam)
{
return (EINVAL);
/*
* Check validity?
*/
return (0);
}
int
const posix_spawnattr_t *attr,
struct sched_param *schedparam)
{
return (EINVAL);
return (0);
}
int
int schedpolicy)
{
return (EINVAL);
/*
* Cache the policy information for later use
* by the vfork() child of posix_spawn().
*/
return (errno);
return (0);
}
int
const posix_spawnattr_t *attr,
int *schedpolicy)
{
return (EINVAL);
return (0);
}
int
const sigset_t *sigdefault)
{
return (EINVAL);
return (0);
}
int
const posix_spawnattr_t *attr,
{
return (EINVAL);
return (0);
}
int
{
return (EINVAL);
return (0);
}
int
const posix_spawnattr_t *attr,
{
return (EINVAL);
return (0);
}