Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / nvi / cl / cl_main.c
blob244e38b5635776946019136e87aeaa1afd6aee6e
1 /* $NetBSD: cl_main.c,v 1.2 2008/12/05 22:51:42 christos Exp $ */
3 /*-
4 * Copyright (c) 1993, 1994
5 * The Regents of the University of California. All rights reserved.
6 * Copyright (c) 1993, 1994, 1995, 1996
7 * Keith Bostic. All rights reserved.
9 * See the LICENSE file for redistribution information.
12 #include "config.h"
14 #ifndef lint
15 static const char sccsid[] = "Id: cl_main.c,v 10.54 2001/07/29 19:07:27 skimo Exp (Berkeley) Date: 2001/07/29 19:07:27";
16 #endif /* not lint */
18 #include <sys/types.h>
19 #include <sys/queue.h>
21 #include <bitstring.h>
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <signal.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <termios.h>
29 #include <unistd.h>
31 #include "../common/common.h"
32 #include "../ip/extern.h"
33 #include "cl.h"
34 #include "pathnames.h"
36 GS *__global_list; /* GLOBAL: List of screens. */
37 sigset_t __sigblockset; /* GLOBAL: Blocked signals. */
39 static void cl_func_std __P((WIN *));
40 #ifdef notused
41 static void cl_end __P((CL_PRIVATE *));
42 #endif
43 static CL_PRIVATE *cl_init __P((WIN *));
44 static void perr __P((const char *, const char *));
45 static int setsig __P((int, struct sigaction *, void (*)(int)));
46 static void sig_end __P((GS *));
47 static void term_init __P((const char *, const char *));
50 * main --
51 * This is the main loop for the standalone curses editor.
53 int
54 main(int argc, char **argv)
56 static int reenter;
57 CL_PRIVATE *clp;
58 GS *gp;
59 WIN *wp;
60 size_t rows, cols;
61 int rval;
62 char **p_av, **t_av;
63 const char *ttype;
65 /* If loaded at 0 and jumping through a NULL pointer, stop. */
66 if (reenter++)
67 abort();
69 /* Create and initialize the global structure. */
70 __global_list = gp = gs_init(argv[0]);
73 * Strip out any arguments that vi isn't going to understand. There's
74 * no way to portably call getopt twice, so arguments parsed here must
75 * be removed from the argument list.
77 for (p_av = t_av = argv;;) {
78 if (*t_av == NULL) {
79 *p_av = NULL;
80 break;
82 if (!strcmp(*t_av, "--")) {
83 while ((*p_av++ = *t_av++) != NULL);
84 break;
86 *p_av++ = *t_av++;
89 /* Create new window */
90 wp = gs_new_win(gp);
92 /* Create and initialize the CL_PRIVATE structure. */
93 clp = cl_init(wp);
96 * Initialize the terminal information.
98 * We have to know what terminal it is from the start, since we may
99 * have to use termcap/terminfo to find out how big the screen is.
101 if ((ttype = getenv("TERM")) == NULL) {
102 if (isatty(STDIN_FILENO))
103 fprintf(stderr, "%s: warning: TERM is not set\n",
104 gp->progname);
105 ttype = "unknown";
107 term_init(gp->progname, ttype);
109 /* Add the terminal type to the global structure. */
110 if ((OG_D_STR(gp, GO_TERM) =
111 OG_STR(gp, GO_TERM) = strdup(ttype)) == NULL)
112 perr(gp->progname, NULL);
114 /* Figure out how big the screen is. */
115 if (cl_ssize(NULL, 0, &rows, &cols, NULL))
116 exit (1);
118 /* Add the rows and columns to the global structure. */
119 OG_VAL(gp, GO_LINES) = OG_D_VAL(gp, GO_LINES) = rows;
120 OG_VAL(gp, GO_COLUMNS) = OG_D_VAL(gp, GO_COLUMNS) = cols;
122 /* Ex wants stdout to be buffered. */
123 (void)setvbuf(stdout, NULL, _IOFBF, 0);
125 /* Start catching signals. */
126 if (sig_init(gp, NULL))
127 exit (1);
129 /* Run ex/vi. */
130 rval = editor(wp, argc, argv);
132 /* Clean out the global structure. */
133 gs_end(gp);
135 /* Clean up signals. */
136 sig_end(gp);
138 /* Clean up the terminal. */
139 (void)cl_quit(gp);
142 * XXX
143 * Reset the O_MESG option.
145 if (clp->tgw != TGW_UNKNOWN)
146 (void)cl_omesg(NULL, clp, clp->tgw == TGW_SET);
149 * XXX
150 * Reset the X11 xterm icon/window name.
152 if (F_ISSET(clp, CL_RENAME))
153 cl_setname(gp, clp->oname);
155 /* If a killer signal arrived, pretend we just got it. */
156 if (clp->killersig) {
157 (void)signal(clp->killersig, SIG_DFL);
158 (void)kill(getpid(), clp->killersig);
159 /* NOTREACHED */
162 /* Free the global and CL private areas. */
163 #if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY)
164 cl_end(clp);
165 free(gp);
166 #endif
168 exit (rval);
172 * cl_init --
173 * Create and partially initialize the CL structure.
175 static CL_PRIVATE *
176 cl_init(WIN *wp)
178 CL_PRIVATE *clp;
179 int fd;
180 GS *gp;
182 gp = wp->gp;
184 /* Allocate the CL private structure. */
185 CALLOC_NOMSG(NULL, clp, CL_PRIVATE *, 1, sizeof(CL_PRIVATE));
186 if (clp == NULL)
187 perr(gp->progname, NULL);
188 gp->cl_private = clp;
191 * Set the CL_STDIN_TTY flag. It's purpose is to avoid setting
192 * and resetting the tty if the input isn't from there. We also
193 * use the same test to determine if we're running a script or
194 * not.
196 if (isatty(STDIN_FILENO))
197 F_SET(clp, CL_STDIN_TTY);
198 else
199 F_SET(gp, G_SCRIPTED);
202 * We expect that if we've lost our controlling terminal that the
203 * open() (but not the tcgetattr()) will fail.
205 if (F_ISSET(clp, CL_STDIN_TTY)) {
206 if (tcgetattr(STDIN_FILENO, &clp->orig) == -1)
207 goto tcfail;
208 } else if ((fd = open(_PATH_TTY, O_RDONLY, 0)) != -1) {
209 if (tcgetattr(fd, &clp->orig) == -1) {
210 tcfail: perr(gp->progname, "tcgetattr");
211 exit (1);
213 (void)close(fd);
216 /* Initialize the list of curses functions. */
217 cl_func_std(wp);
219 return (clp);
222 #ifdef notused
224 * cl_end --
225 * Discard the CL structure.
227 static void
228 cl_end(CL_PRIVATE *clp)
230 if (clp->oname != NULL)
231 free(clp->oname);
232 free(clp);
234 #endif
237 * term_init --
238 * Initialize terminal information.
240 static void
241 term_init(const char *name, const char *ttype)
243 int err;
245 /* Set up the terminal database information. */
246 setupterm(__UNCONST(ttype), STDOUT_FILENO, &err);
247 switch (err) {
248 case -1:
249 (void)fprintf(stderr,
250 "%s: No terminal database found\n", name);
251 exit (1);
252 case 0:
253 (void)fprintf(stderr,
254 "%s: %s: unknown terminal type\n", name, ttype);
255 exit (1);
259 #define GLOBAL_CLP \
260 CL_PRIVATE *clp = GCLP(__global_list);
261 static void
262 h_hup(int signo)
264 GLOBAL_CLP;
266 F_SET(clp, CL_SIGHUP);
267 clp->killersig = SIGHUP;
270 static void
271 h_int(int signo)
273 GLOBAL_CLP;
275 F_SET(clp, CL_SIGINT);
278 static void
279 h_term(int signo)
281 GLOBAL_CLP;
283 F_SET(clp, CL_SIGTERM);
284 clp->killersig = SIGTERM;
287 static void
288 h_winch(int signo)
290 GLOBAL_CLP;
292 F_SET(clp, CL_SIGWINCH);
294 #undef GLOBAL_CLP
297 * sig_init --
298 * Initialize signals.
300 * PUBLIC: int sig_init __P((GS *, SCR *));
303 sig_init(GS *gp, SCR *sp)
305 CL_PRIVATE *clp;
307 clp = GCLP(gp);
309 if (sp == NULL) {
310 (void)sigemptyset(&__sigblockset);
311 if (sigaddset(&__sigblockset, SIGHUP) ||
312 setsig(SIGHUP, &clp->oact[INDX_HUP], h_hup) ||
313 sigaddset(&__sigblockset, SIGINT) ||
314 setsig(SIGINT, &clp->oact[INDX_INT], h_int) ||
315 sigaddset(&__sigblockset, SIGTERM) ||
316 setsig(SIGTERM, &clp->oact[INDX_TERM], h_term)
317 #ifdef SIGWINCH
319 sigaddset(&__sigblockset, SIGWINCH) ||
320 setsig(SIGWINCH, &clp->oact[INDX_WINCH], h_winch)
321 #endif
323 perr(gp->progname, NULL);
324 return (1);
326 } else
327 if (setsig(SIGHUP, NULL, h_hup) ||
328 setsig(SIGINT, NULL, h_int) ||
329 setsig(SIGTERM, NULL, h_term)
330 #ifdef SIGWINCH
332 setsig(SIGWINCH, NULL, h_winch)
333 #endif
335 msgq(sp, M_SYSERR, "signal-reset");
337 return (0);
341 * setsig --
342 * Set a signal handler.
344 static int
345 setsig(int signo, struct sigaction *oactp, void (*handler) (int))
347 struct sigaction act;
350 * Use sigaction(2), not signal(3), since we don't always want to
351 * restart system calls. The example is when waiting for a command
352 * mode keystroke and SIGWINCH arrives. Besides, you can't portably
353 * restart system calls (thanks, POSIX!). On the other hand, you
354 * can't portably NOT restart system calls (thanks, Sun!). SunOS
355 * used SA_INTERRUPT as their extension to NOT restart read calls.
356 * We sure hope nobody else used it for anything else. Mom told me
357 * there'd be days like this. She just never told me that there'd
358 * be so many.
360 act.sa_handler = handler;
361 sigemptyset(&act.sa_mask);
363 #ifdef SA_INTERRUPT
364 act.sa_flags = SA_INTERRUPT;
365 #else
366 act.sa_flags = 0;
367 #endif
368 return (sigaction(signo, &act, oactp));
372 * sig_end --
373 * End signal setup.
375 static void
376 sig_end(GS *gp)
378 CL_PRIVATE *clp;
380 clp = GCLP(gp);
381 (void)sigaction(SIGHUP, NULL, &clp->oact[INDX_HUP]);
382 (void)sigaction(SIGINT, NULL, &clp->oact[INDX_INT]);
383 (void)sigaction(SIGTERM, NULL, &clp->oact[INDX_TERM]);
384 #ifdef SIGWINCH
385 (void)sigaction(SIGWINCH, NULL, &clp->oact[INDX_WINCH]);
386 #endif
390 * cl_func_std --
391 * Initialize the standard curses functions.
393 static void
394 cl_func_std(WIN *wp)
396 GS *gp;
398 gp = wp->gp;
400 gp->scr_addstr = cl_addstr;
401 gp->scr_waddstr = cl_waddstr;
402 gp->scr_attr = cl_attr;
403 gp->scr_baud = cl_baud;
404 gp->scr_bell = cl_bell;
405 gp->scr_busy = NULL;
406 gp->scr_child = NULL;
407 gp->scr_clrtoeol = cl_clrtoeol;
408 gp->scr_cursor = cl_cursor;
409 gp->scr_deleteln = cl_deleteln;
410 gp->scr_reply = NULL;
411 gp->scr_discard = cl_discard;
412 gp->scr_event = cl_event;
413 gp->scr_ex_adjust = cl_ex_adjust;
414 gp->scr_fmap = cl_fmap;
415 gp->scr_insertln = cl_insertln;
416 gp->scr_keyval = cl_keyval;
417 gp->scr_move = cl_move;
418 wp->scr_msg = NULL;
419 gp->scr_optchange = cl_optchange;
420 gp->scr_refresh = cl_refresh;
421 gp->scr_rename = cl_rename;
422 gp->scr_screen = cl_screen;
423 gp->scr_split = cl_split;
424 gp->scr_suspend = cl_suspend;
425 gp->scr_usage = cl_usage;
429 * perr --
430 * Print system error.
432 static void
433 perr(const char *name, const char *msg)
435 (void)fprintf(stderr, "%s:", name);
436 if (msg != NULL)
437 (void)fprintf(stderr, "%s:", msg);
438 (void)fprintf(stderr, "%s\n", strerror(errno));
439 exit(1);