cdrtools/libschily/spawn.c
2025-06-15 04:19:58 +08:00

234 lines
5.0 KiB
C

/* @(#)spawn.c 1.30 15/07/06 Copyright 1985, 1989, 1995-2015 J. Schilling */
/*
* Spawn another process/ wait for child process
*
* Copyright (c) 1985, 1989, 1995-2015 J. Schilling
*
* This is an interface that exists in the public since 1982.
* The POSIX.1-2008 standard did ignore POSIX rules not to
* redefine existing public interfaces and redefined the interfaces
* forcing us to add a js_*() prefix to the original functions.
*/
/*
* 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.
*
* See the file CDDL.Schily.txt in this distribution for details.
* A copy of the CDDL is also available via the Internet at
* http://www.opensource.org/licenses/cddl1.txt
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file CDDL.Schily.txt from this distribution.
*/
#ifndef __DO__FSPAWNL__
#define fspawnv __no__fspawnv__
#define fspawnl __no__fspawnl__
#define fspawnv_nowait __no__fspawnv_nowait__
#include <schily/mconfig.h>
#include <schily/stdio.h>
#include <schily/standard.h>
#include <schily/unistd.h>
#include <schily/stdlib.h>
#include <schily/varargs.h>
#include <schily/wait.h>
#include <schily/errno.h>
#include <schily/schily.h>
#define VMS_VFORK_OK
#include <schily/vfork.h>
#endif /* __DO__FSPAWNL__ */
#define MAX_F_ARGS 16
#ifndef __DO__FSPAWNL__
#ifndef NO_FSPAWN_COMPAT /* Define to disable backward compatibility */
#undef fspawnv
#undef fspawnl
#undef fspawnv_nowait
/*
* The Cygwin compile environment incorrectly implements #pragma weak.
* The weak symbols are only defined as local symbols making it impossible
* to use them from outside the scope of this source file.
* A platform that allows linking with global symbols has HAVE_LINK_WEAK
* defined.
*/
#if defined(HAVE_PRAGMA_WEAK) && defined(HAVE_LINK_WEAK)
#pragma weak fspawnv = js_fspawnv
#pragma weak fspawnl = js_fspawnl
#pragma weak fspawnv_nowait = js_fspawnv_nowait
#else
EXPORT int fspawnv __PR((FILE *, FILE *, FILE *, int, char * const *));
EXPORT int fspawnl __PR((FILE *, FILE *, FILE *, const char *, ...));
EXPORT int fspawnv_nowait __PR((FILE *, FILE *, FILE *,
const char *, int, char *const*));
EXPORT int
fspawnv(in, out, err, argc, argv)
FILE *in;
FILE *out;
FILE *err;
int argc;
char * const argv[];
{
return (js_fspawnv(in, out, err, argc, argv));
}
EXPORT int
fspawnv_nowait(in, out, err, name, argc, argv)
FILE *in;
FILE *out;
FILE *err;
const char *name;
int argc;
char * const argv[];
{
return (js_fspawnv_nowait(in, out, err, name, argc, argv));
}
#define __DO__FSPAWNL__
#define js_fspawnl fspawnl
#include "spawn.c"
#undef js_fspawnl
#undef __DO__FSPAWNL__
#endif /* HAVE_PRAGMA_WEAK && HAVE_LINK_WEAK */
#endif /* NO_FSPAWN_COMPAT */
EXPORT int
js_fspawnv(in, out, err, argc, argv)
FILE *in;
FILE *out;
FILE *err;
int argc;
char * const argv[];
{
int pid;
if ((pid = js_fspawnv_nowait(in, out, err, argv[0], argc, argv)) < 0)
return (pid);
return (wait_chld(pid));
}
#endif /* __DO__FSPAWNL__ */
/* VARARGS3 */
#ifdef PROTOTYPES
EXPORT int
js_fspawnl(FILE *in, FILE *out, FILE *err, const char *arg0, ...)
#else
EXPORT int
js_fspawnl(in, out, err, arg0, va_alist)
FILE *in;
FILE *out;
FILE *err;
const char *arg0;
va_dcl
#endif
{
va_list args;
int ac = 0;
char *xav[MAX_F_ARGS+1];
char **av;
const char **pav;
char *p;
int ret;
#ifdef PROTOTYPES
va_start(args, arg0);
#else
va_start(args);
#endif
if (arg0) {
ac++;
while (va_arg(args, char *) != NULL)
ac++;
}
va_end(args);
if (ac <= MAX_F_ARGS) {
av = xav;
} else {
av = (char **)malloc((ac+1)*sizeof (char *));
if (av == 0)
return (-1);
}
pav = (const char **)av;
#ifdef PROTOTYPES
va_start(args, arg0);
#else
va_start(args);
#endif
*pav++ = arg0;
if (arg0) do {
p = va_arg(args, char *);
*pav++ = p;
} while (p != NULL);
va_end(args);
ret = js_fspawnv(in, out, err, ac, av);
if (av != xav)
free(av);
return (ret);
}
#ifndef __DO__FSPAWNL__
EXPORT int
js_fspawnv_nowait(in, out, err, name, argc, argv)
FILE *in;
FILE *out;
FILE *err;
const char *name;
int argc;
char * const argv[];
{
int pid = -1; /* Initialization needed to make GCC happy */
volatile int i;
for (i = 1; i < 64; i *= 2) {
if ((pid = vfork()) >= 0)
break;
sleep(i);
}
if (pid != 0)
return (pid);
/*
* silly: fexecv must set av[ac] = NULL
* so we have to cast argv tp (char **)
*/
fexecv(name, in, out, err, argc, (char **)argv);
_exit(geterrno());
/* NOTREACHED */
#ifndef lint
return (0); /* keep gnu compiler happy */
#endif
}
EXPORT int
wait_chld(pid)
int pid;
{
int died;
WAIT_T status;
do {
do {
died = wait(&status);
} while (died < 0 && geterrno() == EINTR);
if (died < 0)
return (died);
} while (died != pid);
if (WCOREDUMP(status))
unlink("core");
if (WIFEXITED(status))
return (WEXITSTATUS(status));
return (-WTERMSIG(status));
}
#endif /* __DO__FSPAWNL__ */