14887Schin /***********************************************************************
24887Schin * *
34887Schin * This software is part of the ast package *
4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1982-2010 AT&T Intellectual Property *
54887Schin * and is licensed under the *
64887Schin * Common Public License, Version 1.0 *
78462SApril.Chin@Sun.COM * by AT&T Intellectual Property *
84887Schin * *
94887Schin * A copy of the License is available at *
104887Schin * http://www.opensource.org/licenses/cpl1.0.txt *
114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
124887Schin * *
134887Schin * Information and Software Systems Research *
144887Schin * AT&T Research *
154887Schin * Florham Park NJ *
164887Schin * *
174887Schin * David Korn <dgk@research.att.com> *
184887Schin * *
194887Schin ***********************************************************************/
204887Schin #pragma prototyped
214887Schin /*
224887Schin * trap [-p] action sig...
234887Schin * kill [-l] [sig...]
244887Schin * kill [-s sig] pid...
254887Schin *
264887Schin * David Korn
274887Schin * AT&T Labs
284887Schin * research!dgk
294887Schin *
304887Schin */
314887Schin
324887Schin #include "defs.h"
334887Schin #include "jobs.h"
344887Schin #include "builtins.h"
354887Schin
364887Schin #define L_FLAG 1
374887Schin #define S_FLAG 2
384887Schin
394887Schin static const char trapfmt[] = "trap -- %s %s\n";
404887Schin
414887Schin static int sig_number(const char*);
424887Schin static void sig_list(Shell_t*,int);
434887Schin
b_trap(int argc,char * argv[],void * extra)444887Schin int b_trap(int argc,char *argv[],void *extra)
454887Schin {
464887Schin register char *arg = argv[1];
478462SApril.Chin@Sun.COM register int sig, clear = 0, dflag = 0, pflag = 0;
488462SApril.Chin@Sun.COM register Shell_t *shp = ((Shbltin_t*)extra)->shp;
494887Schin NOT_USED(argc);
504887Schin while (sig = optget(argv, sh_opttrap)) switch (sig)
514887Schin {
524887Schin case 'p':
534887Schin pflag=1;
544887Schin break;
554887Schin case ':':
564887Schin errormsg(SH_DICT,2, "%s", opt_info.arg);
574887Schin break;
584887Schin case '?':
594887Schin errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
604887Schin return(2);
614887Schin break;
624887Schin }
634887Schin argv += opt_info.index;
644887Schin if(error_info.errors)
654887Schin errormsg(SH_DICT,ERROR_usage(2),"%s", optusage((char*)0));
664887Schin if(arg = *argv)
674887Schin {
684887Schin char *action = arg;
698462SApril.Chin@Sun.COM if(!dflag && !pflag)
704887Schin {
714887Schin /* first argument all digits or - means clear */
724887Schin while(isdigit(*arg))
734887Schin arg++;
744887Schin clear = (arg!=action && *arg==0);
754887Schin if(!clear)
764887Schin {
774887Schin ++argv;
784887Schin if(*action=='-' && action[1]==0)
794887Schin clear++;
808462SApril.Chin@Sun.COM /*
818462SApril.Chin@Sun.COM * NOTE: 2007-11-26: workaround for tests/signal.sh
828462SApril.Chin@Sun.COM * if function semantics can be worked out then it
838462SApril.Chin@Sun.COM * may merit a -d,--default option
848462SApril.Chin@Sun.COM */
858462SApril.Chin@Sun.COM else if(*action=='+' && action[1]==0 && sh.st.self == &sh.global)
868462SApril.Chin@Sun.COM {
878462SApril.Chin@Sun.COM clear++;
888462SApril.Chin@Sun.COM dflag++;
898462SApril.Chin@Sun.COM }
904887Schin }
918462SApril.Chin@Sun.COM if(!argv[0])
924887Schin errormsg(SH_DICT,ERROR_exit(1),e_condition);
934887Schin }
944887Schin while(arg = *argv++)
954887Schin {
964887Schin sig = sig_number(arg);
974887Schin if(sig<0)
984887Schin {
994887Schin errormsg(SH_DICT,2,e_trap,arg);
1004887Schin return(1);
1014887Schin }
1024887Schin /* internal traps */
1034887Schin if(sig&SH_TRAP)
1044887Schin {
1054887Schin sig &= ~SH_TRAP;
1064887Schin if(sig>SH_DEBUGTRAP)
1074887Schin {
1084887Schin errormsg(SH_DICT,2,e_trap,arg);
1094887Schin return(1);
1104887Schin }
1114887Schin if(pflag)
1124887Schin {
1134887Schin if(arg=shp->st.trap[sig])
1144887Schin sfputr(sfstdout,sh_fmtq(arg),'\n');
1154887Schin continue;
1164887Schin }
1174887Schin if(shp->st.trap[sig])
1184887Schin free(shp->st.trap[sig]);
1194887Schin shp->st.trap[sig] = 0;
1204887Schin if(!clear && *action)
1214887Schin shp->st.trap[sig] = strdup(action);
1224887Schin if(sig == SH_DEBUGTRAP)
1234887Schin {
1244887Schin if(shp->st.trap[sig])
1254887Schin shp->trapnote |= SH_SIGTRAP;
1264887Schin else
1274887Schin shp->trapnote = 0;
1284887Schin }
1294887Schin continue;
1304887Schin }
1314887Schin if(sig>shp->sigmax)
1324887Schin {
1334887Schin errormsg(SH_DICT,2,e_trap,arg);
1344887Schin return(1);
1354887Schin }
1364887Schin else if(pflag)
1374887Schin {
1384887Schin char **trapcom = (shp->st.otrapcom?shp->st.otrapcom:shp->st.trapcom);
1394887Schin if(arg=trapcom[sig])
1404887Schin sfputr(sfstdout,arg,'\n');
1414887Schin }
1424887Schin else if(clear)
1438462SApril.Chin@Sun.COM {
1444887Schin sh_sigclear(sig);
1458462SApril.Chin@Sun.COM if(dflag)
1468462SApril.Chin@Sun.COM signal(sig,SIG_DFL);
1478462SApril.Chin@Sun.COM }
1484887Schin else
1494887Schin {
1504887Schin if(sig >= shp->st.trapmax)
1514887Schin shp->st.trapmax = sig+1;
15210898Sroland.mainz@nrubsig.org arg = shp->st.trapcom[sig];
15310898Sroland.mainz@nrubsig.org sh_sigtrap(sig);
15410898Sroland.mainz@nrubsig.org shp->st.trapcom[sig] = (shp->sigflag[sig]&SH_SIGOFF) ? Empty : strdup(action);
15510898Sroland.mainz@nrubsig.org if(arg && arg != Empty)
1564887Schin free(arg);
1574887Schin }
1584887Schin }
1594887Schin }
1604887Schin else /* print out current traps */
1614887Schin sig_list(shp,-1);
1624887Schin return(0);
1634887Schin }
1644887Schin
b_kill(int argc,char * argv[],void * extra)1654887Schin int b_kill(int argc,char *argv[],void *extra)
1664887Schin {
1674887Schin register char *signame;
1684887Schin register int sig=SIGTERM, flag=0, n;
1698462SApril.Chin@Sun.COM register Shell_t *shp = ((Shbltin_t*)extra)->shp;
1704887Schin NOT_USED(argc);
1714887Schin while((n = optget(argv,sh_optkill))) switch(n)
1724887Schin {
1734887Schin case ':':
1744887Schin if((signame=argv[opt_info.index++]) && (sig=sig_number(signame+1))>=0)
1754887Schin goto endopts;
1764887Schin opt_info.index--;
1774887Schin errormsg(SH_DICT,2, "%s", opt_info.arg);
1784887Schin break;
1794887Schin case 'n':
1804887Schin sig = (int)opt_info.num;
1814887Schin goto endopts;
1824887Schin case 's':
1834887Schin flag |= S_FLAG;
1844887Schin signame = opt_info.arg;
1854887Schin goto endopts;
1864887Schin case 'l':
1874887Schin flag |= L_FLAG;
1884887Schin break;
1894887Schin case '?':
1904887Schin errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
1914887Schin break;
1924887Schin }
1934887Schin endopts:
1944887Schin argv += opt_info.index;
1954887Schin if(*argv && strcmp(*argv,"--")==0 && strcmp(*(argv-1),"--")!=0)
1964887Schin argv++;
1974887Schin if(error_info.errors || flag==(L_FLAG|S_FLAG) || (!(*argv) && !(flag&L_FLAG)))
1984887Schin errormsg(SH_DICT,ERROR_usage(2),"%s", optusage((char*)0));
1994887Schin /* just in case we send a kill -9 $$ */
2004887Schin sfsync(sfstderr);
2014887Schin if(flag&L_FLAG)
2024887Schin {
2034887Schin if(!(*argv))
2044887Schin sig_list(shp,0);
2054887Schin else while(signame = *argv++)
2064887Schin {
2074887Schin if(isdigit(*signame))
2084887Schin sig_list(shp,((int)strtol(signame, (char**)0, 10)&0177)+1);
2094887Schin else
2104887Schin {
2114887Schin if((sig=sig_number(signame))<0)
2124887Schin {
2134887Schin shp->exitval = 2;
2144887Schin errormsg(SH_DICT,ERROR_exit(1),e_nosignal,signame);
2154887Schin }
2164887Schin sfprintf(sfstdout,"%d\n",sig);
2174887Schin }
2184887Schin }
2194887Schin return(shp->exitval);
2204887Schin }
2214887Schin if(flag&S_FLAG)
2224887Schin {
2234887Schin if((sig=sig_number(signame)) < 0 || sig > shp->sigmax)
2244887Schin errormsg(SH_DICT,ERROR_exit(1),e_nosignal,signame);
2254887Schin }
2264887Schin if(job_walk(sfstdout,job_kill,sig,argv))
2274887Schin shp->exitval = 1;
2284887Schin return(shp->exitval);
2294887Schin }
2304887Schin
2314887Schin /*
2324887Schin * Given the name or number of a signal return the signal number
2334887Schin */
2344887Schin
sig_number(const char * string)2354887Schin static int sig_number(const char *string)
2364887Schin {
2374887Schin const Shtable_t *tp;
2388462SApril.Chin@Sun.COM register int n,o,sig=0;
2398462SApril.Chin@Sun.COM char *last, *name;
2404887Schin if(isdigit(*string))
2414887Schin {
2424887Schin n = strtol(string,&last,10);
2434887Schin if(*last)
2444887Schin n = -1;
2454887Schin }
2464887Schin else
2474887Schin {
2484887Schin register int c;
2498462SApril.Chin@Sun.COM o = staktell();
2504887Schin do
2514887Schin {
2524887Schin c = *string++;
2534887Schin if(islower(c))
2544887Schin c = toupper(c);
2554887Schin stakputc(c);
2564887Schin }
2574887Schin while(c);
2588462SApril.Chin@Sun.COM stakseek(o);
2598462SApril.Chin@Sun.COM if(memcmp(stakptr(o),"SIG",3)==0)
2604887Schin {
2614887Schin sig = 1;
2628462SApril.Chin@Sun.COM o += 3;
26310898Sroland.mainz@nrubsig.org if(isdigit(*stakptr(o)))
26410898Sroland.mainz@nrubsig.org {
26510898Sroland.mainz@nrubsig.org n = strtol(stakptr(o),&last,10);
26610898Sroland.mainz@nrubsig.org if(!*last)
26710898Sroland.mainz@nrubsig.org return(n);
26810898Sroland.mainz@nrubsig.org }
2694887Schin }
2708462SApril.Chin@Sun.COM tp = sh_locate(stakptr(o),(const Shtable_t*)shtab_signals,sizeof(*shtab_signals));
2714887Schin n = tp->sh_number;
2724887Schin if(sig==1 && (n>=(SH_TRAP-1) && n < (1<<SH_SIGBITS)))
2734887Schin {
2744887Schin /* sig prefix cannot match internal traps */
2754887Schin n = 0;
2764887Schin tp = (Shtable_t*)((char*)tp + sizeof(*shtab_signals));
2778462SApril.Chin@Sun.COM if(strcmp(stakptr(o),tp->sh_name)==0)
2784887Schin n = tp->sh_number;
2794887Schin }
2808462SApril.Chin@Sun.COM if((n>>SH_SIGBITS)&SH_SIGRUNTIME)
2818462SApril.Chin@Sun.COM n = sh.sigruntime[(n&((1<<SH_SIGBITS)-1))-1];
2828462SApril.Chin@Sun.COM else
2838462SApril.Chin@Sun.COM {
2848462SApril.Chin@Sun.COM n &= (1<<SH_SIGBITS)-1;
2858462SApril.Chin@Sun.COM if(n < SH_TRAP)
2868462SApril.Chin@Sun.COM n--;
2878462SApril.Chin@Sun.COM }
28810898Sroland.mainz@nrubsig.org if(n<0 && sh.sigruntime[1] && (name=stakptr(o)) && *name++=='R' && *name++=='T')
2898462SApril.Chin@Sun.COM {
2908462SApril.Chin@Sun.COM if(name[0]=='M' && name[1]=='I' && name[2]=='N' && name[3]=='+')
2918462SApril.Chin@Sun.COM {
2928462SApril.Chin@Sun.COM if((sig=(int)strtol(name+4,&name,10)) >= 0 && !*name)
2938462SApril.Chin@Sun.COM n = sh.sigruntime[SH_SIGRTMIN] + sig;
2948462SApril.Chin@Sun.COM }
2958462SApril.Chin@Sun.COM else if(name[0]=='M' && name[1]=='A' && name[2]=='X' && name[3]=='-')
2968462SApril.Chin@Sun.COM {
2978462SApril.Chin@Sun.COM if((sig=(int)strtol(name+4,&name,10)) >= 0 && !*name)
2988462SApril.Chin@Sun.COM n = sh.sigruntime[SH_SIGRTMAX] - sig;
2998462SApril.Chin@Sun.COM }
3008462SApril.Chin@Sun.COM else if((sig=(int)strtol(name,&name,10)) > 0 && !*name)
3018462SApril.Chin@Sun.COM n = sh.sigruntime[SH_SIGRTMIN] + sig - 1;
3028462SApril.Chin@Sun.COM if(n<sh.sigruntime[SH_SIGRTMIN] || n>sh.sigruntime[SH_SIGRTMAX])
3038462SApril.Chin@Sun.COM n = -1;
3048462SApril.Chin@Sun.COM }
3054887Schin }
3064887Schin return(n);
3074887Schin }
3084887Schin
3094887Schin /*
3108462SApril.Chin@Sun.COM * synthesize signal name for sig in buf
3118462SApril.Chin@Sun.COM * pfx!=0 prepends SIG to default signal number
3128462SApril.Chin@Sun.COM */
sig_name(int sig,char * buf,int pfx)3138462SApril.Chin@Sun.COM static char* sig_name(int sig, char* buf, int pfx)
3148462SApril.Chin@Sun.COM {
3158462SApril.Chin@Sun.COM register int i;
3168462SApril.Chin@Sun.COM
3178462SApril.Chin@Sun.COM i = 0;
3188462SApril.Chin@Sun.COM if(sig>sh.sigruntime[SH_SIGRTMIN] && sig<sh.sigruntime[SH_SIGRTMAX])
3198462SApril.Chin@Sun.COM {
3208462SApril.Chin@Sun.COM buf[i++] = 'R';
3218462SApril.Chin@Sun.COM buf[i++] = 'T';
3228462SApril.Chin@Sun.COM buf[i++] = 'M';
3238462SApril.Chin@Sun.COM if(sig>sh.sigruntime[SH_SIGRTMIN]+(sh.sigruntime[SH_SIGRTMAX]-sh.sigruntime[SH_SIGRTMIN])/2)
3248462SApril.Chin@Sun.COM {
3258462SApril.Chin@Sun.COM buf[i++] = 'A';
3268462SApril.Chin@Sun.COM buf[i++] = 'X';
3278462SApril.Chin@Sun.COM buf[i++] = '-';
3288462SApril.Chin@Sun.COM sig = sh.sigruntime[SH_SIGRTMAX]-sig;
3298462SApril.Chin@Sun.COM }
3308462SApril.Chin@Sun.COM else
3318462SApril.Chin@Sun.COM {
3328462SApril.Chin@Sun.COM buf[i++] = 'I';
3338462SApril.Chin@Sun.COM buf[i++] = 'N';
3348462SApril.Chin@Sun.COM buf[i++] = '+';
3358462SApril.Chin@Sun.COM sig = sig-sh.sigruntime[SH_SIGRTMIN];
3368462SApril.Chin@Sun.COM }
3378462SApril.Chin@Sun.COM }
3388462SApril.Chin@Sun.COM else if(pfx)
3398462SApril.Chin@Sun.COM {
3408462SApril.Chin@Sun.COM buf[i++] = 'S';
3418462SApril.Chin@Sun.COM buf[i++] = 'I';
3428462SApril.Chin@Sun.COM buf[i++] = 'G';
3438462SApril.Chin@Sun.COM }
3448462SApril.Chin@Sun.COM i += sfsprintf(buf+i, 8, "%d", sig);
3458462SApril.Chin@Sun.COM buf[i] = 0;
3468462SApril.Chin@Sun.COM return buf;
3478462SApril.Chin@Sun.COM }
3488462SApril.Chin@Sun.COM
3498462SApril.Chin@Sun.COM /*
3504887Schin * if <flag> is positive, then print signal name corresponding to <flag>
3514887Schin * if <flag> is zero, then print all signal names
3524887Schin * if <flag> is negative, then print all traps
3534887Schin */
sig_list(register Shell_t * shp,register int flag)3544887Schin static void sig_list(register Shell_t *shp,register int flag)
3554887Schin {
3564887Schin register const struct shtable2 *tp;
35710898Sroland.mainz@nrubsig.org register int sig;
3588462SApril.Chin@Sun.COM register char *sname;
3598462SApril.Chin@Sun.COM char name[10];
3604887Schin const char *names[SH_TRAP];
3614887Schin const char *traps[SH_DEBUGTRAP+1];
3624887Schin tp=shtab_signals;
3638462SApril.Chin@Sun.COM if(flag<=0)
3644887Schin {
3654887Schin /* not all signals may be defined, so initialize */
36610898Sroland.mainz@nrubsig.org for(sig=shp->sigmax; sig>=0; sig--)
3674887Schin names[sig] = 0;
3684887Schin for(sig=SH_DEBUGTRAP; sig>=0; sig--)
3694887Schin traps[sig] = 0;
3704887Schin }
37110898Sroland.mainz@nrubsig.org for(; *tp->sh_name; tp++)
3724887Schin {
3738462SApril.Chin@Sun.COM sig = tp->sh_number&((1<<SH_SIGBITS)-1);
37410898Sroland.mainz@nrubsig.org if (((tp->sh_number>>SH_SIGBITS) & SH_SIGRUNTIME) && (sig = sh.sigruntime[sig-1]+1) == 1)
37510898Sroland.mainz@nrubsig.org continue;
3764887Schin if(sig==flag)
3774887Schin {
3784887Schin sfprintf(sfstdout,"%s\n",tp->sh_name);
3794887Schin return;
3804887Schin }
3814887Schin else if(sig&SH_TRAP)
3824887Schin traps[sig&~SH_TRAP] = (char*)tp->sh_name;
38310898Sroland.mainz@nrubsig.org else if(sig-- && sig < elementsof(names))
3844887Schin names[sig] = (char*)tp->sh_name;
3854887Schin }
3864887Schin if(flag > 0)
3878462SApril.Chin@Sun.COM sfputr(sfstdout, sig_name(flag-1,name,0), '\n');
3884887Schin else if(flag<0)
3894887Schin {
3904887Schin /* print the traps */
3918462SApril.Chin@Sun.COM register char *trap,**trapcom;
3924887Schin sig = shp->st.trapmax;
3934887Schin /* use parent traps if otrapcom is set (for $(trap) */
3944887Schin trapcom = (shp->st.otrapcom?shp->st.otrapcom:shp->st.trapcom);
3954887Schin while(--sig >= 0)
3964887Schin {
3974887Schin if(!(trap=trapcom[sig]))
3984887Schin continue;
39910898Sroland.mainz@nrubsig.org if(sig > shp->sigmax || !(sname=(char*)names[sig]))
4008462SApril.Chin@Sun.COM sname = sig_name(sig,name,1);
4014887Schin sfprintf(sfstdout,trapfmt,sh_fmtq(trap),sname);
4024887Schin }
4034887Schin for(sig=SH_DEBUGTRAP; sig>=0; sig--)
4044887Schin {
4054887Schin if(!(trap=shp->st.trap[sig]))
4064887Schin continue;
4074887Schin sfprintf(sfstdout,trapfmt,sh_fmtq(trap),traps[sig]);
4084887Schin }
4094887Schin }
4104887Schin else
4114887Schin {
4124887Schin /* print all the signal names */
41310898Sroland.mainz@nrubsig.org for(sig=1; sig <= shp->sigmax; sig++)
4144887Schin {
41510898Sroland.mainz@nrubsig.org if(!(sname=(char*)names[sig]))
4168462SApril.Chin@Sun.COM sname = sig_name(sig,name,1);
4178462SApril.Chin@Sun.COM sfputr(sfstdout,sname,'\n');
4184887Schin }
4194887Schin }
4204887Schin }
421