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 * 234887Schin * Shell initialization 244887Schin * 254887Schin * David Korn 264887Schin * AT&T Labs 274887Schin * 284887Schin */ 294887Schin 304887Schin #include "defs.h" 314887Schin #include <stak.h> 324887Schin #include <ctype.h> 334887Schin #include <ccode.h> 344887Schin #include <pwd.h> 35*8462SApril.Chin@Sun.COM #include <tmx.h> 364887Schin #include "variables.h" 374887Schin #include "path.h" 384887Schin #include "fault.h" 394887Schin #include "name.h" 404887Schin #include "edit.h" 414887Schin #include "jobs.h" 424887Schin #include "io.h" 434887Schin #include "shlex.h" 444887Schin #include "builtins.h" 454887Schin #include "FEATURE/time" 464887Schin #include "FEATURE/dynamic" 474887Schin #include "lexstates.h" 484887Schin #include "version.h" 494887Schin 50*8462SApril.Chin@Sun.COM char e_version[] = "\n@(#)$Id: Version " 51*8462SApril.Chin@Sun.COM #if SHOPT_AUDIT 52*8462SApril.Chin@Sun.COM #define ATTRS 1 53*8462SApril.Chin@Sun.COM "A" 54*8462SApril.Chin@Sun.COM #endif 55*8462SApril.Chin@Sun.COM #if SHOPT_BASH 56*8462SApril.Chin@Sun.COM #define ATTRS 1 57*8462SApril.Chin@Sun.COM "B" 58*8462SApril.Chin@Sun.COM #endif 59*8462SApril.Chin@Sun.COM #if SHOPT_ACCT 60*8462SApril.Chin@Sun.COM #define ATTRS 1 61*8462SApril.Chin@Sun.COM "L" 62*8462SApril.Chin@Sun.COM #endif 634887Schin #if SHOPT_MULTIBYTE 64*8462SApril.Chin@Sun.COM #define ATTRS 1 65*8462SApril.Chin@Sun.COM "M" 66*8462SApril.Chin@Sun.COM #endif 67*8462SApril.Chin@Sun.COM #if SHOPT_PFSH && _hdr_exec_attr 68*8462SApril.Chin@Sun.COM #define ATTRS 1 69*8462SApril.Chin@Sun.COM "P" 70*8462SApril.Chin@Sun.COM #endif 71*8462SApril.Chin@Sun.COM #if ATTRS 72*8462SApril.Chin@Sun.COM " " 73*8462SApril.Chin@Sun.COM #endif 74*8462SApril.Chin@Sun.COM SH_RELEASE " $\0\n"; 754887Schin 764887Schin #if SHOPT_BASH 77*8462SApril.Chin@Sun.COM extern void bash_init(Shell_t*,int); 784887Schin #endif 794887Schin 804887Schin #define RANDMASK 0x7fff 81*8462SApril.Chin@Sun.COM 82*8462SApril.Chin@Sun.COM #ifndef ARG_MAX 83*8462SApril.Chin@Sun.COM # define ARG_MAX (1*1024*1024) 84*8462SApril.Chin@Sun.COM #endif 85*8462SApril.Chin@Sun.COM #ifndef CHILD_MAX 86*8462SApril.Chin@Sun.COM # define CHILD_MAX (1*1024) 87*8462SApril.Chin@Sun.COM #endif 884887Schin #ifndef CLK_TCK 894887Schin # define CLK_TCK 60 904887Schin #endif /* CLK_TCK */ 914887Schin 924887Schin #ifndef environ 934887Schin extern char **environ; 944887Schin #endif 954887Schin 964887Schin #undef getconf 974887Schin #define getconf(x) strtol(astconf(x,NiL,NiL),NiL,0) 984887Schin 994887Schin struct seconds 1004887Schin { 1014887Schin Namfun_t hdr; 1024887Schin Shell_t *sh; 1034887Schin }; 1044887Schin 1054887Schin struct rand 1064887Schin { 1074887Schin Namfun_t hdr; 1084887Schin int32_t rand_last; 1094887Schin }; 1104887Schin 1114887Schin struct ifs 1124887Schin { 1134887Schin Namfun_t hdr; 1144887Schin Namval_t *ifsnp; 1154887Schin }; 1164887Schin 1174887Schin struct match 1184887Schin { 1194887Schin Namfun_t hdr; 1204887Schin char *val; 1214887Schin char *rval; 1224887Schin int vsize; 1234887Schin int nmatch; 1244887Schin int lastsub; 1254887Schin int match[2*(MATCH_MAX+1)]; 1264887Schin }; 1274887Schin 1284887Schin typedef struct _init_ 1294887Schin { 1304887Schin Shell_t *sh; 1314887Schin #if SHOPT_FS_3D 1324887Schin Namfun_t VPATH_init; 1334887Schin #endif /* SHOPT_FS_3D */ 1344887Schin struct ifs IFS_init; 135*8462SApril.Chin@Sun.COM Namfun_t PATH_init; 136*8462SApril.Chin@Sun.COM Namfun_t FPATH_init; 137*8462SApril.Chin@Sun.COM Namfun_t CDPATH_init; 138*8462SApril.Chin@Sun.COM Namfun_t SHELL_init; 139*8462SApril.Chin@Sun.COM Namfun_t ENV_init; 140*8462SApril.Chin@Sun.COM Namfun_t VISUAL_init; 141*8462SApril.Chin@Sun.COM Namfun_t EDITOR_init; 142*8462SApril.Chin@Sun.COM Namfun_t HISTFILE_init; 143*8462SApril.Chin@Sun.COM Namfun_t HISTSIZE_init; 144*8462SApril.Chin@Sun.COM Namfun_t OPTINDEX_init; 1454887Schin struct seconds SECONDS_init; 1464887Schin struct rand RAND_init; 147*8462SApril.Chin@Sun.COM Namfun_t LINENO_init; 148*8462SApril.Chin@Sun.COM Namfun_t L_ARG_init; 149*8462SApril.Chin@Sun.COM Namfun_t SH_VERSION_init; 1504887Schin struct match SH_MATCH_init; 1514887Schin #ifdef _hdr_locale 152*8462SApril.Chin@Sun.COM Namfun_t LC_TYPE_init; 153*8462SApril.Chin@Sun.COM Namfun_t LC_NUM_init; 154*8462SApril.Chin@Sun.COM Namfun_t LC_COLL_init; 155*8462SApril.Chin@Sun.COM Namfun_t LC_MSG_init; 156*8462SApril.Chin@Sun.COM Namfun_t LC_ALL_init; 157*8462SApril.Chin@Sun.COM Namfun_t LANG_init; 1584887Schin #endif /* _hdr_locale */ 1594887Schin } Init_t; 1604887Schin 161*8462SApril.Chin@Sun.COM static int nbltins; 1624887Schin static void env_init(Shell_t*); 1634887Schin static Init_t *nv_init(Shell_t*); 1644887Schin static Dt_t *inittree(Shell_t*,const struct shtable2*); 1654887Schin 1664887Schin #ifdef _WINIX 1674887Schin # define EXE "?(.exe)" 1684887Schin #else 1694887Schin # define EXE 1704887Schin #endif 1714887Schin 1724887Schin static int rand_shift; 1734887Schin 1744887Schin 1754887Schin /* 1764887Schin * Invalidate all path name bindings 1774887Schin */ 1784887Schin static void rehash(register Namval_t *np,void *data) 1794887Schin { 1804887Schin NOT_USED(data); 1814887Schin nv_onattr(np,NV_NOALIAS); 1824887Schin } 1834887Schin 1844887Schin /* 1854887Schin * out of memory routine for stak routines 1864887Schin */ 1874887Schin static char *nospace(int unused) 1884887Schin { 1894887Schin NOT_USED(unused); 1904887Schin errormsg(SH_DICT,ERROR_exit(3),e_nospace); 1914887Schin return(NIL(char*)); 1924887Schin } 1934887Schin 1944887Schin /* Trap for VISUAL and EDITOR variables */ 1954887Schin static void put_ed(register Namval_t* np,const char *val,int flags,Namfun_t *fp) 1964887Schin { 1974887Schin register const char *cp, *name=nv_name(np); 198*8462SApril.Chin@Sun.COM Shell_t *shp = nv_shell(np); 199*8462SApril.Chin@Sun.COM if(*name=='E' && nv_getval(sh_scoped(shp,VISINOD))) 2004887Schin goto done; 2014887Schin sh_offoption(SH_VI); 2024887Schin sh_offoption(SH_EMACS); 2034887Schin sh_offoption(SH_GMACS); 204*8462SApril.Chin@Sun.COM if(!(cp=val) && (*name=='E' || !(cp=nv_getval(sh_scoped(shp,EDITNOD))))) 2054887Schin goto done; 2064887Schin /* turn on vi or emacs option if editor name is either*/ 2074887Schin cp = path_basename(cp); 2084887Schin if(strmatch(cp,"*[Vv][Ii]*")) 2094887Schin sh_onoption(SH_VI); 2104887Schin else if(strmatch(cp,"*gmacs*")) 2114887Schin sh_onoption(SH_GMACS); 2124887Schin else if(strmatch(cp,"*macs*")) 2134887Schin sh_onoption(SH_EMACS); 2144887Schin done: 2154887Schin nv_putv(np, val, flags, fp); 2164887Schin } 2174887Schin 218*8462SApril.Chin@Sun.COM /* Trap for HISTFILE and HISTSIZE variables */ 219*8462SApril.Chin@Sun.COM static void put_history(register Namval_t* np,const char *val,int flags,Namfun_t *fp) 220*8462SApril.Chin@Sun.COM { 221*8462SApril.Chin@Sun.COM Shell_t *shp = nv_shell(np); 222*8462SApril.Chin@Sun.COM void *histopen = shp->hist_ptr; 223*8462SApril.Chin@Sun.COM if(val && histopen) 224*8462SApril.Chin@Sun.COM { 225*8462SApril.Chin@Sun.COM if(np==HISTFILE && strcmp(val,nv_getval(HISTFILE))==0) 226*8462SApril.Chin@Sun.COM return; 227*8462SApril.Chin@Sun.COM if(np==HISTSIZE && sh_arith(val)==nv_getnum(HISTSIZE)) 228*8462SApril.Chin@Sun.COM return; 229*8462SApril.Chin@Sun.COM hist_close(shp->hist_ptr); 230*8462SApril.Chin@Sun.COM } 231*8462SApril.Chin@Sun.COM nv_putv(np, val, flags, fp); 232*8462SApril.Chin@Sun.COM if(histopen) 233*8462SApril.Chin@Sun.COM { 234*8462SApril.Chin@Sun.COM if(val) 235*8462SApril.Chin@Sun.COM sh_histinit(shp); 236*8462SApril.Chin@Sun.COM else 237*8462SApril.Chin@Sun.COM hist_close(histopen); 238*8462SApril.Chin@Sun.COM } 239*8462SApril.Chin@Sun.COM } 240*8462SApril.Chin@Sun.COM 2414887Schin /* Trap for OPTINDEX */ 2424887Schin static void put_optindex(Namval_t* np,const char *val,int flags,Namfun_t *fp) 2434887Schin { 244*8462SApril.Chin@Sun.COM Shell_t *shp = nv_shell(np); 2454887Schin shp->st.opterror = shp->st.optchar = 0; 2464887Schin nv_putv(np, val, flags, fp); 247*8462SApril.Chin@Sun.COM if(!val) 248*8462SApril.Chin@Sun.COM nv_disc(np,fp,NV_POP); 2494887Schin } 2504887Schin 2514887Schin static Sfdouble_t nget_optindex(register Namval_t* np, Namfun_t *fp) 2524887Schin { 2534887Schin return((Sfdouble_t)*np->nvalue.lp); 2544887Schin } 2554887Schin 256*8462SApril.Chin@Sun.COM static Namfun_t *clone_optindex(Namval_t* np, Namval_t *mp, int flags, Namfun_t *fp) 257*8462SApril.Chin@Sun.COM { 258*8462SApril.Chin@Sun.COM Namfun_t *dp = (Namfun_t*)malloc(sizeof(Namfun_t)); 259*8462SApril.Chin@Sun.COM memcpy((void*)dp,(void*)fp,sizeof(Namfun_t)); 260*8462SApril.Chin@Sun.COM mp->nvalue.lp = np->nvalue.lp; 261*8462SApril.Chin@Sun.COM dp->nofree = 0; 262*8462SApril.Chin@Sun.COM return(dp); 263*8462SApril.Chin@Sun.COM } 264*8462SApril.Chin@Sun.COM 265*8462SApril.Chin@Sun.COM 2664887Schin /* Trap for restricted variables FPATH, PATH, SHELL, ENV */ 2674887Schin static void put_restricted(register Namval_t* np,const char *val,int flags,Namfun_t *fp) 2684887Schin { 269*8462SApril.Chin@Sun.COM Shell_t *shp = nv_shell(np); 270*8462SApril.Chin@Sun.COM int path_scoped = 0; 2714887Schin Pathcomp_t *pp; 2724887Schin char *name = nv_name(np); 2734887Schin if(!(flags&NV_RDONLY) && sh_isoption(SH_RESTRICTED)) 2744887Schin errormsg(SH_DICT,ERROR_exit(1),e_restricted,nv_name(np)); 2754887Schin if(np==PATHNOD || (path_scoped=(strcmp(name,PATHNOD->nvname)==0))) 2764887Schin { 2774887Schin nv_scan(shp->track_tree,rehash,(void*)0,NV_TAGGED,NV_TAGGED); 2784887Schin if(path_scoped && !val) 2794887Schin val = PATHNOD->nvalue.cp; 2804887Schin } 2814887Schin if(val && !(flags&NV_RDONLY) && np->nvalue.cp && strcmp(val,np->nvalue.cp)==0) 2824887Schin return; 283*8462SApril.Chin@Sun.COM if(np==FPATHNOD) 2844887Schin shp->pathlist = (void*)path_unsetfpath((Pathcomp_t*)shp->pathlist); 2854887Schin nv_putv(np, val, flags, fp); 286*8462SApril.Chin@Sun.COM shp->universe = 0; 2874887Schin if(shp->pathlist) 2884887Schin { 2894887Schin val = np->nvalue.cp; 2904887Schin if(np==PATHNOD || path_scoped) 2914887Schin pp = (void*)path_addpath((Pathcomp_t*)shp->pathlist,val,PATH_PATH); 2924887Schin else if(val && np==FPATHNOD) 2934887Schin pp = (void*)path_addpath((Pathcomp_t*)shp->pathlist,val,PATH_FPATH); 2944887Schin else 2954887Schin return; 2964887Schin if(shp->pathlist = (void*)pp) 2974887Schin pp->shp = shp; 2984887Schin if(!val && (flags&NV_NOSCOPE)) 2994887Schin { 3004887Schin Namval_t *mp = dtsearch(shp->var_tree,np); 3014887Schin if(mp && (val=nv_getval(mp))) 3024887Schin nv_putval(mp,val,NV_RDONLY); 3034887Schin } 3044887Schin #if 0 3054887Schin sfprintf(sfstderr,"%d: name=%s val=%s\n",getpid(),name,val); 3064887Schin path_dump((Pathcomp_t*)shp->pathlist); 3074887Schin #endif 3084887Schin } 3094887Schin } 3104887Schin 3114887Schin static void put_cdpath(register Namval_t* np,const char *val,int flags,Namfun_t *fp) 3124887Schin { 3134887Schin Pathcomp_t *pp; 314*8462SApril.Chin@Sun.COM Shell_t *shp = nv_shell(np); 3154887Schin nv_putv(np, val, flags, fp); 3164887Schin if(!shp->cdpathlist) 3174887Schin return; 3184887Schin val = np->nvalue.cp; 3194887Schin pp = (void*)path_addpath((Pathcomp_t*)shp->cdpathlist,val,PATH_CDPATH); 3204887Schin if(shp->cdpathlist = (void*)pp) 3214887Schin pp->shp = shp; 3224887Schin } 3234887Schin 3244887Schin #ifdef _hdr_locale 3254887Schin /* 3264887Schin * This function needs to be modified to handle international 3274887Schin * error message translations 3284887Schin */ 3294887Schin #if ERROR_VERSION >= 20000101L 3304887Schin static char* msg_translate(const char* catalog, const char* message) 3314887Schin { 3324887Schin NOT_USED(catalog); 3334887Schin return((char*)message); 3344887Schin } 3354887Schin #else 3364887Schin static char* msg_translate(const char* message, int type) 3374887Schin { 3384887Schin NOT_USED(type); 3394887Schin return((char*)message); 3404887Schin } 3414887Schin #endif 3424887Schin 3434887Schin /* Trap for LC_ALL, LC_TYPE, LC_MESSAGES, LC_COLLATE and LANG */ 3444887Schin static void put_lang(Namval_t* np,const char *val,int flags,Namfun_t *fp) 3454887Schin { 346*8462SApril.Chin@Sun.COM Shell_t *shp = nv_shell(np); 3474887Schin int type; 3484887Schin char *lc_all = nv_getval(LCALLNOD); 3494887Schin char *name = nv_name(np); 3504887Schin if(name==(LCALLNOD)->nvname) 3514887Schin type = LC_ALL; 3524887Schin else if(name==(LCTYPENOD)->nvname) 3534887Schin type = LC_CTYPE; 3544887Schin else if(name==(LCMSGNOD)->nvname) 3554887Schin type = LC_MESSAGES; 3564887Schin else if(name==(LCCOLLNOD)->nvname) 3574887Schin type = LC_COLLATE; 3584887Schin else if(name==(LCNUMNOD)->nvname) 3594887Schin type = LC_NUMERIC; 3604887Schin else if(name==(LANGNOD)->nvname && (!lc_all || *lc_all==0)) 3614887Schin type = LC_ALL; 3624887Schin else 3634887Schin type= -1; 3644887Schin if(sh_isstate(SH_INIT) && type>=0 && type!=LC_ALL && lc_all && *lc_all) 3654887Schin type= -1; 366*8462SApril.Chin@Sun.COM if(type>=0 || type==LC_ALL) 3674887Schin { 3684887Schin if(!setlocale(type,val?val:"")) 3694887Schin { 370*8462SApril.Chin@Sun.COM if(!sh_isstate(SH_INIT) || shp->login_sh==0) 3714887Schin errormsg(SH_DICT,0,e_badlocale,val); 3724887Schin return; 3734887Schin } 3744887Schin } 3754887Schin if(CC_NATIVE==CC_ASCII && (type==LC_ALL || type==LC_CTYPE)) 3764887Schin { 3774887Schin if(sh_lexstates[ST_BEGIN]!=sh_lexrstates[ST_BEGIN]) 3784887Schin free((void*)sh_lexstates[ST_BEGIN]); 3794887Schin if(ast.locale.set&(1<<AST_LC_CTYPE)) 3804887Schin { 3814887Schin register int c; 3824887Schin char *state[4]; 3834887Schin sh_lexstates[ST_BEGIN] = state[0] = (char*)malloc(4*(1<<CHAR_BIT)); 3844887Schin memcpy(state[0],sh_lexrstates[ST_BEGIN],(1<<CHAR_BIT)); 3854887Schin sh_lexstates[ST_NAME] = state[1] = state[0] + (1<<CHAR_BIT); 3864887Schin memcpy(state[1],sh_lexrstates[ST_NAME],(1<<CHAR_BIT)); 3874887Schin sh_lexstates[ST_DOL] = state[2] = state[1] + (1<<CHAR_BIT); 3884887Schin memcpy(state[2],sh_lexrstates[ST_DOL],(1<<CHAR_BIT)); 3894887Schin sh_lexstates[ST_BRACE] = state[3] = state[2] + (1<<CHAR_BIT); 3904887Schin memcpy(state[3],sh_lexrstates[ST_BRACE],(1<<CHAR_BIT)); 3914887Schin for(c=0; c<(1<<CHAR_BIT); c++) 3924887Schin { 3934887Schin if(state[0][c]!=S_REG) 3944887Schin continue; 3954887Schin if(state[2][c]!=S_ERR) 3964887Schin continue; 3974887Schin if(isblank(c)) 3984887Schin { 3994887Schin state[0][c]=0; 4004887Schin state[1][c]=S_BREAK; 4014887Schin state[2][c]=S_BREAK; 4024887Schin continue; 4034887Schin } 4044887Schin if(!isalpha(c)) 4054887Schin continue; 4064887Schin state[0][c]=S_NAME; 4074887Schin if(state[1][c]==S_REG) 4084887Schin state[1][c]=0; 4094887Schin state[2][c]=S_ALP; 4104887Schin if(state[3][c]==S_ERR) 4114887Schin state[3][c]=0; 4124887Schin } 4134887Schin } 4144887Schin else 4154887Schin { 4164887Schin sh_lexstates[ST_BEGIN]=(char*)sh_lexrstates[ST_BEGIN]; 4174887Schin sh_lexstates[ST_NAME]=(char*)sh_lexrstates[ST_NAME]; 4184887Schin sh_lexstates[ST_DOL]=(char*)sh_lexrstates[ST_DOL]; 4194887Schin sh_lexstates[ST_BRACE]=(char*)sh_lexrstates[ST_BRACE]; 4204887Schin } 4214887Schin } 4224887Schin #if ERROR_VERSION < 20000101L 4234887Schin if(type==LC_ALL || type==LC_MESSAGES) 4244887Schin error_info.translate = msg_translate; 4254887Schin #endif 4264887Schin nv_putv(np, val, flags, fp); 4274887Schin } 4284887Schin #endif /* _hdr_locale */ 4294887Schin 4304887Schin /* Trap for IFS assignment and invalidates state table */ 4314887Schin static void put_ifs(register Namval_t* np,const char *val,int flags,Namfun_t *fp) 4324887Schin { 4334887Schin register struct ifs *ip = (struct ifs*)fp; 4344887Schin ip->ifsnp = 0; 4354887Schin if(val != np->nvalue.cp) 4364887Schin nv_putv(np, val, flags, fp); 4374887Schin 4384887Schin } 4394887Schin 4404887Schin /* 4414887Schin * This is the lookup function for IFS 4424887Schin * It keeps the sh.ifstable up to date 4434887Schin */ 4444887Schin static char* get_ifs(register Namval_t* np, Namfun_t *fp) 4454887Schin { 4464887Schin register struct ifs *ip = (struct ifs*)fp; 4474887Schin register char *cp, *value; 4484887Schin register int c,n; 449*8462SApril.Chin@Sun.COM register Shell_t *shp = nv_shell(np); 4504887Schin value = nv_getv(np,fp); 4514887Schin if(np!=ip->ifsnp) 4524887Schin { 4534887Schin ip->ifsnp = np; 4544887Schin memset(shp->ifstable,0,(1<<CHAR_BIT)); 4554887Schin if(cp=value) 4564887Schin { 4574887Schin #if SHOPT_MULTIBYTE 4584887Schin while(n=mbsize(cp),c= *(unsigned char*)cp) 4594887Schin #else 4604887Schin while(c= *(unsigned char*)cp++) 4614887Schin #endif /* SHOPT_MULTIBYTE */ 4624887Schin { 4634887Schin #if SHOPT_MULTIBYTE 4644887Schin cp++; 4654887Schin if(n>1) 4664887Schin { 4674887Schin cp += (n-1); 4684887Schin shp->ifstable[c] = S_MBYTE; 4694887Schin continue; 4704887Schin } 4714887Schin #endif /* SHOPT_MULTIBYTE */ 4724887Schin n = S_DELIM; 4734887Schin if(c== *cp) 4744887Schin cp++; 4754887Schin else if(c=='\n') 4764887Schin n = S_NL; 4774887Schin else if(isspace(c)) 4784887Schin n = S_SPACE; 4794887Schin shp->ifstable[c] = n; 4804887Schin } 4814887Schin } 4824887Schin else 4834887Schin { 4844887Schin shp->ifstable[' '] = shp->ifstable['\t'] = S_SPACE; 4854887Schin shp->ifstable['\n'] = S_NL; 4864887Schin } 4874887Schin } 4884887Schin return(value); 4894887Schin } 4904887Schin 4914887Schin /* 4924887Schin * these functions are used to get and set the SECONDS variable 4934887Schin */ 4944887Schin #ifdef timeofday 4954887Schin # define dtime(tp) ((double)((tp)->tv_sec)+1e-6*((double)((tp)->tv_usec))) 4964887Schin # define tms timeval 4974887Schin #else 4984887Schin # define dtime(tp) (((double)times(tp))/sh.lim.clk_tck) 4994887Schin # define timeofday(a) 5004887Schin #endif 5014887Schin 5024887Schin static void put_seconds(register Namval_t* np,const char *val,int flags,Namfun_t *fp) 5034887Schin { 5044887Schin double d; 5054887Schin struct tms tp; 5064887Schin if(!val) 5074887Schin { 5084887Schin nv_stack(np, NIL(Namfun_t*)); 5094887Schin nv_unset(np); 5104887Schin return; 5114887Schin } 5124887Schin if(!np->nvalue.dp) 5134887Schin { 5144887Schin nv_setsize(np,3); 515*8462SApril.Chin@Sun.COM nv_onattr(np,NV_DOUBLE); 5164887Schin np->nvalue.dp = new_of(double,0); 5174887Schin } 5184887Schin nv_putv(np, val, flags, fp); 5194887Schin d = *np->nvalue.dp; 5204887Schin timeofday(&tp); 5214887Schin *np->nvalue.dp = dtime(&tp)-d; 5224887Schin } 5234887Schin 5244887Schin static char* get_seconds(register Namval_t* np, Namfun_t *fp) 5254887Schin { 526*8462SApril.Chin@Sun.COM Shell_t *shp = nv_shell(np); 5274887Schin register int places = nv_size(np); 5284887Schin struct tms tp; 5294887Schin double d, offset = (np->nvalue.dp?*np->nvalue.dp:0); 5304887Schin NOT_USED(fp); 5314887Schin timeofday(&tp); 5324887Schin d = dtime(&tp)- offset; 533*8462SApril.Chin@Sun.COM sfprintf(shp->strbuf,"%.*f",places,d); 534*8462SApril.Chin@Sun.COM return(sfstruse(shp->strbuf)); 5354887Schin } 5364887Schin 5374887Schin static Sfdouble_t nget_seconds(register Namval_t* np, Namfun_t *fp) 5384887Schin { 5394887Schin struct tms tp; 5404887Schin double offset = (np->nvalue.dp?*np->nvalue.dp:0); 5414887Schin NOT_USED(fp); 5424887Schin timeofday(&tp); 5434887Schin return(dtime(&tp)- offset); 5444887Schin } 5454887Schin 5464887Schin /* 5474887Schin * These three functions are used to get and set the RANDOM variable 5484887Schin */ 5494887Schin static void put_rand(register Namval_t* np,const char *val,int flags,Namfun_t *fp) 5504887Schin { 5514887Schin struct rand *rp = (struct rand*)fp; 5524887Schin register long n; 5534887Schin if(!val) 5544887Schin { 5554887Schin nv_stack(np, NIL(Namfun_t*)); 5564887Schin nv_unset(np); 5574887Schin return; 5584887Schin } 5594887Schin if(flags&NV_INTEGER) 5604887Schin n = *(double*)val; 5614887Schin else 5624887Schin n = sh_arith(val); 5634887Schin srand((int)(n&RANDMASK)); 5644887Schin rp->rand_last = -1; 5654887Schin if(!np->nvalue.lp) 5664887Schin np->nvalue.lp = &rp->rand_last; 5674887Schin } 5684887Schin 5694887Schin /* 5704887Schin * get random number in range of 0 - 2**15 5714887Schin * never pick same number twice in a row 5724887Schin */ 5734887Schin static Sfdouble_t nget_rand(register Namval_t* np, Namfun_t *fp) 5744887Schin { 5754887Schin register long cur, last= *np->nvalue.lp; 5764887Schin NOT_USED(fp); 5774887Schin do 5784887Schin cur = (rand()>>rand_shift)&RANDMASK; 5794887Schin while(cur==last); 5804887Schin *np->nvalue.lp = cur; 5814887Schin return((Sfdouble_t)cur); 5824887Schin } 5834887Schin 5844887Schin static char* get_rand(register Namval_t* np, Namfun_t *fp) 5854887Schin { 5864887Schin register long n = nget_rand(np,fp); 5874887Schin return(fmtbase(n, 10, 0)); 5884887Schin } 5894887Schin 5904887Schin /* 5914887Schin * These three routines are for LINENO 5924887Schin */ 5934887Schin static Sfdouble_t nget_lineno(Namval_t* np, Namfun_t *fp) 5944887Schin { 5954887Schin double d=1; 5964887Schin if(error_info.line >0) 5974887Schin d = error_info.line; 5984887Schin else if(error_info.context && error_info.context->line>0) 5994887Schin d = error_info.context->line; 6004887Schin NOT_USED(np); 6014887Schin NOT_USED(fp); 6024887Schin return(d); 6034887Schin } 6044887Schin 6054887Schin static void put_lineno(Namval_t* np,const char *val,int flags,Namfun_t *fp) 6064887Schin { 6074887Schin register long n; 608*8462SApril.Chin@Sun.COM Shell_t *shp = nv_shell(np); 6094887Schin if(!val) 6104887Schin { 6114887Schin nv_stack(np, NIL(Namfun_t*)); 6124887Schin nv_unset(np); 6134887Schin return; 6144887Schin } 6154887Schin if(flags&NV_INTEGER) 6164887Schin n = *(double*)val; 6174887Schin else 6184887Schin n = sh_arith(val); 6194887Schin shp->st.firstline += nget_lineno(np,fp)+1-n; 6204887Schin } 6214887Schin 6224887Schin static char* get_lineno(register Namval_t* np, Namfun_t *fp) 6234887Schin { 6244887Schin register long n = nget_lineno(np,fp); 6254887Schin return(fmtbase(n, 10, 0)); 6264887Schin } 6274887Schin 6284887Schin static char* get_lastarg(Namval_t* np, Namfun_t *fp) 6294887Schin { 630*8462SApril.Chin@Sun.COM Shell_t *shp = nv_shell(np); 6314887Schin NOT_USED(np); 632*8462SApril.Chin@Sun.COM return(shp->lastarg); 6334887Schin } 6344887Schin 6354887Schin static void put_lastarg(Namval_t* np,const char *val,int flags,Namfun_t *fp) 6364887Schin { 637*8462SApril.Chin@Sun.COM Shell_t *shp = nv_shell(np); 6384887Schin if(flags&NV_INTEGER) 6394887Schin { 640*8462SApril.Chin@Sun.COM sfprintf(shp->strbuf,"%.*g",12,*((double*)val)); 641*8462SApril.Chin@Sun.COM val = sfstruse(shp->strbuf); 6424887Schin } 643*8462SApril.Chin@Sun.COM if(shp->lastarg && !nv_isattr(np,NV_NOFREE)) 644*8462SApril.Chin@Sun.COM free((void*)shp->lastarg); 6454887Schin else 6464887Schin nv_offattr(np,NV_NOFREE); 6474887Schin if(val) 648*8462SApril.Chin@Sun.COM shp->lastarg = strdup(val); 6494887Schin else 650*8462SApril.Chin@Sun.COM shp->lastarg = 0; 6514887Schin } 6524887Schin 6534887Schin static int hasgetdisc(register Namfun_t *fp) 6544887Schin { 6554887Schin while(fp && !fp->disc->getnum && !fp->disc->getval) 6564887Schin fp = fp->next; 6574887Schin return(fp!=0); 6584887Schin } 6594887Schin 6604887Schin /* 6614887Schin * store the most recent value for use in .sh.match 6624887Schin */ 6634887Schin void sh_setmatch(const char *v, int vsize, int nmatch, int match[]) 6644887Schin { 6654887Schin struct match *mp = (struct match*)(SH_MATCHNOD->nvfun); 6664887Schin register int i,n; 6674887Schin if(mp->nmatch = nmatch) 6684887Schin { 6694887Schin memcpy(mp->match,match,nmatch*2*sizeof(match[0])); 6704887Schin for(n=match[0],i=1; i < 2*nmatch; i++) 6714887Schin { 6724887Schin if(mp->match[i] < n) 6734887Schin n = mp->match[i]; 6744887Schin } 6754887Schin for(vsize=0,i=0; i < 2*nmatch; i++) 6764887Schin { 6774887Schin if((mp->match[i] -= n) > vsize) 6784887Schin vsize = mp->match[i]; 6794887Schin } 6804887Schin v += n; 6814887Schin if(vsize >= mp->vsize) 6824887Schin { 6834887Schin if(mp->vsize) 6844887Schin mp->val = (char*)realloc(mp->val,vsize+1); 6854887Schin else 6864887Schin mp->val = (char*)malloc(vsize+1); 6874887Schin mp->vsize = vsize; 6884887Schin } 6894887Schin memcpy(mp->val,v,vsize); 6904887Schin mp->val[vsize] = 0; 691*8462SApril.Chin@Sun.COM nv_putsub(SH_MATCHNOD, NIL(char*), (nmatch-1)|ARRAY_FILL); 6924887Schin mp->lastsub = -1; 6934887Schin } 6944887Schin } 6954887Schin 6964887Schin #define array_scan(np) ((nv_arrayptr(np)->nelem&ARRAY_SCAN)) 6974887Schin 6984887Schin static char* get_match(register Namval_t* np, Namfun_t *fp) 6994887Schin { 7004887Schin struct match *mp = (struct match*)fp; 7014887Schin int sub,n; 7024887Schin char *val; 7034887Schin sub = nv_aindex(np); 7044887Schin if(sub>=mp->nmatch) 7054887Schin return(0); 7064887Schin if(sub==mp->lastsub) 7074887Schin return(mp->rval); 7084887Schin if(mp->rval) 7094887Schin { 7104887Schin free((void*)mp->rval); 7114887Schin mp->rval = 0; 7124887Schin } 7134887Schin n = mp->match[2*sub+1]-mp->match[2*sub]; 7144887Schin if(n<=0) 7154887Schin return(""); 7164887Schin val = mp->val+mp->match[2*sub]; 7174887Schin if(mp->val[mp->match[2*sub+1]]==0) 7184887Schin return(val); 7194887Schin mp->rval = (char*)malloc(n+1); 7204887Schin mp->lastsub = sub; 7214887Schin memcpy(mp->rval,val,n); 7224887Schin mp->rval[n] = 0; 7234887Schin return(mp->rval); 7244887Schin } 7254887Schin 726*8462SApril.Chin@Sun.COM static const Namdisc_t SH_MATCH_disc = { sizeof(struct match), 0, get_match }; 727*8462SApril.Chin@Sun.COM 728*8462SApril.Chin@Sun.COM static char* get_version(register Namval_t* np, Namfun_t *fp) 729*8462SApril.Chin@Sun.COM { 730*8462SApril.Chin@Sun.COM return(nv_getv(np,fp)); 731*8462SApril.Chin@Sun.COM } 732*8462SApril.Chin@Sun.COM 733*8462SApril.Chin@Sun.COM static Sfdouble_t nget_version(register Namval_t* np, Namfun_t *fp) 734*8462SApril.Chin@Sun.COM { 735*8462SApril.Chin@Sun.COM register const char *cp = e_version + strlen(e_version)-10; 736*8462SApril.Chin@Sun.COM register int c; 737*8462SApril.Chin@Sun.COM Sflong_t t = 0; 738*8462SApril.Chin@Sun.COM NOT_USED(fp); 739*8462SApril.Chin@Sun.COM 740*8462SApril.Chin@Sun.COM while (c = *cp++) 741*8462SApril.Chin@Sun.COM if (c >= '0' && c <= '9') 742*8462SApril.Chin@Sun.COM { 743*8462SApril.Chin@Sun.COM t *= 10; 744*8462SApril.Chin@Sun.COM t += c - '0'; 745*8462SApril.Chin@Sun.COM } 746*8462SApril.Chin@Sun.COM return((Sfdouble_t)t); 747*8462SApril.Chin@Sun.COM } 748*8462SApril.Chin@Sun.COM 749*8462SApril.Chin@Sun.COM static const Namdisc_t SH_VERSION_disc = { 0, 0, get_version, nget_version }; 7504887Schin 7514887Schin #if SHOPT_FS_3D 7524887Schin /* 7534887Schin * set or unset the mappings given a colon separated list of directories 7544887Schin */ 7554887Schin static void vpath_set(char *str, int mode) 7564887Schin { 7574887Schin register char *lastp, *oldp=str, *newp=strchr(oldp,':'); 7584887Schin if(!sh.lim.fs3d) 7594887Schin return; 7604887Schin while(newp) 7614887Schin { 7624887Schin *newp++ = 0; 7634887Schin if(lastp=strchr(newp,':')) 7644887Schin *lastp = 0; 7654887Schin mount((mode?newp:""),oldp,FS3D_VIEW,0); 7664887Schin newp[-1] = ':'; 7674887Schin oldp = newp; 7684887Schin newp=lastp; 7694887Schin } 7704887Schin } 7714887Schin 7724887Schin /* catch vpath assignments */ 7734887Schin static void put_vpath(register Namval_t* np,const char *val,int flags,Namfun_t *fp) 7744887Schin { 7754887Schin register char *cp; 7764887Schin if(cp = nv_getval(np)) 7774887Schin vpath_set(cp,0); 7784887Schin if(val) 7794887Schin vpath_set((char*)val,1); 7804887Schin nv_putv(np,val,flags,fp); 7814887Schin } 7824887Schin static const Namdisc_t VPATH_disc = { 0, put_vpath }; 7834887Schin static Namfun_t VPATH_init = { &VPATH_disc, 1 }; 7844887Schin #endif /* SHOPT_FS_3D */ 7854887Schin 7864887Schin 7874887Schin static const Namdisc_t IFS_disc = { sizeof(struct ifs), put_ifs, get_ifs }; 788*8462SApril.Chin@Sun.COM const Namdisc_t RESTRICTED_disc = { sizeof(Namfun_t), put_restricted }; 789*8462SApril.Chin@Sun.COM static const Namdisc_t CDPATH_disc = { sizeof(Namfun_t), put_cdpath }; 790*8462SApril.Chin@Sun.COM static const Namdisc_t EDITOR_disc = { sizeof(Namfun_t), put_ed }; 791*8462SApril.Chin@Sun.COM static const Namdisc_t HISTFILE_disc = { sizeof(Namfun_t), put_history }; 792*8462SApril.Chin@Sun.COM static const Namdisc_t OPTINDEX_disc = { sizeof(Namfun_t), put_optindex, 0, nget_optindex, 0, 0, clone_optindex }; 7934887Schin static const Namdisc_t SECONDS_disc = { sizeof(struct seconds), put_seconds, get_seconds, nget_seconds }; 7944887Schin static const Namdisc_t RAND_disc = { sizeof(struct rand), put_rand, get_rand, nget_rand }; 795*8462SApril.Chin@Sun.COM static const Namdisc_t LINENO_disc = { sizeof(Namfun_t), put_lineno, get_lineno, nget_lineno }; 796*8462SApril.Chin@Sun.COM static const Namdisc_t L_ARG_disc = { sizeof(Namfun_t), put_lastarg, get_lastarg }; 7974887Schin 7984887Schin #if SHOPT_NAMESPACE 7994887Schin static char* get_nspace(Namval_t* np, Namfun_t *fp) 8004887Schin { 8014887Schin if(sh.namespace) 8024887Schin return(nv_name(sh.namespace)); 8034887Schin return((char*)np->nvalue.cp); 8044887Schin } 8054887Schin static const Namdisc_t NSPACE_disc = { 0, 0, get_nspace }; 8064887Schin static Namfun_t NSPACE_init = { &NSPACE_disc, 1}; 8074887Schin #endif /* SHOPT_NAMESPACE */ 8084887Schin 8094887Schin #ifdef _hdr_locale 810*8462SApril.Chin@Sun.COM static const Namdisc_t LC_disc = { sizeof(Namfun_t), put_lang }; 8114887Schin #endif /* _hdr_locale */ 8124887Schin 8134887Schin /* 8144887Schin * This function will get called whenever a configuration parameter changes 8154887Schin */ 8164887Schin static int newconf(const char *name, const char *path, const char *value) 8174887Schin { 8184887Schin register char *arg; 8194887Schin if(!name) 8204887Schin setenviron(value); 8214887Schin else if(strcmp(name,"UNIVERSE")==0 && strcmp(astconf(name,0,0),value)) 8224887Schin { 8234887Schin sh.universe = 0; 8244887Schin /* set directory in new universe */ 8254887Schin if(*(arg = path_pwd(0))=='/') 8264887Schin chdir(arg); 8274887Schin /* clear out old tracked alias */ 8284887Schin stakseek(0); 8294887Schin stakputs(nv_getval(PATHNOD)); 8304887Schin stakputc(0); 8314887Schin nv_putval(PATHNOD,stakseek(0),NV_RDONLY); 8324887Schin } 8334887Schin return(1); 8344887Schin } 8354887Schin 8364887Schin #if (CC_NATIVE != CC_ASCII) 8374887Schin static void a2e(char *d, const char *s) 8384887Schin { 8394887Schin register const unsigned char *t; 8404887Schin register int i; 8414887Schin t = CCMAP(CC_ASCII, CC_NATIVE); 8424887Schin for(i=0; i<(1<<CHAR_BIT); i++) 8434887Schin d[t[i]] = s[i]; 8444887Schin } 8454887Schin 8464887Schin static void init_ebcdic(void) 8474887Schin { 8484887Schin int i; 8494887Schin char *cp = (char*)malloc(ST_NONE*(1<<CHAR_BIT)); 8504887Schin for(i=0; i < ST_NONE; i++) 8514887Schin { 8524887Schin a2e(cp,sh_lexrstates[i]); 8534887Schin sh_lexstates[i] = cp; 8544887Schin cp += (1<<CHAR_BIT); 8554887Schin } 8564887Schin } 8574887Schin #endif 8584887Schin 8594887Schin /* 8604887Schin * return SH_TYPE_* bitmask for path 8614887Schin * 0 for "not a shell" 8624887Schin */ 8634887Schin int sh_type(register const char *path) 8644887Schin { 8654887Schin register const char* s; 8664887Schin register int t = 0; 8674887Schin 8684887Schin if (s = (const char*)strrchr(path, '/')) 8694887Schin { 8704887Schin if (*path == '-') 8714887Schin t |= SH_TYPE_LOGIN; 8724887Schin s++; 8734887Schin } 8744887Schin else 8754887Schin s = path; 8764887Schin if (*s == '-') 8774887Schin { 8784887Schin s++; 8794887Schin t |= SH_TYPE_LOGIN; 8804887Schin } 8814887Schin for (;;) 8824887Schin { 8834887Schin if (!(t & (SH_TYPE_KSH|SH_TYPE_BASH))) 8844887Schin { 8854887Schin if (*s == 'k') 8864887Schin { 8874887Schin s++; 8884887Schin t |= SH_TYPE_KSH; 8894887Schin continue; 8904887Schin } 8914887Schin #if SHOPT_BASH 8924887Schin if (*s == 'b' && *(s+1) == 'a') 8934887Schin { 8944887Schin s += 2; 8954887Schin t |= SH_TYPE_BASH; 8964887Schin continue; 8974887Schin } 8984887Schin #endif 8994887Schin } 9004887Schin if (!(t & (SH_TYPE_PROFILE|SH_TYPE_RESTRICTED))) 9014887Schin { 9024887Schin #if SHOPT_PFSH 9034887Schin if (*s == 'p' && *(s+1) == 'f') 9044887Schin { 9054887Schin s += 2; 9064887Schin t |= SH_TYPE_PROFILE; 9074887Schin continue; 9084887Schin } 9094887Schin #endif 9104887Schin if (*s == 'r') 9114887Schin { 9124887Schin s++; 9134887Schin t |= SH_TYPE_RESTRICTED; 9144887Schin continue; 9154887Schin } 9164887Schin } 9174887Schin break; 9184887Schin } 919*8462SApril.Chin@Sun.COM if (*s++ == 's' && (*s == 'h' || *s == 'u')) 920*8462SApril.Chin@Sun.COM { 921*8462SApril.Chin@Sun.COM s++; 922*8462SApril.Chin@Sun.COM t |= SH_TYPE_SH; 923*8462SApril.Chin@Sun.COM if ((t & SH_TYPE_KSH) && *s == '9' && *(s+1) == '3') 924*8462SApril.Chin@Sun.COM s += 2; 9254887Schin #if _WINIX 926*8462SApril.Chin@Sun.COM if (*s == '.' && *(s+1) == 'e' && *(s+2) == 'x' && *(s+3) == 'e') 927*8462SApril.Chin@Sun.COM s += 4; 9284887Schin #endif 929*8462SApril.Chin@Sun.COM if (!isalnum(*s)) 930*8462SApril.Chin@Sun.COM return t; 931*8462SApril.Chin@Sun.COM } 932*8462SApril.Chin@Sun.COM return t & ~(SH_TYPE_BASH|SH_TYPE_KSH|SH_TYPE_PROFILE|SH_TYPE_RESTRICTED); 933*8462SApril.Chin@Sun.COM } 934*8462SApril.Chin@Sun.COM 935*8462SApril.Chin@Sun.COM 936*8462SApril.Chin@Sun.COM static char *get_mode(Namval_t* np, Namfun_t* nfp) 937*8462SApril.Chin@Sun.COM { 938*8462SApril.Chin@Sun.COM mode_t mode = nv_getn(np,nfp); 939*8462SApril.Chin@Sun.COM return(fmtperm(mode)); 9404887Schin } 9414887Schin 942*8462SApril.Chin@Sun.COM static void put_mode(Namval_t* np, const char* val, int flag, Namfun_t* nfp) 943*8462SApril.Chin@Sun.COM { 944*8462SApril.Chin@Sun.COM if(val) 945*8462SApril.Chin@Sun.COM { 946*8462SApril.Chin@Sun.COM mode_t mode; 947*8462SApril.Chin@Sun.COM char *last; 948*8462SApril.Chin@Sun.COM if(flag&NV_INTEGER) 949*8462SApril.Chin@Sun.COM { 950*8462SApril.Chin@Sun.COM if(flag&NV_LONG) 951*8462SApril.Chin@Sun.COM mode = *(Sfdouble_t*)val; 952*8462SApril.Chin@Sun.COM else 953*8462SApril.Chin@Sun.COM mode = *(double*)val; 954*8462SApril.Chin@Sun.COM } 955*8462SApril.Chin@Sun.COM else 956*8462SApril.Chin@Sun.COM mode = strperm(val, &last,0); 957*8462SApril.Chin@Sun.COM if(*last) 958*8462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_exit(1),"%s: invalid mode string",val); 959*8462SApril.Chin@Sun.COM nv_putv(np,(char*)&mode,NV_INTEGER,nfp); 960*8462SApril.Chin@Sun.COM } 961*8462SApril.Chin@Sun.COM else 962*8462SApril.Chin@Sun.COM nv_putv(np,val,flag,nfp); 963*8462SApril.Chin@Sun.COM } 964*8462SApril.Chin@Sun.COM 965*8462SApril.Chin@Sun.COM static const Namdisc_t modedisc = 966*8462SApril.Chin@Sun.COM { 967*8462SApril.Chin@Sun.COM 0, 968*8462SApril.Chin@Sun.COM put_mode, 969*8462SApril.Chin@Sun.COM get_mode, 970*8462SApril.Chin@Sun.COM }; 971*8462SApril.Chin@Sun.COM 972*8462SApril.Chin@Sun.COM 9734887Schin /* 9744887Schin * initialize the shell 9754887Schin */ 976*8462SApril.Chin@Sun.COM Shell_t *sh_init(register int argc,register char *argv[], Shinit_f userinit) 9774887Schin { 978*8462SApril.Chin@Sun.COM Shell_t *shp = &sh; 9794887Schin register int n; 9804887Schin int type; 9814887Schin static char *login_files[3]; 9824887Schin n = strlen(e_version); 9834887Schin if(e_version[n-1]=='$' && e_version[n-2]==' ') 9844887Schin e_version[n-2]=0; 9854887Schin #if (CC_NATIVE == CC_ASCII) 9864887Schin memcpy(sh_lexstates,sh_lexrstates,ST_NONE*sizeof(char*)); 9874887Schin #else 9884887Schin init_ebcdic(); 9894887Schin #endif 990*8462SApril.Chin@Sun.COM umask(shp->mask=umask(0)); 991*8462SApril.Chin@Sun.COM shp->mac_context = sh_macopen(shp); 992*8462SApril.Chin@Sun.COM shp->arg_context = sh_argopen(shp); 993*8462SApril.Chin@Sun.COM shp->lex_context = (void*)sh_lexopen(0,shp,1); 994*8462SApril.Chin@Sun.COM shp->ed_context = (void*)ed_open(shp); 995*8462SApril.Chin@Sun.COM shp->strbuf = sfstropen(); 996*8462SApril.Chin@Sun.COM shp->stk = stkstd; 997*8462SApril.Chin@Sun.COM sfsetbuf(shp->strbuf,(char*)0,64); 9984887Schin sh_onstate(SH_INIT); 9994887Schin error_info.exit = sh_exit; 10004887Schin error_info.id = path_basename(argv[0]); 10014887Schin #if ERROR_VERSION >= 20000102L 10024887Schin error_info.catalog = e_dict; 10034887Schin #endif 1004*8462SApril.Chin@Sun.COM shp->cpipe[0] = -1; 1005*8462SApril.Chin@Sun.COM shp->coutpipe = -1; 1006*8462SApril.Chin@Sun.COM shp->userid=getuid(); 1007*8462SApril.Chin@Sun.COM shp->euserid=geteuid(); 1008*8462SApril.Chin@Sun.COM shp->groupid=getgid(); 1009*8462SApril.Chin@Sun.COM shp->egroupid=getegid(); 10104887Schin for(n=0;n < 10; n++) 10114887Schin { 10124887Schin /* don't use lower bits when rand() generates large numbers */ 10134887Schin if(rand() > RANDMASK) 10144887Schin { 10154887Schin rand_shift = 3; 10164887Schin break; 10174887Schin } 10184887Schin } 1019*8462SApril.Chin@Sun.COM shp->lim.clk_tck = getconf("CLK_TCK"); 1020*8462SApril.Chin@Sun.COM shp->lim.arg_max = getconf("ARG_MAX"); 1021*8462SApril.Chin@Sun.COM shp->lim.open_max = getconf("OPEN_MAX"); 1022*8462SApril.Chin@Sun.COM shp->lim.child_max = getconf("CHILD_MAX"); 1023*8462SApril.Chin@Sun.COM shp->lim.ngroups_max = getconf("NGROUPS_MAX"); 1024*8462SApril.Chin@Sun.COM shp->lim.posix_version = getconf("VERSION"); 1025*8462SApril.Chin@Sun.COM shp->lim.posix_jobcontrol = getconf("JOB_CONTROL"); 1026*8462SApril.Chin@Sun.COM if(shp->lim.arg_max <=0) 1027*8462SApril.Chin@Sun.COM shp->lim.arg_max = ARG_MAX; 1028*8462SApril.Chin@Sun.COM if(shp->lim.child_max <=0) 1029*8462SApril.Chin@Sun.COM shp->lim.child_max = CHILD_MAX; 1030*8462SApril.Chin@Sun.COM if(shp->lim.open_max <0) 1031*8462SApril.Chin@Sun.COM shp->lim.open_max = OPEN_MAX; 1032*8462SApril.Chin@Sun.COM if(shp->lim.open_max > (SHRT_MAX-2)) 1033*8462SApril.Chin@Sun.COM shp->lim.open_max = SHRT_MAX-2; 1034*8462SApril.Chin@Sun.COM if(shp->lim.clk_tck <=0) 1035*8462SApril.Chin@Sun.COM shp->lim.clk_tck = CLK_TCK; 10364887Schin #if SHOPT_FS_3D 10374887Schin if(fs3d(FS3D_TEST)) 1038*8462SApril.Chin@Sun.COM shp->lim.fs3d = 1; 10394887Schin #endif /* SHOPT_FS_3D */ 1040*8462SApril.Chin@Sun.COM sh_ioinit(shp); 10414887Schin /* initialize signal handling */ 1042*8462SApril.Chin@Sun.COM sh_siginit(shp); 10434887Schin stakinstall(NIL(Stak_t*),nospace); 10444887Schin /* set up memory for name-value pairs */ 1045*8462SApril.Chin@Sun.COM shp->init_context = nv_init(shp); 10464887Schin /* read the environment */ 10474887Schin if(argc>0) 10484887Schin { 10494887Schin type = sh_type(*argv); 10504887Schin if(type&SH_TYPE_LOGIN) 1051*8462SApril.Chin@Sun.COM shp->login_sh = 2; 10524887Schin } 1053*8462SApril.Chin@Sun.COM env_init(shp); 1054*8462SApril.Chin@Sun.COM *SHLVL->nvalue.ip +=1; 10554887Schin #if SHOPT_SPAWN 10564887Schin { 10574887Schin /* 10584887Schin * try to find the pathname for this interpreter 10594887Schin * try using environment variable _ or argv[0] 10604887Schin */ 10614887Schin char *last, *cp=nv_getval(L_ARGNOD); 10624887Schin char buff[PATH_MAX+1]; 1063*8462SApril.Chin@Sun.COM shp->shpath = 0; 1064*8462SApril.Chin@Sun.COM sfprintf(shp->strbuf,"/proc/%d/exe",getpid()); 1065*8462SApril.Chin@Sun.COM if((n=readlink(sfstruse(shp->strbuf),buff,sizeof(buff)-1))>0) 10664887Schin { 10674887Schin buff[n] = 0; 1068*8462SApril.Chin@Sun.COM shp->shpath = strdup(buff); 10694887Schin } 10704887Schin else if((cp && (sh_type(cp)&SH_TYPE_SH)) || (argc>0 && strchr(cp= *argv,'/'))) 10714887Schin { 10724887Schin if(*cp=='/') 1073*8462SApril.Chin@Sun.COM shp->shpath = strdup(cp); 10744887Schin else if(cp = nv_getval(PWDNOD)) 10754887Schin { 10764887Schin int offset = staktell(); 10774887Schin stakputs(cp); 10784887Schin stakputc('/'); 10794887Schin stakputs(argv[0]); 10804887Schin pathcanon(stakptr(offset),PATH_DOTDOT); 1081*8462SApril.Chin@Sun.COM shp->shpath = strdup(stakptr(offset)); 10824887Schin stakseek(offset); 10834887Schin } 10844887Schin } 10854887Schin } 10864887Schin #endif 10874887Schin nv_putval(IFSNOD,(char*)e_sptbnl,NV_RDONLY); 10884887Schin #if SHOPT_FS_3D 10894887Schin nv_stack(VPATHNOD, &VPATH_init); 10904887Schin #endif /* SHOPT_FS_3D */ 10914887Schin astconfdisc(newconf); 10924887Schin #if SHOPT_TIMEOUT 1093*8462SApril.Chin@Sun.COM shp->st.tmout = SHOPT_TIMEOUT; 10944887Schin #endif /* SHOPT_TIMEOUT */ 10954887Schin /* initialize jobs table */ 10964887Schin job_clear(); 10974887Schin if(argc>0) 10984887Schin { 10994887Schin /* check for restricted shell */ 11004887Schin if(type&SH_TYPE_RESTRICTED) 11014887Schin sh_onoption(SH_RESTRICTED); 11024887Schin #if SHOPT_PFSH 11034887Schin /* check for profile shell */ 11044887Schin else if(type&SH_TYPE_PROFILE) 11054887Schin sh_onoption(SH_PFSH); 11064887Schin #endif 11074887Schin #if SHOPT_BASH 11084887Schin /* check for invocation as bash */ 11094887Schin if(type&SH_TYPE_BASH) 11104887Schin { 1111*8462SApril.Chin@Sun.COM shp->userinit = userinit = bash_init; 11124887Schin sh_onoption(SH_BASH); 11134887Schin sh_onstate(SH_PREINIT); 1114*8462SApril.Chin@Sun.COM (*userinit)(shp, 0); 11154887Schin sh_offstate(SH_PREINIT); 11164887Schin } 11174887Schin #endif 11184887Schin /* look for options */ 1119*8462SApril.Chin@Sun.COM /* shp->st.dolc is $# */ 1120*8462SApril.Chin@Sun.COM if((shp->st.dolc = sh_argopts(-argc,argv,shp)) < 0) 11214887Schin { 1122*8462SApril.Chin@Sun.COM shp->exitval = 2; 1123*8462SApril.Chin@Sun.COM sh_done(shp,0); 11244887Schin } 11254887Schin opt_info.disc = 0; 1126*8462SApril.Chin@Sun.COM shp->st.dolv=argv+(argc-1)-shp->st.dolc; 1127*8462SApril.Chin@Sun.COM shp->st.dolv[0] = argv[0]; 1128*8462SApril.Chin@Sun.COM if(shp->st.dolc < 1) 11294887Schin sh_onoption(SH_SFLAG); 11304887Schin if(!sh_isoption(SH_SFLAG)) 11314887Schin { 1132*8462SApril.Chin@Sun.COM shp->st.dolc--; 1133*8462SApril.Chin@Sun.COM shp->st.dolv++; 11344887Schin #if _WINIX 11354887Schin { 11364887Schin char* name; 1137*8462SApril.Chin@Sun.COM name = shp->st.dolv[0]; 11384887Schin if(name[1]==':' && (name[2]=='/' || name[2]=='\\')) 11394887Schin { 11404887Schin #if _lib_pathposix 11414887Schin char* p; 11424887Schin 11434887Schin if((n = pathposix(name, NIL(char*), 0)) > 0 && (p = (char*)malloc(++n))) 11444887Schin { 11454887Schin pathposix(name, p, n); 11464887Schin name = p; 11474887Schin } 11484887Schin else 11494887Schin #endif 11504887Schin { 11514887Schin name[1] = name[0]; 11524887Schin name[0] = name[2] = '/'; 11534887Schin } 11544887Schin } 11554887Schin } 11564887Schin #endif /* _WINIX */ 11574887Schin } 11584887Schin } 11594887Schin #if SHOPT_PFSH 11604887Schin if (sh_isoption(SH_PFSH)) 11614887Schin { 1162*8462SApril.Chin@Sun.COM struct passwd *pw = getpwuid(shp->userid); 11634887Schin if(pw) 1164*8462SApril.Chin@Sun.COM shp->user = strdup(pw->pw_name); 11654887Schin 11664887Schin } 11674887Schin #endif 11684887Schin /* set[ug]id scripts require the -p flag */ 1169*8462SApril.Chin@Sun.COM if(shp->userid!=shp->euserid || shp->groupid!=shp->egroupid) 11704887Schin { 11714887Schin #if SHOPT_P_SUID 11724887Schin /* require sh -p to run setuid and/or setgid */ 1173*8462SApril.Chin@Sun.COM if(!sh_isoption(SH_PRIVILEGED) && shp->euserid < SHOPT_P_SUID) 11744887Schin { 1175*8462SApril.Chin@Sun.COM setuid(shp->euserid=shp->userid); 1176*8462SApril.Chin@Sun.COM setgid(shp->egroupid=shp->groupid); 11774887Schin } 11784887Schin else 11794887Schin #else 11804887Schin sh_onoption(SH_PRIVILEGED); 11814887Schin #endif /* SHOPT_P_SUID */ 11824887Schin #ifdef SHELLMAGIC 11834887Schin /* careful of #! setuid scripts with name beginning with - */ 1184*8462SApril.Chin@Sun.COM if(shp->login_sh && argv[1] && strcmp(argv[0],argv[1])==0) 11854887Schin errormsg(SH_DICT,ERROR_exit(1),e_prohibited); 11864887Schin #endif /*SHELLMAGIC*/ 11874887Schin } 11884887Schin else 11894887Schin sh_offoption(SH_PRIVILEGED); 11904887Schin /* shname for $0 in profiles and . scripts */ 11914887Schin if(strmatch(argv[1],e_devfdNN)) 1192*8462SApril.Chin@Sun.COM shp->shname = strdup(argv[0]); 11934887Schin else 1194*8462SApril.Chin@Sun.COM shp->shname = strdup(shp->st.dolv[0]); 11954887Schin /* 11964887Schin * return here for shell script execution 11974887Schin * but not for parenthesis subshells 11984887Schin */ 1199*8462SApril.Chin@Sun.COM error_info.id = strdup(shp->st.dolv[0]); /* error_info.id is $0 */ 1200*8462SApril.Chin@Sun.COM shp->jmpbuffer = (void*)&shp->checkbase; 1201*8462SApril.Chin@Sun.COM sh_pushcontext(&shp->checkbase,SH_JMPSCRIPT); 1202*8462SApril.Chin@Sun.COM shp->st.self = &shp->global; 1203*8462SApril.Chin@Sun.COM shp->topscope = (Shscope_t*)shp->st.self; 12044887Schin sh_offstate(SH_INIT); 12054887Schin login_files[0] = (char*)e_profile; 12064887Schin login_files[1] = ".profile"; 1207*8462SApril.Chin@Sun.COM shp->login_files = login_files; 1208*8462SApril.Chin@Sun.COM shp->bltindata.version = SH_VERSION; 1209*8462SApril.Chin@Sun.COM shp->bltindata.shp = shp; 1210*8462SApril.Chin@Sun.COM shp->bltindata.shrun = sh_run; 1211*8462SApril.Chin@Sun.COM shp->bltindata.shtrap = sh_trap; 1212*8462SApril.Chin@Sun.COM shp->bltindata.shexit = sh_exit; 1213*8462SApril.Chin@Sun.COM shp->bltindata.shbltin = sh_addbuiltin; 1214*8462SApril.Chin@Sun.COM #if _AST_VERSION >= 20080617L 1215*8462SApril.Chin@Sun.COM shp->bltindata.shgetenv = getenv; 1216*8462SApril.Chin@Sun.COM shp->bltindata.shsetenv = setenviron; 1217*8462SApril.Chin@Sun.COM astintercept(&shp->bltindata,1); 1218*8462SApril.Chin@Sun.COM #endif 1219*8462SApril.Chin@Sun.COM #if 0 1220*8462SApril.Chin@Sun.COM #define NV_MKINTTYPE(x,y,z) nv_mkinttype(#x,sizeof(x),(x)-1<0,(y),(Namdisc_t*)z); 1221*8462SApril.Chin@Sun.COM NV_MKINTTYPE(pid_t,"process id",0); 1222*8462SApril.Chin@Sun.COM NV_MKINTTYPE(gid_t,"group id",0); 1223*8462SApril.Chin@Sun.COM NV_MKINTTYPE(uid_t,"user id",0); 1224*8462SApril.Chin@Sun.COM NV_MKINTTYPE(size_t,(const char*)0,0); 1225*8462SApril.Chin@Sun.COM NV_MKINTTYPE(ssize_t,(const char*)0,0); 1226*8462SApril.Chin@Sun.COM NV_MKINTTYPE(off_t,"offset in bytes",0); 1227*8462SApril.Chin@Sun.COM NV_MKINTTYPE(ino_t,"\ai-\anode number",0); 1228*8462SApril.Chin@Sun.COM NV_MKINTTYPE(mode_t,(const char*)0,&modedisc); 1229*8462SApril.Chin@Sun.COM NV_MKINTTYPE(dev_t,"device id",0); 1230*8462SApril.Chin@Sun.COM NV_MKINTTYPE(nlink_t,"hard link count",0); 1231*8462SApril.Chin@Sun.COM NV_MKINTTYPE(blkcnt_t,"block count",0); 1232*8462SApril.Chin@Sun.COM NV_MKINTTYPE(time_t,"seconds since the epoch",0); 1233*8462SApril.Chin@Sun.COM nv_mkstat(); 1234*8462SApril.Chin@Sun.COM #endif 1235*8462SApril.Chin@Sun.COM if(shp->userinit=userinit) 1236*8462SApril.Chin@Sun.COM (*userinit)(shp, 0); 1237*8462SApril.Chin@Sun.COM return(shp); 12384887Schin } 12394887Schin 12404887Schin Shell_t *sh_getinterp(void) 12414887Schin { 12424887Schin return(&sh); 12434887Schin } 12444887Schin 12454887Schin /* 12464887Schin * reinitialize before executing a script 12474887Schin */ 12484887Schin int sh_reinit(char *argv[]) 12494887Schin { 1250*8462SApril.Chin@Sun.COM Shell_t *shp = &sh; 12514887Schin Shopt_t opt; 1252*8462SApril.Chin@Sun.COM Namval_t *np,*npnext; 1253*8462SApril.Chin@Sun.COM Dt_t *dp; 1254*8462SApril.Chin@Sun.COM for(np=dtfirst(shp->fun_tree);np;np=npnext) 12554887Schin { 1256*8462SApril.Chin@Sun.COM if((dp=shp->fun_tree)->walk) 1257*8462SApril.Chin@Sun.COM dp = dp->walk; 1258*8462SApril.Chin@Sun.COM npnext = (Namval_t*)dtnext(shp->fun_tree,np); 1259*8462SApril.Chin@Sun.COM if(np>= shp->bltin_cmds && np < &shp->bltin_cmds[nbltins]) 1260*8462SApril.Chin@Sun.COM continue; 1261*8462SApril.Chin@Sun.COM if(is_abuiltin(np) && nv_isattr(np,NV_EXPORT)) 1262*8462SApril.Chin@Sun.COM continue; 1263*8462SApril.Chin@Sun.COM if(*np->nvname=='/') 1264*8462SApril.Chin@Sun.COM continue; 1265*8462SApril.Chin@Sun.COM nv_delete(np,dp,NV_NOFREE); 1266*8462SApril.Chin@Sun.COM } 1267*8462SApril.Chin@Sun.COM dtclose(shp->alias_tree); 1268*8462SApril.Chin@Sun.COM shp->alias_tree = inittree(shp,shtab_aliases); 1269*8462SApril.Chin@Sun.COM shp->last_root = shp->var_tree; 1270*8462SApril.Chin@Sun.COM shp->namespace = 0; 1271*8462SApril.Chin@Sun.COM shp->inuse_bits = 0; 1272*8462SApril.Chin@Sun.COM if(shp->userinit) 1273*8462SApril.Chin@Sun.COM (*shp->userinit)(shp, 1); 1274*8462SApril.Chin@Sun.COM if(shp->heredocs) 1275*8462SApril.Chin@Sun.COM { 1276*8462SApril.Chin@Sun.COM sfclose(shp->heredocs); 1277*8462SApril.Chin@Sun.COM shp->heredocs = 0; 12784887Schin } 12794887Schin /* remove locals */ 12804887Schin sh_onstate(SH_INIT); 1281*8462SApril.Chin@Sun.COM nv_scan(shp->var_tree,sh_envnolocal,(void*)0,NV_EXPORT,0); 1282*8462SApril.Chin@Sun.COM nv_scan(shp->var_tree,sh_envnolocal,(void*)0,NV_ARRAY,NV_ARRAY); 12834887Schin sh_offstate(SH_INIT); 1284*8462SApril.Chin@Sun.COM memset(shp->st.trapcom,0,(shp->st.trapmax+1)*sizeof(char*)); 12854887Schin memset((void*)&opt,0,sizeof(opt)); 12864887Schin if(sh_isoption(SH_TRACKALL)) 12874887Schin on_option(&opt,SH_TRACKALL); 12884887Schin if(sh_isoption(SH_EMACS)) 12894887Schin on_option(&opt,SH_EMACS); 12904887Schin if(sh_isoption(SH_GMACS)) 12914887Schin on_option(&opt,SH_GMACS); 12924887Schin if(sh_isoption(SH_VI)) 12934887Schin on_option(&opt,SH_VI); 12944887Schin if(sh_isoption(SH_VIRAW)) 12954887Schin on_option(&opt,SH_VIRAW); 1296*8462SApril.Chin@Sun.COM shp->options = opt; 12974887Schin /* set up new args */ 12984887Schin if(argv) 1299*8462SApril.Chin@Sun.COM shp->arglist = sh_argcreate(argv); 1300*8462SApril.Chin@Sun.COM if(shp->arglist) 1301*8462SApril.Chin@Sun.COM sh_argreset(shp,shp->arglist,NIL(struct dolnod*)); 1302*8462SApril.Chin@Sun.COM shp->envlist=0; 1303*8462SApril.Chin@Sun.COM shp->curenv = 0; 1304*8462SApril.Chin@Sun.COM shp->shname = error_info.id = strdup(shp->st.dolv[0]); 13054887Schin sh_offstate(SH_FORKED); 1306*8462SApril.Chin@Sun.COM shp->fn_depth = shp->dot_depth = 0; 13074887Schin sh_sigreset(0); 1308*8462SApril.Chin@Sun.COM *SHLVL->nvalue.ip +=1; 13094887Schin return(1); 13104887Schin } 13114887Schin 13124887Schin /* 13134887Schin * set when creating a local variable of this name 13144887Schin */ 13154887Schin Namfun_t *nv_cover(register Namval_t *np) 13164887Schin { 13174887Schin if(np==IFSNOD || np==PATHNOD || np==SHELLNOD || np==FPATHNOD || np==CDPNOD || np==SECONDS) 13184887Schin return(np->nvfun); 13194887Schin #ifdef _hdr_locale 13204887Schin if(np==LCALLNOD || np==LCTYPENOD || np==LCMSGNOD || np==LCCOLLNOD || np==LCNUMNOD || np==LANGNOD) 13214887Schin return(np->nvfun); 13224887Schin #endif 13234887Schin return(0); 13244887Schin } 13254887Schin 13264887Schin static const char *shdiscnames[] = { "tilde", 0}; 13274887Schin 1328*8462SApril.Chin@Sun.COM #ifdef SHOPT_STATS 1329*8462SApril.Chin@Sun.COM struct Stats 1330*8462SApril.Chin@Sun.COM { 1331*8462SApril.Chin@Sun.COM Namfun_t hdr; 1332*8462SApril.Chin@Sun.COM Shell_t *sh; 1333*8462SApril.Chin@Sun.COM char *nodes; 1334*8462SApril.Chin@Sun.COM int numnodes; 1335*8462SApril.Chin@Sun.COM int current; 1336*8462SApril.Chin@Sun.COM }; 1337*8462SApril.Chin@Sun.COM 1338*8462SApril.Chin@Sun.COM static Namval_t *next_stat(register Namval_t* np, Dt_t *root,Namfun_t *fp) 1339*8462SApril.Chin@Sun.COM { 1340*8462SApril.Chin@Sun.COM struct Stats *sp = (struct Stats*)fp; 1341*8462SApril.Chin@Sun.COM if(!root) 1342*8462SApril.Chin@Sun.COM sp->current = 0; 1343*8462SApril.Chin@Sun.COM else if(++sp->current>=sp->numnodes) 1344*8462SApril.Chin@Sun.COM return(0); 1345*8462SApril.Chin@Sun.COM return(nv_namptr(sp->nodes,sp->current)); 1346*8462SApril.Chin@Sun.COM } 1347*8462SApril.Chin@Sun.COM 1348*8462SApril.Chin@Sun.COM static Namval_t *create_stat(Namval_t *np,const char *name,int flag,Namfun_t *fp) 1349*8462SApril.Chin@Sun.COM { 1350*8462SApril.Chin@Sun.COM struct Stats *sp = (struct Stats*)fp; 1351*8462SApril.Chin@Sun.COM register const char *cp=name; 1352*8462SApril.Chin@Sun.COM register int i=0,n; 1353*8462SApril.Chin@Sun.COM Namval_t *nq=0; 1354*8462SApril.Chin@Sun.COM Shell_t *shp = sp->sh; 1355*8462SApril.Chin@Sun.COM if(!name) 1356*8462SApril.Chin@Sun.COM return(SH_STATS); 1357*8462SApril.Chin@Sun.COM while((i=*cp++) && i != '=' && i != '+' && i!='['); 1358*8462SApril.Chin@Sun.COM n = (cp-1) -name; 1359*8462SApril.Chin@Sun.COM for(i=0; i < sp->numnodes; i++) 1360*8462SApril.Chin@Sun.COM { 1361*8462SApril.Chin@Sun.COM nq = nv_namptr(sp->nodes,i); 1362*8462SApril.Chin@Sun.COM if((n==0||memcmp(name,nq->nvname,n)==0) && nq->nvname[n]==0) 1363*8462SApril.Chin@Sun.COM goto found; 1364*8462SApril.Chin@Sun.COM } 1365*8462SApril.Chin@Sun.COM nq = 0; 1366*8462SApril.Chin@Sun.COM found: 1367*8462SApril.Chin@Sun.COM if(nq) 1368*8462SApril.Chin@Sun.COM { 1369*8462SApril.Chin@Sun.COM fp->last = (char*)&name[n]; 1370*8462SApril.Chin@Sun.COM shp->last_table = SH_STATS; 1371*8462SApril.Chin@Sun.COM } 1372*8462SApril.Chin@Sun.COM else 1373*8462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_exit(1),e_notelem,n,name,nv_name(np)); 1374*8462SApril.Chin@Sun.COM return(nq); 1375*8462SApril.Chin@Sun.COM } 1376*8462SApril.Chin@Sun.COM 1377*8462SApril.Chin@Sun.COM static const Namdisc_t stat_disc = 1378*8462SApril.Chin@Sun.COM { 1379*8462SApril.Chin@Sun.COM 0, 0, 0, 0, 0, 1380*8462SApril.Chin@Sun.COM create_stat, 1381*8462SApril.Chin@Sun.COM 0, 0, 1382*8462SApril.Chin@Sun.COM next_stat 1383*8462SApril.Chin@Sun.COM }; 1384*8462SApril.Chin@Sun.COM 1385*8462SApril.Chin@Sun.COM static char *name_stat(Namval_t *np, Namfun_t *fp) 1386*8462SApril.Chin@Sun.COM { 1387*8462SApril.Chin@Sun.COM Shell_t *shp = sh_getinterp(); 1388*8462SApril.Chin@Sun.COM sfprintf(shp->strbuf,".sh.stats.%s",np->nvname); 1389*8462SApril.Chin@Sun.COM return(sfstruse(shp->strbuf)); 1390*8462SApril.Chin@Sun.COM } 1391*8462SApril.Chin@Sun.COM 1392*8462SApril.Chin@Sun.COM static const Namdisc_t stat_child_disc = 1393*8462SApril.Chin@Sun.COM { 1394*8462SApril.Chin@Sun.COM 0,0,0,0,0,0,0, 1395*8462SApril.Chin@Sun.COM name_stat 1396*8462SApril.Chin@Sun.COM }; 1397*8462SApril.Chin@Sun.COM 1398*8462SApril.Chin@Sun.COM static Namfun_t stat_child_fun = 1399*8462SApril.Chin@Sun.COM { 1400*8462SApril.Chin@Sun.COM &stat_child_disc, 1, 0, sizeof(Namfun_t) 1401*8462SApril.Chin@Sun.COM }; 1402*8462SApril.Chin@Sun.COM 1403*8462SApril.Chin@Sun.COM static void stat_init(Shell_t *shp) 1404*8462SApril.Chin@Sun.COM { 1405*8462SApril.Chin@Sun.COM int i,nstat = STAT_SUBSHELL+1; 1406*8462SApril.Chin@Sun.COM struct Stats *sp = newof(0,struct Stats,1,nstat*NV_MINSZ); 1407*8462SApril.Chin@Sun.COM Namval_t *np; 1408*8462SApril.Chin@Sun.COM sp->numnodes = nstat; 1409*8462SApril.Chin@Sun.COM sp->nodes = (char*)(sp+1); 1410*8462SApril.Chin@Sun.COM shp->stats = (int*)calloc(sizeof(int*),nstat); 1411*8462SApril.Chin@Sun.COM sp->sh = shp; 1412*8462SApril.Chin@Sun.COM for(i=0; i < nstat; i++) 1413*8462SApril.Chin@Sun.COM { 1414*8462SApril.Chin@Sun.COM np = nv_namptr(sp->nodes,i); 1415*8462SApril.Chin@Sun.COM np->nvfun = &stat_child_fun; 1416*8462SApril.Chin@Sun.COM np->nvname = (char*)shtab_stats[i].sh_name; 1417*8462SApril.Chin@Sun.COM nv_onattr(np,NV_RDONLY|NV_MINIMAL|NV_NOFREE|NV_INTEGER); 1418*8462SApril.Chin@Sun.COM nv_setsize(np,10); 1419*8462SApril.Chin@Sun.COM np->nvalue.ip = &shp->stats[i]; 1420*8462SApril.Chin@Sun.COM } 1421*8462SApril.Chin@Sun.COM sp->hdr.dsize = sizeof(struct Stats) + nstat*(sizeof(int)+NV_MINSZ); 1422*8462SApril.Chin@Sun.COM sp->hdr.disc = &stat_disc; 1423*8462SApril.Chin@Sun.COM nv_stack(SH_STATS,&sp->hdr); 1424*8462SApril.Chin@Sun.COM sp->hdr.nofree = 1; 1425*8462SApril.Chin@Sun.COM nv_setvtree(SH_STATS); 1426*8462SApril.Chin@Sun.COM } 1427*8462SApril.Chin@Sun.COM #else 1428*8462SApril.Chin@Sun.COM # define stat_init(x) 1429*8462SApril.Chin@Sun.COM #endif /* SHOPT_STATS */ 1430*8462SApril.Chin@Sun.COM 14314887Schin /* 14324887Schin * Initialize the shell name and alias table 14334887Schin */ 14344887Schin static Init_t *nv_init(Shell_t *shp) 14354887Schin { 1436*8462SApril.Chin@Sun.COM static int shlvl=0; 14374887Schin Namval_t *np; 14384887Schin register Init_t *ip; 14394887Schin double d=0; 14404887Schin ip = newof(0,Init_t,1,0); 14414887Schin if(!ip) 14424887Schin return(0); 1443*8462SApril.Chin@Sun.COM shp->nvfun.last = (char*)shp; 1444*8462SApril.Chin@Sun.COM shp->nvfun.nofree = 1; 14454887Schin ip->sh = shp; 14464887Schin shp->var_base = shp->var_tree = inittree(shp,shtab_variables); 1447*8462SApril.Chin@Sun.COM SHLVL->nvalue.ip = &shlvl; 14484887Schin ip->IFS_init.hdr.disc = &IFS_disc; 14494887Schin ip->IFS_init.hdr.nofree = 1; 1450*8462SApril.Chin@Sun.COM ip->PATH_init.disc = &RESTRICTED_disc; 1451*8462SApril.Chin@Sun.COM ip->PATH_init.nofree = 1; 1452*8462SApril.Chin@Sun.COM ip->FPATH_init.disc = &RESTRICTED_disc; 1453*8462SApril.Chin@Sun.COM ip->FPATH_init.nofree = 1; 1454*8462SApril.Chin@Sun.COM ip->CDPATH_init.disc = &CDPATH_disc; 1455*8462SApril.Chin@Sun.COM ip->CDPATH_init.nofree = 1; 1456*8462SApril.Chin@Sun.COM ip->SHELL_init.disc = &RESTRICTED_disc; 1457*8462SApril.Chin@Sun.COM ip->SHELL_init.nofree = 1; 1458*8462SApril.Chin@Sun.COM ip->ENV_init.disc = &RESTRICTED_disc; 1459*8462SApril.Chin@Sun.COM ip->ENV_init.nofree = 1; 1460*8462SApril.Chin@Sun.COM ip->VISUAL_init.disc = &EDITOR_disc; 1461*8462SApril.Chin@Sun.COM ip->VISUAL_init.nofree = 1; 1462*8462SApril.Chin@Sun.COM ip->EDITOR_init.disc = &EDITOR_disc; 1463*8462SApril.Chin@Sun.COM ip->EDITOR_init.nofree = 1; 1464*8462SApril.Chin@Sun.COM ip->HISTFILE_init.disc = &HISTFILE_disc; 1465*8462SApril.Chin@Sun.COM ip->HISTFILE_init.nofree = 1; 1466*8462SApril.Chin@Sun.COM ip->HISTSIZE_init.disc = &HISTFILE_disc; 1467*8462SApril.Chin@Sun.COM ip->HISTSIZE_init.nofree = 1; 1468*8462SApril.Chin@Sun.COM ip->OPTINDEX_init.disc = &OPTINDEX_disc; 1469*8462SApril.Chin@Sun.COM ip->OPTINDEX_init.nofree = 1; 14704887Schin ip->SECONDS_init.hdr.disc = &SECONDS_disc; 14714887Schin ip->SECONDS_init.hdr.nofree = 1; 14724887Schin ip->RAND_init.hdr.disc = &RAND_disc; 14734887Schin ip->RAND_init.hdr.nofree = 1; 14744887Schin ip->SH_MATCH_init.hdr.disc = &SH_MATCH_disc; 14754887Schin ip->SH_MATCH_init.hdr.nofree = 1; 1476*8462SApril.Chin@Sun.COM ip->SH_VERSION_init.disc = &SH_VERSION_disc; 1477*8462SApril.Chin@Sun.COM ip->SH_VERSION_init.nofree = 1; 1478*8462SApril.Chin@Sun.COM ip->LINENO_init.disc = &LINENO_disc; 1479*8462SApril.Chin@Sun.COM ip->LINENO_init.nofree = 1; 1480*8462SApril.Chin@Sun.COM ip->L_ARG_init.disc = &L_ARG_disc; 1481*8462SApril.Chin@Sun.COM ip->L_ARG_init.nofree = 1; 14824887Schin #ifdef _hdr_locale 1483*8462SApril.Chin@Sun.COM ip->LC_TYPE_init.disc = &LC_disc; 1484*8462SApril.Chin@Sun.COM ip->LC_TYPE_init.nofree = 1; 1485*8462SApril.Chin@Sun.COM ip->LC_NUM_init.disc = &LC_disc; 1486*8462SApril.Chin@Sun.COM ip->LC_NUM_init.nofree = 1; 1487*8462SApril.Chin@Sun.COM ip->LC_COLL_init.disc = &LC_disc; 1488*8462SApril.Chin@Sun.COM ip->LC_COLL_init.nofree = 1; 1489*8462SApril.Chin@Sun.COM ip->LC_MSG_init.disc = &LC_disc; 1490*8462SApril.Chin@Sun.COM ip->LC_MSG_init.nofree = 1; 1491*8462SApril.Chin@Sun.COM ip->LC_ALL_init.disc = &LC_disc; 1492*8462SApril.Chin@Sun.COM ip->LC_ALL_init.nofree = 1; 1493*8462SApril.Chin@Sun.COM ip->LANG_init.disc = &LC_disc; 1494*8462SApril.Chin@Sun.COM ip->LANG_init.nofree = 1; 14954887Schin #endif /* _hdr_locale */ 14964887Schin nv_stack(IFSNOD, &ip->IFS_init.hdr); 1497*8462SApril.Chin@Sun.COM nv_stack(PATHNOD, &ip->PATH_init); 1498*8462SApril.Chin@Sun.COM nv_stack(FPATHNOD, &ip->FPATH_init); 1499*8462SApril.Chin@Sun.COM nv_stack(CDPNOD, &ip->CDPATH_init); 1500*8462SApril.Chin@Sun.COM nv_stack(SHELLNOD, &ip->SHELL_init); 1501*8462SApril.Chin@Sun.COM nv_stack(ENVNOD, &ip->ENV_init); 1502*8462SApril.Chin@Sun.COM nv_stack(VISINOD, &ip->VISUAL_init); 1503*8462SApril.Chin@Sun.COM nv_stack(EDITNOD, &ip->EDITOR_init); 1504*8462SApril.Chin@Sun.COM nv_stack(HISTFILE, &ip->HISTFILE_init); 1505*8462SApril.Chin@Sun.COM nv_stack(HISTSIZE, &ip->HISTSIZE_init); 1506*8462SApril.Chin@Sun.COM nv_stack(OPTINDNOD, &ip->OPTINDEX_init); 15074887Schin nv_stack(SECONDS, &ip->SECONDS_init.hdr); 1508*8462SApril.Chin@Sun.COM nv_stack(L_ARGNOD, &ip->L_ARG_init); 1509*8462SApril.Chin@Sun.COM nv_putval(SECONDS, (char*)&d, NV_DOUBLE); 15104887Schin nv_stack(RANDNOD, &ip->RAND_init.hdr); 15114887Schin d = (shp->pid&RANDMASK); 1512*8462SApril.Chin@Sun.COM nv_putval(RANDNOD, (char*)&d, NV_DOUBLE); 1513*8462SApril.Chin@Sun.COM nv_stack(LINENO, &ip->LINENO_init); 15144887Schin nv_putsub(SH_MATCHNOD,(char*)0,10); 15154887Schin nv_onattr(SH_MATCHNOD,NV_RDONLY); 15164887Schin nv_stack(SH_MATCHNOD, &ip->SH_MATCH_init.hdr); 1517*8462SApril.Chin@Sun.COM nv_stack(SH_VERSIONNOD, &ip->SH_VERSION_init); 15184887Schin #ifdef _hdr_locale 1519*8462SApril.Chin@Sun.COM nv_stack(LCTYPENOD, &ip->LC_TYPE_init); 1520*8462SApril.Chin@Sun.COM nv_stack(LCALLNOD, &ip->LC_ALL_init); 1521*8462SApril.Chin@Sun.COM nv_stack(LCMSGNOD, &ip->LC_MSG_init); 1522*8462SApril.Chin@Sun.COM nv_stack(LCCOLLNOD, &ip->LC_COLL_init); 1523*8462SApril.Chin@Sun.COM nv_stack(LCNUMNOD, &ip->LC_NUM_init); 1524*8462SApril.Chin@Sun.COM nv_stack(LANGNOD, &ip->LANG_init); 15254887Schin #endif /* _hdr_locale */ 15264887Schin (PPIDNOD)->nvalue.lp = (&shp->ppid); 15274887Schin (TMOUTNOD)->nvalue.lp = (&shp->st.tmout); 15284887Schin (MCHKNOD)->nvalue.lp = (&sh_mailchk); 15294887Schin (OPTINDNOD)->nvalue.lp = (&shp->st.optindex); 15304887Schin /* set up the seconds clock */ 15314887Schin shp->alias_tree = inittree(shp,shtab_aliases); 15324887Schin shp->track_tree = dtopen(&_Nvdisc,Dtset); 15334887Schin shp->bltin_tree = inittree(shp,(const struct shtable2*)shtab_builtins); 15344887Schin shp->fun_tree = dtopen(&_Nvdisc,Dtoset); 15354887Schin dtview(shp->fun_tree,shp->bltin_tree); 15364887Schin #if SHOPT_NAMESPACE 15374887Schin if(np = nv_mount(DOTSHNOD, "global", shp->var_tree)) 15384887Schin nv_onattr(np,NV_RDONLY); 15394887Schin np = nv_search("namespace",nv_dict(DOTSHNOD),NV_ADD); 15404887Schin nv_putval(np,".sh.global",NV_RDONLY|NV_NOFREE); 15414887Schin nv_stack(np, &NSPACE_init); 15424887Schin #endif /* SHOPT_NAMESPACE */ 1543*8462SApril.Chin@Sun.COM np = nv_mount(DOTSHNOD, "type", shp->typedict=dtopen(&_Nvdisc,Dtoset)); 15444887Schin nv_adddisc(DOTSHNOD, shdiscnames, (Namval_t**)0); 1545*8462SApril.Chin@Sun.COM SH_LINENO->nvalue.ip = &shp->st.lineno; 1546*8462SApril.Chin@Sun.COM VERSIONNOD->nvalue.nrp = newof(0,struct Namref,1,0); 1547*8462SApril.Chin@Sun.COM VERSIONNOD->nvalue.nrp->np = SH_VERSIONNOD; 1548*8462SApril.Chin@Sun.COM VERSIONNOD->nvalue.nrp->root = nv_dict(DOTSHNOD); 1549*8462SApril.Chin@Sun.COM VERSIONNOD->nvalue.nrp->table = DOTSHNOD; 1550*8462SApril.Chin@Sun.COM nv_onattr(VERSIONNOD,NV_RDONLY|NV_REF); 1551*8462SApril.Chin@Sun.COM stat_init(shp); 15524887Schin return(ip); 15534887Schin } 15544887Schin 15554887Schin /* 15564887Schin * initialize name-value pairs 15574887Schin */ 15584887Schin 15594887Schin static Dt_t *inittree(Shell_t *shp,const struct shtable2 *name_vals) 15604887Schin { 15614887Schin register Namval_t *np; 15624887Schin register const struct shtable2 *tp; 15634887Schin register unsigned n = 0; 15644887Schin register Dt_t *treep; 15654887Schin Dt_t *base_treep, *dict; 15664887Schin for(tp=name_vals;*tp->sh_name;tp++) 15674887Schin n++; 15684887Schin np = (Namval_t*)calloc(n,sizeof(Namval_t)); 15694887Schin if(!shp->bltin_nodes) 1570*8462SApril.Chin@Sun.COM { 15714887Schin shp->bltin_nodes = np; 1572*8462SApril.Chin@Sun.COM shp->bltin_nnodes = n; 1573*8462SApril.Chin@Sun.COM } 15744887Schin else if(name_vals==(const struct shtable2*)shtab_builtins) 1575*8462SApril.Chin@Sun.COM { 15764887Schin shp->bltin_cmds = np; 1577*8462SApril.Chin@Sun.COM nbltins = n; 1578*8462SApril.Chin@Sun.COM } 15794887Schin base_treep = treep = dtopen(&_Nvdisc,Dtoset); 1580*8462SApril.Chin@Sun.COM treep->user = (void*)shp; 15814887Schin for(tp=name_vals;*tp->sh_name;tp++,np++) 15824887Schin { 15834887Schin if((np->nvname = strrchr(tp->sh_name,'.')) && np->nvname!=((char*)tp->sh_name)) 15844887Schin np->nvname++; 15854887Schin else 15864887Schin { 15874887Schin np->nvname = (char*)tp->sh_name; 15884887Schin treep = base_treep; 15894887Schin } 15904887Schin np->nvenv = 0; 15914887Schin if(name_vals==(const struct shtable2*)shtab_builtins) 15924887Schin np->nvalue.bfp = ((struct shtable3*)tp)->sh_value; 15934887Schin else 1594*8462SApril.Chin@Sun.COM { 1595*8462SApril.Chin@Sun.COM if(name_vals == shtab_variables) 1596*8462SApril.Chin@Sun.COM np->nvfun = &sh.nvfun; 15974887Schin np->nvalue.cp = (char*)tp->sh_value; 1598*8462SApril.Chin@Sun.COM } 15994887Schin nv_setattr(np,tp->sh_number); 16004887Schin if(nv_istable(np)) 16014887Schin nv_mount(np,(const char*)0,dict=dtopen(&_Nvdisc,Dtoset)); 16024887Schin if(nv_isattr(np,NV_INTEGER)) 16034887Schin nv_setsize(np,10); 16044887Schin else 16054887Schin nv_setsize(np,0); 16064887Schin dtinsert(treep,np); 16074887Schin if(nv_istable(np)) 16084887Schin treep = dict; 16094887Schin } 16104887Schin return(treep); 16114887Schin } 16124887Schin 16134887Schin /* 16144887Schin * read in the process environment and set up name-value pairs 16154887Schin * skip over items that are not name-value pairs 16164887Schin */ 16174887Schin 16184887Schin static void env_init(Shell_t *shp) 16194887Schin { 16204887Schin register char *cp; 16214887Schin register Namval_t *np; 16224887Schin register char **ep=environ; 16234887Schin register char *next=0; 16244887Schin #ifdef _ENV_H 16254887Schin shp->env = env_open(environ,3); 16264887Schin env_delete(shp->env,"_"); 16274887Schin #endif 16284887Schin if(ep) 16294887Schin { 16304887Schin while(cp= *ep++) 16314887Schin { 16324887Schin if(*cp=='A' && cp[1]=='_' && cp[2]=='_' && cp[3]=='z' && cp[4]=='=') 16334887Schin next = cp+4; 16344887Schin else if(np=nv_open(cp,shp->var_tree,(NV_EXPORT|NV_IDENT|NV_ASSIGN|NV_NOFAIL))) 16354887Schin { 16364887Schin nv_onattr(np,NV_IMPORT); 16374887Schin np->nvenv = cp; 16384887Schin nv_close(np); 16394887Schin } 1640*8462SApril.Chin@Sun.COM else /* swap with fron */ 1641*8462SApril.Chin@Sun.COM { 1642*8462SApril.Chin@Sun.COM ep[-1] = environ[shp->nenv]; 1643*8462SApril.Chin@Sun.COM environ[shp->nenv++] = cp; 1644*8462SApril.Chin@Sun.COM } 16454887Schin } 16464887Schin while(cp=next) 16474887Schin { 16484887Schin if(next = strchr(++cp,'=')) 16494887Schin *next = 0; 16504887Schin np = nv_search(cp+2,shp->var_tree,NV_ADD); 16514887Schin if(nv_isattr(np,NV_IMPORT|NV_EXPORT)) 16524887Schin { 16534887Schin int flag = *(unsigned char*)cp-' '; 16544887Schin int size = *(unsigned char*)(cp+1)-' '; 16554887Schin if((flag&NV_INTEGER) && size==0) 16564887Schin { 16574887Schin /* check for floating*/ 16584887Schin char *ep,*val = nv_getval(np); 16594887Schin strtol(val,&ep,10); 16604887Schin if(*ep=='.' || *ep=='e' || *ep=='E') 16614887Schin { 16624887Schin char *lp; 16634887Schin flag |= NV_DOUBLE; 16644887Schin if(*ep=='.') 16654887Schin { 16664887Schin strtol(ep+1,&lp,10); 16674887Schin if(*lp) 16684887Schin ep = lp; 16694887Schin } 16704887Schin if(*ep && *ep!='.') 16714887Schin { 16724887Schin flag |= NV_EXPNOTE; 16734887Schin size = ep-val; 16744887Schin } 16754887Schin else 16764887Schin size = strlen(ep); 16774887Schin size--; 16784887Schin } 16794887Schin } 16804887Schin nv_newattr(np,flag|NV_IMPORT|NV_EXPORT,size); 16814887Schin } 16824887Schin } 16834887Schin } 16844887Schin #ifdef _ENV_H 1685*8462SApril.Chin@Sun.COM env_delete(shp->env,e_envmarker); 16864887Schin #endif 16874887Schin if(nv_isnull(PWDNOD) || nv_isattr(PWDNOD,NV_TAGGED)) 16884887Schin { 16894887Schin nv_offattr(PWDNOD,NV_TAGGED); 16904887Schin path_pwd(0); 16914887Schin } 16924887Schin if((cp = nv_getval(SHELLNOD)) && (sh_type(cp)&SH_TYPE_RESTRICTED)) 16934887Schin sh_onoption(SH_RESTRICTED); /* restricted shell */ 16944887Schin return; 16954887Schin } 16964887Schin 16974887Schin /* 16984887Schin * terminate shell and free up the space 16994887Schin */ 17004887Schin int sh_term(void) 17014887Schin { 17024887Schin sfdisc(sfstdin,SF_POPDISC); 17034887Schin free((char*)sh.outbuff); 17044887Schin stakset(NIL(char*),0); 17054887Schin return(0); 17064887Schin } 17074887Schin 17084887Schin /* function versions of these */ 17094887Schin 17104887Schin #define DISABLE /* proto workaround */ 17114887Schin 17124887Schin unsigned long sh_isoption DISABLE (int opt) 17134887Schin { 17144887Schin return(sh_isoption(opt)); 17154887Schin } 17164887Schin 17174887Schin unsigned long sh_onoption DISABLE (int opt) 17184887Schin { 17194887Schin return(sh_onoption(opt)); 17204887Schin } 17214887Schin 17224887Schin unsigned long sh_offoption DISABLE (int opt) 17234887Schin { 17244887Schin return(sh_offoption(opt)); 17254887Schin } 17264887Schin 17274887Schin void sh_sigcheck DISABLE (void) 17284887Schin { 17294887Schin sh_sigcheck(); 17304887Schin } 17314887Schin 17324887Schin Dt_t* sh_bltin_tree DISABLE (void) 17334887Schin { 17344887Schin return(sh.bltin_tree); 17354887Schin } 1736