ip_run.c revision 1.7.4.2 1 1.7.4.2 yamt /* $NetBSD: ip_run.c,v 1.7.4.2 2014/05/22 15:50:35 yamt Exp $ */
2 1.7.4.2 yamt /*-
3 1.7.4.2 yamt * Copyright (c) 1996
4 1.7.4.2 yamt * Rob Zimmermann. All rights reserved.
5 1.7.4.2 yamt * Copyright (c) 1996
6 1.7.4.2 yamt * Keith Bostic. All rights reserved.
7 1.7.4.2 yamt *
8 1.7.4.2 yamt * See the LICENSE file for redistribution information.
9 1.7.4.2 yamt */
10 1.7.4.2 yamt
11 1.7.4.2 yamt #include "config.h"
12 1.7.4.2 yamt
13 1.7.4.2 yamt #include <sys/cdefs.h>
14 1.7.4.2 yamt #if 0
15 1.7.4.2 yamt #ifndef lint
16 1.7.4.2 yamt 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 ";
17 1.7.4.2 yamt #endif /* not lint */
18 1.7.4.2 yamt #else
19 1.7.4.2 yamt __RCSID("$NetBSD: ip_run.c,v 1.7.4.2 2014/05/22 15:50:35 yamt Exp $");
20 1.7.4.2 yamt #endif
21 1.7.4.2 yamt
22 1.7.4.2 yamt #include <sys/types.h>
23 1.7.4.2 yamt #include <sys/queue.h>
24 1.7.4.2 yamt #include <sys/stat.h>
25 1.7.4.2 yamt
26 1.7.4.2 yamt #include <bitstring.h>
27 1.7.4.2 yamt #include <errno.h>
28 1.7.4.2 yamt #include <fcntl.h>
29 1.7.4.2 yamt #include <stdio.h>
30 1.7.4.2 yamt #include <stdlib.h>
31 1.7.4.2 yamt #include <string.h>
32 1.7.4.2 yamt #include <unistd.h>
33 1.7.4.2 yamt
34 1.7.4.2 yamt #include <sys/socket.h>
35 1.7.4.2 yamt
36 1.7.4.2 yamt #include "../common/common.h"
37 1.7.4.2 yamt #include "ip.h"
38 1.7.4.2 yamt #include "pathnames.h"
39 1.7.4.2 yamt
40 1.7.4.2 yamt static void arg_format __P((char *, int *, char **[], int, int));
41 1.7.4.2 yamt static void fatal __P((void)) __dead;
42 1.7.4.2 yamt #ifdef DEBUG
43 1.7.4.2 yamt static void attach __P((void));
44 1.7.4.2 yamt #endif
45 1.7.4.2 yamt static int channel(int rpipe[2], int wpipe[2]);
46 1.7.4.2 yamt
47 1.7.4.2 yamt const char *vi_progname = "vi"; /* Global: program name. */
48 1.7.4.2 yamt
49 1.7.4.2 yamt /*
50 1.7.4.2 yamt * vi_run --
51 1.7.4.2 yamt * Run the vi program.
52 1.7.4.2 yamt *
53 1.7.4.2 yamt * PUBLIC: int vi_run __P((IPVI *, int, char *[]));
54 1.7.4.2 yamt */
55 1.7.4.2 yamt int
56 1.7.4.2 yamt vi_run(ipvi, argc, argv)
57 1.7.4.2 yamt IPVI *ipvi;
58 1.7.4.2 yamt int argc;
59 1.7.4.2 yamt char *argv[];
60 1.7.4.2 yamt {
61 1.7.4.2 yamt struct stat sb;
62 1.7.4.2 yamt int pflag, rpipe[2], wpipe[2];
63 1.7.4.2 yamt char *execp, **p_av, **t_av;
64 1.7.4.2 yamt
65 1.7.4.2 yamt pflag = 0;
66 1.7.4.2 yamt execp = __UNCONST(vi_progname);
67 1.7.4.2 yamt
68 1.7.4.2 yamt /* Strip out any arguments that vi isn't going to understand. */
69 1.7.4.2 yamt for (p_av = t_av = argv;;) {
70 1.7.4.2 yamt if (*t_av == NULL) {
71 1.7.4.2 yamt *p_av = NULL;
72 1.7.4.2 yamt break;
73 1.7.4.2 yamt }
74 1.7.4.2 yamt if (!strcmp(*t_av, "--")) {
75 1.7.4.2 yamt while ((*p_av++ = *++t_av) != NULL);
76 1.7.4.2 yamt break;
77 1.7.4.2 yamt }
78 1.7.4.2 yamt #ifdef DEBUG
79 1.7.4.2 yamt if (!memcmp(*t_av, "-D", sizeof("-D") - 1)) {
80 1.7.4.2 yamt attach();
81 1.7.4.2 yamt
82 1.7.4.2 yamt ++t_av;
83 1.7.4.2 yamt --argc;
84 1.7.4.2 yamt continue;
85 1.7.4.2 yamt }
86 1.7.4.2 yamt #endif
87 1.7.4.2 yamt #ifdef TRACE
88 1.7.4.2 yamt if (!memcmp(*t_av, "-T", sizeof("-T") - 1)) {
89 1.7.4.2 yamt char *p = &t_av[0][sizeof("-T") - 1];
90 1.7.4.2 yamt if (*p == '\0') {
91 1.7.4.2 yamt --argc;
92 1.7.4.2 yamt p = *++t_av;
93 1.7.4.2 yamt }
94 1.7.4.2 yamt vtrace_init(p);
95 1.7.4.2 yamt ++t_av;
96 1.7.4.2 yamt --argc;
97 1.7.4.2 yamt continue;
98 1.7.4.2 yamt }
99 1.7.4.2 yamt #endif
100 1.7.4.2 yamt if (!memcmp(*t_av, "-P", sizeof("-P") - 1)) {
101 1.7.4.2 yamt if (t_av[0][2] != '\0') {
102 1.7.4.2 yamt pflag = 1;
103 1.7.4.2 yamt execp = t_av[0] + 2;
104 1.7.4.2 yamt ++t_av;
105 1.7.4.2 yamt --argc;
106 1.7.4.2 yamt continue;
107 1.7.4.2 yamt }
108 1.7.4.2 yamt if (t_av[1] != NULL) {
109 1.7.4.2 yamt pflag = 1;
110 1.7.4.2 yamt execp = t_av[1];
111 1.7.4.2 yamt t_av += 2;
112 1.7.4.2 yamt argc -= 2;
113 1.7.4.2 yamt continue;
114 1.7.4.2 yamt }
115 1.7.4.2 yamt }
116 1.7.4.2 yamt *p_av++ = *t_av++;
117 1.7.4.2 yamt }
118 1.7.4.2 yamt
119 1.7.4.2 yamt /*
120 1.7.4.2 yamt * Open the communications channels. The pipes are named from the
121 1.7.4.2 yamt * parent's viewpoint, meaning the screen reads from rpipe[0] and
122 1.7.4.2 yamt * writes to wpipe[1]. The vi process reads from wpipe[0], and it
123 1.7.4.2 yamt * writes to rpipe[1].
124 1.7.4.2 yamt */
125 1.7.4.2 yamt if (channel(rpipe, wpipe) == -1)
126 1.7.4.2 yamt fatal();
127 1.7.4.2 yamt ipvi->ifd = rpipe[0];
128 1.7.4.2 yamt ipvi->ofd = wpipe[1];
129 1.7.4.2 yamt
130 1.7.4.2 yamt /*
131 1.7.4.2 yamt * Reformat our arguments, adding a -I to the list. The first file
132 1.7.4.2 yamt * descriptor for the -I argument is vi's input, and the second is
133 1.7.4.2 yamt * vi's output.
134 1.7.4.2 yamt */
135 1.7.4.2 yamt arg_format(execp, &argc, &argv, wpipe[0], rpipe[1]);
136 1.7.4.2 yamt
137 1.7.4.2 yamt /* Run vi. */
138 1.7.4.2 yamt switch (ipvi->pid = fork()) {
139 1.7.4.2 yamt case -1: /* Error. */
140 1.7.4.2 yamt fatal();
141 1.7.4.2 yamt /* NOTREACHED */
142 1.7.4.2 yamt case 0: /* Child: Vi. */
143 1.7.4.2 yamt (void)close(rpipe[0]);
144 1.7.4.2 yamt (void)close(wpipe[1]);
145 1.7.4.2 yamt
146 1.7.4.2 yamt /*
147 1.7.4.2 yamt * If the user didn't override the path and there's a local
148 1.7.4.2 yamt * (debugging) nvi, run it, otherwise run the user's path,
149 1.7.4.2 yamt * if specified, else run the compiled in path.
150 1.7.4.2 yamt */
151 1.7.4.2 yamt /* coverity[+toctou] */
152 1.7.4.2 yamt if (!pflag && stat("vi-ipc", &sb) == 0)
153 1.7.4.2 yamt execvp("vi-ipc", argv);
154 1.7.4.2 yamt execvp(execp, argv);
155 1.7.4.2 yamt (void)fprintf(stderr,
156 1.7.4.2 yamt "%s: %s %s\n", vi_progname, execp, strerror(errno));
157 1.7.4.2 yamt (void)fprintf(stderr,
158 1.7.4.2 yamt #ifdef DEBUG
159 1.7.4.2 yamt "usage: %s [-D] [-P vi_program] [-T trace] [vi arguments]\n",
160 1.7.4.2 yamt #else
161 1.7.4.2 yamt "usage: %s [-P vi_program] [vi arguments]\n",
162 1.7.4.2 yamt #endif
163 1.7.4.2 yamt vi_progname);
164 1.7.4.2 yamt _exit (1);
165 1.7.4.2 yamt default: /* Parent: Screen. */
166 1.7.4.2 yamt (void)close(rpipe[1]);
167 1.7.4.2 yamt (void)close(wpipe[0]);
168 1.7.4.2 yamt break;
169 1.7.4.2 yamt }
170 1.7.4.2 yamt free(argv[1]);
171 1.7.4.2 yamt free(argv);
172 1.7.4.2 yamt return (0);
173 1.7.4.2 yamt }
174 1.7.4.2 yamt
175 1.7.4.2 yamt /*
176 1.7.4.2 yamt * fatal --
177 1.7.4.2 yamt * Fatal error.
178 1.7.4.2 yamt */
179 1.7.4.2 yamt static void
180 1.7.4.2 yamt fatal()
181 1.7.4.2 yamt {
182 1.7.4.2 yamt (void)fprintf(stderr, "%s: %s\n", vi_progname, strerror(errno));
183 1.7.4.2 yamt exit (1);
184 1.7.4.2 yamt }
185 1.7.4.2 yamt
186 1.7.4.2 yamt static int
187 1.7.4.2 yamt channel(int rpipe[2], int wpipe[2])
188 1.7.4.2 yamt {
189 1.7.4.2 yamt int x;
190 1.7.4.2 yamt if ((x = pipe(rpipe) == -1) || pipe(wpipe) == -1) {
191 1.7.4.2 yamt int sockets[2];
192 1.7.4.2 yamt
193 1.7.4.2 yamt if (x != -1) {
194 1.7.4.2 yamt close(rpipe[0]);
195 1.7.4.2 yamt close(rpipe[1]);
196 1.7.4.2 yamt }
197 1.7.4.2 yamt
198 1.7.4.2 yamt if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sockets) == -1)
199 1.7.4.2 yamt return -1;
200 1.7.4.2 yamt
201 1.7.4.2 yamt rpipe[0] = sockets[0];
202 1.7.4.2 yamt wpipe[0] = sockets[1];
203 1.7.4.2 yamt if (((rpipe[1] = dup(sockets[1])) == -1) ||
204 1.7.4.2 yamt ((wpipe[1] = dup(sockets[0])) == -1)) {
205 1.7.4.2 yamt close(sockets[0]);
206 1.7.4.2 yamt close(sockets[1]);
207 1.7.4.2 yamt if (rpipe[1] != -1)
208 1.7.4.2 yamt close(rpipe[1]);
209 1.7.4.2 yamt return -1;
210 1.7.4.2 yamt }
211 1.7.4.2 yamt
212 1.7.4.2 yamt }
213 1.7.4.2 yamt return 0;
214 1.7.4.2 yamt }
215 1.7.4.2 yamt
216 1.7.4.2 yamt /*
217 1.7.4.2 yamt * arg_format --
218 1.7.4.2 yamt * Reformat our arguments to add the -I argument for vi.
219 1.7.4.2 yamt */
220 1.7.4.2 yamt static void
221 1.7.4.2 yamt arg_format(char *execp, int *argcp, char **argvp[], int i_fd, int o_fd)
222 1.7.4.2 yamt {
223 1.7.4.2 yamt char *iarg, **largv = NULL /* XXX gcc */, *p, **p_av, **t_av;
224 1.7.4.2 yamt
225 1.7.4.2 yamt /* Get space for the argument array and the -I argument. */
226 1.7.4.2 yamt if ((iarg = malloc(64)) == NULL ||
227 1.7.4.2 yamt (largv = malloc((*argcp + 3) * sizeof(char *))) == NULL)
228 1.7.4.2 yamt fatal();
229 1.7.4.2 yamt memcpy(largv + 2, *argvp, *argcp * sizeof(char *) + 1);
230 1.7.4.2 yamt
231 1.7.4.2 yamt /* Reset argv[0] to be the exec'd program. */
232 1.7.4.2 yamt if ((p = strrchr(execp, '/')) == NULL)
233 1.7.4.2 yamt largv[0] = execp;
234 1.7.4.2 yamt else
235 1.7.4.2 yamt largv[0] = p + 1;
236 1.7.4.2 yamt
237 1.7.4.2 yamt /* Create the -I argument. */
238 1.7.4.2 yamt (void)sprintf(iarg, "-I%d%s%d", i_fd, ".", o_fd);
239 1.7.4.2 yamt largv[1] = iarg;
240 1.7.4.2 yamt
241 1.7.4.2 yamt /* Copy any remaining arguments into the array. */
242 1.7.4.2 yamt for (p_av = (*argvp) + 1, t_av = largv + 2;;)
243 1.7.4.2 yamt if ((*t_av++ = *p_av++) == NULL)
244 1.7.4.2 yamt break;
245 1.7.4.2 yamt
246 1.7.4.2 yamt /* Reset the argument array. */
247 1.7.4.2 yamt *argvp = largv;
248 1.7.4.2 yamt }
249 1.7.4.2 yamt
250 1.7.4.2 yamt #ifdef DEBUG
251 1.7.4.2 yamt /*
252 1.7.4.2 yamt * attach --
253 1.7.4.2 yamt * Pause and let the user attach a debugger.
254 1.7.4.2 yamt */
255 1.7.4.2 yamt static void
256 1.7.4.2 yamt attach()
257 1.7.4.2 yamt {
258 1.7.4.2 yamt int fd;
259 1.7.4.2 yamt char ch;
260 1.7.4.2 yamt
261 1.7.4.2 yamt (void)printf("process %lu waiting, enter <CR> to continue: ",
262 1.7.4.2 yamt (u_long)getpid());
263 1.7.4.2 yamt (void)fflush(stdout);
264 1.7.4.2 yamt
265 1.7.4.2 yamt if ((fd = open(_PATH_TTY, O_RDONLY, 0)) < 0) {
266 1.7.4.2 yamt (void)fprintf(stderr,
267 1.7.4.2 yamt "%s: %s, %s\n", vi_progname, _PATH_TTY, strerror(errno));
268 1.7.4.2 yamt exit (1);;
269 1.7.4.2 yamt }
270 1.7.4.2 yamt do {
271 1.7.4.2 yamt if (read(fd, &ch, 1) != 1) {
272 1.7.4.2 yamt (void)close(fd);
273 1.7.4.2 yamt return;
274 1.7.4.2 yamt }
275 1.7.4.2 yamt } while (ch != '\n' && ch != '\r');
276 1.7.4.2 yamt (void)close(fd);
277 1.7.4.2 yamt }
278 1.7.4.2 yamt #endif
279