update from From: Sven Verdoolaege <skimo@breughel.ufsia.ac.be>
[nvi.git] / ipc / ip_run.c
blob845a9d88331fa0aeb19698380c8cd57f4e923161
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.13 1997/08/03 15:31:34 bostic Exp $ (Berkeley) $Date: 1997/08/03 15:31:34 $";
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 "../common/common.h"
29 #include "ip.h"
30 #include "pathnames.h"
32 static void arg_format __P((char *, int *, char **[], int, int));
33 static void fatal __P((void));
34 #ifdef DEBUG
35 static void attach __P((void));
36 #endif
38 int vi_ifd = -1; /* Global: input fd. */
39 int vi_ofd = -1; /* Global: output fd. */
40 char *vi_progname = "vi"; /* Global: program name. */
43 * vi_run --
44 * Run the vi program.
46 * PUBLIC: int vi_run __P((int, char *[], int *, int *, pid_t *));
48 int
49 vi_run(argc, argv, ip, op, pidp)
50 int argc, *ip, *op;
51 char *argv[];
52 pid_t *pidp;
54 struct stat sb;
55 int pflag, rpipe[2], wpipe[2];
56 char *execp, **p_av, **t_av;
58 pflag = 0;
59 execp = VI;
61 /* Strip out any arguments that vi isn't going to understand. */
62 for (p_av = t_av = argv;;) {
63 if (*t_av == NULL) {
64 *p_av = NULL;
65 break;
67 if (!strcmp(*t_av, "--")) {
68 while ((*p_av++ = *++t_av) != NULL);
69 break;
71 #ifdef DEBUG
72 if (!memcmp(*t_av, "-D", sizeof("-D") - 1)) {
73 attach();
75 ++t_av;
76 --argc;
77 continue;
79 #endif
80 #ifdef TRACE
81 if (!memcmp(*t_av, "-T", sizeof("-T") - 1)) {
82 char *p = &t_av[0][sizeof("-T") - 1];
83 if (*p == '\0') {
84 --argc;
85 p = *++t_av;
87 vtrace_init(p);
88 ++t_av;
89 --argc;
90 continue;
92 #endif
93 if (!memcmp(*t_av, "-P", sizeof("-P") - 1)) {
94 if (t_av[0][2] != '\0') {
95 pflag = 1;
96 execp = t_av[0] + 2;
97 ++t_av;
98 --argc;
99 continue;
101 if (t_av[1] != NULL) {
102 pflag = 1;
103 execp = t_av[1];
104 t_av += 2;
105 argc -= 2;
106 continue;
109 *p_av++ = *t_av++;
113 * Open the communications channels. The pipes are named from the
114 * parent's viewpoint, meaning the screen reads from rpipe[0] and
115 * writes to wpipe[1]. The vi process reads from wpipe[0], and it
116 * writes to rpipe[1].
118 if (pipe(rpipe) == -1 || pipe(wpipe) == -1)
119 fatal();
120 *ip = rpipe[0];
121 *op = wpipe[1];
124 * Reformat our arguments, adding a -I to the list. The first file
125 * descriptor for the -I argument is vi's input, and the second is
126 * vi's output.
128 arg_format(execp, &argc, &argv, wpipe[0], rpipe[1]);
130 /* Run vi. */
131 switch (*pidp = fork()) {
132 case -1: /* Error. */
133 fatal();
134 /* NOTREACHED */
135 case 0: /* Child: Vi. */
136 (void)close(rpipe[0]);
137 (void)close(wpipe[1]);
140 * If the user didn't override the path and there's a local
141 * (debugging) nvi, run it, otherwise run the user's path,
142 * if specified, else run the compiled in path.
144 if (!pflag && stat("vi", &sb) == 0)
145 execv("vi", argv);
146 execv(execp, argv);
147 (void)fprintf(stderr,
148 "%s: %s %s\n", vi_progname, execp, strerror(errno));
149 (void)fprintf(stderr,
150 #ifdef DEBUG
151 "usage: %s [-D] [-P vi_program] [-T trace] [vi arguments]\n",
152 #else
153 "usage: %s [-P vi_program] [vi arguments]\n",
154 #endif
155 vi_progname);
156 _exit (1);
157 default: /* Parent: Screen. */
158 (void)close(rpipe[1]);
159 (void)close(wpipe[0]);
160 break;
162 return (0);
166 * fatal --
167 * Fatal error.
169 static void
170 fatal()
172 (void)fprintf(stderr, "%s: %s\n", vi_progname, strerror(errno));
173 exit (1);
177 * arg_format --
178 * Reformat our arguments to add the -I argument for vi.
180 static void
181 arg_format(execp, argcp, argvp, i_fd, o_fd)
182 char *execp, **argvp[];
183 int *argcp, i_fd, o_fd;
185 char *iarg, **largv, *p, **p_av, **t_av;
187 /* Get space for the argument array and the -I argument. */
188 if ((iarg = malloc(64)) == NULL ||
189 (largv = malloc((*argcp + 3) * sizeof(char *))) == NULL)
190 fatal();
191 memcpy(largv + 2, *argvp, *argcp * sizeof(char *) + 1);
193 /* Reset argv[0] to be the exec'd program. */
194 if ((p = strrchr(execp, '/')) == NULL)
195 largv[0] = execp;
196 else
197 largv[0] = p + 1;
199 /* Create the -I argument. */
200 (void)sprintf(iarg, "-I%d%s%d", i_fd, ".", o_fd);
201 largv[1] = iarg;
203 /* Copy any remaining arguments into the array. */
204 for (p_av = (*argvp) + 1, t_av = largv + 2;;)
205 if ((*t_av++ = *p_av++) == NULL)
206 break;
208 /* Reset the argument array. */
209 *argvp = largv;
212 #ifdef DEBUG
214 * attach --
215 * Pause and let the user attach a debugger.
217 static void
218 attach()
220 int fd;
221 char ch;
223 (void)printf("process %lu waiting, enter <CR> to continue: ",
224 (u_long)getpid());
225 (void)fflush(stdout);
227 if ((fd = open(_PATH_TTY, O_RDONLY, 0)) < 0) {
228 (void)fprintf(stderr,
229 "%s: %s, %s\n", vi_progname, _PATH_TTY, strerror(errno));
230 exit (1);;
232 do {
233 if (read(fd, &ch, 1) != 1) {
234 (void)close(fd);
235 return;
237 } while (ch != '\n' && ch != '\r');
238 (void)close(fd);
240 #endif