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