include sys/select.h before ex/extern.h
[nvi.git] / ipc / ip_run.c
blobb870edcfe777024c41800b5101f290c3e1224bf4
1 /*-
2 * Copyright (c) 1996
3 * Rob Zimmermann. All rights reserved.
4 * Copyright (c) 1996
5 * Keith Bostic. All rights reserved.
7 * See the LICENSE file for redistribution information.
8 */
10 #include "config.h"
12 #ifndef lint
13 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 $";
14 #endif /* not lint */
16 #include <sys/types.h>
17 #include <sys/queue.h>
18 #include <sys/stat.h>
20 #include <bitstring.h>
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
28 #include <sys/socket.h>
30 #include "../common/common.h"
31 #include "ip.h"
32 #include "pathnames.h"
34 static void arg_format __P((char *, int *, char **[], int, int));
35 static void fatal __P((void));
36 #ifdef DEBUG
37 static void attach __P((void));
38 #endif
39 static int channel(int rpipe[2], int wpipe[2]);
41 char *vi_progname = "vi"; /* Global: program name. */
44 * vi_run --
45 * Run the vi program.
47 * PUBLIC: int vi_run __P((IPVI *, int, char *[]));
49 int
50 vi_run(ipvi, argc, argv)
51 IPVI *ipvi;
52 int argc;
53 char *argv[];
55 struct stat sb;
56 int pflag, rpipe[2], wpipe[2];
57 char *execp, **p_av, **t_av;
59 pflag = 0;
60 execp = VI;
62 /* Strip out any arguments that vi isn't going to understand. */
63 for (p_av = t_av = argv;;) {
64 if (*t_av == NULL) {
65 *p_av = NULL;
66 break;
68 if (!strcmp(*t_av, "--")) {
69 while ((*p_av++ = *++t_av) != NULL);
70 break;
72 #ifdef DEBUG
73 if (!memcmp(*t_av, "-D", sizeof("-D") - 1)) {
74 attach();
76 ++t_av;
77 --argc;
78 continue;
80 #endif
81 #ifdef TRACE
82 if (!memcmp(*t_av, "-T", sizeof("-T") - 1)) {
83 char *p = &t_av[0][sizeof("-T") - 1];
84 if (*p == '\0') {
85 --argc;
86 p = *++t_av;
88 vtrace_init(p);
89 ++t_av;
90 --argc;
91 continue;
93 #endif
94 if (!memcmp(*t_av, "-P", sizeof("-P") - 1)) {
95 if (t_av[0][2] != '\0') {
96 pflag = 1;
97 execp = t_av[0] + 2;
98 ++t_av;
99 --argc;
100 continue;
102 if (t_av[1] != NULL) {
103 pflag = 1;
104 execp = t_av[1];
105 t_av += 2;
106 argc -= 2;
107 continue;
110 *p_av++ = *t_av++;
114 * Open the communications channels. The pipes are named from the
115 * parent's viewpoint, meaning the screen reads from rpipe[0] and
116 * writes to wpipe[1]. The vi process reads from wpipe[0], and it
117 * writes to rpipe[1].
119 if (channel(rpipe, wpipe) == -1)
120 fatal();
121 ipvi->ifd = rpipe[0];
122 ipvi->ofd = wpipe[1];
125 * Reformat our arguments, adding a -I to the list. The first file
126 * descriptor for the -I argument is vi's input, and the second is
127 * vi's output.
129 arg_format(execp, &argc, &argv, wpipe[0], rpipe[1]);
131 /* Run vi. */
132 switch (ipvi->pid = fork()) {
133 case -1: /* Error. */
134 fatal();
135 /* NOTREACHED */
136 case 0: /* Child: Vi. */
137 (void)close(rpipe[0]);
138 (void)close(wpipe[1]);
141 * If the user didn't override the path and there's a local
142 * (debugging) nvi, run it, otherwise run the user's path,
143 * if specified, else run the compiled in path.
145 if (!pflag && stat("vi-ipc", &sb) == 0)
146 execv("vi-ipc", argv);
147 execv(execp, argv);
148 (void)fprintf(stderr,
149 "%s: %s %s\n", vi_progname, execp, strerror(errno));
150 (void)fprintf(stderr,
151 #ifdef DEBUG
152 "usage: %s [-D] [-P vi_program] [-T trace] [vi arguments]\n",
153 #else
154 "usage: %s [-P vi_program] [vi arguments]\n",
155 #endif
156 vi_progname);
157 _exit (1);
158 default: /* Parent: Screen. */
159 (void)close(rpipe[1]);
160 (void)close(wpipe[0]);
161 break;
163 return (0);
167 * fatal --
168 * Fatal error.
170 static void
171 fatal()
173 (void)fprintf(stderr, "%s: %s\n", vi_progname, strerror(errno));
174 exit (1);
177 static
178 int channel(int rpipe[2], int wpipe[2])
180 if (0) {
182 if (pipe(rpipe) == -1 || pipe(wpipe) == -1)
183 return -1;
185 } else {
187 int sockets[2];
189 if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sockets) == -1)
190 return -1;
192 rpipe[0] = sockets[0];
193 wpipe[0] = sockets[1];
194 if (((rpipe[1] = dup(sockets[1])) == -1) ||
195 ((wpipe[1] = dup(sockets[0])) == -1))
196 return -1;
202 * arg_format --
203 * Reformat our arguments to add the -I argument for vi.
205 static void
206 arg_format(execp, argcp, argvp, i_fd, o_fd)
207 char *execp, **argvp[];
208 int *argcp, i_fd, o_fd;
210 char *iarg, **largv, *p, **p_av, **t_av;
212 /* Get space for the argument array and the -I argument. */
213 if ((iarg = malloc(64)) == NULL ||
214 (largv = malloc((*argcp + 3) * sizeof(char *))) == NULL)
215 fatal();
216 memcpy(largv + 2, *argvp, *argcp * sizeof(char *) + 1);
218 /* Reset argv[0] to be the exec'd program. */
219 if ((p = strrchr(execp, '/')) == NULL)
220 largv[0] = execp;
221 else
222 largv[0] = p + 1;
224 /* Create the -I argument. */
225 (void)sprintf(iarg, "-I%d%s%d", i_fd, ".", o_fd);
226 largv[1] = iarg;
228 /* Copy any remaining arguments into the array. */
229 for (p_av = (*argvp) + 1, t_av = largv + 2;;)
230 if ((*t_av++ = *p_av++) == NULL)
231 break;
233 /* Reset the argument array. */
234 *argvp = largv;
237 #ifdef DEBUG
239 * attach --
240 * Pause and let the user attach a debugger.
242 static void
243 attach()
245 int fd;
246 char ch;
248 (void)printf("process %lu waiting, enter <CR> to continue: ",
249 (u_long)getpid());
250 (void)fflush(stdout);
252 if ((fd = open(_PATH_TTY, O_RDONLY, 0)) < 0) {
253 (void)fprintf(stderr,
254 "%s: %s, %s\n", vi_progname, _PATH_TTY, strerror(errno));
255 exit (1);;
257 do {
258 if (read(fd, &ch, 1) != 1) {
259 (void)close(fd);
260 return;
262 } while (ch != '\n' && ch != '\r');
263 (void)close(fd);
265 #endif