Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/ksh93/bltins/trap.c
1810 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1982-2012 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* David Korn <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
/*
22
* trap [-p] action sig...
23
* kill [-l] [sig...]
24
* kill [-s sig] pid...
25
*
26
* David Korn
27
* AT&T Labs
28
* research!dgk
29
*
30
*/
31
32
#include "defs.h"
33
#include "jobs.h"
34
#include "builtins.h"
35
36
#define L_FLAG 1
37
#define S_FLAG 2
38
39
static const char trapfmt[] = "trap -- %s %s\n";
40
41
static int sig_number(Shell_t*,const char*);
42
static void sig_list(Shell_t*,int);
43
44
int b_trap(int argc,char *argv[],Shbltin_t *context)
45
{
46
register char *arg = argv[1];
47
register int sig, clear = 0, dflag = 0, pflag = 0;
48
register Shell_t *shp = context->shp;
49
NOT_USED(argc);
50
while (sig = optget(argv, sh_opttrap)) switch (sig)
51
{
52
case 'p':
53
pflag=1;
54
break;
55
case ':':
56
errormsg(SH_DICT,2, "%s", opt_info.arg);
57
break;
58
case '?':
59
errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
60
return(2);
61
break;
62
}
63
argv += opt_info.index;
64
if(error_info.errors)
65
errormsg(SH_DICT,ERROR_usage(2),"%s", optusage((char*)0));
66
if(arg = *argv)
67
{
68
char *action = arg;
69
if(!dflag && !pflag)
70
{
71
/* first argument all digits or - means clear */
72
while(isdigit(*arg))
73
arg++;
74
clear = (arg!=action && *arg==0);
75
if(!clear)
76
{
77
++argv;
78
if(*action=='-' && action[1]==0)
79
clear++;
80
/*
81
* NOTE: 2007-11-26: workaround for tests/signal.sh
82
* if function semantics can be worked out then it
83
* may merit a -d,--default option
84
*/
85
else if(*action=='+' && action[1]==0 && shp->st.self == &shp->global)
86
{
87
clear++;
88
dflag++;
89
}
90
}
91
if(!argv[0])
92
errormsg(SH_DICT,ERROR_exit(1),e_condition);
93
}
94
while(arg = *argv++)
95
{
96
sig = sig_number(shp,arg);
97
if(sig<0)
98
{
99
errormsg(SH_DICT,2,e_trap,arg);
100
return(1);
101
}
102
/* internal traps */
103
if(sig&SH_TRAP)
104
{
105
char **trap = (shp->st.otrap?shp->st.otrap:shp->st.trap);
106
sig &= ~SH_TRAP;
107
if(sig>SH_DEBUGTRAP)
108
{
109
errormsg(SH_DICT,2,e_trap,arg);
110
return(1);
111
}
112
if(pflag)
113
{
114
if(arg=trap[sig])
115
sfputr(sfstdout,sh_fmtq(arg),'\n');
116
continue;
117
}
118
shp->st.otrap = 0;
119
if(shp->st.trap[sig])
120
free(shp->st.trap[sig]);
121
shp->st.trap[sig] = 0;
122
if(!clear && *action)
123
shp->st.trap[sig] = strdup(action);
124
if(sig == SH_DEBUGTRAP)
125
{
126
if(shp->st.trap[sig])
127
shp->trapnote |= SH_SIGTRAP;
128
else
129
shp->trapnote = 0;
130
}
131
continue;
132
}
133
if(sig>shp->gd->sigmax)
134
{
135
errormsg(SH_DICT,2,e_trap,arg);
136
return(1);
137
}
138
else if(pflag)
139
{
140
char **trapcom = (shp->st.otrapcom?shp->st.otrapcom:shp->st.trapcom);
141
if(arg=trapcom[sig])
142
sfputr(sfstdout,arg,'\n');
143
}
144
else if(clear)
145
{
146
sh_sigclear(sig);
147
if(dflag)
148
signal(sig,SIG_DFL);
149
}
150
else
151
{
152
if(sig >= shp->st.trapmax)
153
shp->st.trapmax = sig+1;
154
arg = shp->st.trapcom[sig];
155
sh_sigtrap(sig);
156
shp->st.trapcom[sig] = (shp->sigflag[sig]&SH_SIGOFF) ? Empty : strdup(action);
157
if(arg && arg != Empty)
158
free(arg);
159
}
160
}
161
}
162
else /* print out current traps */
163
sig_list(shp,-2);
164
return(0);
165
}
166
167
int b_kill(int argc,char *argv[],Shbltin_t *context)
168
{
169
register char *signame;
170
register int sig=SIGTERM, flag=0, n;
171
register Shell_t *shp = context->shp;
172
int usemenu = 0;
173
NOT_USED(argc);
174
while((n = optget(argv,sh_optkill))) switch(n)
175
{
176
case ':':
177
if((signame=argv[opt_info.index++]) && (sig=sig_number(shp,signame+1))>=0)
178
goto endopts;
179
opt_info.index--;
180
errormsg(SH_DICT,2, "%s", opt_info.arg);
181
break;
182
case 'n':
183
sig = (int)opt_info.num;
184
goto endopts;
185
case 's':
186
flag |= S_FLAG;
187
signame = opt_info.arg;
188
goto endopts;
189
case 'L':
190
usemenu = -1;
191
case 'l':
192
flag |= L_FLAG;
193
break;
194
case '?':
195
errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
196
break;
197
}
198
endopts:
199
argv += opt_info.index;
200
if(*argv && strcmp(*argv,"--")==0 && strcmp(*(argv-1),"--")!=0)
201
argv++;
202
if(error_info.errors || flag==(L_FLAG|S_FLAG) || (!(*argv) && !(flag&L_FLAG)))
203
errormsg(SH_DICT,ERROR_usage(2),"%s", optusage((char*)0));
204
/* just in case we send a kill -9 $$ */
205
sfsync(sfstderr);
206
if(flag&L_FLAG)
207
{
208
if(!(*argv))
209
sig_list(shp,usemenu);
210
else while(signame = *argv++)
211
{
212
if(isdigit(*signame))
213
sig_list(shp,((int)strtol(signame, (char**)0, 10)&0177)+1);
214
else
215
{
216
if((sig=sig_number(shp,signame))<0)
217
{
218
shp->exitval = 2;
219
errormsg(SH_DICT,ERROR_exit(1),e_nosignal,signame);
220
}
221
sfprintf(sfstdout,"%d\n",sig);
222
}
223
}
224
return(shp->exitval);
225
}
226
if(flag&S_FLAG)
227
{
228
if((sig=sig_number(shp,signame)) < 0 || sig > shp->gd->sigmax)
229
errormsg(SH_DICT,ERROR_exit(1),e_nosignal,signame);
230
}
231
if(job_walk(sfstdout,job_kill,sig,argv))
232
shp->exitval = 1;
233
return(shp->exitval);
234
}
235
236
/*
237
* Given the name or number of a signal return the signal number
238
*/
239
240
static int sig_number(Shell_t *shp,const char *string)
241
{
242
const Shtable_t *tp;
243
register int n,o,sig=0;
244
char *last, *name;
245
if(isdigit(*string))
246
{
247
n = strtol(string,&last,10);
248
if(*last)
249
n = -1;
250
}
251
else
252
{
253
register int c;
254
o = staktell();
255
do
256
{
257
c = *string++;
258
if(islower(c))
259
c = toupper(c);
260
stakputc(c);
261
}
262
while(c);
263
stakseek(o);
264
if(memcmp(stakptr(o),"SIG",3)==0)
265
{
266
sig = 1;
267
o += 3;
268
if(isdigit(*stakptr(o)))
269
{
270
n = strtol(stakptr(o),&last,10);
271
if(!*last)
272
return(n);
273
}
274
}
275
tp = sh_locate(stakptr(o),(const Shtable_t*)shtab_signals,sizeof(*shtab_signals));
276
n = tp->sh_number;
277
if(sig==1 && (n>=(SH_TRAP-1) && n < (1<<SH_SIGBITS)))
278
{
279
/* sig prefix cannot match internal traps */
280
n = 0;
281
tp = (Shtable_t*)((char*)tp + sizeof(*shtab_signals));
282
if(strcmp(stakptr(o),tp->sh_name)==0)
283
n = tp->sh_number;
284
}
285
if((n>>SH_SIGBITS)&SH_SIGRUNTIME)
286
n = shp->gd->sigruntime[(n&((1<<SH_SIGBITS)-1))-1];
287
else
288
{
289
n &= (1<<SH_SIGBITS)-1;
290
if(n < SH_TRAP)
291
n--;
292
}
293
if(n<0 && shp->gd->sigruntime[1] && (name=stakptr(o)) && *name++=='R' && *name++=='T')
294
{
295
if(name[0]=='M' && name[1]=='I' && name[2]=='N' && name[3]=='+')
296
{
297
if((sig=(int)strtol(name+4,&name,10)) >= 0 && !*name)
298
n = shp->gd->sigruntime[SH_SIGRTMIN] + sig;
299
}
300
else if(name[0]=='M' && name[1]=='A' && name[2]=='X' && name[3]=='-')
301
{
302
if((sig=(int)strtol(name+4,&name,10)) >= 0 && !*name)
303
n = shp->gd->sigruntime[SH_SIGRTMAX] - sig;
304
}
305
else if((sig=(int)strtol(name,&name,10)) > 0 && !*name)
306
n = shp->gd->sigruntime[SH_SIGRTMIN] + sig - 1;
307
if(n<shp->gd->sigruntime[SH_SIGRTMIN] || n>shp->gd->sigruntime[SH_SIGRTMAX])
308
n = -1;
309
}
310
}
311
return(n);
312
}
313
314
/*
315
* synthesize signal name for sig in buf
316
* pfx!=0 prepends SIG to default signal number
317
*/
318
static char* sig_name(Shell_t *shp,int sig, char* buf, int pfx)
319
{
320
register int i;
321
322
i = 0;
323
if(sig>shp->gd->sigruntime[SH_SIGRTMIN] && sig<shp->gd->sigruntime[SH_SIGRTMAX])
324
{
325
buf[i++] = 'R';
326
buf[i++] = 'T';
327
buf[i++] = 'M';
328
if(sig>shp->gd->sigruntime[SH_SIGRTMIN]+(shp->gd->sigruntime[SH_SIGRTMAX]-shp->gd->sigruntime[SH_SIGRTMIN])/2)
329
{
330
buf[i++] = 'A';
331
buf[i++] = 'X';
332
buf[i++] = '-';
333
sig = shp->gd->sigruntime[SH_SIGRTMAX]-sig;
334
}
335
else
336
{
337
buf[i++] = 'I';
338
buf[i++] = 'N';
339
buf[i++] = '+';
340
sig = sig-shp->gd->sigruntime[SH_SIGRTMIN];
341
}
342
}
343
else if(pfx)
344
{
345
buf[i++] = 'S';
346
buf[i++] = 'I';
347
buf[i++] = 'G';
348
}
349
i += sfsprintf(buf+i, 8, "%d", sig);
350
buf[i] = 0;
351
return buf;
352
}
353
354
/*
355
* if <flag> is positive, then print signal name corresponding to <flag>
356
* if <flag> is zero, then print all signal names
357
* if <flag> is -1, then print all signal names in menu format
358
* if <flag> is <-1, then print all traps
359
*/
360
static void sig_list(register Shell_t *shp,register int flag)
361
{
362
register const struct shtable2 *tp;
363
register int sig;
364
register char *sname;
365
char name[10];
366
const char *names[SH_TRAP];
367
const char *traps[SH_DEBUGTRAP+1];
368
tp=shtab_signals;
369
if(flag<=0)
370
{
371
/* not all signals may be defined, so initialize */
372
for(sig=shp->gd->sigmax; sig>=0; sig--)
373
names[sig] = 0;
374
for(sig=SH_DEBUGTRAP; sig>=0; sig--)
375
traps[sig] = 0;
376
}
377
for(; *tp->sh_name; tp++)
378
{
379
sig = tp->sh_number&((1<<SH_SIGBITS)-1);
380
if (((tp->sh_number>>SH_SIGBITS) & SH_SIGRUNTIME) && (sig = shp->gd->sigruntime[sig-1]+1) == 1)
381
continue;
382
if(sig==flag)
383
{
384
sfprintf(sfstdout,"%s\n",tp->sh_name);
385
return;
386
}
387
else if(sig&SH_TRAP)
388
traps[sig&~SH_TRAP] = (char*)tp->sh_name;
389
else if(sig-- && sig < elementsof(names))
390
names[sig] = (char*)tp->sh_name;
391
}
392
if(flag > 0)
393
sfputr(sfstdout, sig_name(shp,flag-1,name,0), '\n');
394
else if(flag<-1)
395
{
396
/* print the traps */
397
register char *trap,**trapcom;
398
sig = shp->st.trapmax;
399
/* use parent traps if otrapcom is set (for $(trap) */
400
trapcom = (shp->st.otrapcom?shp->st.otrapcom:shp->st.trapcom);
401
while(--sig >= 0)
402
{
403
if(!(trap=trapcom[sig]))
404
continue;
405
if(sig > shp->gd->sigmax || !(sname=(char*)names[sig]))
406
sname = sig_name(shp,sig,name,1);
407
sfprintf(sfstdout,trapfmt,sh_fmtq(trap),sname);
408
}
409
for(sig=SH_DEBUGTRAP; sig>=0; sig--)
410
{
411
if(!(trap=shp->st.otrap?shp->st.otrap[sig]:shp->st.trap[sig]))
412
continue;
413
sfprintf(sfstdout,trapfmt,sh_fmtq(trap),traps[sig]);
414
}
415
}
416
else
417
{
418
/* print all the signal names */
419
for(sig=1; sig <= shp->gd->sigmax; sig++)
420
{
421
if(!(sname=(char*)names[sig]))
422
{
423
sname = sig_name(shp,sig,name,1);
424
if(flag)
425
sname = stakcopy(sname);
426
}
427
if(flag)
428
names[sig] = sname;
429
else
430
sfputr(sfstdout,sname,'\n');
431
}
432
if(flag)
433
{
434
names[sig] = 0;
435
sh_menu(sfstdout,shp->gd->sigmax,(char**)names+1);
436
}
437
}
438
}
439
440