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