Subversion Repositories planix.SVN

Rev

Rev 107 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
105 7u83 1
/*
2
 * Copyright (c) 1980 Regents of the University of California.
3
 * All rights reserved.  The Berkeley software License Agreement
4
 * specifies the terms and conditions for redistribution.
5
 */
6
 
7
#if	!defined(lint) && defined(DOSCCS)
8
static char *sccsid = "@(#)ex_unix.c	7.6 (Berkeley) 10/22/85";
9
#endif
10
 
11
#include "ex.h"
12
#include "ex_temp.h"
13
#include "ex_tty.h"
14
#include "ex_vis.h"
15
 
16
/*
17
 * Unix escapes, filtering
18
 */
19
 
20
/*
21
 * First part of a shell escape,
22
 * parse the line, expanding # and % and ! and printing if implied.
23
 */
24
unix0(warn)
25
	bool warn;
26
{
27
	register char *up, *fp;
28
	register short c;
29
	char printub, puxb[UXBSIZE + sizeof (int)];
30
 
31
	printub = 0;
113 7u83 32
	strcpy(puxb, uxb);
105 7u83 33
	c = getchar();
34
	if (c == '\n' || c == EOF)
35
		error("Incomplete shell escape command@- use 'shell' to get a shell");
36
	up = uxb;
37
	do {
38
		switch (c) {
39
 
40
		case '\\':
41
			if (any(peekchar(), "%#!"))
42
				c = getchar();
43
		default:
44
			if (up >= &uxb[UXBSIZE]) {
45
tunix:
46
				uxb[0] = 0;
47
				error("Command too long");
48
			}
49
			*up++ = c;
50
			break;
51
 
52
		case '!':
53
			fp = puxb;
54
			if (*fp == 0) {
55
				uxb[0] = 0;
56
				error("No previous command@to substitute for !");
57
			}
58
			printub++;
59
			while (*fp) {
60
				if (up >= &uxb[UXBSIZE])
61
					goto tunix;
62
				*up++ = *fp++;
63
			}
64
			break;
65
 
66
		case '#':
67
			fp = altfile;
68
			if (*fp == 0) {
69
				uxb[0] = 0;
70
				error("No alternate filename@to substitute for #");
71
			}
72
			goto uexp;
73
 
74
		case '%':
75
			fp = savedfile;
76
			if (*fp == 0) {
77
				uxb[0] = 0;
78
				error("No filename@to substitute for %%");
79
			}
80
uexp:
81
			printub++;
82
			while (*fp) {
83
				if (up >= &uxb[UXBSIZE])
84
					goto tunix;
85
#ifdef	BIT8
86
				/* XXX */ /* GR */
87
				abort();
88
#endif
89
				*up++ = *fp++ | QUOTE;
90
			}
91
			break;
92
		}
93
		c = getchar();
94
	} while (c == '"' || c == '|' || !endcmd(c));
95
	if (c == EOF)
96
		ungetchar(c);
97
	*up = 0;
98
	if (!inopen)
99
		resetflav();
100
	if (warn)
101
		ckaw();
102
	if (warn && hush == 0 && chng && xchng != chng && value(WARN) && dol > zero) {
103
		xchng = chng;
104
		vnfl();
105
		printf(mesg("[No write]|[No write since last change]"));
106
		noonl();
107
		flush();
108
	} else
109
		warn = 0;
110
	if (printub) {
111
		if (uxb[0] == 0)
112
			error("No previous command@to repeat");
113
		if (inopen) {
114
			splitw++;
115
			vclean();
116
			vgoto(WECHO, 0);
117
		}
118
		if (warn)
119
			vnfl();
120
		if (hush == 0)
121
			lprintf("!%s", uxb);
122
		if (inopen && Outchar != termchar) {
123
			vclreol();
124
			vgoto(WECHO, 0);
125
		} else
126
			putnl();
127
		flush();
128
	}
129
}
130
 
131
/*
132
 * Do the real work for execution of a shell escape.
133
 * Mode is like the number passed to open system calls
134
 * and indicates filtering.  If input is implied, newstdin
135
 * must have been setup already.
136
 */
137
ttymode
138
unixex(opt, up, newstdin, mode)
139
	char *opt, *up;
140
	int newstdin, mode;
141
{
142
	int pvec[2];
143
	ttymode f;
144
 
145
	signal(SIGINT, SIG_IGN);
146
#ifdef SIGTSTP
147
	if (dosusp)
148
		signal(SIGTSTP, SIG_DFL);
149
#endif
150
	if (inopen)
151
		f = setty(normf);
152
	if ((mode & 1) && pipe(pvec) < 0) {
153
		/* Newstdin should be io so it will be closed */
154
		if (inopen)
155
			setty(f);
156
		error("Can't make pipe for filter");
157
	}
158
#ifndef VFORK
159
	pid = fork();
160
#else
161
	pid = vfork();
162
#endif
163
	if (pid < 0) {
164
		if (mode & 1) {
165
			close(pvec[0]);
166
			close(pvec[1]);
167
		}
168
		setrupt();
169
		error("No more processes");
170
	}
171
	if (pid == 0) {
172
		if (mode & 2) {
173
			close(0);
174
			dup(newstdin);
175
			close(newstdin);
176
		}
177
		if (mode & 1) {
178
			close(pvec[0]);
179
			close(1);
180
			dup(pvec[1]);
181
			if (inopen) {
182
				close(2);
183
				dup(1);
184
			}
185
			close(pvec[1]);
186
		}
187
		if (io)
188
			close(io);
189
		if (tfile)
190
			close(tfile);
191
#ifndef VMUNIX
192
		close(erfile);
193
#endif
194
		signal(SIGHUP, oldhup);
195
		signal(SIGQUIT, oldquit);
196
		if (ruptible)
197
			signal(SIGINT, SIG_DFL);
198
		execl(svalue(SHELL), "sh", opt, up, (char *) 0);
199
		printf("No %s!\n", svalue(SHELL));
200
		error(NOSTR);
201
	}
202
	if (mode & 1) {
203
		io = pvec[0];
204
		close(pvec[1]);
205
	}
206
	if (newstdin)
207
		close(newstdin);
208
	return (f);
209
}
210
 
211
/*
212
 * Wait for the command to complete.
213
 * F is for restoration of tty mode if from open/visual.
214
 * C flags suppression of printing.
215
 */
216
unixwt(c, f)
217
	bool c;
218
	ttymode f;
219
{
220
 
221
	waitfor();
222
#ifdef SIGTSTP
223
	if (dosusp)
224
		signal(SIGTSTP, onsusp);
225
#endif
226
	if (inopen)
227
		setty(f);
228
	setrupt();
229
	if (!inopen && c && hush == 0) {
230
		printf("!\n");
231
		flush();
232
		termreset();
233
		gettmode();
234
	}
235
}
236
 
237
/*
238
 * Setup a pipeline for the filtration implied by mode
239
 * which is like a open number.  If input is required to
240
 * the filter, then a child editor is created to write it.
241
 * If output is catch it from io which is created by unixex.
242
 */
243
filter(mode)
244
	register int mode;
245
{
246
	static int pvec[2];
247
	ttymode f;	/* mjm: was register */
248
	register int lines = lineDOL();
249
	struct stat statb;
250
 
251
	mode++;
252
	if (mode & 2) {
253
		signal(SIGINT, SIG_IGN);
254
		if (pipe(pvec) < 0)
255
			error("Can't make pipe");
256
		pid = fork();
257
		io = pvec[0];
258
		if (pid < 0) {
259
			setrupt();
260
			close(pvec[1]);
261
			error("No more processes");
262
		}
263
		if (pid == 0) {
264
			setrupt();
265
			io = pvec[1];
266
			close(pvec[0]);
267
			putfile(1);
268
			exit(0);
269
		}
270
		close(pvec[1]);
271
		io = pvec[0];
272
		setrupt();
273
	}
274
	f = unixex("-c", uxb, (mode & 2) ? pvec[0] : 0, mode);
275
	if (mode == 3) {
276
		delete(0);
277
		addr2 = addr1 - 1;
278
	}
279
	if (mode & 1) {
280
		if(FIXUNDO)
281
			undap1 = undap2 = addr2+1;
107 7u83 282
/* XXX		if (fstat(io, &statb) < 0)
105 7u83 283
			bsize = LBSIZE;
284
		else {
285
			bsize = statb.st_blksize;
286
			if (bsize <= 0)
287
				bsize = LBSIZE;
288
		}
107 7u83 289
*/		
290
		bsize = LBSIZE;
291
 
105 7u83 292
		ignore(append(getfile, addr2));
293
#ifdef TRACE
294
		if (trace)
295
			vudump("after append in filter");
296
#endif
297
	}
298
	close(io);
299
	io = -1;
300
	unixwt(!inopen, f);
301
	netchHAD(lines);
302
}
303
 
304
/*
305
 * Set up to do a recover, getting io to be a pipe from
306
 * the recover process.
307
 */
308
recover()
309
{
310
	static int pvec[2];
311
 
312
	if (pipe(pvec) < 0)
313
		error(" Can't make pipe for recovery");
314
	pid = fork();
315
	io = pvec[0];
316
	if (pid < 0) {
317
		close(pvec[1]);
318
		error(" Can't fork to execute recovery");
319
	}
320
	if (pid == 0) {
321
		close(2);
322
		dup(1);
323
		close(1);
324
		dup(pvec[1]);
325
	        close(pvec[1]);
326
		execl(EXRECOVER, "exrecover", svalue(DIRECTORY), file, (char *) 0);
327
		close(1);
328
		dup(2);
329
		error(" No recovery routine");
330
	}
331
	close(pvec[1]);
332
}
333
 
334
/*
335
 * Wait for the process (pid an external) to complete.
336
 */
337
waitfor()
338
{
339
	int stat = 0;
340
 
341
	do {
342
		rpid = wait(&stat);
343
		if (rpid == pid)
344
			status = stat;
345
	} while (rpid != -1);
346
	status = (status >> 8) & 0377;
347
}
348
 
349
/*
350
 * The end of a recover operation.  If the process
351
 * exits non-zero, force not edited; otherwise force
352
 * a write.
353
 */
354
revocer()
355
{
356
 
357
	waitfor();
358
	if (pid == rpid && status != 0)
359
		edited = 0;
360
	else
361
		change();
362
}