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