distrib: let automake add missing files
[nvi.git] / ip / ip_main.c
blob8d266ba8809aa316c2ad94ea0370803cb7ff43c5
1 /*-
2 * Copyright (c) 1996
3 * Keith Bostic. All rights reserved.
5 * See the LICENSE file for redistribution information.
6 */
8 #include "config.h"
10 #ifndef lint
11 static const char sccsid[] = "$Id: ip_main.c,v 8.24 2001/07/29 19:07:30 skimo Exp $ (Berkeley) $Date: 2001/07/29 19:07:30 $";
12 #endif /* not lint */
14 #include <sys/types.h>
15 #include <sys/queue.h>
17 #include <bitstring.h>
18 #include <ctype.h>
19 #include <errno.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
25 #include <sys/uio.h>
27 #include "../common/common.h"
28 #include "../ipc/ip.h"
29 #include "extern.h"
31 GS *__global_list; /* GLOBAL: List of screens. */
33 static void ip_func_std __P((WIN *));
34 static IP_PRIVATE *ip_init __P((WIN *wp, int i_fd, int o_fd, int, int argc, char *argv[]));
35 static void perr __P((char *, char *));
36 static int get_fds __P((char *ip_arg, int *i_fd, int *o_fd));
37 static int get_connection __P((WIN *wp, int main_ifd, int main_ofd,
38 int *i_fd, int *o_fd, int *, int can_pass));
39 static void *run_editor __P((void * vp));
42 * ip_main --
43 * This is the main loop for the vi-as-library editor.
45 int
46 main(int argc, char **argv)
48 IP_PRIVATE *ipp;
49 int rval;
50 char *ip_arg;
51 char **p_av, **t_av;
52 GS *gp;
53 WIN *wp;
54 int i_fd, o_fd, t_fd, main_ifd, main_ofd;
56 /* Create and initialize the global structure. */
57 __global_list = gp = gs_init(argv[0]);
60 * Strip out any arguments that vi isn't going to understand. There's
61 * no way to portably call getopt twice, so arguments parsed here must
62 * be removed from the argument list.
64 ip_arg = NULL;
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 if (!memcmp(*t_av, "-I", sizeof("-I") - 1)) {
75 if (t_av[0][2] != '\0') {
76 ip_arg = t_av[0] + 2;
77 ++t_av;
78 --argc;
79 continue;
81 else if (t_av[1] != NULL) {
82 ip_arg = t_av[1];
83 t_av += 2;
84 argc -= 2;
85 continue;
88 *p_av++ = *t_av++;
91 if (get_fds(ip_arg, &main_ifd, &main_ofd))
92 return 1;
94 wp = NULL;
96 while (get_connection(wp, main_ifd, main_ofd, &i_fd, &o_fd, &t_fd, 1) == 0) {
97 /* Create new window */
98 wp = gs_new_win(gp);
100 /* Create and partially initialize the IP structure. */
101 if ((ipp = ip_init(wp, i_fd, o_fd, t_fd, argc, argv)) == NULL)
102 return (1);
104 gp->run(wp, run_editor, (void *)wp);
107 /* Clean out the global structure. */
108 gs_end(gp);
110 /* Free the global and IP private areas. */
111 #if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY)
112 free(gp);
113 #endif
114 exit (rval);
117 static void *
118 run_editor(void * vp)
120 GS *gp;
121 IP_PRIVATE *ipp;
122 WIN *wp;
123 EVENT ev;
124 int rval;
125 IP_BUF ipb;
127 wp = (WIN *) vp;
128 gp = wp->gp;
129 ipp = wp->ip_private;
131 /* Add the terminal type to the global structure. */
132 if ((OG_D_STR(gp, GO_TERM) =
133 OG_STR(gp, GO_TERM) = strdup("ip_curses")) == NULL)
134 perr(gp->progname, NULL);
137 * Figure out how big the screen is -- read events until we get
138 * the rows and columns.
140 for (;;) {
141 if (ip_wevent(wp, NULL, &ev, 0, 0))
142 return;
143 if (ev.e_event == E_WRESIZE)
144 break;
145 if (ev.e_event == E_EOF || ev.e_event == E_ERR ||
146 ev.e_event == E_SIGHUP || ev.e_event == E_SIGTERM)
147 return;
148 if (ev.e_event == E_IPCOMMAND && ev.e_ipcom == VI_QUIT)
149 return;
152 /* Run ex/vi. */
153 rval = editor(wp, ipp->argc, ipp->argv);
155 /* Clean up the screen. */
156 (void)ip_quit(wp);
158 /* Send the quit message. */
159 ipb.code = SI_QUIT;
160 (void)vi_send(ipp->o_fd, NULL, &ipb);
162 /* Give the screen a couple of seconds to deal with it. */
163 sleep(2);
165 /* Remove window; correct place ? */
166 win_end(wp);
168 #if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY)
169 free(ipp);
170 #endif
171 return NULL;
175 * ip_init --
176 * Create and partially initialize the GS structure.
178 static IP_PRIVATE *
179 ip_init(WIN *wp, int i_fd, int o_fd, int t_fd, int argc, char *argv[])
181 IP_PRIVATE *ipp;
183 /* Allocate the IP private structure. */
184 CALLOC_NOMSG(NULL, ipp, IP_PRIVATE *, 1, sizeof(IP_PRIVATE));
185 if (ipp == NULL)
186 perr(wp->gp->progname, NULL);
187 wp->ip_private = ipp;
189 ipp->i_fd = i_fd;
190 ipp->o_fd = o_fd;
191 ipp->t_fd = t_fd;
193 ipp->argc = argc;
194 ipp->argv = argv;
196 /* Initialize the list of ip functions. */
197 ip_func_std(wp);
199 return (ipp);
202 static int
203 get_fds(char *ip_arg, int *i_fd, int *o_fd)
205 char *ep;
208 * Crack ip_arg -- it's of the form #.#, where the first number is the
209 * file descriptor from the screen, the second is the file descriptor
210 * to the screen.
212 if (!ip_arg || !isdigit(ip_arg[0]))
213 goto usage;
214 *i_fd = strtol(ip_arg, &ep, 10);
215 if (ep[0] != '.' || !isdigit(ep[1]))
216 goto usage;
217 *o_fd = strtol(++ep, &ep, 10);
218 if (ep[0] != '\0') {
219 usage: ip_usage();
220 return 1;
223 return 0;
226 static int
227 get_connection(WIN *wp, int main_ifd, int main_ofd,
228 int *i_fd, int *o_fd, int *t_fd, int can_pass)
230 *t_fd = -1;
232 if (!can_pass) {
233 if (wp == NULL) { /* First call */
234 *i_fd = main_ifd;
235 *o_fd = main_ofd;
236 } else {
237 return 1;
239 } else {
240 struct msghdr mh;
241 IPCMSGHDR ch;
242 char dummy;
243 struct iovec iov;
245 mh.msg_namelen = 0;
246 mh.msg_iovlen = 1;
247 mh.msg_iov = &iov;
248 mh.msg_controllen = sizeof(ch);
249 mh.msg_control = (void *)&ch;
251 iov.iov_len = 1;
252 iov.iov_base = &dummy;
254 if (recvmsg(main_ifd, &mh, 0) != 1)
255 return 1;
256 *i_fd = *(int *)CMSG_DATA(&ch.header);
257 if (recvmsg(*i_fd, &mh, 0) != 1)
258 return 1;
259 *o_fd = *(int *)CMSG_DATA(&ch.header);
260 if (dummy == 'F') {
261 if (recvmsg(*i_fd, &mh, 0) != 1)
262 return 1;
263 *t_fd = *(int *)CMSG_DATA(&ch.header);
267 return 0;
271 * ip_func_std --
272 * Initialize the standard ip functions.
274 static void
275 ip_func_std(WIN *wp)
277 GS *gp;
279 gp = wp->gp;
281 gp->scr_addstr = ip_addstr;
282 gp->scr_waddstr = ip_waddstr;
283 gp->scr_attr = ip_attr;
284 gp->scr_baud = ip_baud;
285 gp->scr_bell = ip_bell;
286 gp->scr_busy = ip_busy;
287 gp->scr_child = ip_child;
288 gp->scr_clrtoeol = ip_clrtoeol;
289 gp->scr_cursor = ip_cursor;
290 gp->scr_deleteln = ip_deleteln;
291 gp->scr_discard = ip_discard;
292 gp->scr_event = ip_event;
293 gp->scr_ex_adjust = ip_ex_adjust;
294 gp->scr_fmap = ip_fmap;
295 gp->scr_insertln = ip_insertln;
296 gp->scr_keyval = ip_keyval;
297 gp->scr_move = ip_move;
298 wp->scr_msg = ip_msg;
299 gp->scr_optchange = ip_optchange;
300 gp->scr_refresh = ip_refresh;
301 gp->scr_rename = ip_rename;
302 gp->scr_reply = ip_reply;
303 gp->scr_screen = ip_screen;
304 gp->scr_split = ip_split;
305 gp->scr_suspend = ip_suspend;
306 gp->scr_usage = ip_usage;
310 * perr --
311 * Print system error.
313 static void
314 perr(char *name, char *msg)
316 (void)fprintf(stderr, "%s:", name);
317 if (msg != NULL)
318 (void)fprintf(stderr, "%s:", msg);
319 (void)fprintf(stderr, "%s\n", strerror(errno));
320 exit(1);