Blame scsilib/libschily/spawn.c

Packit bf707c
/* @(#)spawn.c	1.16 03/07/13 Copyright 1985, 1989, 1995-2003 J. Schilling */
Packit bf707c
/*
Packit bf707c
 *	Spawn another process/ wait for child process
Packit bf707c
 *
Packit bf707c
 *	Copyright (c) 1985, 1989, 1995-2003 J. Schilling
Packit bf707c
 */
Packit bf707c
/*
Packit bf707c
 * This program is free software; you can redistribute it and/or modify
Packit bf707c
 * it under the terms of the GNU General Public License as published by
Packit bf707c
 * the Free Software Foundation; either version 2, or (at your option)
Packit bf707c
 * any later version.
Packit bf707c
 *
Packit bf707c
 * This program is distributed in the hope that it will be useful,
Packit bf707c
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit bf707c
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit bf707c
 * GNU General Public License for more details.
Packit bf707c
 *
Packit bf707c
 * You should have received a copy of the GNU General Public License along with
Packit bf707c
 * this program; see the file COPYING.  If not, write to the Free Software
Packit bf707c
 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Packit bf707c
 */
Packit bf707c
Packit bf707c
#include <mconfig.h>
Packit bf707c
#include <stdio.h>
Packit bf707c
#include <standard.h>
Packit bf707c
#define	fspawnl	__nothing__	/* prototype in schily.h is wrong */
Packit bf707c
#define	spawnl	__nothing__	/* prototype in schily.h is wrong */
Packit bf707c
#include <schily.h>
Packit bf707c
#undef	fspawnl
Packit bf707c
#undef	spawnl
Packit bf707c
#include <unixstd.h>
Packit bf707c
#include <stdxlib.h>
Packit bf707c
#include <vadefs.h>
Packit bf707c
#include <waitdefs.h>
Packit bf707c
#include <errno.h>
Packit bf707c
Packit bf707c
#define	MAX_F_ARGS	16
Packit bf707c
Packit bf707c
EXPORT	int	fspawnl	__PR((FILE *, FILE *, FILE *, ...));
Packit bf707c
Packit bf707c
EXPORT int
Packit bf707c
fspawnv(in, out, err, argc, argv)
Packit bf707c
	FILE	*in;
Packit bf707c
	FILE	*out;
Packit bf707c
	FILE	*err;
Packit bf707c
	int	argc;
Packit bf707c
	char	* const argv[];
Packit bf707c
{
Packit bf707c
	int	pid;
Packit bf707c
Packit bf707c
	if ((pid = fspawnv_nowait(in, out, err, argv[0], argc, argv)) < 0)
Packit bf707c
		return (pid);
Packit bf707c
Packit bf707c
	return (wait_chld(pid));
Packit bf707c
}
Packit bf707c
Packit bf707c
/* VARARGS5 */
Packit bf707c
#ifdef	PROTOTYPES
Packit bf707c
EXPORT int
Packit bf707c
fspawnl(FILE *in, FILE *out, FILE *err, ...)
Packit bf707c
#else
Packit bf707c
EXPORT int
Packit bf707c
fspawnl(in, out, err, va_alist)
Packit bf707c
	FILE	*in;
Packit bf707c
	FILE	*out;
Packit bf707c
	FILE	*err;
Packit bf707c
	va_dcl
Packit bf707c
#endif
Packit bf707c
{
Packit bf707c
	va_list	args;
Packit bf707c
	int	ac = 0;
Packit bf707c
	char	*xav[MAX_F_ARGS];
Packit bf707c
	char	**av;
Packit bf707c
	char	**pav;
Packit bf707c
	char	*p;
Packit bf707c
	int	ret;
Packit bf707c
Packit bf707c
#ifdef	PROTOTYPES
Packit bf707c
	va_start(args, err);
Packit bf707c
#else
Packit bf707c
	va_start(args);
Packit bf707c
#endif
Packit bf707c
	while (va_arg(args, char *) != NULL)
Packit bf707c
		ac++;
Packit bf707c
	va_end(args);
Packit bf707c
Packit bf707c
	if (ac < MAX_F_ARGS) {
Packit bf707c
		pav = av = xav;
Packit bf707c
	} else {
Packit bf707c
		pav = av = (char **)malloc((ac+1)*sizeof (char *));
Packit bf707c
		if (av == 0)
Packit bf707c
			return (-1);
Packit bf707c
	}
Packit bf707c
Packit bf707c
#ifdef	PROTOTYPES
Packit bf707c
	va_start(args, err);
Packit bf707c
#else
Packit bf707c
	va_start(args);
Packit bf707c
#endif
Packit bf707c
	do {
Packit bf707c
		p = va_arg(args, char *);
Packit bf707c
		*pav++ = p;
Packit bf707c
	} while (p != NULL);
Packit bf707c
	va_end(args);
Packit bf707c
Packit bf707c
	ret =  fspawnv(in, out, err, ac, av);
Packit bf707c
	if (av != xav)
Packit bf707c
		free(av);
Packit bf707c
	return (ret);
Packit bf707c
}
Packit bf707c
Packit bf707c
EXPORT int
Packit bf707c
fspawnv_nowait(in, out, err, name, argc, argv)
Packit bf707c
	FILE		*in;
Packit bf707c
	FILE		*out;
Packit bf707c
	FILE		*err;
Packit bf707c
	const char	*name;
Packit bf707c
	int		argc;
Packit bf707c
	char		* const argv[];
Packit bf707c
{
Packit bf707c
	int	pid = -1;	/* Initialization needed to make GCC happy */
Packit bf707c
	int	i;
Packit bf707c
Packit bf707c
	for (i = 1; i < 64; i *= 2) {
Packit bf707c
		if ((pid = fork()) >= 0)
Packit bf707c
			break;
Packit bf707c
		sleep(i);
Packit bf707c
	}
Packit bf707c
	if (pid != 0)
Packit bf707c
		return (pid);
Packit bf707c
				/*
Packit bf707c
				 * silly: fexecv must set av[ac] = NULL
Packit bf707c
				 * so we have to cast argv tp (char **)
Packit bf707c
				 */
Packit bf707c
	fexecv(name, in, out, err, argc, (char **)argv);
Packit bf707c
	exit(geterrno());
Packit bf707c
	/* NOTREACHED */
Packit bf707c
#ifndef	lint
Packit bf707c
	return (0);		/* keep gnu compiler happy */
Packit bf707c
#endif
Packit bf707c
}
Packit bf707c
Packit bf707c
EXPORT int
Packit bf707c
wait_chld(pid)
Packit bf707c
	int	pid;
Packit bf707c
{
Packit bf707c
	int	died;
Packit bf707c
	WAIT_T	status;
Packit bf707c
Packit bf707c
	do {
Packit bf707c
		do {
Packit bf707c
			died = wait(&status);
Packit bf707c
		} while (died < 0 && geterrno() == EINTR);
Packit bf707c
		if (died < 0)
Packit bf707c
			return (died);
Packit bf707c
	} while (died != pid);
Packit bf707c
Packit bf707c
	if (WCOREDUMP(status))
Packit bf707c
		unlink("core");
Packit bf707c
Packit bf707c
	return (WEXITSTATUS(status));
Packit bf707c
}