1*4887Schin /***********************************************************************
2*4887Schin *                                                                      *
3*4887Schin *               This software is part of the ast package               *
4*4887Schin *           Copyright (c) 1982-2007 AT&T Knowledge Ventures            *
5*4887Schin *                      and is licensed under the                       *
6*4887Schin *                  Common Public License, Version 1.0                  *
7*4887Schin *                      by AT&T Knowledge Ventures                      *
8*4887Schin *                                                                      *
9*4887Schin *                A copy of the License is available at                 *
10*4887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
11*4887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12*4887Schin *                                                                      *
13*4887Schin *              Information and Software Systems Research               *
14*4887Schin *                            AT&T Research                             *
15*4887Schin *                           Florham Park NJ                            *
16*4887Schin *                                                                      *
17*4887Schin *                  David Korn <dgk@research.att.com>                   *
18*4887Schin *                                                                      *
19*4887Schin ***********************************************************************/
20*4887Schin #pragma prototyped
21*4887Schin /*
22*4887Schin  * trap  [-p]  action sig...
23*4887Schin  * kill  [-l] [sig...]
24*4887Schin  * kill  [-s sig] pid...
25*4887Schin  *
26*4887Schin  *   David Korn
27*4887Schin  *   AT&T Labs
28*4887Schin  *   research!dgk
29*4887Schin  *
30*4887Schin  */
31*4887Schin 
32*4887Schin #include	"defs.h"
33*4887Schin #include	<ctype.h>
34*4887Schin #include	"jobs.h"
35*4887Schin #include	"builtins.h"
36*4887Schin 
37*4887Schin #define L_FLAG	1
38*4887Schin #define S_FLAG	2
39*4887Schin 
40*4887Schin static const char trapfmt[] = "trap -- %s %s\n";
41*4887Schin 
42*4887Schin static int	sig_number(const char*);
43*4887Schin static void	sig_list(Shell_t*,int);
44*4887Schin 
45*4887Schin int	b_trap(int argc,char *argv[],void *extra)
46*4887Schin {
47*4887Schin 	register char *arg = argv[1];
48*4887Schin 	register int sig, pflag = 0;
49*4887Schin 	register Shell_t *shp = (Shell_t*)extra;
50*4887Schin 	NOT_USED(argc);
51*4887Schin 	while (sig = optget(argv, sh_opttrap)) switch (sig)
52*4887Schin 	{
53*4887Schin 	    case 'p':
54*4887Schin 		pflag=1;
55*4887Schin 		break;
56*4887Schin 	    case ':':
57*4887Schin 		errormsg(SH_DICT,2, "%s", opt_info.arg);
58*4887Schin 		break;
59*4887Schin 	    case '?':
60*4887Schin 		errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
61*4887Schin 		return(2);
62*4887Schin 		break;
63*4887Schin 	}
64*4887Schin 	argv += opt_info.index;
65*4887Schin 	if(error_info.errors)
66*4887Schin 		errormsg(SH_DICT,ERROR_usage(2),"%s", optusage((char*)0));
67*4887Schin 	if(arg = *argv)
68*4887Schin 	{
69*4887Schin 		register int	clear;
70*4887Schin 		char *action = arg;
71*4887Schin 		if(!pflag)
72*4887Schin 		{
73*4887Schin 			/* first argument all digits or - means clear */
74*4887Schin 			while(isdigit(*arg))
75*4887Schin 				arg++;
76*4887Schin 			clear = (arg!=action && *arg==0);
77*4887Schin 			if(!clear)
78*4887Schin 			{
79*4887Schin 				++argv;
80*4887Schin 				if(*action=='-' && action[1]==0)
81*4887Schin 					clear++;
82*4887Schin 			}
83*4887Schin 			while(!argv[0])
84*4887Schin 				errormsg(SH_DICT,ERROR_exit(1),e_condition);
85*4887Schin 		}
86*4887Schin 		while(arg = *argv++)
87*4887Schin 		{
88*4887Schin 			sig = sig_number(arg);
89*4887Schin 			if(sig<0)
90*4887Schin 			{
91*4887Schin 				errormsg(SH_DICT,2,e_trap,arg);
92*4887Schin 				return(1);
93*4887Schin 			}
94*4887Schin 			/* internal traps */
95*4887Schin 			if(sig&SH_TRAP)
96*4887Schin 			{
97*4887Schin 				sig &= ~SH_TRAP;
98*4887Schin 				if(sig>SH_DEBUGTRAP)
99*4887Schin 				{
100*4887Schin 					errormsg(SH_DICT,2,e_trap,arg);
101*4887Schin 					return(1);
102*4887Schin 				}
103*4887Schin 				if(pflag)
104*4887Schin 				{
105*4887Schin 					if(arg=shp->st.trap[sig])
106*4887Schin 						sfputr(sfstdout,sh_fmtq(arg),'\n');
107*4887Schin 					continue;
108*4887Schin 				}
109*4887Schin 				if(shp->st.trap[sig])
110*4887Schin 					free(shp->st.trap[sig]);
111*4887Schin 				shp->st.trap[sig] = 0;
112*4887Schin 				if(!clear && *action)
113*4887Schin 					shp->st.trap[sig] = strdup(action);
114*4887Schin 				if(sig == SH_DEBUGTRAP)
115*4887Schin 				{
116*4887Schin 					if(shp->st.trap[sig])
117*4887Schin 						shp->trapnote |= SH_SIGTRAP;
118*4887Schin 					else
119*4887Schin 						shp->trapnote = 0;
120*4887Schin 				}
121*4887Schin 				continue;
122*4887Schin 			}
123*4887Schin 			if(sig>shp->sigmax)
124*4887Schin 			{
125*4887Schin 				errormsg(SH_DICT,2,e_trap,arg);
126*4887Schin 				return(1);
127*4887Schin 			}
128*4887Schin 			else if(pflag)
129*4887Schin 			{
130*4887Schin 				char **trapcom = (shp->st.otrapcom?shp->st.otrapcom:shp->st.trapcom);
131*4887Schin 				if(arg=trapcom[sig])
132*4887Schin 					sfputr(sfstdout,arg,'\n');
133*4887Schin 			}
134*4887Schin 			else if(clear)
135*4887Schin 				sh_sigclear(sig);
136*4887Schin 			else
137*4887Schin 			{
138*4887Schin 				if(sig >= shp->st.trapmax)
139*4887Schin 					shp->st.trapmax = sig+1;
140*4887Schin 				if(arg=shp->st.trapcom[sig])
141*4887Schin 					free(arg);
142*4887Schin 				shp->st.trapcom[sig] = strdup(action);
143*4887Schin 				sh_sigtrap(sig);
144*4887Schin 			}
145*4887Schin 		}
146*4887Schin 	}
147*4887Schin 	else /* print out current traps */
148*4887Schin 		sig_list(shp,-1);
149*4887Schin 	return(0);
150*4887Schin }
151*4887Schin 
152*4887Schin int	b_kill(int argc,char *argv[],void *extra)
153*4887Schin {
154*4887Schin 	register char *signame;
155*4887Schin 	register int sig=SIGTERM, flag=0, n;
156*4887Schin 	register Shell_t *shp = (Shell_t*)extra;
157*4887Schin 	NOT_USED(argc);
158*4887Schin 	while((n = optget(argv,sh_optkill))) switch(n)
159*4887Schin 	{
160*4887Schin 		case ':':
161*4887Schin 			if((signame=argv[opt_info.index++]) && (sig=sig_number(signame+1))>=0)
162*4887Schin 				goto endopts;
163*4887Schin 			opt_info.index--;
164*4887Schin 			errormsg(SH_DICT,2, "%s", opt_info.arg);
165*4887Schin 			break;
166*4887Schin 		case 'n':
167*4887Schin 			sig = (int)opt_info.num;
168*4887Schin 			goto endopts;
169*4887Schin 		case 's':
170*4887Schin 			flag |= S_FLAG;
171*4887Schin 			signame = opt_info.arg;
172*4887Schin 			goto endopts;
173*4887Schin 		case 'l':
174*4887Schin 			flag |= L_FLAG;
175*4887Schin 			break;
176*4887Schin 		case '?':
177*4887Schin 			errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
178*4887Schin 			break;
179*4887Schin 	}
180*4887Schin endopts:
181*4887Schin 	argv += opt_info.index;
182*4887Schin 	if(*argv && strcmp(*argv,"--")==0 && strcmp(*(argv-1),"--")!=0)
183*4887Schin 		argv++;
184*4887Schin 	if(error_info.errors || flag==(L_FLAG|S_FLAG) || (!(*argv) && !(flag&L_FLAG)))
185*4887Schin 		errormsg(SH_DICT,ERROR_usage(2),"%s", optusage((char*)0));
186*4887Schin 	/* just in case we send a kill -9 $$ */
187*4887Schin 	sfsync(sfstderr);
188*4887Schin 	if(flag&L_FLAG)
189*4887Schin 	{
190*4887Schin 		if(!(*argv))
191*4887Schin 			sig_list(shp,0);
192*4887Schin 		else while(signame = *argv++)
193*4887Schin 		{
194*4887Schin 			if(isdigit(*signame))
195*4887Schin 				sig_list(shp,((int)strtol(signame, (char**)0, 10)&0177)+1);
196*4887Schin 			else
197*4887Schin 			{
198*4887Schin 				if((sig=sig_number(signame))<0)
199*4887Schin 				{
200*4887Schin 					shp->exitval = 2;
201*4887Schin 					errormsg(SH_DICT,ERROR_exit(1),e_nosignal,signame);
202*4887Schin 				}
203*4887Schin 				sfprintf(sfstdout,"%d\n",sig);
204*4887Schin 			}
205*4887Schin 		}
206*4887Schin 		return(shp->exitval);
207*4887Schin 	}
208*4887Schin 	if(flag&S_FLAG)
209*4887Schin 	{
210*4887Schin 		if((sig=sig_number(signame)) < 0 || sig > shp->sigmax)
211*4887Schin 			errormsg(SH_DICT,ERROR_exit(1),e_nosignal,signame);
212*4887Schin 	}
213*4887Schin 	if(job_walk(sfstdout,job_kill,sig,argv))
214*4887Schin 		shp->exitval = 1;
215*4887Schin 	return(shp->exitval);
216*4887Schin }
217*4887Schin 
218*4887Schin /*
219*4887Schin  * Given the name or number of a signal return the signal number
220*4887Schin  */
221*4887Schin 
222*4887Schin static int sig_number(const char *string)
223*4887Schin {
224*4887Schin 	const Shtable_t	*tp;
225*4887Schin 	register int	n,sig=0;
226*4887Schin 	char		*last;
227*4887Schin 	if(isdigit(*string))
228*4887Schin 	{
229*4887Schin 		n = strtol(string,&last,10);
230*4887Schin 		if(*last)
231*4887Schin 			n = -1;
232*4887Schin 	}
233*4887Schin 	else
234*4887Schin 	{
235*4887Schin 		register int c;
236*4887Schin 		n = staktell();
237*4887Schin 		do
238*4887Schin 		{
239*4887Schin 			c = *string++;
240*4887Schin 			if(islower(c))
241*4887Schin 				c = toupper(c);
242*4887Schin 			stakputc(c);
243*4887Schin 		}
244*4887Schin 		while(c);
245*4887Schin 		stakseek(n);
246*4887Schin 		if(memcmp(stakptr(n),"SIG",3)==0)
247*4887Schin 		{
248*4887Schin 			sig = 1;
249*4887Schin 			n += 3;
250*4887Schin 		}
251*4887Schin 		tp = sh_locate(stakptr(n),(const Shtable_t*)shtab_signals,sizeof(*shtab_signals));
252*4887Schin 		n = tp->sh_number;
253*4887Schin 		if(sig==1 && (n>=(SH_TRAP-1) && n < (1<<SH_SIGBITS)))
254*4887Schin 		{
255*4887Schin 			/* sig prefix cannot match internal traps */
256*4887Schin 			n = 0;
257*4887Schin 			tp = (Shtable_t*)((char*)tp + sizeof(*shtab_signals));
258*4887Schin 			if(strcmp(stakptr(n),tp->sh_name)==0)
259*4887Schin 				n = tp->sh_number;
260*4887Schin 		}
261*4887Schin 		n &= (1<<SH_SIGBITS)-1;
262*4887Schin 		if(n < SH_TRAP)
263*4887Schin 			n--;
264*4887Schin 	}
265*4887Schin 	return(n);
266*4887Schin }
267*4887Schin 
268*4887Schin /*
269*4887Schin  * if <flag> is positive, then print signal name corresponding to <flag>
270*4887Schin  * if <flag> is zero, then print all signal names
271*4887Schin  * if <flag> is negative, then print all traps
272*4887Schin  */
273*4887Schin static void sig_list(register Shell_t *shp,register int flag)
274*4887Schin {
275*4887Schin 	register const struct shtable2	*tp;
276*4887Schin 	register int sig = shp->sigmax+1;
277*4887Schin 	const char *names[SH_TRAP];
278*4887Schin 	const char *traps[SH_DEBUGTRAP+1];
279*4887Schin 	tp=shtab_signals;
280*4887Schin 	if(flag==0)
281*4887Schin 	{
282*4887Schin 		/* not all signals may be defined, so initialize */
283*4887Schin 		while(--sig >= 0)
284*4887Schin 			names[sig] = 0;
285*4887Schin 		for(sig=SH_DEBUGTRAP; sig>=0; sig--)
286*4887Schin 			traps[sig] = 0;
287*4887Schin 	}
288*4887Schin 	while(*tp->sh_name)
289*4887Schin 	{
290*4887Schin 		sig = tp->sh_number;
291*4887Schin 		sig &= ((1<<SH_SIGBITS)-1);
292*4887Schin 		if(sig==flag)
293*4887Schin 		{
294*4887Schin 			sfprintf(sfstdout,"%s\n",tp->sh_name);
295*4887Schin 			return;
296*4887Schin 		}
297*4887Schin 		else if(sig&SH_TRAP)
298*4887Schin 			traps[sig&~SH_TRAP] = (char*)tp->sh_name;
299*4887Schin 		else if(sig < sizeof(names)/sizeof(char*))
300*4887Schin 			names[sig] = (char*)tp->sh_name;
301*4887Schin 		tp++;
302*4887Schin 	}
303*4887Schin 	if(flag > 0)
304*4887Schin 		sfprintf(sfstdout,"%d\n",flag-1);
305*4887Schin 	else if(flag<0)
306*4887Schin 	{
307*4887Schin 		/* print the traps */
308*4887Schin 		register char *trap,*sname,**trapcom;
309*4887Schin 		char name[6];
310*4887Schin 		sig = shp->st.trapmax;
311*4887Schin 		/* use parent traps if otrapcom is set (for $(trap)  */
312*4887Schin 		trapcom = (shp->st.otrapcom?shp->st.otrapcom:shp->st.trapcom);
313*4887Schin 		while(--sig >= 0)
314*4887Schin 		{
315*4887Schin 			if(!(trap=trapcom[sig]))
316*4887Schin 				continue;
317*4887Schin 			if(!(sname=(char*)names[sig+1]))
318*4887Schin 			{
319*4887Schin 				sname = name;
320*4887Schin 				sname[0] = 'S';
321*4887Schin 				sname[1] = 'I';
322*4887Schin 				sname[2] = 'G';
323*4887Schin 				sname[3] = (sig/10)+'0';
324*4887Schin 				sname[4] = (sig%10)+'0';
325*4887Schin 			}
326*4887Schin 			sfprintf(sfstdout,trapfmt,sh_fmtq(trap),sname);
327*4887Schin 		}
328*4887Schin 		for(sig=SH_DEBUGTRAP; sig>=0; sig--)
329*4887Schin 		{
330*4887Schin 			if(!(trap=shp->st.trap[sig]))
331*4887Schin 				continue;
332*4887Schin 			sfprintf(sfstdout,trapfmt,sh_fmtq(trap),traps[sig]);
333*4887Schin 		}
334*4887Schin 	}
335*4887Schin 	else
336*4887Schin 	{
337*4887Schin 		/* print all the signal names */
338*4887Schin 		for(sig=2; sig <= shp->sigmax; sig++)
339*4887Schin 		{
340*4887Schin 			if(names[sig])
341*4887Schin 				sfputr(sfstdout,names[sig],'\n');
342*4887Schin 			else
343*4887Schin 				sfprintf(sfstdout,"SIG%d\n",sig-1);
344*4887Schin 		}
345*4887Schin 	}
346*4887Schin }
347*4887Schin 
348