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