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