xref: /onnv-gate/usr/src/cmd/vi/port/ex_unix.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 1995 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28*0Sstevel@tonic-gate /*	  All Rights Reserved  	*/
29*0Sstevel@tonic-gate 
30*0Sstevel@tonic-gate 
31*0Sstevel@tonic-gate /* Copyright (c) 1979 Regents of the University of California */
32*0Sstevel@tonic-gate 
33*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
34*0Sstevel@tonic-gate 
35*0Sstevel@tonic-gate #include "ex.h"
36*0Sstevel@tonic-gate #include "ex_temp.h"
37*0Sstevel@tonic-gate #include "ex_tty.h"
38*0Sstevel@tonic-gate #include "ex_vis.h"
39*0Sstevel@tonic-gate 
40*0Sstevel@tonic-gate extern char	getchar();
41*0Sstevel@tonic-gate /*
42*0Sstevel@tonic-gate  * Unix escapes, filtering
43*0Sstevel@tonic-gate  */
44*0Sstevel@tonic-gate 
45*0Sstevel@tonic-gate /*
46*0Sstevel@tonic-gate  * First part of a shell escape,
47*0Sstevel@tonic-gate  * parse the line, expanding # and % and ! and printing if implied.
48*0Sstevel@tonic-gate  */
49*0Sstevel@tonic-gate unix0(warn)
50*0Sstevel@tonic-gate 	bool warn;
51*0Sstevel@tonic-gate {
52*0Sstevel@tonic-gate 	register unsigned char *up, *fp;
53*0Sstevel@tonic-gate 	register short c;
54*0Sstevel@tonic-gate 	char	multic[MB_LEN_MAX + 1];
55*0Sstevel@tonic-gate 	int	len;
56*0Sstevel@tonic-gate 	wchar_t	wc;
57*0Sstevel@tonic-gate 	unsigned char printub, puxb[UXBSIZE + sizeof (int)];
58*0Sstevel@tonic-gate 
59*0Sstevel@tonic-gate 	printub = 0;
60*0Sstevel@tonic-gate 	CP(puxb, uxb);
61*0Sstevel@tonic-gate 	c = peekchar();
62*0Sstevel@tonic-gate 	if (c == '\n' || c == EOF) {
63*0Sstevel@tonic-gate 		(void) getchar();
64*0Sstevel@tonic-gate 		error(value(vi_TERSE) ?
65*0Sstevel@tonic-gate gettext("Incomplete shell escape command") :
66*0Sstevel@tonic-gate gettext("Incomplete shell escape command - use 'shell' to get a shell"));
67*0Sstevel@tonic-gate 	}
68*0Sstevel@tonic-gate 	up = (unsigned char *)uxb;
69*0Sstevel@tonic-gate 
70*0Sstevel@tonic-gate 	for (;;) {
71*0Sstevel@tonic-gate 		if (!isascii(c)) {
72*0Sstevel@tonic-gate 			if (c == EOF)
73*0Sstevel@tonic-gate 				break;
74*0Sstevel@tonic-gate 			if ((len = _mbftowc(multic, &wc, getchar, &peekc)) > 0) {
75*0Sstevel@tonic-gate 				if ((up + len) >= (unsigned char *)&uxb[UXBSIZE]) {
76*0Sstevel@tonic-gate 					uxb[0] = 0;
77*0Sstevel@tonic-gate 					error(gettext("Command too long"));
78*0Sstevel@tonic-gate 				}
79*0Sstevel@tonic-gate 				strncpy(up, multic, len);
80*0Sstevel@tonic-gate 				up += len;
81*0Sstevel@tonic-gate 				goto loop_check;
82*0Sstevel@tonic-gate 			}
83*0Sstevel@tonic-gate 		}
84*0Sstevel@tonic-gate 
85*0Sstevel@tonic-gate 		(void) getchar();
86*0Sstevel@tonic-gate 		switch (c) {
87*0Sstevel@tonic-gate 
88*0Sstevel@tonic-gate 		case '\\':
89*0Sstevel@tonic-gate 			if (any(peekchar(), "%#!"))
90*0Sstevel@tonic-gate 				c = getchar();
91*0Sstevel@tonic-gate 		default:
92*0Sstevel@tonic-gate 			if (up >= (unsigned char *)&uxb[UXBSIZE]) {
93*0Sstevel@tonic-gate tunix:
94*0Sstevel@tonic-gate 				uxb[0] = 0;
95*0Sstevel@tonic-gate 				error(gettext("Command too long"));
96*0Sstevel@tonic-gate 			}
97*0Sstevel@tonic-gate 			*up++ = c;
98*0Sstevel@tonic-gate 			break;
99*0Sstevel@tonic-gate 
100*0Sstevel@tonic-gate 		case '!':
101*0Sstevel@tonic-gate 			if (up != (unsigned char *)uxb && *puxb != 0) {
102*0Sstevel@tonic-gate 				fp = puxb;
103*0Sstevel@tonic-gate 				if (*fp == 0) {
104*0Sstevel@tonic-gate 					uxb[0] = 0;
105*0Sstevel@tonic-gate 					error(value(vi_TERSE) ?
106*0Sstevel@tonic-gate gettext("No previous command") :
107*0Sstevel@tonic-gate gettext("No previous command to substitute for !"));
108*0Sstevel@tonic-gate 				}
109*0Sstevel@tonic-gate 				printub++;
110*0Sstevel@tonic-gate 				while (*fp) {
111*0Sstevel@tonic-gate 					if (up >= (unsigned char *)&uxb[UXBSIZE])
112*0Sstevel@tonic-gate 						goto tunix;
113*0Sstevel@tonic-gate 					*up++ = *fp++;
114*0Sstevel@tonic-gate 				}
115*0Sstevel@tonic-gate 			} else if (up == (unsigned char *)uxb) {
116*0Sstevel@tonic-gate 				/* If up = uxb it means we are on the first
117*0Sstevel@tonic-gate 				 * character inside the shell command.
118*0Sstevel@tonic-gate 				 * (i.e., after the ":!")
119*0Sstevel@tonic-gate 				 *
120*0Sstevel@tonic-gate 				 * The user has just entered ":!!" which
121*0Sstevel@tonic-gate 				 * means that though there is only technically
122*0Sstevel@tonic-gate 				 * one '!' we know he really meant ":!!!". So
123*0Sstevel@tonic-gate 				 * substitute the last command for him.
124*0Sstevel@tonic-gate 				 */
125*0Sstevel@tonic-gate 				fp = puxb;
126*0Sstevel@tonic-gate 				if (*fp == 0) {
127*0Sstevel@tonic-gate 					uxb[0] = 0;
128*0Sstevel@tonic-gate 					error(value(vi_TERSE) ?
129*0Sstevel@tonic-gate gettext("No previous command") :
130*0Sstevel@tonic-gate gettext("No previous command to substitute for !"));
131*0Sstevel@tonic-gate 				}
132*0Sstevel@tonic-gate 				printub++;
133*0Sstevel@tonic-gate 				while (*fp) {
134*0Sstevel@tonic-gate 					if (up >= (unsigned char *)&uxb[UXBSIZE])
135*0Sstevel@tonic-gate 						goto tunix;
136*0Sstevel@tonic-gate 					*up++ = *fp++;
137*0Sstevel@tonic-gate 				}
138*0Sstevel@tonic-gate 			} else {
139*0Sstevel@tonic-gate 				/*
140*0Sstevel@tonic-gate 				 * Treat a lone "!" as just a regular character
141*0Sstevel@tonic-gate 				 * so commands like "mail machine!login" will
142*0Sstevel@tonic-gate 				 * work as usual (i.e., the user doesn't need
143*0Sstevel@tonic-gate 				 * to dereference the "!" with "\!").
144*0Sstevel@tonic-gate 				 */
145*0Sstevel@tonic-gate 				if (up >= (unsigned char *)&uxb[UXBSIZE]) {
146*0Sstevel@tonic-gate 					uxb[0] = 0;
147*0Sstevel@tonic-gate 					error(gettext("Command too long"));
148*0Sstevel@tonic-gate 				}
149*0Sstevel@tonic-gate 				*up++ = c;
150*0Sstevel@tonic-gate 			}
151*0Sstevel@tonic-gate 			break;
152*0Sstevel@tonic-gate 
153*0Sstevel@tonic-gate 		case '#':
154*0Sstevel@tonic-gate 			fp = (unsigned char *)altfile;
155*0Sstevel@tonic-gate 			if (*fp == 0) {
156*0Sstevel@tonic-gate 				uxb[0] = 0;
157*0Sstevel@tonic-gate 				error(value(vi_TERSE) ?
158*0Sstevel@tonic-gate gettext("No alternate filename") :
159*0Sstevel@tonic-gate gettext("No alternate filename to substitute for #"));
160*0Sstevel@tonic-gate 			}
161*0Sstevel@tonic-gate 			goto uexp;
162*0Sstevel@tonic-gate 
163*0Sstevel@tonic-gate 		case '%':
164*0Sstevel@tonic-gate 			fp = savedfile;
165*0Sstevel@tonic-gate 			if (*fp == 0) {
166*0Sstevel@tonic-gate 				uxb[0] = 0;
167*0Sstevel@tonic-gate 				error(value(vi_TERSE) ?
168*0Sstevel@tonic-gate gettext("No filename") :
169*0Sstevel@tonic-gate gettext("No filename to substitute for %%"));
170*0Sstevel@tonic-gate 			}
171*0Sstevel@tonic-gate uexp:
172*0Sstevel@tonic-gate 			printub++;
173*0Sstevel@tonic-gate 			while (*fp) {
174*0Sstevel@tonic-gate 				if (up >= (unsigned char *)&uxb[UXBSIZE])
175*0Sstevel@tonic-gate 					goto tunix;
176*0Sstevel@tonic-gate 				*up++ = *fp++;
177*0Sstevel@tonic-gate 			}
178*0Sstevel@tonic-gate 			break;
179*0Sstevel@tonic-gate 		}
180*0Sstevel@tonic-gate 
181*0Sstevel@tonic-gate loop_check:
182*0Sstevel@tonic-gate 		c = peekchar();
183*0Sstevel@tonic-gate 		if (c == '"' || c == '|' || !endcmd(c)) {
184*0Sstevel@tonic-gate 			continue;
185*0Sstevel@tonic-gate 		} else {
186*0Sstevel@tonic-gate 			(void) getchar();
187*0Sstevel@tonic-gate 			break;
188*0Sstevel@tonic-gate 		}
189*0Sstevel@tonic-gate 	}
190*0Sstevel@tonic-gate 	if (c == EOF)
191*0Sstevel@tonic-gate 		ungetchar(c);
192*0Sstevel@tonic-gate 	*up = 0;
193*0Sstevel@tonic-gate 	if (!inopen)
194*0Sstevel@tonic-gate 		resetflav();
195*0Sstevel@tonic-gate 	if (warn)
196*0Sstevel@tonic-gate 		ckaw();
197*0Sstevel@tonic-gate 	if (warn && hush == 0 && chng && xchng != chng && value(vi_WARN) && dol > zero) {
198*0Sstevel@tonic-gate 		xchng = chng;
199*0Sstevel@tonic-gate 		vnfl();
200*0Sstevel@tonic-gate 		printf(mesg(value(vi_TERSE) ? gettext("[No write]") :
201*0Sstevel@tonic-gate gettext("[No write since last change]")));
202*0Sstevel@tonic-gate 		noonl();
203*0Sstevel@tonic-gate 		flush();
204*0Sstevel@tonic-gate 	} else
205*0Sstevel@tonic-gate 		warn = 0;
206*0Sstevel@tonic-gate 	if (printub) {
207*0Sstevel@tonic-gate 		if (uxb[0] == 0)
208*0Sstevel@tonic-gate 			error(value(vi_TERSE) ? gettext("No previous command") :
209*0Sstevel@tonic-gate gettext("No previous command to repeat"));
210*0Sstevel@tonic-gate 		if (inopen) {
211*0Sstevel@tonic-gate 			splitw++;
212*0Sstevel@tonic-gate 			vclean();
213*0Sstevel@tonic-gate 			vgoto(WECHO, 0);
214*0Sstevel@tonic-gate 		}
215*0Sstevel@tonic-gate 		if (warn)
216*0Sstevel@tonic-gate 			vnfl();
217*0Sstevel@tonic-gate 		if (hush == 0)
218*0Sstevel@tonic-gate 			lprintf("!%s", uxb);
219*0Sstevel@tonic-gate 		if (inopen && Outchar != termchar) {
220*0Sstevel@tonic-gate 			vclreol();
221*0Sstevel@tonic-gate 			vgoto(WECHO, 0);
222*0Sstevel@tonic-gate 		} else
223*0Sstevel@tonic-gate 			putnl();
224*0Sstevel@tonic-gate 		flush();
225*0Sstevel@tonic-gate 	}
226*0Sstevel@tonic-gate }
227*0Sstevel@tonic-gate 
228*0Sstevel@tonic-gate /*
229*0Sstevel@tonic-gate  * Do the real work for execution of a shell escape.
230*0Sstevel@tonic-gate  * Mode is like the number passed to open system calls
231*0Sstevel@tonic-gate  * and indicates filtering.  If input is implied, newstdin
232*0Sstevel@tonic-gate  * must have been setup already.
233*0Sstevel@tonic-gate  */
234*0Sstevel@tonic-gate ttymode
235*0Sstevel@tonic-gate unixex(opt, up, newstdin, mode)
236*0Sstevel@tonic-gate 	unsigned char *opt, *up;
237*0Sstevel@tonic-gate 	int newstdin, mode;
238*0Sstevel@tonic-gate {
239*0Sstevel@tonic-gate 	int pvec[2];
240*0Sstevel@tonic-gate 	ttymode f;
241*0Sstevel@tonic-gate 
242*0Sstevel@tonic-gate 	signal(SIGINT, SIG_IGN);
243*0Sstevel@tonic-gate #ifdef SIGTSTP
244*0Sstevel@tonic-gate 	if (dosusp)
245*0Sstevel@tonic-gate 		signal(SIGTSTP, SIG_DFL);
246*0Sstevel@tonic-gate #endif
247*0Sstevel@tonic-gate 	if (inopen)
248*0Sstevel@tonic-gate 		f = setty(normf);
249*0Sstevel@tonic-gate 	if ((mode & 1) && pipe(pvec) < 0) {
250*0Sstevel@tonic-gate 		/* Newstdin should be io so it will be closed */
251*0Sstevel@tonic-gate 		if (inopen)
252*0Sstevel@tonic-gate 			setty(f);
253*0Sstevel@tonic-gate 		error(gettext("Can't make pipe for filter"));
254*0Sstevel@tonic-gate 	}
255*0Sstevel@tonic-gate #ifndef VFORK
256*0Sstevel@tonic-gate 	pid = fork();
257*0Sstevel@tonic-gate #else
258*0Sstevel@tonic-gate 	pid = vfork();
259*0Sstevel@tonic-gate #endif
260*0Sstevel@tonic-gate 	if (pid < 0) {
261*0Sstevel@tonic-gate 		if (mode & 1) {
262*0Sstevel@tonic-gate 			close(pvec[0]);
263*0Sstevel@tonic-gate 			close(pvec[1]);
264*0Sstevel@tonic-gate 		}
265*0Sstevel@tonic-gate 		setrupt();
266*0Sstevel@tonic-gate 		if (inopen)
267*0Sstevel@tonic-gate 			setty(f);
268*0Sstevel@tonic-gate 		error(gettext("No more processes"));
269*0Sstevel@tonic-gate 	}
270*0Sstevel@tonic-gate 	if (pid == 0) {
271*0Sstevel@tonic-gate 		if (mode & 2) {
272*0Sstevel@tonic-gate 			close(0);
273*0Sstevel@tonic-gate 			dup(newstdin);
274*0Sstevel@tonic-gate 			close(newstdin);
275*0Sstevel@tonic-gate 		}
276*0Sstevel@tonic-gate 		if (mode & 1) {
277*0Sstevel@tonic-gate 			close(pvec[0]);
278*0Sstevel@tonic-gate 			close(1);
279*0Sstevel@tonic-gate 			dup(pvec[1]);
280*0Sstevel@tonic-gate 			if (inopen) {
281*0Sstevel@tonic-gate 				close(2);
282*0Sstevel@tonic-gate 				dup(1);
283*0Sstevel@tonic-gate 			}
284*0Sstevel@tonic-gate 			close(pvec[1]);
285*0Sstevel@tonic-gate 		}
286*0Sstevel@tonic-gate 		if (io)
287*0Sstevel@tonic-gate 			close(io);
288*0Sstevel@tonic-gate 		if (tfile)
289*0Sstevel@tonic-gate 			close(tfile);
290*0Sstevel@tonic-gate 		signal(SIGHUP, oldhup);
291*0Sstevel@tonic-gate 		signal(SIGQUIT, oldquit);
292*0Sstevel@tonic-gate 		if (ruptible)
293*0Sstevel@tonic-gate 			signal(SIGINT, SIG_DFL);
294*0Sstevel@tonic-gate 	 	execlp(svalue(vi_SHELL), svalue(vi_SHELL), opt, up, (char *) 0);
295*0Sstevel@tonic-gate 		printf(gettext("Invalid SHELL value: %s\n"), svalue(vi_SHELL));
296*0Sstevel@tonic-gate 		flush();
297*0Sstevel@tonic-gate 		error(NOSTR);
298*0Sstevel@tonic-gate 	}
299*0Sstevel@tonic-gate 	if (mode & 1) {
300*0Sstevel@tonic-gate 		io = pvec[0];
301*0Sstevel@tonic-gate 		close(pvec[1]);
302*0Sstevel@tonic-gate 	}
303*0Sstevel@tonic-gate 	if (newstdin)
304*0Sstevel@tonic-gate 		close(newstdin);
305*0Sstevel@tonic-gate 	return (f);
306*0Sstevel@tonic-gate }
307*0Sstevel@tonic-gate 
308*0Sstevel@tonic-gate /*
309*0Sstevel@tonic-gate  * Wait for the command to complete.
310*0Sstevel@tonic-gate  * F is for restoration of tty mode if from open/visual.
311*0Sstevel@tonic-gate  * C flags suppression of printing.
312*0Sstevel@tonic-gate  */
313*0Sstevel@tonic-gate unixwt(c, f)
314*0Sstevel@tonic-gate 	bool c;
315*0Sstevel@tonic-gate 	ttymode f;
316*0Sstevel@tonic-gate {
317*0Sstevel@tonic-gate 
318*0Sstevel@tonic-gate 	waitfor();
319*0Sstevel@tonic-gate #ifdef SIGTSTP
320*0Sstevel@tonic-gate 	if (dosusp)
321*0Sstevel@tonic-gate 		signal(SIGTSTP, onsusp);
322*0Sstevel@tonic-gate #endif
323*0Sstevel@tonic-gate 	if (inopen)
324*0Sstevel@tonic-gate 		setty(f);
325*0Sstevel@tonic-gate 	setrupt();
326*0Sstevel@tonic-gate 	if (!inopen && c && hush == 0) {
327*0Sstevel@tonic-gate 		printf("!\n");
328*0Sstevel@tonic-gate 		flush();
329*0Sstevel@tonic-gate 		termreset();
330*0Sstevel@tonic-gate 		gettmode();
331*0Sstevel@tonic-gate 	}
332*0Sstevel@tonic-gate }
333*0Sstevel@tonic-gate 
334*0Sstevel@tonic-gate /*
335*0Sstevel@tonic-gate  * Setup a pipeline for the filtration implied by mode
336*0Sstevel@tonic-gate  * which is like a open number.  If input is required to
337*0Sstevel@tonic-gate  * the filter, then a child editor is created to write it.
338*0Sstevel@tonic-gate  * If output is catch it from io which is created by unixex.
339*0Sstevel@tonic-gate  */
340*0Sstevel@tonic-gate vi_filter(mode)
341*0Sstevel@tonic-gate 	register int mode;
342*0Sstevel@tonic-gate {
343*0Sstevel@tonic-gate 	static int pvec[2];
344*0Sstevel@tonic-gate 	ttymode f;	/* was register */
345*0Sstevel@tonic-gate 	register int nlines = lineDOL();
346*0Sstevel@tonic-gate 	int status2;
347*0Sstevel@tonic-gate 	pid_t pid2 = 0;
348*0Sstevel@tonic-gate 
349*0Sstevel@tonic-gate 	mode++;
350*0Sstevel@tonic-gate 	if (mode & 2) {
351*0Sstevel@tonic-gate 		signal(SIGINT, SIG_IGN);
352*0Sstevel@tonic-gate 		signal(SIGPIPE, SIG_IGN);
353*0Sstevel@tonic-gate 		if (pipe(pvec) < 0)
354*0Sstevel@tonic-gate 			error(gettext("Can't make pipe"));
355*0Sstevel@tonic-gate 		pid2 = fork();
356*0Sstevel@tonic-gate 		io = pvec[0];
357*0Sstevel@tonic-gate 		if (pid < 0) {
358*0Sstevel@tonic-gate 			setrupt();
359*0Sstevel@tonic-gate 			close(pvec[1]);
360*0Sstevel@tonic-gate 			error(gettext("No more processes"));
361*0Sstevel@tonic-gate 		}
362*0Sstevel@tonic-gate 		if (pid2 == 0) {
363*0Sstevel@tonic-gate 			extern unsigned char tfname[];
364*0Sstevel@tonic-gate 			setrupt();
365*0Sstevel@tonic-gate 			io = pvec[1];
366*0Sstevel@tonic-gate 			close(pvec[0]);
367*0Sstevel@tonic-gate 
368*0Sstevel@tonic-gate 			/* To prevent seeking in this process and the
369*0Sstevel@tonic-gate 				 parent, we must reopen tfile here */
370*0Sstevel@tonic-gate 			close(tfile);
371*0Sstevel@tonic-gate 			tfile = open(tfname, 2);
372*0Sstevel@tonic-gate 
373*0Sstevel@tonic-gate 			putfile(1);
374*0Sstevel@tonic-gate 			exit(errcnt);
375*0Sstevel@tonic-gate 		}
376*0Sstevel@tonic-gate 		close(pvec[1]);
377*0Sstevel@tonic-gate 		io = pvec[0];
378*0Sstevel@tonic-gate 		setrupt();
379*0Sstevel@tonic-gate 	}
380*0Sstevel@tonic-gate 	f = unixex("-c", uxb, (mode & 2) ? pvec[0] : 0, mode);
381*0Sstevel@tonic-gate 	if (mode == 3) {
382*0Sstevel@tonic-gate 		delete(0);
383*0Sstevel@tonic-gate 		addr2 = addr1 - 1;
384*0Sstevel@tonic-gate 	}
385*0Sstevel@tonic-gate 	if (mode == 1)
386*0Sstevel@tonic-gate 		deletenone();
387*0Sstevel@tonic-gate 	if (mode & 1) {
388*0Sstevel@tonic-gate 		if(FIXUNDO)
389*0Sstevel@tonic-gate 			undap1 = undap2 = addr2+1;
390*0Sstevel@tonic-gate 		(void)append(getfile, addr2);
391*0Sstevel@tonic-gate #ifdef UNDOTRACE
392*0Sstevel@tonic-gate 		if (trace)
393*0Sstevel@tonic-gate 			vudump(gettext("after append in filter"));
394*0Sstevel@tonic-gate #endif
395*0Sstevel@tonic-gate 	}
396*0Sstevel@tonic-gate 	close(io);
397*0Sstevel@tonic-gate 	io = -1;
398*0Sstevel@tonic-gate 	unixwt(!inopen, f);
399*0Sstevel@tonic-gate 	if (pid2) {
400*0Sstevel@tonic-gate 		(void)kill(pid2, 9);
401*0Sstevel@tonic-gate 		do
402*0Sstevel@tonic-gate 			rpid = waitpid(pid2, &status2, 0);
403*0Sstevel@tonic-gate 		while (rpid == (pid_t)-1 && errno == EINTR);
404*0Sstevel@tonic-gate 	}
405*0Sstevel@tonic-gate 	netchHAD(nlines);
406*0Sstevel@tonic-gate }
407*0Sstevel@tonic-gate 
408*0Sstevel@tonic-gate /*
409*0Sstevel@tonic-gate  * Set up to do a recover, getting io to be a pipe from
410*0Sstevel@tonic-gate  * the recover process.
411*0Sstevel@tonic-gate  */
412*0Sstevel@tonic-gate recover()
413*0Sstevel@tonic-gate {
414*0Sstevel@tonic-gate 	static int pvec[2];
415*0Sstevel@tonic-gate 
416*0Sstevel@tonic-gate 	if (pipe(pvec) < 0)
417*0Sstevel@tonic-gate 		error(gettext(" Can't make pipe for recovery"));
418*0Sstevel@tonic-gate 	pid = fork();
419*0Sstevel@tonic-gate 	io = pvec[0];
420*0Sstevel@tonic-gate 	if (pid < 0) {
421*0Sstevel@tonic-gate 		close(pvec[1]);
422*0Sstevel@tonic-gate 		error(gettext(" Can't fork to execute recovery"));
423*0Sstevel@tonic-gate 	}
424*0Sstevel@tonic-gate 	if (pid == 0) {
425*0Sstevel@tonic-gate 		unsigned char cryptkey[19];
426*0Sstevel@tonic-gate 		close(2);
427*0Sstevel@tonic-gate 		dup(1);
428*0Sstevel@tonic-gate 		close(1);
429*0Sstevel@tonic-gate 		dup(pvec[1]);
430*0Sstevel@tonic-gate 	        close(pvec[1]);
431*0Sstevel@tonic-gate 		if(xflag) {
432*0Sstevel@tonic-gate 			strcpy(cryptkey, "CrYpTkEy=XXXXXXXXX");
433*0Sstevel@tonic-gate 			strcpy(cryptkey + 9, key);
434*0Sstevel@tonic-gate 			if(putenv((char *)cryptkey) != 0)
435*0Sstevel@tonic-gate 				smerror(gettext(" Cannot copy key to environment"));
436*0Sstevel@tonic-gate 			execlp(EXRECOVER, "exrecover", "-x", svalue(vi_DIRECTORY), file, (char *) 0);
437*0Sstevel@tonic-gate 		} else
438*0Sstevel@tonic-gate 			execlp(EXRECOVER, "exrecover", svalue(vi_DIRECTORY), file, (char *) 0);
439*0Sstevel@tonic-gate 		close(1);
440*0Sstevel@tonic-gate 		dup(2);
441*0Sstevel@tonic-gate 		error(gettext(" No recovery routine"));
442*0Sstevel@tonic-gate 	}
443*0Sstevel@tonic-gate 	close(pvec[1]);
444*0Sstevel@tonic-gate }
445*0Sstevel@tonic-gate 
446*0Sstevel@tonic-gate /*
447*0Sstevel@tonic-gate  * Wait for the process (pid an external) to complete.
448*0Sstevel@tonic-gate  */
449*0Sstevel@tonic-gate waitfor()
450*0Sstevel@tonic-gate {
451*0Sstevel@tonic-gate 
452*0Sstevel@tonic-gate 	do
453*0Sstevel@tonic-gate 		rpid = waitpid(pid, &status, 0);
454*0Sstevel@tonic-gate 	while (rpid == (pid_t)-1 && errno != ECHILD);
455*0Sstevel@tonic-gate 	if ((status & 0377) == 0)
456*0Sstevel@tonic-gate 		status = (status >> 8) & 0377;
457*0Sstevel@tonic-gate 	else {
458*0Sstevel@tonic-gate 		/*
459*0Sstevel@tonic-gate 		 * TRANSLATION_NOTE
460*0Sstevel@tonic-gate 		 *	Reference order of arguments must not
461*0Sstevel@tonic-gate 		 *	be changed using '%digit$', since vi's
462*0Sstevel@tonic-gate 		 *	printf() does not support it.
463*0Sstevel@tonic-gate 		 */
464*0Sstevel@tonic-gate 		printf(gettext("%d: terminated with signal %d"), pid, status & 0177);
465*0Sstevel@tonic-gate 		if (status & 0200)
466*0Sstevel@tonic-gate 			printf(gettext(" -- core dumped"));
467*0Sstevel@tonic-gate 		putchar('\n');
468*0Sstevel@tonic-gate 	}
469*0Sstevel@tonic-gate }
470*0Sstevel@tonic-gate 
471*0Sstevel@tonic-gate /*
472*0Sstevel@tonic-gate  * The end of a recover operation.  If the process
473*0Sstevel@tonic-gate  * exits non-zero, force not edited; otherwise force
474*0Sstevel@tonic-gate  * a write.
475*0Sstevel@tonic-gate  */
476*0Sstevel@tonic-gate revocer()
477*0Sstevel@tonic-gate {
478*0Sstevel@tonic-gate 
479*0Sstevel@tonic-gate 	waitfor();
480*0Sstevel@tonic-gate 	if (pid == rpid && status != 0)
481*0Sstevel@tonic-gate 		edited = 0;
482*0Sstevel@tonic-gate 	else
483*0Sstevel@tonic-gate 		change();
484*0Sstevel@tonic-gate }
485