Remove building with NOCRYPTO option
[minix.git] / external / bsd / nvi / dist / common / main.c
blob7866f348a04b0084f7969fdc2561092daa48bc2b
1 /* $NetBSD: main.c,v 1.6 2014/01/26 21:43:45 christos Exp $ */
2 /*-
3 * Copyright (c) 1992, 1993, 1994
4 * The Regents of the University of California. All rights reserved.
5 * Copyright (c) 1992, 1993, 1994, 1995, 1996
6 * Keith Bostic. All rights reserved.
8 * See the LICENSE file for redistribution information.
9 */
11 #include "config.h"
13 #include <sys/cdefs.h>
14 #if 0
15 #ifndef lint
16 static const char copyright[] =
17 "%Z% Copyright (c) 1992, 1993, 1994\n\
18 The Regents of the University of California. All rights reserved.\n\
19 %Z% Copyright (c) 1992, 1993, 1994, 1995, 1996\n\
20 Keith Bostic. All rights reserved.\n";
21 #endif /* not lint */
22 #else
23 __RCSID("$NetBSD: main.c,v 1.6 2014/01/26 21:43:45 christos Exp $");
24 #endif
26 #include <sys/cdefs.h>
27 #if 0
28 #ifndef lint
29 static const char sccsid[] = "Id: main.c,v 10.63 2001/11/01 15:24:43 skimo Exp (Berkeley) Date: 2001/11/01 15:24:43 ";
30 #endif /* not lint */
31 #else
32 __RCSID("$NetBSD: main.c,v 1.6 2014/01/26 21:43:45 christos Exp $");
33 #endif
35 #include <sys/types.h>
36 #include <sys/queue.h>
37 #include <sys/stat.h>
38 #include <sys/time.h>
40 #include <bitstring.h>
41 #include <errno.h>
42 #include <fcntl.h>
43 #include <limits.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <unistd.h>
49 #include "common.h"
50 #include "../vi/vi.h"
51 #include "pathnames.h"
53 static void v_estr __P((const char *, int, const char *));
54 static int v_obsolete __P((char *, char *[]));
57 * editor --
58 * Main editor routine.
60 * PUBLIC: int editor __P((WIN *, int, char *[]));
62 int
63 editor(WIN *wp, int argc, char **argv)
65 extern int optind;
66 extern char *optarg;
67 const char *p;
68 EVENT ev;
69 FREF *frp;
70 SCR *sp;
71 GS *gp;
72 size_t len;
73 u_int flags;
74 int ch, flagchk, lflag, secure, startup, readonly, rval, silent;
75 #ifdef GTAGS
76 int gtags = 0;
77 #endif
78 char *tag_f, *wsizearg, path[256];
79 const CHAR_T *w;
80 size_t wlen;
82 gp = wp->gp;
84 /* Initialize the busy routine, if not defined by the screen. */
85 if (gp->scr_busy == NULL)
86 gp->scr_busy = vs_busy;
87 /* Initialize the message routine, if not defined by the screen. */
88 if (wp->scr_msg == NULL)
89 wp->scr_msg = vs_msg;
91 /* Set initial screen type and mode based on the program name. */
92 readonly = 0;
93 if (!strcmp(gp->progname, "ex") || !strcmp(gp->progname, "nex"))
94 LF_INIT(SC_EX);
95 else {
96 /* Nview, view are readonly. */
97 if (!strcmp(gp->progname, "nview") ||
98 !strcmp(gp->progname, "view"))
99 readonly = 1;
101 /* Vi is the default. */
102 LF_INIT(SC_VI);
105 /* Convert old-style arguments into new-style ones. */
106 if (v_obsolete(gp->progname, argv))
107 return (1);
109 /* Parse the arguments. */
110 flagchk = '\0';
111 tag_f = wsizearg = NULL;
112 lflag = secure = silent = 0;
113 startup = 1;
115 /* Set the file snapshot flag. */
116 F_SET(gp, G_SNAPSHOT);
118 while ((ch = getopt(argc, argv, "c:"
119 #ifdef DEBUG
120 "D:"
121 #endif
122 "eF"
123 #ifdef GTAGS
125 #endif
126 "lRrSsT:t:vw:")) != EOF)
127 switch (ch) {
128 case 'c': /* Run the command. */
130 * XXX
131 * We should support multiple -c options.
133 if (gp->c_option != NULL) {
134 v_estr(gp->progname, 0,
135 "only one -c command may be specified.");
136 return (1);
138 gp->c_option = optarg;
139 break;
140 #ifdef DEBUG
141 case 'D':
142 switch (optarg[0]) {
143 case 's':
144 startup = 0;
145 break;
146 case 'w':
147 attach(gp);
148 break;
149 default:
150 v_estr(gp->progname, 0,
151 "usage: -D requires s or w argument.");
152 return (1);
154 break;
155 #endif
156 case 'e': /* Ex mode. */
157 LF_CLR(SC_VI);
158 LF_SET(SC_EX);
159 break;
160 case 'F': /* No snapshot. */
161 v_estr(gp->progname, 0,
162 "-F option no longer supported.");
163 break;
164 case 'l': /* Set lisp, showmatch options. */
165 lflag = 1;
166 break;
167 #ifdef GTAGS
168 case 'G': /* gtags mode. */
169 gtags = 1;
170 break;
171 #endif
172 case 'R': /* Readonly. */
173 readonly = 1;
174 break;
175 case 'r': /* Recover. */
176 if (flagchk == 't') {
177 v_estr(gp->progname, 0,
178 "only one of -r and -t may be specified.");
179 return (1);
181 flagchk = 'r';
182 break;
183 case 'S':
184 secure = 1;
185 break;
186 case 's':
187 silent = 1;
188 break;
189 #ifdef TRACE
190 case 'T': /* Trace. */
191 (void)vtrace_init(optarg);
192 break;
193 #endif
194 case 't': /* Tag. */
195 if (flagchk == 'r') {
196 v_estr(gp->progname, 0,
197 "only one of -r and -t may be specified.");
198 return (1);
200 if (flagchk == 't') {
201 v_estr(gp->progname, 0,
202 "only one tag file may be specified.");
203 return (1);
205 flagchk = 't';
206 tag_f = optarg;
207 break;
208 case 'v': /* Vi mode. */
209 LF_CLR(SC_EX);
210 LF_SET(SC_VI);
211 break;
212 case 'w':
213 wsizearg = optarg;
214 break;
215 case '?':
216 default:
217 (void)gp->scr_usage();
218 return (1);
220 argc -= optind;
221 argv += optind;
224 * -s option is only meaningful to ex.
226 * If not reading from a terminal, it's like -s was specified.
228 if (silent && !LF_ISSET(SC_EX)) {
229 v_estr(gp->progname, 0, "-s option is only applicable to ex.");
230 goto err;
232 if (LF_ISSET(SC_EX) && F_ISSET(gp, G_SCRIPTED))
233 silent = 1;
236 * Build and initialize the first/current screen. This is a bit
237 * tricky. If an error is returned, we may or may not have a
238 * screen structure. If we have a screen structure, put it on a
239 * display queue so that the error messages get displayed.
241 * !!!
242 * Everything we do until we go interactive is done in ex mode.
244 if (screen_init(gp, NULL, &sp)) {
245 if (sp != NULL) {
246 TAILQ_INSERT_HEAD(&wp->scrq, sp, q);
247 sp->wp = wp;
249 goto err;
251 F_SET(sp, SC_EX);
252 TAILQ_INSERT_HEAD(&wp->scrq, sp, q);
253 sp->wp = wp;
255 if (v_key_init(sp)) /* Special key initialization. */
256 goto err;
258 { int oargs[5], *oargp = oargs;
259 if (lflag) { /* Command-line options. */
260 *oargp++ = O_LISP;
261 *oargp++ = O_SHOWMATCH;
263 if (readonly)
264 *oargp++ = O_READONLY;
265 #ifdef GTAGS
266 if (gtags)
267 *oargp++ = O_GTAGSMODE;
268 #endif
269 if (secure)
270 *oargp++ = O_SECURE;
271 *oargp = -1; /* Options initialization. */
272 if (opts_init(sp, oargs))
273 goto err;
275 if (wsizearg != NULL) {
276 ARGS *av[2], a, b;
277 (void)snprintf(path, sizeof(path), "window=%s", wsizearg);
278 a.bp = (CHAR_T *)path;
279 a.len = strlen(path);
280 b.bp = NULL;
281 b.len = 0;
282 av[0] = &a;
283 av[1] = &b;
284 (void)opts_set(sp, av, NULL);
286 if (silent) { /* Ex batch mode option values. */
287 O_CLR(sp, O_AUTOPRINT);
288 O_CLR(sp, O_PROMPT);
289 O_CLR(sp, O_VERBOSE);
290 O_CLR(sp, O_WARN);
291 F_SET(sp, SC_EX_SILENT);
294 sp->rows = O_VAL(sp, O_LINES); /* Make ex formatting work. */
295 sp->cols = O_VAL(sp, O_COLUMNS);
297 if (!silent && startup) { /* Read EXINIT, exrc files. */
298 if (ex_exrc(sp))
299 goto err;
300 if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE)) {
301 if (screen_end(sp))
302 goto err;
303 goto done;
308 * List recovery files if -r specified without file arguments.
309 * Note, options must be initialized and startup information
310 * read before doing this.
312 if (flagchk == 'r' && argv[0] == NULL) {
313 if (rcv_list(sp))
314 goto err;
315 if (screen_end(sp))
316 goto err;
317 goto done;
321 * !!!
322 * Initialize the default ^D, ^U scrolling value here, after the
323 * user has had every opportunity to set the window option.
325 * It's historic practice that changing the value of the window
326 * option did not alter the default scrolling value, only giving
327 * a count to ^D/^U did that.
329 sp->defscroll = (O_VAL(sp, O_WINDOW) + 1) / 2;
332 * If we don't have a command-line option, switch into the right
333 * editor now, so that we position default files correctly, and
334 * so that any tags file file-already-locked messages are in the
335 * vi screen, not the ex screen.
337 * XXX
338 * If we have a command-line option, the error message can end
339 * up in the wrong place, but I think that the combination is
340 * unlikely.
342 if (gp->c_option == NULL) {
343 F_CLR(sp, SC_EX | SC_VI);
344 F_SET(sp, LF_ISSET(SC_EX | SC_VI));
347 /* Open a tag file if specified. */
348 if (tag_f != NULL) {
349 CHAR2INT(sp, tag_f, strlen(tag_f) + 1, w, wlen);
350 if (ex_tag_first(sp, w))
351 goto err;
355 * Append any remaining arguments as file names. Files are recovery
356 * files if -r specified. If the tag option or ex startup commands
357 * loaded a file, then any file arguments are going to come after it.
359 if (*argv != NULL) {
360 if (sp->frp != NULL) {
361 /* Cheat -- we know we have an extra argv slot. */
362 MALLOC_NOMSG(sp,
363 *--argv, char *, strlen(sp->frp->name) + 1);
364 if (*argv == NULL) {
365 v_estr(gp->progname, errno, NULL);
366 goto err;
368 (void)strcpy(*argv, sp->frp->name);
370 sp->argv = sp->cargv = argv;
371 F_SET(sp, SC_ARGNOFREE);
372 if (flagchk == 'r')
373 F_SET(sp, SC_ARGRECOVER);
377 * If the ex startup commands and or/the tag option haven't already
378 * created a file, create one. If no command-line files were given,
379 * use a temporary file.
381 if (sp->frp == NULL) {
382 if (sp->argv == NULL) {
383 if ((frp = file_add(sp, NULL)) == NULL)
384 goto err;
385 } else {
386 if ((frp = file_add(sp, sp->argv[0])) == NULL)
387 goto err;
388 if (F_ISSET(sp, SC_ARGRECOVER))
389 F_SET(frp, FR_RECOVER);
392 if (file_init(sp, frp, NULL, 0))
393 goto err;
394 if (EXCMD_RUNNING(wp)) {
395 (void)ex_cmd(sp);
396 if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE)) {
397 if (screen_end(sp))
398 goto err;
399 goto done;
405 * Check to see if we need to wait for ex. If SC_SCR_EX is set, ex
406 * was forced to initialize the screen during startup. We'd like to
407 * wait for a single character from the user, but we can't because
408 * we're not in raw mode. We can't switch to raw mode because the
409 * vi initialization will switch to xterm's alternate screen, causing
410 * us to lose the messages we're pausing to make sure the user read.
411 * So, wait for a complete line.
413 if (F_ISSET(sp, SC_SCR_EX)) {
414 p = msg_cmsg(sp, CMSG_CONT_R, &len);
415 (void)write(STDOUT_FILENO, p, len);
416 for (;;) {
417 if (v_event_get(sp, &ev, 0, 0))
418 goto err;
419 if (ev.e_event == E_INTERRUPT ||
420 (ev.e_event == E_CHARACTER &&
421 (ev.e_value == K_CR || ev.e_value == K_NL)))
422 break;
423 (void)gp->scr_bell(sp);
427 /* Switch into the right editor, regardless. */
428 F_CLR(sp, SC_EX | SC_VI);
429 F_SET(sp, LF_ISSET(SC_EX | SC_VI) | SC_STATUS_CNT);
432 * Main edit loop. Vi handles split screens itself, we only return
433 * here when switching editor modes or restarting the screen.
435 while (sp != NULL)
436 if (F_ISSET(sp, SC_EX) ? ex(&sp) : vi(&sp))
437 goto err;
439 done: rval = 0;
440 if (0)
441 err: rval = 1;
443 return (rval);
447 * v_obsolete --
448 * Convert historic arguments into something getopt(3) will like.
450 static int
451 v_obsolete(char *name, char **argv)
453 size_t len;
454 char *p;
457 * Translate old style arguments into something getopt will like.
458 * Make sure it's not text space memory, because ex modifies the
459 * strings.
460 * Change "+" into "-c$".
461 * Change "+<anything else>" into "-c<anything else>".
462 * Change "-" into "-s"
463 * The c, T, t and w options take arguments so they can't be
464 * special arguments.
466 * Stop if we find "--" as an argument, the user may want to edit
467 * a file named "+foo".
469 while (*++argv && strcmp(argv[0], "--"))
470 if (argv[0][0] == '+') {
471 if (argv[0][1] == '\0') {
472 MALLOC_NOMSG(NULL, argv[0], char *, 4);
473 if (argv[0] == NULL)
474 goto nomem;
475 (void)strcpy(argv[0], "-c$");
476 } else {
477 p = argv[0];
478 len = strlen(argv[0]);
479 MALLOC_NOMSG(NULL, argv[0], char *, len + 2);
480 if (argv[0] == NULL)
481 goto nomem;
482 argv[0][0] = '-';
483 argv[0][1] = 'c';
484 (void)strcpy(argv[0] + 2, p + 1);
486 } else if (argv[0][0] == '-') {
487 if (argv[0][1] == '\0') {
488 MALLOC_NOMSG(NULL, argv[0], char *, 3);
489 if (argv[0] == NULL) {
490 nomem: v_estr(name, errno, NULL);
491 return (1);
493 (void)strcpy(argv[0], "-s");
494 } else
495 if ((argv[0][1] == 'c' || argv[0][1] == 'T' ||
496 argv[0][1] == 't' || argv[0][1] == 'w') &&
497 argv[0][2] == '\0')
498 ++argv;
500 return (0);
503 #ifdef DEBUG
504 static void
505 attach(GS *gp)
507 int fd;
508 char ch;
510 if ((fd = open(_PATH_TTY, O_RDONLY, 0)) < 0) {
511 v_estr(gp->progname, errno, _PATH_TTY);
512 return;
515 (void)printf("process %lu waiting, enter <CR> to continue: ",
516 (u_long)getpid());
517 (void)fflush(stdout);
519 do {
520 if (read(fd, &ch, 1) != 1) {
521 (void)close(fd);
522 return;
524 } while (ch != '\n' && ch != '\r');
525 (void)close(fd);
527 #endif
529 static void
530 v_estr(const char *name, int eno, const char *msg)
532 (void)fprintf(stderr, "%s", name);
533 if (msg != NULL)
534 (void)fprintf(stderr, ": %s", msg);
535 if (eno)
536 (void)fprintf(stderr, ": %s", strerror(errno));
537 (void)fprintf(stderr, "\n");