xref: /titanic_54/usr/src/cmd/ed/ed.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
24*7c478bd9Sstevel@tonic-gate 
25*7c478bd9Sstevel@tonic-gate 
26*7c478bd9Sstevel@tonic-gate /*
27*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
28*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
29*7c478bd9Sstevel@tonic-gate  */
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate /*
34*7c478bd9Sstevel@tonic-gate  * Editor
35*7c478bd9Sstevel@tonic-gate  */
36*7c478bd9Sstevel@tonic-gate 
37*7c478bd9Sstevel@tonic-gate #include	<crypt.h>
38*7c478bd9Sstevel@tonic-gate #include	<libgen.h>
39*7c478bd9Sstevel@tonic-gate #include	<wait.h>
40*7c478bd9Sstevel@tonic-gate #include	<string.h>
41*7c478bd9Sstevel@tonic-gate #include	<sys/types.h>
42*7c478bd9Sstevel@tonic-gate #include	<locale.h>
43*7c478bd9Sstevel@tonic-gate #include	<regexpr.h>
44*7c478bd9Sstevel@tonic-gate #include	<regex.h>
45*7c478bd9Sstevel@tonic-gate #include	<errno.h>
46*7c478bd9Sstevel@tonic-gate 
47*7c478bd9Sstevel@tonic-gate static const 	char	*msgtab[] =
48*7c478bd9Sstevel@tonic-gate {
49*7c478bd9Sstevel@tonic-gate 	"write or open on pipe failed",			/*  0 */
50*7c478bd9Sstevel@tonic-gate 	"warning: expecting `w'",			/*  1 */
51*7c478bd9Sstevel@tonic-gate 	"mark not lower case ascii",			/*  2 */
52*7c478bd9Sstevel@tonic-gate 	"Cannot open input file",			/*  3 */
53*7c478bd9Sstevel@tonic-gate 	"PWB spec problem",				/*  4 */
54*7c478bd9Sstevel@tonic-gate 	"nothing to undo",				/*  5 */
55*7c478bd9Sstevel@tonic-gate 	"restricted shell",				/*  6 */
56*7c478bd9Sstevel@tonic-gate 	"cannot create output file",			/*  7 */
57*7c478bd9Sstevel@tonic-gate 	"filesystem out of space!",			/*  8 */
58*7c478bd9Sstevel@tonic-gate 	"cannot open file",				/*  9 */
59*7c478bd9Sstevel@tonic-gate 	"cannot link",					/* 10 */
60*7c478bd9Sstevel@tonic-gate 	"Range endpoint too large",			/* 11 */
61*7c478bd9Sstevel@tonic-gate 	"unknown command",				/* 12 */
62*7c478bd9Sstevel@tonic-gate 	"search string not found",			/* 13 */
63*7c478bd9Sstevel@tonic-gate 	"-",						/* 14 */
64*7c478bd9Sstevel@tonic-gate 	"line out of range",				/* 15 */
65*7c478bd9Sstevel@tonic-gate 	"bad number",					/* 16 */
66*7c478bd9Sstevel@tonic-gate 	"bad range",					/* 17 */
67*7c478bd9Sstevel@tonic-gate 	"Illegal address count",			/* 18 */
68*7c478bd9Sstevel@tonic-gate 	"incomplete global expression",			/* 19 */
69*7c478bd9Sstevel@tonic-gate 	"illegal suffix",				/* 20 */
70*7c478bd9Sstevel@tonic-gate 	"illegal or missing filename",			/* 21 */
71*7c478bd9Sstevel@tonic-gate 	"no space after command",			/* 22 */
72*7c478bd9Sstevel@tonic-gate 	"fork failed - try again",			/* 23 */
73*7c478bd9Sstevel@tonic-gate 	"maximum of 64 characters in file names",	/* 24 */
74*7c478bd9Sstevel@tonic-gate 	"`\\digit' out of range",			/* 25 */
75*7c478bd9Sstevel@tonic-gate 	"interrupt",					/* 26 */
76*7c478bd9Sstevel@tonic-gate 	"line too long",				/* 27 */
77*7c478bd9Sstevel@tonic-gate 	"illegal character in input file",		/* 28 */
78*7c478bd9Sstevel@tonic-gate 	"write error",					/* 29 */
79*7c478bd9Sstevel@tonic-gate 	"out of memory for append",			/* 30 */
80*7c478bd9Sstevel@tonic-gate 	"temp file too big",				/* 31 */
81*7c478bd9Sstevel@tonic-gate 	"I/O error on temp file",			/* 32 */
82*7c478bd9Sstevel@tonic-gate 	"multiple globals not allowed",			/* 33 */
83*7c478bd9Sstevel@tonic-gate 	"global too long",				/* 34 */
84*7c478bd9Sstevel@tonic-gate 	"no match",					/* 35 */
85*7c478bd9Sstevel@tonic-gate 	"illegal or missing delimiter",			/* 36 */
86*7c478bd9Sstevel@tonic-gate 	"-",						/* 37 */
87*7c478bd9Sstevel@tonic-gate 	"replacement string too long",			/* 38 */
88*7c478bd9Sstevel@tonic-gate 	"illegal move destination",			/* 39 */
89*7c478bd9Sstevel@tonic-gate 	"-",						/* 40 */
90*7c478bd9Sstevel@tonic-gate 	"no remembered search string",			/* 41 */
91*7c478bd9Sstevel@tonic-gate 	"'\\( \\)' imbalance",				/* 42 */
92*7c478bd9Sstevel@tonic-gate 	"Too many `\\(' s",				/* 43 */
93*7c478bd9Sstevel@tonic-gate 	"more than 2 numbers given",			/* 44 */
94*7c478bd9Sstevel@tonic-gate 	"'\\}' expected",				/* 45 */
95*7c478bd9Sstevel@tonic-gate 	"first number exceeds second",			/* 46 */
96*7c478bd9Sstevel@tonic-gate 	"incomplete substitute",			/* 47 */
97*7c478bd9Sstevel@tonic-gate 	"newline unexpected",				/* 48 */
98*7c478bd9Sstevel@tonic-gate 	"'[ ]' imbalance",				/* 49 */
99*7c478bd9Sstevel@tonic-gate 	"regular expression overflow",			/* 50 */
100*7c478bd9Sstevel@tonic-gate 	"regular expression error",			/* 51 */
101*7c478bd9Sstevel@tonic-gate 	"command expected",				/* 52 */
102*7c478bd9Sstevel@tonic-gate 	"a, i, or c not allowed in G",			/* 53 */
103*7c478bd9Sstevel@tonic-gate 	"end of line expected",				/* 54 */
104*7c478bd9Sstevel@tonic-gate 	"no remembered replacement string",		/* 55 */
105*7c478bd9Sstevel@tonic-gate 	"no remembered command",			/* 56 */
106*7c478bd9Sstevel@tonic-gate 	"illegal redirection",				/* 57 */
107*7c478bd9Sstevel@tonic-gate 	"possible concurrent update",			/* 58 */
108*7c478bd9Sstevel@tonic-gate 	"-",						/* 59 */
109*7c478bd9Sstevel@tonic-gate 	"the x command has become X (upper case)",	/* 60 */
110*7c478bd9Sstevel@tonic-gate 	"Warning: 'w' may destroy input file "
111*7c478bd9Sstevel@tonic-gate 	"(due to `illegal char' read earlier)",
112*7c478bd9Sstevel@tonic-gate 							/* 61 */
113*7c478bd9Sstevel@tonic-gate 	"Caution: 'q' may lose data in buffer;"
114*7c478bd9Sstevel@tonic-gate 	" 'w' may destroy input file",
115*7c478bd9Sstevel@tonic-gate 							/* 62 */
116*7c478bd9Sstevel@tonic-gate 	"Encryption of string failed",			/* 63 */
117*7c478bd9Sstevel@tonic-gate 	"Encryption facility not available",		/* 64 */
118*7c478bd9Sstevel@tonic-gate 	"Cannot encrypt temporary file",		/* 65 */
119*7c478bd9Sstevel@tonic-gate 	"Enter key:",					/* 66 */
120*7c478bd9Sstevel@tonic-gate 	"Illegal byte sequence",			/* 67 */
121*7c478bd9Sstevel@tonic-gate 	"File does not exist",				/* 68 */
122*7c478bd9Sstevel@tonic-gate 	"tempnam failed",				/* 69 */
123*7c478bd9Sstevel@tonic-gate 	"Cannot open temporary file",			/* 70 */
124*7c478bd9Sstevel@tonic-gate 	0
125*7c478bd9Sstevel@tonic-gate };
126*7c478bd9Sstevel@tonic-gate 
127*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
128*7c478bd9Sstevel@tonic-gate #include <limits.h>
129*7c478bd9Sstevel@tonic-gate #include <stdio.h>
130*7c478bd9Sstevel@tonic-gate #include <signal.h>
131*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
132*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
133*7c478bd9Sstevel@tonic-gate #include <sys/statvfs.h>
134*7c478bd9Sstevel@tonic-gate #include <unistd.h>
135*7c478bd9Sstevel@tonic-gate #include <termio.h>
136*7c478bd9Sstevel@tonic-gate #include <ctype.h>
137*7c478bd9Sstevel@tonic-gate #include <setjmp.h>
138*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
139*7c478bd9Sstevel@tonic-gate #include <wchar.h>	/* I18N */
140*7c478bd9Sstevel@tonic-gate #include <wctype.h>	/* I18N */
141*7c478bd9Sstevel@tonic-gate #include <widec.h>	/* I18N */
142*7c478bd9Sstevel@tonic-gate 
143*7c478bd9Sstevel@tonic-gate #define	FTYPE(A)	(A.st_mode)
144*7c478bd9Sstevel@tonic-gate #define	FMODE(A)	(A.st_mode)
145*7c478bd9Sstevel@tonic-gate #define	IDENTICAL(A, B)	(A.st_dev == B.st_dev && A.st_ino == B.st_ino)
146*7c478bd9Sstevel@tonic-gate #define	ISBLK(A)	((A.st_mode & S_IFMT) == S_IFBLK)
147*7c478bd9Sstevel@tonic-gate #define	ISCHR(A)	((A.st_mode & S_IFMT) == S_IFCHR)
148*7c478bd9Sstevel@tonic-gate #define	ISDIR(A)	((A.st_mode & S_IFMT) == S_IFDIR)
149*7c478bd9Sstevel@tonic-gate #define	ISFIFO(A)	((A.st_mode & S_IFMT) == S_IFIFO)
150*7c478bd9Sstevel@tonic-gate #define	ISREG(A)	((A.st_mode & S_IFMT) == S_IFREG)
151*7c478bd9Sstevel@tonic-gate 
152*7c478bd9Sstevel@tonic-gate #define	PUTM()	if (xcode >= 0) puts(gettext(msgtab[xcode]))
153*7c478bd9Sstevel@tonic-gate #define	UNGETC(c)	(peekc = c)
154*7c478bd9Sstevel@tonic-gate #define	FNSIZE	PATH_MAX
155*7c478bd9Sstevel@tonic-gate #define	LBSIZE	LINE_MAX
156*7c478bd9Sstevel@tonic-gate 
157*7c478bd9Sstevel@tonic-gate /* size of substitution replacement pattern buffer */
158*7c478bd9Sstevel@tonic-gate #define	RHSIZE	(LINE_MAX*2)
159*7c478bd9Sstevel@tonic-gate 
160*7c478bd9Sstevel@tonic-gate #define	KSIZE	8
161*7c478bd9Sstevel@tonic-gate 
162*7c478bd9Sstevel@tonic-gate #define	READ	0
163*7c478bd9Sstevel@tonic-gate #define	WRITE	1
164*7c478bd9Sstevel@tonic-gate 
165*7c478bd9Sstevel@tonic-gate extern  char	*optarg;	/* Value of argument */
166*7c478bd9Sstevel@tonic-gate extern  int	optind;		/* Indicator of argument */
167*7c478bd9Sstevel@tonic-gate extern	int __xpg4;	/* defined in xpg4.c; 0 if not xpg4-compiled program */
168*7c478bd9Sstevel@tonic-gate 
169*7c478bd9Sstevel@tonic-gate struct  Fspec   {
170*7c478bd9Sstevel@tonic-gate 	char    Ftabs[22];
171*7c478bd9Sstevel@tonic-gate 	char    Fdel;
172*7c478bd9Sstevel@tonic-gate 	unsigned char   Flim;
173*7c478bd9Sstevel@tonic-gate 	char    Fmov;
174*7c478bd9Sstevel@tonic-gate 	char    Ffill;
175*7c478bd9Sstevel@tonic-gate };
176*7c478bd9Sstevel@tonic-gate static struct  Fspec   fss;
177*7c478bd9Sstevel@tonic-gate 
178*7c478bd9Sstevel@tonic-gate static char	*fsp;
179*7c478bd9Sstevel@tonic-gate static int	fsprtn;
180*7c478bd9Sstevel@tonic-gate static char	line[70];
181*7c478bd9Sstevel@tonic-gate static char	*linp = line;
182*7c478bd9Sstevel@tonic-gate static int	sig;
183*7c478bd9Sstevel@tonic-gate static int	Xqt = 0;
184*7c478bd9Sstevel@tonic-gate static int	lastc;
185*7c478bd9Sstevel@tonic-gate static char	savedfile[FNSIZE];
186*7c478bd9Sstevel@tonic-gate static char	file[FNSIZE];
187*7c478bd9Sstevel@tonic-gate static char	funny[FNSIZE];
188*7c478bd9Sstevel@tonic-gate static int	funlink = 0;
189*7c478bd9Sstevel@tonic-gate static char	linebuf[LBSIZE];
190*7c478bd9Sstevel@tonic-gate static char	*tstring = linebuf;
191*7c478bd9Sstevel@tonic-gate 
192*7c478bd9Sstevel@tonic-gate static char *expbuf;
193*7c478bd9Sstevel@tonic-gate 
194*7c478bd9Sstevel@tonic-gate static char	rhsbuf[RHSIZE];
195*7c478bd9Sstevel@tonic-gate struct	lin	{
196*7c478bd9Sstevel@tonic-gate 	long cur;
197*7c478bd9Sstevel@tonic-gate 	long sav;
198*7c478bd9Sstevel@tonic-gate };
199*7c478bd9Sstevel@tonic-gate typedef struct lin *LINE;
200*7c478bd9Sstevel@tonic-gate static LINE	zero;
201*7c478bd9Sstevel@tonic-gate static LINE	dot;
202*7c478bd9Sstevel@tonic-gate static LINE	dol;
203*7c478bd9Sstevel@tonic-gate static LINE	endcore;
204*7c478bd9Sstevel@tonic-gate static LINE	fendcore;
205*7c478bd9Sstevel@tonic-gate static LINE	addr1;
206*7c478bd9Sstevel@tonic-gate static LINE	addr2;
207*7c478bd9Sstevel@tonic-gate static LINE	savdol, savdot;
208*7c478bd9Sstevel@tonic-gate static int	globflg;
209*7c478bd9Sstevel@tonic-gate static int	initflg;
210*7c478bd9Sstevel@tonic-gate static char	genbuf[LBSIZE];
211*7c478bd9Sstevel@tonic-gate static long	count;
212*7c478bd9Sstevel@tonic-gate static int	numpass;	/* Number of passes thru dosub(). */
213*7c478bd9Sstevel@tonic-gate static int	gsubf;		/* Occurrence value. LBSIZE-1=all. */
214*7c478bd9Sstevel@tonic-gate static int	ocerr1;	/* Allows lines NOT changed by dosub() to NOT be put */
215*7c478bd9Sstevel@tonic-gate 			/* out. Retains last line changed as current line. */
216*7c478bd9Sstevel@tonic-gate static int	ocerr2;	/* Flags if ANY line changed by substitute(). 0=nc. */
217*7c478bd9Sstevel@tonic-gate static char	*nextip;
218*7c478bd9Sstevel@tonic-gate static char	*linebp;
219*7c478bd9Sstevel@tonic-gate static int	ninbuf;
220*7c478bd9Sstevel@tonic-gate static int	peekc;
221*7c478bd9Sstevel@tonic-gate static int	io;
222*7c478bd9Sstevel@tonic-gate static void	(*oldhup)(), (*oldintr)();
223*7c478bd9Sstevel@tonic-gate static void	(*oldquit)(), (*oldpipe)();
224*7c478bd9Sstevel@tonic-gate static void	quit(int);
225*7c478bd9Sstevel@tonic-gate static int	vflag = 1;
226*7c478bd9Sstevel@tonic-gate static int	xflag;
227*7c478bd9Sstevel@tonic-gate static int	xtflag;
228*7c478bd9Sstevel@tonic-gate static int	kflag;
229*7c478bd9Sstevel@tonic-gate static int	crflag;
230*7c478bd9Sstevel@tonic-gate 		/* Flag for determining if file being read is encrypted */
231*7c478bd9Sstevel@tonic-gate static int	hflag;
232*7c478bd9Sstevel@tonic-gate static int	xcode = -1;
233*7c478bd9Sstevel@tonic-gate static char	crbuf[LBSIZE];
234*7c478bd9Sstevel@tonic-gate static	int	perm[2];
235*7c478bd9Sstevel@tonic-gate static int	tperm[2];
236*7c478bd9Sstevel@tonic-gate static int	permflag;
237*7c478bd9Sstevel@tonic-gate static int	tpermflag;
238*7c478bd9Sstevel@tonic-gate static int	col;
239*7c478bd9Sstevel@tonic-gate static char	*globp;
240*7c478bd9Sstevel@tonic-gate static int	tfile = -1;
241*7c478bd9Sstevel@tonic-gate static int	tline;
242*7c478bd9Sstevel@tonic-gate static char	*tfname;
243*7c478bd9Sstevel@tonic-gate extern char	*locs;
244*7c478bd9Sstevel@tonic-gate static char	ibuff[LBSIZE];
245*7c478bd9Sstevel@tonic-gate static int	iblock = -1;
246*7c478bd9Sstevel@tonic-gate static char	obuff[LBSIZE];
247*7c478bd9Sstevel@tonic-gate static int	oblock = -1;
248*7c478bd9Sstevel@tonic-gate static int	ichanged;
249*7c478bd9Sstevel@tonic-gate static int	nleft;
250*7c478bd9Sstevel@tonic-gate static long	savnames[26], names[26];
251*7c478bd9Sstevel@tonic-gate static int	anymarks;
252*7c478bd9Sstevel@tonic-gate static long	subnewa;
253*7c478bd9Sstevel@tonic-gate static int	fchange;
254*7c478bd9Sstevel@tonic-gate static int	nline;
255*7c478bd9Sstevel@tonic-gate static int	fflg, shflg;
256*7c478bd9Sstevel@tonic-gate static char	prompt[16] = "*";
257*7c478bd9Sstevel@tonic-gate static int	rflg;
258*7c478bd9Sstevel@tonic-gate static int	readflg;
259*7c478bd9Sstevel@tonic-gate static int 	eflg;
260*7c478bd9Sstevel@tonic-gate static int 	qflg = 0;
261*7c478bd9Sstevel@tonic-gate static int 	ncflg;
262*7c478bd9Sstevel@tonic-gate static int 	listn;
263*7c478bd9Sstevel@tonic-gate static int 	listf;
264*7c478bd9Sstevel@tonic-gate static int 	pflag;
265*7c478bd9Sstevel@tonic-gate static int 	flag28 = 0; /* Prevents write after a partial read */
266*7c478bd9Sstevel@tonic-gate static int 	save28 = 0; /* Flag whether buffer empty at start of read */
267*7c478bd9Sstevel@tonic-gate static long 	savtime;
268*7c478bd9Sstevel@tonic-gate static char	*name = "SHELL";
269*7c478bd9Sstevel@tonic-gate static char	*rshell = "/usr/lib/rsh";
270*7c478bd9Sstevel@tonic-gate static	char	*shpath; /* pointer to correct shell for execution */
271*7c478bd9Sstevel@tonic-gate 			/* of execlp() */
272*7c478bd9Sstevel@tonic-gate static char	*val;
273*7c478bd9Sstevel@tonic-gate static char	*home;
274*7c478bd9Sstevel@tonic-gate static int	nodelim;
275*7c478bd9Sstevel@tonic-gate 
276*7c478bd9Sstevel@tonic-gate int	makekey(int *);
277*7c478bd9Sstevel@tonic-gate int	_mbftowc(char *, wchar_t *, int (*)(), int *);
278*7c478bd9Sstevel@tonic-gate static int	error(int code);
279*7c478bd9Sstevel@tonic-gate static void	tlist(struct Fspec *);
280*7c478bd9Sstevel@tonic-gate static void	tstd(struct Fspec *);
281*7c478bd9Sstevel@tonic-gate static void	gdelete(void);
282*7c478bd9Sstevel@tonic-gate static void	delete(void);
283*7c478bd9Sstevel@tonic-gate static void	exfile(void);
284*7c478bd9Sstevel@tonic-gate static void	filename(int comm);
285*7c478bd9Sstevel@tonic-gate static void	newline(void);
286*7c478bd9Sstevel@tonic-gate static int	gettty(void);
287*7c478bd9Sstevel@tonic-gate static void	commands(void);
288*7c478bd9Sstevel@tonic-gate static void	undo(void);
289*7c478bd9Sstevel@tonic-gate static void	save(void);
290*7c478bd9Sstevel@tonic-gate static void	strcopy(char *source, char *dest);
291*7c478bd9Sstevel@tonic-gate static int	strequal(char **scan1, char *str);
292*7c478bd9Sstevel@tonic-gate static int	stdtab(char *, char *);
293*7c478bd9Sstevel@tonic-gate static int	lenchk(char *, struct Fspec *);
294*7c478bd9Sstevel@tonic-gate static void	clear(struct Fspec *);
295*7c478bd9Sstevel@tonic-gate static int	expnd(char *, char *, int *, struct Fspec *);
296*7c478bd9Sstevel@tonic-gate static void	tincr(int, struct Fspec *);
297*7c478bd9Sstevel@tonic-gate static void	targ(struct Fspec *);
298*7c478bd9Sstevel@tonic-gate static int	numb(void);
299*7c478bd9Sstevel@tonic-gate static int	fspec(char *, struct Fspec *, int);
300*7c478bd9Sstevel@tonic-gate static void	red(char *);
301*7c478bd9Sstevel@tonic-gate static void	newtime(void);
302*7c478bd9Sstevel@tonic-gate static void	chktime(void);
303*7c478bd9Sstevel@tonic-gate static void	getime(void);
304*7c478bd9Sstevel@tonic-gate static void	mkfunny(void);
305*7c478bd9Sstevel@tonic-gate static int	eopen(char *, int);
306*7c478bd9Sstevel@tonic-gate static void	eclose(int f);
307*7c478bd9Sstevel@tonic-gate static void	globaln(int);
308*7c478bd9Sstevel@tonic-gate static char	*getkey(const char *);
309*7c478bd9Sstevel@tonic-gate static int	execute(int, LINE);
310*7c478bd9Sstevel@tonic-gate static void	error1(int);
311*7c478bd9Sstevel@tonic-gate static int	getcopy(void);
312*7c478bd9Sstevel@tonic-gate static void	move(int);
313*7c478bd9Sstevel@tonic-gate static void	dosub(void);
314*7c478bd9Sstevel@tonic-gate static int	getsub(void);
315*7c478bd9Sstevel@tonic-gate static int	compsub(void);
316*7c478bd9Sstevel@tonic-gate static void	substitute(int);
317*7c478bd9Sstevel@tonic-gate static void	join(void);
318*7c478bd9Sstevel@tonic-gate static void	global(int);
319*7c478bd9Sstevel@tonic-gate static void	init(void);
320*7c478bd9Sstevel@tonic-gate static void	rdelete(LINE, LINE);
321*7c478bd9Sstevel@tonic-gate static void	append(int (*)(void), LINE);
322*7c478bd9Sstevel@tonic-gate static int	getfile(void);
323*7c478bd9Sstevel@tonic-gate static void	putfile(void);
324*7c478bd9Sstevel@tonic-gate static void	onpipe(int);
325*7c478bd9Sstevel@tonic-gate static void	onhup(int);
326*7c478bd9Sstevel@tonic-gate static void	onintr(int);
327*7c478bd9Sstevel@tonic-gate static void	setdot(void);
328*7c478bd9Sstevel@tonic-gate static void	setall(void);
329*7c478bd9Sstevel@tonic-gate static void	setnoaddr(void);
330*7c478bd9Sstevel@tonic-gate static void	nonzero(void);
331*7c478bd9Sstevel@tonic-gate static void	setzeroasone(void);
332*7c478bd9Sstevel@tonic-gate static long	putline(void);
333*7c478bd9Sstevel@tonic-gate static LINE	address(void);
334*7c478bd9Sstevel@tonic-gate static char	*getline(long);
335*7c478bd9Sstevel@tonic-gate static char	*getblock(long, long);
336*7c478bd9Sstevel@tonic-gate static char	*place(char *, char *, char *);
337*7c478bd9Sstevel@tonic-gate static void	comple(wchar_t);
338*7c478bd9Sstevel@tonic-gate static void	putchr(unsigned char);
339*7c478bd9Sstevel@tonic-gate static void	putwchr(wchar_t);
340*7c478bd9Sstevel@tonic-gate static int	getchr(void);
341*7c478bd9Sstevel@tonic-gate static void	unixcom(void);
342*7c478bd9Sstevel@tonic-gate static void	blkio(int, char *, ssize_t (*)());
343*7c478bd9Sstevel@tonic-gate static void	reverse(LINE, LINE);
344*7c478bd9Sstevel@tonic-gate static void	putd();
345*7c478bd9Sstevel@tonic-gate static wchar_t	get_wchr(void);
346*7c478bd9Sstevel@tonic-gate 
347*7c478bd9Sstevel@tonic-gate static struct stat	Fl, Tf;
348*7c478bd9Sstevel@tonic-gate #ifndef RESEARCH
349*7c478bd9Sstevel@tonic-gate static struct statvfs	U;
350*7c478bd9Sstevel@tonic-gate static int	Short = 0;
351*7c478bd9Sstevel@tonic-gate static mode_t	oldmask; /* No umask while writing */
352*7c478bd9Sstevel@tonic-gate #endif
353*7c478bd9Sstevel@tonic-gate static jmp_buf	savej;
354*7c478bd9Sstevel@tonic-gate 
355*7c478bd9Sstevel@tonic-gate #ifdef	NULLS
356*7c478bd9Sstevel@tonic-gate int	nulls;	/* Null count */
357*7c478bd9Sstevel@tonic-gate #endif
358*7c478bd9Sstevel@tonic-gate static long	ccount;
359*7c478bd9Sstevel@tonic-gate 
360*7c478bd9Sstevel@tonic-gate static int	errcnt = 0;
361*7c478bd9Sstevel@tonic-gate 
362*7c478bd9Sstevel@tonic-gate 
363*7c478bd9Sstevel@tonic-gate static void
364*7c478bd9Sstevel@tonic-gate onpipe(int sig)
365*7c478bd9Sstevel@tonic-gate {
366*7c478bd9Sstevel@tonic-gate 	(int)error(0);
367*7c478bd9Sstevel@tonic-gate }
368*7c478bd9Sstevel@tonic-gate 
369*7c478bd9Sstevel@tonic-gate int
370*7c478bd9Sstevel@tonic-gate main(int argc, char **argv)
371*7c478bd9Sstevel@tonic-gate {
372*7c478bd9Sstevel@tonic-gate 	char *p1, *p2;
373*7c478bd9Sstevel@tonic-gate 	int c;
374*7c478bd9Sstevel@tonic-gate 
375*7c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
376*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
377*7c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"	/* Use this only if it weren't */
378*7c478bd9Sstevel@tonic-gate #endif
379*7c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
380*7c478bd9Sstevel@tonic-gate 
381*7c478bd9Sstevel@tonic-gate 	oldquit = signal(SIGQUIT, SIG_IGN);
382*7c478bd9Sstevel@tonic-gate 	oldhup = signal(SIGHUP, SIG_IGN);
383*7c478bd9Sstevel@tonic-gate 	oldintr = signal(SIGINT, SIG_IGN);
384*7c478bd9Sstevel@tonic-gate 	oldpipe = signal(SIGPIPE, onpipe);
385*7c478bd9Sstevel@tonic-gate 	if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
386*7c478bd9Sstevel@tonic-gate 		signal(SIGTERM, quit);
387*7c478bd9Sstevel@tonic-gate 	p1 = *argv;
388*7c478bd9Sstevel@tonic-gate 	while (*p1++);
389*7c478bd9Sstevel@tonic-gate 	while (--p1 >= *argv)
390*7c478bd9Sstevel@tonic-gate 		if (*p1 == '/')
391*7c478bd9Sstevel@tonic-gate 			break;
392*7c478bd9Sstevel@tonic-gate 	*argv = p1 + 1;
393*7c478bd9Sstevel@tonic-gate 	/* if SHELL set in environment and is /usr/lib/rsh, set rflg */
394*7c478bd9Sstevel@tonic-gate 	if ((val = getenv(name)) != NULL)
395*7c478bd9Sstevel@tonic-gate 		if (strcmp(val, rshell) == 0)
396*7c478bd9Sstevel@tonic-gate 			rflg++;
397*7c478bd9Sstevel@tonic-gate 	if (**argv == 'r')
398*7c478bd9Sstevel@tonic-gate 		rflg++;
399*7c478bd9Sstevel@tonic-gate 	home = getenv("HOME");
400*7c478bd9Sstevel@tonic-gate 	while (1) {
401*7c478bd9Sstevel@tonic-gate 		while ((c = getopt(argc, argv, "sp:qxC")) != EOF) {
402*7c478bd9Sstevel@tonic-gate 			switch (c) {
403*7c478bd9Sstevel@tonic-gate 
404*7c478bd9Sstevel@tonic-gate 			case 's':
405*7c478bd9Sstevel@tonic-gate 				vflag = 0;
406*7c478bd9Sstevel@tonic-gate 				break;
407*7c478bd9Sstevel@tonic-gate 
408*7c478bd9Sstevel@tonic-gate 			case 'p':
409*7c478bd9Sstevel@tonic-gate 				strncpy(prompt, optarg, sizeof (prompt)-1);
410*7c478bd9Sstevel@tonic-gate 				shflg = 1;
411*7c478bd9Sstevel@tonic-gate 				break;
412*7c478bd9Sstevel@tonic-gate 
413*7c478bd9Sstevel@tonic-gate 			case 'q':
414*7c478bd9Sstevel@tonic-gate 				signal(SIGQUIT, SIG_DFL);
415*7c478bd9Sstevel@tonic-gate 				vflag = 1;
416*7c478bd9Sstevel@tonic-gate 				break;
417*7c478bd9Sstevel@tonic-gate 
418*7c478bd9Sstevel@tonic-gate 			case 'x':
419*7c478bd9Sstevel@tonic-gate 				crflag = -1;
420*7c478bd9Sstevel@tonic-gate 				xflag = 1;
421*7c478bd9Sstevel@tonic-gate 				break;
422*7c478bd9Sstevel@tonic-gate 
423*7c478bd9Sstevel@tonic-gate 			case 'C':
424*7c478bd9Sstevel@tonic-gate 				crflag = 1;
425*7c478bd9Sstevel@tonic-gate 				xflag = 1;
426*7c478bd9Sstevel@tonic-gate 				break;
427*7c478bd9Sstevel@tonic-gate 
428*7c478bd9Sstevel@tonic-gate 			case '?':
429*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(
430*7c478bd9Sstevel@tonic-gate 		"Usage:   ed [- | -s] [-p string] [-x] [-C] [file]\n"
431*7c478bd9Sstevel@tonic-gate 		"	  red [- | -s] [-p string] [-x] [-C] [file]\n"));
432*7c478bd9Sstevel@tonic-gate 				exit(2);
433*7c478bd9Sstevel@tonic-gate 			}
434*7c478bd9Sstevel@tonic-gate 		}
435*7c478bd9Sstevel@tonic-gate 		if (argv[optind] && strcmp(argv[optind], "-") == 0 &&
436*7c478bd9Sstevel@tonic-gate 			strcmp(argv[optind-1], "--") != 0) {
437*7c478bd9Sstevel@tonic-gate 			vflag = 0;
438*7c478bd9Sstevel@tonic-gate 			optind++;
439*7c478bd9Sstevel@tonic-gate 			continue;
440*7c478bd9Sstevel@tonic-gate 		}
441*7c478bd9Sstevel@tonic-gate 		break;
442*7c478bd9Sstevel@tonic-gate 	}
443*7c478bd9Sstevel@tonic-gate 	argc = argc - optind;
444*7c478bd9Sstevel@tonic-gate 	argv = &argv[optind];
445*7c478bd9Sstevel@tonic-gate 
446*7c478bd9Sstevel@tonic-gate 	if (xflag) {
447*7c478bd9Sstevel@tonic-gate 		if (permflag)
448*7c478bd9Sstevel@tonic-gate 			crypt_close(perm);
449*7c478bd9Sstevel@tonic-gate 		permflag = 1;
450*7c478bd9Sstevel@tonic-gate 		if ((kflag = run_setkey(&perm[0], getkey(msgtab[66])))
451*7c478bd9Sstevel@tonic-gate 			== -1) {
452*7c478bd9Sstevel@tonic-gate 			puts(gettext(msgtab[64]));
453*7c478bd9Sstevel@tonic-gate 			xflag = 0;
454*7c478bd9Sstevel@tonic-gate 			kflag = 0;
455*7c478bd9Sstevel@tonic-gate 		}
456*7c478bd9Sstevel@tonic-gate 		if (kflag == 0)
457*7c478bd9Sstevel@tonic-gate 			crflag = 0;
458*7c478bd9Sstevel@tonic-gate 	}
459*7c478bd9Sstevel@tonic-gate 
460*7c478bd9Sstevel@tonic-gate 	if (argc > 0) {
461*7c478bd9Sstevel@tonic-gate 		p1 = *argv;
462*7c478bd9Sstevel@tonic-gate 		if (strlen(p1) >= (size_t)FNSIZE) {
463*7c478bd9Sstevel@tonic-gate 			puts(gettext("file name too long"));
464*7c478bd9Sstevel@tonic-gate 			if (kflag)
465*7c478bd9Sstevel@tonic-gate 				crypt_close(perm);
466*7c478bd9Sstevel@tonic-gate 			exit(2);
467*7c478bd9Sstevel@tonic-gate 		}
468*7c478bd9Sstevel@tonic-gate 		p2 = savedfile;
469*7c478bd9Sstevel@tonic-gate 		while (*p2++ = *p1++);
470*7c478bd9Sstevel@tonic-gate 		globp = "e";
471*7c478bd9Sstevel@tonic-gate 		fflg++;
472*7c478bd9Sstevel@tonic-gate 	} else 	/* editing with no file so set savtime to 0 */
473*7c478bd9Sstevel@tonic-gate 		savtime = 0;
474*7c478bd9Sstevel@tonic-gate 	eflg++;
475*7c478bd9Sstevel@tonic-gate 	if ((tfname = tempnam("", "ea")) == NULL) {
476*7c478bd9Sstevel@tonic-gate 		puts(gettext(msgtab[69]));
477*7c478bd9Sstevel@tonic-gate 		exit(2);
478*7c478bd9Sstevel@tonic-gate 	}
479*7c478bd9Sstevel@tonic-gate 
480*7c478bd9Sstevel@tonic-gate 	fendcore = (LINE)sbrk(0);
481*7c478bd9Sstevel@tonic-gate 	init();
482*7c478bd9Sstevel@tonic-gate 	if (oldintr != SIG_IGN)
483*7c478bd9Sstevel@tonic-gate 		signal(SIGINT, onintr);
484*7c478bd9Sstevel@tonic-gate 	if (oldhup != SIG_IGN)
485*7c478bd9Sstevel@tonic-gate 		signal(SIGHUP, onhup);
486*7c478bd9Sstevel@tonic-gate 	setjmp(savej);
487*7c478bd9Sstevel@tonic-gate 	commands();
488*7c478bd9Sstevel@tonic-gate 	quit(sig);
489*7c478bd9Sstevel@tonic-gate 	return (0);
490*7c478bd9Sstevel@tonic-gate }
491*7c478bd9Sstevel@tonic-gate 
492*7c478bd9Sstevel@tonic-gate static void
493*7c478bd9Sstevel@tonic-gate commands(void)
494*7c478bd9Sstevel@tonic-gate {
495*7c478bd9Sstevel@tonic-gate 	LINE a1;
496*7c478bd9Sstevel@tonic-gate 	int c;
497*7c478bd9Sstevel@tonic-gate 	char *p1, *p2;
498*7c478bd9Sstevel@tonic-gate 	int fsave, m, n;
499*7c478bd9Sstevel@tonic-gate 
500*7c478bd9Sstevel@tonic-gate 	for (;;) {
501*7c478bd9Sstevel@tonic-gate 	nodelim = 0;
502*7c478bd9Sstevel@tonic-gate 	if (pflag) {
503*7c478bd9Sstevel@tonic-gate 		pflag = 0;
504*7c478bd9Sstevel@tonic-gate 		addr1 = addr2 = dot;
505*7c478bd9Sstevel@tonic-gate 		goto print;
506*7c478bd9Sstevel@tonic-gate 	}
507*7c478bd9Sstevel@tonic-gate 	if (shflg && globp == 0)
508*7c478bd9Sstevel@tonic-gate 		write(1, gettext(prompt), strlen(gettext(prompt)));
509*7c478bd9Sstevel@tonic-gate 	addr1 = 0;
510*7c478bd9Sstevel@tonic-gate 	addr2 = 0;
511*7c478bd9Sstevel@tonic-gate 	if ((c = getchr()) == ',') {
512*7c478bd9Sstevel@tonic-gate 		addr1 = zero + 1;
513*7c478bd9Sstevel@tonic-gate 		addr2 = dol;
514*7c478bd9Sstevel@tonic-gate #ifdef XPG6
515*7c478bd9Sstevel@tonic-gate 	/* XPG4 - it was an error if the second address was */
516*7c478bd9Sstevel@tonic-gate 	/* input and the first address was ommitted	*/
517*7c478bd9Sstevel@tonic-gate 	/* Parse second address	*/
518*7c478bd9Sstevel@tonic-gate 		if ((a1 = address()) != 0) {
519*7c478bd9Sstevel@tonic-gate 			addr2 = a1;
520*7c478bd9Sstevel@tonic-gate 		}
521*7c478bd9Sstevel@tonic-gate #endif
522*7c478bd9Sstevel@tonic-gate 		c = getchr();
523*7c478bd9Sstevel@tonic-gate 		goto swch;
524*7c478bd9Sstevel@tonic-gate 	} else if (c == ';') {
525*7c478bd9Sstevel@tonic-gate 		addr1 = dot;
526*7c478bd9Sstevel@tonic-gate 		addr2 = dol;
527*7c478bd9Sstevel@tonic-gate #ifdef XPG6
528*7c478bd9Sstevel@tonic-gate 	/* XPG4 - it was an error if the second address was */
529*7c478bd9Sstevel@tonic-gate 	/* input and the first address was ommitted	*/
530*7c478bd9Sstevel@tonic-gate 	/* Parse second address	*/
531*7c478bd9Sstevel@tonic-gate 		if ((a1 = address()) != 0) {
532*7c478bd9Sstevel@tonic-gate 			addr2 = a1;
533*7c478bd9Sstevel@tonic-gate 		}
534*7c478bd9Sstevel@tonic-gate #endif
535*7c478bd9Sstevel@tonic-gate 		c = getchr();
536*7c478bd9Sstevel@tonic-gate 		goto swch;
537*7c478bd9Sstevel@tonic-gate 	} else
538*7c478bd9Sstevel@tonic-gate 		peekc = c;
539*7c478bd9Sstevel@tonic-gate 	do {
540*7c478bd9Sstevel@tonic-gate 		addr1 = addr2;
541*7c478bd9Sstevel@tonic-gate 		if ((a1 = address()) == 0) {
542*7c478bd9Sstevel@tonic-gate 			c = getchr();
543*7c478bd9Sstevel@tonic-gate 			break;
544*7c478bd9Sstevel@tonic-gate 		}
545*7c478bd9Sstevel@tonic-gate 		addr2 = a1;
546*7c478bd9Sstevel@tonic-gate 		if ((c = getchr()) == ';') {
547*7c478bd9Sstevel@tonic-gate 			c = ',';
548*7c478bd9Sstevel@tonic-gate 			dot = a1;
549*7c478bd9Sstevel@tonic-gate 		}
550*7c478bd9Sstevel@tonic-gate 	} while (c == ',');
551*7c478bd9Sstevel@tonic-gate 	if (addr1 == 0)
552*7c478bd9Sstevel@tonic-gate 		addr1 = addr2;
553*7c478bd9Sstevel@tonic-gate swch:
554*7c478bd9Sstevel@tonic-gate 	switch (c) {
555*7c478bd9Sstevel@tonic-gate 
556*7c478bd9Sstevel@tonic-gate 	case 'a':
557*7c478bd9Sstevel@tonic-gate 		setdot();
558*7c478bd9Sstevel@tonic-gate 		newline();
559*7c478bd9Sstevel@tonic-gate 		if (!globflg) save();
560*7c478bd9Sstevel@tonic-gate 		append(gettty, addr2);
561*7c478bd9Sstevel@tonic-gate 		continue;
562*7c478bd9Sstevel@tonic-gate 
563*7c478bd9Sstevel@tonic-gate 	case 'c':
564*7c478bd9Sstevel@tonic-gate #ifdef XPG6
565*7c478bd9Sstevel@tonic-gate 		setzeroasone();
566*7c478bd9Sstevel@tonic-gate #endif
567*7c478bd9Sstevel@tonic-gate 		delete();
568*7c478bd9Sstevel@tonic-gate 		append(gettty, addr1-1);
569*7c478bd9Sstevel@tonic-gate 
570*7c478bd9Sstevel@tonic-gate 		/* XPG4 - If no new lines are inserted, then the current */
571*7c478bd9Sstevel@tonic-gate 		/* line becomes the line after the lines deleted. */
572*7c478bd9Sstevel@tonic-gate 
573*7c478bd9Sstevel@tonic-gate 		if (((linebuf[0] != '.') || (dot == (addr1-1))) &&
574*7c478bd9Sstevel@tonic-gate 			(addr2 <= dol))
575*7c478bd9Sstevel@tonic-gate 			dot = addr1;
576*7c478bd9Sstevel@tonic-gate 		continue;
577*7c478bd9Sstevel@tonic-gate 
578*7c478bd9Sstevel@tonic-gate 	case 'd':
579*7c478bd9Sstevel@tonic-gate 		delete();
580*7c478bd9Sstevel@tonic-gate 		continue;
581*7c478bd9Sstevel@tonic-gate 
582*7c478bd9Sstevel@tonic-gate 	case 'E':
583*7c478bd9Sstevel@tonic-gate 		fchange = 0;
584*7c478bd9Sstevel@tonic-gate 		c = 'e';
585*7c478bd9Sstevel@tonic-gate 	case 'e':
586*7c478bd9Sstevel@tonic-gate 		fflg++;
587*7c478bd9Sstevel@tonic-gate 		setnoaddr();
588*7c478bd9Sstevel@tonic-gate 		if (vflag && fchange) {
589*7c478bd9Sstevel@tonic-gate 			fchange = 0;
590*7c478bd9Sstevel@tonic-gate 			(void) error(1);
591*7c478bd9Sstevel@tonic-gate 		}
592*7c478bd9Sstevel@tonic-gate 		filename(c);
593*7c478bd9Sstevel@tonic-gate 		eflg++;
594*7c478bd9Sstevel@tonic-gate 		init();
595*7c478bd9Sstevel@tonic-gate 		addr2 = zero;
596*7c478bd9Sstevel@tonic-gate 		goto caseread;
597*7c478bd9Sstevel@tonic-gate 
598*7c478bd9Sstevel@tonic-gate 	case 'f':
599*7c478bd9Sstevel@tonic-gate 		setnoaddr();
600*7c478bd9Sstevel@tonic-gate 		filename(c);
601*7c478bd9Sstevel@tonic-gate 		if (!ncflg)  /* there is a filename */
602*7c478bd9Sstevel@tonic-gate 			getime();
603*7c478bd9Sstevel@tonic-gate 		else
604*7c478bd9Sstevel@tonic-gate 			ncflg--;
605*7c478bd9Sstevel@tonic-gate 		puts(savedfile);
606*7c478bd9Sstevel@tonic-gate 		continue;
607*7c478bd9Sstevel@tonic-gate 
608*7c478bd9Sstevel@tonic-gate 	case 'g':
609*7c478bd9Sstevel@tonic-gate 		global(1);
610*7c478bd9Sstevel@tonic-gate 		continue;
611*7c478bd9Sstevel@tonic-gate 	case 'G':
612*7c478bd9Sstevel@tonic-gate 		globaln(1);
613*7c478bd9Sstevel@tonic-gate 		continue;
614*7c478bd9Sstevel@tonic-gate 
615*7c478bd9Sstevel@tonic-gate 	case 'h':
616*7c478bd9Sstevel@tonic-gate 		newline();
617*7c478bd9Sstevel@tonic-gate 		setnoaddr();
618*7c478bd9Sstevel@tonic-gate 		PUTM();
619*7c478bd9Sstevel@tonic-gate 		continue;
620*7c478bd9Sstevel@tonic-gate 
621*7c478bd9Sstevel@tonic-gate 	case 'H':
622*7c478bd9Sstevel@tonic-gate 		newline();
623*7c478bd9Sstevel@tonic-gate 		setnoaddr();
624*7c478bd9Sstevel@tonic-gate 		if (!hflag) {
625*7c478bd9Sstevel@tonic-gate 			hflag = 1;
626*7c478bd9Sstevel@tonic-gate 			PUTM();
627*7c478bd9Sstevel@tonic-gate 		}
628*7c478bd9Sstevel@tonic-gate 		else
629*7c478bd9Sstevel@tonic-gate 			hflag = 0;
630*7c478bd9Sstevel@tonic-gate 		continue;
631*7c478bd9Sstevel@tonic-gate 
632*7c478bd9Sstevel@tonic-gate 	case 'i':
633*7c478bd9Sstevel@tonic-gate #ifdef XPG6
634*7c478bd9Sstevel@tonic-gate 		setzeroasone();
635*7c478bd9Sstevel@tonic-gate #endif
636*7c478bd9Sstevel@tonic-gate 		setdot();
637*7c478bd9Sstevel@tonic-gate 		nonzero();
638*7c478bd9Sstevel@tonic-gate 		newline();
639*7c478bd9Sstevel@tonic-gate 		if (!globflg) save();
640*7c478bd9Sstevel@tonic-gate 		append(gettty, addr2-1);
641*7c478bd9Sstevel@tonic-gate 		if (dot == addr2-1)
642*7c478bd9Sstevel@tonic-gate 			dot += 1;
643*7c478bd9Sstevel@tonic-gate 		continue;
644*7c478bd9Sstevel@tonic-gate 
645*7c478bd9Sstevel@tonic-gate 	case 'j':
646*7c478bd9Sstevel@tonic-gate 		if (addr2 == 0) {
647*7c478bd9Sstevel@tonic-gate 			addr1 = dot;
648*7c478bd9Sstevel@tonic-gate 			addr2 = dot+1;
649*7c478bd9Sstevel@tonic-gate 		}
650*7c478bd9Sstevel@tonic-gate 		setdot();
651*7c478bd9Sstevel@tonic-gate 		newline();
652*7c478bd9Sstevel@tonic-gate 		nonzero();
653*7c478bd9Sstevel@tonic-gate 		if (!globflg) save();
654*7c478bd9Sstevel@tonic-gate 		join();
655*7c478bd9Sstevel@tonic-gate 		continue;
656*7c478bd9Sstevel@tonic-gate 
657*7c478bd9Sstevel@tonic-gate 	case 'k':
658*7c478bd9Sstevel@tonic-gate 		if ((c = getchr()) < 'a' || c > 'z')
659*7c478bd9Sstevel@tonic-gate 			(void) error(2);
660*7c478bd9Sstevel@tonic-gate 		newline();
661*7c478bd9Sstevel@tonic-gate 		setdot();
662*7c478bd9Sstevel@tonic-gate 		nonzero();
663*7c478bd9Sstevel@tonic-gate 		names[c-'a'] = addr2->cur & ~01;
664*7c478bd9Sstevel@tonic-gate 		anymarks |= 01;
665*7c478bd9Sstevel@tonic-gate 		continue;
666*7c478bd9Sstevel@tonic-gate 
667*7c478bd9Sstevel@tonic-gate 	case 'm':
668*7c478bd9Sstevel@tonic-gate 		move(0);
669*7c478bd9Sstevel@tonic-gate 		continue;
670*7c478bd9Sstevel@tonic-gate 
671*7c478bd9Sstevel@tonic-gate 	case '\n':
672*7c478bd9Sstevel@tonic-gate 		if (addr2 == 0)
673*7c478bd9Sstevel@tonic-gate 			addr2 = dot+1;
674*7c478bd9Sstevel@tonic-gate 		addr1 = addr2;
675*7c478bd9Sstevel@tonic-gate 		goto print;
676*7c478bd9Sstevel@tonic-gate 
677*7c478bd9Sstevel@tonic-gate 	case 'n':
678*7c478bd9Sstevel@tonic-gate 		listn++;
679*7c478bd9Sstevel@tonic-gate 		newline();
680*7c478bd9Sstevel@tonic-gate 		goto print;
681*7c478bd9Sstevel@tonic-gate 
682*7c478bd9Sstevel@tonic-gate 	case 'l':
683*7c478bd9Sstevel@tonic-gate 		listf++;
684*7c478bd9Sstevel@tonic-gate 	case 'p':
685*7c478bd9Sstevel@tonic-gate 		newline();
686*7c478bd9Sstevel@tonic-gate 	print:
687*7c478bd9Sstevel@tonic-gate 		setdot();
688*7c478bd9Sstevel@tonic-gate 		nonzero();
689*7c478bd9Sstevel@tonic-gate 		a1 = addr1;
690*7c478bd9Sstevel@tonic-gate 		do {
691*7c478bd9Sstevel@tonic-gate 			if (listn) {
692*7c478bd9Sstevel@tonic-gate 				count = a1 - zero;
693*7c478bd9Sstevel@tonic-gate 				putd();
694*7c478bd9Sstevel@tonic-gate 				putchr('\t');
695*7c478bd9Sstevel@tonic-gate 			}
696*7c478bd9Sstevel@tonic-gate 			puts(getline((a1++)->cur));
697*7c478bd9Sstevel@tonic-gate 		}
698*7c478bd9Sstevel@tonic-gate 		while (a1 <= addr2);
699*7c478bd9Sstevel@tonic-gate 		dot = addr2;
700*7c478bd9Sstevel@tonic-gate 		pflag = 0;
701*7c478bd9Sstevel@tonic-gate 		listn = 0;
702*7c478bd9Sstevel@tonic-gate 		listf = 0;
703*7c478bd9Sstevel@tonic-gate 		continue;
704*7c478bd9Sstevel@tonic-gate 
705*7c478bd9Sstevel@tonic-gate 	case 'Q':
706*7c478bd9Sstevel@tonic-gate 		fchange = 0;
707*7c478bd9Sstevel@tonic-gate 	case 'q':
708*7c478bd9Sstevel@tonic-gate 		setnoaddr();
709*7c478bd9Sstevel@tonic-gate 		newline();
710*7c478bd9Sstevel@tonic-gate 		quit(sig);
711*7c478bd9Sstevel@tonic-gate 
712*7c478bd9Sstevel@tonic-gate 	case 'r':
713*7c478bd9Sstevel@tonic-gate 		filename(c);
714*7c478bd9Sstevel@tonic-gate 	caseread:
715*7c478bd9Sstevel@tonic-gate 		readflg = 1;
716*7c478bd9Sstevel@tonic-gate 		save28 = (dol != fendcore);
717*7c478bd9Sstevel@tonic-gate 		if (crflag == 2 || crflag == -2)
718*7c478bd9Sstevel@tonic-gate 			crflag = -1; /* restore crflag for next file */
719*7c478bd9Sstevel@tonic-gate 		errno = 0;
720*7c478bd9Sstevel@tonic-gate 		if ((io = eopen(file, O_RDONLY)) < 0) {
721*7c478bd9Sstevel@tonic-gate 			lastc = '\n';
722*7c478bd9Sstevel@tonic-gate 			/* if first entering editor and file does not exist */
723*7c478bd9Sstevel@tonic-gate 			/* set saved access time to 0 */
724*7c478bd9Sstevel@tonic-gate 			if (eflg) {
725*7c478bd9Sstevel@tonic-gate 				savtime = 0;
726*7c478bd9Sstevel@tonic-gate 				eflg  = 0;
727*7c478bd9Sstevel@tonic-gate 				if (c == 'e' && vflag == 0)
728*7c478bd9Sstevel@tonic-gate 					qflg = 1;
729*7c478bd9Sstevel@tonic-gate 			}
730*7c478bd9Sstevel@tonic-gate 			if (errno == ENOENT) {
731*7c478bd9Sstevel@tonic-gate 				(void) error(68);
732*7c478bd9Sstevel@tonic-gate 			} else {
733*7c478bd9Sstevel@tonic-gate 				(void) error(3);
734*7c478bd9Sstevel@tonic-gate 			}
735*7c478bd9Sstevel@tonic-gate 		}
736*7c478bd9Sstevel@tonic-gate 		/* get last mod time of file */
737*7c478bd9Sstevel@tonic-gate 		/* eflg - entered editor with ed or e  */
738*7c478bd9Sstevel@tonic-gate 		if (eflg) {
739*7c478bd9Sstevel@tonic-gate 			eflg = 0;
740*7c478bd9Sstevel@tonic-gate 			getime();
741*7c478bd9Sstevel@tonic-gate 		}
742*7c478bd9Sstevel@tonic-gate 		setall();
743*7c478bd9Sstevel@tonic-gate 		ninbuf = 0;
744*7c478bd9Sstevel@tonic-gate 		n = zero != dol;
745*7c478bd9Sstevel@tonic-gate #ifdef NULLS
746*7c478bd9Sstevel@tonic-gate 		nulls = 0;
747*7c478bd9Sstevel@tonic-gate #endif
748*7c478bd9Sstevel@tonic-gate 		if (!globflg && (c == 'r')) save();
749*7c478bd9Sstevel@tonic-gate 		append(getfile, addr2);
750*7c478bd9Sstevel@tonic-gate 		exfile();
751*7c478bd9Sstevel@tonic-gate 		readflg = 0;
752*7c478bd9Sstevel@tonic-gate 		fchange = n;
753*7c478bd9Sstevel@tonic-gate 		continue;
754*7c478bd9Sstevel@tonic-gate 
755*7c478bd9Sstevel@tonic-gate 	case 's':
756*7c478bd9Sstevel@tonic-gate 		setdot();
757*7c478bd9Sstevel@tonic-gate 		nonzero();
758*7c478bd9Sstevel@tonic-gate 		if (!globflg) save();
759*7c478bd9Sstevel@tonic-gate 		substitute(globp != 0);
760*7c478bd9Sstevel@tonic-gate 		continue;
761*7c478bd9Sstevel@tonic-gate 
762*7c478bd9Sstevel@tonic-gate 	case 't':
763*7c478bd9Sstevel@tonic-gate 		move(1);
764*7c478bd9Sstevel@tonic-gate 		continue;
765*7c478bd9Sstevel@tonic-gate 
766*7c478bd9Sstevel@tonic-gate 	case 'u':
767*7c478bd9Sstevel@tonic-gate 		setdot();
768*7c478bd9Sstevel@tonic-gate 		newline();
769*7c478bd9Sstevel@tonic-gate 		if (!initflg)
770*7c478bd9Sstevel@tonic-gate 			undo();
771*7c478bd9Sstevel@tonic-gate 		else
772*7c478bd9Sstevel@tonic-gate 			(void) error(5);
773*7c478bd9Sstevel@tonic-gate 		fchange = 1;
774*7c478bd9Sstevel@tonic-gate 		continue;
775*7c478bd9Sstevel@tonic-gate 
776*7c478bd9Sstevel@tonic-gate 	case 'v':
777*7c478bd9Sstevel@tonic-gate 		global(0);
778*7c478bd9Sstevel@tonic-gate 		continue;
779*7c478bd9Sstevel@tonic-gate 	case 'V':
780*7c478bd9Sstevel@tonic-gate 		globaln(0);
781*7c478bd9Sstevel@tonic-gate 		continue;
782*7c478bd9Sstevel@tonic-gate 
783*7c478bd9Sstevel@tonic-gate 	case 'W':
784*7c478bd9Sstevel@tonic-gate 	case 'w':
785*7c478bd9Sstevel@tonic-gate 		if (flag28) {
786*7c478bd9Sstevel@tonic-gate 			flag28 = 0;
787*7c478bd9Sstevel@tonic-gate 			fchange = 0;
788*7c478bd9Sstevel@tonic-gate 			(void) error(61);
789*7c478bd9Sstevel@tonic-gate 		}
790*7c478bd9Sstevel@tonic-gate 		setall();
791*7c478bd9Sstevel@tonic-gate 
792*7c478bd9Sstevel@tonic-gate 		/* on NULL-RE condition do not generate error */
793*7c478bd9Sstevel@tonic-gate 
794*7c478bd9Sstevel@tonic-gate 		if ((linebuf[0] != '.') && (zero != dol) &&
795*7c478bd9Sstevel@tonic-gate 			(addr1 <= zero || addr2 > dol))
796*7c478bd9Sstevel@tonic-gate 			(void) error(15);
797*7c478bd9Sstevel@tonic-gate 		filename(c);
798*7c478bd9Sstevel@tonic-gate 		if (Xqt) {
799*7c478bd9Sstevel@tonic-gate 			io = eopen(file, O_WRONLY);
800*7c478bd9Sstevel@tonic-gate 			n = 1;	/* set n so newtime will not execute */
801*7c478bd9Sstevel@tonic-gate 		} else {
802*7c478bd9Sstevel@tonic-gate 			struct stat lFl;
803*7c478bd9Sstevel@tonic-gate 			fstat(tfile, &Tf);
804*7c478bd9Sstevel@tonic-gate 			if (stat(file, &Fl) < 0) {
805*7c478bd9Sstevel@tonic-gate 				if ((io = creat(file, S_IRUSR|S_IWUSR|S_IRGRP
806*7c478bd9Sstevel@tonic-gate 					|S_IWGRP|S_IROTH|S_IWOTH)) < 0)
807*7c478bd9Sstevel@tonic-gate 					(void) error(7);
808*7c478bd9Sstevel@tonic-gate 				fstat(io, &Fl);
809*7c478bd9Sstevel@tonic-gate 				Fl.st_mtime = 0;
810*7c478bd9Sstevel@tonic-gate 				lFl = Fl;
811*7c478bd9Sstevel@tonic-gate 				close(io);
812*7c478bd9Sstevel@tonic-gate 			} else {
813*7c478bd9Sstevel@tonic-gate #ifndef	RESEARCH
814*7c478bd9Sstevel@tonic-gate 				oldmask = umask(0);
815*7c478bd9Sstevel@tonic-gate 				/*
816*7c478bd9Sstevel@tonic-gate 				 * Must determine if file is
817*7c478bd9Sstevel@tonic-gate 				 * a symbolic link
818*7c478bd9Sstevel@tonic-gate 				 */
819*7c478bd9Sstevel@tonic-gate 				lstat(file, &lFl);
820*7c478bd9Sstevel@tonic-gate #endif
821*7c478bd9Sstevel@tonic-gate 			}
822*7c478bd9Sstevel@tonic-gate #ifndef RESEARCH
823*7c478bd9Sstevel@tonic-gate 			/*
824*7c478bd9Sstevel@tonic-gate 			 * Determine if there are enough free blocks on system
825*7c478bd9Sstevel@tonic-gate 			 */
826*7c478bd9Sstevel@tonic-gate 			if (!Short && statvfs(file, &U) == 0 &&
827*7c478bd9Sstevel@tonic-gate 			    U.f_bfree < ((Tf.st_size/U.f_frsize) + 100)) {
828*7c478bd9Sstevel@tonic-gate 				Short = 1;
829*7c478bd9Sstevel@tonic-gate 				(void) error(8);
830*7c478bd9Sstevel@tonic-gate 			}
831*7c478bd9Sstevel@tonic-gate 			Short = 0;
832*7c478bd9Sstevel@tonic-gate #endif
833*7c478bd9Sstevel@tonic-gate 			p1 = savedfile;		/* The current filename */
834*7c478bd9Sstevel@tonic-gate 			p2 = file;
835*7c478bd9Sstevel@tonic-gate 			m = strcmp(p1, p2);
836*7c478bd9Sstevel@tonic-gate 			if (c == 'w' && Fl.st_nlink == 1 && ISREG(lFl)) {
837*7c478bd9Sstevel@tonic-gate 				if (close(open(file, O_WRONLY)) < 0)
838*7c478bd9Sstevel@tonic-gate 					(void) error(9);
839*7c478bd9Sstevel@tonic-gate 				if (!(n = m))
840*7c478bd9Sstevel@tonic-gate 					chktime();
841*7c478bd9Sstevel@tonic-gate 				mkfunny();
842*7c478bd9Sstevel@tonic-gate 				/*
843*7c478bd9Sstevel@tonic-gate 				 * If funlink equals one it means that
844*7c478bd9Sstevel@tonic-gate 				 * funny points to a valid file which must
845*7c478bd9Sstevel@tonic-gate 				 * be unlinked when interrupted.
846*7c478bd9Sstevel@tonic-gate 				 */
847*7c478bd9Sstevel@tonic-gate 
848*7c478bd9Sstevel@tonic-gate 				funlink = 1;
849*7c478bd9Sstevel@tonic-gate 				if ((io = creat(funny, FMODE(Fl))) >= 0) {
850*7c478bd9Sstevel@tonic-gate 					chown(funny, Fl.st_uid, Fl.st_gid);
851*7c478bd9Sstevel@tonic-gate 					chmod(funny, FMODE(Fl));
852*7c478bd9Sstevel@tonic-gate 					putfile();
853*7c478bd9Sstevel@tonic-gate 					exfile();
854*7c478bd9Sstevel@tonic-gate 
855*7c478bd9Sstevel@tonic-gate 					if (rename(funny, file))
856*7c478bd9Sstevel@tonic-gate 						(void) error(10);
857*7c478bd9Sstevel@tonic-gate 					funlink = 0;
858*7c478bd9Sstevel@tonic-gate 					/* if filenames are the same */
859*7c478bd9Sstevel@tonic-gate 					if (!n)
860*7c478bd9Sstevel@tonic-gate 						newtime();
861*7c478bd9Sstevel@tonic-gate 					/* check if entire buffer was written */
862*7c478bd9Sstevel@tonic-gate 					fsave = fchange;
863*7c478bd9Sstevel@tonic-gate 		fchange = (((addr1 == zero) || (addr1 == (zero + 1))) &&
864*7c478bd9Sstevel@tonic-gate 			(addr2 == dol)) ? 0 : 1;
865*7c478bd9Sstevel@tonic-gate 			if (fchange == 1 && m != 0) fchange = fsave;
866*7c478bd9Sstevel@tonic-gate 					continue;
867*7c478bd9Sstevel@tonic-gate 				}
868*7c478bd9Sstevel@tonic-gate 			} else
869*7c478bd9Sstevel@tonic-gate 				n = 1;	/* set n so newtime will not execute */
870*7c478bd9Sstevel@tonic-gate 			if ((io = open(file,
871*7c478bd9Sstevel@tonic-gate 				(c == 'w') ? O_WRONLY|O_CREAT|O_TRUNC
872*7c478bd9Sstevel@tonic-gate 				: O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR
873*7c478bd9Sstevel@tonic-gate 				|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0)
874*7c478bd9Sstevel@tonic-gate 				(void) error(7);
875*7c478bd9Sstevel@tonic-gate 		}
876*7c478bd9Sstevel@tonic-gate 		putfile();
877*7c478bd9Sstevel@tonic-gate 		exfile();
878*7c478bd9Sstevel@tonic-gate 		if (!n) newtime();
879*7c478bd9Sstevel@tonic-gate 		fsave = fchange;
880*7c478bd9Sstevel@tonic-gate 		fchange = (((addr1 == zero) || (addr1 == (zero + 1))) &&
881*7c478bd9Sstevel@tonic-gate 			(addr2 == dol)) ? 0 : 1;
882*7c478bd9Sstevel@tonic-gate 	/* Leave fchange alone if partial write was to another file */
883*7c478bd9Sstevel@tonic-gate 		if (fchange == 1 && m != 0) fchange = fsave;
884*7c478bd9Sstevel@tonic-gate 		continue;
885*7c478bd9Sstevel@tonic-gate 
886*7c478bd9Sstevel@tonic-gate 	case 'C':
887*7c478bd9Sstevel@tonic-gate 		crflag = 1;
888*7c478bd9Sstevel@tonic-gate 			/*
889*7c478bd9Sstevel@tonic-gate 			 * C is same as X, but always assume input files are
890*7c478bd9Sstevel@tonic-gate 			 * ciphertext
891*7c478bd9Sstevel@tonic-gate 			 */
892*7c478bd9Sstevel@tonic-gate 		goto encrypt;
893*7c478bd9Sstevel@tonic-gate 
894*7c478bd9Sstevel@tonic-gate 	case 'X':
895*7c478bd9Sstevel@tonic-gate 		crflag = -1;
896*7c478bd9Sstevel@tonic-gate encrypt:
897*7c478bd9Sstevel@tonic-gate 		setnoaddr();
898*7c478bd9Sstevel@tonic-gate 		newline();
899*7c478bd9Sstevel@tonic-gate 		xflag = 1;
900*7c478bd9Sstevel@tonic-gate 		if (permflag)
901*7c478bd9Sstevel@tonic-gate 			(void) crypt_close(perm);
902*7c478bd9Sstevel@tonic-gate 		permflag = 1;
903*7c478bd9Sstevel@tonic-gate 		if ((kflag = run_setkey(&perm[0], getkey(msgtab[66])))
904*7c478bd9Sstevel@tonic-gate 			== -1) {
905*7c478bd9Sstevel@tonic-gate 			xflag = 0;
906*7c478bd9Sstevel@tonic-gate 			kflag = 0;
907*7c478bd9Sstevel@tonic-gate 			crflag = 0;
908*7c478bd9Sstevel@tonic-gate 			(void) error(64);
909*7c478bd9Sstevel@tonic-gate 		}
910*7c478bd9Sstevel@tonic-gate 		if (kflag == 0)
911*7c478bd9Sstevel@tonic-gate 			crflag = 0;
912*7c478bd9Sstevel@tonic-gate 		continue;
913*7c478bd9Sstevel@tonic-gate 
914*7c478bd9Sstevel@tonic-gate 	case '=':
915*7c478bd9Sstevel@tonic-gate 		setall();
916*7c478bd9Sstevel@tonic-gate 		newline();
917*7c478bd9Sstevel@tonic-gate 		count = (addr2-zero)&077777;
918*7c478bd9Sstevel@tonic-gate 		putd();
919*7c478bd9Sstevel@tonic-gate 		putchr('\n');
920*7c478bd9Sstevel@tonic-gate 		continue;
921*7c478bd9Sstevel@tonic-gate 
922*7c478bd9Sstevel@tonic-gate 	case '!':
923*7c478bd9Sstevel@tonic-gate 		unixcom();
924*7c478bd9Sstevel@tonic-gate 		continue;
925*7c478bd9Sstevel@tonic-gate 
926*7c478bd9Sstevel@tonic-gate 	case EOF:
927*7c478bd9Sstevel@tonic-gate 		return;
928*7c478bd9Sstevel@tonic-gate 
929*7c478bd9Sstevel@tonic-gate 	case 'P':
930*7c478bd9Sstevel@tonic-gate 		setnoaddr();
931*7c478bd9Sstevel@tonic-gate 		newline();
932*7c478bd9Sstevel@tonic-gate 		if (shflg)
933*7c478bd9Sstevel@tonic-gate 			shflg = 0;
934*7c478bd9Sstevel@tonic-gate 		else
935*7c478bd9Sstevel@tonic-gate 			shflg++;
936*7c478bd9Sstevel@tonic-gate 		continue;
937*7c478bd9Sstevel@tonic-gate 	}
938*7c478bd9Sstevel@tonic-gate 	if (c == 'x')
939*7c478bd9Sstevel@tonic-gate 		(void) error(60);
940*7c478bd9Sstevel@tonic-gate 	else
941*7c478bd9Sstevel@tonic-gate 		(void) error(12);
942*7c478bd9Sstevel@tonic-gate 	}
943*7c478bd9Sstevel@tonic-gate }
944*7c478bd9Sstevel@tonic-gate 
945*7c478bd9Sstevel@tonic-gate LINE
946*7c478bd9Sstevel@tonic-gate address(void)
947*7c478bd9Sstevel@tonic-gate {
948*7c478bd9Sstevel@tonic-gate 	int minus, c;
949*7c478bd9Sstevel@tonic-gate 	LINE a1;
950*7c478bd9Sstevel@tonic-gate 	int n, relerr, retval;
951*7c478bd9Sstevel@tonic-gate 
952*7c478bd9Sstevel@tonic-gate 	minus = 0;
953*7c478bd9Sstevel@tonic-gate 	a1 = 0;
954*7c478bd9Sstevel@tonic-gate 	for (;;) {
955*7c478bd9Sstevel@tonic-gate 		c = getchr();
956*7c478bd9Sstevel@tonic-gate 		if ('0' <= c && c <= '9') {
957*7c478bd9Sstevel@tonic-gate 			n = 0;
958*7c478bd9Sstevel@tonic-gate 			do {
959*7c478bd9Sstevel@tonic-gate 				n *= 10;
960*7c478bd9Sstevel@tonic-gate 				n += c - '0';
961*7c478bd9Sstevel@tonic-gate 			} while ((c = getchr()) >= '0' && c <= '9');
962*7c478bd9Sstevel@tonic-gate 			peekc = c;
963*7c478bd9Sstevel@tonic-gate 			if (a1 == 0)
964*7c478bd9Sstevel@tonic-gate 				a1 = zero;
965*7c478bd9Sstevel@tonic-gate 			if (minus < 0)
966*7c478bd9Sstevel@tonic-gate 				n = -n;
967*7c478bd9Sstevel@tonic-gate 			a1 += n;
968*7c478bd9Sstevel@tonic-gate 			minus = 0;
969*7c478bd9Sstevel@tonic-gate 			continue;
970*7c478bd9Sstevel@tonic-gate 		}
971*7c478bd9Sstevel@tonic-gate 		relerr = 0;
972*7c478bd9Sstevel@tonic-gate 		if (a1 || minus)
973*7c478bd9Sstevel@tonic-gate 			relerr++;
974*7c478bd9Sstevel@tonic-gate 		switch (c) {
975*7c478bd9Sstevel@tonic-gate 		case ' ':
976*7c478bd9Sstevel@tonic-gate 		case '\t':
977*7c478bd9Sstevel@tonic-gate 			continue;
978*7c478bd9Sstevel@tonic-gate 
979*7c478bd9Sstevel@tonic-gate 		case '+':
980*7c478bd9Sstevel@tonic-gate 			minus++;
981*7c478bd9Sstevel@tonic-gate 			if (a1 == 0)
982*7c478bd9Sstevel@tonic-gate 				a1 = dot;
983*7c478bd9Sstevel@tonic-gate 			continue;
984*7c478bd9Sstevel@tonic-gate 
985*7c478bd9Sstevel@tonic-gate 		case '-':
986*7c478bd9Sstevel@tonic-gate 		case '^':
987*7c478bd9Sstevel@tonic-gate 			minus--;
988*7c478bd9Sstevel@tonic-gate 			if (a1 == 0)
989*7c478bd9Sstevel@tonic-gate 				a1 = dot;
990*7c478bd9Sstevel@tonic-gate 			continue;
991*7c478bd9Sstevel@tonic-gate 
992*7c478bd9Sstevel@tonic-gate 		case '?':
993*7c478bd9Sstevel@tonic-gate 		case '/':
994*7c478bd9Sstevel@tonic-gate 			comple(c);
995*7c478bd9Sstevel@tonic-gate 			a1 = dot;
996*7c478bd9Sstevel@tonic-gate 			for (;;) {
997*7c478bd9Sstevel@tonic-gate 				if (c == '/') {
998*7c478bd9Sstevel@tonic-gate 					a1++;
999*7c478bd9Sstevel@tonic-gate 					if (a1 > dol)
1000*7c478bd9Sstevel@tonic-gate 						a1 = zero;
1001*7c478bd9Sstevel@tonic-gate 				} else {
1002*7c478bd9Sstevel@tonic-gate 					a1--;
1003*7c478bd9Sstevel@tonic-gate 					if (a1 < zero)
1004*7c478bd9Sstevel@tonic-gate 						a1 = dol;
1005*7c478bd9Sstevel@tonic-gate 				}
1006*7c478bd9Sstevel@tonic-gate 
1007*7c478bd9Sstevel@tonic-gate 				if (execute(0, a1))
1008*7c478bd9Sstevel@tonic-gate 					break;
1009*7c478bd9Sstevel@tonic-gate 				if (a1 == dot)
1010*7c478bd9Sstevel@tonic-gate 					(void) error(13);
1011*7c478bd9Sstevel@tonic-gate 			}
1012*7c478bd9Sstevel@tonic-gate 			break;
1013*7c478bd9Sstevel@tonic-gate 
1014*7c478bd9Sstevel@tonic-gate 		case '$':
1015*7c478bd9Sstevel@tonic-gate 			a1 = dol;
1016*7c478bd9Sstevel@tonic-gate 			break;
1017*7c478bd9Sstevel@tonic-gate 
1018*7c478bd9Sstevel@tonic-gate 		case '.':
1019*7c478bd9Sstevel@tonic-gate 			a1 = dot;
1020*7c478bd9Sstevel@tonic-gate 			break;
1021*7c478bd9Sstevel@tonic-gate 
1022*7c478bd9Sstevel@tonic-gate 		case '\'':
1023*7c478bd9Sstevel@tonic-gate 			if ((c = getchr()) < 'a' || c > 'z')
1024*7c478bd9Sstevel@tonic-gate 				(void) error(2);
1025*7c478bd9Sstevel@tonic-gate 			for (a1 = zero; a1 <= dol; a1++)
1026*7c478bd9Sstevel@tonic-gate 				if (names[c-'a'] == (a1->cur & ~01))
1027*7c478bd9Sstevel@tonic-gate 					break;
1028*7c478bd9Sstevel@tonic-gate 			break;
1029*7c478bd9Sstevel@tonic-gate 
1030*7c478bd9Sstevel@tonic-gate 		default:
1031*7c478bd9Sstevel@tonic-gate 			peekc = c;
1032*7c478bd9Sstevel@tonic-gate 			if (a1 == 0)
1033*7c478bd9Sstevel@tonic-gate 				return (0);
1034*7c478bd9Sstevel@tonic-gate 			a1 += minus;
1035*7c478bd9Sstevel@tonic-gate 
1036*7c478bd9Sstevel@tonic-gate 			/* on NULL-RE condition do not generate error */
1037*7c478bd9Sstevel@tonic-gate 
1038*7c478bd9Sstevel@tonic-gate 			if ((linebuf[0] != '.') && (a1 < zero || a1 > dol))
1039*7c478bd9Sstevel@tonic-gate 				(void) error(15);
1040*7c478bd9Sstevel@tonic-gate 			return (a1);
1041*7c478bd9Sstevel@tonic-gate 		}
1042*7c478bd9Sstevel@tonic-gate 		if (relerr)
1043*7c478bd9Sstevel@tonic-gate 			(void) error(16);
1044*7c478bd9Sstevel@tonic-gate 	}
1045*7c478bd9Sstevel@tonic-gate }
1046*7c478bd9Sstevel@tonic-gate 
1047*7c478bd9Sstevel@tonic-gate static void
1048*7c478bd9Sstevel@tonic-gate setdot(void)
1049*7c478bd9Sstevel@tonic-gate {
1050*7c478bd9Sstevel@tonic-gate 	if (addr2 == 0)
1051*7c478bd9Sstevel@tonic-gate 		addr1 = addr2 = dot;
1052*7c478bd9Sstevel@tonic-gate 	if (addr1 > addr2)
1053*7c478bd9Sstevel@tonic-gate 		(void) error(17);
1054*7c478bd9Sstevel@tonic-gate }
1055*7c478bd9Sstevel@tonic-gate 
1056*7c478bd9Sstevel@tonic-gate static void
1057*7c478bd9Sstevel@tonic-gate setall(void)
1058*7c478bd9Sstevel@tonic-gate {
1059*7c478bd9Sstevel@tonic-gate 	if (addr2 == 0) {
1060*7c478bd9Sstevel@tonic-gate 		addr1 = zero+1;
1061*7c478bd9Sstevel@tonic-gate 		addr2 = dol;
1062*7c478bd9Sstevel@tonic-gate 		if (dol == zero)
1063*7c478bd9Sstevel@tonic-gate 			addr1 = zero;
1064*7c478bd9Sstevel@tonic-gate 	}
1065*7c478bd9Sstevel@tonic-gate 	setdot();
1066*7c478bd9Sstevel@tonic-gate }
1067*7c478bd9Sstevel@tonic-gate 
1068*7c478bd9Sstevel@tonic-gate static void
1069*7c478bd9Sstevel@tonic-gate setnoaddr(void)
1070*7c478bd9Sstevel@tonic-gate {
1071*7c478bd9Sstevel@tonic-gate 	if (addr2)
1072*7c478bd9Sstevel@tonic-gate 		(void) error(18);
1073*7c478bd9Sstevel@tonic-gate }
1074*7c478bd9Sstevel@tonic-gate 
1075*7c478bd9Sstevel@tonic-gate static void
1076*7c478bd9Sstevel@tonic-gate nonzero(void)
1077*7c478bd9Sstevel@tonic-gate {
1078*7c478bd9Sstevel@tonic-gate 	/* on NULL-RE condition do not generate error */
1079*7c478bd9Sstevel@tonic-gate 
1080*7c478bd9Sstevel@tonic-gate 	if ((linebuf[0] != '.') && (addr1 <= zero || addr2 > dol))
1081*7c478bd9Sstevel@tonic-gate 		(void) error(15);
1082*7c478bd9Sstevel@tonic-gate }
1083*7c478bd9Sstevel@tonic-gate 
1084*7c478bd9Sstevel@tonic-gate static void
1085*7c478bd9Sstevel@tonic-gate setzeroasone(void)
1086*7c478bd9Sstevel@tonic-gate {
1087*7c478bd9Sstevel@tonic-gate /* for the c and i commands 0 equal to 1 address */
1088*7c478bd9Sstevel@tonic-gate 	if (addr1 == zero) {
1089*7c478bd9Sstevel@tonic-gate 		addr1 = zero+1;
1090*7c478bd9Sstevel@tonic-gate 	}
1091*7c478bd9Sstevel@tonic-gate 	if (addr2 == zero) {
1092*7c478bd9Sstevel@tonic-gate 		addr2 = zero+1;
1093*7c478bd9Sstevel@tonic-gate 	}
1094*7c478bd9Sstevel@tonic-gate }
1095*7c478bd9Sstevel@tonic-gate 
1096*7c478bd9Sstevel@tonic-gate 
1097*7c478bd9Sstevel@tonic-gate static void
1098*7c478bd9Sstevel@tonic-gate newline(void)
1099*7c478bd9Sstevel@tonic-gate {
1100*7c478bd9Sstevel@tonic-gate 	int c;
1101*7c478bd9Sstevel@tonic-gate 
1102*7c478bd9Sstevel@tonic-gate 	if ((c = getchr()) == '\n')
1103*7c478bd9Sstevel@tonic-gate 		return;
1104*7c478bd9Sstevel@tonic-gate 	if (c == 'p' || c == 'l' || c == 'n') {
1105*7c478bd9Sstevel@tonic-gate 		pflag++;
1106*7c478bd9Sstevel@tonic-gate 		if (c == 'l') listf++;
1107*7c478bd9Sstevel@tonic-gate 		if (c == 'n') listn++;
1108*7c478bd9Sstevel@tonic-gate 		if ((c = getchr()) == '\n')
1109*7c478bd9Sstevel@tonic-gate 			return;
1110*7c478bd9Sstevel@tonic-gate 	}
1111*7c478bd9Sstevel@tonic-gate 	(void) error(20);
1112*7c478bd9Sstevel@tonic-gate }
1113*7c478bd9Sstevel@tonic-gate 
1114*7c478bd9Sstevel@tonic-gate static void
1115*7c478bd9Sstevel@tonic-gate filename(int comm)
1116*7c478bd9Sstevel@tonic-gate {
1117*7c478bd9Sstevel@tonic-gate 	char *p1, *p2;
1118*7c478bd9Sstevel@tonic-gate 	int c;
1119*7c478bd9Sstevel@tonic-gate 	int i = 0;
1120*7c478bd9Sstevel@tonic-gate 
1121*7c478bd9Sstevel@tonic-gate 	count = 0;
1122*7c478bd9Sstevel@tonic-gate 	c = getchr();
1123*7c478bd9Sstevel@tonic-gate 	if (c == '\n' || c == EOF) {
1124*7c478bd9Sstevel@tonic-gate 		p1 = savedfile;
1125*7c478bd9Sstevel@tonic-gate 		if (*p1 == 0 && comm != 'f')
1126*7c478bd9Sstevel@tonic-gate 			(void) error(21);
1127*7c478bd9Sstevel@tonic-gate 		/* ncflg set means do not get mod time of file */
1128*7c478bd9Sstevel@tonic-gate 		/* since no filename followed f */
1129*7c478bd9Sstevel@tonic-gate 		if (comm == 'f')
1130*7c478bd9Sstevel@tonic-gate 			ncflg++;
1131*7c478bd9Sstevel@tonic-gate 		p2 = file;
1132*7c478bd9Sstevel@tonic-gate 		while (*p2++ = *p1++);
1133*7c478bd9Sstevel@tonic-gate 		red(savedfile);
1134*7c478bd9Sstevel@tonic-gate 		return;
1135*7c478bd9Sstevel@tonic-gate 	}
1136*7c478bd9Sstevel@tonic-gate 	if (c != ' ')
1137*7c478bd9Sstevel@tonic-gate 		(void) error(22);
1138*7c478bd9Sstevel@tonic-gate 	while ((c = getchr()) == ' ');
1139*7c478bd9Sstevel@tonic-gate 	if (c == '!')
1140*7c478bd9Sstevel@tonic-gate 		++Xqt, c = getchr();
1141*7c478bd9Sstevel@tonic-gate 	if (c == '\n')
1142*7c478bd9Sstevel@tonic-gate 		(void) error(21);
1143*7c478bd9Sstevel@tonic-gate 	p1 = file;
1144*7c478bd9Sstevel@tonic-gate 	do {
1145*7c478bd9Sstevel@tonic-gate 		if (++i >= FNSIZE)
1146*7c478bd9Sstevel@tonic-gate 			(void) error(24);
1147*7c478bd9Sstevel@tonic-gate 		*p1++ = c;
1148*7c478bd9Sstevel@tonic-gate 		if (c == EOF || (c == ' ' && !Xqt))
1149*7c478bd9Sstevel@tonic-gate 			(void) error(21);
1150*7c478bd9Sstevel@tonic-gate 	} while ((c = getchr()) != '\n');
1151*7c478bd9Sstevel@tonic-gate 	*p1++ = 0;
1152*7c478bd9Sstevel@tonic-gate 	if (Xqt)
1153*7c478bd9Sstevel@tonic-gate 		if (comm == 'f') {
1154*7c478bd9Sstevel@tonic-gate 			--Xqt;
1155*7c478bd9Sstevel@tonic-gate 			(void) error(57);
1156*7c478bd9Sstevel@tonic-gate 		}
1157*7c478bd9Sstevel@tonic-gate 		else
1158*7c478bd9Sstevel@tonic-gate 			return;
1159*7c478bd9Sstevel@tonic-gate 	if (savedfile[0] == 0 || comm == 'e' || comm == 'f') {
1160*7c478bd9Sstevel@tonic-gate 		p1 = savedfile;
1161*7c478bd9Sstevel@tonic-gate 		p2 = file;
1162*7c478bd9Sstevel@tonic-gate 		while (*p1++ = *p2++);
1163*7c478bd9Sstevel@tonic-gate 	}
1164*7c478bd9Sstevel@tonic-gate 	red(file);
1165*7c478bd9Sstevel@tonic-gate }
1166*7c478bd9Sstevel@tonic-gate 
1167*7c478bd9Sstevel@tonic-gate 
1168*7c478bd9Sstevel@tonic-gate static void
1169*7c478bd9Sstevel@tonic-gate exfile(void)
1170*7c478bd9Sstevel@tonic-gate {
1171*7c478bd9Sstevel@tonic-gate #ifdef NULLS
1172*7c478bd9Sstevel@tonic-gate 	int c;
1173*7c478bd9Sstevel@tonic-gate #endif
1174*7c478bd9Sstevel@tonic-gate 
1175*7c478bd9Sstevel@tonic-gate #ifndef RESEARCH
1176*7c478bd9Sstevel@tonic-gate 	if (oldmask) {
1177*7c478bd9Sstevel@tonic-gate 		umask(oldmask);
1178*7c478bd9Sstevel@tonic-gate 		oldmask = 0;
1179*7c478bd9Sstevel@tonic-gate 	}
1180*7c478bd9Sstevel@tonic-gate #endif
1181*7c478bd9Sstevel@tonic-gate 	eclose(io);
1182*7c478bd9Sstevel@tonic-gate 	io = -1;
1183*7c478bd9Sstevel@tonic-gate 	if (vflag) {
1184*7c478bd9Sstevel@tonic-gate 		putd();
1185*7c478bd9Sstevel@tonic-gate 		putchr('\n');
1186*7c478bd9Sstevel@tonic-gate #ifdef NULLS
1187*7c478bd9Sstevel@tonic-gate 		if (nulls) {
1188*7c478bd9Sstevel@tonic-gate 			c = count;
1189*7c478bd9Sstevel@tonic-gate 			count = nulls;
1190*7c478bd9Sstevel@tonic-gate 			nulls = 0;
1191*7c478bd9Sstevel@tonic-gate 			putd();
1192*7c478bd9Sstevel@tonic-gate 			puts(gettext(" nulls replaced by '\\0'"));
1193*7c478bd9Sstevel@tonic-gate 			count = c;
1194*7c478bd9Sstevel@tonic-gate 		}
1195*7c478bd9Sstevel@tonic-gate #endif
1196*7c478bd9Sstevel@tonic-gate 	}
1197*7c478bd9Sstevel@tonic-gate }
1198*7c478bd9Sstevel@tonic-gate 
1199*7c478bd9Sstevel@tonic-gate static void
1200*7c478bd9Sstevel@tonic-gate onintr(int sig)
1201*7c478bd9Sstevel@tonic-gate {
1202*7c478bd9Sstevel@tonic-gate 	signal(SIGINT, onintr);
1203*7c478bd9Sstevel@tonic-gate 	putchr('\n');
1204*7c478bd9Sstevel@tonic-gate 	lastc = '\n';
1205*7c478bd9Sstevel@tonic-gate 	globflg = 0;
1206*7c478bd9Sstevel@tonic-gate 	if (funlink) unlink(funny); /* remove tmp file */
1207*7c478bd9Sstevel@tonic-gate 	/* if interrupted a read, only part of file may be in buffer */
1208*7c478bd9Sstevel@tonic-gate 	if (readflg) {
1209*7c478bd9Sstevel@tonic-gate 		sprintf(tstring, "\007read may be incomplete - beware!\007");
1210*7c478bd9Sstevel@tonic-gate 		puts(gettext(tstring));
1211*7c478bd9Sstevel@tonic-gate 		fchange = 0;
1212*7c478bd9Sstevel@tonic-gate 	}
1213*7c478bd9Sstevel@tonic-gate 	(void) error(26);
1214*7c478bd9Sstevel@tonic-gate }
1215*7c478bd9Sstevel@tonic-gate 
1216*7c478bd9Sstevel@tonic-gate static void
1217*7c478bd9Sstevel@tonic-gate onhup(int sig)
1218*7c478bd9Sstevel@tonic-gate {
1219*7c478bd9Sstevel@tonic-gate 	signal(SIGINT, SIG_IGN);
1220*7c478bd9Sstevel@tonic-gate 	signal(SIGHUP, SIG_IGN);
1221*7c478bd9Sstevel@tonic-gate 	/*
1222*7c478bd9Sstevel@tonic-gate 	 * if there are lines in file and file was not written
1223*7c478bd9Sstevel@tonic-gate 	 * since last update, save in ed.hup, or $HOME/ed.hup
1224*7c478bd9Sstevel@tonic-gate 	 */
1225*7c478bd9Sstevel@tonic-gate 	if (dol > zero && fchange == 1) {
1226*7c478bd9Sstevel@tonic-gate 		addr1 = zero+1;
1227*7c478bd9Sstevel@tonic-gate 		addr2 = dol;
1228*7c478bd9Sstevel@tonic-gate 		io = creat("ed.hup",
1229*7c478bd9Sstevel@tonic-gate 			S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
1230*7c478bd9Sstevel@tonic-gate 		if (io < 0 && home) {
1231*7c478bd9Sstevel@tonic-gate 			char	*fn;
1232*7c478bd9Sstevel@tonic-gate 
1233*7c478bd9Sstevel@tonic-gate 			fn = (char *)calloc(strlen(home) + 8, sizeof (char));
1234*7c478bd9Sstevel@tonic-gate 			if (fn) {
1235*7c478bd9Sstevel@tonic-gate 				strcpy(fn, home);
1236*7c478bd9Sstevel@tonic-gate 				strcat(fn, "/ed.hup");
1237*7c478bd9Sstevel@tonic-gate 				io = creat(fn, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
1238*7c478bd9Sstevel@tonic-gate 						|S_IROTH|S_IWOTH);
1239*7c478bd9Sstevel@tonic-gate 				free(fn);
1240*7c478bd9Sstevel@tonic-gate 			}
1241*7c478bd9Sstevel@tonic-gate 		}
1242*7c478bd9Sstevel@tonic-gate 		if (io > 0)
1243*7c478bd9Sstevel@tonic-gate 			putfile();
1244*7c478bd9Sstevel@tonic-gate 	}
1245*7c478bd9Sstevel@tonic-gate 	fchange = 0;
1246*7c478bd9Sstevel@tonic-gate 	++errcnt;
1247*7c478bd9Sstevel@tonic-gate 	quit(sig);
1248*7c478bd9Sstevel@tonic-gate }
1249*7c478bd9Sstevel@tonic-gate 
1250*7c478bd9Sstevel@tonic-gate static int
1251*7c478bd9Sstevel@tonic-gate error(int code)
1252*7c478bd9Sstevel@tonic-gate {
1253*7c478bd9Sstevel@tonic-gate 	int c;
1254*7c478bd9Sstevel@tonic-gate 
1255*7c478bd9Sstevel@tonic-gate 	if (code == 28 && save28 == 0) {
1256*7c478bd9Sstevel@tonic-gate 		fchange = 0;
1257*7c478bd9Sstevel@tonic-gate 		flag28++;
1258*7c478bd9Sstevel@tonic-gate 	}
1259*7c478bd9Sstevel@tonic-gate 	readflg = 0;
1260*7c478bd9Sstevel@tonic-gate 	++errcnt;
1261*7c478bd9Sstevel@tonic-gate 	listf = listn = 0;
1262*7c478bd9Sstevel@tonic-gate 	pflag = 0;
1263*7c478bd9Sstevel@tonic-gate #ifndef RESEARCH
1264*7c478bd9Sstevel@tonic-gate 	if (oldmask) {
1265*7c478bd9Sstevel@tonic-gate 		umask(oldmask);
1266*7c478bd9Sstevel@tonic-gate 		oldmask = 0;
1267*7c478bd9Sstevel@tonic-gate 	}
1268*7c478bd9Sstevel@tonic-gate #endif
1269*7c478bd9Sstevel@tonic-gate #ifdef NULLS	/* Not really nulls, but close enough */
1270*7c478bd9Sstevel@tonic-gate 	/* This is a bug because of buffering */
1271*7c478bd9Sstevel@tonic-gate 	if (code == 28) /* illegal char. */
1272*7c478bd9Sstevel@tonic-gate 		putd();
1273*7c478bd9Sstevel@tonic-gate #endif
1274*7c478bd9Sstevel@tonic-gate 	/* Cant open file or file does not exist */
1275*7c478bd9Sstevel@tonic-gate 	if ((code == 3) || (code == 68)) {
1276*7c478bd9Sstevel@tonic-gate 		if (qflg == 0) {
1277*7c478bd9Sstevel@tonic-gate 			putchr('?');
1278*7c478bd9Sstevel@tonic-gate 			puts(file);
1279*7c478bd9Sstevel@tonic-gate 		}
1280*7c478bd9Sstevel@tonic-gate 		else
1281*7c478bd9Sstevel@tonic-gate 			qflg = 0;
1282*7c478bd9Sstevel@tonic-gate 	}
1283*7c478bd9Sstevel@tonic-gate 	else
1284*7c478bd9Sstevel@tonic-gate 	{
1285*7c478bd9Sstevel@tonic-gate 		putchr('?');
1286*7c478bd9Sstevel@tonic-gate 		putchr('\n');
1287*7c478bd9Sstevel@tonic-gate 	}
1288*7c478bd9Sstevel@tonic-gate 	count = 0;
1289*7c478bd9Sstevel@tonic-gate 	lseek(0, (long)0, 2);
1290*7c478bd9Sstevel@tonic-gate 	if (globp)
1291*7c478bd9Sstevel@tonic-gate 		lastc = '\n';
1292*7c478bd9Sstevel@tonic-gate 	globp = 0;
1293*7c478bd9Sstevel@tonic-gate 	peekc = lastc;
1294*7c478bd9Sstevel@tonic-gate 	if (lastc)
1295*7c478bd9Sstevel@tonic-gate 		while ((c = getchr()) != '\n' && c != EOF);
1296*7c478bd9Sstevel@tonic-gate 	if (io) {
1297*7c478bd9Sstevel@tonic-gate 		eclose(io);
1298*7c478bd9Sstevel@tonic-gate 		io = -1;
1299*7c478bd9Sstevel@tonic-gate 	}
1300*7c478bd9Sstevel@tonic-gate 	xcode = code;
1301*7c478bd9Sstevel@tonic-gate 	if (hflag)
1302*7c478bd9Sstevel@tonic-gate 		PUTM();
1303*7c478bd9Sstevel@tonic-gate 	if (code == 4)
1304*7c478bd9Sstevel@tonic-gate 		return (0);	/* Non-fatal error. */
1305*7c478bd9Sstevel@tonic-gate 	longjmp(savej, 1);
1306*7c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
1307*7c478bd9Sstevel@tonic-gate }
1308*7c478bd9Sstevel@tonic-gate 
1309*7c478bd9Sstevel@tonic-gate static int
1310*7c478bd9Sstevel@tonic-gate getchr(void)
1311*7c478bd9Sstevel@tonic-gate {
1312*7c478bd9Sstevel@tonic-gate 	char c;
1313*7c478bd9Sstevel@tonic-gate 	if (lastc = peekc) {
1314*7c478bd9Sstevel@tonic-gate 		peekc = 0;
1315*7c478bd9Sstevel@tonic-gate 		return (lastc);
1316*7c478bd9Sstevel@tonic-gate 	}
1317*7c478bd9Sstevel@tonic-gate 	if (globp) {
1318*7c478bd9Sstevel@tonic-gate 		if ((lastc = (unsigned char)*globp++) != 0)
1319*7c478bd9Sstevel@tonic-gate 			return (lastc);
1320*7c478bd9Sstevel@tonic-gate 		globp = 0;
1321*7c478bd9Sstevel@tonic-gate 		return (EOF);
1322*7c478bd9Sstevel@tonic-gate 	}
1323*7c478bd9Sstevel@tonic-gate 	if (read(0, &c, 1) <= 0)
1324*7c478bd9Sstevel@tonic-gate 		return (lastc = EOF);
1325*7c478bd9Sstevel@tonic-gate 	lastc = (unsigned char)c;
1326*7c478bd9Sstevel@tonic-gate 	return (lastc);
1327*7c478bd9Sstevel@tonic-gate }
1328*7c478bd9Sstevel@tonic-gate 
1329*7c478bd9Sstevel@tonic-gate static int
1330*7c478bd9Sstevel@tonic-gate gettty(void)
1331*7c478bd9Sstevel@tonic-gate {
1332*7c478bd9Sstevel@tonic-gate 	int c;
1333*7c478bd9Sstevel@tonic-gate 	char *gf;
1334*7c478bd9Sstevel@tonic-gate 	char *p;
1335*7c478bd9Sstevel@tonic-gate 
1336*7c478bd9Sstevel@tonic-gate 	p = linebuf;
1337*7c478bd9Sstevel@tonic-gate 	gf = globp;
1338*7c478bd9Sstevel@tonic-gate 	while ((c = getchr()) != '\n') {
1339*7c478bd9Sstevel@tonic-gate 		if (c == EOF) {
1340*7c478bd9Sstevel@tonic-gate 			if (gf)
1341*7c478bd9Sstevel@tonic-gate 				peekc = c;
1342*7c478bd9Sstevel@tonic-gate 			return (c);
1343*7c478bd9Sstevel@tonic-gate 		}
1344*7c478bd9Sstevel@tonic-gate 		if (c == 0)
1345*7c478bd9Sstevel@tonic-gate 			continue;
1346*7c478bd9Sstevel@tonic-gate 		*p++ = c;
1347*7c478bd9Sstevel@tonic-gate 
1348*7c478bd9Sstevel@tonic-gate 		if (p > &linebuf[LBSIZE-1])
1349*7c478bd9Sstevel@tonic-gate 			(void) error(27);
1350*7c478bd9Sstevel@tonic-gate 	}
1351*7c478bd9Sstevel@tonic-gate 	*p++ = 0;
1352*7c478bd9Sstevel@tonic-gate 	if (linebuf[0] == '.' && linebuf[1] == 0)
1353*7c478bd9Sstevel@tonic-gate 		return (EOF);
1354*7c478bd9Sstevel@tonic-gate 
1355*7c478bd9Sstevel@tonic-gate 	/*
1356*7c478bd9Sstevel@tonic-gate 	 * POSIX.2/XPG4 explicitly says no to this:
1357*7c478bd9Sstevel@tonic-gate 	 *
1358*7c478bd9Sstevel@tonic-gate 	 * in Solaris backslash followed by special character "." is
1359*7c478bd9Sstevel@tonic-gate 	 * special character "." itself; (so terminating input mode can be
1360*7c478bd9Sstevel@tonic-gate 	 * "\.\n").
1361*7c478bd9Sstevel@tonic-gate 	 *
1362*7c478bd9Sstevel@tonic-gate 	 * however, POSIX2/XPG4 says, input mode is terminated by
1363*7c478bd9Sstevel@tonic-gate 	 * entering line consisting of only 2 characters: ".\n"
1364*7c478bd9Sstevel@tonic-gate 	 *
1365*7c478bd9Sstevel@tonic-gate 	 * if (linebuf[0]=='\\' && linebuf[1]=='.' && linebuf[2]==0) {
1366*7c478bd9Sstevel@tonic-gate 	 *	linebuf[0] = '.';
1367*7c478bd9Sstevel@tonic-gate 	 *	linebuf[1] = 0;
1368*7c478bd9Sstevel@tonic-gate 	 * }
1369*7c478bd9Sstevel@tonic-gate 	 */
1370*7c478bd9Sstevel@tonic-gate 	return (0);
1371*7c478bd9Sstevel@tonic-gate }
1372*7c478bd9Sstevel@tonic-gate 
1373*7c478bd9Sstevel@tonic-gate static int
1374*7c478bd9Sstevel@tonic-gate getfile(void)
1375*7c478bd9Sstevel@tonic-gate {
1376*7c478bd9Sstevel@tonic-gate 	char c;
1377*7c478bd9Sstevel@tonic-gate 	char *lp, *fp;
1378*7c478bd9Sstevel@tonic-gate 
1379*7c478bd9Sstevel@tonic-gate 	lp = linebuf;
1380*7c478bd9Sstevel@tonic-gate 	fp = nextip;
1381*7c478bd9Sstevel@tonic-gate 	do {
1382*7c478bd9Sstevel@tonic-gate 		if (--ninbuf < 0) {
1383*7c478bd9Sstevel@tonic-gate 			if ((ninbuf = read(io, genbuf, LBSIZE)-1) < 0)
1384*7c478bd9Sstevel@tonic-gate 				if (lp > linebuf) {
1385*7c478bd9Sstevel@tonic-gate 					puts(gettext("'\\n' appended"));
1386*7c478bd9Sstevel@tonic-gate 					*genbuf = '\n';
1387*7c478bd9Sstevel@tonic-gate 				}
1388*7c478bd9Sstevel@tonic-gate 				else
1389*7c478bd9Sstevel@tonic-gate 					return (EOF);
1390*7c478bd9Sstevel@tonic-gate 			if (crflag == -1) {
1391*7c478bd9Sstevel@tonic-gate 				if (isencrypt(genbuf, ninbuf + 1))
1392*7c478bd9Sstevel@tonic-gate 					crflag = 2;
1393*7c478bd9Sstevel@tonic-gate 				else
1394*7c478bd9Sstevel@tonic-gate 					crflag = -2;
1395*7c478bd9Sstevel@tonic-gate 			}
1396*7c478bd9Sstevel@tonic-gate 			fp = genbuf;
1397*7c478bd9Sstevel@tonic-gate 			if (crflag > 0)
1398*7c478bd9Sstevel@tonic-gate 			if (run_crypt(count, genbuf, ninbuf+1, perm) == -1)
1399*7c478bd9Sstevel@tonic-gate 				(void) error(63);
1400*7c478bd9Sstevel@tonic-gate 		}
1401*7c478bd9Sstevel@tonic-gate 		if (lp >= &linebuf[LBSIZE]) {
1402*7c478bd9Sstevel@tonic-gate 			lastc = '\n';
1403*7c478bd9Sstevel@tonic-gate 			(void) error(27);
1404*7c478bd9Sstevel@tonic-gate 		}
1405*7c478bd9Sstevel@tonic-gate 		if ((*lp++ = c = *fp++) == 0) {
1406*7c478bd9Sstevel@tonic-gate #ifdef NULLS
1407*7c478bd9Sstevel@tonic-gate 			lp[-1] = '\\';
1408*7c478bd9Sstevel@tonic-gate 			*lp++ = '0';
1409*7c478bd9Sstevel@tonic-gate 			nulls++;
1410*7c478bd9Sstevel@tonic-gate #else
1411*7c478bd9Sstevel@tonic-gate 			lp--;
1412*7c478bd9Sstevel@tonic-gate 			continue;
1413*7c478bd9Sstevel@tonic-gate #endif
1414*7c478bd9Sstevel@tonic-gate 		}
1415*7c478bd9Sstevel@tonic-gate 		count++;
1416*7c478bd9Sstevel@tonic-gate 	} while (c != '\n');
1417*7c478bd9Sstevel@tonic-gate 	*--lp = 0;
1418*7c478bd9Sstevel@tonic-gate 	nextip = fp;
1419*7c478bd9Sstevel@tonic-gate 	if (fss.Ffill && fss.Flim && lenchk(linebuf, &fss) < 0) {
1420*7c478bd9Sstevel@tonic-gate 		write(1, gettext("line too long: lno = "),
1421*7c478bd9Sstevel@tonic-gate 			strlen(gettext("line too long: lno = ")));
1422*7c478bd9Sstevel@tonic-gate 		ccount = count;
1423*7c478bd9Sstevel@tonic-gate 		count = (++dot-zero)&077777;
1424*7c478bd9Sstevel@tonic-gate 		dot--;
1425*7c478bd9Sstevel@tonic-gate 		putd();
1426*7c478bd9Sstevel@tonic-gate 		count = ccount;
1427*7c478bd9Sstevel@tonic-gate 		putchr('\n');
1428*7c478bd9Sstevel@tonic-gate 	}
1429*7c478bd9Sstevel@tonic-gate 	return (0);
1430*7c478bd9Sstevel@tonic-gate }
1431*7c478bd9Sstevel@tonic-gate 
1432*7c478bd9Sstevel@tonic-gate static void
1433*7c478bd9Sstevel@tonic-gate putfile(void)
1434*7c478bd9Sstevel@tonic-gate {
1435*7c478bd9Sstevel@tonic-gate 	int n;
1436*7c478bd9Sstevel@tonic-gate 	LINE a1;
1437*7c478bd9Sstevel@tonic-gate 	char *fp, *lp;
1438*7c478bd9Sstevel@tonic-gate 	int nib;
1439*7c478bd9Sstevel@tonic-gate 
1440*7c478bd9Sstevel@tonic-gate 	nib = LBSIZE;
1441*7c478bd9Sstevel@tonic-gate 	fp = genbuf;
1442*7c478bd9Sstevel@tonic-gate 	a1 = addr1;
1443*7c478bd9Sstevel@tonic-gate 	do {
1444*7c478bd9Sstevel@tonic-gate 		lp = getline(a1++->cur);
1445*7c478bd9Sstevel@tonic-gate 		if (fss.Ffill && fss.Flim && lenchk(linebuf, &fss) < 0) {
1446*7c478bd9Sstevel@tonic-gate 			write(1, gettext("line too long: lno = "),
1447*7c478bd9Sstevel@tonic-gate 				strlen(gettext("line too long: lno = ")));
1448*7c478bd9Sstevel@tonic-gate 			ccount = count;
1449*7c478bd9Sstevel@tonic-gate 			count = (a1-zero-1)&077777;
1450*7c478bd9Sstevel@tonic-gate 			putd();
1451*7c478bd9Sstevel@tonic-gate 			count = ccount;
1452*7c478bd9Sstevel@tonic-gate 			putchr('\n');
1453*7c478bd9Sstevel@tonic-gate 		}
1454*7c478bd9Sstevel@tonic-gate 		for (;;) {
1455*7c478bd9Sstevel@tonic-gate 			if (--nib < 0) {
1456*7c478bd9Sstevel@tonic-gate 				n = fp-genbuf;
1457*7c478bd9Sstevel@tonic-gate 				if (kflag)
1458*7c478bd9Sstevel@tonic-gate 				if (run_crypt(count-n, genbuf, n, perm) == -1)
1459*7c478bd9Sstevel@tonic-gate 					(void) error(63);
1460*7c478bd9Sstevel@tonic-gate 				if (write(io, genbuf, n) != n)
1461*7c478bd9Sstevel@tonic-gate 					(void) error(29);
1462*7c478bd9Sstevel@tonic-gate 				nib = LBSIZE - 1;
1463*7c478bd9Sstevel@tonic-gate 				fp = genbuf;
1464*7c478bd9Sstevel@tonic-gate 			}
1465*7c478bd9Sstevel@tonic-gate 			if (dol->cur == 0L)break; /* Allow write of null file */
1466*7c478bd9Sstevel@tonic-gate 			count++;
1467*7c478bd9Sstevel@tonic-gate 			if ((*fp++ = *lp++) == 0) {
1468*7c478bd9Sstevel@tonic-gate 				fp[-1] = '\n';
1469*7c478bd9Sstevel@tonic-gate 				break;
1470*7c478bd9Sstevel@tonic-gate 			}
1471*7c478bd9Sstevel@tonic-gate 		}
1472*7c478bd9Sstevel@tonic-gate 	} while (a1 <= addr2);
1473*7c478bd9Sstevel@tonic-gate 	n = fp-genbuf;
1474*7c478bd9Sstevel@tonic-gate 	if (kflag)
1475*7c478bd9Sstevel@tonic-gate 		if (run_crypt(count-n, genbuf, n, perm) == -1)
1476*7c478bd9Sstevel@tonic-gate 			(void) error(63);
1477*7c478bd9Sstevel@tonic-gate 	if (write(io, genbuf, n) != n)
1478*7c478bd9Sstevel@tonic-gate 		(void) error(29);
1479*7c478bd9Sstevel@tonic-gate }
1480*7c478bd9Sstevel@tonic-gate 
1481*7c478bd9Sstevel@tonic-gate static void
1482*7c478bd9Sstevel@tonic-gate append(int (*f)(void), LINE a)
1483*7c478bd9Sstevel@tonic-gate {
1484*7c478bd9Sstevel@tonic-gate 	LINE a1, a2, rdot;
1485*7c478bd9Sstevel@tonic-gate 	long tl;
1486*7c478bd9Sstevel@tonic-gate 
1487*7c478bd9Sstevel@tonic-gate 	nline = 0;
1488*7c478bd9Sstevel@tonic-gate 	dot = a;
1489*7c478bd9Sstevel@tonic-gate 	while ((*f)() == 0) {
1490*7c478bd9Sstevel@tonic-gate 		if (dol >= endcore) {
1491*7c478bd9Sstevel@tonic-gate 			if ((int)sbrk(512 * sizeof (struct lin)) == -1) {
1492*7c478bd9Sstevel@tonic-gate 				lastc = '\n';
1493*7c478bd9Sstevel@tonic-gate 				(void) error(30);
1494*7c478bd9Sstevel@tonic-gate 			}
1495*7c478bd9Sstevel@tonic-gate 			endcore += 512;
1496*7c478bd9Sstevel@tonic-gate 		}
1497*7c478bd9Sstevel@tonic-gate 		tl = putline();
1498*7c478bd9Sstevel@tonic-gate 		nline++;
1499*7c478bd9Sstevel@tonic-gate 		a1 = ++dol;
1500*7c478bd9Sstevel@tonic-gate 		a2 = a1+1;
1501*7c478bd9Sstevel@tonic-gate 		rdot = ++dot;
1502*7c478bd9Sstevel@tonic-gate 		while (a1 > rdot)
1503*7c478bd9Sstevel@tonic-gate 			(--a2)->cur = (--a1)->cur;
1504*7c478bd9Sstevel@tonic-gate 		rdot->cur = tl;
1505*7c478bd9Sstevel@tonic-gate 	}
1506*7c478bd9Sstevel@tonic-gate }
1507*7c478bd9Sstevel@tonic-gate 
1508*7c478bd9Sstevel@tonic-gate static void
1509*7c478bd9Sstevel@tonic-gate unixcom(void)
1510*7c478bd9Sstevel@tonic-gate {
1511*7c478bd9Sstevel@tonic-gate 	void (*savint)();
1512*7c478bd9Sstevel@tonic-gate 	pid_t	pid, rpid;
1513*7c478bd9Sstevel@tonic-gate 	int retcode;
1514*7c478bd9Sstevel@tonic-gate 	static char savcmd[LBSIZE];	/* last command */
1515*7c478bd9Sstevel@tonic-gate 	char curcmd[LBSIZE];		/* current command */
1516*7c478bd9Sstevel@tonic-gate 	char *psavcmd, *pcurcmd, *psavedfile;
1517*7c478bd9Sstevel@tonic-gate 	int endflg = 1, shflg = 0;
1518*7c478bd9Sstevel@tonic-gate 	wchar_t	c;
1519*7c478bd9Sstevel@tonic-gate 	int	len;
1520*7c478bd9Sstevel@tonic-gate 
1521*7c478bd9Sstevel@tonic-gate 	setnoaddr();
1522*7c478bd9Sstevel@tonic-gate 	if (rflg)
1523*7c478bd9Sstevel@tonic-gate 		(void) error(6);
1524*7c478bd9Sstevel@tonic-gate 	pcurcmd = curcmd;
1525*7c478bd9Sstevel@tonic-gate 	/* read command til end */
1526*7c478bd9Sstevel@tonic-gate 
1527*7c478bd9Sstevel@tonic-gate 	/*
1528*7c478bd9Sstevel@tonic-gate 	 * a '!' found in beginning of command is replaced with the saved
1529*7c478bd9Sstevel@tonic-gate 	 * command.  a '%' found in command is replaced with the current
1530*7c478bd9Sstevel@tonic-gate 	 * filename
1531*7c478bd9Sstevel@tonic-gate 	 */
1532*7c478bd9Sstevel@tonic-gate 
1533*7c478bd9Sstevel@tonic-gate 	c = getchr();
1534*7c478bd9Sstevel@tonic-gate 	if (c == '!') {
1535*7c478bd9Sstevel@tonic-gate 		if (savcmd[0] == 0)
1536*7c478bd9Sstevel@tonic-gate 			(void) error(56);
1537*7c478bd9Sstevel@tonic-gate 		else {
1538*7c478bd9Sstevel@tonic-gate 			psavcmd = savcmd;
1539*7c478bd9Sstevel@tonic-gate 			while (*pcurcmd++ = *psavcmd++);
1540*7c478bd9Sstevel@tonic-gate 			--pcurcmd;
1541*7c478bd9Sstevel@tonic-gate 			shflg = 1;
1542*7c478bd9Sstevel@tonic-gate 		}
1543*7c478bd9Sstevel@tonic-gate 	} else
1544*7c478bd9Sstevel@tonic-gate 		UNGETC(c);  /* put c back */
1545*7c478bd9Sstevel@tonic-gate 	while (endflg == 1) {
1546*7c478bd9Sstevel@tonic-gate 		while ((c = get_wchr()) != '\n' && c != '%' && c != '\\') {
1547*7c478bd9Sstevel@tonic-gate 			if ((len = wctomb(pcurcmd, c)) <= 0) {
1548*7c478bd9Sstevel@tonic-gate 				*pcurcmd = (unsigned char)c;
1549*7c478bd9Sstevel@tonic-gate 				len = 1;
1550*7c478bd9Sstevel@tonic-gate 			}
1551*7c478bd9Sstevel@tonic-gate 			pcurcmd += len;
1552*7c478bd9Sstevel@tonic-gate 		}
1553*7c478bd9Sstevel@tonic-gate 
1554*7c478bd9Sstevel@tonic-gate 		if (c == '%') {
1555*7c478bd9Sstevel@tonic-gate 			if (savedfile[0] == 0)
1556*7c478bd9Sstevel@tonic-gate 				(void) error(21);
1557*7c478bd9Sstevel@tonic-gate 			else {
1558*7c478bd9Sstevel@tonic-gate 				psavedfile = savedfile;
1559*7c478bd9Sstevel@tonic-gate 				while (pcurcmd < curcmd + LBSIZE &&
1560*7c478bd9Sstevel@tonic-gate 					(*pcurcmd++ = *psavedfile++));
1561*7c478bd9Sstevel@tonic-gate 				--pcurcmd;
1562*7c478bd9Sstevel@tonic-gate 				shflg = 1;
1563*7c478bd9Sstevel@tonic-gate 			}
1564*7c478bd9Sstevel@tonic-gate 		} else if (c == '\\') {
1565*7c478bd9Sstevel@tonic-gate 			c = get_wchr();
1566*7c478bd9Sstevel@tonic-gate 			if (c != '%')
1567*7c478bd9Sstevel@tonic-gate 				*pcurcmd++ = '\\';
1568*7c478bd9Sstevel@tonic-gate 			if ((len = wctomb(pcurcmd, c)) <= 0) {
1569*7c478bd9Sstevel@tonic-gate 				*pcurcmd = (unsigned char)c;
1570*7c478bd9Sstevel@tonic-gate 				len = 1;
1571*7c478bd9Sstevel@tonic-gate 			}
1572*7c478bd9Sstevel@tonic-gate 			pcurcmd += len;
1573*7c478bd9Sstevel@tonic-gate 		}
1574*7c478bd9Sstevel@tonic-gate 		else
1575*7c478bd9Sstevel@tonic-gate 			/* end of command hit */
1576*7c478bd9Sstevel@tonic-gate 			endflg = 0;
1577*7c478bd9Sstevel@tonic-gate 	}
1578*7c478bd9Sstevel@tonic-gate 	*pcurcmd++ = 0;
1579*7c478bd9Sstevel@tonic-gate 	if (shflg == 1)
1580*7c478bd9Sstevel@tonic-gate 		puts(curcmd);
1581*7c478bd9Sstevel@tonic-gate 	/* save command */
1582*7c478bd9Sstevel@tonic-gate 	strcpy(savcmd, curcmd);
1583*7c478bd9Sstevel@tonic-gate 
1584*7c478bd9Sstevel@tonic-gate 	if ((pid = fork()) == 0) {
1585*7c478bd9Sstevel@tonic-gate 		signal(SIGHUP, oldhup);
1586*7c478bd9Sstevel@tonic-gate 		signal(SIGQUIT, oldquit);
1587*7c478bd9Sstevel@tonic-gate 		close(tfile);
1588*7c478bd9Sstevel@tonic-gate 		if (__xpg4 == 0) {	/* not XPG4 */
1589*7c478bd9Sstevel@tonic-gate 			shpath = "/usr/bin/sh";
1590*7c478bd9Sstevel@tonic-gate 		} else {
1591*7c478bd9Sstevel@tonic-gate 			/* XPG4 */
1592*7c478bd9Sstevel@tonic-gate 			shpath = "/usr/xpg4/bin/sh";
1593*7c478bd9Sstevel@tonic-gate 		}
1594*7c478bd9Sstevel@tonic-gate 		execlp((const char *)shpath, "sh", "-c", curcmd, (char *)0);
1595*7c478bd9Sstevel@tonic-gate 		exit(0100);
1596*7c478bd9Sstevel@tonic-gate 	}
1597*7c478bd9Sstevel@tonic-gate 	savint = signal(SIGINT, SIG_IGN);
1598*7c478bd9Sstevel@tonic-gate 	while ((rpid = wait(&retcode)) != pid && rpid != (pid_t)-1);
1599*7c478bd9Sstevel@tonic-gate 	signal(SIGINT, savint);
1600*7c478bd9Sstevel@tonic-gate 	if (vflag) puts("!");
1601*7c478bd9Sstevel@tonic-gate }
1602*7c478bd9Sstevel@tonic-gate 
1603*7c478bd9Sstevel@tonic-gate static void
1604*7c478bd9Sstevel@tonic-gate quit(int sig)
1605*7c478bd9Sstevel@tonic-gate {
1606*7c478bd9Sstevel@tonic-gate 	if (vflag && fchange) {
1607*7c478bd9Sstevel@tonic-gate 		fchange = 0;
1608*7c478bd9Sstevel@tonic-gate 		if (flag28) {
1609*7c478bd9Sstevel@tonic-gate 			flag28 = 0;
1610*7c478bd9Sstevel@tonic-gate 			(void) error(62);
1611*7c478bd9Sstevel@tonic-gate 		}
1612*7c478bd9Sstevel@tonic-gate 
1613*7c478bd9Sstevel@tonic-gate 		/*
1614*7c478bd9Sstevel@tonic-gate 		 * For case where user reads in BOTH a good
1615*7c478bd9Sstevel@tonic-gate 		 * file & a bad file
1616*7c478bd9Sstevel@tonic-gate 		 */
1617*7c478bd9Sstevel@tonic-gate 		(void) error(1);
1618*7c478bd9Sstevel@tonic-gate 	}
1619*7c478bd9Sstevel@tonic-gate 	unlink(tfname);
1620*7c478bd9Sstevel@tonic-gate 	if (kflag)
1621*7c478bd9Sstevel@tonic-gate 		crypt_close(perm);
1622*7c478bd9Sstevel@tonic-gate 	if (xtflag)
1623*7c478bd9Sstevel@tonic-gate 		crypt_close(tperm);
1624*7c478bd9Sstevel@tonic-gate 	exit(errcnt? 2: 0);
1625*7c478bd9Sstevel@tonic-gate }
1626*7c478bd9Sstevel@tonic-gate 
1627*7c478bd9Sstevel@tonic-gate static void
1628*7c478bd9Sstevel@tonic-gate delete(void)
1629*7c478bd9Sstevel@tonic-gate {
1630*7c478bd9Sstevel@tonic-gate 	setdot();
1631*7c478bd9Sstevel@tonic-gate 	newline();
1632*7c478bd9Sstevel@tonic-gate 	nonzero();
1633*7c478bd9Sstevel@tonic-gate 	if (!globflg) save();
1634*7c478bd9Sstevel@tonic-gate 	rdelete(addr1, addr2);
1635*7c478bd9Sstevel@tonic-gate }
1636*7c478bd9Sstevel@tonic-gate 
1637*7c478bd9Sstevel@tonic-gate static void
1638*7c478bd9Sstevel@tonic-gate rdelete(LINE ad1, LINE ad2)
1639*7c478bd9Sstevel@tonic-gate {
1640*7c478bd9Sstevel@tonic-gate 	LINE a1, a2, a3;
1641*7c478bd9Sstevel@tonic-gate 
1642*7c478bd9Sstevel@tonic-gate 	a1 = ad1;
1643*7c478bd9Sstevel@tonic-gate 	a2 = ad2+1;
1644*7c478bd9Sstevel@tonic-gate 	a3 = dol;
1645*7c478bd9Sstevel@tonic-gate 	dol -= a2 - a1;
1646*7c478bd9Sstevel@tonic-gate 	do
1647*7c478bd9Sstevel@tonic-gate 		(a1++)->cur = (a2++)->cur;
1648*7c478bd9Sstevel@tonic-gate 	while (a2 <= a3);
1649*7c478bd9Sstevel@tonic-gate 	a1 = ad1;
1650*7c478bd9Sstevel@tonic-gate 	if (a1 > dol)
1651*7c478bd9Sstevel@tonic-gate 		a1 = dol;
1652*7c478bd9Sstevel@tonic-gate 	dot = a1;
1653*7c478bd9Sstevel@tonic-gate 	fchange = 1;
1654*7c478bd9Sstevel@tonic-gate }
1655*7c478bd9Sstevel@tonic-gate 
1656*7c478bd9Sstevel@tonic-gate static void
1657*7c478bd9Sstevel@tonic-gate gdelete(void)
1658*7c478bd9Sstevel@tonic-gate {
1659*7c478bd9Sstevel@tonic-gate 	LINE a1, a2, a3;
1660*7c478bd9Sstevel@tonic-gate 
1661*7c478bd9Sstevel@tonic-gate 	a3 = dol;
1662*7c478bd9Sstevel@tonic-gate 	for (a1 = zero+1; (a1->cur&01) == 0; a1++)
1663*7c478bd9Sstevel@tonic-gate 		if (a1 >= a3)
1664*7c478bd9Sstevel@tonic-gate 			return;
1665*7c478bd9Sstevel@tonic-gate 	for (a2 = a1 + 1; a2 <= a3; ) {
1666*7c478bd9Sstevel@tonic-gate 		if (a2->cur & 01) {
1667*7c478bd9Sstevel@tonic-gate 			a2++;
1668*7c478bd9Sstevel@tonic-gate 			dot = a1;
1669*7c478bd9Sstevel@tonic-gate 		} else
1670*7c478bd9Sstevel@tonic-gate 			(a1++)->cur = (a2++)->cur;
1671*7c478bd9Sstevel@tonic-gate 	}
1672*7c478bd9Sstevel@tonic-gate 	dol = a1-1;
1673*7c478bd9Sstevel@tonic-gate 	if (dot > dol)
1674*7c478bd9Sstevel@tonic-gate 		dot = dol;
1675*7c478bd9Sstevel@tonic-gate 	fchange = 1;
1676*7c478bd9Sstevel@tonic-gate }
1677*7c478bd9Sstevel@tonic-gate 
1678*7c478bd9Sstevel@tonic-gate static char *
1679*7c478bd9Sstevel@tonic-gate getline(long tl)
1680*7c478bd9Sstevel@tonic-gate {
1681*7c478bd9Sstevel@tonic-gate 	char *bp, *lp;
1682*7c478bd9Sstevel@tonic-gate 	int nl;
1683*7c478bd9Sstevel@tonic-gate 
1684*7c478bd9Sstevel@tonic-gate 	lp = linebuf;
1685*7c478bd9Sstevel@tonic-gate 	bp = getblock(tl, READ);
1686*7c478bd9Sstevel@tonic-gate 	nl = nleft;
1687*7c478bd9Sstevel@tonic-gate 	tl &= ~0377;
1688*7c478bd9Sstevel@tonic-gate 	while (*lp++ = *bp++)
1689*7c478bd9Sstevel@tonic-gate 		if (--nl == 0) {
1690*7c478bd9Sstevel@tonic-gate 			bp = getblock(tl += 0400, READ);
1691*7c478bd9Sstevel@tonic-gate 			nl = nleft;
1692*7c478bd9Sstevel@tonic-gate 		}
1693*7c478bd9Sstevel@tonic-gate 	return (linebuf);
1694*7c478bd9Sstevel@tonic-gate }
1695*7c478bd9Sstevel@tonic-gate 
1696*7c478bd9Sstevel@tonic-gate static long
1697*7c478bd9Sstevel@tonic-gate putline(void)
1698*7c478bd9Sstevel@tonic-gate {
1699*7c478bd9Sstevel@tonic-gate 	char *bp, *lp;
1700*7c478bd9Sstevel@tonic-gate 	int nl;
1701*7c478bd9Sstevel@tonic-gate 	long tl;
1702*7c478bd9Sstevel@tonic-gate 
1703*7c478bd9Sstevel@tonic-gate 	fchange = 1;
1704*7c478bd9Sstevel@tonic-gate 	lp = linebuf;
1705*7c478bd9Sstevel@tonic-gate 	tl = tline;
1706*7c478bd9Sstevel@tonic-gate 	bp = getblock(tl, WRITE);
1707*7c478bd9Sstevel@tonic-gate 	nl = nleft;
1708*7c478bd9Sstevel@tonic-gate 	tl &= ~0377;
1709*7c478bd9Sstevel@tonic-gate 	while (*bp = *lp++) {
1710*7c478bd9Sstevel@tonic-gate 		if (*bp++ == '\n') {
1711*7c478bd9Sstevel@tonic-gate 			*--bp = 0;
1712*7c478bd9Sstevel@tonic-gate 			linebp = lp;
1713*7c478bd9Sstevel@tonic-gate 			break;
1714*7c478bd9Sstevel@tonic-gate 		}
1715*7c478bd9Sstevel@tonic-gate 		if (--nl == 0) {
1716*7c478bd9Sstevel@tonic-gate 			bp = getblock(tl += 0400, WRITE);
1717*7c478bd9Sstevel@tonic-gate 			nl = nleft;
1718*7c478bd9Sstevel@tonic-gate 		}
1719*7c478bd9Sstevel@tonic-gate 	}
1720*7c478bd9Sstevel@tonic-gate 	nl = tline;
1721*7c478bd9Sstevel@tonic-gate 	tline += (((lp-linebuf)+03)>>1)&077776;
1722*7c478bd9Sstevel@tonic-gate 	return (nl);
1723*7c478bd9Sstevel@tonic-gate }
1724*7c478bd9Sstevel@tonic-gate 
1725*7c478bd9Sstevel@tonic-gate static char *
1726*7c478bd9Sstevel@tonic-gate getblock(long atl, long iof)
1727*7c478bd9Sstevel@tonic-gate {
1728*7c478bd9Sstevel@tonic-gate 	int bno, off;
1729*7c478bd9Sstevel@tonic-gate 	char *p1, *p2;
1730*7c478bd9Sstevel@tonic-gate 	int n;
1731*7c478bd9Sstevel@tonic-gate 
1732*7c478bd9Sstevel@tonic-gate 	bno = atl >> 8;
1733*7c478bd9Sstevel@tonic-gate 	off = (atl<<1)&0774;
1734*7c478bd9Sstevel@tonic-gate 
1735*7c478bd9Sstevel@tonic-gate 	/* bno is limited to 16 bits */
1736*7c478bd9Sstevel@tonic-gate 	if (bno >= 65535) {
1737*7c478bd9Sstevel@tonic-gate 		lastc = '\n';
1738*7c478bd9Sstevel@tonic-gate 		(void) error(31);
1739*7c478bd9Sstevel@tonic-gate 	}
1740*7c478bd9Sstevel@tonic-gate 	nleft = 512 - off;
1741*7c478bd9Sstevel@tonic-gate 	if (bno == iblock) {
1742*7c478bd9Sstevel@tonic-gate 		ichanged |= iof;
1743*7c478bd9Sstevel@tonic-gate 		return (ibuff+off);
1744*7c478bd9Sstevel@tonic-gate 	}
1745*7c478bd9Sstevel@tonic-gate 	if (bno == oblock)
1746*7c478bd9Sstevel@tonic-gate 		return (obuff+off);
1747*7c478bd9Sstevel@tonic-gate 	if (iof == READ) {
1748*7c478bd9Sstevel@tonic-gate 		if (ichanged) {
1749*7c478bd9Sstevel@tonic-gate 			if (xtflag)
1750*7c478bd9Sstevel@tonic-gate 				if (run_crypt(0L, ibuff, 512, tperm) == -1)
1751*7c478bd9Sstevel@tonic-gate 					(void) error(63);
1752*7c478bd9Sstevel@tonic-gate 			blkio(iblock, ibuff, write);
1753*7c478bd9Sstevel@tonic-gate 		}
1754*7c478bd9Sstevel@tonic-gate 		ichanged = 0;
1755*7c478bd9Sstevel@tonic-gate 		iblock = bno;
1756*7c478bd9Sstevel@tonic-gate 		blkio(bno, ibuff, read);
1757*7c478bd9Sstevel@tonic-gate 		if (xtflag)
1758*7c478bd9Sstevel@tonic-gate 			if (run_crypt(0L, ibuff, 512, tperm) == -1)
1759*7c478bd9Sstevel@tonic-gate 				(void) error(63);
1760*7c478bd9Sstevel@tonic-gate 		return (ibuff+off);
1761*7c478bd9Sstevel@tonic-gate 	}
1762*7c478bd9Sstevel@tonic-gate 	if (oblock >= 0) {
1763*7c478bd9Sstevel@tonic-gate 		if (xtflag) {
1764*7c478bd9Sstevel@tonic-gate 			p1 = obuff;
1765*7c478bd9Sstevel@tonic-gate 			p2 = crbuf;
1766*7c478bd9Sstevel@tonic-gate 			n = 512;
1767*7c478bd9Sstevel@tonic-gate 			while (n--)
1768*7c478bd9Sstevel@tonic-gate 				*p2++ = *p1++;
1769*7c478bd9Sstevel@tonic-gate 			if (run_crypt(0L, crbuf, 512, tperm) == -1)
1770*7c478bd9Sstevel@tonic-gate 				(void) error(63);
1771*7c478bd9Sstevel@tonic-gate 			blkio(oblock, crbuf, write);
1772*7c478bd9Sstevel@tonic-gate 		} else
1773*7c478bd9Sstevel@tonic-gate 			blkio(oblock, obuff, write);
1774*7c478bd9Sstevel@tonic-gate 	}
1775*7c478bd9Sstevel@tonic-gate 	oblock = bno;
1776*7c478bd9Sstevel@tonic-gate 	return (obuff+off);
1777*7c478bd9Sstevel@tonic-gate }
1778*7c478bd9Sstevel@tonic-gate 
1779*7c478bd9Sstevel@tonic-gate static void
1780*7c478bd9Sstevel@tonic-gate blkio(int b, char *buf, ssize_t (*iofcn)())
1781*7c478bd9Sstevel@tonic-gate {
1782*7c478bd9Sstevel@tonic-gate 	lseek(tfile, (long)b<<9, 0);
1783*7c478bd9Sstevel@tonic-gate 	if ((*iofcn)(tfile, buf, 512) != 512) {
1784*7c478bd9Sstevel@tonic-gate 		if (dol != zero)
1785*7c478bd9Sstevel@tonic-gate 			(void) error(32); /* Bypass this if writing null file */
1786*7c478bd9Sstevel@tonic-gate 	}
1787*7c478bd9Sstevel@tonic-gate }
1788*7c478bd9Sstevel@tonic-gate 
1789*7c478bd9Sstevel@tonic-gate static void
1790*7c478bd9Sstevel@tonic-gate init(void)
1791*7c478bd9Sstevel@tonic-gate {
1792*7c478bd9Sstevel@tonic-gate 	long *markp;
1793*7c478bd9Sstevel@tonic-gate 	mode_t omask;
1794*7c478bd9Sstevel@tonic-gate 
1795*7c478bd9Sstevel@tonic-gate 	if (tfile != -1) {
1796*7c478bd9Sstevel@tonic-gate 		(void) close(tfile);
1797*7c478bd9Sstevel@tonic-gate 		(void) unlink(tfname);
1798*7c478bd9Sstevel@tonic-gate 	}
1799*7c478bd9Sstevel@tonic-gate 
1800*7c478bd9Sstevel@tonic-gate 	tline = 2;
1801*7c478bd9Sstevel@tonic-gate 	for (markp = names; markp < &names[26]; )
1802*7c478bd9Sstevel@tonic-gate 		*markp++ = 0L;
1803*7c478bd9Sstevel@tonic-gate 	subnewa = 0L;
1804*7c478bd9Sstevel@tonic-gate 	anymarks = 0;
1805*7c478bd9Sstevel@tonic-gate 	iblock = -1;
1806*7c478bd9Sstevel@tonic-gate 	oblock = -1;
1807*7c478bd9Sstevel@tonic-gate 	ichanged = 0;
1808*7c478bd9Sstevel@tonic-gate 	initflg = 1;
1809*7c478bd9Sstevel@tonic-gate 	omask = umask(0);
1810*7c478bd9Sstevel@tonic-gate 
1811*7c478bd9Sstevel@tonic-gate 	if ((tfile = open(tfname, O_CREAT|O_EXCL|O_RDWR,
1812*7c478bd9Sstevel@tonic-gate 	    S_IRUSR|S_IWUSR)) < 0) {
1813*7c478bd9Sstevel@tonic-gate 		puts(gettext(msgtab[70]));
1814*7c478bd9Sstevel@tonic-gate 		exit(2);
1815*7c478bd9Sstevel@tonic-gate 	}
1816*7c478bd9Sstevel@tonic-gate 
1817*7c478bd9Sstevel@tonic-gate 	umask(omask);
1818*7c478bd9Sstevel@tonic-gate 	if (xflag) {
1819*7c478bd9Sstevel@tonic-gate 		xtflag = 1;
1820*7c478bd9Sstevel@tonic-gate 		if (tpermflag)
1821*7c478bd9Sstevel@tonic-gate 			(void) crypt_close(tperm);
1822*7c478bd9Sstevel@tonic-gate 		tpermflag = 1;
1823*7c478bd9Sstevel@tonic-gate 		if (makekey(tperm)) {
1824*7c478bd9Sstevel@tonic-gate 			xtflag = 0;
1825*7c478bd9Sstevel@tonic-gate 			puts(gettext(msgtab[65]));
1826*7c478bd9Sstevel@tonic-gate 		}
1827*7c478bd9Sstevel@tonic-gate 	}
1828*7c478bd9Sstevel@tonic-gate 	brk((char *)fendcore);
1829*7c478bd9Sstevel@tonic-gate 	dot = zero = dol = savdot = savdol = fendcore;
1830*7c478bd9Sstevel@tonic-gate 	flag28 = save28 = 0;
1831*7c478bd9Sstevel@tonic-gate 	endcore = fendcore - sizeof (struct lin);
1832*7c478bd9Sstevel@tonic-gate }
1833*7c478bd9Sstevel@tonic-gate 
1834*7c478bd9Sstevel@tonic-gate static void
1835*7c478bd9Sstevel@tonic-gate global(int k)
1836*7c478bd9Sstevel@tonic-gate {
1837*7c478bd9Sstevel@tonic-gate 	char *gp;
1838*7c478bd9Sstevel@tonic-gate 	wchar_t l;
1839*7c478bd9Sstevel@tonic-gate 	char multic[MB_LEN_MAX];
1840*7c478bd9Sstevel@tonic-gate 	wchar_t c;
1841*7c478bd9Sstevel@tonic-gate 	LINE a1;
1842*7c478bd9Sstevel@tonic-gate 	char globuf[LBSIZE];
1843*7c478bd9Sstevel@tonic-gate 	int n;
1844*7c478bd9Sstevel@tonic-gate 	int	len;
1845*7c478bd9Sstevel@tonic-gate 
1846*7c478bd9Sstevel@tonic-gate 	if (globp)
1847*7c478bd9Sstevel@tonic-gate 		(void) error(33);
1848*7c478bd9Sstevel@tonic-gate 	setall();
1849*7c478bd9Sstevel@tonic-gate 	nonzero();
1850*7c478bd9Sstevel@tonic-gate 	if ((n = _mbftowc(multic, &l, getchr, &peekc)) <= 0)
1851*7c478bd9Sstevel@tonic-gate 		(void) error(67);
1852*7c478bd9Sstevel@tonic-gate 	if (l == '\n')
1853*7c478bd9Sstevel@tonic-gate 		(void) error(19);
1854*7c478bd9Sstevel@tonic-gate 	save();
1855*7c478bd9Sstevel@tonic-gate 	comple(l);
1856*7c478bd9Sstevel@tonic-gate 	gp = globuf;
1857*7c478bd9Sstevel@tonic-gate 	while ((c = get_wchr()) != '\n') {
1858*7c478bd9Sstevel@tonic-gate 		if (c == EOF)
1859*7c478bd9Sstevel@tonic-gate 			(void) error(19);
1860*7c478bd9Sstevel@tonic-gate 
1861*7c478bd9Sstevel@tonic-gate 		/* '\\' has special meaning only if preceding a '\n' */
1862*7c478bd9Sstevel@tonic-gate 		if (c == '\\') {
1863*7c478bd9Sstevel@tonic-gate 			c = get_wchr();
1864*7c478bd9Sstevel@tonic-gate 			if (c != '\n')
1865*7c478bd9Sstevel@tonic-gate 				*gp++ = '\\';
1866*7c478bd9Sstevel@tonic-gate 		}
1867*7c478bd9Sstevel@tonic-gate 		if ((gp + (unsigned int)MB_CUR_MAX) >= &globuf[LBSIZE-1])
1868*7c478bd9Sstevel@tonic-gate 			(void) error(34);
1869*7c478bd9Sstevel@tonic-gate 		if ((len = wctomb(gp, c)) <= 0) {
1870*7c478bd9Sstevel@tonic-gate 			*gp = (unsigned char)c;
1871*7c478bd9Sstevel@tonic-gate 			len = 1;
1872*7c478bd9Sstevel@tonic-gate 		}
1873*7c478bd9Sstevel@tonic-gate 		gp += len;
1874*7c478bd9Sstevel@tonic-gate 	}
1875*7c478bd9Sstevel@tonic-gate 	if (gp == globuf)
1876*7c478bd9Sstevel@tonic-gate 		*gp++ = 'p';
1877*7c478bd9Sstevel@tonic-gate 	*gp++ = '\n';
1878*7c478bd9Sstevel@tonic-gate 	*gp++ = 0;
1879*7c478bd9Sstevel@tonic-gate 	for (a1 = zero; a1 <= dol; a1++) {
1880*7c478bd9Sstevel@tonic-gate 		a1->cur &= ~01;
1881*7c478bd9Sstevel@tonic-gate 		if (a1 >= addr1 && a1 <= addr2 && execute(0, a1) == k)
1882*7c478bd9Sstevel@tonic-gate 			a1->cur |= 01;
1883*7c478bd9Sstevel@tonic-gate 	}
1884*7c478bd9Sstevel@tonic-gate 	/*
1885*7c478bd9Sstevel@tonic-gate 	 * Special case: g/.../d (avoid n^2 algorithm)
1886*7c478bd9Sstevel@tonic-gate 	 */
1887*7c478bd9Sstevel@tonic-gate 	if (globuf[0] == 'd' && globuf[1] == '\n' && globuf[2] == '\0') {
1888*7c478bd9Sstevel@tonic-gate 		gdelete();
1889*7c478bd9Sstevel@tonic-gate 		return;
1890*7c478bd9Sstevel@tonic-gate 	}
1891*7c478bd9Sstevel@tonic-gate 	for (a1 = zero; a1 <= dol; a1++) {
1892*7c478bd9Sstevel@tonic-gate 		if (a1->cur & 01) {
1893*7c478bd9Sstevel@tonic-gate 			a1->cur &= ~01;
1894*7c478bd9Sstevel@tonic-gate 			dot = a1;
1895*7c478bd9Sstevel@tonic-gate 			globp = globuf;
1896*7c478bd9Sstevel@tonic-gate 			globflg = 1;
1897*7c478bd9Sstevel@tonic-gate 			commands();
1898*7c478bd9Sstevel@tonic-gate 			globflg = 0;
1899*7c478bd9Sstevel@tonic-gate 			a1 = zero;
1900*7c478bd9Sstevel@tonic-gate 		}
1901*7c478bd9Sstevel@tonic-gate 	}
1902*7c478bd9Sstevel@tonic-gate }
1903*7c478bd9Sstevel@tonic-gate 
1904*7c478bd9Sstevel@tonic-gate static void
1905*7c478bd9Sstevel@tonic-gate join(void)
1906*7c478bd9Sstevel@tonic-gate {
1907*7c478bd9Sstevel@tonic-gate 	char *gp, *lp;
1908*7c478bd9Sstevel@tonic-gate 	LINE a1;
1909*7c478bd9Sstevel@tonic-gate 
1910*7c478bd9Sstevel@tonic-gate 	if (addr1 == addr2)
1911*7c478bd9Sstevel@tonic-gate 		return;
1912*7c478bd9Sstevel@tonic-gate 	gp = genbuf;
1913*7c478bd9Sstevel@tonic-gate 	for (a1 = addr1; a1 <= addr2; a1++) {
1914*7c478bd9Sstevel@tonic-gate 		lp = getline(a1->cur);
1915*7c478bd9Sstevel@tonic-gate 		while (*gp = *lp++)
1916*7c478bd9Sstevel@tonic-gate 			if (gp++ > &genbuf[LBSIZE-1])
1917*7c478bd9Sstevel@tonic-gate 				(void) error(27);
1918*7c478bd9Sstevel@tonic-gate 	}
1919*7c478bd9Sstevel@tonic-gate 	lp = linebuf;
1920*7c478bd9Sstevel@tonic-gate 	gp = genbuf;
1921*7c478bd9Sstevel@tonic-gate 	while (*lp++ = *gp++);
1922*7c478bd9Sstevel@tonic-gate 	addr1->cur = putline();
1923*7c478bd9Sstevel@tonic-gate 	if (addr1 < addr2)
1924*7c478bd9Sstevel@tonic-gate 		rdelete(addr1+1, addr2);
1925*7c478bd9Sstevel@tonic-gate 	dot = addr1;
1926*7c478bd9Sstevel@tonic-gate }
1927*7c478bd9Sstevel@tonic-gate 
1928*7c478bd9Sstevel@tonic-gate static void
1929*7c478bd9Sstevel@tonic-gate substitute(int inglob)
1930*7c478bd9Sstevel@tonic-gate {
1931*7c478bd9Sstevel@tonic-gate 	int nl;
1932*7c478bd9Sstevel@tonic-gate 	LINE a1;
1933*7c478bd9Sstevel@tonic-gate 	long *markp;
1934*7c478bd9Sstevel@tonic-gate 	int ingsav;		/* For saving arg. */
1935*7c478bd9Sstevel@tonic-gate 
1936*7c478bd9Sstevel@tonic-gate 	ingsav = inglob;
1937*7c478bd9Sstevel@tonic-gate 	ocerr2 = 0;
1938*7c478bd9Sstevel@tonic-gate 	gsubf = compsub();
1939*7c478bd9Sstevel@tonic-gate 	for (a1 = addr1; a1 <= addr2; a1++) {
1940*7c478bd9Sstevel@tonic-gate 		if (execute(0, a1) == 0)
1941*7c478bd9Sstevel@tonic-gate 			continue;
1942*7c478bd9Sstevel@tonic-gate 		numpass = 0;
1943*7c478bd9Sstevel@tonic-gate 		ocerr1 = 0;
1944*7c478bd9Sstevel@tonic-gate 		inglob |= 01;
1945*7c478bd9Sstevel@tonic-gate 		dosub();
1946*7c478bd9Sstevel@tonic-gate 		if (gsubf) {
1947*7c478bd9Sstevel@tonic-gate 			while (*loc2) {
1948*7c478bd9Sstevel@tonic-gate 				if (execute(1, (LINE)0) == 0)
1949*7c478bd9Sstevel@tonic-gate 					break;
1950*7c478bd9Sstevel@tonic-gate 				dosub();
1951*7c478bd9Sstevel@tonic-gate 			}
1952*7c478bd9Sstevel@tonic-gate 		}
1953*7c478bd9Sstevel@tonic-gate 		if (ocerr1 == 0)continue;	/* Don't put out-not changed. */
1954*7c478bd9Sstevel@tonic-gate 		subnewa = putline();
1955*7c478bd9Sstevel@tonic-gate 		a1->cur &= ~01;
1956*7c478bd9Sstevel@tonic-gate 		if (anymarks) {
1957*7c478bd9Sstevel@tonic-gate 			for (markp = names; markp < &names[26]; markp++)
1958*7c478bd9Sstevel@tonic-gate 				if (*markp == a1->cur)
1959*7c478bd9Sstevel@tonic-gate 					*markp = subnewa;
1960*7c478bd9Sstevel@tonic-gate 		}
1961*7c478bd9Sstevel@tonic-gate 		a1->cur = subnewa;
1962*7c478bd9Sstevel@tonic-gate 		append(getsub, a1);
1963*7c478bd9Sstevel@tonic-gate 		nl = nline;
1964*7c478bd9Sstevel@tonic-gate 		a1 += nl;
1965*7c478bd9Sstevel@tonic-gate 		addr2 += nl;
1966*7c478bd9Sstevel@tonic-gate 	}
1967*7c478bd9Sstevel@tonic-gate 	if (ingsav)
1968*7c478bd9Sstevel@tonic-gate 		return;	/* Was in global-no error msg allowed. */
1969*7c478bd9Sstevel@tonic-gate 	if (inglob == 0)
1970*7c478bd9Sstevel@tonic-gate 		(void) error(35);	/* Not in global, but not found. */
1971*7c478bd9Sstevel@tonic-gate 	if (ocerr2 == 0)
1972*7c478bd9Sstevel@tonic-gate 		(void) error(35); /* RE found, but occurrence match failed. */
1973*7c478bd9Sstevel@tonic-gate }
1974*7c478bd9Sstevel@tonic-gate 
1975*7c478bd9Sstevel@tonic-gate static int
1976*7c478bd9Sstevel@tonic-gate compsub(void)
1977*7c478bd9Sstevel@tonic-gate {
1978*7c478bd9Sstevel@tonic-gate 	int c;
1979*7c478bd9Sstevel@tonic-gate 	wchar_t seof;
1980*7c478bd9Sstevel@tonic-gate 	char *p;
1981*7c478bd9Sstevel@tonic-gate 	char multic[MB_LEN_MAX];
1982*7c478bd9Sstevel@tonic-gate 	int n;
1983*7c478bd9Sstevel@tonic-gate 	static char remem[RHSIZE];
1984*7c478bd9Sstevel@tonic-gate 	static int remflg = -1;
1985*7c478bd9Sstevel@tonic-gate 	int i;
1986*7c478bd9Sstevel@tonic-gate 
1987*7c478bd9Sstevel@tonic-gate 	if ((n = _mbftowc(multic, &seof, getchr, &peekc)) <= 0)
1988*7c478bd9Sstevel@tonic-gate 		(void) error(67);
1989*7c478bd9Sstevel@tonic-gate 	if (seof == '\n' || seof == ' ')
1990*7c478bd9Sstevel@tonic-gate 		(void) error(36);
1991*7c478bd9Sstevel@tonic-gate 	comple(seof);
1992*7c478bd9Sstevel@tonic-gate 	p = rhsbuf;
1993*7c478bd9Sstevel@tonic-gate 	for (;;) {
1994*7c478bd9Sstevel@tonic-gate 		wchar_t cl;
1995*7c478bd9Sstevel@tonic-gate 		if ((n = _mbftowc(multic, &cl, getchr, &peekc)) <= 0)
1996*7c478bd9Sstevel@tonic-gate 			(void) error(67);
1997*7c478bd9Sstevel@tonic-gate 		if (cl == '\\') {
1998*7c478bd9Sstevel@tonic-gate 			*p++ = '\\';
1999*7c478bd9Sstevel@tonic-gate 			if (p >= &rhsbuf[RHSIZE])
2000*7c478bd9Sstevel@tonic-gate 				(void) error(38);
2001*7c478bd9Sstevel@tonic-gate 			if ((n = _mbftowc(multic, &cl, getchr, &peekc)) <= 0)
2002*7c478bd9Sstevel@tonic-gate 				(void) error(67);
2003*7c478bd9Sstevel@tonic-gate 		} else if (cl == '\n') {
2004*7c478bd9Sstevel@tonic-gate 			if (nodelim == 1) {
2005*7c478bd9Sstevel@tonic-gate 				nodelim = 0;
2006*7c478bd9Sstevel@tonic-gate 				(void) error(36);
2007*7c478bd9Sstevel@tonic-gate 			}
2008*7c478bd9Sstevel@tonic-gate 			if (!(globp && globp[0])) {
2009*7c478bd9Sstevel@tonic-gate 				UNGETC('\n');
2010*7c478bd9Sstevel@tonic-gate 				pflag++;
2011*7c478bd9Sstevel@tonic-gate 				break;
2012*7c478bd9Sstevel@tonic-gate 			}
2013*7c478bd9Sstevel@tonic-gate 		} else if (cl == seof)
2014*7c478bd9Sstevel@tonic-gate 			break;
2015*7c478bd9Sstevel@tonic-gate 		if (p + n > &rhsbuf[RHSIZE])
2016*7c478bd9Sstevel@tonic-gate 			(void) error(38);
2017*7c478bd9Sstevel@tonic-gate 		(void) strncpy(p, multic, n);
2018*7c478bd9Sstevel@tonic-gate 		p += n;
2019*7c478bd9Sstevel@tonic-gate 	}
2020*7c478bd9Sstevel@tonic-gate 	*p++ = 0;
2021*7c478bd9Sstevel@tonic-gate 	if (rhsbuf[0] == '%' && rhsbuf[1] == 0)
2022*7c478bd9Sstevel@tonic-gate 		/*
2023*7c478bd9Sstevel@tonic-gate 		 * If there isn't a remembered string, it is an error;
2024*7c478bd9Sstevel@tonic-gate 		 * otherwise the right hand side is the previous right
2025*7c478bd9Sstevel@tonic-gate 		 * hand side.
2026*7c478bd9Sstevel@tonic-gate 		 */
2027*7c478bd9Sstevel@tonic-gate 
2028*7c478bd9Sstevel@tonic-gate 		if (remflg == -1)
2029*7c478bd9Sstevel@tonic-gate 			(void) error(55);
2030*7c478bd9Sstevel@tonic-gate 		else
2031*7c478bd9Sstevel@tonic-gate 			strcpy(rhsbuf, remem);
2032*7c478bd9Sstevel@tonic-gate 	else {
2033*7c478bd9Sstevel@tonic-gate 		strcpy(remem, rhsbuf);
2034*7c478bd9Sstevel@tonic-gate 		remflg = 0;
2035*7c478bd9Sstevel@tonic-gate 	}
2036*7c478bd9Sstevel@tonic-gate 	c = 0;
2037*7c478bd9Sstevel@tonic-gate 	peekc = getchr();	/* Gets char after third delimiter. */
2038*7c478bd9Sstevel@tonic-gate 	if (peekc == 'g') {
2039*7c478bd9Sstevel@tonic-gate 		c = LBSIZE; peekc = 0;
2040*7c478bd9Sstevel@tonic-gate 	}
2041*7c478bd9Sstevel@tonic-gate 	if (peekc >= '1' && peekc <= '9') {
2042*7c478bd9Sstevel@tonic-gate 		c = peekc-'0';
2043*7c478bd9Sstevel@tonic-gate 		peekc = 0;	/* Allows getchr() to get next char. */
2044*7c478bd9Sstevel@tonic-gate 		while (1) {
2045*7c478bd9Sstevel@tonic-gate 			i = getchr();
2046*7c478bd9Sstevel@tonic-gate 			if (i < '0' || i > '9')
2047*7c478bd9Sstevel@tonic-gate 				break;
2048*7c478bd9Sstevel@tonic-gate 			c = c*10 + i-'0';
2049*7c478bd9Sstevel@tonic-gate 			if (c > LBSIZE-1)
2050*7c478bd9Sstevel@tonic-gate 				(void) error(20);	/* "Illegal suffix" */
2051*7c478bd9Sstevel@tonic-gate 			}
2052*7c478bd9Sstevel@tonic-gate 		peekc = i;	/* Effectively an unget. */
2053*7c478bd9Sstevel@tonic-gate 		}
2054*7c478bd9Sstevel@tonic-gate 	newline();
2055*7c478bd9Sstevel@tonic-gate 	return (c);
2056*7c478bd9Sstevel@tonic-gate 
2057*7c478bd9Sstevel@tonic-gate 	/*
2058*7c478bd9Sstevel@tonic-gate 	 * Returns occurrence value. 0 & 1 both do first occurrence
2059*7c478bd9Sstevel@tonic-gate 	 * only: c = 0 if ordinary substitute; c = 1
2060*7c478bd9Sstevel@tonic-gate 	 * if use 1 in global sub(s/a/b/1). 0 in global form is illegal.
2061*7c478bd9Sstevel@tonic-gate 	 */
2062*7c478bd9Sstevel@tonic-gate }
2063*7c478bd9Sstevel@tonic-gate 
2064*7c478bd9Sstevel@tonic-gate static int
2065*7c478bd9Sstevel@tonic-gate getsub(void)
2066*7c478bd9Sstevel@tonic-gate {
2067*7c478bd9Sstevel@tonic-gate 	char *p1, *p2;
2068*7c478bd9Sstevel@tonic-gate 
2069*7c478bd9Sstevel@tonic-gate 	p1 = linebuf;
2070*7c478bd9Sstevel@tonic-gate 	if ((p2 = linebp) == 0)
2071*7c478bd9Sstevel@tonic-gate 		return (EOF);
2072*7c478bd9Sstevel@tonic-gate 	while (*p1++ = *p2++);
2073*7c478bd9Sstevel@tonic-gate 	linebp = 0;
2074*7c478bd9Sstevel@tonic-gate 	return (0);
2075*7c478bd9Sstevel@tonic-gate }
2076*7c478bd9Sstevel@tonic-gate 
2077*7c478bd9Sstevel@tonic-gate static void
2078*7c478bd9Sstevel@tonic-gate dosub(void)
2079*7c478bd9Sstevel@tonic-gate {
2080*7c478bd9Sstevel@tonic-gate 	char *lp, *sp, *rp;
2081*7c478bd9Sstevel@tonic-gate 	int c;
2082*7c478bd9Sstevel@tonic-gate 
2083*7c478bd9Sstevel@tonic-gate 	if (gsubf > 0 && gsubf < LBSIZE) {
2084*7c478bd9Sstevel@tonic-gate 		numpass++;
2085*7c478bd9Sstevel@tonic-gate 		if (gsubf != numpass)
2086*7c478bd9Sstevel@tonic-gate 			return;
2087*7c478bd9Sstevel@tonic-gate 	}
2088*7c478bd9Sstevel@tonic-gate 	ocerr1++;
2089*7c478bd9Sstevel@tonic-gate 	ocerr2++;
2090*7c478bd9Sstevel@tonic-gate 	lp = linebuf;
2091*7c478bd9Sstevel@tonic-gate 	sp = genbuf;
2092*7c478bd9Sstevel@tonic-gate 	rp = rhsbuf;
2093*7c478bd9Sstevel@tonic-gate 	while (lp < loc1)
2094*7c478bd9Sstevel@tonic-gate 		*sp++ = *lp++;
2095*7c478bd9Sstevel@tonic-gate 	while (c = *rp++) {
2096*7c478bd9Sstevel@tonic-gate 		if (c == '&') {
2097*7c478bd9Sstevel@tonic-gate 			sp = place(sp, loc1, loc2);
2098*7c478bd9Sstevel@tonic-gate 			continue;
2099*7c478bd9Sstevel@tonic-gate 		} else if (c == '\\') {
2100*7c478bd9Sstevel@tonic-gate 			c = *rp++;
2101*7c478bd9Sstevel@tonic-gate 			if (c >= '1' && c < nbra + '1') {
2102*7c478bd9Sstevel@tonic-gate 			sp = place(sp, braslist[c-'1'], braelist[c-'1']);
2103*7c478bd9Sstevel@tonic-gate 				continue;
2104*7c478bd9Sstevel@tonic-gate 			}
2105*7c478bd9Sstevel@tonic-gate 		}
2106*7c478bd9Sstevel@tonic-gate 		*sp++ = c;
2107*7c478bd9Sstevel@tonic-gate 		if (sp >= &genbuf[LBSIZE])
2108*7c478bd9Sstevel@tonic-gate 			(void) error(27);
2109*7c478bd9Sstevel@tonic-gate 	}
2110*7c478bd9Sstevel@tonic-gate 	lp = loc2;
2111*7c478bd9Sstevel@tonic-gate 	loc2 = sp - genbuf + linebuf;
2112*7c478bd9Sstevel@tonic-gate 	while (*sp++ = *lp++)
2113*7c478bd9Sstevel@tonic-gate 		if (sp >= &genbuf[LBSIZE])
2114*7c478bd9Sstevel@tonic-gate 			(void) error(27);
2115*7c478bd9Sstevel@tonic-gate 	lp = linebuf;
2116*7c478bd9Sstevel@tonic-gate 	sp = genbuf;
2117*7c478bd9Sstevel@tonic-gate 	while (*lp++ = *sp++);
2118*7c478bd9Sstevel@tonic-gate }
2119*7c478bd9Sstevel@tonic-gate 
2120*7c478bd9Sstevel@tonic-gate static char *
2121*7c478bd9Sstevel@tonic-gate place(char *sp, char *l1, char *l2)
2122*7c478bd9Sstevel@tonic-gate {
2123*7c478bd9Sstevel@tonic-gate 
2124*7c478bd9Sstevel@tonic-gate 	while (l1 < l2) {
2125*7c478bd9Sstevel@tonic-gate 		*sp++ = *l1++;
2126*7c478bd9Sstevel@tonic-gate 		if (sp >= &genbuf[LBSIZE])
2127*7c478bd9Sstevel@tonic-gate 			(void) error(27);
2128*7c478bd9Sstevel@tonic-gate 	}
2129*7c478bd9Sstevel@tonic-gate 	return (sp);
2130*7c478bd9Sstevel@tonic-gate }
2131*7c478bd9Sstevel@tonic-gate 
2132*7c478bd9Sstevel@tonic-gate static void
2133*7c478bd9Sstevel@tonic-gate comple(wchar_t seof)
2134*7c478bd9Sstevel@tonic-gate {
2135*7c478bd9Sstevel@tonic-gate 	int cclass = 0;
2136*7c478bd9Sstevel@tonic-gate 	wchar_t c;
2137*7c478bd9Sstevel@tonic-gate 	int n;
2138*7c478bd9Sstevel@tonic-gate 	char *cp = genbuf;
2139*7c478bd9Sstevel@tonic-gate 	char multic[MB_LEN_MAX];
2140*7c478bd9Sstevel@tonic-gate 
2141*7c478bd9Sstevel@tonic-gate 	while (1) {
2142*7c478bd9Sstevel@tonic-gate 		if ((n = _mbftowc(multic, &c, getchr, &peekc)) < 0)
2143*7c478bd9Sstevel@tonic-gate 			error1(67);
2144*7c478bd9Sstevel@tonic-gate 		if (n == 0 || c == '\n') {
2145*7c478bd9Sstevel@tonic-gate 			if (cclass)
2146*7c478bd9Sstevel@tonic-gate 				error1(49);
2147*7c478bd9Sstevel@tonic-gate 			else
2148*7c478bd9Sstevel@tonic-gate 				break;
2149*7c478bd9Sstevel@tonic-gate 		}
2150*7c478bd9Sstevel@tonic-gate 		if (c == seof && !cclass)
2151*7c478bd9Sstevel@tonic-gate 			break;
2152*7c478bd9Sstevel@tonic-gate 		if (cclass && c == ']') {
2153*7c478bd9Sstevel@tonic-gate 			cclass = 0;
2154*7c478bd9Sstevel@tonic-gate 			if (cp > &genbuf[LBSIZE-1])
2155*7c478bd9Sstevel@tonic-gate 				error1(50);
2156*7c478bd9Sstevel@tonic-gate 			*cp++ = ']';
2157*7c478bd9Sstevel@tonic-gate 			continue;
2158*7c478bd9Sstevel@tonic-gate 		}
2159*7c478bd9Sstevel@tonic-gate 		if (c == '[' && !cclass) {
2160*7c478bd9Sstevel@tonic-gate 			cclass = 1;
2161*7c478bd9Sstevel@tonic-gate 			if (cp > &genbuf[LBSIZE-1])
2162*7c478bd9Sstevel@tonic-gate 				error1(50);
2163*7c478bd9Sstevel@tonic-gate 			*cp++ = '[';
2164*7c478bd9Sstevel@tonic-gate 			if ((n = _mbftowc(multic, &c, getchr, &peekc)) < 0)
2165*7c478bd9Sstevel@tonic-gate 				error1(67);
2166*7c478bd9Sstevel@tonic-gate 			if (n == 0 || c == '\n')
2167*7c478bd9Sstevel@tonic-gate 				error1(49);
2168*7c478bd9Sstevel@tonic-gate 		}
2169*7c478bd9Sstevel@tonic-gate 		if (c == '\\' && !cclass) {
2170*7c478bd9Sstevel@tonic-gate 			if (cp > &genbuf[LBSIZE-1])
2171*7c478bd9Sstevel@tonic-gate 				error1(50);
2172*7c478bd9Sstevel@tonic-gate 			*cp++ = '\\';
2173*7c478bd9Sstevel@tonic-gate 			if ((n = _mbftowc(multic, &c, getchr, &peekc)) < 0)
2174*7c478bd9Sstevel@tonic-gate 				error1(67);
2175*7c478bd9Sstevel@tonic-gate 			if (n == 0 || c == '\n')
2176*7c478bd9Sstevel@tonic-gate 				error1(36);
2177*7c478bd9Sstevel@tonic-gate 		}
2178*7c478bd9Sstevel@tonic-gate 		if (cp + n > &genbuf[LBSIZE-1])
2179*7c478bd9Sstevel@tonic-gate 			error1(50);
2180*7c478bd9Sstevel@tonic-gate 		(void) strncpy(cp, multic, n);
2181*7c478bd9Sstevel@tonic-gate 		cp += n;
2182*7c478bd9Sstevel@tonic-gate 	}
2183*7c478bd9Sstevel@tonic-gate 	*cp = '\0';
2184*7c478bd9Sstevel@tonic-gate 	if (n != 0 && c == '\n')
2185*7c478bd9Sstevel@tonic-gate 		UNGETC('\n');
2186*7c478bd9Sstevel@tonic-gate 	if (n == 0 || c == '\n')
2187*7c478bd9Sstevel@tonic-gate 		nodelim = 1;
2188*7c478bd9Sstevel@tonic-gate 
2189*7c478bd9Sstevel@tonic-gate 	/*
2190*7c478bd9Sstevel@tonic-gate 	 * NULL RE: do not compile a null regular expression; but process
2191*7c478bd9Sstevel@tonic-gate 	 * input with last regular expression encountered
2192*7c478bd9Sstevel@tonic-gate 	 */
2193*7c478bd9Sstevel@tonic-gate 
2194*7c478bd9Sstevel@tonic-gate 	if (genbuf[0] != '\0') {
2195*7c478bd9Sstevel@tonic-gate 		if (expbuf)
2196*7c478bd9Sstevel@tonic-gate 			free(expbuf);
2197*7c478bd9Sstevel@tonic-gate 		expbuf = compile(genbuf, (char *)0, (char *)0);
2198*7c478bd9Sstevel@tonic-gate 	}
2199*7c478bd9Sstevel@tonic-gate 	if (regerrno)
2200*7c478bd9Sstevel@tonic-gate 		error1(regerrno);
2201*7c478bd9Sstevel@tonic-gate }
2202*7c478bd9Sstevel@tonic-gate 
2203*7c478bd9Sstevel@tonic-gate static void
2204*7c478bd9Sstevel@tonic-gate move(int cflag)
2205*7c478bd9Sstevel@tonic-gate {
2206*7c478bd9Sstevel@tonic-gate 	LINE adt, ad1, ad2;
2207*7c478bd9Sstevel@tonic-gate 
2208*7c478bd9Sstevel@tonic-gate 	setdot();
2209*7c478bd9Sstevel@tonic-gate 	nonzero();
2210*7c478bd9Sstevel@tonic-gate 	if ((adt = address()) == 0)
2211*7c478bd9Sstevel@tonic-gate 		(void) error(39);
2212*7c478bd9Sstevel@tonic-gate 	newline();
2213*7c478bd9Sstevel@tonic-gate 	if (!globflg) save();
2214*7c478bd9Sstevel@tonic-gate 	if (cflag) {
2215*7c478bd9Sstevel@tonic-gate 		ad1 = dol;
2216*7c478bd9Sstevel@tonic-gate 		append(getcopy, ad1++);
2217*7c478bd9Sstevel@tonic-gate 		ad2 = dol;
2218*7c478bd9Sstevel@tonic-gate 	} else {
2219*7c478bd9Sstevel@tonic-gate 		ad2 = addr2;
2220*7c478bd9Sstevel@tonic-gate 		for (ad1 = addr1; ad1 <= ad2; )
2221*7c478bd9Sstevel@tonic-gate 			(ad1++)->cur &= ~01;
2222*7c478bd9Sstevel@tonic-gate 		ad1 = addr1;
2223*7c478bd9Sstevel@tonic-gate 	}
2224*7c478bd9Sstevel@tonic-gate 	ad2++;
2225*7c478bd9Sstevel@tonic-gate 	if (adt < ad1) {
2226*7c478bd9Sstevel@tonic-gate 		dot = adt + (ad2-ad1);
2227*7c478bd9Sstevel@tonic-gate 		if ((++adt) == ad1)
2228*7c478bd9Sstevel@tonic-gate 			return;
2229*7c478bd9Sstevel@tonic-gate 		reverse(adt, ad1);
2230*7c478bd9Sstevel@tonic-gate 		reverse(ad1, ad2);
2231*7c478bd9Sstevel@tonic-gate 		reverse(adt, ad2);
2232*7c478bd9Sstevel@tonic-gate 	} else if (adt >= ad2) {
2233*7c478bd9Sstevel@tonic-gate 		dot = adt++;
2234*7c478bd9Sstevel@tonic-gate 		reverse(ad1, ad2);
2235*7c478bd9Sstevel@tonic-gate 		reverse(ad2, adt);
2236*7c478bd9Sstevel@tonic-gate 		reverse(ad1, adt);
2237*7c478bd9Sstevel@tonic-gate 	} else
2238*7c478bd9Sstevel@tonic-gate 		(void) error(39);
2239*7c478bd9Sstevel@tonic-gate 	fchange = 1;
2240*7c478bd9Sstevel@tonic-gate }
2241*7c478bd9Sstevel@tonic-gate 
2242*7c478bd9Sstevel@tonic-gate static void
2243*7c478bd9Sstevel@tonic-gate reverse(LINE a1, LINE a2)
2244*7c478bd9Sstevel@tonic-gate {
2245*7c478bd9Sstevel@tonic-gate 	long t;
2246*7c478bd9Sstevel@tonic-gate 
2247*7c478bd9Sstevel@tonic-gate 	for (;;) {
2248*7c478bd9Sstevel@tonic-gate 		t = (--a2)->cur;
2249*7c478bd9Sstevel@tonic-gate 		if (a2 <= a1)
2250*7c478bd9Sstevel@tonic-gate 			return;
2251*7c478bd9Sstevel@tonic-gate 		a2->cur = a1->cur;
2252*7c478bd9Sstevel@tonic-gate 		(a1++)->cur = t;
2253*7c478bd9Sstevel@tonic-gate 	}
2254*7c478bd9Sstevel@tonic-gate }
2255*7c478bd9Sstevel@tonic-gate 
2256*7c478bd9Sstevel@tonic-gate static int
2257*7c478bd9Sstevel@tonic-gate getcopy(void)
2258*7c478bd9Sstevel@tonic-gate {
2259*7c478bd9Sstevel@tonic-gate 
2260*7c478bd9Sstevel@tonic-gate 	if (addr1 > addr2)
2261*7c478bd9Sstevel@tonic-gate 		return (EOF);
2262*7c478bd9Sstevel@tonic-gate 	(void) getline((addr1++)->cur);
2263*7c478bd9Sstevel@tonic-gate 	return (0);
2264*7c478bd9Sstevel@tonic-gate }
2265*7c478bd9Sstevel@tonic-gate 
2266*7c478bd9Sstevel@tonic-gate 
2267*7c478bd9Sstevel@tonic-gate /*
2268*7c478bd9Sstevel@tonic-gate  * Handles error code returned from comple() routine: regular expression
2269*7c478bd9Sstevel@tonic-gate  * compile and match routines
2270*7c478bd9Sstevel@tonic-gate  */
2271*7c478bd9Sstevel@tonic-gate 
2272*7c478bd9Sstevel@tonic-gate static void
2273*7c478bd9Sstevel@tonic-gate error1(int code)
2274*7c478bd9Sstevel@tonic-gate {
2275*7c478bd9Sstevel@tonic-gate 	nbra = 0;
2276*7c478bd9Sstevel@tonic-gate 	(void) error(code);
2277*7c478bd9Sstevel@tonic-gate }
2278*7c478bd9Sstevel@tonic-gate 
2279*7c478bd9Sstevel@tonic-gate 
2280*7c478bd9Sstevel@tonic-gate static int
2281*7c478bd9Sstevel@tonic-gate execute(int gf, LINE addr)
2282*7c478bd9Sstevel@tonic-gate {
2283*7c478bd9Sstevel@tonic-gate 	char *p1;
2284*7c478bd9Sstevel@tonic-gate 	int c;
2285*7c478bd9Sstevel@tonic-gate 
2286*7c478bd9Sstevel@tonic-gate 	for (c = 0; c < nbra; c++) {
2287*7c478bd9Sstevel@tonic-gate 		braslist[c] = 0;
2288*7c478bd9Sstevel@tonic-gate 		braelist[c] = 0;
2289*7c478bd9Sstevel@tonic-gate 	}
2290*7c478bd9Sstevel@tonic-gate 	if (gf)
2291*7c478bd9Sstevel@tonic-gate 		locs = p1 = loc2;
2292*7c478bd9Sstevel@tonic-gate 	else {
2293*7c478bd9Sstevel@tonic-gate 		if (addr == zero)
2294*7c478bd9Sstevel@tonic-gate 			return (0);
2295*7c478bd9Sstevel@tonic-gate 		p1 = getline(addr->cur);
2296*7c478bd9Sstevel@tonic-gate 		locs = 0;
2297*7c478bd9Sstevel@tonic-gate 	}
2298*7c478bd9Sstevel@tonic-gate 	return (step(p1, expbuf));
2299*7c478bd9Sstevel@tonic-gate }
2300*7c478bd9Sstevel@tonic-gate 
2301*7c478bd9Sstevel@tonic-gate 
2302*7c478bd9Sstevel@tonic-gate static void
2303*7c478bd9Sstevel@tonic-gate putd()
2304*7c478bd9Sstevel@tonic-gate {
2305*7c478bd9Sstevel@tonic-gate 	int r;
2306*7c478bd9Sstevel@tonic-gate 
2307*7c478bd9Sstevel@tonic-gate 	r = (int)(count%10);
2308*7c478bd9Sstevel@tonic-gate 	count /= 10;
2309*7c478bd9Sstevel@tonic-gate 	if (count)
2310*7c478bd9Sstevel@tonic-gate 		putd();
2311*7c478bd9Sstevel@tonic-gate 	putchr(r + '0');
2312*7c478bd9Sstevel@tonic-gate }
2313*7c478bd9Sstevel@tonic-gate 
2314*7c478bd9Sstevel@tonic-gate 
2315*7c478bd9Sstevel@tonic-gate int
2316*7c478bd9Sstevel@tonic-gate puts(const char *sp)
2317*7c478bd9Sstevel@tonic-gate {
2318*7c478bd9Sstevel@tonic-gate 	int n;
2319*7c478bd9Sstevel@tonic-gate 	wchar_t c;
2320*7c478bd9Sstevel@tonic-gate 	int sz, i;
2321*7c478bd9Sstevel@tonic-gate 	if (fss.Ffill && (listf == 0)) {
2322*7c478bd9Sstevel@tonic-gate 
2323*7c478bd9Sstevel@tonic-gate 		/* deliberate attempt to remove constness of sp because */
2324*7c478bd9Sstevel@tonic-gate 		/* it needs to be expanded */
2325*7c478bd9Sstevel@tonic-gate 
2326*7c478bd9Sstevel@tonic-gate 		if ((i = expnd((char *)sp, funny, &sz, &fss)) == -1) {
2327*7c478bd9Sstevel@tonic-gate 			write(1, funny, fss.Flim & 0377);
2328*7c478bd9Sstevel@tonic-gate 			putchr('\n');
2329*7c478bd9Sstevel@tonic-gate 			write(1, gettext("too long"),
2330*7c478bd9Sstevel@tonic-gate 				strlen(gettext("too long")));
2331*7c478bd9Sstevel@tonic-gate 		}
2332*7c478bd9Sstevel@tonic-gate 		else
2333*7c478bd9Sstevel@tonic-gate 			write(1, funny, sz);
2334*7c478bd9Sstevel@tonic-gate 		putchr('\n');
2335*7c478bd9Sstevel@tonic-gate 		if (i == -2)
2336*7c478bd9Sstevel@tonic-gate 			write(1, gettext("tab count\n"),
2337*7c478bd9Sstevel@tonic-gate 				strlen(gettext("tab count\n")));
2338*7c478bd9Sstevel@tonic-gate 		return (0);
2339*7c478bd9Sstevel@tonic-gate 	}
2340*7c478bd9Sstevel@tonic-gate 	col = 0;
2341*7c478bd9Sstevel@tonic-gate 	while (*sp) {
2342*7c478bd9Sstevel@tonic-gate 		n = mbtowc(&c, sp, MB_LEN_MAX);
2343*7c478bd9Sstevel@tonic-gate 		if (listf) {
2344*7c478bd9Sstevel@tonic-gate 			if (n < 1)
2345*7c478bd9Sstevel@tonic-gate 				(void) error(28);
2346*7c478bd9Sstevel@tonic-gate 			else if (n == 1)
2347*7c478bd9Sstevel@tonic-gate 				putchr((unsigned char)*sp++);
2348*7c478bd9Sstevel@tonic-gate 			else {
2349*7c478bd9Sstevel@tonic-gate 				sp += n;
2350*7c478bd9Sstevel@tonic-gate 				putwchr(c);
2351*7c478bd9Sstevel@tonic-gate 			}
2352*7c478bd9Sstevel@tonic-gate 		} else {
2353*7c478bd9Sstevel@tonic-gate 			putchr((unsigned char)*sp++);
2354*7c478bd9Sstevel@tonic-gate 		}
2355*7c478bd9Sstevel@tonic-gate 	}
2356*7c478bd9Sstevel@tonic-gate #ifndef XPG6
2357*7c478bd9Sstevel@tonic-gate 	if (listf)
2358*7c478bd9Sstevel@tonic-gate 		putchr('$');    /* end of line is marked with a $ */
2359*7c478bd9Sstevel@tonic-gate #else
2360*7c478bd9Sstevel@tonic-gate 	if (listf) {
2361*7c478bd9Sstevel@tonic-gate 	/* xpg6 - ensure that the end of line $ is not preceeded with a "\" */
2362*7c478bd9Sstevel@tonic-gate 	/* by doing a putchr() with listf=0, thereby avoiding the $ case */
2363*7c478bd9Sstevel@tonic-gate 	/* statement  in putchr() */
2364*7c478bd9Sstevel@tonic-gate 		listf = 0;
2365*7c478bd9Sstevel@tonic-gate 		putchr('$');    /* end of line is marked with a $ */
2366*7c478bd9Sstevel@tonic-gate 		listf++;
2367*7c478bd9Sstevel@tonic-gate 	}
2368*7c478bd9Sstevel@tonic-gate #endif
2369*7c478bd9Sstevel@tonic-gate 	putchr('\n');
2370*7c478bd9Sstevel@tonic-gate 	return (1);
2371*7c478bd9Sstevel@tonic-gate }
2372*7c478bd9Sstevel@tonic-gate 
2373*7c478bd9Sstevel@tonic-gate 
2374*7c478bd9Sstevel@tonic-gate static void
2375*7c478bd9Sstevel@tonic-gate putwchr(wchar_t ac)
2376*7c478bd9Sstevel@tonic-gate {
2377*7c478bd9Sstevel@tonic-gate 	char buf[MB_LEN_MAX], *p;
2378*7c478bd9Sstevel@tonic-gate 	char *lp;
2379*7c478bd9Sstevel@tonic-gate 	wchar_t c;
2380*7c478bd9Sstevel@tonic-gate 	short len;
2381*7c478bd9Sstevel@tonic-gate 
2382*7c478bd9Sstevel@tonic-gate 	lp = linp;
2383*7c478bd9Sstevel@tonic-gate 	c = ac;
2384*7c478bd9Sstevel@tonic-gate 	if (listf) {
2385*7c478bd9Sstevel@tonic-gate 		if (!iswprint(c)) {
2386*7c478bd9Sstevel@tonic-gate 			p = &buf[0];
2387*7c478bd9Sstevel@tonic-gate 			if ((len = wctomb(p, c)) <= 0) {
2388*7c478bd9Sstevel@tonic-gate 				*p = (unsigned char)c;
2389*7c478bd9Sstevel@tonic-gate 				len = 1;
2390*7c478bd9Sstevel@tonic-gate 			};
2391*7c478bd9Sstevel@tonic-gate 			while (len--) {
2392*7c478bd9Sstevel@tonic-gate 				if (col + 4 >= 72) {
2393*7c478bd9Sstevel@tonic-gate 					col = 0;
2394*7c478bd9Sstevel@tonic-gate 					*lp++ = '\\';
2395*7c478bd9Sstevel@tonic-gate 					*lp++ = '\n';
2396*7c478bd9Sstevel@tonic-gate 				}
2397*7c478bd9Sstevel@tonic-gate 				(void) sprintf(lp, "\\%03o",
2398*7c478bd9Sstevel@tonic-gate 					*(unsigned char *)p++);
2399*7c478bd9Sstevel@tonic-gate 				col += 4;
2400*7c478bd9Sstevel@tonic-gate 				lp += 4;
2401*7c478bd9Sstevel@tonic-gate 			}
2402*7c478bd9Sstevel@tonic-gate 		} else {
2403*7c478bd9Sstevel@tonic-gate 			if ((len = wcwidth(c)) <= 0)
2404*7c478bd9Sstevel@tonic-gate 				len = 0;
2405*7c478bd9Sstevel@tonic-gate 			if (col + len >= 72) {
2406*7c478bd9Sstevel@tonic-gate 				col = 0;
2407*7c478bd9Sstevel@tonic-gate 				*lp++ = '\\';
2408*7c478bd9Sstevel@tonic-gate 				*lp++ = '\n';
2409*7c478bd9Sstevel@tonic-gate 			}
2410*7c478bd9Sstevel@tonic-gate 			col += len;
2411*7c478bd9Sstevel@tonic-gate 			if ((len = wctomb(lp, c)) <= 0) {
2412*7c478bd9Sstevel@tonic-gate 				*lp = (unsigned char)c;
2413*7c478bd9Sstevel@tonic-gate 				len = 1;
2414*7c478bd9Sstevel@tonic-gate 			}
2415*7c478bd9Sstevel@tonic-gate 			lp += len;
2416*7c478bd9Sstevel@tonic-gate 		}
2417*7c478bd9Sstevel@tonic-gate 	} else {
2418*7c478bd9Sstevel@tonic-gate 		if ((len = wctomb(lp, c)) <= 0) {
2419*7c478bd9Sstevel@tonic-gate 			*lp = (unsigned char)c;
2420*7c478bd9Sstevel@tonic-gate 			len = 1;
2421*7c478bd9Sstevel@tonic-gate 		}
2422*7c478bd9Sstevel@tonic-gate 		lp += len;
2423*7c478bd9Sstevel@tonic-gate 	}
2424*7c478bd9Sstevel@tonic-gate 	if (c == '\n' || lp >= &line[64]) {
2425*7c478bd9Sstevel@tonic-gate 		linp = line;
2426*7c478bd9Sstevel@tonic-gate 		len = lp - line;
2427*7c478bd9Sstevel@tonic-gate 		write(1, line, len);
2428*7c478bd9Sstevel@tonic-gate 		return;
2429*7c478bd9Sstevel@tonic-gate 	}
2430*7c478bd9Sstevel@tonic-gate 	linp = lp;
2431*7c478bd9Sstevel@tonic-gate }
2432*7c478bd9Sstevel@tonic-gate 
2433*7c478bd9Sstevel@tonic-gate 
2434*7c478bd9Sstevel@tonic-gate static void
2435*7c478bd9Sstevel@tonic-gate putchr(unsigned char c)
2436*7c478bd9Sstevel@tonic-gate {
2437*7c478bd9Sstevel@tonic-gate 	char *lp;
2438*7c478bd9Sstevel@tonic-gate 	int len;
2439*7c478bd9Sstevel@tonic-gate 
2440*7c478bd9Sstevel@tonic-gate 	lp = linp;
2441*7c478bd9Sstevel@tonic-gate 	if (listf && c != '\n') {
2442*7c478bd9Sstevel@tonic-gate 		switch (c) {
2443*7c478bd9Sstevel@tonic-gate 			case '\\' :
2444*7c478bd9Sstevel@tonic-gate 				*lp++ = '\\';
2445*7c478bd9Sstevel@tonic-gate 				*lp++ = '\\';
2446*7c478bd9Sstevel@tonic-gate 				col += 2;
2447*7c478bd9Sstevel@tonic-gate 				break;
2448*7c478bd9Sstevel@tonic-gate 			case '\007' :
2449*7c478bd9Sstevel@tonic-gate 				*lp++ = '\\';
2450*7c478bd9Sstevel@tonic-gate 				*lp++ = 'a';
2451*7c478bd9Sstevel@tonic-gate 				col += 2;
2452*7c478bd9Sstevel@tonic-gate 				break;
2453*7c478bd9Sstevel@tonic-gate 			case '\b' :
2454*7c478bd9Sstevel@tonic-gate 				*lp++ = '\\';
2455*7c478bd9Sstevel@tonic-gate 				*lp++ = 'b';
2456*7c478bd9Sstevel@tonic-gate 				col += 2;
2457*7c478bd9Sstevel@tonic-gate 				break;
2458*7c478bd9Sstevel@tonic-gate 			case '\f' :
2459*7c478bd9Sstevel@tonic-gate 				*lp++ = '\\';
2460*7c478bd9Sstevel@tonic-gate 				*lp++ = 'f';
2461*7c478bd9Sstevel@tonic-gate 				col += 2;
2462*7c478bd9Sstevel@tonic-gate 				break;
2463*7c478bd9Sstevel@tonic-gate 			case '\r' :
2464*7c478bd9Sstevel@tonic-gate 				*lp++ = '\\';
2465*7c478bd9Sstevel@tonic-gate 				*lp++ = 'r';
2466*7c478bd9Sstevel@tonic-gate 				col += 2;
2467*7c478bd9Sstevel@tonic-gate 				break;
2468*7c478bd9Sstevel@tonic-gate 			case '\t' :
2469*7c478bd9Sstevel@tonic-gate 				*lp++ = '\\';
2470*7c478bd9Sstevel@tonic-gate 				*lp++ = 't';
2471*7c478bd9Sstevel@tonic-gate 				col += 2;
2472*7c478bd9Sstevel@tonic-gate 				break;
2473*7c478bd9Sstevel@tonic-gate 			case '\v' :
2474*7c478bd9Sstevel@tonic-gate 				*lp++ = '\\';
2475*7c478bd9Sstevel@tonic-gate 				*lp++ = 'v';
2476*7c478bd9Sstevel@tonic-gate 				col += 2;
2477*7c478bd9Sstevel@tonic-gate 				break;
2478*7c478bd9Sstevel@tonic-gate #ifdef XPG6
2479*7c478bd9Sstevel@tonic-gate 		/* if $ characters are within the line preceed with \ */
2480*7c478bd9Sstevel@tonic-gate 			case '$' :
2481*7c478bd9Sstevel@tonic-gate 				*lp++ = '\\';
2482*7c478bd9Sstevel@tonic-gate 				*lp++ = '$';
2483*7c478bd9Sstevel@tonic-gate 				col += 2;
2484*7c478bd9Sstevel@tonic-gate 				break;
2485*7c478bd9Sstevel@tonic-gate #endif
2486*7c478bd9Sstevel@tonic-gate 			default:
2487*7c478bd9Sstevel@tonic-gate 				if (isprint(c)) {
2488*7c478bd9Sstevel@tonic-gate 					*lp++ = c;
2489*7c478bd9Sstevel@tonic-gate 					col += 1;
2490*7c478bd9Sstevel@tonic-gate 				} else {
2491*7c478bd9Sstevel@tonic-gate 					(void) sprintf(lp, "\\%03o", c);
2492*7c478bd9Sstevel@tonic-gate 					col += 4;
2493*7c478bd9Sstevel@tonic-gate 					lp += 4;
2494*7c478bd9Sstevel@tonic-gate 				}
2495*7c478bd9Sstevel@tonic-gate 				break;
2496*7c478bd9Sstevel@tonic-gate 		}
2497*7c478bd9Sstevel@tonic-gate 
2498*7c478bd9Sstevel@tonic-gate 	/*
2499*7c478bd9Sstevel@tonic-gate 	 * long lines are folded w/ pt of folding indicated by writing
2500*7c478bd9Sstevel@tonic-gate 	 * backslash/newline character
2501*7c478bd9Sstevel@tonic-gate 	 */
2502*7c478bd9Sstevel@tonic-gate 
2503*7c478bd9Sstevel@tonic-gate 		if (col + 1 >= 72) {
2504*7c478bd9Sstevel@tonic-gate 			col = 0;
2505*7c478bd9Sstevel@tonic-gate 			*lp++ = '\\';
2506*7c478bd9Sstevel@tonic-gate 			*lp++ = '\n';
2507*7c478bd9Sstevel@tonic-gate 		}
2508*7c478bd9Sstevel@tonic-gate 	} else
2509*7c478bd9Sstevel@tonic-gate 		*lp++ = c;
2510*7c478bd9Sstevel@tonic-gate 	if (c == '\n' || lp >= &line[64]) {
2511*7c478bd9Sstevel@tonic-gate 		linp = line;
2512*7c478bd9Sstevel@tonic-gate 		len = lp - line;
2513*7c478bd9Sstevel@tonic-gate 		(void) write(1, line, len);
2514*7c478bd9Sstevel@tonic-gate 		return;
2515*7c478bd9Sstevel@tonic-gate 	}
2516*7c478bd9Sstevel@tonic-gate 	linp = lp;
2517*7c478bd9Sstevel@tonic-gate }
2518*7c478bd9Sstevel@tonic-gate 
2519*7c478bd9Sstevel@tonic-gate 
2520*7c478bd9Sstevel@tonic-gate static char *
2521*7c478bd9Sstevel@tonic-gate getkey(const char *prompt)
2522*7c478bd9Sstevel@tonic-gate {
2523*7c478bd9Sstevel@tonic-gate 	struct termio b;
2524*7c478bd9Sstevel@tonic-gate 	int save;
2525*7c478bd9Sstevel@tonic-gate 	void (*sig)();
2526*7c478bd9Sstevel@tonic-gate 	static char key[KSIZE+1];
2527*7c478bd9Sstevel@tonic-gate 	char *p;
2528*7c478bd9Sstevel@tonic-gate 	int c;
2529*7c478bd9Sstevel@tonic-gate 
2530*7c478bd9Sstevel@tonic-gate 	sig = signal(SIGINT, SIG_IGN);
2531*7c478bd9Sstevel@tonic-gate 	ioctl(0, TCGETA, &b);
2532*7c478bd9Sstevel@tonic-gate 	save = b.c_lflag;
2533*7c478bd9Sstevel@tonic-gate 	b.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
2534*7c478bd9Sstevel@tonic-gate 	ioctl(0, TCSETAW, &b);
2535*7c478bd9Sstevel@tonic-gate 	write(1, gettext(prompt), strlen(gettext(prompt)));
2536*7c478bd9Sstevel@tonic-gate 	p = key;
2537*7c478bd9Sstevel@tonic-gate 	while (((c = getchr()) != EOF) && (c != '\n')) {
2538*7c478bd9Sstevel@tonic-gate 		if (p < &key[KSIZE])
2539*7c478bd9Sstevel@tonic-gate 			*p++ = c;
2540*7c478bd9Sstevel@tonic-gate 	}
2541*7c478bd9Sstevel@tonic-gate 	*p = 0;
2542*7c478bd9Sstevel@tonic-gate 	write(1, "\n", 1);
2543*7c478bd9Sstevel@tonic-gate 	b.c_lflag = save;
2544*7c478bd9Sstevel@tonic-gate 	ioctl(0, TCSETAW, &b);
2545*7c478bd9Sstevel@tonic-gate 	signal(SIGINT, sig);
2546*7c478bd9Sstevel@tonic-gate 	return (key);
2547*7c478bd9Sstevel@tonic-gate }
2548*7c478bd9Sstevel@tonic-gate 
2549*7c478bd9Sstevel@tonic-gate 
2550*7c478bd9Sstevel@tonic-gate static void
2551*7c478bd9Sstevel@tonic-gate globaln(int k)
2552*7c478bd9Sstevel@tonic-gate {
2553*7c478bd9Sstevel@tonic-gate 	char *gp;
2554*7c478bd9Sstevel@tonic-gate 	int c;
2555*7c478bd9Sstevel@tonic-gate 	int n;
2556*7c478bd9Sstevel@tonic-gate 	wchar_t cl;
2557*7c478bd9Sstevel@tonic-gate 	LINE a1;
2558*7c478bd9Sstevel@tonic-gate 	int  nfirst;
2559*7c478bd9Sstevel@tonic-gate 	char globuf[LBSIZE];
2560*7c478bd9Sstevel@tonic-gate 	char multic[MB_LEN_MAX];
2561*7c478bd9Sstevel@tonic-gate 	int	len;
2562*7c478bd9Sstevel@tonic-gate 	int pflag_save = 0;
2563*7c478bd9Sstevel@tonic-gate 	int listf_save = 0;
2564*7c478bd9Sstevel@tonic-gate 	int listn_save = 0;
2565*7c478bd9Sstevel@tonic-gate 
2566*7c478bd9Sstevel@tonic-gate 	if (globp)
2567*7c478bd9Sstevel@tonic-gate 		(void) error(33);
2568*7c478bd9Sstevel@tonic-gate 	setall();
2569*7c478bd9Sstevel@tonic-gate 	nonzero();
2570*7c478bd9Sstevel@tonic-gate 	if ((n = _mbftowc(multic, &cl, getchr, &peekc)) <= 0)
2571*7c478bd9Sstevel@tonic-gate 		(void) error(67);
2572*7c478bd9Sstevel@tonic-gate 	if (cl == '\n')
2573*7c478bd9Sstevel@tonic-gate 		(void) error(19);
2574*7c478bd9Sstevel@tonic-gate 	save();
2575*7c478bd9Sstevel@tonic-gate 	comple(cl);
2576*7c478bd9Sstevel@tonic-gate 	for (a1 = zero; a1 <= dol; a1++) {
2577*7c478bd9Sstevel@tonic-gate 		a1->cur &= ~01;
2578*7c478bd9Sstevel@tonic-gate 		if (a1 >= addr1 && a1 <= addr2 && execute(0, a1) == k)
2579*7c478bd9Sstevel@tonic-gate 			a1->cur |= 01;
2580*7c478bd9Sstevel@tonic-gate 	}
2581*7c478bd9Sstevel@tonic-gate 	nfirst = 0;
2582*7c478bd9Sstevel@tonic-gate 	newline();
2583*7c478bd9Sstevel@tonic-gate 	/*
2584*7c478bd9Sstevel@tonic-gate 	 * preserve the p, l, and n suffix commands of the G and V
2585*7c478bd9Sstevel@tonic-gate 	 * commands during the interactive section and restore
2586*7c478bd9Sstevel@tonic-gate 	 * on completion of the G and V command.
2587*7c478bd9Sstevel@tonic-gate 	 */
2588*7c478bd9Sstevel@tonic-gate 	pflag_save = pflag;
2589*7c478bd9Sstevel@tonic-gate 	listf_save = listf;
2590*7c478bd9Sstevel@tonic-gate 	listn_save = listn;
2591*7c478bd9Sstevel@tonic-gate 	pflag = 0;
2592*7c478bd9Sstevel@tonic-gate 	listf = 0;
2593*7c478bd9Sstevel@tonic-gate 	listn = 0;
2594*7c478bd9Sstevel@tonic-gate 	for (a1 = zero; a1 <= dol; a1++) {
2595*7c478bd9Sstevel@tonic-gate 		if (a1->cur & 01) {
2596*7c478bd9Sstevel@tonic-gate 			a1->cur &= ~01;
2597*7c478bd9Sstevel@tonic-gate 			dot = a1;
2598*7c478bd9Sstevel@tonic-gate 			puts(getline(a1->cur));
2599*7c478bd9Sstevel@tonic-gate 			if ((c = get_wchr()) == EOF)
2600*7c478bd9Sstevel@tonic-gate 				(void) error(52);
2601*7c478bd9Sstevel@tonic-gate 			if (c == 'a' || c == 'i' || c == 'c')
2602*7c478bd9Sstevel@tonic-gate 				(void) error(53);
2603*7c478bd9Sstevel@tonic-gate 			if (c == '\n') {
2604*7c478bd9Sstevel@tonic-gate 				a1 = zero;
2605*7c478bd9Sstevel@tonic-gate 				continue;
2606*7c478bd9Sstevel@tonic-gate 			}
2607*7c478bd9Sstevel@tonic-gate 			if (c != '&') {
2608*7c478bd9Sstevel@tonic-gate 				gp = globuf;
2609*7c478bd9Sstevel@tonic-gate 				if ((len = wctomb(gp, c)) <= 0) {
2610*7c478bd9Sstevel@tonic-gate 					*gp = (unsigned char)c;
2611*7c478bd9Sstevel@tonic-gate 					len = 1;
2612*7c478bd9Sstevel@tonic-gate 				}
2613*7c478bd9Sstevel@tonic-gate 				gp += len;
2614*7c478bd9Sstevel@tonic-gate 				while ((c = get_wchr()) != '\n') {
2615*7c478bd9Sstevel@tonic-gate 
2616*7c478bd9Sstevel@tonic-gate 			/* '\\' has special meaning only if preceding a '\n' */
2617*7c478bd9Sstevel@tonic-gate 					if (c == '\\') {
2618*7c478bd9Sstevel@tonic-gate 						c = get_wchr();
2619*7c478bd9Sstevel@tonic-gate 						if (c != '\n')
2620*7c478bd9Sstevel@tonic-gate 							*gp++ = '\\';
2621*7c478bd9Sstevel@tonic-gate 					}
2622*7c478bd9Sstevel@tonic-gate 					if ((gp + (unsigned int)MB_CUR_MAX) >=
2623*7c478bd9Sstevel@tonic-gate 							&globuf[LBSIZE-1])
2624*7c478bd9Sstevel@tonic-gate 						(void) error(34);
2625*7c478bd9Sstevel@tonic-gate 
2626*7c478bd9Sstevel@tonic-gate 					if ((len = wctomb(gp, c)) <= 0) {
2627*7c478bd9Sstevel@tonic-gate 						*gp = (unsigned char)c;
2628*7c478bd9Sstevel@tonic-gate 						len = 1;
2629*7c478bd9Sstevel@tonic-gate 					}
2630*7c478bd9Sstevel@tonic-gate 					gp += len;
2631*7c478bd9Sstevel@tonic-gate 				}
2632*7c478bd9Sstevel@tonic-gate 				*gp++ = '\n';
2633*7c478bd9Sstevel@tonic-gate 				*gp++ = 0;
2634*7c478bd9Sstevel@tonic-gate 				nfirst = 1;
2635*7c478bd9Sstevel@tonic-gate 			} else if ((c = get_wchr()) != '\n')
2636*7c478bd9Sstevel@tonic-gate 				(void) error(54);
2637*7c478bd9Sstevel@tonic-gate 			globp = globuf;
2638*7c478bd9Sstevel@tonic-gate 			if (nfirst) {
2639*7c478bd9Sstevel@tonic-gate 				globflg = 1;
2640*7c478bd9Sstevel@tonic-gate 				commands();
2641*7c478bd9Sstevel@tonic-gate 				globflg = 0;
2642*7c478bd9Sstevel@tonic-gate 			} else
2643*7c478bd9Sstevel@tonic-gate 				(void) error(56);
2644*7c478bd9Sstevel@tonic-gate 			globp = 0;
2645*7c478bd9Sstevel@tonic-gate 			a1 = zero;
2646*7c478bd9Sstevel@tonic-gate 		}
2647*7c478bd9Sstevel@tonic-gate 	}
2648*7c478bd9Sstevel@tonic-gate 	pflag = pflag_save;
2649*7c478bd9Sstevel@tonic-gate 	listf = listf_save;
2650*7c478bd9Sstevel@tonic-gate 	listn = listn_save;
2651*7c478bd9Sstevel@tonic-gate }
2652*7c478bd9Sstevel@tonic-gate 
2653*7c478bd9Sstevel@tonic-gate 
2654*7c478bd9Sstevel@tonic-gate static int
2655*7c478bd9Sstevel@tonic-gate eopen(char *string, int rw)
2656*7c478bd9Sstevel@tonic-gate {
2657*7c478bd9Sstevel@tonic-gate #define	w_or_r(a, b) (rw ? a : b)
2658*7c478bd9Sstevel@tonic-gate 	int pf[2];
2659*7c478bd9Sstevel@tonic-gate 	pid_t i;
2660*7c478bd9Sstevel@tonic-gate 	int io;
2661*7c478bd9Sstevel@tonic-gate 	int chcount;	/* # of char read. */
2662*7c478bd9Sstevel@tonic-gate 
2663*7c478bd9Sstevel@tonic-gate 	if (rflg) {	/* restricted shell */
2664*7c478bd9Sstevel@tonic-gate 		if (Xqt) {
2665*7c478bd9Sstevel@tonic-gate 			Xqt = 0;
2666*7c478bd9Sstevel@tonic-gate 			(void) error(6);
2667*7c478bd9Sstevel@tonic-gate 		}
2668*7c478bd9Sstevel@tonic-gate 	}
2669*7c478bd9Sstevel@tonic-gate 	if (!Xqt) {
2670*7c478bd9Sstevel@tonic-gate 		if ((io = open(string, rw)) >= 0) {
2671*7c478bd9Sstevel@tonic-gate 			if (fflg) {
2672*7c478bd9Sstevel@tonic-gate 				chcount = read(io, crbuf, LBSIZE);
2673*7c478bd9Sstevel@tonic-gate 				if (crflag == -1) {
2674*7c478bd9Sstevel@tonic-gate 					if (isencrypt(crbuf, chcount))
2675*7c478bd9Sstevel@tonic-gate 						crflag = 2;
2676*7c478bd9Sstevel@tonic-gate 					else
2677*7c478bd9Sstevel@tonic-gate 						crflag = -2;
2678*7c478bd9Sstevel@tonic-gate 				}
2679*7c478bd9Sstevel@tonic-gate 				if (crflag > 0)
2680*7c478bd9Sstevel@tonic-gate 				if (run_crypt(0L, crbuf, chcount, perm) == -1)
2681*7c478bd9Sstevel@tonic-gate 						(void) error(63);
2682*7c478bd9Sstevel@tonic-gate 				if (fspec(crbuf, &fss, 0) < 0) {
2683*7c478bd9Sstevel@tonic-gate 					fss.Ffill = 0;
2684*7c478bd9Sstevel@tonic-gate 					fflg = 0;
2685*7c478bd9Sstevel@tonic-gate 					(void) error(4);
2686*7c478bd9Sstevel@tonic-gate 				}
2687*7c478bd9Sstevel@tonic-gate 				lseek(io, 0L, 0);
2688*7c478bd9Sstevel@tonic-gate 			}
2689*7c478bd9Sstevel@tonic-gate 		}
2690*7c478bd9Sstevel@tonic-gate 		fflg = 0;
2691*7c478bd9Sstevel@tonic-gate 		return (io);
2692*7c478bd9Sstevel@tonic-gate 	}
2693*7c478bd9Sstevel@tonic-gate 	if (pipe(pf) < 0)
2694*7c478bd9Sstevel@tonic-gate xerr:		(void) error(0);
2695*7c478bd9Sstevel@tonic-gate 	if ((i = fork()) == 0) {
2696*7c478bd9Sstevel@tonic-gate 		signal(SIGHUP, oldhup);
2697*7c478bd9Sstevel@tonic-gate 		signal(SIGQUIT, oldquit);
2698*7c478bd9Sstevel@tonic-gate 		signal(SIGPIPE, oldpipe);
2699*7c478bd9Sstevel@tonic-gate 		signal(SIGINT, (void (*)()) 0);
2700*7c478bd9Sstevel@tonic-gate 		close(w_or_r(pf[1], pf[0]));
2701*7c478bd9Sstevel@tonic-gate 		close(w_or_r(0, 1));
2702*7c478bd9Sstevel@tonic-gate 		dup(w_or_r(pf[0], pf[1]));
2703*7c478bd9Sstevel@tonic-gate 		close(w_or_r(pf[0], pf[1]));
2704*7c478bd9Sstevel@tonic-gate 		if (__xpg4 == 0) {	/* not XPG4 */
2705*7c478bd9Sstevel@tonic-gate 			shpath = "/usr/bin/sh";
2706*7c478bd9Sstevel@tonic-gate 		} else {
2707*7c478bd9Sstevel@tonic-gate 			/* XPG4 */
2708*7c478bd9Sstevel@tonic-gate 			shpath = "/usr/xpg4/bin/sh";
2709*7c478bd9Sstevel@tonic-gate 		}
2710*7c478bd9Sstevel@tonic-gate 		execlp((const char *)shpath, "sh", "-c", string, (char *)0);
2711*7c478bd9Sstevel@tonic-gate 		exit(1);
2712*7c478bd9Sstevel@tonic-gate 	}
2713*7c478bd9Sstevel@tonic-gate 	if (i == (pid_t)-1)
2714*7c478bd9Sstevel@tonic-gate 		goto xerr;
2715*7c478bd9Sstevel@tonic-gate 	close(w_or_r(pf[0], pf[1]));
2716*7c478bd9Sstevel@tonic-gate 	return (w_or_r(pf[1], pf[0]));
2717*7c478bd9Sstevel@tonic-gate }
2718*7c478bd9Sstevel@tonic-gate 
2719*7c478bd9Sstevel@tonic-gate 
2720*7c478bd9Sstevel@tonic-gate static void
2721*7c478bd9Sstevel@tonic-gate eclose(int f)
2722*7c478bd9Sstevel@tonic-gate {
2723*7c478bd9Sstevel@tonic-gate 	close(f);
2724*7c478bd9Sstevel@tonic-gate 	if (Xqt)
2725*7c478bd9Sstevel@tonic-gate 		Xqt = 0, wait((int *)0);
2726*7c478bd9Sstevel@tonic-gate }
2727*7c478bd9Sstevel@tonic-gate 
2728*7c478bd9Sstevel@tonic-gate 
2729*7c478bd9Sstevel@tonic-gate static void
2730*7c478bd9Sstevel@tonic-gate mkfunny(void)
2731*7c478bd9Sstevel@tonic-gate {
2732*7c478bd9Sstevel@tonic-gate 	char *p, *p1, *p2;
2733*7c478bd9Sstevel@tonic-gate 
2734*7c478bd9Sstevel@tonic-gate 	p2 = p1 = funny;
2735*7c478bd9Sstevel@tonic-gate 	p = file;
2736*7c478bd9Sstevel@tonic-gate 	/*
2737*7c478bd9Sstevel@tonic-gate 	 * Go to end of file name
2738*7c478bd9Sstevel@tonic-gate 	 */
2739*7c478bd9Sstevel@tonic-gate 	while (*p)
2740*7c478bd9Sstevel@tonic-gate 		p++;
2741*7c478bd9Sstevel@tonic-gate 	while (*--p  == '/')	/* delete trailing slashes */
2742*7c478bd9Sstevel@tonic-gate 		*p = '\0';
2743*7c478bd9Sstevel@tonic-gate 	/*
2744*7c478bd9Sstevel@tonic-gate 	 * go back to beginning of file
2745*7c478bd9Sstevel@tonic-gate 	 */
2746*7c478bd9Sstevel@tonic-gate 	p = file;
2747*7c478bd9Sstevel@tonic-gate 	/*
2748*7c478bd9Sstevel@tonic-gate 	 * Copy file name to funny setting p2 at
2749*7c478bd9Sstevel@tonic-gate 	 * basename of file.
2750*7c478bd9Sstevel@tonic-gate 	 */
2751*7c478bd9Sstevel@tonic-gate 	while (*p1++ = *p)
2752*7c478bd9Sstevel@tonic-gate 		if (*p++ == '/') p2 = p1;
2753*7c478bd9Sstevel@tonic-gate 	/*
2754*7c478bd9Sstevel@tonic-gate 	 * Set p1 to point to basename of tfname.
2755*7c478bd9Sstevel@tonic-gate 	 */
2756*7c478bd9Sstevel@tonic-gate 	p1 = strrchr(tfname, '/');
2757*7c478bd9Sstevel@tonic-gate 	if (strlen(tfname) > (size_t)6)
2758*7c478bd9Sstevel@tonic-gate 		p1 = &tfname[strlen(tfname)-6];
2759*7c478bd9Sstevel@tonic-gate 	p1++;
2760*7c478bd9Sstevel@tonic-gate 	*p2 = '\007'; /* add unprintable char for funny  a unique name */
2761*7c478bd9Sstevel@tonic-gate 	/*
2762*7c478bd9Sstevel@tonic-gate 	 * Copy tfname to file.
2763*7c478bd9Sstevel@tonic-gate 	 */
2764*7c478bd9Sstevel@tonic-gate 	while (*++p2 = *p1++);
2765*7c478bd9Sstevel@tonic-gate }
2766*7c478bd9Sstevel@tonic-gate 
2767*7c478bd9Sstevel@tonic-gate 
2768*7c478bd9Sstevel@tonic-gate static void
2769*7c478bd9Sstevel@tonic-gate getime(void) /* get modified time of file and save */
2770*7c478bd9Sstevel@tonic-gate {
2771*7c478bd9Sstevel@tonic-gate 	if (stat(file, &Fl) < 0)
2772*7c478bd9Sstevel@tonic-gate 		savtime = 0;
2773*7c478bd9Sstevel@tonic-gate 	else
2774*7c478bd9Sstevel@tonic-gate 		savtime = Fl.st_mtime;
2775*7c478bd9Sstevel@tonic-gate }
2776*7c478bd9Sstevel@tonic-gate 
2777*7c478bd9Sstevel@tonic-gate 
2778*7c478bd9Sstevel@tonic-gate static void
2779*7c478bd9Sstevel@tonic-gate chktime(void) /* check saved mod time against current mod time */
2780*7c478bd9Sstevel@tonic-gate {
2781*7c478bd9Sstevel@tonic-gate 	if (savtime != 0 && Fl.st_mtime != 0) {
2782*7c478bd9Sstevel@tonic-gate 		if (savtime != Fl.st_mtime)
2783*7c478bd9Sstevel@tonic-gate 			(void) error(58);
2784*7c478bd9Sstevel@tonic-gate 	}
2785*7c478bd9Sstevel@tonic-gate }
2786*7c478bd9Sstevel@tonic-gate 
2787*7c478bd9Sstevel@tonic-gate 
2788*7c478bd9Sstevel@tonic-gate static void
2789*7c478bd9Sstevel@tonic-gate newtime(void) /* get new mod time and save */
2790*7c478bd9Sstevel@tonic-gate {
2791*7c478bd9Sstevel@tonic-gate 	stat(file, &Fl);
2792*7c478bd9Sstevel@tonic-gate 	savtime = Fl.st_mtime;
2793*7c478bd9Sstevel@tonic-gate }
2794*7c478bd9Sstevel@tonic-gate 
2795*7c478bd9Sstevel@tonic-gate 
2796*7c478bd9Sstevel@tonic-gate static void
2797*7c478bd9Sstevel@tonic-gate red(char *op)	/* restricted - check for '/' in name */
2798*7c478bd9Sstevel@tonic-gate 		/* and delete trailing '/' */
2799*7c478bd9Sstevel@tonic-gate {
2800*7c478bd9Sstevel@tonic-gate 	char *p;
2801*7c478bd9Sstevel@tonic-gate 
2802*7c478bd9Sstevel@tonic-gate 	p = op;
2803*7c478bd9Sstevel@tonic-gate 	while (*p)
2804*7c478bd9Sstevel@tonic-gate 		if (*p++ == '/'&& rflg) {
2805*7c478bd9Sstevel@tonic-gate 			*op = 0;
2806*7c478bd9Sstevel@tonic-gate 			(void) error(6);
2807*7c478bd9Sstevel@tonic-gate 		}
2808*7c478bd9Sstevel@tonic-gate 	/* delete trailing '/' */
2809*7c478bd9Sstevel@tonic-gate 	while (p > op) {
2810*7c478bd9Sstevel@tonic-gate 		if (*--p == '/')
2811*7c478bd9Sstevel@tonic-gate 			*p = '\0';
2812*7c478bd9Sstevel@tonic-gate 		else break;
2813*7c478bd9Sstevel@tonic-gate 	}
2814*7c478bd9Sstevel@tonic-gate }
2815*7c478bd9Sstevel@tonic-gate 
2816*7c478bd9Sstevel@tonic-gate 
2817*7c478bd9Sstevel@tonic-gate /*
2818*7c478bd9Sstevel@tonic-gate  * Searches thru beginning of file looking for a string of the form
2819*7c478bd9Sstevel@tonic-gate  *	<: values... :>
2820*7c478bd9Sstevel@tonic-gate  *
2821*7c478bd9Sstevel@tonic-gate  * where "values" are
2822*7c478bd9Sstevel@tonic-gate  *
2823*7c478bd9Sstevel@tonic-gate  *	\b      ignored
2824*7c478bd9Sstevel@tonic-gate  *	s<num>  sets the Flim to <num>
2825*7c478bd9Sstevel@tonic-gate  *	t???    sets tab stop stuff
2826*7c478bd9Sstevel@tonic-gate  *	d       ignored
2827*7c478bd9Sstevel@tonic-gate  *	m<num>  ignored
2828*7c478bd9Sstevel@tonic-gate  *	e       ignored
2829*7c478bd9Sstevel@tonic-gate  */
2830*7c478bd9Sstevel@tonic-gate 
2831*7c478bd9Sstevel@tonic-gate static int
2832*7c478bd9Sstevel@tonic-gate fspec(char line[], struct Fspec *f, int up)
2833*7c478bd9Sstevel@tonic-gate {
2834*7c478bd9Sstevel@tonic-gate 	struct termio arg;
2835*7c478bd9Sstevel@tonic-gate 	int havespec, n;
2836*7c478bd9Sstevel@tonic-gate 	int	len;
2837*7c478bd9Sstevel@tonic-gate 
2838*7c478bd9Sstevel@tonic-gate 	if (!up) clear(f);
2839*7c478bd9Sstevel@tonic-gate 
2840*7c478bd9Sstevel@tonic-gate 	havespec = fsprtn = 0;
2841*7c478bd9Sstevel@tonic-gate 	for (fsp = line; *fsp && *fsp != '\n'; fsp += len) {
2842*7c478bd9Sstevel@tonic-gate 		if ((len = mblen(fsp, MB_CUR_MAX)) <= 0)
2843*7c478bd9Sstevel@tonic-gate 			len = 1;
2844*7c478bd9Sstevel@tonic-gate 		switch (*fsp) {
2845*7c478bd9Sstevel@tonic-gate 
2846*7c478bd9Sstevel@tonic-gate 			case '<':	if (havespec)
2847*7c478bd9Sstevel@tonic-gate 						return (-1);
2848*7c478bd9Sstevel@tonic-gate 					if (*(fsp+1) == ':') {
2849*7c478bd9Sstevel@tonic-gate 						havespec = 1;
2850*7c478bd9Sstevel@tonic-gate 						clear(f);
2851*7c478bd9Sstevel@tonic-gate 						if (!ioctl(1, TCGETA, &arg) &&
2852*7c478bd9Sstevel@tonic-gate 						((arg.c_oflag&TAB3) == TAB3))
2853*7c478bd9Sstevel@tonic-gate 						    f->Ffill = 1;
2854*7c478bd9Sstevel@tonic-gate 						fsp++;
2855*7c478bd9Sstevel@tonic-gate 						continue;
2856*7c478bd9Sstevel@tonic-gate 					}
2857*7c478bd9Sstevel@tonic-gate 
2858*7c478bd9Sstevel@tonic-gate 			case ' ':	continue;
2859*7c478bd9Sstevel@tonic-gate 
2860*7c478bd9Sstevel@tonic-gate 			case 's':	if (havespec && (n = numb()) >= 0)
2861*7c478bd9Sstevel@tonic-gate 						f->Flim = n;
2862*7c478bd9Sstevel@tonic-gate 					continue;
2863*7c478bd9Sstevel@tonic-gate 
2864*7c478bd9Sstevel@tonic-gate 			case 't':	if (havespec) targ(f);
2865*7c478bd9Sstevel@tonic-gate 					continue;
2866*7c478bd9Sstevel@tonic-gate 
2867*7c478bd9Sstevel@tonic-gate 			case 'd':	continue;
2868*7c478bd9Sstevel@tonic-gate 
2869*7c478bd9Sstevel@tonic-gate 			case 'm':	if (havespec)  n = numb();
2870*7c478bd9Sstevel@tonic-gate 					continue;
2871*7c478bd9Sstevel@tonic-gate 
2872*7c478bd9Sstevel@tonic-gate 			case 'e':	continue;
2873*7c478bd9Sstevel@tonic-gate 			case ':':	if (!havespec) continue;
2874*7c478bd9Sstevel@tonic-gate 					if (*(fsp+1) != '>') fsprtn = -1;
2875*7c478bd9Sstevel@tonic-gate 					return (fsprtn);
2876*7c478bd9Sstevel@tonic-gate 
2877*7c478bd9Sstevel@tonic-gate 			default:	if (!havespec) continue;
2878*7c478bd9Sstevel@tonic-gate 					return (-1);
2879*7c478bd9Sstevel@tonic-gate 		}
2880*7c478bd9Sstevel@tonic-gate 	}
2881*7c478bd9Sstevel@tonic-gate 	return (1);
2882*7c478bd9Sstevel@tonic-gate }
2883*7c478bd9Sstevel@tonic-gate 
2884*7c478bd9Sstevel@tonic-gate 
2885*7c478bd9Sstevel@tonic-gate static int
2886*7c478bd9Sstevel@tonic-gate numb(void)
2887*7c478bd9Sstevel@tonic-gate {
2888*7c478bd9Sstevel@tonic-gate 	int n;
2889*7c478bd9Sstevel@tonic-gate 
2890*7c478bd9Sstevel@tonic-gate 	n = 0;
2891*7c478bd9Sstevel@tonic-gate 	while (*++fsp >= '0' && *fsp <= '9')
2892*7c478bd9Sstevel@tonic-gate 		n = 10*n + *fsp-'0';
2893*7c478bd9Sstevel@tonic-gate 	fsp--;
2894*7c478bd9Sstevel@tonic-gate 	return (n);
2895*7c478bd9Sstevel@tonic-gate }
2896*7c478bd9Sstevel@tonic-gate 
2897*7c478bd9Sstevel@tonic-gate 
2898*7c478bd9Sstevel@tonic-gate static void
2899*7c478bd9Sstevel@tonic-gate targ(struct Fspec *f)
2900*7c478bd9Sstevel@tonic-gate {
2901*7c478bd9Sstevel@tonic-gate 
2902*7c478bd9Sstevel@tonic-gate 	if (*++fsp == '-') {
2903*7c478bd9Sstevel@tonic-gate 		if (*(fsp + 1) >= '0' && *(fsp+1) <= '9') tincr(numb(), f);
2904*7c478bd9Sstevel@tonic-gate 		else tstd(f);
2905*7c478bd9Sstevel@tonic-gate 		return;
2906*7c478bd9Sstevel@tonic-gate 	}
2907*7c478bd9Sstevel@tonic-gate 	if (*fsp >= '0' && *fsp <= '9') {
2908*7c478bd9Sstevel@tonic-gate 		tlist(f);
2909*7c478bd9Sstevel@tonic-gate 		return;
2910*7c478bd9Sstevel@tonic-gate 	}
2911*7c478bd9Sstevel@tonic-gate 	fsprtn = -1;
2912*7c478bd9Sstevel@tonic-gate 	fsp--;
2913*7c478bd9Sstevel@tonic-gate }
2914*7c478bd9Sstevel@tonic-gate 
2915*7c478bd9Sstevel@tonic-gate 
2916*7c478bd9Sstevel@tonic-gate static void
2917*7c478bd9Sstevel@tonic-gate tincr(int n, struct Fspec *f)
2918*7c478bd9Sstevel@tonic-gate {
2919*7c478bd9Sstevel@tonic-gate 	int l, i;
2920*7c478bd9Sstevel@tonic-gate 
2921*7c478bd9Sstevel@tonic-gate 	l = 1;
2922*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < 20; i++)
2923*7c478bd9Sstevel@tonic-gate 		f->Ftabs[i] = l += n;
2924*7c478bd9Sstevel@tonic-gate 	f->Ftabs[i] = 0;
2925*7c478bd9Sstevel@tonic-gate }
2926*7c478bd9Sstevel@tonic-gate 
2927*7c478bd9Sstevel@tonic-gate 
2928*7c478bd9Sstevel@tonic-gate static void
2929*7c478bd9Sstevel@tonic-gate tstd(struct Fspec *f)
2930*7c478bd9Sstevel@tonic-gate {
2931*7c478bd9Sstevel@tonic-gate 	char std[3];
2932*7c478bd9Sstevel@tonic-gate 
2933*7c478bd9Sstevel@tonic-gate 	std[0] = *++fsp;
2934*7c478bd9Sstevel@tonic-gate 	if (*(fsp+1) >= '0' && *(fsp+1) <= '9')  {
2935*7c478bd9Sstevel@tonic-gate 						std[1] = *++fsp;
2936*7c478bd9Sstevel@tonic-gate 						std[2] = '\0';
2937*7c478bd9Sstevel@tonic-gate 	} else std[1] = '\0';
2938*7c478bd9Sstevel@tonic-gate 	fsprtn = stdtab(std, f->Ftabs);
2939*7c478bd9Sstevel@tonic-gate }
2940*7c478bd9Sstevel@tonic-gate 
2941*7c478bd9Sstevel@tonic-gate 
2942*7c478bd9Sstevel@tonic-gate static void
2943*7c478bd9Sstevel@tonic-gate tlist(struct Fspec *f)
2944*7c478bd9Sstevel@tonic-gate {
2945*7c478bd9Sstevel@tonic-gate 	int n, last, i;
2946*7c478bd9Sstevel@tonic-gate 
2947*7c478bd9Sstevel@tonic-gate 	fsp--;
2948*7c478bd9Sstevel@tonic-gate 	last = i = 0;
2949*7c478bd9Sstevel@tonic-gate 
2950*7c478bd9Sstevel@tonic-gate 	do {
2951*7c478bd9Sstevel@tonic-gate 		if ((n = numb()) <= last || i >= 20) {
2952*7c478bd9Sstevel@tonic-gate 			fsprtn = -1;
2953*7c478bd9Sstevel@tonic-gate 			return;
2954*7c478bd9Sstevel@tonic-gate 		}
2955*7c478bd9Sstevel@tonic-gate 		f->Ftabs[i++] = last = n;
2956*7c478bd9Sstevel@tonic-gate 	} while (*++fsp == ',');
2957*7c478bd9Sstevel@tonic-gate 
2958*7c478bd9Sstevel@tonic-gate 	f->Ftabs[i] = 0;
2959*7c478bd9Sstevel@tonic-gate 	fsp--;
2960*7c478bd9Sstevel@tonic-gate }
2961*7c478bd9Sstevel@tonic-gate 
2962*7c478bd9Sstevel@tonic-gate 
2963*7c478bd9Sstevel@tonic-gate static int
2964*7c478bd9Sstevel@tonic-gate expnd(char line[], char buf[], int *sz, struct Fspec *f)
2965*7c478bd9Sstevel@tonic-gate {
2966*7c478bd9Sstevel@tonic-gate 	char *l, *t;
2967*7c478bd9Sstevel@tonic-gate 	int b;
2968*7c478bd9Sstevel@tonic-gate 
2969*7c478bd9Sstevel@tonic-gate 	l = line - 1;
2970*7c478bd9Sstevel@tonic-gate 	b = 1;
2971*7c478bd9Sstevel@tonic-gate 	t = f->Ftabs;
2972*7c478bd9Sstevel@tonic-gate 	fsprtn = 0;
2973*7c478bd9Sstevel@tonic-gate 
2974*7c478bd9Sstevel@tonic-gate 	while (*++l && *l != '\n' && b < 511) {
2975*7c478bd9Sstevel@tonic-gate 		if (*l == '\t') {
2976*7c478bd9Sstevel@tonic-gate 			while (*t && b >= *t) t++;
2977*7c478bd9Sstevel@tonic-gate 			if (*t == 0) fsprtn = -2;
2978*7c478bd9Sstevel@tonic-gate 			do buf[b-1] = ' '; while (++b < *t);
2979*7c478bd9Sstevel@tonic-gate 		} else buf[b++ - 1] = *l;
2980*7c478bd9Sstevel@tonic-gate 	}
2981*7c478bd9Sstevel@tonic-gate 
2982*7c478bd9Sstevel@tonic-gate 	buf[b] = '\0';
2983*7c478bd9Sstevel@tonic-gate 	*sz = b;
2984*7c478bd9Sstevel@tonic-gate 	if (*l != '\0' && *l != '\n') {
2985*7c478bd9Sstevel@tonic-gate 		buf[b-1] = '\n';
2986*7c478bd9Sstevel@tonic-gate 		return (-1);
2987*7c478bd9Sstevel@tonic-gate 	}
2988*7c478bd9Sstevel@tonic-gate 	buf[b-1] = *l;
2989*7c478bd9Sstevel@tonic-gate 	if (f->Flim && (b-1 > (int)f->Flim))
2990*7c478bd9Sstevel@tonic-gate 		return (-1);
2991*7c478bd9Sstevel@tonic-gate 	return (fsprtn);
2992*7c478bd9Sstevel@tonic-gate }
2993*7c478bd9Sstevel@tonic-gate 
2994*7c478bd9Sstevel@tonic-gate 
2995*7c478bd9Sstevel@tonic-gate static void
2996*7c478bd9Sstevel@tonic-gate clear(struct Fspec *f)
2997*7c478bd9Sstevel@tonic-gate {
2998*7c478bd9Sstevel@tonic-gate 	f->Ftabs[0] = f->Fdel = f->Fmov = f->Ffill = 0;
2999*7c478bd9Sstevel@tonic-gate 	f->Flim = 0;
3000*7c478bd9Sstevel@tonic-gate }
3001*7c478bd9Sstevel@tonic-gate 
3002*7c478bd9Sstevel@tonic-gate 
3003*7c478bd9Sstevel@tonic-gate static int
3004*7c478bd9Sstevel@tonic-gate lenchk(char line[], struct Fspec *f)
3005*7c478bd9Sstevel@tonic-gate {
3006*7c478bd9Sstevel@tonic-gate 	char *l, *t;
3007*7c478bd9Sstevel@tonic-gate 	int b;
3008*7c478bd9Sstevel@tonic-gate 
3009*7c478bd9Sstevel@tonic-gate 	l = line - 1;
3010*7c478bd9Sstevel@tonic-gate 	b = 1;
3011*7c478bd9Sstevel@tonic-gate 	t = f->Ftabs;
3012*7c478bd9Sstevel@tonic-gate 
3013*7c478bd9Sstevel@tonic-gate 	while (*++l && *l != '\n' && b < 511) {
3014*7c478bd9Sstevel@tonic-gate 		if (*l == '\t') {
3015*7c478bd9Sstevel@tonic-gate 			while (*t && b >= *t) t++;
3016*7c478bd9Sstevel@tonic-gate 			while (++b < *t);
3017*7c478bd9Sstevel@tonic-gate 		} else b++;
3018*7c478bd9Sstevel@tonic-gate 	}
3019*7c478bd9Sstevel@tonic-gate 
3020*7c478bd9Sstevel@tonic-gate 	if ((*l != '\0' && *l != '\n') || (f->Flim && (b-1 > (int)f->Flim)))
3021*7c478bd9Sstevel@tonic-gate 		return (-1);
3022*7c478bd9Sstevel@tonic-gate 	return (0);
3023*7c478bd9Sstevel@tonic-gate }
3024*7c478bd9Sstevel@tonic-gate #define	NTABS 21
3025*7c478bd9Sstevel@tonic-gate 
3026*7c478bd9Sstevel@tonic-gate 
3027*7c478bd9Sstevel@tonic-gate /*
3028*7c478bd9Sstevel@tonic-gate  *	stdtabs: standard tabs table
3029*7c478bd9Sstevel@tonic-gate  *	format: option code letter(s), null, tabs, null
3030*7c478bd9Sstevel@tonic-gate  */
3031*7c478bd9Sstevel@tonic-gate 
3032*7c478bd9Sstevel@tonic-gate static char stdtabs[] = {
3033*7c478bd9Sstevel@tonic-gate 'a', 0, 1, 10, 16, 36, 72, 0,			/* IBM 370 Assembler */
3034*7c478bd9Sstevel@tonic-gate 'a', '2', 0, 1, 10, 16, 40, 72, 0,		/* IBM Assembler alternative */
3035*7c478bd9Sstevel@tonic-gate 'c', 0, 1, 8, 12, 16, 20, 55, 0,		/* COBOL, normal */
3036*7c478bd9Sstevel@tonic-gate 'c', '2', 0, 1, 6, 10, 14, 49, 0,		/* COBOL, crunched */
3037*7c478bd9Sstevel@tonic-gate 'c', '3', 0, 1, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50,
3038*7c478bd9Sstevel@tonic-gate 	54, 58, 62, 67, 0,
3039*7c478bd9Sstevel@tonic-gate 'f', 0, 1, 7, 11, 15, 19, 23, 0,		/* FORTRAN */
3040*7c478bd9Sstevel@tonic-gate 'p', 0, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 0,
3041*7c478bd9Sstevel@tonic-gate 						/* PL/I */
3042*7c478bd9Sstevel@tonic-gate 's', 0, 1, 10, 55, 0,    			/* SNOBOL */
3043*7c478bd9Sstevel@tonic-gate 'u', 0, 1, 12, 20, 44, 0, 			/* UNIVAC ASM */
3044*7c478bd9Sstevel@tonic-gate 0 };
3045*7c478bd9Sstevel@tonic-gate 
3046*7c478bd9Sstevel@tonic-gate 
3047*7c478bd9Sstevel@tonic-gate /*
3048*7c478bd9Sstevel@tonic-gate  *	stdtab: return tab list for any "canned" tab option.
3049*7c478bd9Sstevel@tonic-gate  *		entry: option points to null-terminated option string
3050*7c478bd9Sstevel@tonic-gate  *		tabvect points to vector to be filled in
3051*7c478bd9Sstevel@tonic-gate  *	exit: return (0) if legal, tabvect filled, ending with zero
3052*7c478bd9Sstevel@tonic-gate  *		return (-1) if unknown option
3053*7c478bd9Sstevel@tonic-gate  */
3054*7c478bd9Sstevel@tonic-gate 
3055*7c478bd9Sstevel@tonic-gate 
3056*7c478bd9Sstevel@tonic-gate static int
3057*7c478bd9Sstevel@tonic-gate stdtab(char option[], char tabvect[NTABS])
3058*7c478bd9Sstevel@tonic-gate {
3059*7c478bd9Sstevel@tonic-gate 	char *scan;
3060*7c478bd9Sstevel@tonic-gate 	tabvect[0] = 0;
3061*7c478bd9Sstevel@tonic-gate 	scan = stdtabs;
3062*7c478bd9Sstevel@tonic-gate 	while (*scan) {
3063*7c478bd9Sstevel@tonic-gate 		if (strequal(&scan, option)) {
3064*7c478bd9Sstevel@tonic-gate 			strcopy(scan, tabvect);
3065*7c478bd9Sstevel@tonic-gate 			break;
3066*7c478bd9Sstevel@tonic-gate 		} else
3067*7c478bd9Sstevel@tonic-gate 			while (*scan++);    /* skip over tab specs */
3068*7c478bd9Sstevel@tonic-gate 	}
3069*7c478bd9Sstevel@tonic-gate 
3070*7c478bd9Sstevel@tonic-gate /*	later: look up code in /etc/something */
3071*7c478bd9Sstevel@tonic-gate 	return (tabvect[0] ? 0 : -1);
3072*7c478bd9Sstevel@tonic-gate }
3073*7c478bd9Sstevel@tonic-gate 
3074*7c478bd9Sstevel@tonic-gate 
3075*7c478bd9Sstevel@tonic-gate /*
3076*7c478bd9Sstevel@tonic-gate  *	strequal: checks strings for equality
3077*7c478bd9Sstevel@tonic-gate  *		entry: scan1 points to scan pointer, str points to string
3078*7c478bd9Sstevel@tonic-gate  *	exit: return (1) if equal, return (0) if not
3079*7c478bd9Sstevel@tonic-gate  *		*scan1 is advanced to next nonzero byte after null
3080*7c478bd9Sstevel@tonic-gate  */
3081*7c478bd9Sstevel@tonic-gate 
3082*7c478bd9Sstevel@tonic-gate 
3083*7c478bd9Sstevel@tonic-gate static int
3084*7c478bd9Sstevel@tonic-gate strequal(char **scan1, char *str)
3085*7c478bd9Sstevel@tonic-gate {
3086*7c478bd9Sstevel@tonic-gate 	char c, *scan;
3087*7c478bd9Sstevel@tonic-gate 	scan = *scan1;
3088*7c478bd9Sstevel@tonic-gate 	while ((c = *scan++) == *str && c) str++;
3089*7c478bd9Sstevel@tonic-gate 	*scan1 = scan;
3090*7c478bd9Sstevel@tonic-gate 	if (c == 0 && *str == 0)
3091*7c478bd9Sstevel@tonic-gate 		return (1);
3092*7c478bd9Sstevel@tonic-gate 	if (c)
3093*7c478bd9Sstevel@tonic-gate 		while (*scan++);
3094*7c478bd9Sstevel@tonic-gate 			*scan1 = scan;
3095*7c478bd9Sstevel@tonic-gate 	return (0);
3096*7c478bd9Sstevel@tonic-gate }
3097*7c478bd9Sstevel@tonic-gate 
3098*7c478bd9Sstevel@tonic-gate 
3099*7c478bd9Sstevel@tonic-gate /*	strcopy: copy source to destination */
3100*7c478bd9Sstevel@tonic-gate 
3101*7c478bd9Sstevel@tonic-gate 
3102*7c478bd9Sstevel@tonic-gate static void
3103*7c478bd9Sstevel@tonic-gate strcopy(char *source, char *dest)
3104*7c478bd9Sstevel@tonic-gate {
3105*7c478bd9Sstevel@tonic-gate 	while (*dest++ = *source++);
3106*7c478bd9Sstevel@tonic-gate }
3107*7c478bd9Sstevel@tonic-gate 
3108*7c478bd9Sstevel@tonic-gate 
3109*7c478bd9Sstevel@tonic-gate /* This is called before a buffer modifying command so that the */
3110*7c478bd9Sstevel@tonic-gate /* current array of line ptrs is saved in sav and dot and dol are saved */
3111*7c478bd9Sstevel@tonic-gate 
3112*7c478bd9Sstevel@tonic-gate 
3113*7c478bd9Sstevel@tonic-gate static void
3114*7c478bd9Sstevel@tonic-gate save(void) {
3115*7c478bd9Sstevel@tonic-gate 	LINE i;
3116*7c478bd9Sstevel@tonic-gate 	int	j;
3117*7c478bd9Sstevel@tonic-gate 
3118*7c478bd9Sstevel@tonic-gate 	savdot = dot;
3119*7c478bd9Sstevel@tonic-gate 	savdol = dol;
3120*7c478bd9Sstevel@tonic-gate 	for (j = 0; j <= 25; j++)
3121*7c478bd9Sstevel@tonic-gate 		savnames[j] = names[j];
3122*7c478bd9Sstevel@tonic-gate 
3123*7c478bd9Sstevel@tonic-gate 	for (i = zero + 1; i <= dol; i++)
3124*7c478bd9Sstevel@tonic-gate 		i->sav = i->cur;
3125*7c478bd9Sstevel@tonic-gate 	initflg = 0;
3126*7c478bd9Sstevel@tonic-gate }
3127*7c478bd9Sstevel@tonic-gate 
3128*7c478bd9Sstevel@tonic-gate 
3129*7c478bd9Sstevel@tonic-gate /* The undo command calls this to restore the previous ptr array sav */
3130*7c478bd9Sstevel@tonic-gate /* and swap with cur - dot and dol are swapped also. This allows user to */
3131*7c478bd9Sstevel@tonic-gate /* undo an undo */
3132*7c478bd9Sstevel@tonic-gate 
3133*7c478bd9Sstevel@tonic-gate 
3134*7c478bd9Sstevel@tonic-gate static void
3135*7c478bd9Sstevel@tonic-gate undo(void) {
3136*7c478bd9Sstevel@tonic-gate 	int j;
3137*7c478bd9Sstevel@tonic-gate 	long tmp;
3138*7c478bd9Sstevel@tonic-gate 	LINE i, tmpdot, tmpdol;
3139*7c478bd9Sstevel@tonic-gate 
3140*7c478bd9Sstevel@tonic-gate 	tmpdot = dot; dot = savdot; savdot = tmpdot;
3141*7c478bd9Sstevel@tonic-gate 	tmpdol = dol; dol = savdol; savdol = tmpdol;
3142*7c478bd9Sstevel@tonic-gate 	/* swap arrays using the greater of dol or savdol as upper limit */
3143*7c478bd9Sstevel@tonic-gate 	for (i = zero + 1; i <= ((dol > savdol) ? dol : savdol); i++) {
3144*7c478bd9Sstevel@tonic-gate 		tmp = i->cur;
3145*7c478bd9Sstevel@tonic-gate 		i->cur = i->sav;
3146*7c478bd9Sstevel@tonic-gate 		i->sav = tmp;
3147*7c478bd9Sstevel@tonic-gate 	}
3148*7c478bd9Sstevel@tonic-gate 		/*
3149*7c478bd9Sstevel@tonic-gate 		 * If the current text lines are swapped with the
3150*7c478bd9Sstevel@tonic-gate 		 * text lines in the save buffer, then swap the current
3151*7c478bd9Sstevel@tonic-gate 		 * marks with those in the save area.
3152*7c478bd9Sstevel@tonic-gate 		 */
3153*7c478bd9Sstevel@tonic-gate 
3154*7c478bd9Sstevel@tonic-gate 		for (j = 0; j <= 25; j++) {
3155*7c478bd9Sstevel@tonic-gate 			tmp = names[j];
3156*7c478bd9Sstevel@tonic-gate 			names[j] = savnames[j];
3157*7c478bd9Sstevel@tonic-gate 			savnames[j] = tmp;
3158*7c478bd9Sstevel@tonic-gate 		}
3159*7c478bd9Sstevel@tonic-gate }
3160*7c478bd9Sstevel@tonic-gate 
3161*7c478bd9Sstevel@tonic-gate static wchar_t
3162*7c478bd9Sstevel@tonic-gate get_wchr()
3163*7c478bd9Sstevel@tonic-gate {
3164*7c478bd9Sstevel@tonic-gate 	wchar_t	wc;
3165*7c478bd9Sstevel@tonic-gate 	char	multi[MB_LEN_MAX];
3166*7c478bd9Sstevel@tonic-gate 
3167*7c478bd9Sstevel@tonic-gate 	if (_mbftowc(multi, &wc, getchr, &peekc) <= 0)
3168*7c478bd9Sstevel@tonic-gate 		wc = getchr();
3169*7c478bd9Sstevel@tonic-gate 	return (wc);
3170*7c478bd9Sstevel@tonic-gate }
3171