1 /* @(#)call.c	1.18 09/07/11 Copyright 1985-2009 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static	UConst char sccsid[] =
5 	"@(#)call.c	1.18 09/07/11 Copyright 1985-2009 J. Schilling";
6 #endif
7 /*
8  *	Call bsh defined functions and signal handlers
9  *
10  *	Copyright (c) 1985-2009 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 <schily/stdio.h>
27 #include <schily/signal.h>
28 #include "bsh.h"
29 #include "node.h"
30 #include "btab.h"
31 #include "str.h"
32 #include "strsubs.h"
33 #include <schily/stdlib.h>
34 #include <schily/string.h>
35 
36 #define	NSIGNALS	32
37 #define	SIG_DEF		(sigtype) SIG_DFL
38 
39 typedef struct functions {
40 		char	  *f_name;
41 		char	  *f_val;
42 	struct	functions *f_next;
43 } _FUNCS, *FUNCS;
44 
45 LOCAL FUNCS	funcs = (FUNCS) NULL;
46 LOCAL int	in_function = 0;
47 LOCAL int	do_return = 0;
48 
49 char		*sigcmds[NSIGNALS + 1] = {0};
50 int		sigcount[NSIGNALS + 1] = {0};
51 sigtype		ofunc[NSIGNALS + 1] = {
52     SIG_DEF,
53     SIG_DEF, SIG_DEF, SIG_DEF, SIG_DEF, SIG_DEF, SIG_DEF, SIG_DEF, SIG_DEF,
54     SIG_DEF, SIG_DEF, SIG_DEF, SIG_DEF, SIG_DEF, SIG_DEF, SIG_DEF, SIG_DEF,
55     SIG_DEF, SIG_DEF, SIG_DEF, SIG_DEF, SIG_DEF, SIG_DEF, SIG_DEF, SIG_DEF,
56     SIG_DEF, SIG_DEF, SIG_DEF, SIG_DEF, SIG_DEF, SIG_DEF, SIG_DEF, SIG_DEF
57 };
58 
59 LOCAL	sigret	sig		__PR((int signo));
60 EXPORT	void	bsignal		__PR((Argvec * vp, FILE ** std, int flag));
61 LOCAL	void	print_sigs	__PR((FILE * f));
62 LOCAL	void	set_some_sigs	__PR((Argvec * vp, FILE ** std));
63 LOCAL	void	set_sig		__PR((FILE ** std, int signo, char *cmd));
64 LOCAL	void	del_sig		__PR((FILE ** std, int signo));
65 EXPORT	void	esigs		__PR((void));
66 LOCAL	void	sig_cmd		__PR((int signo, char *cmdl));
67 LOCAL	void	call_cmd	__PR((char *cmdl, FILE ** std));
68 EXPORT	void	bfunc		__PR((Argvec * vp, FILE ** std, int flag));
69 EXPORT	void	breturn		__PR((Argvec * vp, FILE ** std, int flag));
70 EXPORT	BOOL	func_call	__PR((Argvec * vp, FILE ** std, int flag));
71 EXPORT	char	*map_func	__PR((char *name));
72 LOCAL	void	set_func	__PR((Argvec * vp));
73 LOCAL	void	del_func	__PR((Argvec * vp, FILE ** std));
74 LOCAL	void	unknown_func	__PR((FILE ** std, char *name));
75 LOCAL	void	pr_funcs	__PR((FILE * f));
76 LOCAL	void	pr_func		__PR((FILE * f, char *name, char *val));
77 
78 LOCAL sigret
sig(signo)79 sig(signo)
80 	int signo;
81 {
82 	signal(signo, sig);
83 	sigcount[signo]++;
84 #ifdef	DEBUG
85 	printf("sig:  pid: %d sigcount[%d]: %d.\n",
86 				getpid(), signo, sigcount[signo]);
87 #endif
88 }
89 
90 /* ARGSUSED */
91 EXPORT void
bsignal(vp,std,flag)92 bsignal(vp, std, flag)
93 	Argvec	*vp;
94 	FILE	*std[];
95 	int	flag;
96 {
97 	if (vp->av_ac == 1)
98 		print_sigs(std[1]);
99 	else if (vp->av_ac == 2)
100 		wrong_args(vp, std);
101 	else
102 		set_some_sigs(vp, std);
103 }
104 
105 LOCAL void
print_sigs(f)106 print_sigs(f)
107 	FILE	*f;
108 {
109 	register	int	i;
110 
111 	for (i = 1; i <= NSIGNALS; i++) {
112 		if (sigcmds[i])
113 			fprintf(f, "%2d: %s\n", i, sigcmds[i]);
114 	}
115 }
116 
117 LOCAL void
set_some_sigs(vp,std)118 set_some_sigs(vp, std)
119 	Argvec	*vp;
120 	FILE	*std[];
121 {
122 			int	signo;
123 	register	char	**av = &(vp->av_av[2]);
124 
125 	for (; *av; av++) {
126 		if (!toint(std, *av, &signo)) {
127 			return;
128 		} else if (signo < 1 || signo > NSIGNALS) {
129 			ex_status = 1;
130 			fprintf(std[2], "bad signo: %d.\n", signo);
131 		} else {
132 			if (strlen(vp->av_av[1]))
133 				set_sig(std, signo, vp->av_av[1]);
134 			else
135 				del_sig(std, signo);
136 		}
137 	}
138 }
139 
140 LOCAL void
set_sig(std,signo,cmd)141 set_sig(std, signo, cmd)
142 		FILE	*std[];
143 	register int	signo;
144 		char	*cmd;
145 {
146 	if (sigcmds[signo])
147 		del_sig(std, signo);
148 	sigcmds[signo] = makestr(cmd);
149 	sigcount[signo] = 0;
150 	if (signo == SIGINT) {
151 		ofunc[signo] = signal(SIGINT, intr);
152 		if (ofunc[signo] != intr)
153 			signal(SIGINT, sig);
154 	} else {
155 		ofunc[signo] = signal(signo, sig);
156 	}
157 }
158 
159 LOCAL void
del_sig(std,signo)160 del_sig(std, signo)
161 		FILE	*std[];
162 	register int	signo;
163 {
164 	if (sigcmds[signo]) {
165 		free(sigcmds[signo]);
166 		sigcmds[signo] = NULL;
167 		signal(signo, ofunc[signo]);
168 	} else {
169 		fprintf(std[2], "Signal #%d not set.\n", signo);
170 		ex_status = 1;
171 	}
172 }
173 
174 EXPORT void
esigs()175 esigs()
176 {
177 	register int	i;
178 	register char	**rsigcmds = sigcmds;
179 	register int	*rsigcount = sigcount;
180 
181 	for (i = 1; i <= NSIGNALS; i++) {
182 		if (rsigcount[i]) {
183 #ifdef	DEBUG
184 			printf("esigs: sigcount[%d]: %d, sigcmds[%d]: %s.\n",
185 					i, rsigcount[i], i, rsigcmds[i]);
186 #endif
187 			rsigcount[i] = 0;
188 			if (rsigcmds[i])
189 				sig_cmd(i, rsigcmds[i]);
190 		}
191 	}
192 }
193 
194 LOCAL void
sig_cmd(signo,cmdl)195 sig_cmd(signo, cmdl)
196 	int	signo;
197 	char	*cmdl;
198 {
199 	char	buf[11];
200 	int	ctlcsave = ctlc;
201 
202 	ctlc = 0;
203 	sprintf(buf, "%d", signo);
204 	ev_insert(concat("signo", eql, buf, (char *)NULL));
205 	call_cmd(cmdl, gstd);
206 	ev_delete("signo");
207 	ctlc = ctlcsave;
208 }
209 
210 LOCAL void
call_cmd(cmdl,std)211 call_cmd(cmdl, std)
212 	char	*cmdl;
213 	FILE	*std[];
214 {
215 	extern int 	delim;
216 		int	s_delim = delim;
217 
218 	extern int	level,			/* aus cond.c	*/
219 			idsp,
220 			idlen,
221 			read_delim,
222 			*idstack;
223 	extern char	*firstp,		/* ist eigentlich MSTK  */
224 			*stackp,
225 			*foundline;
226 
227 		int	s_level = level,
228 			s_idsp = idsp,
229 			s_idlen = idlen,
230 			s_read_delim = read_delim,
231 			*s_idstack = idstack;
232 		char	*s_firstp = firstp,
233 			*s_stackp = stackp,
234 			*s_foundline = foundline;
235 
236 
237 	in_function++;
238 	level = 0;				/* definierter Anfangswert */
239 	idsp = 0;
240 	idlen = 0;
241 	read_delim = 0;
242 	idstack = (int *) NULL;
243 	firstp = NULL,
244 	stackp = NULL,
245 	foundline = NULL;
246 
247 	delim = EOF;
248 	pushline(cmdl);
249 	do {
250 		freetree(cmdline(0, std, FALSE));
251 #ifdef	DEBUG
252 		printf("das war cmdline.\n");
253 #endif
254 		if (do_return) {
255 			--ctlc, --do_return;
256 			if (delim != EOF)
257 				while (nextch() != EOF);
258 		}
259 	} while (delim != EOF);
260 	if (idstack)
261 		freestack();
262 	delim = s_delim;
263 	level = s_level;
264 	idsp = s_idsp;
265 	idlen = s_idlen;
266 	read_delim = s_read_delim;
267 	idstack = s_idstack;
268 	firstp = s_firstp;
269 	stackp = s_stackp;
270 	foundline = s_foundline;
271 	in_function--;
272 }
273 
274 /* ARGSUSED */
275 EXPORT void
bfunc(vp,std,flag)276 bfunc(vp, std, flag)
277 	Argvec	*vp;
278 	FILE	*std[];
279 	int	flag;
280 {
281 	register int 	ac = vp->av_ac;
282 	register char	**av = vp->av_av;
283 		char	*cmd;
284 
285 	if (ac == 1) {
286 		pr_funcs(std[1]);
287 	} else if (ac == 2) {
288 		if (!(cmd = map_func(av[1]))) {
289 			unknown_func(std, av[1]);
290 			return;
291 		}
292 		pr_func(std[2], av[1], cmd);
293 	} else if (ac > 3) {
294 		wrong_args(vp, std);
295 	} else {
296 		if (strlen(av[2]))
297 			set_func(vp);
298 		else
299 			del_func(vp, std);
300 	}
301 }
302 
303 /* ARGSUSED */
304 EXPORT void
breturn(vp,std,flag)305 breturn(vp, std, flag)
306 	Argvec	*vp;
307 	FILE	*std[];
308 	int	flag;
309 {
310 	if (!in_function) {
311 		bnallo(vp, std, flag);
312 	} else if (vp->av_ac > 2) {
313 		wrong_args(vp, std);
314 	} else {
315 		if (vp->av_ac == 2)
316 			toint(std, vp->av_av[1], &ex_status);
317 		ctlc++;						/* Hihi */
318 		do_return++;
319 	}
320 }
321 
322 /* ARGSUSED */
323 EXPORT BOOL
func_call(vp,std,flag)324 func_call(vp, std, flag)
325 	Argvec	*vp;
326 	FILE	*std[];
327 	int	flag;
328 {
329 	char	*cmd;
330 
331 	if (!(cmd = map_func(vp->av_av[0])))
332 		return (FALSE);
333 	if (vp->av_ac != 1)
334 		wrong_args(vp, std);
335 	else
336 		call_cmd(cmd, std);
337 	return (TRUE);
338 }
339 
340 EXPORT char *
map_func(name)341 map_func(name)
342 	register char	*name;
343 {
344 	register FUNCS	rf = funcs;
345 	register int	cmp;
346 
347 	while (rf) {
348 		if ((cmp = strcmp(name, rf->f_name)) < 0)
349 			return (NULL);
350 		if (cmp == 0)
351 			break;
352 		rf = rf->f_next;
353 	}
354 	if (!rf)
355 		return (NULL);
356 	return (rf->f_val);
357 }
358 
359 LOCAL void
set_func(vp)360 set_func(vp)
361 	Argvec	*vp;
362 {
363 	register char	*name = vp->av_av[1];
364 	register FUNCS	rf = funcs;
365 	register FUNCS	rf1 = funcs;
366 	register FUNCS	new;
367 	register int	cmp;
368 
369 	new = (FUNCS)malloc(sizeof (_FUNCS));
370 	new->f_name = makestr(name);
371 	new->f_val = makestr(vp->av_av[2]);
372 
373 	while (rf) {
374 		if ((cmp = strcmp(name, rf->f_name)) < 0)
375 			break;
376 		if (cmp == 0) {
377 			free(rf->f_name);
378 			free(rf->f_val);
379 			rf->f_name = new->f_name;
380 			rf->f_val = new->f_val;
381 			free((char *) new);
382 			return;
383 		}
384 		rf1 = rf;
385 		rf = rf->f_next;
386 	}
387 
388 	if (rf == rf1) {	/* erster Eintrag */
389 		new->f_next = rf1;
390 		funcs = new;
391 	} else {
392 		new->f_next = rf1->f_next;
393 		rf1->f_next = new;
394 	}
395 }
396 
397 LOCAL void
del_func(vp,std)398 del_func(vp, std)
399 	Argvec	*vp;
400 	FILE	*std[];
401 {
402 	register char	*name = vp->av_av[1];
403 	register FUNCS	rf = funcs;
404 	register FUNCS	rf1 = funcs;
405 
406 	while (rf) {
407 		if (streql(name, rf->f_name))
408 			break;
409 		rf1 = rf;
410 		rf = rf->f_next;
411 	}
412 	if (!rf) {
413 		unknown_func(std, name);
414 		return;
415 	}
416 	if (rf == rf1) 	/* erster Eintrag */
417 		funcs = rf1->f_next;
418 	else
419 		rf1->f_next = rf->f_next;
420 
421 	free(rf->f_name);
422 	free(rf->f_val);
423 	free((char *) rf);
424 }
425 
426 LOCAL void
unknown_func(std,name)427 unknown_func(std, name)
428 	FILE	*std[];
429 	char	*name;
430 {
431 	fprintf(std[2], "Function '%s' unknown.\n", name);
432 	ex_status = 1;
433 }
434 
435 LOCAL void
pr_funcs(f)436 pr_funcs(f)
437 	register FILE	*f;
438 {
439 	register FUNCS	rf = funcs;
440 
441 	while (rf) {
442 		pr_func(f, rf->f_name, rf->f_val);
443 		rf = rf->f_next;
444 	}
445 }
446 
447 LOCAL void
pr_func(f,name,val)448 pr_func(f, name, val)
449 	FILE	*f;
450 	char	*name;
451 	char	*val;
452 {
453 	fprintf(f, "function %s '%s'\n", name, quote_string(val, "\n'"));
454 }
455