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 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 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 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 */ 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 */ 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