minix/external/bsd/nvi/dist/ipc/ip_run.c
Lionel Sambuc 84d9c625bf Synchronize on NetBSD-CVS (2013/12/1 12:00:00 UTC)
- Fix for possible unset uid/gid in toproto
 - Fix for default mtree style
 - Update libelf
 - Importing libexecinfo
 - Resynchronize GCC, mpc, gmp, mpfr
 - build.sh: Replace params with show-params.
     This has been done as the make target has been renamed in the same
     way, while a new target named params has been added. This new
     target generates a file containing all the parameters, instead of
     printing it on the console.
 - Update test48 with new etc/services (Fix by Ben Gras <ben@minix3.org)
     get getservbyport() out of the inner loop

Change-Id: Ie6ad5226fa2621ff9f0dee8782ea48f9443d2091
2014-07-28 17:05:06 +02:00

273 lines
5.6 KiB
C

/* $NetBSD: ip_run.c,v 1.6 2013/11/27 18:06:28 christos Exp $ */
/*-
* Copyright (c) 1996
* Rob Zimmermann. All rights reserved.
* Copyright (c) 1996
* Keith Bostic. All rights reserved.
*
* See the LICENSE file for redistribution information.
*/
#include "config.h"
#ifndef lint
static const char sccsid[] = "Id: ip_run.c,v 8.17 2000/07/04 21:48:54 skimo Exp (Berkeley) Date: 2000/07/04 21:48:54 ";
#endif /* not lint */
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/stat.h>
#include <bitstring.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include "../common/common.h"
#include "ip.h"
#include "pathnames.h"
static void arg_format __P((char *, int *, char **[], int, int));
static void fatal __P((void)) __dead;
#ifdef DEBUG
static void attach __P((void));
#endif
static int channel(int rpipe[2], int wpipe[2]);
const char *vi_progname = "vi"; /* Global: program name. */
/*
* vi_run --
* Run the vi program.
*
* PUBLIC: int vi_run __P((IPVI *, int, char *[]));
*/
int
vi_run(ipvi, argc, argv)
IPVI *ipvi;
int argc;
char *argv[];
{
struct stat sb;
int pflag, rpipe[2], wpipe[2];
char *execp, **p_av, **t_av;
pflag = 0;
execp = __UNCONST(vi_progname);
/* Strip out any arguments that vi isn't going to understand. */
for (p_av = t_av = argv;;) {
if (*t_av == NULL) {
*p_av = NULL;
break;
}
if (!strcmp(*t_av, "--")) {
while ((*p_av++ = *++t_av) != NULL);
break;
}
#ifdef DEBUG
if (!memcmp(*t_av, "-D", sizeof("-D") - 1)) {
attach();
++t_av;
--argc;
continue;
}
#endif
#ifdef TRACE
if (!memcmp(*t_av, "-T", sizeof("-T") - 1)) {
char *p = &t_av[0][sizeof("-T") - 1];
if (*p == '\0') {
--argc;
p = *++t_av;
}
vtrace_init(p);
++t_av;
--argc;
continue;
}
#endif
if (!memcmp(*t_av, "-P", sizeof("-P") - 1)) {
if (t_av[0][2] != '\0') {
pflag = 1;
execp = t_av[0] + 2;
++t_av;
--argc;
continue;
}
if (t_av[1] != NULL) {
pflag = 1;
execp = t_av[1];
t_av += 2;
argc -= 2;
continue;
}
}
*p_av++ = *t_av++;
}
/*
* Open the communications channels. The pipes are named from the
* parent's viewpoint, meaning the screen reads from rpipe[0] and
* writes to wpipe[1]. The vi process reads from wpipe[0], and it
* writes to rpipe[1].
*/
if (channel(rpipe, wpipe) == -1)
fatal();
ipvi->ifd = rpipe[0];
ipvi->ofd = wpipe[1];
/*
* Reformat our arguments, adding a -I to the list. The first file
* descriptor for the -I argument is vi's input, and the second is
* vi's output.
*/
arg_format(execp, &argc, &argv, wpipe[0], rpipe[1]);
/* Run vi. */
switch (ipvi->pid = fork()) {
case -1: /* Error. */
fatal();
/* NOTREACHED */
case 0: /* Child: Vi. */
(void)close(rpipe[0]);
(void)close(wpipe[1]);
/*
* If the user didn't override the path and there's a local
* (debugging) nvi, run it, otherwise run the user's path,
* if specified, else run the compiled in path.
*/
/* coverity[+toctou] */
if (!pflag && stat("vi-ipc", &sb) == 0)
execvp("vi-ipc", argv);
execvp(execp, argv);
(void)fprintf(stderr,
"%s: %s %s\n", vi_progname, execp, strerror(errno));
(void)fprintf(stderr,
#ifdef DEBUG
"usage: %s [-D] [-P vi_program] [-T trace] [vi arguments]\n",
#else
"usage: %s [-P vi_program] [vi arguments]\n",
#endif
vi_progname);
_exit (1);
default: /* Parent: Screen. */
(void)close(rpipe[1]);
(void)close(wpipe[0]);
break;
}
free(argv[1]);
free(argv);
return (0);
}
/*
* fatal --
* Fatal error.
*/
static void
fatal()
{
(void)fprintf(stderr, "%s: %s\n", vi_progname, strerror(errno));
exit (1);
}
static int
channel(int rpipe[2], int wpipe[2])
{
int x;
if ((x = pipe(rpipe) == -1) || pipe(wpipe) == -1) {
int sockets[2];
if (x != -1) {
close(rpipe[0]);
close(rpipe[1]);
}
if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sockets) == -1)
return -1;
rpipe[0] = sockets[0];
wpipe[0] = sockets[1];
if (((rpipe[1] = dup(sockets[1])) == -1) ||
((wpipe[1] = dup(sockets[0])) == -1)) {
close(sockets[0]);
close(sockets[1]);
if (rpipe[1] != -1)
close(rpipe[1]);
return -1;
}
}
return 0;
}
/*
* arg_format --
* Reformat our arguments to add the -I argument for vi.
*/
static void
arg_format(char *execp, int *argcp, char **argvp[], int i_fd, int o_fd)
{
char *iarg, **largv = NULL /* XXX gcc */, *p, **p_av, **t_av;
/* Get space for the argument array and the -I argument. */
if ((iarg = malloc(64)) == NULL ||
(largv = malloc((*argcp + 3) * sizeof(char *))) == NULL)
fatal();
memcpy(largv + 2, *argvp, *argcp * sizeof(char *) + 1);
/* Reset argv[0] to be the exec'd program. */
if ((p = strrchr(execp, '/')) == NULL)
largv[0] = execp;
else
largv[0] = p + 1;
/* Create the -I argument. */
(void)sprintf(iarg, "-I%d%s%d", i_fd, ".", o_fd);
largv[1] = iarg;
/* Copy any remaining arguments into the array. */
for (p_av = (*argvp) + 1, t_av = largv + 2;;)
if ((*t_av++ = *p_av++) == NULL)
break;
/* Reset the argument array. */
*argvp = largv;
}
#ifdef DEBUG
/*
* attach --
* Pause and let the user attach a debugger.
*/
static void
attach()
{
int fd;
char ch;
(void)printf("process %lu waiting, enter <CR> to continue: ",
(u_long)getpid());
(void)fflush(stdout);
if ((fd = open(_PATH_TTY, O_RDONLY, 0)) < 0) {
(void)fprintf(stderr,
"%s: %s, %s\n", vi_progname, _PATH_TTY, strerror(errno));
exit (1);;
}
do {
if (read(fd, &ch, 1) != 1) {
(void)close(fd);
return;
}
} while (ch != '\n' && ch != '\r');
(void)close(fd);
}
#endif