summaryrefslogtreecommitdiff
path: root/src/cmd/ksh93/bltins/misc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/ksh93/bltins/misc.c')
-rw-r--r--src/cmd/ksh93/bltins/misc.c590
1 files changed, 590 insertions, 0 deletions
diff --git a/src/cmd/ksh93/bltins/misc.c b/src/cmd/ksh93/bltins/misc.c
new file mode 100644
index 0000000..d810a05
--- /dev/null
+++ b/src/cmd/ksh93/bltins/misc.c
@@ -0,0 +1,590 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * exec [arg...]
+ * eval [arg...]
+ * jobs [-lnp] [job...]
+ * login [arg...]
+ * let expr...
+ * . file [arg...]
+ * :, true, false
+ * vpath [top] [base]
+ * vmap [top] [base]
+ * wait [job...]
+ * shift [n]
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#include "defs.h"
+#include "variables.h"
+#include "shnodes.h"
+#include "path.h"
+#include "io.h"
+#include "name.h"
+#include "history.h"
+#include "builtins.h"
+#include "jobs.h"
+
+#define DOTMAX MAXDEPTH /* maximum level of . nesting */
+
+static void noexport(Namval_t*,void*);
+
+struct login
+{
+ Shell_t *sh;
+ int clear;
+ char *arg0;
+};
+
+int b_exec(int argc,char *argv[], Shbltin_t *context)
+{
+ struct login logdata;
+ register int n;
+ logdata.clear = 0;
+ logdata.arg0 = 0;
+ logdata.sh = context->shp;
+ logdata.sh->st.ioset = 0;
+ while (n = optget(argv, sh_optexec)) switch (n)
+ {
+ case 'a':
+ logdata.arg0 = opt_info.arg;
+ argc = 0;
+ break;
+ case 'c':
+ logdata.clear=1;
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
+ return(2);
+ }
+ argv += opt_info.index;
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ if(*argv)
+ B_login(0,argv,(Shbltin_t*)&logdata);
+ return(0);
+}
+
+static void noexport(register Namval_t* np, void *data)
+{
+ NOT_USED(data);
+ nv_offattr(np,NV_EXPORT);
+}
+
+int B_login(int argc,char *argv[],Shbltin_t *context)
+{
+ struct checkpt *pp;
+ register struct login *logp=0;
+ register Shell_t *shp;
+ const char *pname;
+ if(argc)
+ shp = context->shp;
+ else
+ {
+ logp = (struct login*)context;
+ shp = logp->sh;
+ }
+ pp = (struct checkpt*)shp->jmplist;
+ if(sh_isoption(SH_RESTRICTED))
+ errormsg(SH_DICT,ERROR_exit(1),e_restricted,argv[0]);
+ else
+ {
+ register struct argnod *arg=shp->envlist;
+ register Namval_t* np;
+ register char *cp;
+ if(shp->subshell && !shp->subshare)
+ sh_subfork();
+ if(logp && logp->clear)
+ {
+#ifdef _ENV_H
+ env_close(shp->env);
+ shp->env = env_open((char**)0,3);
+#else
+ nv_scan(shp->var_tree,noexport,0,NV_EXPORT,NV_EXPORT);
+#endif
+ }
+ while(arg)
+ {
+ if((cp=strchr(arg->argval,'=')) &&
+ (*cp=0,np=nv_search(arg->argval,shp->var_tree,0)))
+ {
+ nv_onattr(np,NV_EXPORT);
+ sh_envput(shp->env,np);
+ }
+ if(cp)
+ *cp = '=';
+ arg=arg->argnxt.ap;
+ }
+ pname = argv[0];
+ if(logp && logp->arg0)
+ argv[0] = logp->arg0;
+#ifdef JOBS
+ if(job_close(shp) < 0)
+ return(1);
+#endif /* JOBS */
+ /* force bad exec to terminate shell */
+ pp->mode = SH_JMPEXIT;
+ sh_sigreset(2);
+ sh_freeup(shp);
+ path_exec(shp,pname,argv,NIL(struct argnod*));
+ sh_done(shp,0);
+ }
+ return(1);
+}
+
+int b_let(int argc,char *argv[],Shbltin_t *context)
+{
+ register int r;
+ register char *arg;
+ Shell_t *shp = context->shp;
+ NOT_USED(argc);
+ while (r = optget(argv,sh_optlet)) switch (r)
+ {
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ argv += opt_info.index;
+ if(error_info.errors || !*argv)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ while(arg= *argv++)
+ r = !sh_arith(shp,arg);
+ return(r);
+}
+
+int b_eval(int argc,char *argv[], Shbltin_t *context)
+{
+ register int r;
+ register Shell_t *shp = context->shp;
+ NOT_USED(argc);
+ while (r = optget(argv,sh_opteval)) switch (r)
+ {
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(0), "%s",opt_info.arg);
+ return(2);
+ }
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ argv += opt_info.index;
+ if(*argv && **argv)
+ {
+ sh_offstate(SH_MONITOR);
+ sh_eval(sh_sfeval(argv),0);
+ }
+ return(shp->exitval);
+}
+
+int b_dot_cmd(register int n,char *argv[],Shbltin_t *context)
+{
+ register char *script;
+ register Namval_t *np;
+ register int jmpval;
+ register Shell_t *shp = context->shp;
+ struct sh_scoped savst, *prevscope = shp->st.self;
+ char *filename=0;
+ int fd;
+ struct dolnod *argsave=0, *saveargfor;
+ struct checkpt buff;
+ Sfio_t *iop=0;
+ short level;
+ while (n = optget(argv,sh_optdot)) switch (n)
+ {
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(0), "%s",opt_info.arg);
+ return(2);
+ }
+ argv += opt_info.index;
+ script = *argv;
+ if(error_info.errors || !script)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ if(shp->dot_depth+1 > DOTMAX)
+ errormsg(SH_DICT,ERROR_exit(1),e_toodeep,script);
+ if(!(np=shp->posix_fun))
+ {
+ /* check for KornShell style function first */
+ np = nv_search(script,shp->fun_tree,0);
+ if(np && is_afunction(np) && !nv_isattr(np,NV_FPOSIX))
+ {
+ if(!np->nvalue.ip)
+ {
+ path_search(shp,script,NIL(Pathcomp_t**),0);
+ if(np->nvalue.ip)
+ {
+ if(nv_isattr(np,NV_FPOSIX))
+ np = 0;
+ }
+ else
+ errormsg(SH_DICT,ERROR_exit(1),e_found,script);
+ }
+ }
+ else
+ np = 0;
+ if(!np)
+ {
+ if((fd=path_open(shp,script,path_get(shp,script))) < 0)
+ errormsg(SH_DICT,ERROR_system(1),e_open,script);
+ filename = path_fullname(shp,stkptr(shp->stk,PATH_OFFSET));
+ }
+ }
+ *prevscope = shp->st;
+ shp->st.lineno = np?((struct functnod*)nv_funtree(np))->functline:1;
+ shp->st.var_local = shp->st.save_tree = shp->var_tree;
+ if(filename)
+ {
+ shp->st.filename = filename;
+ shp->st.lineno = 1;
+ }
+ level = shp->fn_depth+shp->dot_depth+1;
+ nv_putval(SH_LEVELNOD,(char*)&level,NV_INT16);
+ shp->st.prevst = prevscope;
+ shp->st.self = &savst;
+ shp->topscope = (Shscope_t*)shp->st.self;
+ prevscope->save_tree = shp->var_tree;
+ if(np)
+ shp->st.filename = np->nvalue.rp->fname;
+ nv_putval(SH_PATHNAMENOD, shp->st.filename ,NV_NOFREE);
+ shp->posix_fun = 0;
+ if(np || argv[1])
+ argsave = sh_argnew(shp,argv,&saveargfor);
+ sh_pushcontext(shp,&buff,SH_JMPDOT);
+ jmpval = sigsetjmp(buff.buff,0);
+ if(jmpval == 0)
+ {
+ shp->dot_depth++;
+ if(np)
+ sh_exec((Shnode_t*)(nv_funtree(np)),sh_isstate(SH_ERREXIT));
+ else
+ {
+ char buff[IOBSIZE+1];
+ iop = sfnew(NIL(Sfio_t*),buff,IOBSIZE,fd,SF_READ);
+ sh_offstate(SH_NOFORK);
+ sh_eval(iop,sh_isstate(SH_PROFILE)?SH_FUNEVAL:0);
+ }
+ }
+ sh_popcontext(shp,&buff);
+ if(!np)
+ free((void*)shp->st.filename);
+ shp->dot_depth--;
+ if((np || argv[1]) && jmpval!=SH_JMPSCRIPT)
+ sh_argreset(shp,argsave,saveargfor);
+ else
+ {
+ prevscope->dolc = shp->st.dolc;
+ prevscope->dolv = shp->st.dolv;
+ }
+ if (shp->st.self != &savst)
+ *shp->st.self = shp->st;
+ /* only restore the top Shscope_t portion for posix functions */
+ memcpy((void*)&shp->st, (void*)prevscope, sizeof(Shscope_t));
+ shp->topscope = (Shscope_t*)prevscope;
+ nv_putval(SH_PATHNAMENOD, shp->st.filename ,NV_NOFREE);
+ if(jmpval && jmpval!=SH_JMPFUN)
+ siglongjmp(*shp->jmplist,jmpval);
+ return(shp->exitval);
+}
+
+/*
+ * null, true command
+ */
+int b_true(int argc,register char *argv[],Shbltin_t *context)
+{
+ NOT_USED(argc);
+ NOT_USED(argv[0]);
+ NOT_USED(context);
+ return(0);
+}
+
+/*
+ * false command
+ */
+int b_false(int argc,register char *argv[], Shbltin_t *context)
+{
+ NOT_USED(argc);
+ NOT_USED(argv[0]);
+ NOT_USED(context);
+ return(1);
+}
+
+int b_shift(register int n, register char *argv[], Shbltin_t *context)
+{
+ register char *arg;
+ register Shell_t *shp = context->shp;
+ while((n = optget(argv,sh_optshift))) switch(n)
+ {
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(0), "%s",opt_info.arg);
+ return(2);
+ }
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ argv += opt_info.index;
+ n = ((arg= *argv)?(int)sh_arith(shp,arg):1);
+ if(n<0 || shp->st.dolc<n)
+ errormsg(SH_DICT,ERROR_exit(1),e_number,arg);
+ else
+ {
+ shp->st.dolv += n;
+ shp->st.dolc -= n;
+ }
+ return(0);
+}
+
+int b_wait(int n,register char *argv[],Shbltin_t *context)
+{
+ register Shell_t *shp = context->shp;
+ while((n = optget(argv,sh_optwait))) switch(n)
+ {
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s",opt_info.arg);
+ break;
+ }
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ argv += opt_info.index;
+ job_bwait(argv);
+ return(shp->exitval);
+}
+
+#ifdef JOBS
+# if 0
+ /* for the dictionary generator */
+ int b_fg(int n,char *argv[],Shbltin_t *context){}
+ int b_disown(int n,char *argv[],Shbltin_t *context){}
+# endif
+int b_bg(register int n,register char *argv[],Shbltin_t *context)
+{
+ register int flag = **argv;
+ register Shell_t *shp = context->shp;
+ register const char *optstr = sh_optbg;
+ if(*argv[0]=='f')
+ optstr = sh_optfg;
+ else if(*argv[0]=='d')
+ optstr = sh_optdisown;
+ while((n = optget(argv,optstr))) switch(n)
+ {
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s",opt_info.arg);
+ break;
+ }
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ argv += opt_info.index;
+ if(!sh_isoption(SH_MONITOR) || !job.jobcontrol)
+ {
+ if(sh_isstate(SH_INTERACTIVE))
+ errormsg(SH_DICT,ERROR_exit(1),e_no_jctl);
+ return(1);
+ }
+ if(flag=='d' && *argv==0)
+ argv = (char**)0;
+ if(job_walk(sfstdout,job_switch,flag,argv))
+ errormsg(SH_DICT,ERROR_exit(1),e_no_job);
+ return(shp->exitval);
+}
+
+int b_jobs(register int n,char *argv[],Shbltin_t *context)
+{
+ register int flag = 0;
+ register Shell_t *shp = context->shp;
+ while((n = optget(argv,sh_optjobs))) switch(n)
+ {
+ case 'l':
+ flag = JOB_LFLAG;
+ break;
+ case 'n':
+ flag = JOB_NFLAG;
+ break;
+ case 'p':
+ flag = JOB_PFLAG;
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s",opt_info.arg);
+ break;
+ }
+ argv += opt_info.index;
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ if(*argv==0)
+ argv = (char**)0;
+ if(job_walk(sfstdout,job_list,flag,argv))
+ errormsg(SH_DICT,ERROR_exit(1),e_no_job);
+ job_wait((pid_t)0);
+ return(shp->exitval);
+}
+#endif
+
+#ifdef _cmd_universe
+/*
+ * There are several universe styles that are masked by the getuniv(),
+ * setuniv() calls.
+ */
+int b_universe(int argc, char *argv[],Shbltin_t *context)
+{
+ register char *arg;
+ register int n;
+ NOT_USED(context);
+ while((n = optget(argv,sh_optuniverse))) switch(n)
+ {
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s",opt_info.arg);
+ break;
+ }
+ argv += opt_info.index;
+ argc -= opt_info.index;
+ if(error_info.errors || argc>1)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ if(arg = argv[0])
+ {
+ if(!astconf("UNIVERSE",0,arg))
+ errormsg(SH_DICT,ERROR_exit(1), e_badname,arg);
+ }
+ else
+ {
+ if(!(arg=astconf("UNIVERSE",0,0)))
+ errormsg(SH_DICT,ERROR_exit(1),e_nouniverse);
+ else
+ sfputr(sfstdout,arg,'\n');
+ }
+ return(0);
+}
+#endif /* cmd_universe */
+
+#if SHOPT_FS_3D
+#if _UWIN
+#include <sys/mount.h>
+#endif
+# if 0
+ /* for the dictionary generator */
+ int b_vmap(int argc,char *argv[], Shbltin_t *context){}
+# endif
+ int b_vpath(register int argc,char *argv[], Shbltin_t *context)
+ {
+ register int flag, n;
+ register const char *optstr;
+ register char *vend;
+ register Shell_t *shp = context->shp;
+ if(argv[0][1]=='p')
+ {
+ optstr = sh_optvpath;
+ flag = FS3D_VIEW;
+ }
+ else
+ {
+ optstr = sh_optvmap;
+ flag = FS3D_VERSION;
+ }
+ while(n = optget(argv, optstr)) switch(n)
+ {
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s",opt_info.arg);
+ break;
+ }
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+#ifdef MS_3D
+ flag |= MS_3D;
+#else
+ if(!shp->gd->lim.fs3d)
+ goto failed;
+#endif
+ argv += opt_info.index;
+ argc -= opt_info.index;
+ switch(argc)
+ {
+ case 0:
+ case 1:
+ flag |= FS3D_GET;
+ if((n = mount(*argv,(char*)0,flag,0)) >= 0)
+ {
+ vend = stkalloc(shp->stk,++n);
+ n = mount(*argv,vend,flag|FS3D_SIZE(n),0);
+ }
+ if(n < 0)
+ goto failed;
+ if(argc==1)
+ {
+ sfprintf(sfstdout,"%s\n",vend);
+ break;
+ }
+ n = 0;
+ while(flag = *vend++)
+ {
+ if(flag==' ')
+ {
+ flag = e_sptbnl[n+1];
+ n = !n;
+ }
+ sfputc(sfstdout,flag);
+ }
+ if(n)
+ sfputc(sfstdout,'\n');
+ break;
+ default:
+ if((argc&1))
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ /*FALLTHROUGH*/
+ case 2:
+ if(shp->subshell && !shp->subshare)
+ sh_subfork();
+ for(n=0;n<argc;n+=2)
+ if(mount(argv[n+1],argv[n],flag,0)<0)
+ goto failed;
+ }
+ return(0);
+failed:
+ errormsg(SH_DICT,ERROR_exit(1),(argc>1)?e_cantset:e_cantget,(flag&FS3D_VIEW)?e_mapping:e_versions);
+ return(1);
+ }
+#endif /* SHOPT_FS_3D */
+