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