1 /* @(#)execcmds.c 1.46 15/04/23 Copyright 1984-1986, 1995-2013 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static UConst char sccsid[] =
5 "@(#)execcmds.c 1.46 15/04/23 Copyright 1984-1986, 1995-2015 J. Schilling";
6 #endif
7 /*
8 * Commands that deal with execution of shell commands from ved
9 *
10 * Copyright (c) 1984-1986, 1995-2015 J. Schilling
11 */
12 /*
13 * The contents of this file are subject to the terms of the
14 * Common Development and Distribution License, Version 1.0 only
15 * (the "License"). You may not use this file except in compliance
16 * with the License.
17 *
18 * See the file CDDL.Schily.txt in this distribution for details.
19 * A copy of the CDDL is also available via the Internet at
20 * http://www.opensource.org/licenses/cddl1.txt
21 *
22 * When distributing Covered Code, include this CDDL HEADER in each
23 * file and include the License file CDDL.Schily.txt from this distribution.
24 */
25
26 #include "ved.h"
27 #include <schily/signal.h>
28 #include <schily/wait.h>
29
30 #define XBUFSIZE 1024
31 LOCAL Uchar *exbase; /* xbuffer base */
32 LOCAL Uchar *exbptr; /* current read pointer in xbuffer */
33 LOCAL epos_t exbpos; /* position foe next extract to xbuffer */
34 LOCAL epos_t exblen; /* total amount of characters to extract*/
35
36 EXPORT void vexec __PR((ewin_t *wp));
37 EXPORT void vtexec __PR((ewin_t *wp));
38 EXPORT void vsexec __PR((ewin_t *wp));
39 LOCAL void execcmd __PR((ewin_t *wp, Uchar(*)(ewin_t *wp)));
40 LOCAL void doexec __PR((ewin_t *wp, FILE *f));
41 LOCAL void execute __PR((ewin_t *wp));
42 EXPORT int spawncmd __PR((ewin_t *wp, char *name, char *arg));
43 EXPORT BOOL white __PR((int ch));
44 LOCAL Uchar exbufgetc __PR((ewin_t *wp));
45 LOCAL Uchar extakegetc __PR((ewin_t *wp));
46
47 /*
48 * Execute command from commandline.
49 */
50 EXPORT void
vexec(wp)51 vexec(wp)
52 ewin_t *wp;
53 {
54 Uchar cmdline[XBUFSIZE];
55
56 if (! (exblen = getcmdline(wp, cmdline, sizeof (cmdline), "Execute: ")))
57 return;
58 exbptr = exbase = cmdline;
59 execcmd(wp, exbufgetc);
60 macro_reinit(wp);
61 }
62
63 /*
64 * Execute content of current take buffer.
65 */
66 EXPORT void
vtexec(wp)67 vtexec(wp)
68 ewin_t *wp;
69 {
70 Uchar buf[XBUFSIZE + 1];
71
72 lseek(fdown(takefile), (off_t)0, SEEK_SET);
73 exbase = buf;
74 exbptr = &buf[XBUFSIZE];
75 exblen = takesize;
76 execcmd(wp, extakegetc);
77 }
78
79 /*
80 * Execute content of selection (between cursor and mark).
81 */
82 EXPORT void
vsexec(wp)83 vsexec(wp)
84 ewin_t *wp;
85 {
86 Uchar buf[XBUFSIZE + 1];
87 epos_t begin = min(wp->dot, wp->mark);
88 epos_t end = max(wp->dot, wp->mark);
89
90 if (! wp->markvalid) {
91 nomarkmsg(wp);
92 } else {
93 exbase = buf;
94 exbptr = &buf[XBUFSIZE];
95 exbpos = begin;
96 exblen = end - begin;
97 execcmd(wp, exbufgetc);
98 }
99 }
100
101 /*
102 * Copy characters from comand buffer into execute-file.
103 * Expand tape buffer names.
104 * Execute content of execute-file.
105 */
106 LOCAL void
execcmd(wp,nextc)107 execcmd(wp, nextc)
108 ewin_t *wp;
109 Uchar (*nextc) __PR((ewin_t *wp));
110 {
111 FILE *f;
112 Uchar c;
113 Uchar *tfpath;
114 Uchar tbuf[NAMESIZE]; /* We don't know the max namelen of a takebuf*/
115 int i;
116
117 if ((f = opensyserr(wp, execname, "ctwb")) == NULL)
118 return;
119 stmpfmodes(execname);
120
121 for (;;) switch (c = (*nextc)(wp)) {
122
123 case '\\':
124 /*
125 * Check if this is a quoted take-buffer name.
126 */
127 if ((c = (*nextc)(wp)) != '\\') {
128 for (i = 0; !white(c) && i < (NAMESIZE-1); ) {
129 tbuf[i++] = c;
130 c = (*nextc)(wp);
131 }
132 tbuf[i] = '\0';
133 if (!(tfpath = findtake(wp, tbuf)))
134 return;
135
136 /*
137 * Use real path name of take buffer
138 * instead of take-buffer name.
139 */
140 while (*tfpath != '\0')
141 putc(*tfpath++, f);
142 }
143 /* FALLTHROUGH */
144 default:
145 if (c != '\0') {
146 putc(c, f);
147 continue;
148 }
149 /* FALLTHROUGH */
150 case '\0':
151 doexec(wp, f);
152 return;
153 }
154 }
155
156 LOCAL void
doexec(wp,f)157 doexec(wp, f)
158 ewin_t *wp;
159 FILE *f;
160 {
161 int c;
162
163 putc('\n', f); /* Add a newline csh wants it */
164 fclose(f);
165 if (!wp->modflg && !mflag) {
166 /*
167 * XXX Falls das Kommando das File modifiziert,
168 * XXX wird es nicht wieder eingelesen!
169 */
170 flush();
171 execute(wp);
172 vredisp(wp);
173 return;
174 }
175 if (wp->modflg)
176 writeerr(wp, "FILE MODIFIED!");
177
178 switch (c = getcmdchar(wp, NULL, "EXECUTING. PUT EDITS?(Y/W/N/F/!) ")) {
179
180 default:
181 abortmsg(wp);
182 case 0:
183 return; /* aborted */
184 case 'w':
185 case 'W':
186 case '!':
187 if (!writebuf(wp, c == '!'))
188 return;
189 goto ex_it;
190 case 'y':
191 case 'Y':
192 case 'f':
193 case 'F':
194 if (!bakbuf(wp, c == 'f' || c == 'F'))
195 return;
196 ex_it:
197 execute(wp);
198 fchange(wp, wp->curfile);
199 newwindow(wp);
200 return;
201 case 'n':
202 case 'N':
203 execute(wp);
204 vredisp(wp);
205 return;
206 }
207 }
208
209 /*
210 * Execute the content ot the execute file.
211 * Write back the ontent of the current take buffer.
212 */
213 LOCAL void
execute(wp)214 execute(wp)
215 ewin_t *wp;
216 {
217 char *sh;
218
219 backuptake(wp);
220 if ((sh = getenv("SHELL")) == NULL)
221 spawncmd(wp, DEFSHELL, C execname);
222 else
223 spawncmd(wp, sh, C execname);
224 loadtake(wp);
225 wait_for_confirm(wp);
226 }
227
228 /*
229 * Spawn new process and execute the content ot the execute file.
230 * Do this with default signal handler and default tty modes.
231 */
232 EXPORT int
spawncmd(wp,name,arg)233 spawncmd(wp, name, arg)
234 ewin_t *wp;
235 char *name;
236 char *arg;
237 {
238 #define VOID_SIGS
239 #ifdef VOID_SIGS
240 void (*old) __PR((int));
241 #else
242 int (*old) __PR((int));
243 #endif
244 int stat;
245 int newpid;
246 #ifdef JOS
247 int err;
248 #endif
249
250 #ifdef HAVE_FORK
251 old = signal(SIGINT, SIG_IGN);
252 rsttmodes(wp);
253 newpid = fork();
254 if (newpid == 0) {
255 signal(SIGINT, SIG_DFL);
256 signal(SIGQUIT, SIG_DFL);
257 fexecl(name, stdin, stdout, stderr, name, arg, (char *)NULL);
258 comerr("Can not execute %s.\n", name);
259 }
260 #ifdef JOS
261 err = cwait(&newpid, &stat);
262 if (err == 4)
263 kill(newpid, SIGKILL); /* UNOS "coredump" */
264 if (err > 0 && stat == 0)
265 stat = -1;
266 #else
267 newpid = wait(&stat);
268 if (WCOREDUMP(stat))
269 unlink("core");
270 #endif
271 settmodes(wp);
272 signal(SIGINT, old);
273 #else
274 writeerr(wp, "Fork/exec not available");
275 stat = -1;
276 #endif
277
278 return (stat);
279 }
280
281 /*
282 * Check for whitespace characters.
283 */
284 EXPORT BOOL
white(ch)285 white(ch)
286 Uchar ch;
287 {
288 if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\0')
289 return (TRUE);
290 return (FALSE);
291
292 }
293
294 /*
295 * Extract one character from current selection.
296 * Refill xbuffer if empty.
297 */
298 LOCAL Uchar
exbufgetc(wp)299 exbufgetc(wp)
300 ewin_t *wp;
301 {
302 int amt;
303
304 if (exbptr >= &exbase[XBUFSIZE]) {
305 amt = extract(wp, exbpos, exbase, (int)min(exblen, XBUFSIZE));
306 if (amt == 0)
307 return ('\0');
308 exbpos += amt;
309 exbptr = exbase;
310 }
311 if (--exblen < 0)
312 return ('\0');
313 return (*exbptr++);
314 }
315
316 /*
317 * Extract one character from current takefile.
318 */
319 LOCAL Uchar
extakegetc(wp)320 extakegetc(wp)
321 ewin_t *wp;
322 {
323 int amt;
324 extern char TAKEBUF[];
325
326 if (exbptr >= &exbase[XBUFSIZE]) {
327 amt = readsyserr(wp, takefile, exbase, (int)min(exblen, XBUFSIZE), UC TAKEBUF);
328 if (amt == 0)
329 return ('\0');
330 exbptr = exbase;
331 }
332 if (--exblen < 0)
333 return ('\0');
334 return (*exbptr++);
335 }
336