xref: /csrg-svn/contrib/ed/main.c (revision 59915)
157694Sbostic /*-
257694Sbostic  * Copyright (c) 1992 The Regents of the University of California.
357694Sbostic  * All rights reserved.
457694Sbostic  *
557694Sbostic  * This code is derived from software contributed to Berkeley by
657694Sbostic  * Rodney Ruddock of the University of Guelph.
757694Sbostic  *
857694Sbostic  * %sccs.include.redist.c%
957694Sbostic  */
1057694Sbostic 
1157694Sbostic #ifndef lint
1259475Sbostic char copyright[] =
1359475Sbostic "@(#) Copyright (c) 1992 The Regents of the University of California.\n\
1459475Sbostic  All rights reserved.\n";
1557694Sbostic #endif /* not lint */
1657694Sbostic 
1759475Sbostic #ifndef lint
18*59915Sbostic static char sccsid[] = "@(#)main.c	5.12 (Berkeley) 05/11/93";
1959475Sbostic #endif /* not lint */
2059475Sbostic 
2157710Sbostic #include <sys/types.h>
2258315Sbostic #include <sys/ioctl.h>
2357710Sbostic 
2459477Sbostic #include <limits.h>
2557710Sbostic #include <regex.h>
2657710Sbostic #include <setjmp.h>
2757710Sbostic #include <signal.h>
2857710Sbostic #include <stdio.h>
2957710Sbostic #include <stdlib.h>
3057710Sbostic #include <string.h>
3159477Sbostic #include <unistd.h>
3257710Sbostic 
3358315Sbostic #ifdef DBI
3458315Sbostic #include <db.h>
3558315Sbostic #endif
3658315Sbostic 
3757694Sbostic #include "ed.h"
3857710Sbostic #include "extern.h"
3957694Sbostic 
4057694Sbostic /*
4157694Sbostic  * This is where all of the "global" variables are declared. They are
4257694Sbostic  * set for extern in the ed.h header file (so everyone can get them).
4357694Sbostic  */
4457694Sbostic 
4558564Sralph int nn_max, nn_max_flag, Start_default, End_default, address_flag;
4658315Sbostic int zsnum, filename_flag, add_flag=0, join_flag=0;
4759558Sbostic int help_flag=0, gut_num=-1;
4858315Sbostic #ifdef STDIO
4958315Sbostic FILE *fhtmp;
5058315Sbostic int file_seek;
5158315Sbostic #endif
5257694Sbostic 
5358315Sbostic #ifdef DBI
5457694Sbostic DB *dbhtmp;
5558315Sbostic #endif
5657694Sbostic 
5757694Sbostic LINE *nn_max_start, *nn_max_end;
5857694Sbostic 
5957694Sbostic struct MARK mark_matrix[26]; /* in init set all to null */
6057694Sbostic 
6157694Sbostic char *text;
6259475Sbostic LINE **gut=NULL;
6357694Sbostic char *filename_current, *prompt_string=NULL, help_msg[130];
6457694Sbostic char *template=NULL;
6557694Sbostic int prompt_str_flg=0, start_up_flag=0, name_set=0;
6657694Sbostic 
6758564Sralph LINE *top, *current, *bottom, *Start, *End;
6857694Sbostic struct u_layer *u_stk;
6957694Sbostic struct d_layer *d_stk;
7057694Sbostic LINE *u_current, *u_top, *u_bottom;
7157694Sbostic int u_set;
7257694Sbostic regex_t RE_comp;
7357694Sbostic regmatch_t RE_match[RE_SEC];
7457694Sbostic int RE_sol=0, RE_flag=0;
7557694Sbostic char *RE_patt=NULL;
7657694Sbostic 
7757694Sbostic int ss; /* for the getc() */
7859475Sbostic int explain_flag=1, g_flag=0, GV_flag=0, printsfx=0, exit_code=0;
7957694Sbostic long change_flag=0L;
8057694Sbostic int line_length;
8158352Sbostic jmp_buf ctrl_position, ctrl_position2, ctrl_position3; /* For SIGnal handling. */
8258352Sbostic int sigint_flag, sighup_flag, sigspecial=0, sigspecial2=0, sigspecial3=0;
8357694Sbostic 
8457710Sbostic static void sigint_handler __P((int));
8557710Sbostic static void sighup_handler __P((int));
8657710Sbostic 
8757710Sbostic /*
8857710Sbostic  * Starts the whole show going. Set things up as the arguments spec
8957710Sbostic  * in the shell and set a couple of the global variables.
9057710Sbostic  *
9157710Sbostic  * Note naming viol'n with errnum for consistancy.
9257694Sbostic  */
9357710Sbostic int
9457710Sbostic main(argc, argv)
9557710Sbostic 	int argc;
9657710Sbostic 	char *argv[];
9757694Sbostic {
98*59915Sbostic 	int l_num, errnum=0, l_err=0;
9958710Sbostic 	char *l_fnametmp, *l_col, buf[2];
10058315Sbostic 	struct winsize win;
10157694Sbostic 
10258710Sbostic 	setbuffer(stdin, buf, 1);
10358315Sbostic 	line_length = ((l_col = getenv("COLUMNS")) == NULL ? 0 : atoi(l_col));
10459475Sbostic 	if ((line_length == 0 && isatty(STDOUT_FILENO) &&
10559475Sbostic 		ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) != -1))
10658315Sbostic 		line_length = win.ws_col;
10758315Sbostic 	if (line_length == 0)
10858315Sbostic 		line_length = 78;
10957694Sbostic 
11058564Sralph 	Start = End = NULL;
11157710Sbostic 	top = bottom = NULL;
11257710Sbostic 	current = NULL;
11357710Sbostic 	nn_max_flag = 0;
11457710Sbostic 	nn_max_start = nn_max_end = NULL;
11557710Sbostic 	l_fnametmp = calloc(FILENAME_LEN, sizeof(char));
11657710Sbostic 	if (l_fnametmp == NULL)
11757710Sbostic 		ed_exit(4);
11857710Sbostic 	text = calloc(NN_MAX_START + 2, sizeof(char));
11957710Sbostic 	if (text == NULL)
12057710Sbostic 		ed_exit(4);
12158564Sralph 	Start_default = End_default = 0;
12257710Sbostic 	zsnum = 22;		/* for the 'z' command */
12359558Sbostic 	help_msg[0] = '\0';
12457710Sbostic 	u_stk = NULL;
12557710Sbostic 	d_stk = NULL;
12657710Sbostic 	u_current = u_top = u_bottom = NULL;
12757710Sbostic 	u_set = 0;		/* for in d after a j */
12857710Sbostic 	filename_flag = 0;
12957710Sbostic 	filename_current = NULL;
13057694Sbostic 
13157710Sbostic 	l_num = 1;
13257710Sbostic 	for (;;) {
13357710Sbostic 		/* Process the command line options */
13457710Sbostic 		if (l_num >= argc)
13557710Sbostic 			break;
13657710Sbostic 		switch (argv[l_num][0]) {
13757710Sbostic 		case '-':
13857710Sbostic 			switch (argv[l_num][1]) {
13957710Sbostic 			case '\0':	/* this is why 'getopt' not used */
14057710Sbostic 			case 's':
14157710Sbostic 				explain_flag = 0;
14257710Sbostic 				break;
14357710Sbostic 			case 'p':
14457710Sbostic 				if (++l_num < argc) {
14557710Sbostic 					prompt_string =
14657710Sbostic 					    calloc(strlen(argv[l_num]),
14757710Sbostic 					    sizeof(char));
14857710Sbostic 					if (prompt_string == NULL)
14957710Sbostic 						ed_exit(4);
15057710Sbostic 					strcpy(prompt_string, argv[l_num]);
15157710Sbostic 					prompt_str_flg = 1;
15257710Sbostic 					break;
15357710Sbostic 				}
15457710Sbostic 				l_err = 1;
15558710Sbostic 			case 'v':
15658710Sbostic #ifdef BSD
15759558Sbostic 				(void)printf("ed: in BSD mode:\n");
15858710Sbostic #endif
15958710Sbostic #ifdef POSIX
16059558Sbostic 				(void)printf("ed: in POSIX mode:\n");
16158710Sbostic #endif
16259475Sbostic 				break;
16357710Sbostic 			default:
16457710Sbostic 				l_err++;
16557710Sbostic 				ed_exit(l_err);
16657710Sbostic 			}
16757710Sbostic 			break;
16857710Sbostic 		default:
16957710Sbostic 			if (name_set)
17057710Sbostic 				ed_exit(3);
17157710Sbostic 			strcpy(l_fnametmp, argv[l_num]);
17257710Sbostic 			filename_current = l_fnametmp;
17357710Sbostic 			name_set = 1;
17457710Sbostic 			if (prompt_str_flg)
17557710Sbostic 				break;
17657710Sbostic 			/* default ed prompt */
17757710Sbostic 			prompt_string = (char *) calloc(3, sizeof(char));
17857710Sbostic 			strcpy(prompt_string, "*");
17957710Sbostic 			break;
18057710Sbostic 		}
18157710Sbostic 		l_num++;
18257710Sbostic 	}
18357710Sbostic 
18457710Sbostic 	start_up_flag = 1;
18557710Sbostic 	cmd_loop(stdin, &errnum);
18657710Sbostic 	/* NOTREACHED */
18757710Sbostic }
18857710Sbostic 
18957694Sbostic /*
19057710Sbostic  * The command loop. What the command is that the user has specified
19157694Sbostic  * is determined here. This is not just for commands coming from
19257694Sbostic  * the terminal but any standard i/o stream; see the global commands.
19357694Sbostic  * Some of the commands are handled within here (i.e. 'H') while most
19457694Sbostic  * are handled in their own functions (as called).
19557694Sbostic  */
19657694Sbostic void
19757694Sbostic cmd_loop(inputt, errnum)
19857710Sbostic 	FILE *inputt;
19957710Sbostic 	int *errnum;
20057694Sbostic {
20157710Sbostic 	LINE *l_tempp;
20257710Sbostic 	int l_last, l_jmp_flag;
20357694Sbostic 
20458315Sbostic 	l_last = 0; /* value in l_last may be clobbered (reset to = 0) by longjump, but that's okay */
20557694Sbostic 
20657710Sbostic 	if (g_flag == 0) {	/* big, BIG trouble if we don't check! think. */
20757710Sbostic 		/* set the jump point for the signals */
20857710Sbostic 		l_jmp_flag = setjmp(ctrl_position);
20957710Sbostic 		signal(SIGINT, sigint_handler);
21057710Sbostic 		signal(SIGHUP, sighup_handler);
21157710Sbostic 		switch (l_jmp_flag) {
21257710Sbostic 		case JMP_SET:
21357710Sbostic 			break;
21457710Sbostic 		/* Some general cleanup not specific to the jmp pt. */
21557710Sbostic 		case INTERUPT:
21657710Sbostic 			sigint_flag = 0;
21757710Sbostic 			GV_flag = 0;	/* safest place to do these flags */
21857710Sbostic 			g_flag = 0;
21959558Sbostic 			(void)printf("\n?\n");
22057710Sbostic 			break;
22157710Sbostic 		case HANGUP:		/* shouldn't get here. */
22257710Sbostic 			break;
22357710Sbostic 		default:
22457710Sbostic 			(void)fprintf(stderr, "Signal jump problem\n");
22557710Sbostic 		}
22657710Sbostic 		/* Only do this once! */
22757710Sbostic 		if (start_up_flag) {
22857710Sbostic 			start_up_flag = 0;
22957710Sbostic 			/* simulate the 'e' at startup */
23057710Sbostic 			e2(inputt, errnum);
231*59915Sbostic 			if (*errnum == 0)
232*59915Sbostic 				goto errmsg2;
23357710Sbostic 		}
23457710Sbostic 	}
23557710Sbostic 	for (;;) {
23657710Sbostic 		if (prompt_str_flg == 1)
23757710Sbostic 			(void)printf("%s", prompt_string);
23857710Sbostic 		ss = getc(inputt);
23957710Sbostic 		*errnum = 0;
24058564Sralph 		l_tempp = Start = End = NULL;
24158564Sralph 		Start_default = End_default = 1;
24257694Sbostic 
24357710Sbostic 		/*
24457710Sbostic 		 * This isn't nice and alphabetical mainly because of
24557710Sbostic 		 * restrictions with 'G' and 'V' (see ed(1)).
24657710Sbostic 		 */
24757710Sbostic 		for (;;) {
24857710Sbostic 			switch (ss) {
24957710Sbostic 			case 'd':
25057710Sbostic 				d(inputt, errnum);
25157710Sbostic 				break;
25257710Sbostic 			case 'e':
25357710Sbostic 			case 'E':
25457710Sbostic 				e(inputt, errnum);
255*59915Sbostic 				if (*errnum == 0)
256*59915Sbostic 					goto errmsg2;
25757710Sbostic 				break;
25857710Sbostic 			case 'f':
25957710Sbostic 				f(inputt, errnum);
26057710Sbostic 				break;
26157710Sbostic 			case 'a':
26257710Sbostic 			case 'c':
26357710Sbostic 			case 'i':
26457710Sbostic 			case 'g':
26557710Sbostic 			case 'G':
26657710Sbostic 			case 'v':
26757710Sbostic 			case 'V':
26857710Sbostic 				if (GV_flag == 1) {
26957710Sbostic 					(void)sprintf(help_msg,
27057710Sbostic 					    "command `%c' illegal in G/V", ss);
27157710Sbostic 					*errnum = -1;
27257710Sbostic 					break;
27357710Sbostic 				}
27457710Sbostic 				switch (ss) {
27557710Sbostic 				case 'a':
27657710Sbostic 					a(inputt, errnum);
27757710Sbostic 					break;
27857710Sbostic 				case 'c':
27957710Sbostic 					c(inputt, errnum);
28057710Sbostic 					break;
28157710Sbostic 				case 'i':
28257710Sbostic 					i(inputt, errnum);
28357710Sbostic 					break;
28457710Sbostic 				default:
28557710Sbostic 					g(inputt, errnum);
28657710Sbostic 				}
28757710Sbostic 				break;
28857710Sbostic 			case 'h':
28957710Sbostic 				if (rol(inputt, errnum))
29057710Sbostic 					break;
29159558Sbostic 				if (help_msg[0])
29259558Sbostic 					(void)printf("%s\n", help_msg);
29357710Sbostic 				*errnum = 1;
29457710Sbostic 				break;
29557710Sbostic 			case 'H':
29657710Sbostic 				if (rol(inputt, errnum))
29757710Sbostic 					break;
29857710Sbostic 				if (help_flag == 0) {
29957710Sbostic 					help_flag = 1;
30059558Sbostic 					if (help_msg[0])
30159558Sbostic 						(void)printf("%s\n",
30259558Sbostic 						    help_msg);
30357710Sbostic 				} else
30457710Sbostic 					help_flag = 0;
30557710Sbostic 				*errnum = 1;
30657710Sbostic 				break;
30757710Sbostic 			case 'j':
30857710Sbostic 				j(inputt, errnum);
30957710Sbostic 				break;
31057710Sbostic 			case 'k':
31157710Sbostic 				set_mark(inputt, errnum);
31257710Sbostic 				break;
31357710Sbostic 			case 'l':
31457710Sbostic 				l(inputt, errnum);
31557710Sbostic 				break;
31657710Sbostic 			case 'm':
31757710Sbostic 				m(inputt, errnum);
31857710Sbostic 				break;
31957694Sbostic #ifdef POSIX
32057710Sbostic 				/* In POSIX-land 'P' toggles the prompt. */
32157710Sbostic 			case 'P':
32257710Sbostic 				if (rol(inputt, errnum))
32357710Sbostic 					break;
32457710Sbostic 				prompt_str_flg = prompt_str_flg ? 0 : 1;
32557710Sbostic 				*errnum = 1;
32657710Sbostic 				break;
32757694Sbostic #endif
32857710Sbostic 			case '\n':
32957710Sbostic 				if (GV_flag == 1)
33057710Sbostic 					return;
33157710Sbostic 				/* For 'p' to consume. */
33257710Sbostic 				ungetc(ss, inputt);
33357710Sbostic 				if ((current == bottom) && (End == NULL)) {
33457710Sbostic 					strcpy(help_msg, "at end of buffer");
33557710Sbostic 					*errnum = -1;
33657710Sbostic 					break;
33757710Sbostic 				}
33857710Sbostic 				current = current->below;
33957694Sbostic #ifdef BSD
34057710Sbostic 				/* In BSD 'P'=='p'. */
34157710Sbostic 			case 'P':
34257694Sbostic #endif
34357710Sbostic 			case 'p':
34457710Sbostic 				p(inputt, errnum, 0);
34557710Sbostic 				break;
34657710Sbostic 			case 'n':
34757710Sbostic 				p(inputt, errnum, 1);
34857710Sbostic 				break;
34957710Sbostic 			/*
35057710Sbostic 			 * An EOF means 'q' unless we're still in the middle
35157710Sbostic 			 * of a global command, in which case it was just the
35257710Sbostic 			 * end of the command list found.
35357710Sbostic 			 */
35457710Sbostic 			case EOF:
35557710Sbostic 				clearerr(inputt);
35657710Sbostic 				if (g_flag > 0)
35757710Sbostic 					return;
35858710Sbostic 				/*ss = 'q';*/
35957710Sbostic 			case 'q':
36057710Sbostic 			case 'Q':
361*59915Sbostic 				if ((!isatty(STDIN_FILENO)) && (ss == 'q'))
362*59915Sbostic 					ss = 'Q';
36357710Sbostic 				q(inputt, errnum);
36457710Sbostic 				break;
36557710Sbostic 			case 'r':
36657710Sbostic 				r(inputt, errnum);
367*59915Sbostic 				if (*errnum == 0)
368*59915Sbostic 					goto errmsg2;
36957710Sbostic 				break;
37057710Sbostic 			case 's':
37157710Sbostic 				s(inputt, errnum);
37257710Sbostic 				break;
37357710Sbostic 			case 't':
37457710Sbostic 				t(inputt, errnum);
37557710Sbostic 				break;
37657710Sbostic 			case 'u':
37757710Sbostic 				u(inputt, errnum);
37857710Sbostic 				break;
37957710Sbostic 			case 'w':
38057710Sbostic 			case 'W':
38157710Sbostic 				w(inputt, errnum);
38257710Sbostic 				break;
38357710Sbostic 			case 'z':
38457710Sbostic 				z(inputt, errnum);
38557710Sbostic 				break;
38657710Sbostic 			case '!':
38757710Sbostic 				bang(inputt, errnum);
38857710Sbostic 				break;
38957710Sbostic 			case '=':
39057710Sbostic 				equal(inputt, errnum);
39157710Sbostic 				break;
39257710Sbostic 			/*
39357710Sbostic 			 * Control of address forms from here down.
39457710Sbostic 			 *
39557710Sbostic 			 * It's a head-game to understand why ";" and "," look
39657710Sbostic 			 * as they do below, but a lot of it has to do with ";"
39757710Sbostic 			 * and "," being special address pair forms themselves
39857710Sbostic 			 * and the compatibility for address "chains".
39957710Sbostic 			 */
40057710Sbostic 			case ';':
40158564Sralph 				if (End_default == 1 && Start_default == 1) {
40258564Sralph 					Start = current;
40357710Sbostic 					End = bottom;
40458564Sralph 					Start_default = End_default = 0;
40557710Sbostic 				} else {
40658564Sralph 					Start = current = End;
40758564Sralph 					Start_default = 0;
40857710Sbostic 					End_default = 1;
40957710Sbostic 				}
41057710Sbostic 				l_tempp = NULL;
41157710Sbostic 				break;
41257710Sbostic 			/*
41357710Sbostic 			 * Note address ".,x" where x is a cmd is legal; not a
41457710Sbostic 			 * bug - for backward compatability.
41557710Sbostic 			 */
41657710Sbostic 			case ',':
41758564Sralph 				if (End_default == 1 && Start_default == 1) {
41858564Sralph 					Start = top;
41957710Sbostic 					End = bottom;
42058564Sralph 					Start_default = End_default = 0;
42157710Sbostic 				} else {
42258564Sralph 					Start = End;
42358564Sralph 					Start_default = 0;
42457710Sbostic 					End_default = 1;
42557710Sbostic 				}
42657710Sbostic 				l_tempp = NULL;
42757710Sbostic 				break;
42857710Sbostic 			case '%':
42957710Sbostic 				if (End_default == 0) {
43057710Sbostic 					strcpy(help_msg,
43157710Sbostic 					    "'%' is an address pair");
43257710Sbostic 					*errnum = -1;
43357710Sbostic 					break;
43457710Sbostic 				}
43558564Sralph 				Start = top;
43657710Sbostic 				End = bottom;
43758564Sralph 				Start_default = End_default = 0;
43857710Sbostic 				l_tempp = NULL;
43957710Sbostic 				break;
44057710Sbostic 			/*
44157710Sbostic 			 * Within address_conv => l_last = '+', foobar, but
44257710Sbostic 			 * historical and now POSIX...
44357710Sbostic 			 */
44457710Sbostic 			case ' ':
44557710Sbostic 				break;
44657710Sbostic 			case '0':
44757710Sbostic 			case '1':
44857710Sbostic 			case '2':
44957710Sbostic 			case '3':
45057710Sbostic 			case '4':
45157710Sbostic 			case '5':
45257710Sbostic 			case '6':
45357710Sbostic 			case '7':
45457710Sbostic 			case '8':
45557710Sbostic 			case '9':
45657710Sbostic 			case '-':
45757710Sbostic 			case '^':
45857710Sbostic 			case '+':
45957710Sbostic 			case '\'':
46057710Sbostic 			case '$':
46157710Sbostic 			case '?':
46257710Sbostic 			case '/':
46357710Sbostic 			case '.':
46457710Sbostic 				ungetc(ss, inputt);
46558564Sralph 				if (Start_default == 0 && End_default == 0) {
46657710Sbostic 					strcpy(help_msg,
46757710Sbostic 					    "badly formed address");
46857710Sbostic 					*errnum = -1;
46957710Sbostic 					break;
47057710Sbostic 				}
47157710Sbostic 				ss = l_last;
47257710Sbostic 				l_tempp = address_conv(l_tempp, inputt, errnum);
47357710Sbostic 				if (*errnum < 0)
47457710Sbostic 					break;
47557710Sbostic 				End = l_tempp;
47657710Sbostic 				End_default = 0;
47758564Sralph 				if (Start_default == 0)
47858564Sralph 					*errnum = address_check(Start, End);
47957710Sbostic 				break;
48057710Sbostic 			default:
48157710Sbostic 				*errnum = -1;
48257710Sbostic 				strcpy(help_msg, "unknown command");
48357710Sbostic 				break;
48457710Sbostic 			}	/* end-switch(ss) */
48557694Sbostic 
48657710Sbostic 			/* Things came out okay with the last command. */
48757710Sbostic 			if (*errnum > 0) {
48857710Sbostic 				if (GV_flag == 1)
48957710Sbostic 					return;
49057710Sbostic 				/* Do the suffixes if there were any. */
49157710Sbostic 				if (printsfx > 0) {
49258564Sralph 					Start = End = current;
49357710Sbostic 					ungetc(ss, inputt);
49457710Sbostic 					if (printsfx == 1)
49557710Sbostic 						p(inputt, errnum, 0);
49657710Sbostic 					else
49757710Sbostic 						if (printsfx == 2)
49857710Sbostic 							p(inputt, errnum, 1);
49957710Sbostic 						else if (printsfx == 4)
50057710Sbostic 							l(inputt, errnum);
50157710Sbostic 					/* Unlikely it's needed, but... */
50257710Sbostic 					if (*errnum < 0)
50357710Sbostic 						goto errmsg;
50457710Sbostic 				}
50557710Sbostic 				break;
50657710Sbostic 			}
50757710Sbostic 			/* There was a problem with the last command. */
50857710Sbostic 			else if (*errnum < 0) {
50957710Sbostic errmsg:				while (((ss = getc(inputt)) != '\n') &&
51057710Sbostic 				    (ss != EOF));
511*59915Sbostic 				(void)printf("?\n");
512*59915Sbostic errmsg2:			if (help_flag)
513*59915Sbostic 					(void)printf("%s\n", help_msg);
51459475Sbostic 				exit_code = 4;
51559475Sbostic /* for people wanting scripts to carry on after a cmd error, then
51659475Sbostic  * define NOENDONSCRIPT on the compile line.
51759475Sbostic  */
51859475Sbostic #ifndef NOENDONSCRIPT
51959475Sbostic 				if (!isatty(STDIN_FILENO)) {
52059475Sbostic 					ss = 'Q';
52159475Sbostic 					ungetc('\n', inputt);
52259475Sbostic 					q(inputt, errnum);
52359475Sbostic 				}
52459475Sbostic #endif
52558315Sbostic 				break;
52657710Sbostic 			}
52757710Sbostic 			l_last = ss;
52857710Sbostic 			ss = getc(inputt);
52957710Sbostic 		}
53057710Sbostic 	}
53157710Sbostic }
53257694Sbostic 
53357710Sbostic /*
53457710Sbostic  * Exits ed and prints an appropriate message about the command line
53557694Sbostic  * being malformed (see below).
53657694Sbostic  */
53757694Sbostic void
53857694Sbostic ed_exit(err)
53957710Sbostic 	int err;
54057694Sbostic {
54157710Sbostic 	switch (err) {
54257710Sbostic           case 1:
54357710Sbostic 		(void)fprintf(stderr, "ed: illegal option\n");
54457710Sbostic 		break;
54557710Sbostic           case 2:
54657710Sbostic 		(void)fprintf(stderr, "ed: missing promptstring\n");
54757710Sbostic 		break;
54857710Sbostic           case 3:
54957710Sbostic 		(void)fprintf(stderr, "ed: too many filenames\n");
55057710Sbostic 		break;
55157710Sbostic           case 4:
55257710Sbostic 		(void)fprintf(stderr, "ed: out of memory error\n");
55357710Sbostic 		break;
55458315Sbostic 	  case 5:
55558315Sbostic 		(void)fprintf(stderr, "ed: unable to create buffer\n");
55658315Sbostic 		break;
55757710Sbostic           default:
55857710Sbostic 		(void)fprintf(stderr, "ed: command line error\n");
55957710Sbostic 		break;
56057710Sbostic         }
56157710Sbostic 	(void)fprintf(stderr,
56257710Sbostic 	    "ed: ed [ -s ] [ -p promptstring ] [ filename ]\n");
56357710Sbostic 	exit(1);
56457710Sbostic }
56557694Sbostic 
56657694Sbostic /*
56757710Sbostic  * SIGINT is never turned off. We flag it happened and then pay attention
56857710Sbostic  * to it at certain logical locations in the code we don't do more here
56957710Sbostic  * cause some of our buffer pointer's may be in an inbetween state at the
57057710Sbostic  * time of the SIGINT. So we flag it happened, let the local fn handle it
57157710Sbostic  * and do a jump back to the cmd_loop
57257694Sbostic  */
57357710Sbostic static void
57457710Sbostic sigint_handler(signo)
57557710Sbostic 	int signo;
57657710Sbostic {
57757710Sbostic 	sigint_flag = 1;
57858352Sbostic 	if (sigspecial3) {
57958352Sbostic 		sigspecial3 = 0;
58058352Sbostic 		SIGINT_ILACTION;
58158352Sbostic 	}
58258315Sbostic 	else
58358315Sbostic 		if (sigspecial);
58458315Sbostic 		else
58558315Sbostic 			SIGINT_ACTION;
58657710Sbostic }
58757694Sbostic 
58857710Sbostic static void
58957710Sbostic sighup_handler(signo)
59057710Sbostic 	int signo;
59157694Sbostic {
59257710Sbostic 	sighup_flag = 1;
59357710Sbostic 	undo();
59457710Sbostic 	do_hup();
59557710Sbostic 	/* NOTREACHED */
59657694Sbostic 
59757710Sbostic 	SIGHUP_ACTION;
59857710Sbostic }
599