1 /***********************************************************************
3 * This software is part of the ast package *
4 * Copyright (c) 1982-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * David Korn <dgk@research.att.com> *
19 ***********************************************************************/
22 * trap [-p] action sig...
24 * kill [-s sig] pid...
39 static const char trapfmt
[] = "trap -- %s %s\n";
41 static int sig_number(const char*);
42 static void sig_list(Shell_t
*,int);
44 int b_trap(int argc
,char *argv
[],void *extra
)
46 register char *arg
= argv
[1];
47 register int sig
, clear
= 0, dflag
= 0, pflag
= 0;
48 register Shell_t
*shp
= ((Shbltin_t
*)extra
)->shp
;
50 while (sig
= optget(argv
, sh_opttrap
)) switch (sig
)
56 errormsg(SH_DICT
,2, "%s", opt_info
.arg
);
59 errormsg(SH_DICT
,ERROR_usage(0), "%s", opt_info
.arg
);
63 argv
+= opt_info
.index
;
65 errormsg(SH_DICT
,ERROR_usage(2),"%s", optusage((char*)0));
71 /* first argument all digits or - means clear */
74 clear
= (arg
!=action
&& *arg
==0);
78 if(*action
=='-' && action
[1]==0)
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
85 else if(*action
=='+' && action
[1]==0 && sh
.st
.self
== &sh
.global
)
92 errormsg(SH_DICT
,ERROR_exit(1),e_condition
);
96 sig
= sig_number(arg
);
99 errormsg(SH_DICT
,2,e_trap
,arg
);
108 errormsg(SH_DICT
,2,e_trap
,arg
);
113 if(arg
=shp
->st
.trap
[sig
])
114 sfputr(sfstdout
,sh_fmtq(arg
),'\n');
117 if(shp
->st
.trap
[sig
])
118 free(shp
->st
.trap
[sig
]);
119 shp
->st
.trap
[sig
] = 0;
120 if(!clear
&& *action
)
121 shp
->st
.trap
[sig
] = strdup(action
);
122 if(sig
== SH_DEBUGTRAP
)
124 if(shp
->st
.trap
[sig
])
125 shp
->trapnote
|= SH_SIGTRAP
;
133 errormsg(SH_DICT
,2,e_trap
,arg
);
138 char **trapcom
= (shp
->st
.otrapcom
?shp
->st
.otrapcom
:shp
->st
.trapcom
);
140 sfputr(sfstdout
,arg
,'\n');
150 if(sig
>= shp
->st
.trapmax
)
151 shp
->st
.trapmax
= sig
+1;
152 arg
= shp
->st
.trapcom
[sig
];
154 shp
->st
.trapcom
[sig
] = (shp
->sigflag
[sig
]&SH_SIGOFF
) ? Empty
: strdup(action
);
155 if(arg
&& arg
!= Empty
)
160 else /* print out current traps */
165 int b_kill(int argc
,char *argv
[],void *extra
)
167 register char *signame
;
168 register int sig
=SIGTERM
, flag
=0, n
;
169 register Shell_t
*shp
= ((Shbltin_t
*)extra
)->shp
;
171 while((n
= optget(argv
,sh_optkill
))) switch(n
)
174 if((signame
=argv
[opt_info
.index
++]) && (sig
=sig_number(signame
+1))>=0)
177 errormsg(SH_DICT
,2, "%s", opt_info
.arg
);
180 sig
= (int)opt_info
.num
;
184 signame
= opt_info
.arg
;
190 errormsg(SH_DICT
,ERROR_usage(2), "%s", opt_info
.arg
);
194 argv
+= opt_info
.index
;
195 if(*argv
&& strcmp(*argv
,"--")==0 && strcmp(*(argv
-1),"--")!=0)
197 if(error_info
.errors
|| flag
==(L_FLAG
|S_FLAG
) || (!(*argv
) && !(flag
&L_FLAG
)))
198 errormsg(SH_DICT
,ERROR_usage(2),"%s", optusage((char*)0));
199 /* just in case we send a kill -9 $$ */
205 else while(signame
= *argv
++)
207 if(isdigit(*signame
))
208 sig_list(shp
,((int)strtol(signame
, (char**)0, 10)&0177)+1);
211 if((sig
=sig_number(signame
))<0)
214 errormsg(SH_DICT
,ERROR_exit(1),e_nosignal
,signame
);
216 sfprintf(sfstdout
,"%d\n",sig
);
219 return(shp
->exitval
);
223 if((sig
=sig_number(signame
)) < 0 || sig
> shp
->sigmax
)
224 errormsg(SH_DICT
,ERROR_exit(1),e_nosignal
,signame
);
226 if(job_walk(sfstdout
,job_kill
,sig
,argv
))
228 return(shp
->exitval
);
232 * Given the name or number of a signal return the signal number
235 static int sig_number(const char *string
)
238 register int n
,o
,sig
=0;
242 n
= strtol(string
,&last
,10);
259 if(memcmp(stakptr(o
),"SIG",3)==0)
263 if(isdigit(*stakptr(o
)))
265 n
= strtol(stakptr(o
),&last
,10);
270 tp
= sh_locate(stakptr(o
),(const Shtable_t
*)shtab_signals
,sizeof(*shtab_signals
));
272 if(sig
==1 && (n
>=(SH_TRAP
-1) && n
< (1<<SH_SIGBITS
)))
274 /* sig prefix cannot match internal traps */
276 tp
= (Shtable_t
*)((char*)tp
+ sizeof(*shtab_signals
));
277 if(strcmp(stakptr(o
),tp
->sh_name
)==0)
280 if((n
>>SH_SIGBITS
)&SH_SIGRUNTIME
)
281 n
= sh
.sigruntime
[(n
&((1<<SH_SIGBITS
)-1))-1];
284 n
&= (1<<SH_SIGBITS
)-1;
288 if(n
<0 && sh
.sigruntime
[1] && (name
=stakptr(o
)) && *name
++=='R' && *name
++=='T')
290 if(name
[0]=='M' && name
[1]=='I' && name
[2]=='N' && name
[3]=='+')
292 if((sig
=(int)strtol(name
+4,&name
,10)) >= 0 && !*name
)
293 n
= sh
.sigruntime
[SH_SIGRTMIN
] + sig
;
295 else if(name
[0]=='M' && name
[1]=='A' && name
[2]=='X' && name
[3]=='-')
297 if((sig
=(int)strtol(name
+4,&name
,10)) >= 0 && !*name
)
298 n
= sh
.sigruntime
[SH_SIGRTMAX
] - sig
;
300 else if((sig
=(int)strtol(name
,&name
,10)) > 0 && !*name
)
301 n
= sh
.sigruntime
[SH_SIGRTMIN
] + sig
- 1;
302 if(n
<sh
.sigruntime
[SH_SIGRTMIN
] || n
>sh
.sigruntime
[SH_SIGRTMAX
])
310 * synthesize signal name for sig in buf
311 * pfx!=0 prepends SIG to default signal number
313 static char* sig_name(int sig
, char* buf
, int pfx
)
318 if(sig
>sh
.sigruntime
[SH_SIGRTMIN
] && sig
<sh
.sigruntime
[SH_SIGRTMAX
])
323 if(sig
>sh
.sigruntime
[SH_SIGRTMIN
]+(sh
.sigruntime
[SH_SIGRTMAX
]-sh
.sigruntime
[SH_SIGRTMIN
])/2)
328 sig
= sh
.sigruntime
[SH_SIGRTMAX
]-sig
;
335 sig
= sig
-sh
.sigruntime
[SH_SIGRTMIN
];
344 i
+= sfsprintf(buf
+i
, 8, "%d", sig
);
350 * if <flag> is positive, then print signal name corresponding to <flag>
351 * if <flag> is zero, then print all signal names
352 * if <flag> is negative, then print all traps
354 static void sig_list(register Shell_t
*shp
,register int flag
)
356 register const struct shtable2
*tp
;
358 register char *sname
;
360 const char *names
[SH_TRAP
];
361 const char *traps
[SH_DEBUGTRAP
+1];
365 /* not all signals may be defined, so initialize */
366 for(sig
=shp
->sigmax
; sig
>=0; sig
--)
368 for(sig
=SH_DEBUGTRAP
; sig
>=0; sig
--)
371 for(; *tp
->sh_name
; tp
++)
373 sig
= tp
->sh_number
&((1<<SH_SIGBITS
)-1);
374 if (((tp
->sh_number
>>SH_SIGBITS
) & SH_SIGRUNTIME
) && (sig
= sh
.sigruntime
[sig
-1]+1) == 1)
378 sfprintf(sfstdout
,"%s\n",tp
->sh_name
);
382 traps
[sig
&~SH_TRAP
] = (char*)tp
->sh_name
;
383 else if(sig
-- && sig
< elementsof(names
))
384 names
[sig
] = (char*)tp
->sh_name
;
387 sfputr(sfstdout
, sig_name(flag
-1,name
,0), '\n');
390 /* print the traps */
391 register char *trap
,**trapcom
;
392 sig
= shp
->st
.trapmax
;
393 /* use parent traps if otrapcom is set (for $(trap) */
394 trapcom
= (shp
->st
.otrapcom
?shp
->st
.otrapcom
:shp
->st
.trapcom
);
397 if(!(trap
=trapcom
[sig
]))
399 if(sig
> shp
->sigmax
|| !(sname
=(char*)names
[sig
]))
400 sname
= sig_name(sig
,name
,1);
401 sfprintf(sfstdout
,trapfmt
,sh_fmtq(trap
),sname
);
403 for(sig
=SH_DEBUGTRAP
; sig
>=0; sig
--)
405 if(!(trap
=shp
->st
.trap
[sig
]))
407 sfprintf(sfstdout
,trapfmt
,sh_fmtq(trap
),traps
[sig
]);
412 /* print all the signal names */
413 for(sig
=1; sig
<= shp
->sigmax
; sig
++)
415 if(!(sname
=(char*)names
[sig
]))
416 sname
= sig_name(sig
,name
,1);
417 sfputr(sfstdout
,sname
,'\n');