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