14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*8462SApril.Chin@Sun.COM * Copyright (c) 1982-2008 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 7*8462SApril.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 <ctype.h> 344887Schin #include "jobs.h" 354887Schin #include "builtins.h" 364887Schin 374887Schin #define L_FLAG 1 384887Schin #define S_FLAG 2 394887Schin 404887Schin static const char trapfmt[] = "trap -- %s %s\n"; 414887Schin 424887Schin static int sig_number(const char*); 434887Schin static void sig_list(Shell_t*,int); 444887Schin 454887Schin int b_trap(int argc,char *argv[],void *extra) 464887Schin { 474887Schin register char *arg = argv[1]; 48*8462SApril.Chin@Sun.COM register int sig, clear = 0, dflag = 0, pflag = 0; 49*8462SApril.Chin@Sun.COM register Shell_t *shp = ((Shbltin_t*)extra)->shp; 504887Schin NOT_USED(argc); 514887Schin while (sig = optget(argv, sh_opttrap)) switch (sig) 524887Schin { 534887Schin case 'p': 544887Schin pflag=1; 554887Schin break; 564887Schin case ':': 574887Schin errormsg(SH_DICT,2, "%s", opt_info.arg); 584887Schin break; 594887Schin case '?': 604887Schin errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg); 614887Schin return(2); 624887Schin break; 634887Schin } 644887Schin argv += opt_info.index; 654887Schin if(error_info.errors) 664887Schin errormsg(SH_DICT,ERROR_usage(2),"%s", optusage((char*)0)); 674887Schin if(arg = *argv) 684887Schin { 694887Schin char *action = arg; 70*8462SApril.Chin@Sun.COM if(!dflag && !pflag) 714887Schin { 724887Schin /* first argument all digits or - means clear */ 734887Schin while(isdigit(*arg)) 744887Schin arg++; 754887Schin clear = (arg!=action && *arg==0); 764887Schin if(!clear) 774887Schin { 784887Schin ++argv; 794887Schin if(*action=='-' && action[1]==0) 804887Schin clear++; 81*8462SApril.Chin@Sun.COM /* 82*8462SApril.Chin@Sun.COM * NOTE: 2007-11-26: workaround for tests/signal.sh 83*8462SApril.Chin@Sun.COM * if function semantics can be worked out then it 84*8462SApril.Chin@Sun.COM * may merit a -d,--default option 85*8462SApril.Chin@Sun.COM */ 86*8462SApril.Chin@Sun.COM else if(*action=='+' && action[1]==0 && sh.st.self == &sh.global) 87*8462SApril.Chin@Sun.COM { 88*8462SApril.Chin@Sun.COM clear++; 89*8462SApril.Chin@Sun.COM dflag++; 90*8462SApril.Chin@Sun.COM } 914887Schin } 92*8462SApril.Chin@Sun.COM if(!argv[0]) 934887Schin errormsg(SH_DICT,ERROR_exit(1),e_condition); 944887Schin } 954887Schin while(arg = *argv++) 964887Schin { 974887Schin sig = sig_number(arg); 984887Schin if(sig<0) 994887Schin { 1004887Schin errormsg(SH_DICT,2,e_trap,arg); 1014887Schin return(1); 1024887Schin } 1034887Schin /* internal traps */ 1044887Schin if(sig&SH_TRAP) 1054887Schin { 1064887Schin sig &= ~SH_TRAP; 1074887Schin if(sig>SH_DEBUGTRAP) 1084887Schin { 1094887Schin errormsg(SH_DICT,2,e_trap,arg); 1104887Schin return(1); 1114887Schin } 1124887Schin if(pflag) 1134887Schin { 1144887Schin if(arg=shp->st.trap[sig]) 1154887Schin sfputr(sfstdout,sh_fmtq(arg),'\n'); 1164887Schin continue; 1174887Schin } 1184887Schin if(shp->st.trap[sig]) 1194887Schin free(shp->st.trap[sig]); 1204887Schin shp->st.trap[sig] = 0; 1214887Schin if(!clear && *action) 1224887Schin shp->st.trap[sig] = strdup(action); 1234887Schin if(sig == SH_DEBUGTRAP) 1244887Schin { 1254887Schin if(shp->st.trap[sig]) 1264887Schin shp->trapnote |= SH_SIGTRAP; 1274887Schin else 1284887Schin shp->trapnote = 0; 1294887Schin } 1304887Schin continue; 1314887Schin } 1324887Schin if(sig>shp->sigmax) 1334887Schin { 1344887Schin errormsg(SH_DICT,2,e_trap,arg); 1354887Schin return(1); 1364887Schin } 1374887Schin else if(pflag) 1384887Schin { 1394887Schin char **trapcom = (shp->st.otrapcom?shp->st.otrapcom:shp->st.trapcom); 1404887Schin if(arg=trapcom[sig]) 1414887Schin sfputr(sfstdout,arg,'\n'); 1424887Schin } 1434887Schin else if(clear) 144*8462SApril.Chin@Sun.COM { 1454887Schin sh_sigclear(sig); 146*8462SApril.Chin@Sun.COM if(dflag) 147*8462SApril.Chin@Sun.COM signal(sig,SIG_DFL); 148*8462SApril.Chin@Sun.COM } 1494887Schin else 1504887Schin { 1514887Schin if(sig >= shp->st.trapmax) 1524887Schin shp->st.trapmax = sig+1; 1534887Schin if(arg=shp->st.trapcom[sig]) 1544887Schin free(arg); 1554887Schin shp->st.trapcom[sig] = strdup(action); 1564887Schin sh_sigtrap(sig); 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; 169*8462SApril.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; 238*8462SApril.Chin@Sun.COM register int n,o,sig=0; 239*8462SApril.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; 249*8462SApril.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); 258*8462SApril.Chin@Sun.COM stakseek(o); 259*8462SApril.Chin@Sun.COM if(memcmp(stakptr(o),"SIG",3)==0) 2604887Schin { 2614887Schin sig = 1; 262*8462SApril.Chin@Sun.COM o += 3; 2634887Schin } 264*8462SApril.Chin@Sun.COM tp = sh_locate(stakptr(o),(const Shtable_t*)shtab_signals,sizeof(*shtab_signals)); 2654887Schin n = tp->sh_number; 2664887Schin if(sig==1 && (n>=(SH_TRAP-1) && n < (1<<SH_SIGBITS))) 2674887Schin { 2684887Schin /* sig prefix cannot match internal traps */ 2694887Schin n = 0; 2704887Schin tp = (Shtable_t*)((char*)tp + sizeof(*shtab_signals)); 271*8462SApril.Chin@Sun.COM if(strcmp(stakptr(o),tp->sh_name)==0) 2724887Schin n = tp->sh_number; 2734887Schin } 274*8462SApril.Chin@Sun.COM if((n>>SH_SIGBITS)&SH_SIGRUNTIME) 275*8462SApril.Chin@Sun.COM n = sh.sigruntime[(n&((1<<SH_SIGBITS)-1))-1]; 276*8462SApril.Chin@Sun.COM else 277*8462SApril.Chin@Sun.COM { 278*8462SApril.Chin@Sun.COM n &= (1<<SH_SIGBITS)-1; 279*8462SApril.Chin@Sun.COM if(n < SH_TRAP) 280*8462SApril.Chin@Sun.COM n--; 281*8462SApril.Chin@Sun.COM } 282*8462SApril.Chin@Sun.COM if(n<0 && (name=stakptr(o)) && *name++=='R' && *name++=='T') 283*8462SApril.Chin@Sun.COM { 284*8462SApril.Chin@Sun.COM if(name[0]=='M' && name[1]=='I' && name[2]=='N' && name[3]=='+') 285*8462SApril.Chin@Sun.COM { 286*8462SApril.Chin@Sun.COM if((sig=(int)strtol(name+4,&name,10)) >= 0 && !*name) 287*8462SApril.Chin@Sun.COM n = sh.sigruntime[SH_SIGRTMIN] + sig; 288*8462SApril.Chin@Sun.COM } 289*8462SApril.Chin@Sun.COM else if(name[0]=='M' && name[1]=='A' && name[2]=='X' && name[3]=='-') 290*8462SApril.Chin@Sun.COM { 291*8462SApril.Chin@Sun.COM if((sig=(int)strtol(name+4,&name,10)) >= 0 && !*name) 292*8462SApril.Chin@Sun.COM n = sh.sigruntime[SH_SIGRTMAX] - sig; 293*8462SApril.Chin@Sun.COM } 294*8462SApril.Chin@Sun.COM else if((sig=(int)strtol(name,&name,10)) > 0 && !*name) 295*8462SApril.Chin@Sun.COM n = sh.sigruntime[SH_SIGRTMIN] + sig - 1; 296*8462SApril.Chin@Sun.COM if(n<sh.sigruntime[SH_SIGRTMIN] || n>sh.sigruntime[SH_SIGRTMAX]) 297*8462SApril.Chin@Sun.COM n = -1; 298*8462SApril.Chin@Sun.COM } 2994887Schin } 3004887Schin return(n); 3014887Schin } 3024887Schin 3034887Schin /* 304*8462SApril.Chin@Sun.COM * synthesize signal name for sig in buf 305*8462SApril.Chin@Sun.COM * pfx!=0 prepends SIG to default signal number 306*8462SApril.Chin@Sun.COM */ 307*8462SApril.Chin@Sun.COM static char* sig_name(int sig, char* buf, int pfx) 308*8462SApril.Chin@Sun.COM { 309*8462SApril.Chin@Sun.COM register int i; 310*8462SApril.Chin@Sun.COM 311*8462SApril.Chin@Sun.COM i = 0; 312*8462SApril.Chin@Sun.COM if(sig>sh.sigruntime[SH_SIGRTMIN] && sig<sh.sigruntime[SH_SIGRTMAX]) 313*8462SApril.Chin@Sun.COM { 314*8462SApril.Chin@Sun.COM buf[i++] = 'R'; 315*8462SApril.Chin@Sun.COM buf[i++] = 'T'; 316*8462SApril.Chin@Sun.COM buf[i++] = 'M'; 317*8462SApril.Chin@Sun.COM if(sig>sh.sigruntime[SH_SIGRTMIN]+(sh.sigruntime[SH_SIGRTMAX]-sh.sigruntime[SH_SIGRTMIN])/2) 318*8462SApril.Chin@Sun.COM { 319*8462SApril.Chin@Sun.COM buf[i++] = 'A'; 320*8462SApril.Chin@Sun.COM buf[i++] = 'X'; 321*8462SApril.Chin@Sun.COM buf[i++] = '-'; 322*8462SApril.Chin@Sun.COM sig = sh.sigruntime[SH_SIGRTMAX]-sig; 323*8462SApril.Chin@Sun.COM } 324*8462SApril.Chin@Sun.COM else 325*8462SApril.Chin@Sun.COM { 326*8462SApril.Chin@Sun.COM buf[i++] = 'I'; 327*8462SApril.Chin@Sun.COM buf[i++] = 'N'; 328*8462SApril.Chin@Sun.COM buf[i++] = '+'; 329*8462SApril.Chin@Sun.COM sig = sig-sh.sigruntime[SH_SIGRTMIN]; 330*8462SApril.Chin@Sun.COM } 331*8462SApril.Chin@Sun.COM } 332*8462SApril.Chin@Sun.COM else if(pfx) 333*8462SApril.Chin@Sun.COM { 334*8462SApril.Chin@Sun.COM buf[i++] = 'S'; 335*8462SApril.Chin@Sun.COM buf[i++] = 'I'; 336*8462SApril.Chin@Sun.COM buf[i++] = 'G'; 337*8462SApril.Chin@Sun.COM } 338*8462SApril.Chin@Sun.COM i += sfsprintf(buf+i, 8, "%d", sig); 339*8462SApril.Chin@Sun.COM buf[i] = 0; 340*8462SApril.Chin@Sun.COM return buf; 341*8462SApril.Chin@Sun.COM } 342*8462SApril.Chin@Sun.COM 343*8462SApril.Chin@Sun.COM /* 3444887Schin * if <flag> is positive, then print signal name corresponding to <flag> 3454887Schin * if <flag> is zero, then print all signal names 3464887Schin * if <flag> is negative, then print all traps 3474887Schin */ 3484887Schin static void sig_list(register Shell_t *shp,register int flag) 3494887Schin { 3504887Schin register const struct shtable2 *tp; 3514887Schin register int sig = shp->sigmax+1; 352*8462SApril.Chin@Sun.COM register char *sname; 353*8462SApril.Chin@Sun.COM char name[10]; 3544887Schin const char *names[SH_TRAP]; 3554887Schin const char *traps[SH_DEBUGTRAP+1]; 3564887Schin tp=shtab_signals; 357*8462SApril.Chin@Sun.COM if(flag<=0) 3584887Schin { 3594887Schin /* not all signals may be defined, so initialize */ 3604887Schin while(--sig >= 0) 3614887Schin names[sig] = 0; 3624887Schin for(sig=SH_DEBUGTRAP; sig>=0; sig--) 3634887Schin traps[sig] = 0; 3644887Schin } 3654887Schin while(*tp->sh_name) 3664887Schin { 367*8462SApril.Chin@Sun.COM sig = tp->sh_number&((1<<SH_SIGBITS)-1); 368*8462SApril.Chin@Sun.COM if ((tp->sh_number>>SH_SIGBITS) & SH_SIGRUNTIME) 369*8462SApril.Chin@Sun.COM sig = sh.sigruntime[sig-1]+1; 3704887Schin if(sig==flag) 3714887Schin { 3724887Schin sfprintf(sfstdout,"%s\n",tp->sh_name); 3734887Schin return; 3744887Schin } 3754887Schin else if(sig&SH_TRAP) 3764887Schin traps[sig&~SH_TRAP] = (char*)tp->sh_name; 3774887Schin else if(sig < sizeof(names)/sizeof(char*)) 3784887Schin names[sig] = (char*)tp->sh_name; 3794887Schin tp++; 3804887Schin } 3814887Schin if(flag > 0) 382*8462SApril.Chin@Sun.COM sfputr(sfstdout, sig_name(flag-1,name,0), '\n'); 3834887Schin else if(flag<0) 3844887Schin { 3854887Schin /* print the traps */ 386*8462SApril.Chin@Sun.COM register char *trap,**trapcom; 3874887Schin sig = shp->st.trapmax; 3884887Schin /* use parent traps if otrapcom is set (for $(trap) */ 3894887Schin trapcom = (shp->st.otrapcom?shp->st.otrapcom:shp->st.trapcom); 3904887Schin while(--sig >= 0) 3914887Schin { 3924887Schin if(!(trap=trapcom[sig])) 3934887Schin continue; 3944887Schin if(!(sname=(char*)names[sig+1])) 395*8462SApril.Chin@Sun.COM sname = sig_name(sig,name,1); 3964887Schin sfprintf(sfstdout,trapfmt,sh_fmtq(trap),sname); 3974887Schin } 3984887Schin for(sig=SH_DEBUGTRAP; sig>=0; sig--) 3994887Schin { 4004887Schin if(!(trap=shp->st.trap[sig])) 4014887Schin continue; 4024887Schin sfprintf(sfstdout,trapfmt,sh_fmtq(trap),traps[sig]); 4034887Schin } 4044887Schin } 4054887Schin else 4064887Schin { 4074887Schin /* print all the signal names */ 4084887Schin for(sig=2; sig <= shp->sigmax; sig++) 4094887Schin { 410*8462SApril.Chin@Sun.COM if(!(sname=(char*)names[sig+1])) 411*8462SApril.Chin@Sun.COM sname = sig_name(sig,name,1); 412*8462SApril.Chin@Sun.COM sfputr(sfstdout,sname,'\n'); 4134887Schin } 4144887Schin } 4154887Schin } 416