added sccs, Bill put in more buffers
[unix-history] / usr / src / usr.bin / ex / ex_unix.c
CommitLineData
9cf6814f
MH
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 */
15unix0(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]) {
36tunix:
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 }
71uexp:
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 */
124ttymode
125unixex(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#ifdef TIOCLGET
134 if (dosusp)
135 signal(SIGTSTP, SIG_DFL);
136#endif
137 if (inopen)
138 f = setty(normf);
139 if ((mode & 1) && pipe(pvec) < 0) {
140 /* Newstdin should be io so it will be closed */
141 if (inopen)
142 setty(f);
143 error("Can't make pipe for filter");
144 }
145#ifndef VFORK
146 pid = fork();
147#else
148 pid = vfork();
149#endif
150 if (pid < 0) {
151 if (mode & 1) {
152 close(pvec[0]);
153 close(pvec[1]);
154 }
155 setrupt();
156 error("No more processes");
157 }
158 if (pid == 0) {
159 if (mode & 2) {
160 close(0);
161 dup(newstdin);
162 close(newstdin);
163 }
164 if (mode & 1) {
165 close(pvec[0]);
166 close(1);
167 dup(pvec[1]);
168 if (inopen) {
169 close(2);
170 dup(1);
171 }
172 close(pvec[1]);
173 }
174 if (io)
175 close(io);
176 if (tfile)
177 close(tfile);
178#ifndef VMUNIX
179 close(erfile);
180#endif
181 signal(SIGHUP, oldhup);
182 signal(SIGQUIT, oldquit);
183 if (ruptible)
184 signal(SIGINT, SIG_DFL);
185 execl(svalue(SHELL), "sh", opt, up, (char *) 0);
186 printf("No %s!\n", svalue(SHELL));
187 error(NOSTR);
188 }
189 if (mode & 1) {
190 io = pvec[0];
191 close(pvec[1]);
192 }
193 if (newstdin)
194 close(newstdin);
195 return (f);
196}
197
198/*
199 * Wait for the command to complete.
200 * F is for restoration of tty mode if from open/visual.
201 * C flags suppression of printing.
202 */
203unixwt(c, f)
204 bool c;
205 ttymode f;
206{
207
208 waitfor();
209#ifdef TIOCLGET
210 if (dosusp)
211 signal(SIGTSTP, onsusp);
212#endif
213 if (inopen)
214 setty(f);
215 setrupt();
216 if (!inopen && c && hush == 0) {
217 printf("!\n");
218 flush();
219 termreset();
220 gettmode();
221 }
222}
223
224/*
225 * Setup a pipeline for the filtration implied by mode
226 * which is like a open number. If input is required to
227 * the filter, then a child editor is created to write it.
228 * If output is catch it from io which is created by unixex.
229 */
230filter(mode)
231 register int mode;
232{
233 static int pvec[2];
234 register ttymode f;
235 register int lines = lineDOL();
236
237 mode++;
238 if (mode & 2) {
239 signal(SIGINT, SIG_IGN);
240 if (pipe(pvec) < 0)
241 error("Can't make pipe");
242 pid = fork();
243 io = pvec[0];
244 if (pid < 0) {
245 setrupt();
246 close(pvec[1]);
247 error("No more processes");
248 }
249 if (pid == 0) {
250 setrupt();
251 io = pvec[1];
252 close(pvec[0]);
253 putfile();
254 exit(0);
255 }
256 close(pvec[1]);
257 io = pvec[0];
258 setrupt();
259 }
260 f = unixex("-c", uxb, (mode & 2) ? pvec[0] : 0, mode);
261 if (mode == 3) {
262 delete(0);
263 addr2 = addr1 - 1;
264 }
265 if (mode & 1) {
266 if(FIXUNDO)
267 undap1 = undap2 = addr2+1;
268 ignore(append(getfile, addr2));
269 }
270 close(io);
271 io = -1;
272 unixwt(!inopen, f);
273 netchHAD(lines);
274}
275
276/*
277 * Set up to do a recover, getting io to be a pipe from
278 * the recover process.
279 */
280recover()
281{
282 static int pvec[2];
283
284 if (pipe(pvec) < 0)
285 error(" Can't make pipe for recovery");
286 pid = fork();
287 io = pvec[0];
288 if (pid < 0) {
289 close(pvec[1]);
290 error(" Can't fork to execute recovery");
291 }
292 if (pid == 0) {
293 close(2);
294 dup(1);
295 close(1);
296 dup(pvec[1]);
297 close(pvec[1]);
298 execl(EXRECOVER, "exrecover", svalue(DIRECTORY), file, (char *) 0);
299 close(1);
300 dup(2);
301 error(" No recovery routine");
302 }
303 close(pvec[1]);
304}
305
306/*
307 * Wait for the process (pid an external) to complete.
308 */
309waitfor()
310{
311
312 do
313 rpid = wait(&status);
314 while (rpid != pid && rpid != -1);
315 status = (status >> 8) & 0377;
316}
317
318/*
319 * The end of a recover operation. If the process
320 * exits non-zero, force not edited; otherwise force
321 * a write.
322 */
323revocer()
324{
325
326 waitfor();
327 if (pid == rpid && status != 0)
328 edited = 0;
329 else
330 change();
331}