Sync usage with man page.
[netbsd-mini2440.git] / dist / nvi / ipc / ip_run.c
blobdfea2bbbcb60ef1eb631819d416c3ce862092289
1 /* $NetBSD$ */
3 /*-
4 * Copyright (c) 1996
5 * Rob Zimmermann. All rights reserved.
6 * Copyright (c) 1996
7 * Keith Bostic. All rights reserved.
9 * See the LICENSE file for redistribution information.
12 #include "config.h"
14 #ifndef lint
15 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";
16 #endif /* not lint */
18 #include <sys/types.h>
19 #include <sys/queue.h>
20 #include <sys/stat.h>
22 #include <bitstring.h>
23 #include <errno.h>
24 #include <fcntl.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
30 #include <sys/socket.h>
32 #include "../common/common.h"
33 #include "ip.h"
34 #include "pathnames.h"
36 static void arg_format __P((char *, int *, char **[], int, int));
37 static void fatal __P((void));
38 #ifdef DEBUG
39 static void attach __P((void));
40 #endif
41 static int channel(int rpipe[2], int wpipe[2]);
43 char *vi_progname = "vi"; /* Global: program name. */
46 * vi_run --
47 * Run the vi program.
49 * PUBLIC: int vi_run __P((IPVI *, int, char *[]));
51 int
52 vi_run(ipvi, argc, argv)
53 IPVI *ipvi;
54 int argc;
55 char *argv[];
57 struct stat sb;
58 int pflag, rpipe[2], wpipe[2];
59 char *execp, **p_av, **t_av;
61 pflag = 0;
62 execp = VI;
64 /* Strip out any arguments that vi isn't going to understand. */
65 for (p_av = t_av = argv;;) {
66 if (*t_av == NULL) {
67 *p_av = NULL;
68 break;
70 if (!strcmp(*t_av, "--")) {
71 while ((*p_av++ = *++t_av) != NULL);
72 break;
74 #ifdef DEBUG
75 if (!memcmp(*t_av, "-D", sizeof("-D") - 1)) {
76 attach();
78 ++t_av;
79 --argc;
80 continue;
82 #endif
83 #ifdef TRACE
84 if (!memcmp(*t_av, "-T", sizeof("-T") - 1)) {
85 char *p = &t_av[0][sizeof("-T") - 1];
86 if (*p == '\0') {
87 --argc;
88 p = *++t_av;
90 vtrace_init(p);
91 ++t_av;
92 --argc;
93 continue;
95 #endif
96 if (!memcmp(*t_av, "-P", sizeof("-P") - 1)) {
97 if (t_av[0][2] != '\0') {
98 pflag = 1;
99 execp = t_av[0] + 2;
100 ++t_av;
101 --argc;
102 continue;
104 if (t_av[1] != NULL) {
105 pflag = 1;
106 execp = t_av[1];
107 t_av += 2;
108 argc -= 2;
109 continue;
112 *p_av++ = *t_av++;
116 * Open the communications channels. The pipes are named from the
117 * parent's viewpoint, meaning the screen reads from rpipe[0] and
118 * writes to wpipe[1]. The vi process reads from wpipe[0], and it
119 * writes to rpipe[1].
121 if (channel(rpipe, wpipe) == -1)
122 fatal();
123 ipvi->ifd = rpipe[0];
124 ipvi->ofd = wpipe[1];
127 * Reformat our arguments, adding a -I to the list. The first file
128 * descriptor for the -I argument is vi's input, and the second is
129 * vi's output.
131 arg_format(execp, &argc, &argv, wpipe[0], rpipe[1]);
133 /* Run vi. */
134 switch (ipvi->pid = fork()) {
135 case -1: /* Error. */
136 fatal();
137 /* NOTREACHED */
138 case 0: /* Child: Vi. */
139 (void)close(rpipe[0]);
140 (void)close(wpipe[1]);
143 * If the user didn't override the path and there's a local
144 * (debugging) nvi, run it, otherwise run the user's path,
145 * if specified, else run the compiled in path.
147 if (!pflag && stat("vi-ipc", &sb) == 0)
148 execv("vi-ipc", argv);
149 execv(execp, argv);
150 (void)fprintf(stderr,
151 "%s: %s %s\n", vi_progname, execp, strerror(errno));
152 (void)fprintf(stderr,
153 #ifdef DEBUG
154 "usage: %s [-D] [-P vi_program] [-T trace] [vi arguments]\n",
155 #else
156 "usage: %s [-P vi_program] [vi arguments]\n",
157 #endif
158 vi_progname);
159 _exit (1);
160 default: /* Parent: Screen. */
161 (void)close(rpipe[1]);
162 (void)close(wpipe[0]);
163 break;
165 return (0);
169 * fatal --
170 * Fatal error.
172 static void
173 fatal()
175 (void)fprintf(stderr, "%s: %s\n", vi_progname, strerror(errno));
176 exit (1);
179 static
180 int channel(int rpipe[2], int wpipe[2])
182 if (0) {
184 if (pipe(rpipe) == -1 || pipe(wpipe) == -1)
185 return -1;
187 } else {
189 int sockets[2];
191 if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sockets) == -1)
192 return -1;
194 rpipe[0] = sockets[0];
195 wpipe[0] = sockets[1];
196 if (((rpipe[1] = dup(sockets[1])) == -1) ||
197 ((wpipe[1] = dup(sockets[0])) == -1))
198 return -1;
204 * arg_format --
205 * Reformat our arguments to add the -I argument for vi.
207 static void
208 arg_format(execp, argcp, argvp, i_fd, o_fd)
209 char *execp, **argvp[];
210 int *argcp, i_fd, o_fd;
212 char *iarg, **largv, *p, **p_av, **t_av;
214 /* Get space for the argument array and the -I argument. */
215 if ((iarg = malloc(64)) == NULL ||
216 (largv = malloc((*argcp + 3) * sizeof(char *))) == NULL)
217 fatal();
218 memcpy(largv + 2, *argvp, *argcp * sizeof(char *) + 1);
220 /* Reset argv[0] to be the exec'd program. */
221 if ((p = strrchr(execp, '/')) == NULL)
222 largv[0] = execp;
223 else
224 largv[0] = p + 1;
226 /* Create the -I argument. */
227 (void)sprintf(iarg, "-I%d%s%d", i_fd, ".", o_fd);
228 largv[1] = iarg;
230 /* Copy any remaining arguments into the array. */
231 for (p_av = (*argvp) + 1, t_av = largv + 2;;)
232 if ((*t_av++ = *p_av++) == NULL)
233 break;
235 /* Reset the argument array. */
236 *argvp = largv;
239 #ifdef DEBUG
241 * attach --
242 * Pause and let the user attach a debugger.
244 static void
245 attach()
247 int fd;
248 char ch;
250 (void)printf("process %lu waiting, enter <CR> to continue: ",
251 (u_long)getpid());
252 (void)fflush(stdout);
254 if ((fd = open(_PATH_TTY, O_RDONLY, 0)) < 0) {
255 (void)fprintf(stderr,
256 "%s: %s, %s\n", vi_progname, _PATH_TTY, strerror(errno));
257 exit (1);;
259 do {
260 if (read(fd, &ch, 1) != 1) {
261 (void)close(fd);
262 return;
264 } while (ch != '\n' && ch != '\r');
265 (void)close(fd);
267 #endif