119304Speter/*-
219304Speter * Copyright (c) 1992, 1993, 1994
319304Speter *	The Regents of the University of California.  All rights reserved.
419304Speter * Copyright (c) 1992, 1993, 1994, 1995, 1996
519304Speter *	Keith Bostic.  All rights reserved.
619304Speter *
719304Speter * See the LICENSE file for redistribution information.
819304Speter */
919304Speter
1019304Speter#include "config.h"
1119304Speter
1219304Speter#ifndef lint
1319304Speterstatic const char copyright[] =
14258231Sgjb"@(#) Copyright (c) 1992, 1993, 1994\n\
1519304Speter	The Regents of the University of California.  All rights reserved.\n\
16258231Sgjb@(#) Copyright (c) 1992, 1993, 1994, 1995, 1996\n\
1719304Speter	Keith Bostic.  All rights reserved.\n";
1819304Speter#endif /* not lint */
1919304Speter
2019304Speter#ifndef lint
21254225Speterstatic const char sccsid[] = "$Id: main.c,v 11.0 2012/10/17 06:34:37 zy Exp $";
2219304Speter#endif /* not lint */
2319304Speter
2419304Speter#include <sys/types.h>
2519304Speter#include <sys/queue.h>
2619304Speter#include <sys/stat.h>
2719304Speter
2819304Speter#include <bitstring.h>
2919304Speter#include <errno.h>
3019304Speter#include <fcntl.h>
3119304Speter#include <limits.h>
3219304Speter#include <stdio.h>
3319304Speter#include <stdlib.h>
3419304Speter#include <string.h>
3519304Speter#include <unistd.h>
3619304Speter
3719304Speter#include "common.h"
3819304Speter#include "../vi/vi.h"
3919304Speter#include "pathnames.h"
4019304Speter
4119304Speterstatic void	 attach __P((GS *));
4219304Speterstatic void	 v_estr __P((char *, int, char *));
4319304Speterstatic int	 v_obsolete __P((char *, char *[]));
4419304Speter
4519304Speter/*
4619304Speter * editor --
4719304Speter *	Main editor routine.
4819304Speter *
4919304Speter * PUBLIC: int editor __P((GS *, int, char *[]));
5019304Speter */
5119304Speterint
52254225Spetereditor(
53254225Speter	GS *gp,
54254225Speter	int argc,
55254225Speter	char *argv[])
5619304Speter{
5719304Speter	extern int optind;
5819304Speter	extern char *optarg;
5919304Speter	const char *p;
6019304Speter	EVENT ev;
6119304Speter	FREF *frp;
6219304Speter	SCR *sp;
6319304Speter	size_t len;
6419304Speter	u_int flags;
6519304Speter	int ch, flagchk, lflag, secure, startup, readonly, rval, silent;
6619304Speter	char *tag_f, *wsizearg, path[256];
67254225Speter	CHAR_T *w;
68254225Speter	size_t wlen;
6919304Speter
7019304Speter	/* Initialize the busy routine, if not defined by the screen. */
7119304Speter	if (gp->scr_busy == NULL)
7219304Speter		gp->scr_busy = vs_busy;
7319304Speter	/* Initialize the message routine, if not defined by the screen. */
7419304Speter	if (gp->scr_msg == NULL)
7519304Speter		gp->scr_msg = vs_msg;
76254225Speter	gp->catd = (nl_catd)-1;
7719304Speter
7819304Speter	/* Common global structure initialization. */
79254225Speter	TAILQ_INIT(gp->dq);
80254225Speter	TAILQ_INIT(gp->hq);
81254225Speter	SLIST_INIT(gp->ecq);
82254225Speter	SLIST_INSERT_HEAD(gp->ecq, &gp->excmd, q);
8319304Speter	gp->noprint = DEFAULT_NOPRINT;
8419304Speter
8519304Speter	/* Structures shared by screens so stored in the GS structure. */
86254225Speter	TAILQ_INIT(gp->frefq);
87254225Speter	TAILQ_INIT(gp->dcb_store.textq);
88254225Speter	SLIST_INIT(gp->cutq);
89254225Speter	SLIST_INIT(gp->seqq);
9019304Speter
9119304Speter	/* Set initial screen type and mode based on the program name. */
9219304Speter	readonly = 0;
9319304Speter	if (!strcmp(gp->progname, "ex") || !strcmp(gp->progname, "nex"))
9419304Speter		LF_INIT(SC_EX);
9519304Speter	else {
9619304Speter		/* Nview, view are readonly. */
9719304Speter		if (!strcmp(gp->progname, "nview") ||
9819304Speter		    !strcmp(gp->progname, "view"))
9919304Speter			readonly = 1;
10019304Speter
10119304Speter		/* Vi is the default. */
10219304Speter		LF_INIT(SC_VI);
10319304Speter	}
10419304Speter
10519304Speter	/* Convert old-style arguments into new-style ones. */
10619304Speter	if (v_obsolete(gp->progname, argv))
10719304Speter		return (1);
10819304Speter
10919304Speter	/* Parse the arguments. */
11019304Speter	flagchk = '\0';
11119304Speter	tag_f = wsizearg = NULL;
11219304Speter	lflag = secure = silent = 0;
11319304Speter	startup = 1;
11419304Speter
11519304Speter	/* Set the file snapshot flag. */
11619304Speter	F_SET(gp, G_SNAPSHOT);
11719304Speter
11819304Speter#ifdef DEBUG
11919304Speter	while ((ch = getopt(argc, argv, "c:D:eFlRrSsT:t:vw:")) != EOF)
12019304Speter#else
12119304Speter	while ((ch = getopt(argc, argv, "c:eFlRrSst:vw:")) != EOF)
12219304Speter#endif
12319304Speter		switch (ch) {
12419304Speter		case 'c':		/* Run the command. */
12519304Speter			/*
12619304Speter			 * XXX
12719304Speter			 * We should support multiple -c options.
12819304Speter			 */
12919304Speter			if (gp->c_option != NULL) {
13019304Speter				v_estr(gp->progname, 0,
13119304Speter				    "only one -c command may be specified.");
13219304Speter				return (1);
13319304Speter			}
13419304Speter			gp->c_option = optarg;
13519304Speter			break;
13619304Speter#ifdef DEBUG
13719304Speter		case 'D':
13819304Speter			switch (optarg[0]) {
13919304Speter			case 's':
14019304Speter				startup = 0;
14119304Speter				break;
14219304Speter			case 'w':
14319304Speter				attach(gp);
14419304Speter				break;
14519304Speter			default:
14619304Speter				v_estr(gp->progname, 0,
14719304Speter				    "usage: -D requires s or w argument.");
14819304Speter				return (1);
14919304Speter			}
15019304Speter			break;
15119304Speter#endif
15219304Speter		case 'e':		/* Ex mode. */
15319304Speter			LF_CLR(SC_VI);
15419304Speter			LF_SET(SC_EX);
15519304Speter			break;
15619304Speter		case 'F':		/* No snapshot. */
15719304Speter			F_CLR(gp, G_SNAPSHOT);
15819304Speter			break;
15919304Speter		case 'l':		/* Set lisp, showmatch options. */
16019304Speter			lflag = 1;
16119304Speter			break;
16219304Speter		case 'R':		/* Readonly. */
16319304Speter			readonly = 1;
16419304Speter			break;
16519304Speter		case 'r':		/* Recover. */
16619304Speter			if (flagchk == 't') {
16719304Speter				v_estr(gp->progname, 0,
16819304Speter				    "only one of -r and -t may be specified.");
16919304Speter				return (1);
17019304Speter			}
17119304Speter			flagchk = 'r';
17219304Speter			break;
17319304Speter		case 'S':
17419304Speter			secure = 1;
17519304Speter			break;
17619304Speter		case 's':
17719304Speter			silent = 1;
17819304Speter			break;
17919304Speter#ifdef DEBUG
18019304Speter		case 'T':		/* Trace. */
18119304Speter			if ((gp->tracefp = fopen(optarg, "w")) == NULL) {
18219304Speter				v_estr(gp->progname, errno, optarg);
18319304Speter				goto err;
18419304Speter			}
18519304Speter			(void)fprintf(gp->tracefp,
18619304Speter			    "\n===\ntrace: open %s\n", optarg);
18719304Speter			break;
18819304Speter#endif
18919304Speter		case 't':		/* Tag. */
19019304Speter			if (flagchk == 'r') {
19119304Speter				v_estr(gp->progname, 0,
19219304Speter				    "only one of -r and -t may be specified.");
19319304Speter				return (1);
19419304Speter			}
19519304Speter			if (flagchk == 't') {
19619304Speter				v_estr(gp->progname, 0,
19719304Speter				    "only one tag file may be specified.");
19819304Speter				return (1);
19919304Speter			}
20019304Speter			flagchk = 't';
20119304Speter			tag_f = optarg;
20219304Speter			break;
20319304Speter		case 'v':		/* Vi mode. */
20419304Speter			LF_CLR(SC_EX);
20519304Speter			LF_SET(SC_VI);
20619304Speter			break;
20719304Speter		case 'w':
20819304Speter			wsizearg = optarg;
20919304Speter			break;
21019304Speter		case '?':
21119304Speter		default:
21219304Speter			(void)gp->scr_usage();
21319304Speter			return (1);
21419304Speter		}
21519304Speter	argc -= optind;
21619304Speter	argv += optind;
21719304Speter
21819304Speter	/*
21919304Speter	 * -s option is only meaningful to ex.
22019304Speter	 *
22119304Speter	 * If not reading from a terminal, it's like -s was specified.
22219304Speter	 */
22319304Speter	if (silent && !LF_ISSET(SC_EX)) {
22419304Speter		v_estr(gp->progname, 0, "-s option is only applicable to ex.");
22519304Speter		goto err;
22619304Speter	}
22719304Speter	if (LF_ISSET(SC_EX) && F_ISSET(gp, G_SCRIPTED))
22819304Speter		silent = 1;
22919304Speter
23019304Speter	/*
23119304Speter	 * Build and initialize the first/current screen.  This is a bit
23219304Speter	 * tricky.  If an error is returned, we may or may not have a
23319304Speter	 * screen structure.  If we have a screen structure, put it on a
23419304Speter	 * display queue so that the error messages get displayed.
23519304Speter	 *
23619304Speter	 * !!!
23719304Speter	 * Everything we do until we go interactive is done in ex mode.
23819304Speter	 */
23919304Speter	if (screen_init(gp, NULL, &sp)) {
24019304Speter		if (sp != NULL)
241254225Speter			TAILQ_INSERT_HEAD(gp->dq, sp, q);
24219304Speter		goto err;
24319304Speter	}
24419304Speter	F_SET(sp, SC_EX);
245254225Speter	TAILQ_INSERT_HEAD(gp->dq, sp, q);
24619304Speter
24719304Speter	if (v_key_init(sp))		/* Special key initialization. */
24819304Speter		goto err;
24919304Speter
25019304Speter	{ int oargs[5], *oargp = oargs;
25119304Speter	if (lflag) {			/* Command-line options. */
25219304Speter		*oargp++ = O_LISP;
25319304Speter		*oargp++ = O_SHOWMATCH;
25419304Speter	}
25519304Speter	if (readonly)
25619304Speter		*oargp++ = O_READONLY;
25719304Speter	if (secure)
25819304Speter		*oargp++ = O_SECURE;
25919304Speter	*oargp = -1;			/* Options initialization. */
26019304Speter	if (opts_init(sp, oargs))
26119304Speter		goto err;
26219304Speter	}
26319304Speter	if (wsizearg != NULL) {
26419304Speter		ARGS *av[2], a, b;
26519304Speter		(void)snprintf(path, sizeof(path), "window=%s", wsizearg);
26619304Speter		a.bp = (CHAR_T *)path;
26719304Speter		a.len = strlen(path);
26819304Speter		b.bp = NULL;
26919304Speter		b.len = 0;
27019304Speter		av[0] = &a;
27119304Speter		av[1] = &b;
27219304Speter		(void)opts_set(sp, av, NULL);
27319304Speter	}
27419304Speter	if (silent) {			/* Ex batch mode option values. */
27519304Speter		O_CLR(sp, O_AUTOPRINT);
27619304Speter		O_CLR(sp, O_PROMPT);
27719304Speter		O_CLR(sp, O_VERBOSE);
27819304Speter		O_CLR(sp, O_WARN);
27919304Speter		F_SET(sp, SC_EX_SILENT);
28019304Speter	}
28119304Speter
28219304Speter	sp->rows = O_VAL(sp, O_LINES);	/* Make ex formatting work. */
28319304Speter	sp->cols = O_VAL(sp, O_COLUMNS);
28419304Speter
28519304Speter	if (!silent && startup) {	/* Read EXINIT, exrc files. */
28619304Speter		if (ex_exrc(sp))
28719304Speter			goto err;
28819304Speter		if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE)) {
28919304Speter			if (screen_end(sp))
29019304Speter				goto err;
29119304Speter			goto done;
29219304Speter		}
29319304Speter	}
29419304Speter
29519304Speter	/*
29619304Speter	 * List recovery files if -r specified without file arguments.
29719304Speter	 * Note, options must be initialized and startup information
29819304Speter	 * read before doing this.
29919304Speter	 */
30019304Speter	if (flagchk == 'r' && argv[0] == NULL) {
30119304Speter		if (rcv_list(sp))
30219304Speter			goto err;
30319304Speter		if (screen_end(sp))
30419304Speter			goto err;
30519304Speter		goto done;
30619304Speter	}
30719304Speter
30819304Speter	/*
30919304Speter	 * !!!
31019304Speter	 * Initialize the default ^D, ^U scrolling value here, after the
31119304Speter	 * user has had every opportunity to set the window option.
31219304Speter	 *
31319304Speter	 * It's historic practice that changing the value of the window
31419304Speter	 * option did not alter the default scrolling value, only giving
31519304Speter	 * a count to ^D/^U did that.
31619304Speter	 */
31719304Speter	sp->defscroll = (O_VAL(sp, O_WINDOW) + 1) / 2;
31819304Speter
31919304Speter	/*
32019304Speter	 * If we don't have a command-line option, switch into the right
32119304Speter	 * editor now, so that we position default files correctly, and
32219304Speter	 * so that any tags file file-already-locked messages are in the
32319304Speter	 * vi screen, not the ex screen.
32419304Speter	 *
32519304Speter	 * XXX
32619304Speter	 * If we have a command-line option, the error message can end
32719304Speter	 * up in the wrong place, but I think that the combination is
32819304Speter	 * unlikely.
32919304Speter	 */
33019304Speter	if (gp->c_option == NULL) {
33119304Speter		F_CLR(sp, SC_EX | SC_VI);
33219304Speter		F_SET(sp, LF_ISSET(SC_EX | SC_VI));
33319304Speter	}
33419304Speter
33519304Speter	/* Open a tag file if specified. */
336254225Speter	if (tag_f != NULL) {
337254225Speter		CHAR2INT(sp, tag_f, strlen(tag_f) + 1, w, wlen);
338254225Speter		if (ex_tag_first(sp, w))
339254225Speter			goto err;
340254225Speter	}
34119304Speter
34219304Speter	/*
34319304Speter	 * Append any remaining arguments as file names.  Files are recovery
34419304Speter	 * files if -r specified.  If the tag option or ex startup commands
34519304Speter	 * loaded a file, then any file arguments are going to come after it.
34619304Speter	 */
34719304Speter	if (*argv != NULL) {
34819304Speter		if (sp->frp != NULL) {
34919304Speter			/* Cheat -- we know we have an extra argv slot. */
350254225Speter			*--argv = strdup(sp->frp->name);
35119304Speter			if (*argv == NULL) {
35219304Speter				v_estr(gp->progname, errno, NULL);
35319304Speter				goto err;
35419304Speter			}
35519304Speter		}
35619304Speter		sp->argv = sp->cargv = argv;
35719304Speter		F_SET(sp, SC_ARGNOFREE);
35819304Speter		if (flagchk == 'r')
35919304Speter			F_SET(sp, SC_ARGRECOVER);
36019304Speter	}
36119304Speter
36219304Speter	/*
36319304Speter	 * If the ex startup commands and or/the tag option haven't already
36419304Speter	 * created a file, create one.  If no command-line files were given,
36519304Speter	 * use a temporary file.
36619304Speter	 */
36719304Speter	if (sp->frp == NULL) {
36819304Speter		if (sp->argv == NULL) {
36919304Speter			if ((frp = file_add(sp, NULL)) == NULL)
37019304Speter				goto err;
37119304Speter		} else  {
372254225Speter			if ((frp = file_add(sp, sp->argv[0])) == NULL)
37319304Speter				goto err;
37419304Speter			if (F_ISSET(sp, SC_ARGRECOVER))
37519304Speter				F_SET(frp, FR_RECOVER);
37619304Speter		}
37719304Speter
37819304Speter		if (file_init(sp, frp, NULL, 0))
37919304Speter			goto err;
38019304Speter		if (EXCMD_RUNNING(gp)) {
38119304Speter			(void)ex_cmd(sp);
38219304Speter			if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE)) {
38319304Speter				if (screen_end(sp))
38419304Speter					goto err;
38519304Speter				goto done;
38619304Speter			}
38719304Speter		}
38819304Speter	}
38919304Speter
39019304Speter	/*
39119304Speter	 * Check to see if we need to wait for ex.  If SC_SCR_EX is set, ex
39219304Speter	 * was forced to initialize the screen during startup.  We'd like to
39319304Speter	 * wait for a single character from the user, but we can't because
39419304Speter	 * we're not in raw mode.  We can't switch to raw mode because the
39519304Speter	 * vi initialization will switch to xterm's alternate screen, causing
39619304Speter	 * us to lose the messages we're pausing to make sure the user read.
39719304Speter	 * So, wait for a complete line.
39819304Speter	 */
39919304Speter	if (F_ISSET(sp, SC_SCR_EX)) {
40019304Speter		p = msg_cmsg(sp, CMSG_CONT_R, &len);
40119304Speter		(void)write(STDOUT_FILENO, p, len);
40219304Speter		for (;;) {
40319304Speter			if (v_event_get(sp, &ev, 0, 0))
40419304Speter				goto err;
40519304Speter			if (ev.e_event == E_INTERRUPT ||
406254225Speter			    (ev.e_event == E_CHARACTER &&
407254225Speter			     (ev.e_value == K_CR || ev.e_value == K_NL)))
40819304Speter				break;
40919304Speter			(void)gp->scr_bell(sp);
41019304Speter		}
41119304Speter	}
41219304Speter
41319304Speter	/* Switch into the right editor, regardless. */
41419304Speter	F_CLR(sp, SC_EX | SC_VI);
41519304Speter	F_SET(sp, LF_ISSET(SC_EX | SC_VI) | SC_STATUS_CNT);
41619304Speter
41719304Speter	/*
41819304Speter	 * Main edit loop.  Vi handles split screens itself, we only return
41919304Speter	 * here when switching editor modes or restarting the screen.
42019304Speter	 */
42119304Speter	while (sp != NULL)
42219304Speter		if (F_ISSET(sp, SC_EX) ? ex(&sp) : vi(&sp))
42319304Speter			goto err;
42419304Speter
42519304Speterdone:	rval = 0;
42619304Speter	if (0)
42719304Spetererr:		rval = 1;
42819304Speter
42919304Speter	/* Clean out the global structure. */
43019304Speter	v_end(gp);
43119304Speter
43219304Speter	return (rval);
43319304Speter}
43419304Speter
43519304Speter/*
43619304Speter * v_end --
43719304Speter *	End the program, discarding screens and most of the global area.
43819304Speter *
43919304Speter * PUBLIC: void v_end __P((GS *));
44019304Speter */
44119304Spetervoid
44219304Speterv_end(gp)
44319304Speter	GS *gp;
44419304Speter{
44519304Speter	MSGS *mp;
44619304Speter	SCR *sp;
44719304Speter
44819304Speter	/* If there are any remaining screens, kill them off. */
44919304Speter	if (gp->ccl_sp != NULL) {
45019304Speter		(void)file_end(gp->ccl_sp, NULL, 1);
45119304Speter		(void)screen_end(gp->ccl_sp);
45219304Speter	}
453254225Speter	while ((sp = TAILQ_FIRST(gp->dq)) != NULL)
45419304Speter		(void)screen_end(sp);
455254225Speter	while ((sp = TAILQ_FIRST(gp->hq)) != NULL)
45619304Speter		(void)screen_end(sp);
45719304Speter
45819304Speter#if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY)
45919304Speter	{ FREF *frp;
46019304Speter		/* Free FREF's. */
461254225Speter		while ((frp = TAILQ_FIRST(gp->frefq)) != NULL) {
462254225Speter			TAILQ_REMOVE(gp->frefq, frp, q);
46319304Speter			if (frp->name != NULL)
46419304Speter				free(frp->name);
46519304Speter			if (frp->tname != NULL)
46619304Speter				free(frp->tname);
46719304Speter			free(frp);
46819304Speter		}
46919304Speter	}
47019304Speter
47119304Speter	/* Free key input queue. */
47219304Speter	if (gp->i_event != NULL)
47319304Speter		free(gp->i_event);
47419304Speter
47519304Speter	/* Free cut buffers. */
47619304Speter	cut_close(gp);
47719304Speter
47819304Speter	/* Free map sequences. */
47919304Speter	seq_close(gp);
48019304Speter
48119304Speter	/* Free default buffer storage. */
482254225Speter	(void)text_lfree(gp->dcb_store.textq);
48319304Speter
48419304Speter	/* Close message catalogs. */
48519304Speter	msg_close(gp);
48619304Speter#endif
48719304Speter
48819304Speter	/* Ring the bell if scheduled. */
48919304Speter	if (F_ISSET(gp, G_BELLSCHED))
49019304Speter		(void)fprintf(stderr, "\07");		/* \a */
49119304Speter
49219304Speter	/*
49319304Speter	 * Flush any remaining messages.  If a message is here, it's almost
49419304Speter	 * certainly the message about the event that killed us (although
49519304Speter	 * it's possible that the user is sourcing a file that exits from the
49619304Speter	 * editor).
49719304Speter	 */
498254225Speter	while ((mp = SLIST_FIRST(gp->msgq)) != NULL) {
49919304Speter		(void)fprintf(stderr, "%s%.*s",
50019304Speter		    mp->mtype == M_ERR ? "ex/vi: " : "", (int)mp->len, mp->buf);
501254225Speter		SLIST_REMOVE_HEAD(gp->msgq, q);
50219304Speter#if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY)
50319304Speter		free(mp->buf);
50419304Speter		free(mp);
50519304Speter#endif
50619304Speter	}
50719304Speter
50819304Speter#if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY)
50919304Speter	/* Free any temporary space. */
51019304Speter	if (gp->tmp_bp != NULL)
51119304Speter		free(gp->tmp_bp);
51219304Speter
51319304Speter#if defined(DEBUG)
51419304Speter	/* Close debugging file descriptor. */
51519304Speter	if (gp->tracefp != NULL)
51619304Speter		(void)fclose(gp->tracefp);
51719304Speter#endif
51819304Speter#endif
51919304Speter}
52019304Speter
52119304Speter/*
52219304Speter * v_obsolete --
52319304Speter *	Convert historic arguments into something getopt(3) will like.
52419304Speter */
52519304Speterstatic int
526254225Speterv_obsolete(
527254225Speter	char *name,
528254225Speter	char *argv[])
52919304Speter{
53019304Speter	size_t len;
53119304Speter	char *p;
53219304Speter
53319304Speter	/*
53419304Speter	 * Translate old style arguments into something getopt will like.
53519304Speter	 * Make sure it's not text space memory, because ex modifies the
53619304Speter	 * strings.
53719304Speter	 *	Change "+" into "-c$".
53819304Speter	 *	Change "+<anything else>" into "-c<anything else>".
53919304Speter	 *	Change "-" into "-s"
54019304Speter	 *	The c, T, t and w options take arguments so they can't be
54119304Speter	 *	    special arguments.
54219304Speter	 *
54319304Speter	 * Stop if we find "--" as an argument, the user may want to edit
54419304Speter	 * a file named "+foo".
54519304Speter	 */
54619304Speter	while (*++argv && strcmp(argv[0], "--"))
54719304Speter		if (argv[0][0] == '+') {
54819304Speter			if (argv[0][1] == '\0') {
549254225Speter				argv[0] = strdup("-c$");
55019304Speter				if (argv[0] == NULL)
55119304Speter					goto nomem;
55219304Speter			} else  {
55319304Speter				p = argv[0];
55419304Speter				len = strlen(argv[0]);
555254225Speter				argv[0] = malloc(len + 2);
55619304Speter				if (argv[0] == NULL)
55719304Speter					goto nomem;
55819304Speter				argv[0][0] = '-';
55919304Speter				argv[0][1] = 'c';
560254225Speter				(void)strlcpy(argv[0] + 2, p + 1, len);
56119304Speter			}
56219304Speter		} else if (argv[0][0] == '-')
56319304Speter			if (argv[0][1] == '\0') {
564254225Speter				argv[0] = strdup("-s");
56519304Speter				if (argv[0] == NULL) {
56619304Speternomem:					v_estr(name, errno, NULL);
56719304Speter					return (1);
56819304Speter				}
56919304Speter			} else
57019304Speter				if ((argv[0][1] == 'c' || argv[0][1] == 'T' ||
57119304Speter				    argv[0][1] == 't' || argv[0][1] == 'w') &&
57219304Speter				    argv[0][2] == '\0')
57319304Speter					++argv;
57419304Speter	return (0);
57519304Speter}
57619304Speter
57719304Speter#ifdef DEBUG
57819304Speterstatic void
579254225Speterattach(GS *gp)
58019304Speter{
58119304Speter	int fd;
58219304Speter	char ch;
58319304Speter
58419304Speter	if ((fd = open(_PATH_TTY, O_RDONLY, 0)) < 0) {
58519304Speter		v_estr(gp->progname, errno, _PATH_TTY);
58619304Speter		return;
58719304Speter	}
58819304Speter
58919304Speter	(void)printf("process %lu waiting, enter <CR> to continue: ",
59019304Speter	    (u_long)getpid());
59119304Speter	(void)fflush(stdout);
59219304Speter
59319304Speter	do {
59419304Speter		if (read(fd, &ch, 1) != 1) {
59519304Speter			(void)close(fd);
59619304Speter			return;
59719304Speter		}
59819304Speter	} while (ch != '\n' && ch != '\r');
59919304Speter	(void)close(fd);
60019304Speter}
60119304Speter#endif
60219304Speter
60319304Speterstatic void
604254225Speterv_estr(
605254225Speter	char *name,
606254225Speter	int eno,
607254225Speter	char *msg)
60819304Speter{
60919304Speter	(void)fprintf(stderr, "%s", name);
61019304Speter	if (msg != NULL)
61119304Speter		(void)fprintf(stderr, ": %s", msg);
61219304Speter	if (eno)
61319304Speter		(void)fprintf(stderr, ": %s", strerror(errno));
61419304Speter	(void)fprintf(stderr, "\n");
61519304Speter}
616