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