1/*********************************************************************** 2* * 3* This software is part of the ast package * 4* Copyright (c) 1982-2011 AT&T Intellectual Property * 5* and is licensed under the * 6* Common Public License, Version 1.0 * 7* by AT&T Intellectual Property * 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 * exec [arg...] 23 * eval [arg...] 24 * jobs [-lnp] [job...] 25 * login [arg...] 26 * let expr... 27 * . file [arg...] 28 * :, true, false 29 * vpath [top] [base] 30 * vmap [top] [base] 31 * wait [job...] 32 * shift [n] 33 * 34 * David Korn 35 * AT&T Labs 36 * 37 */ 38 39#include "defs.h" 40#include "variables.h" 41#include "shnodes.h" 42#include "path.h" 43#include "io.h" 44#include "name.h" 45#include "history.h" 46#include "builtins.h" 47#include "jobs.h" 48 49#define DOTMAX MAXDEPTH /* maximum level of . nesting */ 50 51static void noexport(Namval_t*,void*); 52 53struct login 54{ 55 Shell_t *sh; 56 int clear; 57 char *arg0; 58}; 59 60int b_exec(int argc,char *argv[], void *extra) 61{ 62 struct login logdata; 63 register int n; 64 logdata.clear = 0; 65 logdata.arg0 = 0; 66 logdata.sh = ((Shbltin_t*)extra)->shp; 67 logdata.sh->st.ioset = 0; 68 while (n = optget(argv, sh_optexec)) switch (n) 69 { 70 case 'a': 71 logdata.arg0 = opt_info.arg; 72 argc = 0; 73 break; 74 case 'c': 75 logdata.clear=1; 76 break; 77 case ':': 78 errormsg(SH_DICT,2, "%s", opt_info.arg); 79 break; 80 case '?': 81 errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg); 82 return(2); 83 } 84 argv += opt_info.index; 85 if(error_info.errors) 86 errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0)); 87 if(*argv) 88 B_login(0,argv,(void*)&logdata); 89 return(0); 90} 91 92static void noexport(register Namval_t* np, void *data) 93{ 94 NOT_USED(data); 95 nv_offattr(np,NV_EXPORT); 96} 97 98int B_login(int argc,char *argv[],void *extra) 99{ 100 struct checkpt *pp; 101 register struct login *logp=0; 102 register Shell_t *shp; 103 const char *pname; 104 if(argc) 105 shp = ((Shbltin_t*)extra)->shp; 106 else 107 { 108 logp = (struct login*)extra; 109 shp = logp->sh; 110 } 111 pp = (struct checkpt*)shp->jmplist; 112 if(sh_isoption(SH_RESTRICTED)) 113 errormsg(SH_DICT,ERROR_exit(1),e_restricted,argv[0]); 114 else 115 { 116 register struct argnod *arg=shp->envlist; 117 register Namval_t* np; 118 register char *cp; 119 if(shp->subshell && !shp->subshare) 120 sh_subfork(); 121 if(logp && logp->clear) 122 { 123#ifdef _ENV_H 124 env_close(shp->env); 125 shp->env = env_open((char**)0,3); 126#else 127 nv_scan(shp->var_tree,noexport,0,NV_EXPORT,NV_EXPORT); 128#endif 129 } 130 while(arg) 131 { 132 if((cp=strchr(arg->argval,'=')) && 133 (*cp=0,np=nv_search(arg->argval,shp->var_tree,0))) 134 { 135 nv_onattr(np,NV_EXPORT); 136 sh_envput(shp->env,np); 137 } 138 if(cp) 139 *cp = '='; 140 arg=arg->argnxt.ap; 141 } 142 pname = argv[0]; 143 if(logp && logp->arg0) 144 argv[0] = logp->arg0; 145#ifdef JOBS 146 if(job_close(shp) < 0) 147 return(1); 148#endif /* JOBS */ 149 /* force bad exec to terminate shell */ 150 pp->mode = SH_JMPEXIT; 151 sh_sigreset(2); 152 sh_freeup(shp); 153 path_exec(shp,pname,argv,NIL(struct argnod*)); 154 sh_done(shp,0); 155 } 156 return(1); 157} 158 159int b_let(int argc,char *argv[],void *extra) 160{ 161 register int r; 162 register char *arg; 163 Shell_t *shp = ((Shbltin_t*)extra)->shp; 164 NOT_USED(argc); 165 while (r = optget(argv,sh_optlet)) switch (r) 166 { 167 case ':': 168 errormsg(SH_DICT,2, "%s", opt_info.arg); 169 break; 170 case '?': 171 errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg); 172 break; 173 } 174 argv += opt_info.index; 175 if(error_info.errors || !*argv) 176 errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0)); 177 while(arg= *argv++) 178 r = !sh_arith(shp,arg); 179 return(r); 180} 181 182int b_eval(int argc,char *argv[], void *extra) 183{ 184 register int r; 185 register Shell_t *shp = ((Shbltin_t*)extra)->shp; 186 NOT_USED(argc); 187 while (r = optget(argv,sh_opteval)) switch (r) 188 { 189 case ':': 190 errormsg(SH_DICT,2, "%s", opt_info.arg); 191 break; 192 case '?': 193 errormsg(SH_DICT,ERROR_usage(0), "%s",opt_info.arg); 194 return(2); 195 } 196 if(error_info.errors) 197 errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0)); 198 argv += opt_info.index; 199 if(*argv && **argv) 200 { 201 sh_offstate(SH_MONITOR); 202 sh_eval(sh_sfeval(argv),0); 203 } 204 return(shp->exitval); 205} 206 207int b_dot_cmd(register int n,char *argv[],void* extra) 208{ 209 register char *script; 210 register Namval_t *np; 211 register int jmpval; 212 register Shell_t *shp = ((Shbltin_t*)extra)->shp; 213 struct sh_scoped savst, *prevscope = shp->st.self; 214 char *filename=0; 215 int fd; 216 struct dolnod *argsave=0, *saveargfor; 217 struct checkpt buff; 218 Sfio_t *iop=0; 219 short level; 220 while (n = optget(argv,sh_optdot)) switch (n) 221 { 222 case ':': 223 errormsg(SH_DICT,2, "%s", opt_info.arg); 224 break; 225 case '?': 226 errormsg(SH_DICT,ERROR_usage(0), "%s",opt_info.arg); 227 return(2); 228 } 229 argv += opt_info.index; 230 script = *argv; 231 if(error_info.errors || !script) 232 errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0)); 233 if(shp->dot_depth+1 > DOTMAX) 234 errormsg(SH_DICT,ERROR_exit(1),e_toodeep,script); 235 if(!(np=shp->posix_fun)) 236 { 237 /* check for KornShell style function first */ 238 np = nv_search(script,shp->fun_tree,0); 239 if(np && is_afunction(np) && !nv_isattr(np,NV_FPOSIX)) 240 { 241 if(!np->nvalue.ip) 242 { 243 path_search(shp,script,NIL(Pathcomp_t**),0); 244 if(np->nvalue.ip) 245 { 246 if(nv_isattr(np,NV_FPOSIX)) 247 np = 0; 248 } 249 else 250 errormsg(SH_DICT,ERROR_exit(1),e_found,script); 251 } 252 } 253 else 254 np = 0; 255 if(!np) 256 { 257 if((fd=path_open(shp,script,path_get(shp,script))) < 0) 258 errormsg(SH_DICT,ERROR_system(1),e_open,script); 259 filename = path_fullname(shp,stkptr(shp->stk,PATH_OFFSET)); 260 } 261 } 262 *prevscope = shp->st; 263 shp->st.lineno = np?((struct functnod*)nv_funtree(np))->functline:1; 264 shp->st.var_local = shp->st.save_tree = shp->var_tree; 265 if(filename) 266 { 267 shp->st.filename = filename; 268 shp->st.lineno = 1; 269 } 270 level = shp->fn_depth+shp->dot_depth+1; 271 nv_putval(SH_LEVELNOD,(char*)&level,NV_INT16); 272 shp->st.prevst = prevscope; 273 shp->st.self = &savst; 274 shp->topscope = (Shscope_t*)shp->st.self; 275 prevscope->save_tree = shp->var_tree; 276 shp->st.cmdname = argv[0]; 277 if(np) 278 shp->st.filename = np->nvalue.rp->fname; 279 nv_putval(SH_PATHNAMENOD, shp->st.filename ,NV_NOFREE); 280 shp->posix_fun = 0; 281 if(np || argv[1]) 282 argsave = sh_argnew(shp,argv,&saveargfor); 283 sh_pushcontext(shp,&buff,SH_JMPDOT); 284 jmpval = sigsetjmp(buff.buff,0); 285 if(jmpval == 0) 286 { 287 shp->dot_depth++; 288 if(np) 289 sh_exec((Shnode_t*)(nv_funtree(np)),sh_isstate(SH_ERREXIT)); 290 else 291 { 292 char buff[IOBSIZE+1]; 293 iop = sfnew(NIL(Sfio_t*),buff,IOBSIZE,fd,SF_READ); 294 sh_offstate(SH_NOFORK); 295 sh_eval(iop,0); 296 } 297 } 298 sh_popcontext(shp,&buff); 299 if(!np) 300 free((void*)shp->st.filename); 301 shp->dot_depth--; 302 if((np || argv[1]) && jmpval!=SH_JMPSCRIPT) 303 sh_argreset(shp,argsave,saveargfor); 304 else 305 { 306 prevscope->dolc = shp->st.dolc; 307 prevscope->dolv = shp->st.dolv; 308 } 309 if (shp->st.self != &savst) 310 *shp->st.self = shp->st; 311 /* only restore the top Shscope_t portion for posix functions */ 312 memcpy((void*)&shp->st, (void*)prevscope, sizeof(Shscope_t)); 313 shp->topscope = (Shscope_t*)prevscope; 314 nv_putval(SH_PATHNAMENOD, shp->st.filename ,NV_NOFREE); 315 if(jmpval && jmpval!=SH_JMPFUN) 316 siglongjmp(*shp->jmplist,jmpval); 317 return(shp->exitval); 318} 319 320/* 321 * null, true command 322 */ 323int b_true(int argc,register char *argv[],void *extra) 324{ 325 NOT_USED(argc); 326 NOT_USED(argv[0]); 327 NOT_USED(extra); 328 return(0); 329} 330 331/* 332 * false command 333 */ 334int b_false(int argc,register char *argv[], void *extra) 335{ 336 NOT_USED(argc); 337 NOT_USED(argv[0]); 338 NOT_USED(extra); 339 return(1); 340} 341 342int b_shift(register int n, register char *argv[], void *extra) 343{ 344 register char *arg; 345 register Shell_t *shp = ((Shbltin_t*)extra)->shp; 346 while((n = optget(argv,sh_optshift))) switch(n) 347 { 348 case ':': 349 errormsg(SH_DICT,2, "%s", opt_info.arg); 350 break; 351 case '?': 352 errormsg(SH_DICT,ERROR_usage(0), "%s",opt_info.arg); 353 return(2); 354 } 355 if(error_info.errors) 356 errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0)); 357 argv += opt_info.index; 358 n = ((arg= *argv)?(int)sh_arith(shp,arg):1); 359 if(n<0 || shp->st.dolc<n) 360 errormsg(SH_DICT,ERROR_exit(1),e_number,arg); 361 else 362 { 363 shp->st.dolv += n; 364 shp->st.dolc -= n; 365 } 366 return(0); 367} 368 369int b_wait(int n,register char *argv[],void *extra) 370{ 371 register Shell_t *shp = ((Shbltin_t*)extra)->shp; 372 while((n = optget(argv,sh_optwait))) switch(n) 373 { 374 case ':': 375 errormsg(SH_DICT,2, "%s", opt_info.arg); 376 break; 377 case '?': 378 errormsg(SH_DICT,ERROR_usage(2), "%s",opt_info.arg); 379 break; 380 } 381 if(error_info.errors) 382 errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0)); 383 argv += opt_info.index; 384 job_bwait(argv); 385 return(shp->exitval); 386} 387 388#ifdef JOBS 389# if 0 390 /* for the dictionary generator */ 391 int b_fg(int n,char *argv[],void *extra){} 392 int b_disown(int n,char *argv[],void *extra){} 393# endif 394int b_bg(register int n,register char *argv[],void *extra) 395{ 396 register int flag = **argv; 397 register Shell_t *shp = ((Shbltin_t*)extra)->shp; 398 register const char *optstr = sh_optbg; 399 if(*argv[0]=='f') 400 optstr = sh_optfg; 401 else if(*argv[0]=='d') 402 optstr = sh_optdisown; 403 while((n = optget(argv,optstr))) switch(n) 404 { 405 case ':': 406 errormsg(SH_DICT,2, "%s", opt_info.arg); 407 break; 408 case '?': 409 errormsg(SH_DICT,ERROR_usage(2), "%s",opt_info.arg); 410 break; 411 } 412 if(error_info.errors) 413 errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0)); 414 argv += opt_info.index; 415 if(!sh_isoption(SH_MONITOR) || !job.jobcontrol) 416 { 417 if(sh_isstate(SH_INTERACTIVE)) 418 errormsg(SH_DICT,ERROR_exit(1),e_no_jctl); 419 return(1); 420 } 421 if(flag=='d' && *argv==0) 422 argv = (char**)0; 423 if(job_walk(sfstdout,job_switch,flag,argv)) 424 errormsg(SH_DICT,ERROR_exit(1),e_no_job); 425 return(shp->exitval); 426} 427 428int b_jobs(register int n,char *argv[],void *extra) 429{ 430 register int flag = 0; 431 register Shell_t *shp = ((Shbltin_t*)extra)->shp; 432 while((n = optget(argv,sh_optjobs))) switch(n) 433 { 434 case 'l': 435 flag = JOB_LFLAG; 436 break; 437 case 'n': 438 flag = JOB_NFLAG; 439 break; 440 case 'p': 441 flag = JOB_PFLAG; 442 break; 443 case ':': 444 errormsg(SH_DICT,2, "%s", opt_info.arg); 445 break; 446 case '?': 447 errormsg(SH_DICT,ERROR_usage(2), "%s",opt_info.arg); 448 break; 449 } 450 argv += opt_info.index; 451 if(error_info.errors) 452 errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0)); 453 if(*argv==0) 454 argv = (char**)0; 455 if(job_walk(sfstdout,job_list,flag,argv)) 456 errormsg(SH_DICT,ERROR_exit(1),e_no_job); 457 job_wait((pid_t)0); 458 return(shp->exitval); 459} 460#endif 461 462#ifdef _cmd_universe 463/* 464 * There are several universe styles that are masked by the getuniv(), 465 * setuniv() calls. 466 */ 467int b_universe(int argc, char *argv[],void *extra) 468{ 469 register char *arg; 470 register int n; 471 NOT_USED(extra); 472 while((n = optget(argv,sh_optuniverse))) switch(n) 473 { 474 case ':': 475 errormsg(SH_DICT,2, "%s", opt_info.arg); 476 break; 477 case '?': 478 errormsg(SH_DICT,ERROR_usage(2), "%s",opt_info.arg); 479 break; 480 } 481 argv += opt_info.index; 482 argc -= opt_info.index; 483 if(error_info.errors || argc>1) 484 errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0)); 485 if(arg = argv[0]) 486 { 487 if(!astconf("UNIVERSE",0,arg)) 488 errormsg(SH_DICT,ERROR_exit(1), e_badname,arg); 489 } 490 else 491 { 492 if(!(arg=astconf("UNIVERSE",0,0))) 493 errormsg(SH_DICT,ERROR_exit(1),e_nouniverse); 494 else 495 sfputr(sfstdout,arg,'\n'); 496 } 497 return(0); 498} 499#endif /* cmd_universe */ 500 501#if SHOPT_FS_3D 502#if _UWIN 503#include <sys/mount.h> 504#endif 505# if 0 506 /* for the dictionary generator */ 507 int b_vmap(int argc,char *argv[], void *extra){} 508# endif 509 int b_vpath(register int argc,char *argv[], void *extra) 510 { 511 register int flag, n; 512 register const char *optstr; 513 register char *vend; 514 register Shell_t *shp = ((Shbltin_t*)extra)->shp; 515 if(argv[0][1]=='p') 516 { 517 optstr = sh_optvpath; 518 flag = FS3D_VIEW; 519 } 520 else 521 { 522 optstr = sh_optvmap; 523 flag = FS3D_VERSION; 524 } 525 while(n = optget(argv, optstr)) switch(n) 526 { 527 case ':': 528 errormsg(SH_DICT,2, "%s", opt_info.arg); 529 break; 530 case '?': 531 errormsg(SH_DICT,ERROR_usage(2), "%s",opt_info.arg); 532 break; 533 } 534 if(error_info.errors) 535 errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0)); 536#ifdef MS_3D 537 flag |= MS_3D; 538#else 539 if(!shp->gd->lim.fs3d) 540 goto failed; 541#endif 542 argv += opt_info.index; 543 argc -= opt_info.index; 544 switch(argc) 545 { 546 case 0: 547 case 1: 548 flag |= FS3D_GET; 549 if((n = mount(*argv,(char*)0,flag,0)) >= 0) 550 { 551 vend = stkalloc(shp->stk,++n); 552 n = mount(*argv,vend,flag|FS3D_SIZE(n),0); 553 } 554 if(n < 0) 555 goto failed; 556 if(argc==1) 557 { 558 sfprintf(sfstdout,"%s\n",vend); 559 break; 560 } 561 n = 0; 562 while(flag = *vend++) 563 { 564 if(flag==' ') 565 { 566 flag = e_sptbnl[n+1]; 567 n = !n; 568 } 569 sfputc(sfstdout,flag); 570 } 571 if(n) 572 sfputc(sfstdout,'\n'); 573 break; 574 default: 575 if((argc&1)) 576 errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0)); 577 /*FALLTHROUGH*/ 578 case 2: 579 if(shp->subshell && !shp->subshare) 580 sh_subfork(); 581 for(n=0;n<argc;n+=2) 582 if(mount(argv[n+1],argv[n],flag,0)<0) 583 goto failed; 584 } 585 return(0); 586failed: 587 errormsg(SH_DICT,ERROR_exit(1),(argc>1)?e_cantset:e_cantget,(flag&FS3D_VIEW)?e_mapping:e_versions); 588 return(1); 589 } 590#endif /* SHOPT_FS_3D */ 591 592