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