break Motif code up into motif and motif_l
[nvi.git] / ipc / ip_run.c
blob19f028b56f68f24ebae32587bc91d453155cc956
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.7 1996/12/11 20:57:03 bostic Exp $ (Berkeley) $Date: 1996/12/11 20:57:03 $";
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/ip.h"
30 #include "ipc_extern.h"
31 #include "pathnames.h"
33 static void arg_format __P((char *, int *, char **[], int, int));
34 static void fatal __P((void));
35 #ifdef DEBUG
36 static void attach __P((void));
37 #endif
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, **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 if (!memcmp(*t_av, "-T", sizeof("-T") - 1)) {
80 p = &t_av[0][sizeof("-T") - 1];
81 if (*p == '\0') {
82 --argc;
83 p = *++t_av;
85 trace_init(p);
86 ++t_av;
87 --argc;
88 continue;
90 #endif
91 if (!memcmp(*t_av, "-P", sizeof("-P") - 1)) {
92 if (t_av[0][2] != '\0') {
93 pflag = 1;
94 execp = t_av[0] + 2;
95 ++t_av;
96 --argc;
97 continue;
99 if (t_av[1] != NULL) {
100 pflag = 1;
101 execp = t_av[1];
102 t_av += 2;
103 argc -= 2;
104 continue;
107 *p_av++ = *t_av++;
111 * Open the communications channels. The pipes are named from the
112 * parent's viewpoint, meaning the screen reads from rpipe[0] and
113 * writes to wpipe[1]. The vi process reads from wpipe[0], and it
114 * writes to rpipe[1].
116 if (pipe(rpipe) == -1 || pipe(wpipe) == -1)
117 fatal();
118 *ip = rpipe[0];
119 *op = wpipe[1];
122 * Reformat our arguments, adding a -I to the list. The first file
123 * descriptor for the -I argument is vi's input, and the second is
124 * vi's output.
126 arg_format(execp, &argc, &argv, wpipe[0], rpipe[1]);
128 /* Run vi. */
129 switch (*pidp = fork()) {
130 case -1: /* Error. */
131 fatal();
132 /* NOTREACHED */
133 case 0: /* Child: Vi. */
134 (void)close(rpipe[0]);
135 (void)close(wpipe[1]);
138 * If the user didn't override the path and there's a local
139 * (debugging) nvi, run it, otherwise run the user's path,
140 * if specified, else run the compiled in path.
142 if (!pflag && stat("vi", &sb) == 0)
143 execv("vi", argv);
144 execv(execp, argv);
145 (void)fprintf(stderr,
146 "%s: %s %s\n", vi_progname, execp, strerror(errno));
147 (void)fprintf(stderr,
148 #ifdef DEBUG
149 "usage: %s [-D] [-P vi_program] [-T trace] [vi arguments]\n",
150 #else
151 "usage: %s [-P vi_program] [vi arguments]\n",
152 #endif
153 vi_progname);
154 _exit (1);
155 default: /* Parent: Screen. */
156 (void)close(rpipe[1]);
157 (void)close(wpipe[0]);
158 break;
160 return (0);
164 * fatal --
165 * Fatal error.
167 static void
168 fatal()
170 (void)fprintf(stderr, "%s: %s\n", vi_progname, strerror(errno));
171 exit (1);
175 * arg_format --
176 * Reformat our arguments to add the -I argument for vi.
178 static void
179 arg_format(execp, argcp, argvp, i_fd, o_fd)
180 char *execp, **argvp[];
181 int *argcp, i_fd, o_fd;
183 char *iarg, **largv, *p, **p_av, **t_av;
185 /* Get space for the argument array and the -I argument. */
186 if ((iarg = malloc(64)) == NULL ||
187 (largv = malloc((*argcp + 3) * sizeof(char *))) == NULL)
188 fatal();
189 memcpy(largv + 2, *argvp, *argcp * sizeof(char *) + 1);
191 /* Reset argv[0] to be the exec'd program. */
192 if ((p = strrchr(execp, '/')) == NULL)
193 largv[0] = execp;
194 else
195 largv[0] = p + 1;
197 /* Create the -I argument. */
198 (void)sprintf(iarg, "-I%d%s%d", i_fd, ".", o_fd);
199 largv[1] = iarg;
201 /* Copy any remaining arguments into the array. */
202 for (p_av = (*argvp) + 1, t_av = largv + 2;;)
203 if ((*t_av++ = *p_av++) == NULL)
204 break;
206 /* Reset the argument array. */
207 *argvp = largv;
210 #ifdef DEBUG
212 * attach --
213 * Pause and let the user attach a debugger.
215 static void
216 attach()
218 int fd;
219 char ch;
221 (void)printf("process %lu waiting, enter <CR> to continue: ",
222 (u_long)getpid());
223 (void)fflush(stdout);
225 if ((fd = open(_PATH_TTY, O_RDONLY, 0)) < 0) {
226 (void)fprintf(stderr,
227 "%s: %s, %s\n", vi_progname, _PATH_TTY, strerror(errno));
228 exit (1);;
230 do {
231 if (read(fd, &ch, 1) != 1) {
232 (void)close(fd);
233 return;
235 } while (ch != '\n' && ch != '\r');
236 (void)close(fd);
238 #endif