14887Schin /***********************************************************************
24887Schin * *
34887Schin * This software is part of the ast package *
4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1982-2010 AT&T Intellectual Property *
54887Schin * and is licensed under the *
64887Schin * Common Public License, Version 1.0 *
78462SApril.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 <ccode.h>
334887Schin #include <pwd.h>
348462SApril.Chin@Sun.COM #include <tmx.h>
354887Schin #include "variables.h"
364887Schin #include "path.h"
374887Schin #include "fault.h"
384887Schin #include "name.h"
394887Schin #include "edit.h"
404887Schin #include "jobs.h"
414887Schin #include "io.h"
424887Schin #include "shlex.h"
434887Schin #include "builtins.h"
444887Schin #include "FEATURE/time"
454887Schin #include "FEATURE/dynamic"
4610898Sroland.mainz@nrubsig.org #include "FEATURE/externs"
474887Schin #include "lexstates.h"
484887Schin #include "version.h"
494887Schin
508462SApril.Chin@Sun.COM char e_version[] = "\n@(#)$Id: Version "
518462SApril.Chin@Sun.COM #if SHOPT_AUDIT
528462SApril.Chin@Sun.COM #define ATTRS 1
538462SApril.Chin@Sun.COM "A"
548462SApril.Chin@Sun.COM #endif
558462SApril.Chin@Sun.COM #if SHOPT_BASH
568462SApril.Chin@Sun.COM #define ATTRS 1
578462SApril.Chin@Sun.COM "B"
588462SApril.Chin@Sun.COM #endif
5910898Sroland.mainz@nrubsig.org #if SHOPT_BGX
6010898Sroland.mainz@nrubsig.org #define ATTRS 1
6110898Sroland.mainz@nrubsig.org "J"
6210898Sroland.mainz@nrubsig.org #endif
638462SApril.Chin@Sun.COM #if SHOPT_ACCT
648462SApril.Chin@Sun.COM #define ATTRS 1
658462SApril.Chin@Sun.COM "L"
668462SApril.Chin@Sun.COM #endif
674887Schin #if SHOPT_MULTIBYTE
688462SApril.Chin@Sun.COM #define ATTRS 1
698462SApril.Chin@Sun.COM "M"
708462SApril.Chin@Sun.COM #endif
718462SApril.Chin@Sun.COM #if SHOPT_PFSH && _hdr_exec_attr
728462SApril.Chin@Sun.COM #define ATTRS 1
738462SApril.Chin@Sun.COM "P"
748462SApril.Chin@Sun.COM #endif
7510898Sroland.mainz@nrubsig.org #if SHOPT_REGRESS
7610898Sroland.mainz@nrubsig.org #define ATTRS 1
7710898Sroland.mainz@nrubsig.org "R"
7810898Sroland.mainz@nrubsig.org #endif
798462SApril.Chin@Sun.COM #if ATTRS
808462SApril.Chin@Sun.COM " "
818462SApril.Chin@Sun.COM #endif
828462SApril.Chin@Sun.COM SH_RELEASE " $\0\n";
834887Schin
844887Schin #if SHOPT_BASH
858462SApril.Chin@Sun.COM extern void bash_init(Shell_t*,int);
864887Schin #endif
874887Schin
884887Schin #define RANDMASK 0x7fff
898462SApril.Chin@Sun.COM
908462SApril.Chin@Sun.COM #ifndef ARG_MAX
918462SApril.Chin@Sun.COM # define ARG_MAX (1*1024*1024)
928462SApril.Chin@Sun.COM #endif
938462SApril.Chin@Sun.COM #ifndef CHILD_MAX
948462SApril.Chin@Sun.COM # define CHILD_MAX (1*1024)
958462SApril.Chin@Sun.COM #endif
964887Schin #ifndef CLK_TCK
974887Schin # define CLK_TCK 60
984887Schin #endif /* CLK_TCK */
994887Schin
1004887Schin #ifndef environ
1014887Schin extern char **environ;
1024887Schin #endif
1034887Schin
1044887Schin #undef getconf
1054887Schin #define getconf(x) strtol(astconf(x,NiL,NiL),NiL,0)
1064887Schin
1074887Schin struct seconds
1084887Schin {
1094887Schin Namfun_t hdr;
1104887Schin Shell_t *sh;
1114887Schin };
1124887Schin
1134887Schin struct rand
1144887Schin {
1154887Schin Namfun_t hdr;
1164887Schin int32_t rand_last;
1174887Schin };
1184887Schin
1194887Schin struct ifs
1204887Schin {
1214887Schin Namfun_t hdr;
1224887Schin Namval_t *ifsnp;
1234887Schin };
1244887Schin
1254887Schin struct match
1264887Schin {
1274887Schin Namfun_t hdr;
1284887Schin char *val;
1294887Schin char *rval;
1304887Schin int vsize;
1314887Schin int nmatch;
1324887Schin int lastsub;
1334887Schin int match[2*(MATCH_MAX+1)];
1344887Schin };
1354887Schin
1364887Schin typedef struct _init_
1374887Schin {
1384887Schin Shell_t *sh;
1394887Schin #if SHOPT_FS_3D
1404887Schin Namfun_t VPATH_init;
1414887Schin #endif /* SHOPT_FS_3D */
1424887Schin struct ifs IFS_init;
1438462SApril.Chin@Sun.COM Namfun_t PATH_init;
1448462SApril.Chin@Sun.COM Namfun_t FPATH_init;
1458462SApril.Chin@Sun.COM Namfun_t CDPATH_init;
1468462SApril.Chin@Sun.COM Namfun_t SHELL_init;
1478462SApril.Chin@Sun.COM Namfun_t ENV_init;
1488462SApril.Chin@Sun.COM Namfun_t VISUAL_init;
1498462SApril.Chin@Sun.COM Namfun_t EDITOR_init;
1508462SApril.Chin@Sun.COM Namfun_t HISTFILE_init;
1518462SApril.Chin@Sun.COM Namfun_t HISTSIZE_init;
1528462SApril.Chin@Sun.COM Namfun_t OPTINDEX_init;
1534887Schin struct seconds SECONDS_init;
1544887Schin struct rand RAND_init;
1558462SApril.Chin@Sun.COM Namfun_t LINENO_init;
1568462SApril.Chin@Sun.COM Namfun_t L_ARG_init;
1578462SApril.Chin@Sun.COM Namfun_t SH_VERSION_init;
1584887Schin struct match SH_MATCH_init;
1594887Schin #ifdef _hdr_locale
1608462SApril.Chin@Sun.COM Namfun_t LC_TYPE_init;
1618462SApril.Chin@Sun.COM Namfun_t LC_NUM_init;
1628462SApril.Chin@Sun.COM Namfun_t LC_COLL_init;
1638462SApril.Chin@Sun.COM Namfun_t LC_MSG_init;
1648462SApril.Chin@Sun.COM Namfun_t LC_ALL_init;
1658462SApril.Chin@Sun.COM Namfun_t LANG_init;
1664887Schin #endif /* _hdr_locale */
1674887Schin } Init_t;
1684887Schin
1698462SApril.Chin@Sun.COM static int nbltins;
1704887Schin static void env_init(Shell_t*);
1714887Schin static Init_t *nv_init(Shell_t*);
1724887Schin static Dt_t *inittree(Shell_t*,const struct shtable2*);
17310898Sroland.mainz@nrubsig.org static int shlvl;
1744887Schin
1754887Schin #ifdef _WINIX
1764887Schin # define EXE "?(.exe)"
1774887Schin #else
1784887Schin # define EXE
1794887Schin #endif
1804887Schin
1814887Schin static int rand_shift;
1824887Schin
1834887Schin
1844887Schin /*
1854887Schin * Invalidate all path name bindings
1864887Schin */
rehash(register Namval_t * np,void * data)1874887Schin static void rehash(register Namval_t *np,void *data)
1884887Schin {
1894887Schin NOT_USED(data);
1904887Schin nv_onattr(np,NV_NOALIAS);
1914887Schin }
1924887Schin
1934887Schin /*
1944887Schin * out of memory routine for stak routines
1954887Schin */
nospace(int unused)1964887Schin static char *nospace(int unused)
1974887Schin {
1984887Schin NOT_USED(unused);
1994887Schin errormsg(SH_DICT,ERROR_exit(3),e_nospace);
2004887Schin return(NIL(char*));
2014887Schin }
2024887Schin
2034887Schin /* Trap for VISUAL and EDITOR variables */
put_ed(register Namval_t * np,const char * val,int flags,Namfun_t * fp)2044887Schin static void put_ed(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
2054887Schin {
2064887Schin register const char *cp, *name=nv_name(np);
20710898Sroland.mainz@nrubsig.org register int newopt=0;
2088462SApril.Chin@Sun.COM Shell_t *shp = nv_shell(np);
2098462SApril.Chin@Sun.COM if(*name=='E' && nv_getval(sh_scoped(shp,VISINOD)))
2104887Schin goto done;
2118462SApril.Chin@Sun.COM if(!(cp=val) && (*name=='E' || !(cp=nv_getval(sh_scoped(shp,EDITNOD)))))
2124887Schin goto done;
2134887Schin /* turn on vi or emacs option if editor name is either*/
2144887Schin cp = path_basename(cp);
2154887Schin if(strmatch(cp,"*[Vv][Ii]*"))
21610898Sroland.mainz@nrubsig.org newopt=SH_VI;
2174887Schin else if(strmatch(cp,"*gmacs*"))
21810898Sroland.mainz@nrubsig.org newopt=SH_GMACS;
2194887Schin else if(strmatch(cp,"*macs*"))
22010898Sroland.mainz@nrubsig.org newopt=SH_EMACS;
22110898Sroland.mainz@nrubsig.org if(newopt)
22210898Sroland.mainz@nrubsig.org {
22310898Sroland.mainz@nrubsig.org sh_offoption(SH_VI);
22410898Sroland.mainz@nrubsig.org sh_offoption(SH_EMACS);
22510898Sroland.mainz@nrubsig.org sh_offoption(SH_GMACS);
22610898Sroland.mainz@nrubsig.org sh_onoption(newopt);
22710898Sroland.mainz@nrubsig.org }
2284887Schin done:
2294887Schin nv_putv(np, val, flags, fp);
2304887Schin }
2314887Schin
2328462SApril.Chin@Sun.COM /* Trap for HISTFILE and HISTSIZE variables */
put_history(register Namval_t * np,const char * val,int flags,Namfun_t * fp)2338462SApril.Chin@Sun.COM static void put_history(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
2348462SApril.Chin@Sun.COM {
2358462SApril.Chin@Sun.COM Shell_t *shp = nv_shell(np);
2368462SApril.Chin@Sun.COM void *histopen = shp->hist_ptr;
23710898Sroland.mainz@nrubsig.org char *cp;
2388462SApril.Chin@Sun.COM if(val && histopen)
2398462SApril.Chin@Sun.COM {
24010898Sroland.mainz@nrubsig.org if(np==HISTFILE && (cp=nv_getval(np)) && strcmp(val,cp)==0)
2418462SApril.Chin@Sun.COM return;
24210898Sroland.mainz@nrubsig.org if(np==HISTSIZE && sh_arith(val)==nv_getnum(HISTSIZE))
2438462SApril.Chin@Sun.COM return;
2448462SApril.Chin@Sun.COM hist_close(shp->hist_ptr);
2458462SApril.Chin@Sun.COM }
2468462SApril.Chin@Sun.COM nv_putv(np, val, flags, fp);
2478462SApril.Chin@Sun.COM if(histopen)
2488462SApril.Chin@Sun.COM {
2498462SApril.Chin@Sun.COM if(val)
2508462SApril.Chin@Sun.COM sh_histinit(shp);
2518462SApril.Chin@Sun.COM else
2528462SApril.Chin@Sun.COM hist_close(histopen);
2538462SApril.Chin@Sun.COM }
2548462SApril.Chin@Sun.COM }
2558462SApril.Chin@Sun.COM
2564887Schin /* Trap for OPTINDEX */
put_optindex(Namval_t * np,const char * val,int flags,Namfun_t * fp)2574887Schin static void put_optindex(Namval_t* np,const char *val,int flags,Namfun_t *fp)
2584887Schin {
2598462SApril.Chin@Sun.COM Shell_t *shp = nv_shell(np);
2604887Schin shp->st.opterror = shp->st.optchar = 0;
2614887Schin nv_putv(np, val, flags, fp);
2628462SApril.Chin@Sun.COM if(!val)
2638462SApril.Chin@Sun.COM nv_disc(np,fp,NV_POP);
2644887Schin }
2654887Schin
nget_optindex(register Namval_t * np,Namfun_t * fp)2664887Schin static Sfdouble_t nget_optindex(register Namval_t* np, Namfun_t *fp)
2674887Schin {
2684887Schin return((Sfdouble_t)*np->nvalue.lp);
2694887Schin }
2704887Schin
clone_optindex(Namval_t * np,Namval_t * mp,int flags,Namfun_t * fp)2718462SApril.Chin@Sun.COM static Namfun_t *clone_optindex(Namval_t* np, Namval_t *mp, int flags, Namfun_t *fp)
2728462SApril.Chin@Sun.COM {
2738462SApril.Chin@Sun.COM Namfun_t *dp = (Namfun_t*)malloc(sizeof(Namfun_t));
2748462SApril.Chin@Sun.COM memcpy((void*)dp,(void*)fp,sizeof(Namfun_t));
2758462SApril.Chin@Sun.COM mp->nvalue.lp = np->nvalue.lp;
2768462SApril.Chin@Sun.COM dp->nofree = 0;
2778462SApril.Chin@Sun.COM return(dp);
2788462SApril.Chin@Sun.COM }
2798462SApril.Chin@Sun.COM
2808462SApril.Chin@Sun.COM
2814887Schin /* Trap for restricted variables FPATH, PATH, SHELL, ENV */
put_restricted(register Namval_t * np,const char * val,int flags,Namfun_t * fp)2824887Schin static void put_restricted(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
2834887Schin {
2848462SApril.Chin@Sun.COM Shell_t *shp = nv_shell(np);
2858462SApril.Chin@Sun.COM int path_scoped = 0;
2864887Schin Pathcomp_t *pp;
2874887Schin char *name = nv_name(np);
2884887Schin if(!(flags&NV_RDONLY) && sh_isoption(SH_RESTRICTED))
2894887Schin errormsg(SH_DICT,ERROR_exit(1),e_restricted,nv_name(np));
2904887Schin if(np==PATHNOD || (path_scoped=(strcmp(name,PATHNOD->nvname)==0)))
2914887Schin {
2924887Schin nv_scan(shp->track_tree,rehash,(void*)0,NV_TAGGED,NV_TAGGED);
2934887Schin if(path_scoped && !val)
2944887Schin val = PATHNOD->nvalue.cp;
2954887Schin }
2964887Schin if(val && !(flags&NV_RDONLY) && np->nvalue.cp && strcmp(val,np->nvalue.cp)==0)
2974887Schin return;
2988462SApril.Chin@Sun.COM if(np==FPATHNOD)
2994887Schin shp->pathlist = (void*)path_unsetfpath((Pathcomp_t*)shp->pathlist);
3004887Schin nv_putv(np, val, flags, fp);
3018462SApril.Chin@Sun.COM shp->universe = 0;
3024887Schin if(shp->pathlist)
3034887Schin {
3044887Schin val = np->nvalue.cp;
3054887Schin if(np==PATHNOD || path_scoped)
3064887Schin pp = (void*)path_addpath((Pathcomp_t*)shp->pathlist,val,PATH_PATH);
3074887Schin else if(val && np==FPATHNOD)
3084887Schin pp = (void*)path_addpath((Pathcomp_t*)shp->pathlist,val,PATH_FPATH);
3094887Schin else
3104887Schin return;
3114887Schin if(shp->pathlist = (void*)pp)
3124887Schin pp->shp = shp;
3134887Schin if(!val && (flags&NV_NOSCOPE))
3144887Schin {
3154887Schin Namval_t *mp = dtsearch(shp->var_tree,np);
3164887Schin if(mp && (val=nv_getval(mp)))
3174887Schin nv_putval(mp,val,NV_RDONLY);
3184887Schin }
3194887Schin #if 0
3204887Schin sfprintf(sfstderr,"%d: name=%s val=%s\n",getpid(),name,val);
3214887Schin path_dump((Pathcomp_t*)shp->pathlist);
3224887Schin #endif
3234887Schin }
3244887Schin }
3254887Schin
put_cdpath(register Namval_t * np,const char * val,int flags,Namfun_t * fp)3264887Schin static void put_cdpath(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
3274887Schin {
3284887Schin Pathcomp_t *pp;
3298462SApril.Chin@Sun.COM Shell_t *shp = nv_shell(np);
3304887Schin nv_putv(np, val, flags, fp);
3314887Schin if(!shp->cdpathlist)
3324887Schin return;
3334887Schin val = np->nvalue.cp;
3344887Schin pp = (void*)path_addpath((Pathcomp_t*)shp->cdpathlist,val,PATH_CDPATH);
3354887Schin if(shp->cdpathlist = (void*)pp)
3364887Schin pp->shp = shp;
3374887Schin }
3384887Schin
3394887Schin #ifdef _hdr_locale
3404887Schin /*
3414887Schin * This function needs to be modified to handle international
3424887Schin * error message translations
3434887Schin */
3444887Schin #if ERROR_VERSION >= 20000101L
msg_translate(const char * catalog,const char * message)3454887Schin static char* msg_translate(const char* catalog, const char* message)
3464887Schin {
3474887Schin NOT_USED(catalog);
3484887Schin return((char*)message);
3494887Schin }
3504887Schin #else
msg_translate(const char * message,int type)3514887Schin static char* msg_translate(const char* message, int type)
3524887Schin {
3534887Schin NOT_USED(type);
3544887Schin return((char*)message);
3554887Schin }
3564887Schin #endif
3574887Schin
35810898Sroland.mainz@nrubsig.org /* Trap for LC_ALL, LC_CTYPE, LC_MESSAGES, LC_COLLATE and LANG */
put_lang(Namval_t * np,const char * val,int flags,Namfun_t * fp)3594887Schin static void put_lang(Namval_t* np,const char *val,int flags,Namfun_t *fp)
3604887Schin {
3618462SApril.Chin@Sun.COM Shell_t *shp = nv_shell(np);
3624887Schin int type;
363*12068SRoger.Faulkner@Oracle.COM char *cp;
3644887Schin char *name = nv_name(np);
3654887Schin if(name==(LCALLNOD)->nvname)
3664887Schin type = LC_ALL;
3674887Schin else if(name==(LCTYPENOD)->nvname)
3684887Schin type = LC_CTYPE;
3694887Schin else if(name==(LCMSGNOD)->nvname)
3704887Schin type = LC_MESSAGES;
3714887Schin else if(name==(LCCOLLNOD)->nvname)
3724887Schin type = LC_COLLATE;
3734887Schin else if(name==(LCNUMNOD)->nvname)
3744887Schin type = LC_NUMERIC;
37510898Sroland.mainz@nrubsig.org #ifdef LC_LANG
37610898Sroland.mainz@nrubsig.org else if(name==(LANGNOD)->nvname)
37710898Sroland.mainz@nrubsig.org type = LC_LANG;
37810898Sroland.mainz@nrubsig.org #else
37910898Sroland.mainz@nrubsig.org #define LC_LANG LC_ALL
380*12068SRoger.Faulkner@Oracle.COM else if(name==(LANGNOD)->nvname && (!(cp=nv_getval(LCALLNOD)) || !*cp))
38110898Sroland.mainz@nrubsig.org type = LC_LANG;
38210898Sroland.mainz@nrubsig.org #endif
3834887Schin else
3844887Schin type= -1;
385*12068SRoger.Faulkner@Oracle.COM if(!sh_isstate(SH_INIT) && (type>=0 || type==LC_ALL || type==LC_LANG))
3864887Schin {
387*12068SRoger.Faulkner@Oracle.COM struct lconv* lc;
388*12068SRoger.Faulkner@Oracle.COM char* r;
389*12068SRoger.Faulkner@Oracle.COM #ifdef AST_LC_setenv
390*12068SRoger.Faulkner@Oracle.COM ast.locale.set |= AST_LC_setenv;
391*12068SRoger.Faulkner@Oracle.COM #endif
392*12068SRoger.Faulkner@Oracle.COM r = setlocale(type,val?val:"");
393*12068SRoger.Faulkner@Oracle.COM #ifdef AST_LC_setenv
394*12068SRoger.Faulkner@Oracle.COM ast.locale.set ^= AST_LC_setenv;
395*12068SRoger.Faulkner@Oracle.COM #endif
396*12068SRoger.Faulkner@Oracle.COM if(!r && val)
3974887Schin {
3988462SApril.Chin@Sun.COM if(!sh_isstate(SH_INIT) || shp->login_sh==0)
3994887Schin errormsg(SH_DICT,0,e_badlocale,val);
4004887Schin return;
4014887Schin }
402*12068SRoger.Faulkner@Oracle.COM shp->decomma = (lc=localeconv()) && lc->decimal_point && *lc->decimal_point==',';
4034887Schin }
404*12068SRoger.Faulkner@Oracle.COM nv_putv(np, val, flags, fp);
405*12068SRoger.Faulkner@Oracle.COM if(CC_NATIVE!=CC_ASCII && (type==LC_ALL || type==LC_LANG || type==LC_CTYPE))
4064887Schin {
4074887Schin if(sh_lexstates[ST_BEGIN]!=sh_lexrstates[ST_BEGIN])
4084887Schin free((void*)sh_lexstates[ST_BEGIN]);
4094887Schin if(ast.locale.set&(1<<AST_LC_CTYPE))
4104887Schin {
4114887Schin register int c;
4124887Schin char *state[4];
4134887Schin sh_lexstates[ST_BEGIN] = state[0] = (char*)malloc(4*(1<<CHAR_BIT));
4144887Schin memcpy(state[0],sh_lexrstates[ST_BEGIN],(1<<CHAR_BIT));
4154887Schin sh_lexstates[ST_NAME] = state[1] = state[0] + (1<<CHAR_BIT);
4164887Schin memcpy(state[1],sh_lexrstates[ST_NAME],(1<<CHAR_BIT));
4174887Schin sh_lexstates[ST_DOL] = state[2] = state[1] + (1<<CHAR_BIT);
4184887Schin memcpy(state[2],sh_lexrstates[ST_DOL],(1<<CHAR_BIT));
4194887Schin sh_lexstates[ST_BRACE] = state[3] = state[2] + (1<<CHAR_BIT);
4204887Schin memcpy(state[3],sh_lexrstates[ST_BRACE],(1<<CHAR_BIT));
4214887Schin for(c=0; c<(1<<CHAR_BIT); c++)
4224887Schin {
4234887Schin if(state[0][c]!=S_REG)
4244887Schin continue;
4254887Schin if(state[2][c]!=S_ERR)
4264887Schin continue;
4274887Schin if(isblank(c))
4284887Schin {
4294887Schin state[0][c]=0;
4304887Schin state[1][c]=S_BREAK;
4314887Schin state[2][c]=S_BREAK;
4324887Schin continue;
4334887Schin }
4344887Schin if(!isalpha(c))
4354887Schin continue;
4364887Schin state[0][c]=S_NAME;
4374887Schin if(state[1][c]==S_REG)
4384887Schin state[1][c]=0;
4394887Schin state[2][c]=S_ALP;
4404887Schin if(state[3][c]==S_ERR)
4414887Schin state[3][c]=0;
4424887Schin }
4434887Schin }
4444887Schin else
4454887Schin {
4464887Schin sh_lexstates[ST_BEGIN]=(char*)sh_lexrstates[ST_BEGIN];
4474887Schin sh_lexstates[ST_NAME]=(char*)sh_lexrstates[ST_NAME];
4484887Schin sh_lexstates[ST_DOL]=(char*)sh_lexrstates[ST_DOL];
4494887Schin sh_lexstates[ST_BRACE]=(char*)sh_lexrstates[ST_BRACE];
4504887Schin }
4514887Schin }
4524887Schin #if ERROR_VERSION < 20000101L
4534887Schin if(type==LC_ALL || type==LC_MESSAGES)
4544887Schin error_info.translate = msg_translate;
4554887Schin #endif
4564887Schin }
4574887Schin #endif /* _hdr_locale */
4584887Schin
4594887Schin /* Trap for IFS assignment and invalidates state table */
put_ifs(register Namval_t * np,const char * val,int flags,Namfun_t * fp)4604887Schin static void put_ifs(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
4614887Schin {
4624887Schin register struct ifs *ip = (struct ifs*)fp;
46310898Sroland.mainz@nrubsig.org Shell_t *shp;
4644887Schin ip->ifsnp = 0;
46510898Sroland.mainz@nrubsig.org if(!val)
46610898Sroland.mainz@nrubsig.org {
46710898Sroland.mainz@nrubsig.org fp = nv_stack(np, NIL(Namfun_t*));
46810898Sroland.mainz@nrubsig.org if(fp && !fp->nofree)
46910898Sroland.mainz@nrubsig.org free((void*)fp);
47010898Sroland.mainz@nrubsig.org }
4714887Schin if(val != np->nvalue.cp)
4724887Schin nv_putv(np, val, flags, fp);
47310898Sroland.mainz@nrubsig.org if(!val && !(flags&NV_CLONE) && (fp=np->nvfun) && !fp->disc && (shp=(Shell_t*)(fp->last)))
47410898Sroland.mainz@nrubsig.org nv_stack(np,&((Init_t*)shp->init_context)->IFS_init.hdr);
4754887Schin }
4764887Schin
4774887Schin /*
4784887Schin * This is the lookup function for IFS
4794887Schin * It keeps the sh.ifstable up to date
4804887Schin */
get_ifs(register Namval_t * np,Namfun_t * fp)4814887Schin static char* get_ifs(register Namval_t* np, Namfun_t *fp)
4824887Schin {
4834887Schin register struct ifs *ip = (struct ifs*)fp;
4844887Schin register char *cp, *value;
4854887Schin register int c,n;
4868462SApril.Chin@Sun.COM register Shell_t *shp = nv_shell(np);
4874887Schin value = nv_getv(np,fp);
4884887Schin if(np!=ip->ifsnp)
4894887Schin {
4904887Schin ip->ifsnp = np;
4914887Schin memset(shp->ifstable,0,(1<<CHAR_BIT));
4924887Schin if(cp=value)
4934887Schin {
4944887Schin #if SHOPT_MULTIBYTE
4954887Schin while(n=mbsize(cp),c= *(unsigned char*)cp)
4964887Schin #else
4974887Schin while(c= *(unsigned char*)cp++)
4984887Schin #endif /* SHOPT_MULTIBYTE */
4994887Schin {
5004887Schin #if SHOPT_MULTIBYTE
5014887Schin cp++;
5024887Schin if(n>1)
5034887Schin {
5044887Schin cp += (n-1);
5054887Schin shp->ifstable[c] = S_MBYTE;
5064887Schin continue;
5074887Schin }
5084887Schin #endif /* SHOPT_MULTIBYTE */
5094887Schin n = S_DELIM;
5104887Schin if(c== *cp)
5114887Schin cp++;
5124887Schin else if(c=='\n')
5134887Schin n = S_NL;
5144887Schin else if(isspace(c))
5154887Schin n = S_SPACE;
5164887Schin shp->ifstable[c] = n;
5174887Schin }
5184887Schin }
5194887Schin else
5204887Schin {
5214887Schin shp->ifstable[' '] = shp->ifstable['\t'] = S_SPACE;
5224887Schin shp->ifstable['\n'] = S_NL;
5234887Schin }
5244887Schin }
5254887Schin return(value);
5264887Schin }
5274887Schin
5284887Schin /*
5294887Schin * these functions are used to get and set the SECONDS variable
5304887Schin */
5314887Schin #ifdef timeofday
5324887Schin # define dtime(tp) ((double)((tp)->tv_sec)+1e-6*((double)((tp)->tv_usec)))
5334887Schin # define tms timeval
5344887Schin #else
5354887Schin # define dtime(tp) (((double)times(tp))/sh.lim.clk_tck)
5364887Schin # define timeofday(a)
5374887Schin #endif
5384887Schin
put_seconds(register Namval_t * np,const char * val,int flags,Namfun_t * fp)5394887Schin static void put_seconds(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
5404887Schin {
5414887Schin double d;
5424887Schin struct tms tp;
5434887Schin if(!val)
5444887Schin {
54510898Sroland.mainz@nrubsig.org fp = nv_stack(np, NIL(Namfun_t*));
54610898Sroland.mainz@nrubsig.org if(fp && !fp->nofree)
54710898Sroland.mainz@nrubsig.org free((void*)fp);
54810898Sroland.mainz@nrubsig.org nv_putv(np, val, flags, fp);
5494887Schin return;
5504887Schin }
5514887Schin if(!np->nvalue.dp)
5524887Schin {
5534887Schin nv_setsize(np,3);
5548462SApril.Chin@Sun.COM nv_onattr(np,NV_DOUBLE);
5554887Schin np->nvalue.dp = new_of(double,0);
5564887Schin }
5574887Schin nv_putv(np, val, flags, fp);
5584887Schin d = *np->nvalue.dp;
5594887Schin timeofday(&tp);
5604887Schin *np->nvalue.dp = dtime(&tp)-d;
5614887Schin }
5624887Schin
get_seconds(register Namval_t * np,Namfun_t * fp)5634887Schin static char* get_seconds(register Namval_t* np, Namfun_t *fp)
5644887Schin {
5658462SApril.Chin@Sun.COM Shell_t *shp = nv_shell(np);
5664887Schin register int places = nv_size(np);
5674887Schin struct tms tp;
5684887Schin double d, offset = (np->nvalue.dp?*np->nvalue.dp:0);
5694887Schin NOT_USED(fp);
5704887Schin timeofday(&tp);
5714887Schin d = dtime(&tp)- offset;
5728462SApril.Chin@Sun.COM sfprintf(shp->strbuf,"%.*f",places,d);
5738462SApril.Chin@Sun.COM return(sfstruse(shp->strbuf));
5744887Schin }
5754887Schin
nget_seconds(register Namval_t * np,Namfun_t * fp)5764887Schin static Sfdouble_t nget_seconds(register Namval_t* np, Namfun_t *fp)
5774887Schin {
5784887Schin struct tms tp;
5794887Schin double offset = (np->nvalue.dp?*np->nvalue.dp:0);
5804887Schin NOT_USED(fp);
5814887Schin timeofday(&tp);
5824887Schin return(dtime(&tp)- offset);
5834887Schin }
5844887Schin
5854887Schin /*
5864887Schin * These three functions are used to get and set the RANDOM variable
5874887Schin */
put_rand(register Namval_t * np,const char * val,int flags,Namfun_t * fp)5884887Schin static void put_rand(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
5894887Schin {
5904887Schin struct rand *rp = (struct rand*)fp;
5914887Schin register long n;
5924887Schin if(!val)
5934887Schin {
59410898Sroland.mainz@nrubsig.org fp = nv_stack(np, NIL(Namfun_t*));
59510898Sroland.mainz@nrubsig.org if(fp && !fp->nofree)
59610898Sroland.mainz@nrubsig.org free((void*)fp);
5974887Schin nv_unset(np);
5984887Schin return;
5994887Schin }
6004887Schin if(flags&NV_INTEGER)
6014887Schin n = *(double*)val;
6024887Schin else
6034887Schin n = sh_arith(val);
6044887Schin srand((int)(n&RANDMASK));
6054887Schin rp->rand_last = -1;
6064887Schin if(!np->nvalue.lp)
6074887Schin np->nvalue.lp = &rp->rand_last;
6084887Schin }
6094887Schin
6104887Schin /*
6114887Schin * get random number in range of 0 - 2**15
6124887Schin * never pick same number twice in a row
6134887Schin */
nget_rand(register Namval_t * np,Namfun_t * fp)6144887Schin static Sfdouble_t nget_rand(register Namval_t* np, Namfun_t *fp)
6154887Schin {
6164887Schin register long cur, last= *np->nvalue.lp;
6174887Schin NOT_USED(fp);
6184887Schin do
6194887Schin cur = (rand()>>rand_shift)&RANDMASK;
6204887Schin while(cur==last);
6214887Schin *np->nvalue.lp = cur;
6224887Schin return((Sfdouble_t)cur);
6234887Schin }
6244887Schin
get_rand(register Namval_t * np,Namfun_t * fp)6254887Schin static char* get_rand(register Namval_t* np, Namfun_t *fp)
6264887Schin {
6274887Schin register long n = nget_rand(np,fp);
6284887Schin return(fmtbase(n, 10, 0));
6294887Schin }
6304887Schin
6314887Schin /*
6324887Schin * These three routines are for LINENO
6334887Schin */
nget_lineno(Namval_t * np,Namfun_t * fp)6344887Schin static Sfdouble_t nget_lineno(Namval_t* np, Namfun_t *fp)
6354887Schin {
6364887Schin double d=1;
6374887Schin if(error_info.line >0)
6384887Schin d = error_info.line;
6394887Schin else if(error_info.context && error_info.context->line>0)
6404887Schin d = error_info.context->line;
6414887Schin NOT_USED(np);
6424887Schin NOT_USED(fp);
6434887Schin return(d);
6444887Schin }
6454887Schin
put_lineno(Namval_t * np,const char * val,int flags,Namfun_t * fp)6464887Schin static void put_lineno(Namval_t* np,const char *val,int flags,Namfun_t *fp)
6474887Schin {
6484887Schin register long n;
6498462SApril.Chin@Sun.COM Shell_t *shp = nv_shell(np);
6504887Schin if(!val)
6514887Schin {
65210898Sroland.mainz@nrubsig.org fp = nv_stack(np, NIL(Namfun_t*));
65310898Sroland.mainz@nrubsig.org if(fp && !fp->nofree)
65410898Sroland.mainz@nrubsig.org free((void*)fp);
6554887Schin nv_unset(np);
6564887Schin return;
6574887Schin }
6584887Schin if(flags&NV_INTEGER)
6594887Schin n = *(double*)val;
6604887Schin else
6614887Schin n = sh_arith(val);
6624887Schin shp->st.firstline += nget_lineno(np,fp)+1-n;
6634887Schin }
6644887Schin
get_lineno(register Namval_t * np,Namfun_t * fp)6654887Schin static char* get_lineno(register Namval_t* np, Namfun_t *fp)
6664887Schin {
6674887Schin register long n = nget_lineno(np,fp);
6684887Schin return(fmtbase(n, 10, 0));
6694887Schin }
6704887Schin
get_lastarg(Namval_t * np,Namfun_t * fp)6714887Schin static char* get_lastarg(Namval_t* np, Namfun_t *fp)
6724887Schin {
67310898Sroland.mainz@nrubsig.org Shell_t *shp = nv_shell(np);
67410898Sroland.mainz@nrubsig.org char *cp;
67510898Sroland.mainz@nrubsig.org int pid;
67610898Sroland.mainz@nrubsig.org if(sh_isstate(SH_INIT) && (cp=shp->lastarg) && *cp=='*' && (pid=strtol(cp+1,&cp,10)) && *cp=='*')
67710898Sroland.mainz@nrubsig.org nv_putval(np,(pid==getppid()?cp+1:0),0);
6788462SApril.Chin@Sun.COM return(shp->lastarg);
6794887Schin }
6804887Schin
put_lastarg(Namval_t * np,const char * val,int flags,Namfun_t * fp)6814887Schin static void put_lastarg(Namval_t* np,const char *val,int flags,Namfun_t *fp)
6824887Schin {
6838462SApril.Chin@Sun.COM Shell_t *shp = nv_shell(np);
6844887Schin if(flags&NV_INTEGER)
6854887Schin {
6868462SApril.Chin@Sun.COM sfprintf(shp->strbuf,"%.*g",12,*((double*)val));
6878462SApril.Chin@Sun.COM val = sfstruse(shp->strbuf);
6884887Schin }
68910898Sroland.mainz@nrubsig.org if(val)
69010898Sroland.mainz@nrubsig.org val = strdup(val);
6918462SApril.Chin@Sun.COM if(shp->lastarg && !nv_isattr(np,NV_NOFREE))
6928462SApril.Chin@Sun.COM free((void*)shp->lastarg);
6934887Schin else
6944887Schin nv_offattr(np,NV_NOFREE);
69510898Sroland.mainz@nrubsig.org shp->lastarg = (char*)val;
69610898Sroland.mainz@nrubsig.org nv_offattr(np,NV_EXPORT);
69710898Sroland.mainz@nrubsig.org np->nvenv = 0;
6984887Schin }
6994887Schin
hasgetdisc(register Namfun_t * fp)7004887Schin static int hasgetdisc(register Namfun_t *fp)
7014887Schin {
7024887Schin while(fp && !fp->disc->getnum && !fp->disc->getval)
7034887Schin fp = fp->next;
7044887Schin return(fp!=0);
7054887Schin }
7064887Schin
7074887Schin /*
7084887Schin * store the most recent value for use in .sh.match
7094887Schin */
sh_setmatch(const char * v,int vsize,int nmatch,int match[])7104887Schin void sh_setmatch(const char *v, int vsize, int nmatch, int match[])
7114887Schin {
7124887Schin struct match *mp = (struct match*)(SH_MATCHNOD->nvfun);
7134887Schin register int i,n;
7144887Schin if(mp->nmatch = nmatch)
7154887Schin {
7164887Schin memcpy(mp->match,match,nmatch*2*sizeof(match[0]));
7174887Schin for(n=match[0],i=1; i < 2*nmatch; i++)
7184887Schin {
7194887Schin if(mp->match[i] < n)
7204887Schin n = mp->match[i];
7214887Schin }
7224887Schin for(vsize=0,i=0; i < 2*nmatch; i++)
7234887Schin {
7244887Schin if((mp->match[i] -= n) > vsize)
7254887Schin vsize = mp->match[i];
7264887Schin }
7274887Schin v += n;
7284887Schin if(vsize >= mp->vsize)
7294887Schin {
7304887Schin if(mp->vsize)
7314887Schin mp->val = (char*)realloc(mp->val,vsize+1);
7324887Schin else
7334887Schin mp->val = (char*)malloc(vsize+1);
7344887Schin mp->vsize = vsize;
7354887Schin }
7364887Schin memcpy(mp->val,v,vsize);
7374887Schin mp->val[vsize] = 0;
7388462SApril.Chin@Sun.COM nv_putsub(SH_MATCHNOD, NIL(char*), (nmatch-1)|ARRAY_FILL);
7394887Schin mp->lastsub = -1;
7404887Schin }
7414887Schin }
7424887Schin
7434887Schin #define array_scan(np) ((nv_arrayptr(np)->nelem&ARRAY_SCAN))
7444887Schin
get_match(register Namval_t * np,Namfun_t * fp)7454887Schin static char* get_match(register Namval_t* np, Namfun_t *fp)
7464887Schin {
7474887Schin struct match *mp = (struct match*)fp;
7484887Schin int sub,n;
7494887Schin char *val;
7504887Schin sub = nv_aindex(np);
7514887Schin if(sub>=mp->nmatch)
7524887Schin return(0);
7534887Schin if(sub==mp->lastsub)
7544887Schin return(mp->rval);
7554887Schin if(mp->rval)
7564887Schin {
7574887Schin free((void*)mp->rval);
7584887Schin mp->rval = 0;
7594887Schin }
7604887Schin n = mp->match[2*sub+1]-mp->match[2*sub];
7614887Schin if(n<=0)
7624887Schin return("");
7634887Schin val = mp->val+mp->match[2*sub];
7644887Schin if(mp->val[mp->match[2*sub+1]]==0)
7654887Schin return(val);
7664887Schin mp->rval = (char*)malloc(n+1);
7674887Schin mp->lastsub = sub;
7684887Schin memcpy(mp->rval,val,n);
7694887Schin mp->rval[n] = 0;
7704887Schin return(mp->rval);
7714887Schin }
7724887Schin
7738462SApril.Chin@Sun.COM static const Namdisc_t SH_MATCH_disc = { sizeof(struct match), 0, get_match };
7748462SApril.Chin@Sun.COM
get_version(register Namval_t * np,Namfun_t * fp)7758462SApril.Chin@Sun.COM static char* get_version(register Namval_t* np, Namfun_t *fp)
7768462SApril.Chin@Sun.COM {
7778462SApril.Chin@Sun.COM return(nv_getv(np,fp));
7788462SApril.Chin@Sun.COM }
7798462SApril.Chin@Sun.COM
nget_version(register Namval_t * np,Namfun_t * fp)7808462SApril.Chin@Sun.COM static Sfdouble_t nget_version(register Namval_t* np, Namfun_t *fp)
7818462SApril.Chin@Sun.COM {
7828462SApril.Chin@Sun.COM register const char *cp = e_version + strlen(e_version)-10;
7838462SApril.Chin@Sun.COM register int c;
7848462SApril.Chin@Sun.COM Sflong_t t = 0;
7858462SApril.Chin@Sun.COM NOT_USED(fp);
7868462SApril.Chin@Sun.COM
7878462SApril.Chin@Sun.COM while (c = *cp++)
7888462SApril.Chin@Sun.COM if (c >= '0' && c <= '9')
7898462SApril.Chin@Sun.COM {
7908462SApril.Chin@Sun.COM t *= 10;
7918462SApril.Chin@Sun.COM t += c - '0';
7928462SApril.Chin@Sun.COM }
7938462SApril.Chin@Sun.COM return((Sfdouble_t)t);
7948462SApril.Chin@Sun.COM }
7958462SApril.Chin@Sun.COM
7968462SApril.Chin@Sun.COM static const Namdisc_t SH_VERSION_disc = { 0, 0, get_version, nget_version };
7974887Schin
7984887Schin #if SHOPT_FS_3D
7994887Schin /*
8004887Schin * set or unset the mappings given a colon separated list of directories
8014887Schin */
vpath_set(char * str,int mode)8024887Schin static void vpath_set(char *str, int mode)
8034887Schin {
8044887Schin register char *lastp, *oldp=str, *newp=strchr(oldp,':');
8054887Schin if(!sh.lim.fs3d)
8064887Schin return;
8074887Schin while(newp)
8084887Schin {
8094887Schin *newp++ = 0;
8104887Schin if(lastp=strchr(newp,':'))
8114887Schin *lastp = 0;
8124887Schin mount((mode?newp:""),oldp,FS3D_VIEW,0);
8134887Schin newp[-1] = ':';
8144887Schin oldp = newp;
8154887Schin newp=lastp;
8164887Schin }
8174887Schin }
8184887Schin
8194887Schin /* catch vpath assignments */
put_vpath(register Namval_t * np,const char * val,int flags,Namfun_t * fp)8204887Schin static void put_vpath(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
8214887Schin {
8224887Schin register char *cp;
8234887Schin if(cp = nv_getval(np))
8244887Schin vpath_set(cp,0);
8254887Schin if(val)
8264887Schin vpath_set((char*)val,1);
8274887Schin nv_putv(np,val,flags,fp);
8284887Schin }
8294887Schin static const Namdisc_t VPATH_disc = { 0, put_vpath };
8304887Schin static Namfun_t VPATH_init = { &VPATH_disc, 1 };
8314887Schin #endif /* SHOPT_FS_3D */
8324887Schin
8334887Schin
8344887Schin static const Namdisc_t IFS_disc = { sizeof(struct ifs), put_ifs, get_ifs };
8358462SApril.Chin@Sun.COM const Namdisc_t RESTRICTED_disc = { sizeof(Namfun_t), put_restricted };
8368462SApril.Chin@Sun.COM static const Namdisc_t CDPATH_disc = { sizeof(Namfun_t), put_cdpath };
8378462SApril.Chin@Sun.COM static const Namdisc_t EDITOR_disc = { sizeof(Namfun_t), put_ed };
8388462SApril.Chin@Sun.COM static const Namdisc_t HISTFILE_disc = { sizeof(Namfun_t), put_history };
8398462SApril.Chin@Sun.COM static const Namdisc_t OPTINDEX_disc = { sizeof(Namfun_t), put_optindex, 0, nget_optindex, 0, 0, clone_optindex };
8404887Schin static const Namdisc_t SECONDS_disc = { sizeof(struct seconds), put_seconds, get_seconds, nget_seconds };
8414887Schin static const Namdisc_t RAND_disc = { sizeof(struct rand), put_rand, get_rand, nget_rand };
8428462SApril.Chin@Sun.COM static const Namdisc_t LINENO_disc = { sizeof(Namfun_t), put_lineno, get_lineno, nget_lineno };
8438462SApril.Chin@Sun.COM static const Namdisc_t L_ARG_disc = { sizeof(Namfun_t), put_lastarg, get_lastarg };
8444887Schin
8454887Schin #if SHOPT_NAMESPACE
get_nspace(Namval_t * np,Namfun_t * fp)8464887Schin static char* get_nspace(Namval_t* np, Namfun_t *fp)
8474887Schin {
8484887Schin if(sh.namespace)
8494887Schin return(nv_name(sh.namespace));
8504887Schin return((char*)np->nvalue.cp);
8514887Schin }
8524887Schin static const Namdisc_t NSPACE_disc = { 0, 0, get_nspace };
8534887Schin static Namfun_t NSPACE_init = { &NSPACE_disc, 1};
8544887Schin #endif /* SHOPT_NAMESPACE */
8554887Schin
8564887Schin #ifdef _hdr_locale
8578462SApril.Chin@Sun.COM static const Namdisc_t LC_disc = { sizeof(Namfun_t), put_lang };
8584887Schin #endif /* _hdr_locale */
8594887Schin
8604887Schin /*
8614887Schin * This function will get called whenever a configuration parameter changes
8624887Schin */
newconf(const char * name,const char * path,const char * value)8634887Schin static int newconf(const char *name, const char *path, const char *value)
8644887Schin {
8654887Schin register char *arg;
8664887Schin if(!name)
8674887Schin setenviron(value);
8684887Schin else if(strcmp(name,"UNIVERSE")==0 && strcmp(astconf(name,0,0),value))
8694887Schin {
8704887Schin sh.universe = 0;
8714887Schin /* set directory in new universe */
8724887Schin if(*(arg = path_pwd(0))=='/')
8734887Schin chdir(arg);
8744887Schin /* clear out old tracked alias */
8754887Schin stakseek(0);
8764887Schin stakputs(nv_getval(PATHNOD));
8774887Schin stakputc(0);
8784887Schin nv_putval(PATHNOD,stakseek(0),NV_RDONLY);
8794887Schin }
8804887Schin return(1);
8814887Schin }
8824887Schin
8834887Schin #if (CC_NATIVE != CC_ASCII)
a2e(char * d,const char * s)8844887Schin static void a2e(char *d, const char *s)
8854887Schin {
8864887Schin register const unsigned char *t;
8874887Schin register int i;
8884887Schin t = CCMAP(CC_ASCII, CC_NATIVE);
8894887Schin for(i=0; i<(1<<CHAR_BIT); i++)
8904887Schin d[t[i]] = s[i];
8914887Schin }
8924887Schin
init_ebcdic(void)8934887Schin static void init_ebcdic(void)
8944887Schin {
8954887Schin int i;
8964887Schin char *cp = (char*)malloc(ST_NONE*(1<<CHAR_BIT));
8974887Schin for(i=0; i < ST_NONE; i++)
8984887Schin {
8994887Schin a2e(cp,sh_lexrstates[i]);
9004887Schin sh_lexstates[i] = cp;
9014887Schin cp += (1<<CHAR_BIT);
9024887Schin }
9034887Schin }
9044887Schin #endif
9054887Schin
9064887Schin /*
9074887Schin * return SH_TYPE_* bitmask for path
9084887Schin * 0 for "not a shell"
9094887Schin */
sh_type(register const char * path)9104887Schin int sh_type(register const char *path)
9114887Schin {
9124887Schin register const char* s;
9134887Schin register int t = 0;
9144887Schin
9154887Schin if (s = (const char*)strrchr(path, '/'))
9164887Schin {
9174887Schin if (*path == '-')
9184887Schin t |= SH_TYPE_LOGIN;
9194887Schin s++;
9204887Schin }
9214887Schin else
9224887Schin s = path;
9234887Schin if (*s == '-')
9244887Schin {
9254887Schin s++;
9264887Schin t |= SH_TYPE_LOGIN;
9274887Schin }
9284887Schin for (;;)
9294887Schin {
9304887Schin if (!(t & (SH_TYPE_KSH|SH_TYPE_BASH)))
9314887Schin {
9324887Schin if (*s == 'k')
9334887Schin {
9344887Schin s++;
9354887Schin t |= SH_TYPE_KSH;
9364887Schin continue;
9374887Schin }
9384887Schin #if SHOPT_BASH
9394887Schin if (*s == 'b' && *(s+1) == 'a')
9404887Schin {
9414887Schin s += 2;
9424887Schin t |= SH_TYPE_BASH;
9434887Schin continue;
9444887Schin }
9454887Schin #endif
9464887Schin }
9474887Schin if (!(t & (SH_TYPE_PROFILE|SH_TYPE_RESTRICTED)))
9484887Schin {
9494887Schin #if SHOPT_PFSH
9504887Schin if (*s == 'p' && *(s+1) == 'f')
9514887Schin {
9524887Schin s += 2;
9534887Schin t |= SH_TYPE_PROFILE;
9544887Schin continue;
9554887Schin }
9564887Schin #endif
9574887Schin if (*s == 'r')
9584887Schin {
9594887Schin s++;
9604887Schin t |= SH_TYPE_RESTRICTED;
9614887Schin continue;
9624887Schin }
9634887Schin }
9644887Schin break;
9654887Schin }
9668462SApril.Chin@Sun.COM if (*s++ == 's' && (*s == 'h' || *s == 'u'))
9678462SApril.Chin@Sun.COM {
9688462SApril.Chin@Sun.COM s++;
9698462SApril.Chin@Sun.COM t |= SH_TYPE_SH;
9708462SApril.Chin@Sun.COM if ((t & SH_TYPE_KSH) && *s == '9' && *(s+1) == '3')
9718462SApril.Chin@Sun.COM s += 2;
9724887Schin #if _WINIX
9738462SApril.Chin@Sun.COM if (*s == '.' && *(s+1) == 'e' && *(s+2) == 'x' && *(s+3) == 'e')
9748462SApril.Chin@Sun.COM s += 4;
9754887Schin #endif
9768462SApril.Chin@Sun.COM if (!isalnum(*s))
9778462SApril.Chin@Sun.COM return t;
9788462SApril.Chin@Sun.COM }
9798462SApril.Chin@Sun.COM return t & ~(SH_TYPE_BASH|SH_TYPE_KSH|SH_TYPE_PROFILE|SH_TYPE_RESTRICTED);
9808462SApril.Chin@Sun.COM }
9818462SApril.Chin@Sun.COM
9828462SApril.Chin@Sun.COM
get_mode(Namval_t * np,Namfun_t * nfp)9838462SApril.Chin@Sun.COM static char *get_mode(Namval_t* np, Namfun_t* nfp)
9848462SApril.Chin@Sun.COM {
9858462SApril.Chin@Sun.COM mode_t mode = nv_getn(np,nfp);
9868462SApril.Chin@Sun.COM return(fmtperm(mode));
9874887Schin }
9884887Schin
put_mode(Namval_t * np,const char * val,int flag,Namfun_t * nfp)9898462SApril.Chin@Sun.COM static void put_mode(Namval_t* np, const char* val, int flag, Namfun_t* nfp)
9908462SApril.Chin@Sun.COM {
9918462SApril.Chin@Sun.COM if(val)
9928462SApril.Chin@Sun.COM {
9938462SApril.Chin@Sun.COM mode_t mode;
9948462SApril.Chin@Sun.COM char *last;
9958462SApril.Chin@Sun.COM if(flag&NV_INTEGER)
9968462SApril.Chin@Sun.COM {
9978462SApril.Chin@Sun.COM if(flag&NV_LONG)
9988462SApril.Chin@Sun.COM mode = *(Sfdouble_t*)val;
9998462SApril.Chin@Sun.COM else
10008462SApril.Chin@Sun.COM mode = *(double*)val;
10018462SApril.Chin@Sun.COM }
10028462SApril.Chin@Sun.COM else
10038462SApril.Chin@Sun.COM mode = strperm(val, &last,0);
10048462SApril.Chin@Sun.COM if(*last)
10058462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_exit(1),"%s: invalid mode string",val);
10068462SApril.Chin@Sun.COM nv_putv(np,(char*)&mode,NV_INTEGER,nfp);
10078462SApril.Chin@Sun.COM }
10088462SApril.Chin@Sun.COM else
10098462SApril.Chin@Sun.COM nv_putv(np,val,flag,nfp);
10108462SApril.Chin@Sun.COM }
10118462SApril.Chin@Sun.COM
10128462SApril.Chin@Sun.COM static const Namdisc_t modedisc =
10138462SApril.Chin@Sun.COM {
10148462SApril.Chin@Sun.COM 0,
10158462SApril.Chin@Sun.COM put_mode,
10168462SApril.Chin@Sun.COM get_mode,
10178462SApril.Chin@Sun.COM };
10188462SApril.Chin@Sun.COM
10198462SApril.Chin@Sun.COM
10204887Schin /*
10214887Schin * initialize the shell
10224887Schin */
sh_init(register int argc,register char * argv[],Shinit_f userinit)10238462SApril.Chin@Sun.COM Shell_t *sh_init(register int argc,register char *argv[], Shinit_f userinit)
10244887Schin {
10258462SApril.Chin@Sun.COM Shell_t *shp = &sh;
10264887Schin register int n;
10274887Schin int type;
1028*12068SRoger.Faulkner@Oracle.COM long v;
10294887Schin static char *login_files[3];
103010898Sroland.mainz@nrubsig.org memfatal();
10314887Schin n = strlen(e_version);
10324887Schin if(e_version[n-1]=='$' && e_version[n-2]==' ')
10334887Schin e_version[n-2]=0;
10344887Schin #if (CC_NATIVE == CC_ASCII)
10354887Schin memcpy(sh_lexstates,sh_lexrstates,ST_NONE*sizeof(char*));
10364887Schin #else
10374887Schin init_ebcdic();
10384887Schin #endif
10398462SApril.Chin@Sun.COM umask(shp->mask=umask(0));
10408462SApril.Chin@Sun.COM shp->mac_context = sh_macopen(shp);
10418462SApril.Chin@Sun.COM shp->arg_context = sh_argopen(shp);
10428462SApril.Chin@Sun.COM shp->lex_context = (void*)sh_lexopen(0,shp,1);
10438462SApril.Chin@Sun.COM shp->ed_context = (void*)ed_open(shp);
10448462SApril.Chin@Sun.COM shp->strbuf = sfstropen();
10458462SApril.Chin@Sun.COM shp->stk = stkstd;
10468462SApril.Chin@Sun.COM sfsetbuf(shp->strbuf,(char*)0,64);
10474887Schin sh_onstate(SH_INIT);
10484887Schin error_info.exit = sh_exit;
10494887Schin error_info.id = path_basename(argv[0]);
10504887Schin #if ERROR_VERSION >= 20000102L
10514887Schin error_info.catalog = e_dict;
10524887Schin #endif
105310898Sroland.mainz@nrubsig.org #if SHOPT_REGRESS
105410898Sroland.mainz@nrubsig.org {
105510898Sroland.mainz@nrubsig.org Opt_t* nopt;
105610898Sroland.mainz@nrubsig.org Opt_t* oopt;
105710898Sroland.mainz@nrubsig.org char* a;
105810898Sroland.mainz@nrubsig.org char** av = argv;
105910898Sroland.mainz@nrubsig.org char* regress[3];
106010898Sroland.mainz@nrubsig.org
106110898Sroland.mainz@nrubsig.org sh_regress_init(shp);
106210898Sroland.mainz@nrubsig.org regress[0] = "__regress__";
106310898Sroland.mainz@nrubsig.org regress[2] = 0;
106410898Sroland.mainz@nrubsig.org /* NOTE: only shp is used by __regress__ at this point */
106510898Sroland.mainz@nrubsig.org shp->bltindata.shp = shp;
106610898Sroland.mainz@nrubsig.org while ((a = *++av) && a[0] == '-' && (a[1] == 'I' || a[1] == '-' && a[2] == 'r'))
106710898Sroland.mainz@nrubsig.org {
106810898Sroland.mainz@nrubsig.org if (a[1] == 'I')
106910898Sroland.mainz@nrubsig.org {
107010898Sroland.mainz@nrubsig.org if (a[2])
107110898Sroland.mainz@nrubsig.org regress[1] = a + 2;
107210898Sroland.mainz@nrubsig.org else if (!(regress[1] = *++av))
107310898Sroland.mainz@nrubsig.org break;
107410898Sroland.mainz@nrubsig.org }
107510898Sroland.mainz@nrubsig.org else if (strncmp(a+2, "regress", 7))
107610898Sroland.mainz@nrubsig.org break;
107710898Sroland.mainz@nrubsig.org else if (a[9] == '=')
107810898Sroland.mainz@nrubsig.org regress[1] = a + 10;
107910898Sroland.mainz@nrubsig.org else if (!(regress[1] = *++av))
108010898Sroland.mainz@nrubsig.org break;
108110898Sroland.mainz@nrubsig.org nopt = optctx(0, 0);
108210898Sroland.mainz@nrubsig.org oopt = optctx(nopt, 0);
108310898Sroland.mainz@nrubsig.org b___regress__(2, regress, &shp->bltindata);
108410898Sroland.mainz@nrubsig.org optctx(oopt, nopt);
108510898Sroland.mainz@nrubsig.org }
108610898Sroland.mainz@nrubsig.org }
108710898Sroland.mainz@nrubsig.org #endif
10888462SApril.Chin@Sun.COM shp->cpipe[0] = -1;
10898462SApril.Chin@Sun.COM shp->coutpipe = -1;
10908462SApril.Chin@Sun.COM shp->userid=getuid();
10918462SApril.Chin@Sun.COM shp->euserid=geteuid();
10928462SApril.Chin@Sun.COM shp->groupid=getgid();
10938462SApril.Chin@Sun.COM shp->egroupid=getegid();
10944887Schin for(n=0;n < 10; n++)
10954887Schin {
10964887Schin /* don't use lower bits when rand() generates large numbers */
10974887Schin if(rand() > RANDMASK)
10984887Schin {
10994887Schin rand_shift = 3;
11004887Schin break;
11014887Schin }
11024887Schin }
11038462SApril.Chin@Sun.COM shp->lim.clk_tck = getconf("CLK_TCK");
11048462SApril.Chin@Sun.COM shp->lim.arg_max = getconf("ARG_MAX");
11058462SApril.Chin@Sun.COM shp->lim.open_max = getconf("OPEN_MAX");
11068462SApril.Chin@Sun.COM shp->lim.child_max = getconf("CHILD_MAX");
11078462SApril.Chin@Sun.COM shp->lim.ngroups_max = getconf("NGROUPS_MAX");
11088462SApril.Chin@Sun.COM shp->lim.posix_version = getconf("VERSION");
11098462SApril.Chin@Sun.COM shp->lim.posix_jobcontrol = getconf("JOB_CONTROL");
11108462SApril.Chin@Sun.COM if(shp->lim.arg_max <=0)
11118462SApril.Chin@Sun.COM shp->lim.arg_max = ARG_MAX;
11128462SApril.Chin@Sun.COM if(shp->lim.child_max <=0)
11138462SApril.Chin@Sun.COM shp->lim.child_max = CHILD_MAX;
1114*12068SRoger.Faulkner@Oracle.COM if((v = getconf("PID_MAX")) > 0 && shp->lim.child_max > v)
1115*12068SRoger.Faulkner@Oracle.COM shp->lim.child_max = v;
11168462SApril.Chin@Sun.COM if(shp->lim.open_max <0)
11178462SApril.Chin@Sun.COM shp->lim.open_max = OPEN_MAX;
11188462SApril.Chin@Sun.COM if(shp->lim.open_max > (SHRT_MAX-2))
11198462SApril.Chin@Sun.COM shp->lim.open_max = SHRT_MAX-2;
11208462SApril.Chin@Sun.COM if(shp->lim.clk_tck <=0)
11218462SApril.Chin@Sun.COM shp->lim.clk_tck = CLK_TCK;
11224887Schin #if SHOPT_FS_3D
11234887Schin if(fs3d(FS3D_TEST))
11248462SApril.Chin@Sun.COM shp->lim.fs3d = 1;
11254887Schin #endif /* SHOPT_FS_3D */
11268462SApril.Chin@Sun.COM sh_ioinit(shp);
11274887Schin /* initialize signal handling */
11288462SApril.Chin@Sun.COM sh_siginit(shp);
11294887Schin stakinstall(NIL(Stak_t*),nospace);
11304887Schin /* set up memory for name-value pairs */
11318462SApril.Chin@Sun.COM shp->init_context = nv_init(shp);
11324887Schin /* read the environment */
11334887Schin if(argc>0)
11344887Schin {
11354887Schin type = sh_type(*argv);
11364887Schin if(type&SH_TYPE_LOGIN)
11378462SApril.Chin@Sun.COM shp->login_sh = 2;
11384887Schin }
11398462SApril.Chin@Sun.COM env_init(shp);
114010898Sroland.mainz@nrubsig.org if(!ENVNOD->nvalue.cp)
114110898Sroland.mainz@nrubsig.org {
114210898Sroland.mainz@nrubsig.org sfprintf(shp->strbuf,"%s/.kshrc",nv_getval(HOME));
114310898Sroland.mainz@nrubsig.org nv_putval(ENVNOD,sfstruse(shp->strbuf),NV_RDONLY);
114410898Sroland.mainz@nrubsig.org }
11458462SApril.Chin@Sun.COM *SHLVL->nvalue.ip +=1;
11464887Schin #if SHOPT_SPAWN
11474887Schin {
11484887Schin /*
11494887Schin * try to find the pathname for this interpreter
11504887Schin * try using environment variable _ or argv[0]
11514887Schin */
115210898Sroland.mainz@nrubsig.org char *cp=nv_getval(L_ARGNOD);
11534887Schin char buff[PATH_MAX+1];
11548462SApril.Chin@Sun.COM shp->shpath = 0;
115510898Sroland.mainz@nrubsig.org #if _AST_VERSION >= 20090202L
115610898Sroland.mainz@nrubsig.org if((n = pathprog(NiL, buff, sizeof(buff))) > 0 && n <= sizeof(buff))
115710898Sroland.mainz@nrubsig.org shp->shpath = strdup(buff);
115810898Sroland.mainz@nrubsig.org #else
11598462SApril.Chin@Sun.COM sfprintf(shp->strbuf,"/proc/%d/exe",getpid());
11608462SApril.Chin@Sun.COM if((n=readlink(sfstruse(shp->strbuf),buff,sizeof(buff)-1))>0)
11614887Schin {
11624887Schin buff[n] = 0;
11638462SApril.Chin@Sun.COM shp->shpath = strdup(buff);
11644887Schin }
116510898Sroland.mainz@nrubsig.org #endif
11664887Schin else if((cp && (sh_type(cp)&SH_TYPE_SH)) || (argc>0 && strchr(cp= *argv,'/')))
11674887Schin {
11684887Schin if(*cp=='/')
11698462SApril.Chin@Sun.COM shp->shpath = strdup(cp);
11704887Schin else if(cp = nv_getval(PWDNOD))
11714887Schin {
11724887Schin int offset = staktell();
11734887Schin stakputs(cp);
11744887Schin stakputc('/');
11754887Schin stakputs(argv[0]);
11764887Schin pathcanon(stakptr(offset),PATH_DOTDOT);
11778462SApril.Chin@Sun.COM shp->shpath = strdup(stakptr(offset));
11784887Schin stakseek(offset);
11794887Schin }
11804887Schin }
11814887Schin }
11824887Schin #endif
11834887Schin nv_putval(IFSNOD,(char*)e_sptbnl,NV_RDONLY);
11844887Schin #if SHOPT_FS_3D
11854887Schin nv_stack(VPATHNOD, &VPATH_init);
11864887Schin #endif /* SHOPT_FS_3D */
11874887Schin astconfdisc(newconf);
11884887Schin #if SHOPT_TIMEOUT
11898462SApril.Chin@Sun.COM shp->st.tmout = SHOPT_TIMEOUT;
11904887Schin #endif /* SHOPT_TIMEOUT */
11914887Schin /* initialize jobs table */
11924887Schin job_clear();
11934887Schin if(argc>0)
11944887Schin {
11954887Schin /* check for restricted shell */
11964887Schin if(type&SH_TYPE_RESTRICTED)
11974887Schin sh_onoption(SH_RESTRICTED);
11984887Schin #if SHOPT_PFSH
11994887Schin /* check for profile shell */
12004887Schin else if(type&SH_TYPE_PROFILE)
12014887Schin sh_onoption(SH_PFSH);
12024887Schin #endif
12034887Schin #if SHOPT_BASH
12044887Schin /* check for invocation as bash */
12054887Schin if(type&SH_TYPE_BASH)
12064887Schin {
12078462SApril.Chin@Sun.COM shp->userinit = userinit = bash_init;
12084887Schin sh_onoption(SH_BASH);
12094887Schin sh_onstate(SH_PREINIT);
12108462SApril.Chin@Sun.COM (*userinit)(shp, 0);
12114887Schin sh_offstate(SH_PREINIT);
12124887Schin }
12134887Schin #endif
12144887Schin /* look for options */
12158462SApril.Chin@Sun.COM /* shp->st.dolc is $# */
12168462SApril.Chin@Sun.COM if((shp->st.dolc = sh_argopts(-argc,argv,shp)) < 0)
12174887Schin {
12188462SApril.Chin@Sun.COM shp->exitval = 2;
12198462SApril.Chin@Sun.COM sh_done(shp,0);
12204887Schin }
12214887Schin opt_info.disc = 0;
12228462SApril.Chin@Sun.COM shp->st.dolv=argv+(argc-1)-shp->st.dolc;
12238462SApril.Chin@Sun.COM shp->st.dolv[0] = argv[0];
12248462SApril.Chin@Sun.COM if(shp->st.dolc < 1)
12254887Schin sh_onoption(SH_SFLAG);
12264887Schin if(!sh_isoption(SH_SFLAG))
12274887Schin {
12288462SApril.Chin@Sun.COM shp->st.dolc--;
12298462SApril.Chin@Sun.COM shp->st.dolv++;
12304887Schin #if _WINIX
12314887Schin {
12324887Schin char* name;
12338462SApril.Chin@Sun.COM name = shp->st.dolv[0];
12344887Schin if(name[1]==':' && (name[2]=='/' || name[2]=='\\'))
12354887Schin {
12364887Schin #if _lib_pathposix
12374887Schin char* p;
12384887Schin
12394887Schin if((n = pathposix(name, NIL(char*), 0)) > 0 && (p = (char*)malloc(++n)))
12404887Schin {
12414887Schin pathposix(name, p, n);
12424887Schin name = p;
12434887Schin }
12444887Schin else
12454887Schin #endif
12464887Schin {
12474887Schin name[1] = name[0];
12484887Schin name[0] = name[2] = '/';
12494887Schin }
12504887Schin }
12514887Schin }
12524887Schin #endif /* _WINIX */
12534887Schin }
12544887Schin }
12554887Schin #if SHOPT_PFSH
12564887Schin if (sh_isoption(SH_PFSH))
12574887Schin {
12588462SApril.Chin@Sun.COM struct passwd *pw = getpwuid(shp->userid);
12594887Schin if(pw)
12608462SApril.Chin@Sun.COM shp->user = strdup(pw->pw_name);
12614887Schin
12624887Schin }
12634887Schin #endif
12644887Schin /* set[ug]id scripts require the -p flag */
12658462SApril.Chin@Sun.COM if(shp->userid!=shp->euserid || shp->groupid!=shp->egroupid)
12664887Schin {
126710898Sroland.mainz@nrubsig.org #ifdef SHOPT_P_SUID
12684887Schin /* require sh -p to run setuid and/or setgid */
126910898Sroland.mainz@nrubsig.org if(!sh_isoption(SH_PRIVILEGED) && shp->userid >= SHOPT_P_SUID)
12704887Schin {
12718462SApril.Chin@Sun.COM setuid(shp->euserid=shp->userid);
12728462SApril.Chin@Sun.COM setgid(shp->egroupid=shp->groupid);
12734887Schin }
12744887Schin else
127510898Sroland.mainz@nrubsig.org #endif /* SHOPT_P_SUID */
12764887Schin sh_onoption(SH_PRIVILEGED);
12774887Schin #ifdef SHELLMAGIC
12784887Schin /* careful of #! setuid scripts with name beginning with - */
12798462SApril.Chin@Sun.COM if(shp->login_sh && argv[1] && strcmp(argv[0],argv[1])==0)
12804887Schin errormsg(SH_DICT,ERROR_exit(1),e_prohibited);
12814887Schin #endif /*SHELLMAGIC*/
12824887Schin }
12834887Schin else
12844887Schin sh_offoption(SH_PRIVILEGED);
12854887Schin /* shname for $0 in profiles and . scripts */
12864887Schin if(strmatch(argv[1],e_devfdNN))
12878462SApril.Chin@Sun.COM shp->shname = strdup(argv[0]);
12884887Schin else
12898462SApril.Chin@Sun.COM shp->shname = strdup(shp->st.dolv[0]);
12904887Schin /*
12914887Schin * return here for shell script execution
12924887Schin * but not for parenthesis subshells
12934887Schin */
12948462SApril.Chin@Sun.COM error_info.id = strdup(shp->st.dolv[0]); /* error_info.id is $0 */
12958462SApril.Chin@Sun.COM shp->jmpbuffer = (void*)&shp->checkbase;
12968462SApril.Chin@Sun.COM sh_pushcontext(&shp->checkbase,SH_JMPSCRIPT);
12978462SApril.Chin@Sun.COM shp->st.self = &shp->global;
12988462SApril.Chin@Sun.COM shp->topscope = (Shscope_t*)shp->st.self;
12994887Schin sh_offstate(SH_INIT);
13004887Schin login_files[0] = (char*)e_profile;
13014887Schin login_files[1] = ".profile";
13028462SApril.Chin@Sun.COM shp->login_files = login_files;
13038462SApril.Chin@Sun.COM shp->bltindata.version = SH_VERSION;
13048462SApril.Chin@Sun.COM shp->bltindata.shp = shp;
13058462SApril.Chin@Sun.COM shp->bltindata.shrun = sh_run;
13068462SApril.Chin@Sun.COM shp->bltindata.shtrap = sh_trap;
13078462SApril.Chin@Sun.COM shp->bltindata.shexit = sh_exit;
13088462SApril.Chin@Sun.COM shp->bltindata.shbltin = sh_addbuiltin;
13098462SApril.Chin@Sun.COM #if _AST_VERSION >= 20080617L
1310*12068SRoger.Faulkner@Oracle.COM shp->bltindata.shgetenv = sh_getenv;
1311*12068SRoger.Faulkner@Oracle.COM shp->bltindata.shsetenv = sh_setenviron;
13128462SApril.Chin@Sun.COM astintercept(&shp->bltindata,1);
13138462SApril.Chin@Sun.COM #endif
13148462SApril.Chin@Sun.COM #if 0
13158462SApril.Chin@Sun.COM #define NV_MKINTTYPE(x,y,z) nv_mkinttype(#x,sizeof(x),(x)-1<0,(y),(Namdisc_t*)z);
13168462SApril.Chin@Sun.COM NV_MKINTTYPE(pid_t,"process id",0);
13178462SApril.Chin@Sun.COM NV_MKINTTYPE(gid_t,"group id",0);
13188462SApril.Chin@Sun.COM NV_MKINTTYPE(uid_t,"user id",0);
13198462SApril.Chin@Sun.COM NV_MKINTTYPE(size_t,(const char*)0,0);
13208462SApril.Chin@Sun.COM NV_MKINTTYPE(ssize_t,(const char*)0,0);
13218462SApril.Chin@Sun.COM NV_MKINTTYPE(off_t,"offset in bytes",0);
13228462SApril.Chin@Sun.COM NV_MKINTTYPE(ino_t,"\ai-\anode number",0);
13238462SApril.Chin@Sun.COM NV_MKINTTYPE(mode_t,(const char*)0,&modedisc);
13248462SApril.Chin@Sun.COM NV_MKINTTYPE(dev_t,"device id",0);
13258462SApril.Chin@Sun.COM NV_MKINTTYPE(nlink_t,"hard link count",0);
13268462SApril.Chin@Sun.COM NV_MKINTTYPE(blkcnt_t,"block count",0);
13278462SApril.Chin@Sun.COM NV_MKINTTYPE(time_t,"seconds since the epoch",0);
13288462SApril.Chin@Sun.COM nv_mkstat();
13298462SApril.Chin@Sun.COM #endif
13308462SApril.Chin@Sun.COM if(shp->userinit=userinit)
13318462SApril.Chin@Sun.COM (*userinit)(shp, 0);
13328462SApril.Chin@Sun.COM return(shp);
13334887Schin }
13344887Schin
sh_getinterp(void)13354887Schin Shell_t *sh_getinterp(void)
13364887Schin {
13374887Schin return(&sh);
13384887Schin }
13394887Schin
13404887Schin /*
13414887Schin * reinitialize before executing a script
13424887Schin */
sh_reinit(char * argv[])13434887Schin int sh_reinit(char *argv[])
13444887Schin {
13458462SApril.Chin@Sun.COM Shell_t *shp = &sh;
13464887Schin Shopt_t opt;
13478462SApril.Chin@Sun.COM Namval_t *np,*npnext;
13488462SApril.Chin@Sun.COM Dt_t *dp;
13498462SApril.Chin@Sun.COM for(np=dtfirst(shp->fun_tree);np;np=npnext)
13504887Schin {
13518462SApril.Chin@Sun.COM if((dp=shp->fun_tree)->walk)
13528462SApril.Chin@Sun.COM dp = dp->walk;
13538462SApril.Chin@Sun.COM npnext = (Namval_t*)dtnext(shp->fun_tree,np);
13548462SApril.Chin@Sun.COM if(np>= shp->bltin_cmds && np < &shp->bltin_cmds[nbltins])
13558462SApril.Chin@Sun.COM continue;
13568462SApril.Chin@Sun.COM if(is_abuiltin(np) && nv_isattr(np,NV_EXPORT))
13578462SApril.Chin@Sun.COM continue;
13588462SApril.Chin@Sun.COM if(*np->nvname=='/')
13598462SApril.Chin@Sun.COM continue;
13608462SApril.Chin@Sun.COM nv_delete(np,dp,NV_NOFREE);
13618462SApril.Chin@Sun.COM }
13628462SApril.Chin@Sun.COM dtclose(shp->alias_tree);
13638462SApril.Chin@Sun.COM shp->alias_tree = inittree(shp,shtab_aliases);
13648462SApril.Chin@Sun.COM shp->last_root = shp->var_tree;
13658462SApril.Chin@Sun.COM shp->namespace = 0;
13668462SApril.Chin@Sun.COM shp->inuse_bits = 0;
13678462SApril.Chin@Sun.COM if(shp->userinit)
13688462SApril.Chin@Sun.COM (*shp->userinit)(shp, 1);
13698462SApril.Chin@Sun.COM if(shp->heredocs)
13708462SApril.Chin@Sun.COM {
13718462SApril.Chin@Sun.COM sfclose(shp->heredocs);
13728462SApril.Chin@Sun.COM shp->heredocs = 0;
13734887Schin }
13744887Schin /* remove locals */
13754887Schin sh_onstate(SH_INIT);
13768462SApril.Chin@Sun.COM nv_scan(shp->var_tree,sh_envnolocal,(void*)0,NV_EXPORT,0);
13778462SApril.Chin@Sun.COM nv_scan(shp->var_tree,sh_envnolocal,(void*)0,NV_ARRAY,NV_ARRAY);
13784887Schin sh_offstate(SH_INIT);
13798462SApril.Chin@Sun.COM memset(shp->st.trapcom,0,(shp->st.trapmax+1)*sizeof(char*));
13804887Schin memset((void*)&opt,0,sizeof(opt));
13814887Schin if(sh_isoption(SH_TRACKALL))
13824887Schin on_option(&opt,SH_TRACKALL);
13834887Schin if(sh_isoption(SH_EMACS))
13844887Schin on_option(&opt,SH_EMACS);
13854887Schin if(sh_isoption(SH_GMACS))
13864887Schin on_option(&opt,SH_GMACS);
13874887Schin if(sh_isoption(SH_VI))
13884887Schin on_option(&opt,SH_VI);
13894887Schin if(sh_isoption(SH_VIRAW))
13904887Schin on_option(&opt,SH_VIRAW);
13918462SApril.Chin@Sun.COM shp->options = opt;
13924887Schin /* set up new args */
13934887Schin if(argv)
13948462SApril.Chin@Sun.COM shp->arglist = sh_argcreate(argv);
13958462SApril.Chin@Sun.COM if(shp->arglist)
13968462SApril.Chin@Sun.COM sh_argreset(shp,shp->arglist,NIL(struct dolnod*));
13978462SApril.Chin@Sun.COM shp->envlist=0;
13988462SApril.Chin@Sun.COM shp->curenv = 0;
13998462SApril.Chin@Sun.COM shp->shname = error_info.id = strdup(shp->st.dolv[0]);
14004887Schin sh_offstate(SH_FORKED);
14018462SApril.Chin@Sun.COM shp->fn_depth = shp->dot_depth = 0;
14024887Schin sh_sigreset(0);
140310898Sroland.mainz@nrubsig.org if(!(SHLVL->nvalue.ip))
140410898Sroland.mainz@nrubsig.org {
140510898Sroland.mainz@nrubsig.org shlvl = 0;
140610898Sroland.mainz@nrubsig.org SHLVL->nvalue.ip = &shlvl;
140710898Sroland.mainz@nrubsig.org nv_onattr(SHLVL,NV_INTEGER|NV_EXPORT|NV_NOFREE);
140810898Sroland.mainz@nrubsig.org }
14098462SApril.Chin@Sun.COM *SHLVL->nvalue.ip +=1;
141010898Sroland.mainz@nrubsig.org shp->st.filename = strdup(shp->lastarg);
14114887Schin return(1);
14124887Schin }
14134887Schin
14144887Schin /*
14154887Schin * set when creating a local variable of this name
14164887Schin */
nv_cover(register Namval_t * np)14174887Schin Namfun_t *nv_cover(register Namval_t *np)
14184887Schin {
141910898Sroland.mainz@nrubsig.org if(np==IFSNOD || np==PATHNOD || np==SHELLNOD || np==FPATHNOD || np==CDPNOD || np==SECONDS || np==ENVNOD)
14204887Schin return(np->nvfun);
14214887Schin #ifdef _hdr_locale
14224887Schin if(np==LCALLNOD || np==LCTYPENOD || np==LCMSGNOD || np==LCCOLLNOD || np==LCNUMNOD || np==LANGNOD)
14234887Schin return(np->nvfun);
14244887Schin #endif
14254887Schin return(0);
14264887Schin }
14274887Schin
14284887Schin static const char *shdiscnames[] = { "tilde", 0};
14294887Schin
14308462SApril.Chin@Sun.COM #ifdef SHOPT_STATS
14318462SApril.Chin@Sun.COM struct Stats
14328462SApril.Chin@Sun.COM {
14338462SApril.Chin@Sun.COM Namfun_t hdr;
14348462SApril.Chin@Sun.COM Shell_t *sh;
14358462SApril.Chin@Sun.COM char *nodes;
14368462SApril.Chin@Sun.COM int numnodes;
14378462SApril.Chin@Sun.COM int current;
14388462SApril.Chin@Sun.COM };
14398462SApril.Chin@Sun.COM
next_stat(register Namval_t * np,Dt_t * root,Namfun_t * fp)14408462SApril.Chin@Sun.COM static Namval_t *next_stat(register Namval_t* np, Dt_t *root,Namfun_t *fp)
14418462SApril.Chin@Sun.COM {
14428462SApril.Chin@Sun.COM struct Stats *sp = (struct Stats*)fp;
14438462SApril.Chin@Sun.COM if(!root)
14448462SApril.Chin@Sun.COM sp->current = 0;
14458462SApril.Chin@Sun.COM else if(++sp->current>=sp->numnodes)
14468462SApril.Chin@Sun.COM return(0);
14478462SApril.Chin@Sun.COM return(nv_namptr(sp->nodes,sp->current));
14488462SApril.Chin@Sun.COM }
14498462SApril.Chin@Sun.COM
create_stat(Namval_t * np,const char * name,int flag,Namfun_t * fp)14508462SApril.Chin@Sun.COM static Namval_t *create_stat(Namval_t *np,const char *name,int flag,Namfun_t *fp)
14518462SApril.Chin@Sun.COM {
14528462SApril.Chin@Sun.COM struct Stats *sp = (struct Stats*)fp;
14538462SApril.Chin@Sun.COM register const char *cp=name;
14548462SApril.Chin@Sun.COM register int i=0,n;
14558462SApril.Chin@Sun.COM Namval_t *nq=0;
14568462SApril.Chin@Sun.COM Shell_t *shp = sp->sh;
14578462SApril.Chin@Sun.COM if(!name)
14588462SApril.Chin@Sun.COM return(SH_STATS);
14598462SApril.Chin@Sun.COM while((i=*cp++) && i != '=' && i != '+' && i!='[');
14608462SApril.Chin@Sun.COM n = (cp-1) -name;
14618462SApril.Chin@Sun.COM for(i=0; i < sp->numnodes; i++)
14628462SApril.Chin@Sun.COM {
14638462SApril.Chin@Sun.COM nq = nv_namptr(sp->nodes,i);
14648462SApril.Chin@Sun.COM if((n==0||memcmp(name,nq->nvname,n)==0) && nq->nvname[n]==0)
14658462SApril.Chin@Sun.COM goto found;
14668462SApril.Chin@Sun.COM }
14678462SApril.Chin@Sun.COM nq = 0;
14688462SApril.Chin@Sun.COM found:
14698462SApril.Chin@Sun.COM if(nq)
14708462SApril.Chin@Sun.COM {
14718462SApril.Chin@Sun.COM fp->last = (char*)&name[n];
14728462SApril.Chin@Sun.COM shp->last_table = SH_STATS;
14738462SApril.Chin@Sun.COM }
14748462SApril.Chin@Sun.COM else
14758462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_exit(1),e_notelem,n,name,nv_name(np));
14768462SApril.Chin@Sun.COM return(nq);
14778462SApril.Chin@Sun.COM }
14788462SApril.Chin@Sun.COM
14798462SApril.Chin@Sun.COM static const Namdisc_t stat_disc =
14808462SApril.Chin@Sun.COM {
14818462SApril.Chin@Sun.COM 0, 0, 0, 0, 0,
14828462SApril.Chin@Sun.COM create_stat,
14838462SApril.Chin@Sun.COM 0, 0,
14848462SApril.Chin@Sun.COM next_stat
14858462SApril.Chin@Sun.COM };
14868462SApril.Chin@Sun.COM
name_stat(Namval_t * np,Namfun_t * fp)14878462SApril.Chin@Sun.COM static char *name_stat(Namval_t *np, Namfun_t *fp)
14888462SApril.Chin@Sun.COM {
14898462SApril.Chin@Sun.COM Shell_t *shp = sh_getinterp();
14908462SApril.Chin@Sun.COM sfprintf(shp->strbuf,".sh.stats.%s",np->nvname);
14918462SApril.Chin@Sun.COM return(sfstruse(shp->strbuf));
14928462SApril.Chin@Sun.COM }
14938462SApril.Chin@Sun.COM
14948462SApril.Chin@Sun.COM static const Namdisc_t stat_child_disc =
14958462SApril.Chin@Sun.COM {
14968462SApril.Chin@Sun.COM 0,0,0,0,0,0,0,
14978462SApril.Chin@Sun.COM name_stat
14988462SApril.Chin@Sun.COM };
14998462SApril.Chin@Sun.COM
15008462SApril.Chin@Sun.COM static Namfun_t stat_child_fun =
15018462SApril.Chin@Sun.COM {
15028462SApril.Chin@Sun.COM &stat_child_disc, 1, 0, sizeof(Namfun_t)
15038462SApril.Chin@Sun.COM };
15048462SApril.Chin@Sun.COM
stat_init(Shell_t * shp)15058462SApril.Chin@Sun.COM static void stat_init(Shell_t *shp)
15068462SApril.Chin@Sun.COM {
15078462SApril.Chin@Sun.COM int i,nstat = STAT_SUBSHELL+1;
15088462SApril.Chin@Sun.COM struct Stats *sp = newof(0,struct Stats,1,nstat*NV_MINSZ);
15098462SApril.Chin@Sun.COM Namval_t *np;
15108462SApril.Chin@Sun.COM sp->numnodes = nstat;
15118462SApril.Chin@Sun.COM sp->nodes = (char*)(sp+1);
15128462SApril.Chin@Sun.COM shp->stats = (int*)calloc(sizeof(int*),nstat);
15138462SApril.Chin@Sun.COM sp->sh = shp;
15148462SApril.Chin@Sun.COM for(i=0; i < nstat; i++)
15158462SApril.Chin@Sun.COM {
15168462SApril.Chin@Sun.COM np = nv_namptr(sp->nodes,i);
15178462SApril.Chin@Sun.COM np->nvfun = &stat_child_fun;
15188462SApril.Chin@Sun.COM np->nvname = (char*)shtab_stats[i].sh_name;
15198462SApril.Chin@Sun.COM nv_onattr(np,NV_RDONLY|NV_MINIMAL|NV_NOFREE|NV_INTEGER);
15208462SApril.Chin@Sun.COM nv_setsize(np,10);
15218462SApril.Chin@Sun.COM np->nvalue.ip = &shp->stats[i];
15228462SApril.Chin@Sun.COM }
15238462SApril.Chin@Sun.COM sp->hdr.dsize = sizeof(struct Stats) + nstat*(sizeof(int)+NV_MINSZ);
15248462SApril.Chin@Sun.COM sp->hdr.disc = &stat_disc;
15258462SApril.Chin@Sun.COM nv_stack(SH_STATS,&sp->hdr);
15268462SApril.Chin@Sun.COM sp->hdr.nofree = 1;
15278462SApril.Chin@Sun.COM nv_setvtree(SH_STATS);
15288462SApril.Chin@Sun.COM }
15298462SApril.Chin@Sun.COM #else
15308462SApril.Chin@Sun.COM # define stat_init(x)
15318462SApril.Chin@Sun.COM #endif /* SHOPT_STATS */
15328462SApril.Chin@Sun.COM
15334887Schin /*
15344887Schin * Initialize the shell name and alias table
15354887Schin */
nv_init(Shell_t * shp)15364887Schin static Init_t *nv_init(Shell_t *shp)
15374887Schin {
15384887Schin Namval_t *np;
15394887Schin register Init_t *ip;
15404887Schin double d=0;
15414887Schin ip = newof(0,Init_t,1,0);
15424887Schin if(!ip)
15434887Schin return(0);
15448462SApril.Chin@Sun.COM shp->nvfun.last = (char*)shp;
15458462SApril.Chin@Sun.COM shp->nvfun.nofree = 1;
15464887Schin ip->sh = shp;
15474887Schin shp->var_base = shp->var_tree = inittree(shp,shtab_variables);
15488462SApril.Chin@Sun.COM SHLVL->nvalue.ip = &shlvl;
15494887Schin ip->IFS_init.hdr.disc = &IFS_disc;
15504887Schin ip->IFS_init.hdr.nofree = 1;
15518462SApril.Chin@Sun.COM ip->PATH_init.disc = &RESTRICTED_disc;
15528462SApril.Chin@Sun.COM ip->PATH_init.nofree = 1;
15538462SApril.Chin@Sun.COM ip->FPATH_init.disc = &RESTRICTED_disc;
15548462SApril.Chin@Sun.COM ip->FPATH_init.nofree = 1;
15558462SApril.Chin@Sun.COM ip->CDPATH_init.disc = &CDPATH_disc;
15568462SApril.Chin@Sun.COM ip->CDPATH_init.nofree = 1;
15578462SApril.Chin@Sun.COM ip->SHELL_init.disc = &RESTRICTED_disc;
15588462SApril.Chin@Sun.COM ip->SHELL_init.nofree = 1;
15598462SApril.Chin@Sun.COM ip->ENV_init.disc = &RESTRICTED_disc;
15608462SApril.Chin@Sun.COM ip->ENV_init.nofree = 1;
15618462SApril.Chin@Sun.COM ip->VISUAL_init.disc = &EDITOR_disc;
15628462SApril.Chin@Sun.COM ip->VISUAL_init.nofree = 1;
15638462SApril.Chin@Sun.COM ip->EDITOR_init.disc = &EDITOR_disc;
15648462SApril.Chin@Sun.COM ip->EDITOR_init.nofree = 1;
15658462SApril.Chin@Sun.COM ip->HISTFILE_init.disc = &HISTFILE_disc;
15668462SApril.Chin@Sun.COM ip->HISTFILE_init.nofree = 1;
15678462SApril.Chin@Sun.COM ip->HISTSIZE_init.disc = &HISTFILE_disc;
15688462SApril.Chin@Sun.COM ip->HISTSIZE_init.nofree = 1;
15698462SApril.Chin@Sun.COM ip->OPTINDEX_init.disc = &OPTINDEX_disc;
15708462SApril.Chin@Sun.COM ip->OPTINDEX_init.nofree = 1;
15714887Schin ip->SECONDS_init.hdr.disc = &SECONDS_disc;
15724887Schin ip->SECONDS_init.hdr.nofree = 1;
15734887Schin ip->RAND_init.hdr.disc = &RAND_disc;
15744887Schin ip->RAND_init.hdr.nofree = 1;
15754887Schin ip->SH_MATCH_init.hdr.disc = &SH_MATCH_disc;
15764887Schin ip->SH_MATCH_init.hdr.nofree = 1;
15778462SApril.Chin@Sun.COM ip->SH_VERSION_init.disc = &SH_VERSION_disc;
15788462SApril.Chin@Sun.COM ip->SH_VERSION_init.nofree = 1;
15798462SApril.Chin@Sun.COM ip->LINENO_init.disc = &LINENO_disc;
15808462SApril.Chin@Sun.COM ip->LINENO_init.nofree = 1;
15818462SApril.Chin@Sun.COM ip->L_ARG_init.disc = &L_ARG_disc;
15828462SApril.Chin@Sun.COM ip->L_ARG_init.nofree = 1;
15834887Schin #ifdef _hdr_locale
15848462SApril.Chin@Sun.COM ip->LC_TYPE_init.disc = &LC_disc;
15858462SApril.Chin@Sun.COM ip->LC_TYPE_init.nofree = 1;
15868462SApril.Chin@Sun.COM ip->LC_NUM_init.disc = &LC_disc;
15878462SApril.Chin@Sun.COM ip->LC_NUM_init.nofree = 1;
15888462SApril.Chin@Sun.COM ip->LC_COLL_init.disc = &LC_disc;
15898462SApril.Chin@Sun.COM ip->LC_COLL_init.nofree = 1;
15908462SApril.Chin@Sun.COM ip->LC_MSG_init.disc = &LC_disc;
15918462SApril.Chin@Sun.COM ip->LC_MSG_init.nofree = 1;
15928462SApril.Chin@Sun.COM ip->LC_ALL_init.disc = &LC_disc;
15938462SApril.Chin@Sun.COM ip->LC_ALL_init.nofree = 1;
15948462SApril.Chin@Sun.COM ip->LANG_init.disc = &LC_disc;
15958462SApril.Chin@Sun.COM ip->LANG_init.nofree = 1;
15964887Schin #endif /* _hdr_locale */
15974887Schin nv_stack(IFSNOD, &ip->IFS_init.hdr);
15988462SApril.Chin@Sun.COM nv_stack(PATHNOD, &ip->PATH_init);
15998462SApril.Chin@Sun.COM nv_stack(FPATHNOD, &ip->FPATH_init);
16008462SApril.Chin@Sun.COM nv_stack(CDPNOD, &ip->CDPATH_init);
16018462SApril.Chin@Sun.COM nv_stack(SHELLNOD, &ip->SHELL_init);
16028462SApril.Chin@Sun.COM nv_stack(ENVNOD, &ip->ENV_init);
16038462SApril.Chin@Sun.COM nv_stack(VISINOD, &ip->VISUAL_init);
16048462SApril.Chin@Sun.COM nv_stack(EDITNOD, &ip->EDITOR_init);
16058462SApril.Chin@Sun.COM nv_stack(HISTFILE, &ip->HISTFILE_init);
16068462SApril.Chin@Sun.COM nv_stack(HISTSIZE, &ip->HISTSIZE_init);
16078462SApril.Chin@Sun.COM nv_stack(OPTINDNOD, &ip->OPTINDEX_init);
16084887Schin nv_stack(SECONDS, &ip->SECONDS_init.hdr);
16098462SApril.Chin@Sun.COM nv_stack(L_ARGNOD, &ip->L_ARG_init);
16108462SApril.Chin@Sun.COM nv_putval(SECONDS, (char*)&d, NV_DOUBLE);
16114887Schin nv_stack(RANDNOD, &ip->RAND_init.hdr);
16124887Schin d = (shp->pid&RANDMASK);
16138462SApril.Chin@Sun.COM nv_putval(RANDNOD, (char*)&d, NV_DOUBLE);
16148462SApril.Chin@Sun.COM nv_stack(LINENO, &ip->LINENO_init);
16154887Schin nv_putsub(SH_MATCHNOD,(char*)0,10);
16164887Schin nv_onattr(SH_MATCHNOD,NV_RDONLY);
16174887Schin nv_stack(SH_MATCHNOD, &ip->SH_MATCH_init.hdr);
16188462SApril.Chin@Sun.COM nv_stack(SH_VERSIONNOD, &ip->SH_VERSION_init);
16194887Schin #ifdef _hdr_locale
16208462SApril.Chin@Sun.COM nv_stack(LCTYPENOD, &ip->LC_TYPE_init);
16218462SApril.Chin@Sun.COM nv_stack(LCALLNOD, &ip->LC_ALL_init);
16228462SApril.Chin@Sun.COM nv_stack(LCMSGNOD, &ip->LC_MSG_init);
16238462SApril.Chin@Sun.COM nv_stack(LCCOLLNOD, &ip->LC_COLL_init);
16248462SApril.Chin@Sun.COM nv_stack(LCNUMNOD, &ip->LC_NUM_init);
16258462SApril.Chin@Sun.COM nv_stack(LANGNOD, &ip->LANG_init);
16264887Schin #endif /* _hdr_locale */
16274887Schin (PPIDNOD)->nvalue.lp = (&shp->ppid);
16284887Schin (TMOUTNOD)->nvalue.lp = (&shp->st.tmout);
16294887Schin (MCHKNOD)->nvalue.lp = (&sh_mailchk);
16304887Schin (OPTINDNOD)->nvalue.lp = (&shp->st.optindex);
16314887Schin /* set up the seconds clock */
16324887Schin shp->alias_tree = inittree(shp,shtab_aliases);
16334887Schin shp->track_tree = dtopen(&_Nvdisc,Dtset);
16344887Schin shp->bltin_tree = inittree(shp,(const struct shtable2*)shtab_builtins);
16354887Schin shp->fun_tree = dtopen(&_Nvdisc,Dtoset);
16364887Schin dtview(shp->fun_tree,shp->bltin_tree);
16374887Schin #if SHOPT_NAMESPACE
16384887Schin if(np = nv_mount(DOTSHNOD, "global", shp->var_tree))
16394887Schin nv_onattr(np,NV_RDONLY);
16404887Schin np = nv_search("namespace",nv_dict(DOTSHNOD),NV_ADD);
16414887Schin nv_putval(np,".sh.global",NV_RDONLY|NV_NOFREE);
16424887Schin nv_stack(np, &NSPACE_init);
16434887Schin #endif /* SHOPT_NAMESPACE */
16448462SApril.Chin@Sun.COM np = nv_mount(DOTSHNOD, "type", shp->typedict=dtopen(&_Nvdisc,Dtoset));
16454887Schin nv_adddisc(DOTSHNOD, shdiscnames, (Namval_t**)0);
16468462SApril.Chin@Sun.COM SH_LINENO->nvalue.ip = &shp->st.lineno;
16478462SApril.Chin@Sun.COM VERSIONNOD->nvalue.nrp = newof(0,struct Namref,1,0);
16488462SApril.Chin@Sun.COM VERSIONNOD->nvalue.nrp->np = SH_VERSIONNOD;
16498462SApril.Chin@Sun.COM VERSIONNOD->nvalue.nrp->root = nv_dict(DOTSHNOD);
16508462SApril.Chin@Sun.COM VERSIONNOD->nvalue.nrp->table = DOTSHNOD;
16518462SApril.Chin@Sun.COM nv_onattr(VERSIONNOD,NV_RDONLY|NV_REF);
16528462SApril.Chin@Sun.COM stat_init(shp);
16534887Schin return(ip);
16544887Schin }
16554887Schin
16564887Schin /*
16574887Schin * initialize name-value pairs
16584887Schin */
16594887Schin
inittree(Shell_t * shp,const struct shtable2 * name_vals)16604887Schin static Dt_t *inittree(Shell_t *shp,const struct shtable2 *name_vals)
16614887Schin {
16624887Schin register Namval_t *np;
16634887Schin register const struct shtable2 *tp;
16644887Schin register unsigned n = 0;
16654887Schin register Dt_t *treep;
16664887Schin Dt_t *base_treep, *dict;
16674887Schin for(tp=name_vals;*tp->sh_name;tp++)
16684887Schin n++;
16694887Schin np = (Namval_t*)calloc(n,sizeof(Namval_t));
16704887Schin if(!shp->bltin_nodes)
16718462SApril.Chin@Sun.COM {
16724887Schin shp->bltin_nodes = np;
16738462SApril.Chin@Sun.COM shp->bltin_nnodes = n;
16748462SApril.Chin@Sun.COM }
16754887Schin else if(name_vals==(const struct shtable2*)shtab_builtins)
16768462SApril.Chin@Sun.COM {
16774887Schin shp->bltin_cmds = np;
16788462SApril.Chin@Sun.COM nbltins = n;
16798462SApril.Chin@Sun.COM }
16804887Schin base_treep = treep = dtopen(&_Nvdisc,Dtoset);
16818462SApril.Chin@Sun.COM treep->user = (void*)shp;
16824887Schin for(tp=name_vals;*tp->sh_name;tp++,np++)
16834887Schin {
16844887Schin if((np->nvname = strrchr(tp->sh_name,'.')) && np->nvname!=((char*)tp->sh_name))
16854887Schin np->nvname++;
16864887Schin else
16874887Schin {
16884887Schin np->nvname = (char*)tp->sh_name;
16894887Schin treep = base_treep;
16904887Schin }
16914887Schin np->nvenv = 0;
16924887Schin if(name_vals==(const struct shtable2*)shtab_builtins)
16934887Schin np->nvalue.bfp = ((struct shtable3*)tp)->sh_value;
16944887Schin else
16958462SApril.Chin@Sun.COM {
16968462SApril.Chin@Sun.COM if(name_vals == shtab_variables)
16978462SApril.Chin@Sun.COM np->nvfun = &sh.nvfun;
16984887Schin np->nvalue.cp = (char*)tp->sh_value;
16998462SApril.Chin@Sun.COM }
17004887Schin nv_setattr(np,tp->sh_number);
17014887Schin if(nv_istable(np))
17024887Schin nv_mount(np,(const char*)0,dict=dtopen(&_Nvdisc,Dtoset));
17034887Schin if(nv_isattr(np,NV_INTEGER))
17044887Schin nv_setsize(np,10);
17054887Schin else
17064887Schin nv_setsize(np,0);
17074887Schin dtinsert(treep,np);
17084887Schin if(nv_istable(np))
17094887Schin treep = dict;
17104887Schin }
17114887Schin return(treep);
17124887Schin }
17134887Schin
17144887Schin /*
17154887Schin * read in the process environment and set up name-value pairs
17164887Schin * skip over items that are not name-value pairs
17174887Schin */
17184887Schin
env_init(Shell_t * shp)17194887Schin static void env_init(Shell_t *shp)
17204887Schin {
17214887Schin register char *cp;
17224887Schin register Namval_t *np;
17234887Schin register char **ep=environ;
17244887Schin register char *next=0;
17254887Schin #ifdef _ENV_H
17264887Schin shp->env = env_open(environ,3);
17274887Schin env_delete(shp->env,"_");
17284887Schin #endif
17294887Schin if(ep)
17304887Schin {
17314887Schin while(cp= *ep++)
17324887Schin {
17334887Schin if(*cp=='A' && cp[1]=='_' && cp[2]=='_' && cp[3]=='z' && cp[4]=='=')
17344887Schin next = cp+4;
17354887Schin else if(np=nv_open(cp,shp->var_tree,(NV_EXPORT|NV_IDENT|NV_ASSIGN|NV_NOFAIL)))
17364887Schin {
17374887Schin nv_onattr(np,NV_IMPORT);
17384887Schin np->nvenv = cp;
17394887Schin nv_close(np);
17404887Schin }
1741*12068SRoger.Faulkner@Oracle.COM else /* swap with front */
17428462SApril.Chin@Sun.COM {
17438462SApril.Chin@Sun.COM ep[-1] = environ[shp->nenv];
17448462SApril.Chin@Sun.COM environ[shp->nenv++] = cp;
17458462SApril.Chin@Sun.COM }
17464887Schin }
17474887Schin while(cp=next)
17484887Schin {
17494887Schin if(next = strchr(++cp,'='))
17504887Schin *next = 0;
17514887Schin np = nv_search(cp+2,shp->var_tree,NV_ADD);
1752*12068SRoger.Faulkner@Oracle.COM if(np!=SHLVL && nv_isattr(np,NV_IMPORT|NV_EXPORT))
17534887Schin {
17544887Schin int flag = *(unsigned char*)cp-' ';
17554887Schin int size = *(unsigned char*)(cp+1)-' ';
17564887Schin if((flag&NV_INTEGER) && size==0)
17574887Schin {
17584887Schin /* check for floating*/
17594887Schin char *ep,*val = nv_getval(np);
17604887Schin strtol(val,&ep,10);
17614887Schin if(*ep=='.' || *ep=='e' || *ep=='E')
17624887Schin {
17634887Schin char *lp;
17644887Schin flag |= NV_DOUBLE;
17654887Schin if(*ep=='.')
17664887Schin {
17674887Schin strtol(ep+1,&lp,10);
17684887Schin if(*lp)
17694887Schin ep = lp;
17704887Schin }
17714887Schin if(*ep && *ep!='.')
17724887Schin {
17734887Schin flag |= NV_EXPNOTE;
17744887Schin size = ep-val;
17754887Schin }
17764887Schin else
17774887Schin size = strlen(ep);
17784887Schin size--;
17794887Schin }
17804887Schin }
17814887Schin nv_newattr(np,flag|NV_IMPORT|NV_EXPORT,size);
17824887Schin }
1783*12068SRoger.Faulkner@Oracle.COM else
1784*12068SRoger.Faulkner@Oracle.COM cp += 2;
17854887Schin }
17864887Schin }
17874887Schin #ifdef _ENV_H
17888462SApril.Chin@Sun.COM env_delete(shp->env,e_envmarker);
17894887Schin #endif
17904887Schin if(nv_isnull(PWDNOD) || nv_isattr(PWDNOD,NV_TAGGED))
17914887Schin {
17924887Schin nv_offattr(PWDNOD,NV_TAGGED);
17934887Schin path_pwd(0);
17944887Schin }
17954887Schin if((cp = nv_getval(SHELLNOD)) && (sh_type(cp)&SH_TYPE_RESTRICTED))
17964887Schin sh_onoption(SH_RESTRICTED); /* restricted shell */
17974887Schin return;
17984887Schin }
17994887Schin
18004887Schin /*
18014887Schin * terminate shell and free up the space
18024887Schin */
sh_term(void)18034887Schin int sh_term(void)
18044887Schin {
18054887Schin sfdisc(sfstdin,SF_POPDISC);
18064887Schin free((char*)sh.outbuff);
18074887Schin stakset(NIL(char*),0);
18084887Schin return(0);
18094887Schin }
18104887Schin
18114887Schin /* function versions of these */
18124887Schin
18134887Schin #define DISABLE /* proto workaround */
18144887Schin
DISABLE(int opt)18154887Schin unsigned long sh_isoption DISABLE (int opt)
18164887Schin {
18174887Schin return(sh_isoption(opt));
18184887Schin }
18194887Schin
DISABLE(int opt)18204887Schin unsigned long sh_onoption DISABLE (int opt)
18214887Schin {
18224887Schin return(sh_onoption(opt));
18234887Schin }
18244887Schin
DISABLE(int opt)18254887Schin unsigned long sh_offoption DISABLE (int opt)
18264887Schin {
18274887Schin return(sh_offoption(opt));
18284887Schin }
18294887Schin
DISABLE(void)18304887Schin void sh_sigcheck DISABLE (void)
18314887Schin {
18324887Schin sh_sigcheck();
18334887Schin }
18344887Schin
DISABLE(void)18354887Schin Dt_t* sh_bltin_tree DISABLE (void)
18364887Schin {
18374887Schin return(sh.bltin_tree);
18384887Schin }
1839