|
|
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.6 (Berkeley) 10/22/85";
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:
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;
32: CP(puxb, uxb);
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: *up++ = *fp++ | QUOTE;
86: }
87: break;
88: }
89: c = getchar();
90: } while (c == '"' || c == '|' || !endcmd(c));
91: if (c == EOF)
92: ungetchar(c);
93: *up = 0;
94: if (!inopen)
95: resetflav();
96: if (warn)
97: ckaw();
98: if (warn && hush == 0 && chng && xchng != chng && value(WARN) && dol > zero) {
99: xchng = chng;
100: vnfl();
101: printf(mesg("[No write]|[No write since last change]"));
102: noonl();
103: flush();
104: } else
105: warn = 0;
106: if (printub) {
107: if (uxb[0] == 0)
108: error("No previous command@to repeat");
109: if (inopen) {
110: splitw++;
111: vclean();
112: vgoto(WECHO, 0);
113: }
114: if (warn)
115: vnfl();
116: if (hush == 0)
117: lprintf("!%s", uxb);
118: if (inopen && Outchar != termchar) {
119: vclreol();
120: vgoto(WECHO, 0);
121: } else
122: putnl();
123: flush();
124: }
125: }
126:
127: /*
128: * Do the real work for execution of a shell escape.
129: * Mode is like the number passed to open system calls
130: * and indicates filtering. If input is implied, newstdin
131: * must have been setup already.
132: */
133: ttymode
134: unixex(opt, up, newstdin, mode)
135: char *opt, *up;
136: int newstdin, mode;
137: {
138: int pvec[2];
139: ttymode f;
140:
141: signal(SIGINT, SIG_IGN);
142: #ifdef SIGTSTP
143: if (dosusp)
144: signal(SIGTSTP, SIG_DFL);
145: #endif
146: if (inopen)
147: f = setty(normf);
148: if ((mode & 1) && pipe(pvec) < 0) {
149: /* Newstdin should be io so it will be closed */
150: if (inopen)
151: setty(f);
152: error("Can't make pipe for filter");
153: }
154: #ifndef VFORK
155: pid = fork();
156: #else
157: pid = vfork();
158: #endif
159: if (pid < 0) {
160: if (mode & 1) {
161: close(pvec[0]);
162: close(pvec[1]);
163: }
164: setrupt();
165: error("No more processes");
166: }
167: if (pid == 0) {
168: if (mode & 2) {
169: close(0);
170: dup(newstdin);
171: close(newstdin);
172: }
173: if (mode & 1) {
174: close(pvec[0]);
175: close(1);
176: dup(pvec[1]);
177: if (inopen) {
178: close(2);
179: dup(1);
180: }
181: close(pvec[1]);
182: }
183: if (io)
184: close(io);
185: if (tfile)
186: close(tfile);
187: #ifndef VMUNIX
188: close(erfile);
189: #endif
190: signal(SIGHUP, oldhup);
191: signal(SIGQUIT, oldquit);
192: if (ruptible)
193: signal(SIGINT, SIG_DFL);
194: execl(svalue(SHELL), "sh", opt, up, (char *) 0);
195: printf("No %s!\n", svalue(SHELL));
196: error(NOSTR);
197: }
198: if (mode & 1) {
199: io = pvec[0];
200: close(pvec[1]);
201: }
202: if (newstdin)
203: close(newstdin);
204: return (f);
205: }
206:
207: /*
208: * Wait for the command to complete.
209: * F is for restoration of tty mode if from open/visual.
210: * C flags suppression of printing.
211: */
212: unixwt(c, f)
213: bool c;
214: ttymode f;
215: {
216:
217: waitfor();
218: #ifdef SIGTSTP
219: if (dosusp)
220: signal(SIGTSTP, onsusp);
221: #endif
222: if (inopen)
223: setty(f);
224: setrupt();
225: if (!inopen && c && hush == 0) {
226: printf("!\n");
227: flush();
228: termreset();
229: gettmode();
230: }
231: }
232:
233: /*
234: * Setup a pipeline for the filtration implied by mode
235: * which is like a open number. If input is required to
236: * the filter, then a child editor is created to write it.
237: * If output is catch it from io which is created by unixex.
238: */
239: filter(mode)
240: register int mode;
241: {
242: static int pvec[2];
243: ttymode f; /* mjm: was register */
244: register int lines = lineDOL();
245: struct stat statb;
246:
247: mode++;
248: if (mode & 2) {
249: signal(SIGINT, SIG_IGN);
250: if (pipe(pvec) < 0)
251: error("Can't make pipe");
252: pid = fork();
253: io = pvec[0];
254: if (pid < 0) {
255: setrupt();
256: close(pvec[1]);
257: error("No more processes");
258: }
259: if (pid == 0) {
260: setrupt();
261: io = pvec[1];
262: close(pvec[0]);
263: putfile(1);
264: exit(0);
265: }
266: close(pvec[1]);
267: io = pvec[0];
268: setrupt();
269: }
270: f = unixex("-c", uxb, (mode & 2) ? pvec[0] : 0, mode);
271: if (mode == 3) {
272: delete(0);
273: addr2 = addr1 - 1;
274: }
275: if (mode & 1) {
276: if(FIXUNDO)
277: undap1 = undap2 = addr2+1;
278: if (fstat(io, &statb) < 0)
279: bsize = LBSIZE;
280: else {
281: bsize = statb.st_blksize;
282: if (bsize <= 0)
283: bsize = LBSIZE;
284: }
285: ignore(append(getfile, addr2));
286: #ifdef TRACE
287: if (trace)
288: vudump("after append in filter");
289: #endif
290: }
291: close(io);
292: io = -1;
293: unixwt(!inopen, f);
294: netchHAD(lines);
295: }
296:
297: /*
298: * Set up to do a recover, getting io to be a pipe from
299: * the recover process.
300: */
301: recover()
302: {
303: static int pvec[2];
304:
305: if (pipe(pvec) < 0)
306: error(" Can't make pipe for recovery");
307: pid = fork();
308: io = pvec[0];
309: if (pid < 0) {
310: close(pvec[1]);
311: error(" Can't fork to execute recovery");
312: }
313: if (pid == 0) {
314: close(2);
315: dup(1);
316: close(1);
317: dup(pvec[1]);
318: close(pvec[1]);
319: execl(EXRECOVER, "exrecover", svalue(DIRECTORY), file, (char *) 0);
320: close(1);
321: dup(2);
322: error(" No recovery routine");
323: }
324: close(pvec[1]);
325: }
326:
327: /*
328: * Wait for the process (pid an external) to complete.
329: */
330: waitfor()
331: {
332: int stat = 0;
333:
334: do {
335: rpid = wait(&stat);
336: if (rpid == pid)
337: status = stat;
338: } while (rpid != -1);
339: status = (status >> 8) & 0377;
340: }
341:
342: /*
343: * The end of a recover operation. If the process
344: * exits non-zero, force not edited; otherwise force
345: * a write.
346: */
347: revocer()
348: {
349:
350: waitfor();
351: if (pid == rpid && status != 0)
352: edited = 0;
353: else
354: change();
355: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.