Esempio n. 1
0
int    B_login(int argc,char *argv[],void *extra)
{
	struct checkpt *pp;
	register struct login *logp=0;
	register Shell_t *shp;
	const char *pname;
	if(argc)
		shp = ((Shbltin_t*)extra)->shp;
	else
	{
		logp = (struct login*)extra;
		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(pname,argv,NIL(struct argnod*));
		sh_done(shp,0);
        }
	return(1);
}
Esempio n. 2
0
static void r_comarg(Shell_t *shp,struct comnod *com)
{
	char *cmdname=0;
	com->comio = r_redirect(shp);
	com->comset = r_arg(shp);
	com->comstate = 0;
	if(com->comtyp&COMSCAN)
	{
		com->comarg = r_arg(shp);
		if(com->comarg->argflag==ARG_RAW)
			cmdname = com->comarg->argval;
	}
	else if(com->comarg = (struct argnod*)r_comlist(shp))
		cmdname = ((struct dolnod*)(com->comarg))->dolval[ARG_SPARE];
	com->comline = sfgetu(infile);
	com->comnamq = 0;
	if(cmdname)
	{
		char *cp;
		com->comnamp = (void*)nv_search(cmdname,shp->fun_tree,0);
		if(com->comnamp && (cp =strrchr(cmdname+1,'.')))
		{
			*cp = 0;
			com->comnamp =  (void*)nv_open(cmdname,shp->var_tree,NV_VARNAME|NV_NOADD|NV_NOARRAY);
			*cp = '.';
		}
	}
	else
		com->comnamp  = 0;
}
Esempio n. 3
0
File: completion.c Progetto: att/ast
//
// Look for edit macro named _i. If found, puts the macro definition into lookahead buffer and
// returns 1.
//
int ed_macro(Edit_t *ep, int i) {
    char *out;
    Namval_t *np;
    genchar buff[LOOKAHEAD + 1];

    if (i != '@') ep->e_macro[1] = i;
    // Undocumented feature, macros of the form <ESC>[c evoke alias __c.
    if (i == '_') {
        ep->e_macro[2] = ed_getchar(ep, 1);
    } else {
        ep->e_macro[2] = 0;
    }
    if (isalnum(i) && (np = nv_search(ep->e_macro, ep->sh->alias_tree, 0)) &&
        (out = nv_getval(np))) {
        // Copy to buff in internal representation.
        int c = 0;
        if (strlen(out) > LOOKAHEAD) {
            c = out[LOOKAHEAD];
            out[LOOKAHEAD] = 0;
        }
        i = ed_internal(out, buff);
        if (c) out[LOOKAHEAD] = c;
        while (i-- > 0) ed_ungetchar(ep, buff[i]);
        return 1;
    }
    return 0;
}
Esempio n. 4
0
void lib_init(int flag, void* context)
{
	Shell_t		*shp = ((Shbltin_t*)context)->shp;
	Namval_t	*mp,*bp;
	if(flag)
		return;
	bp = sh_addbuiltin(shp,"Enum", enum_create, (void*)0); 
	mp = nv_search("typeset",shp->bltin_tree,0);
	nv_onattr(bp,nv_isattr(mp,NV_PUBLIC));
}
Esempio n. 5
0
static Namval_t *make_time(Namval_t* np)
{
	int offset = stktell(stkstd);
	char *name = nv_name(np);
	struct dctime *dp = newof(NULL,struct dctime,1,0); 
	if(!dp)
		return((Namval_t*)0);
	sfprintf(stkstd,"%s.format\0",name);
	sfputc(stkstd,0);
	dp->format = nv_search(stkptr(stkstd,offset),sh.var_tree,NV_ADD);
	dp->fun.disc = &timedisc;
	nv_stack(np,&dp->fun);
	return(np);
}
Esempio n. 6
0
static Namval_t *sh_newnode(register Shfield_t *fp, Namval_t *np)
{
	char *val = np->nvalue + fp->offset;
	char *name = nv_name(np);
	register Namval_t *nq;
	int offset = stktell(stkstd);
	sfprintf(stkstd,"%s.%s\0",name,fp->name);
	sfputc(stkstd,0);
	nq = nv_search(stkptr(stkstd,offset),sh.var_tree,NV_ADD);
	if(fp->size<0)
		val = *(char**)val;
	nv_putval(nq,val,fp->flags|NV_NOFREE);
	if(fp->make)
		(*fp->make)(nq);
	return(nq);
}
Esempio n. 7
0
File: misc.c Progetto: att/ast
//
// Builtin `login`.
//
int B_login(int argc, char *argv[], Shbltin_t *context) {
    checkpt_t *pp;
    struct login *logp = NULL;
    Shell_t *shp;
    const char *pname;
    if (argc) {
        shp = context->shp;
    } else {
        logp = (struct login *)context;
        shp = logp->sh;
    }

    pp = shp->jmplist;
    if (sh_isoption(shp, SH_RESTRICTED)) {
        errormsg(SH_DICT, ERROR_exit(1), e_restricted, argv[0]);
        __builtin_unreachable();
    } else {
        struct argnod *arg = shp->envlist;
        Namval_t *np;
        char *cp;
        if (shp->subshell && !shp->subshare) sh_subfork();
        if (logp && logp->clear) {
            nv_scan(shp->var_tree, noexport, 0, NV_EXPORT, NV_EXPORT);
        }
        while (arg) {
            cp = strchr(arg->argval, '=');
            if (cp && (*cp = 0, np = nv_search(arg->argval, shp->var_tree, 0))) {
                nv_onattr(np, NV_EXPORT);
                sh_envput(shp, 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(shp, 2);
        sh_freeup(shp);
        path_exec(shp, pname, argv, NULL);
        sh_done(shp, 0);
    }
    return 1;
}
Esempio n. 8
0
int    b_dot_cmd(register int n,char *argv[],void* extra)
{
	register char *script;
	register Namval_t *np;
	register int jmpval;
	register Shell_t *shp = ((Shbltin_t*)extra)->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(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);
			}
		}
Esempio n. 9
0
    static int  acctinit(History_t *hp)
    {
	register char *cp, *acctfile;
	Namval_t *np = nv_search("ACCTFILE",((Shell_t*)hp->histshell)->var_tree,0);

	if(!np || !(acctfile=nv_getval(np)))
		return(0);
	if(!(cp = getlogin()))
	{
		struct passwd *userinfo = getpwuid(getuid());
		if(userinfo)
			cp = userinfo->pw_name;
		else
			cp = "unknown";
	}
	logname = strdup(cp);
	if((acctfd=sh_open(acctfile,
		O_BINARY|O_WRONLY|O_APPEND|O_CREAT,S_IRUSR|S_IWUSR))>=0 &&
	    (unsigned)acctfd < 10)
	{
		int n;
		if((n = fcntl(acctfd, F_DUPFD, 10)) >= 0)
		{
			close(acctfd);
			acctfd = n;
		}
	}
	if(acctfd < 0)
	{
		acctfd = 0;
		return(0);
	}
	if(sh_isdevfd(acctfile))
	{
		char newfile[16];
		sfsprintf(newfile,sizeof(newfile),"%.8s%d\0",e_devfdNN,acctfd);
		nv_putval(np,newfile,NV_RDONLY);
	}
	else
		fcntl(acctfd,F_SETFD,FD_CLOEXEC);
	return(1);
    }
Esempio n. 10
0
/*
 * look for edit macro named _i
 * if found, puts the macro definition into lookahead buffer and returns 1
 */
int ed_macro(Edit_t *ep, register int i)
{
	register char *out;
	Namval_t *np;
	genchar buff[LOOKAHEAD+1];
	if(i != '@')
		ep->e_macro[1] = i;
	/* undocumented feature, macros of the form <ESC>[c evoke alias __c */
	if(i=='_')
		ep->e_macro[2] = ed_getchar(ep,1);
	else
		ep->e_macro[2] = 0;
	if (isalnum(i)&&(np=nv_search(ep->e_macro,ep->sh->alias_tree,HASH_SCOPE))&&(out=nv_getval(np)))
	{
#if SHOPT_MULTIBYTE
		/* copy to buff in internal representation */
		int c = 0;
		if( strlen(out) > LOOKAHEAD )
		{
			c = out[LOOKAHEAD];
			out[LOOKAHEAD] = 0;
		}
		i = ed_internal(out,buff);
		if(c)
			out[LOOKAHEAD] = c;
#else
		strncpy((char*)buff,out,LOOKAHEAD);
		buff[LOOKAHEAD] = 0;
		i = strlen((char*)buff);
#endif /* SHOPT_MULTIBYTE */
		while(i-- > 0)
			ed_ungetchar(ep,buff[i]);
		return(1);
	} 
	return(0);
}
Esempio n. 11
0
void	ed_setup(register Edit_t *ep, int fd, int reedit)
{
	Shell_t *shp = ep->sh;
	register char *pp;
	register char *last, *prev;
	char *ppmax;
	int myquote = 0, n;
	register int qlen = 1, qwid;
	char inquote = 0;
	ep->e_fd = fd;
	ep->e_multiline = sh_isoption(SH_MULTILINE)!=0;
#ifdef SIGWINCH
	if(!(shp->sigflag[SIGWINCH]&SH_SIGFAULT))
	{
		signal(SIGWINCH,sh_fault);
		shp->sigflag[SIGWINCH] |= SH_SIGFAULT;
	}
	pp = shp->st.trapcom[SIGWINCH];
	shp->st.trapcom[SIGWINCH] = 0;
	sh_fault(SIGWINCH);
	shp->st.trapcom[SIGWINCH] = pp;
	ep->sh->winch = 0;
#endif
#if SHOPT_EDPREDICT
	ep->hlist = 0;
	ep->nhlist = 0;
	ep->hoff = 0;
#endif /* SHOPT_EDPREDICT */
#if KSHELL
	ep->e_stkptr = stakptr(0);
	ep->e_stkoff = staktell();
	if(!(last = shp->prompt))
		last = "";
	shp->prompt = 0;
#else
	last = ep->e_prbuff;
#endif /* KSHELL */
	if(shp->gd->hist_ptr)
	{
		register History_t *hp = shp->gd->hist_ptr;
		ep->e_hismax = hist_max(hp);
		ep->e_hismin = hist_min(hp);
	}
	else
	{
		ep->e_hismax = ep->e_hismin = ep->e_hloff = 0;
	}
	ep->e_hline = ep->e_hismax;
	if(!sh_isoption(SH_VI) && !sh_isoption(SH_EMACS) && !sh_isoption(SH_GMACS))
		ep->e_wsize = MAXLINE;
	else
		ep->e_wsize = ed_window()-2;
	ep->e_winsz = ep->e_wsize+2;
	ep->e_crlf = 1;
	ep->e_plen = 0;
	pp = ep->e_prompt;
	ppmax = pp+PRSIZE-1;
	*pp++ = '\r';
	{
		register int c;
		while(prev = last, c = mbchar(last)) switch(c)
		{
			case ESC:
			{
				int skip=0;
				ep->e_crlf = 0;
				*pp++ = c;
				for(n=1; c = *last++; n++)
				{
					if(pp < ppmax)
						*pp++ = c;
					if(c=='\a' || c==ESC || c=='\r')
						break;
					if(skip || (c>='0' && c<='9'))
					{
						skip = 0;
						continue;
					}
					if(n>1 && c==';')
						skip = 1;
					else if(n>2 || (c!= '[' &&  c!= ']'))
						break;
				}
				if(c==0 || c==ESC || c=='\r')
					last--;
				qlen += (n+1);
				break;
			}
			case '\b':
				if(pp>ep->e_prompt+1)
					pp--;
				break;
			case '\r':
				if(pp == (ep->e_prompt+2)) /* quote char */
					myquote = *(pp-1);
				/*FALLTHROUGH*/

			case '\n':
				/* start again */
				ep->e_crlf = 1;
				qlen = 1;
				inquote = 0;
				pp = ep->e_prompt+1;
				break;

			case '\t':
				/* expand tabs */
				while((pp-ep->e_prompt)%TABSIZE)
				{
					if(pp >= ppmax)
						break;
					*pp++ = ' ';
				}
				break;

			case '\a':
				/* cut out bells */
				break;

			default:
				if(c==myquote)
				{
					qlen += inquote;
					inquote ^= 1;
				}
				if(pp < ppmax)
				{
					if(inquote)
						qlen++;
					else if(!is_print(c))
						ep->e_crlf = 0;
					if((qwid = last - prev) > 1)
						qlen += qwid - mbwidth(c);
					while(prev < last && pp < ppmax)
						*pp++ = *prev++;
				}
				break;
		}
	}
	if(pp-ep->e_prompt > qlen)
		ep->e_plen = pp - ep->e_prompt - qlen;
	*pp = 0;
	if(!ep->e_multiline && (ep->e_wsize -= ep->e_plen) < 7)
	{
		register int shift = 7-ep->e_wsize;
		ep->e_wsize = 7;
		pp = ep->e_prompt+1;
		strcpy(pp,pp+shift);
		ep->e_plen -= shift;
		last[-ep->e_plen-2] = '\r';
	}
	sfsync(sfstderr);
	if(fd == sffileno(sfstderr))
	{
		/* can't use output buffer when reading from stderr */
		static char *buff;
		if(!buff)
			buff = (char*)malloc(MAXLINE);
		ep->e_outbase = ep->e_outptr = buff;
		ep->e_outlast = ep->e_outptr + MAXLINE;
		return;
	}
	qlen = sfset(sfstderr,SF_READ,0);
	/* make sure SF_READ not on */
	ep->e_outbase = ep->e_outptr = (char*)sfreserve(sfstderr,SF_UNBOUND,SF_LOCKR);
	ep->e_outlast = ep->e_outptr + sfvalue(sfstderr);
	if(qlen)
		sfset(sfstderr,SF_READ,1);
	sfwrite(sfstderr,ep->e_outptr,0);
	ep->e_eol = reedit;
	if(ep->e_multiline)
	{
#ifdef _cmd_tput
		char *term;
		if(!ep->e_term)
			ep->e_term = nv_search("TERM",shp->var_tree,0);
		if(ep->e_term && (term=nv_getval(ep->e_term)) && strlen(term)<sizeof(ep->e_termname) && strcmp(term,ep->e_termname))
		{
			sh_trap(".sh.subscript=$(tput cuu1 2>/dev/null)",0);
			if(pp=nv_getval(SH_SUBSCRNOD))
				strncpy(CURSOR_UP,pp,sizeof(CURSOR_UP)-1);
			nv_unset(SH_SUBSCRNOD);
			strcpy(ep->e_termname,term);
		}
#endif
		ep->e_wsize = MAXLINE - (ep->e_plen+1);
	}
	if(ep->e_default && (pp = nv_getval(ep->e_default)))
	{
		n = strlen(pp);
		if(n > LOOKAHEAD)
			n = LOOKAHEAD;
		ep->e_lookahead = n;
		while(n-- > 0)
			ep->e_lbuf[n] = *pp++;
		ep->e_default = 0;
	}
}
Esempio n. 12
0
int ed_expand(Edit_t *ep, char outbuff[],int *cur,int *eol,int mode, int count)
{
	struct comnod	*comptr;
	struct argnod	*ap;
	register char	*out;
	char 		*av[2], *begin , *dir=0;
	int		addstar=0, rval=0, var=0, strip=1;
	int 		nomarkdirs = !sh_isoption(SH_MARKDIRS);
	sh_onstate(SH_FCOMPLETE);
	if(ep->e_nlist)
	{
		if(mode=='=' && count>0)
		{
			if(count> ep->e_nlist)
				return(-1);
			mode = '?';
			av[0] = ep->e_clist[count-1];
			av[1] = 0;
		}
		else
		{
			stakset(ep->e_stkptr,ep->e_stkoff);
			ep->e_nlist = 0;
		}
	}
	comptr = (struct comnod*)stakalloc(sizeof(struct comnod));
	ap = (struct argnod*)stakseek(ARGVAL);
#if SHOPT_MULTIBYTE
	{
		register int c = *cur;
		register genchar *cp;
		/* adjust cur */
		cp = (genchar *)outbuff + *cur;
		c = *cp;
		*cp = 0;
		*cur = ed_external((genchar*)outbuff,(char*)stakptr(0));
		*cp = c;
		*eol = ed_external((genchar*)outbuff,outbuff);
	}
#endif /* SHOPT_MULTIBYTE */
	out = outbuff + *cur + (sh_isoption(SH_VI)!=0);
	if(out[-1]=='"' || out[-1]=='\'')
	{
		rval = -(sh_isoption(SH_VI)!=0);
		goto done;
	}
	comptr->comtyp = COMSCAN;
	comptr->comarg = ap;
	ap->argflag = (ARG_MAC|ARG_EXP);
	ap->argnxt.ap = 0;
	ap->argchn.cp = 0;
	{
		register int c;
		char *last = out;
		c =  *(unsigned char*)out;
		var = mode;
		begin = out = find_begin(outbuff,last,0,&var);
		/* addstar set to zero if * should not be added */
		if(var=='$')
		{
			stakputs("${!");
			stakwrite(out,last-out);
			stakputs("@}");
			out = last;
		}
		else
		{
			addstar = '*';
			while(out < last)
			{
				c = *(unsigned char*)out;
				if(isexp(c))
					addstar = 0;
				if (c == '/')
				{
					if(addstar == 0)
						strip = 0;
					dir = out+1;
				}
				stakputc(c);
				out++;
			}
		}
		if(mode=='?')
			mode = '*';
		if(var!='$' && mode=='\\' && out[-1]!='*')
			addstar = '*';
		if(*begin=='~' && !strchr(begin,'/'))
			addstar = 0;
		stakputc(addstar);
		ap = (struct argnod*)stakfreeze(1);
	}
	if(mode!='*')
		sh_onoption(SH_MARKDIRS);
	{
		register char	**com;
		char		*cp=begin, *left=0, *saveout=".";
		int	 	nocase=0,narg,cmd_completion=0;
		register 	int size='x';
		while(cp>outbuff && ((size=cp[-1])==' ' || size=='\t'))
			cp--;
		if(!var && !strchr(ap->argval,'/') && (((cp==outbuff&&ep->sh->nextprompt==1) || (strchr(";&|(",size)) && (cp==outbuff+1||size=='('||cp[-2]!='>') && *begin!='~' )))
		{
			cmd_completion=1;
			sh_onstate(SH_COMPLETE);
		}
		if(ep->e_nlist)
		{
			narg = 1;
			com = av;
			if(dir)
				begin += (dir-begin);
		}
		else
		{
			com = sh_argbuild(ep->sh,&narg,comptr,0);
			/* special handling for leading quotes */
			if(begin>outbuff && (begin[-1]=='"' || begin[-1]=='\''))
			begin--;
		}
		sh_offstate(SH_COMPLETE);
                /* allow a search to be aborted */
		if(ep->sh->trapnote&SH_SIGSET)
		{
			rval = -1;
			goto done;
		}
		/*  match? */
		if (*com==0 || (narg <= 1 && (strcmp(ap->argval,*com)==0) || (addstar && com[0][strlen(*com)-1]=='*')))
		{
			rval = -1;
			goto done;
		}
		if(mode=='\\' && out[-1]=='/'  && narg>1)
			mode = '=';
		if(mode=='=')
		{
			if (strip && !cmd_completion)
			{
				register char **ptrcom;
				for(ptrcom=com;*ptrcom;ptrcom++)
					/* trim directory prefix */
					*ptrcom = path_basename(*ptrcom);
			}
			sfputc(sfstderr,'\n');
			sh_menu(sfstderr,narg,com);
			sfsync(sfstderr);
			ep->e_nlist = narg;
			ep->e_clist = com;
			goto done;
		}
		/* see if there is enough room */
		size = *eol - (out-begin);
		if(mode=='\\')
		{
			int c;
			if(dir)
			{
				c = *dir;
				*dir = 0;
				saveout = begin;
			}
			if(saveout=astconf("PATH_ATTRIBUTES",saveout,(char*)0))
				nocase = (strchr(saveout,'c')!=0);
			if(dir)
				*dir = c;
			/* just expand until name is unique */
			size += strlen(*com);
		}
		else
		{
			size += narg;
			{
				char **savcom = com;
				while (*com)
					size += strlen(cp=fmtx(*com++));
				com = savcom;
			}
		}
		/* see if room for expansion */
		if(outbuff+size >= &outbuff[MAXLINE])
		{
			com[0] = ap->argval;
			com[1] = 0;
		}
		/* save remainder of the buffer */
		if(*out)
			left=stakcopy(out);
		if(cmd_completion && mode=='\\')
			out = strcopy(begin,path_basename(cp= *com++));
		else if(mode=='*')
		{
			if(ep->e_nlist && dir && var)
			{
				if(*cp==var)
					cp++;
				else
					*begin++ = var;
				out = strcopy(begin,cp);
				var = 0;
			}
			else
				out = strcopy(begin,fmtx(*com));
			com++;
		}
		else
			out = strcopy(begin,*com++);
		if(mode=='\\')
		{
			saveout= ++out;
			while (*com && *begin)
			{
				if(cmd_completion)
					out = overlaid(begin,path_basename(*com++),nocase);
				else
					out = overlaid(begin,*com++,nocase);
			}
			mode = (out==saveout);
			if(out[-1]==0)
				out--;
			if(mode && out[-1]!='/')
			{
				if(cmd_completion)
				{
					Namval_t *np;
					/* add as tracked alias */
					Pathcomp_t *pp;
					if(*cp=='/' && (pp=path_dirfind(ep->sh->pathlist,cp,'/')) && (np=nv_search(begin,ep->sh->track_tree,NV_ADD)))
						path_alias(np,pp);
					out = strcopy(begin,cp);
				}
				/* add quotes if necessary */
				if((cp=fmtx(begin))!=begin)
					out = strcopy(begin,cp);
				if(var=='$' && begin[-1]=='{')
					*out = '}';
				else
					*out = ' ';
				*++out = 0;
			}
			else if((cp=fmtx(begin))!=begin)
			{
				out = strcopy(begin,cp);
				if(out[-1] =='"' || out[-1]=='\'')
					  *--out = 0;
			}
			if(*begin==0)
				ed_ringbell();
		}
		else
		{
			while (*com)
			{
				*out++  = ' ';
				out = strcopy(out,fmtx(*com++));
			}
		}
		if(ep->e_nlist)
		{
			cp = com[-1];
			if(cp[strlen(cp)-1]!='/')
			{
				if(var=='$' && begin[-1]=='{')
					*out = '}';
				else
					*out = ' ';
				out++;
			}
			else if(out[-1] =='"' || out[-1]=='\'')
				out--;
			*out = 0;
		}
		*cur = (out-outbuff);
		/* restore rest of buffer */
		if(left)
			out = strcopy(out,left);
		*eol = (out-outbuff);
	}
 done:
	sh_offstate(SH_FCOMPLETE);
	if(!ep->e_nlist)
		stakset(ep->e_stkptr,ep->e_stkoff);
	if(nomarkdirs)
		sh_offoption(SH_MARKDIRS);
#if SHOPT_MULTIBYTE
	{
		register int c,n=0;
		/* first re-adjust cur */
		c = outbuff[*cur];
		outbuff[*cur] = 0;
		for(out=outbuff; *out;n++)
			mbchar(out);
		outbuff[*cur] = c;
		*cur = n;
		outbuff[*eol+1] = 0;
		*eol = ed_internal(outbuff,(genchar*)outbuff);
	}
#endif /* SHOPT_MULTIBYTE */
	return(rval);
}
Esempio n. 13
0
static int whence(Shell_t *shp,char **argv, register int flags)
{
	register const char *name;
	register Namval_t *np;
	register const char *cp;
	register int aflag,r=0;
	register const char *msg;
	int	tofree;
	Dt_t *root;
	Namval_t *nq;
	char *notused;
	Pathcomp_t *pp=0;
	int notrack = 1;
	if(flags&Q_FLAG)
		flags &= ~A_FLAG;
	while(name= *argv++)
	{
		tofree=0;
		aflag = ((flags&A_FLAG)!=0);
		cp = 0;
		np = 0;
		if(flags&P_FLAG)
			goto search;
		if(flags&Q_FLAG)
			goto bltins;
		/* reserved words first */
		if(sh_lookup(name,shtab_reserved))
		{
			sfprintf(sfstdout,"%s%s\n",name,(flags&V_FLAG)?sh_translate(is_reserved):"");
			if(!aflag)
				continue;
			aflag++;
		}
		/* non-tracked aliases */
		if((np=nv_search(name,shp->alias_tree,0))
			&& !nv_isnull(np) && !(notrack=nv_isattr(np,NV_TAGGED))
			&& (cp=nv_getval(np))) 
		{
			if(flags&V_FLAG)
			{
				if(nv_isattr(np,NV_EXPORT))
					msg = sh_translate(is_xalias);
				else
					msg = sh_translate(is_alias);
				sfprintf(sfstdout,msg,name);
			}
			sfputr(sfstdout,sh_fmtq(cp),'\n');
			if(!aflag)
				continue;
			cp = 0;
			aflag++;
		}
		/* built-ins and functions next */
	bltins:
		root = (flags&F_FLAG)?shp->bltin_tree:shp->fun_tree;
		if(np= nv_bfsearch(name, root, &nq, &notused))
		{
			if(is_abuiltin(np) && nv_isnull(np))
				goto search;
			cp = "";
			if(flags&V_FLAG)
			{
				if(nv_isnull(np))
					cp = sh_translate(is_ufunction);
				else if(is_abuiltin(np))
				{
					if(nv_isattr(np,BLT_SPC))
						cp = sh_translate(is_spcbuiltin);
					else
						cp = sh_translate(is_builtin);
				}
				else
					cp = sh_translate(is_function);
			}
			if(flags&Q_FLAG)
				continue;
			sfprintf(sfstdout,"%s%s\n",name,cp);
			if(!aflag)
				continue;
			cp = 0;
			aflag++;
		}
	search:
		if(sh_isstate(SH_DEFPATH))
		{
			cp=0;
			notrack=1;
		}
		do
		{
			if(path_search(shp,name,&pp,2+(aflag>1)))
			{
				cp = name;
				if((flags&P_FLAG) && *cp!='/')
					cp = 0;
			}
			else
			{
				cp = stakptr(PATH_OFFSET);
				if(*cp==0)
					cp = 0;
				else if(*cp!='/')
				{
					cp = path_fullname(shp,cp);
					tofree=1;
				}
			}
			if(flags&Q_FLAG)
			{
				pp = 0;
				r |= !cp;
			}
			else if(cp)
			{
				if(flags&V_FLAG)
				{
					if(*cp!= '/')
					{
						if(!np && (np=nv_search(name,shp->track_tree,0)))
							sfprintf(sfstdout,"%s %s %s/%s\n",name,sh_translate(is_talias),path_pwd(shp,0),cp);
						else if(!np || nv_isnull(np))
							sfprintf(sfstdout,"%s%s\n",name,sh_translate(is_ufunction));
						continue;
					}
					sfputr(sfstdout,sh_fmtq(name),' ');
					/* built-in version of program */
					if(*cp=='/' && (np=nv_search(cp,shp->bltin_tree,0)))
						msg = sh_translate(is_builtver);
					/* tracked aliases next */
					else if(aflag>1 || !notrack || strchr(name,'/'))
						msg = sh_translate("is");
					else
						msg = sh_translate(is_talias);
					sfputr(sfstdout,msg,' ');
				}
				sfputr(sfstdout,sh_fmtq(cp),'\n');
				if(aflag)
				{
					if(aflag<=1)
						aflag++;
					if (pp)
						pp = pp->next;
				}
				else
					pp = 0;
				if(tofree)
				{
					free((char*)cp);
					tofree = 0;
				}
			}
			else if(aflag<=1) 
			{
				r |= 1;
				if(flags&V_FLAG)
					 errormsg(SH_DICT,ERROR_exit(0),e_found,sh_fmtq(name));
			}
		} while(pp);
	}
	return(r);
}
Esempio n. 14
0
void *nv_diropen(Namval_t *np,const char *name)
{
	char *next,*last;
	int c,len=strlen(name);
	struct nvdir *save, *dp = new_of(struct nvdir,len+1);
	Namval_t *nq=0,fake;
	Namfun_t *nfp=0;
	if(!dp)
		return(0);
	memset((void*)dp, 0, sizeof(*dp));
	dp->data = (char*)(dp+1);
	if(name[len-1]=='*' || name[len-1]=='@')
		len -= 1;
	name = memcpy(dp->data,name,len);
	dp->data[len] = 0;
	dp->len = len;
	dp->root = sh.last_root?sh.last_root:sh.var_tree;
#if 1
	while(1)
	{
		dp->table = sh.last_table;
		sh.last_table = 0;
		if(*(last=(char*)name)==0)
			break;
		if(!(next=nextdot(last)))
			break;
		*next = 0;
		np = nv_open(name, dp->root, NV_NOFAIL);
		*next = '.';
		if(!np || !nv_istable(np))
			break;
		dp->root = nv_dict(np);
		name = next+1;
	}
#else
	dp->table = sh.last_table;
	sh.last_table = 0;
	last = dp->data;
#endif
	if(*name)
	{
		fake.nvname = (char*)name;
		if(dp->hp = (Namval_t*)dtprev(dp->root,&fake))
		{
			char *cp = nv_name(dp->hp);
			c = strlen(cp);
			if(memcmp(name,cp,c) || name[c]!='[')
				dp->hp = (Namval_t*)dtnext(dp->root,dp->hp);
			else
			{
				np = dp->hp;
				last = 0;
			}
		}
		else
			dp->hp = (Namval_t*)dtfirst(dp->root);
	}
	else
		dp->hp = (Namval_t*)dtfirst(dp->root);
	while(1)
	{
		if(!last)
			next = 0;
		else if(next= nextdot(last))
		{
			c = *next;
			*next = 0;
		}
		if(!np)
		{
			if(nfp && nfp->disc && nfp->disc->createf)
			{
				np =  (*nfp->disc->createf)(nq,last,0,nfp);
				if(*nfp->last == '[')
				{
					nv_endsubscript(np,nfp->last,NV_NOADD);
					if(nq = nv_opensub(np))
						np = nq;
				}
			}
			else
				np = nv_search(last,dp->root,0);
		}
		if(next)
			*next = c;
		if(np==dp->hp && !next)
			dp->hp = (Namval_t*)dtnext(dp->root,dp->hp);
		if(np && ((nfp=nextdisc(np)) || nv_istable(np)))
		{
			if(!(save = new_of(struct nvdir,0)))
				return(0);
			*save = *dp;
			dp->prev = save;
			if(nv_istable(np))
				dp->root = nv_dict(np);
			else
				dp->root = (Dt_t*)np;
			if(nfp)
			{
				dp->nextnode = nfp->disc->nextf;
				dp->table = np;
				dp->otable = sh.last_table;
				dp->fun = nfp;
				dp->hp = (*dp->nextnode)(np,(Dt_t*)0,nfp);
			}
			else
				dp->nextnode = 0;
		}
		else
			break;
		if(!next || next[1]==0)
			break;
		last = next+1;
		nq = np;
		np = 0;
	}
Esempio n. 15
0
File: completion.c Progetto: att/ast
//
// File name generation for edit modes.
// Non-zero exit for error, <0 ring bell.
// Don't search back past beginning of the buffer.
// Mode is '*' for inline expansion.
// Mode is '\' for filename completion.
// Mode is '=' cause files to be listed in select format.
//
int ed_expand(Edit_t *ep, char outbuff[], int *cur, int *eol, int mode, int count) {
    struct comnod *comptr;
    struct argnod *ap;
    char *out;
    char *av[2], *begin;
    char *dir = NULL;
    int addstar = 0, rval = 0, var = 0, strip = 1, narg = 0;
    int nomarkdirs = !sh_isoption(ep->sh, SH_MARKDIRS);
    Shell_t *shp = ep->sh;
    char **com = NULL;

    sh_onstate(shp, SH_FCOMPLETE);
    if (ep->e_nlist) {
        if (mode == '=' && count > 0) {
            if (count > ep->e_nlist) return -1;
            mode = '?';
            av[0] = ep->e_clist[count - 1];
            av[1] = 0;
        } else {
            stkset(shp->stk, ep->e_stkptr, ep->e_stkoff);
            ep->e_nlist = 0;
        }
    }
    comptr = stkalloc(shp->stk, sizeof(struct comnod));
    ap = (struct argnod *)stkseek(shp->stk, ARGVAL);

    {
        // Adjust cur.
        int c;
        genchar *cp;
        cp = (genchar *)outbuff + *cur;
        c = *cp;
        *cp = 0;
        *cur = ed_external((genchar *)outbuff, (char *)stkptr(shp->stk, 0));
        *cp = c;
        *eol = ed_external((genchar *)outbuff, outbuff);
    }

    out = outbuff + *cur + (sh_isoption(shp, SH_VI) != 0);
#if 0
        if(out[-1]=='"' || out[-1]=='\'')
        {
                rval = -(sh_isoption(shp,SH_VI)!=0);
                goto done;
        }
#endif
    comptr->comtyp = COMSCAN;
    comptr->comarg = ap;
    ap->argflag = (ARG_MAC | ARG_EXP);
    ap->argnxt.ap = NULL;
    ap->argchn.cp = NULL;

    {
        char *last = out;
        Namval_t *np = nv_search("COMP_KEY", shp->var_tree, 0);
        if (np) STORE_VT(np->nvalue, i16, '\t');
        np = nv_search("COMP_TYPE", shp->var_tree, 0);
        if (np) STORE_VT(np->nvalue, i16, mode == '\\' ? '\t' : '?');
        var = mode;
        begin = out = find_begin(outbuff, last, 0, &var);
        if (ep->compdict && mode != '?' &&
            (com = prog_complete(ep->compdict, outbuff, out, *cur))) {
            char **av;
            for (av = com; *av; av++) {
                ;  // empty loop
            }
            narg = av - com;
        }
        // Addstar set to zero if * should not be added.
        if (var == '$') {
            sfwrite(shp->stk, "${!", 3);
            sfwrite(shp->stk, out, last - out);
            sfwrite(shp->stk, "$@}", 2);
            out = last;
        } else {
            addstar = '*';
            while (out < last) {
                char c = *out;
                if (c == 0) break;
                if (isexp(c)) addstar = 0;
                if (c == '/') {
                    if (addstar == 0) strip = 0;
                    dir = out + 1;
                }
                sfputc(shp->stk, c);
                out++;
            }
        }
        if (mode == '?') mode = '*';
        if (var != '$' && mode == '\\' && out[-1] != '*') addstar = '*';
        if (*begin == '~' && !strchr(begin, '/')) addstar = 0;
        sfputc(shp->stk, addstar);
        ap = (struct argnod *)stkfreeze(shp->stk, 1);
    }

    if (mode != '*') sh_onoption(shp, SH_MARKDIRS);

    {
        char *cp = begin, *left = NULL;
        int cmd_completion = 0;
        int size = 'x';
        while (cp > outbuff && ((size = cp[-1]) == ' ' || size == '\t')) cp--;
        if (!var && !strchr(ap->argval, '/') &&
            ((cp == outbuff && shp->nextprompt == 1) ||
             (strchr(";&|(", size) && (cp == outbuff + 1 || size == '(' || cp[-2] != '>') &&
              *begin != '~'))) {
            cmd_completion = 1;
            sh_onstate(shp, SH_COMPLETE);
        }
        if (ep->e_nlist) {
            narg = 1;
            com = av;
            if (dir) begin += (dir - begin);
        } else {
            if (!com) com = sh_argbuild(shp, &narg, comptr, 0);
            // Special handling for leading quotes.
            if (begin > outbuff && (begin[-1] == '"' || begin[-1] == '\'')) begin--;
        }
        sh_offstate(shp, SH_COMPLETE);
        // Allow a search to be aborted.
        if (shp->trapnote & SH_SIGSET) {
            rval = -1;
            goto done;
        }
        // Match?
        if (*com == 0 || ((narg <= 1 && (strcmp(ap->argval, *com) == 0)) ||
                          (addstar && com[0][strlen(*com) - 1] == '*'))) {
            rval = -1;
            goto done;
        }
        if (mode == '\\' && out[-1] == '/' && narg > 1) mode = '=';
        if (mode == '=') {
            if (strip && !cmd_completion) {
                char **ptrcom;
                for (ptrcom = com; *ptrcom; ptrcom++) {  // trim directory prefix
                    *ptrcom = path_basename(*ptrcom);
                }
            }
            sfputc(sfstderr, '\n');
            sh_menu(shp, sfstderr, narg, com);
            sfsync(sfstderr);
            ep->e_nlist = narg;
            ep->e_clist = com;
            goto done;
        }
        // See if there is enough room.
        size = *eol - (out - begin);
        if (mode == '\\') {
            int c;
            if (dir) {
                c = *dir;
                *dir = 0;
            }
            if (dir) *dir = c;
            // Just expand until name is unique.
            size += strlen(*com);
        } else {
            char **tmpcom = com;
            size += narg;
            while (*tmpcom) {
                cp = fmtx(shp, *tmpcom++);
                size += strlen(cp);
            }
        }
        // See if room for expansion.
        if (outbuff + size >= &outbuff[MAXLINE]) {
            com[0] = ap->argval;
            com[1] = 0;
        }
        // Save remainder of the buffer.
        if (*out) left = stkcopy(shp->stk, out);
        if (cmd_completion && mode == '\\') {
            cp = *com++;
            out = stpcpy(begin, path_basename(cp));
        } else if (mode == '*') {
            if (ep->e_nlist && dir && var) {
                if (*cp == var) {
                    cp++;
                } else {
                    *begin++ = var;
                }
                out = stpcpy(begin, cp);
                var = 0;
            } else {
                out = stpcpy(begin, fmtx(shp, *com));
            }
            com++;
        } else {
            out = stpcpy(begin, *com++);
        }
        if (mode == '\\') {
            char *saveout = ++out;
            while (*com && *begin) {
                if (cmd_completion) {
                    out = overlaid(begin, path_basename(*com++), false);
                } else {
                    out = overlaid(begin, *com++, false);
                }
            }
            mode = (out == saveout);
            if (out[-1] == 0) out--;
            if (mode && out[-1] != '/') {
                if (cmd_completion) {
                    Namval_t *np;
                    // Add as tracked alias.
                    Pathcomp_t *pp;
                    if (*cp == '/' && (pp = path_dirfind(shp->pathlist, cp, '/')) &&
                        (np = nv_search(begin, shp->track_tree, NV_ADD))) {
                        path_alias(np, pp);
                    }
                    out = stpcpy(begin, cp);
                }
                // Add quotes if necessary.
                if ((cp = fmtx(shp, begin)) != begin) out = stpcpy(begin, cp);
                if (var == '$' && begin[-1] == '{') {
                    *out = '}';
                } else {
                    *out = ' ';
                }
                *++out = 0;
            } else if ((cp = fmtx(shp, begin)) != begin) {
                out = stpcpy(begin, cp);
                if (out[-1] == '"' || out[-1] == '\'') *--out = 0;
            }
            if (*begin == 0 && begin[-1] != ' ') ed_ringbell();
        } else {
            while (*com) {
                *out++ = ' ';
                out = stpcpy(out, fmtx(shp, *com++));
            }
        }
        if (ep->e_nlist) {
            cp = com[-1];
            if (cp[strlen(cp) - 1] != '/') {
                if (var == '$' && begin[-1] == '{') {
                    *out = '}';
                } else {
                    *out = ' ';
                }
                out++;
            } else if (out[-1] == '"' || out[-1] == '\'') {
                out--;
            }
            *out = 0;
        }
        *cur = (out - outbuff);
        // Restore rest of buffer.
        if (left) out = stpcpy(out, left);
        *eol = (out - outbuff);
    }

done:
    sh_offstate(shp, SH_FCOMPLETE);
    if (!ep->e_nlist) stkset(shp->stk, ep->e_stkptr, ep->e_stkoff);
    if (nomarkdirs) sh_offoption(shp, SH_MARKDIRS);

    {
        // First re-adjust cur.
        int c, n = 0;
        c = outbuff[*cur];
        outbuff[*cur] = 0;
        for (out = outbuff; *out; n++) mb1char(&out);
        outbuff[*cur] = c;
        *cur = n;
        outbuff[*eol + 1] = 0;
        *eol = ed_internal(outbuff, (genchar *)outbuff);
    }

    return rval;
}
Esempio n. 16
0
File: misc.c Progetto: att/ast
int b_dot_cmd(int n, char *argv[], Shbltin_t *context) {
    char *script;
    Namval_t *np;
    int jmpval;
    Shell_t *shp = context->shp;
    struct sh_scoped savst, *prevscope = shp->st.self;
    int fd;
    char *filename = NULL;
    char *buffer = NULL;
    struct dolnod *saveargfor = NULL;
    volatile struct dolnod *argsave = NULL;
    checkpt_t buff;
    Sfio_t *iop = NULL;
    short level;
    Optdisc_t disc;

    memset(&disc, 0, sizeof(disc));
    disc.version = OPT_VERSION;
    opt_info.disc = &disc;

    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;
            }
            default: { break; }
        }
    }

    argv += opt_info.index;
    script = *argv;
    if (error_info.errors || !script) {
        errormsg(SH_DICT, ERROR_usage(2), "%s", optusage(NULL));
        __builtin_unreachable();
    }
    if (shp->dot_depth + 1 > DOTMAX) {
        errormsg(SH_DICT, ERROR_exit(1), e_toodeep, script);
        __builtin_unreachable();
    }
    np = shp->posix_fun;
    if (!np) {
        // 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 (!FETCH_VT(np->nvalue, ip)) {
                // TODO: Replace this with a comment explaining why the return value of this
                // path_search() call is ignored. At the time I wrote this (2019-03-16) no unit test
                // exercises this statement. I added the void cast to silence Coverity Scan 253792.
                (void)path_search(shp, script, NULL, 0);
                if (FETCH_VT(np->nvalue, ip)) {
                    if (nv_isattr(np, NV_FPOSIX)) np = NULL;
                } else {
                    errormsg(SH_DICT, ERROR_exit(1), e_found, script);
                    __builtin_unreachable();
                }
            }
        } else {
            np = NULL;
        }

        if (!np) {
            fd = path_open(shp, script, path_get(shp, script));
            if (fd < 0) {
                errormsg(SH_DICT, ERROR_system(1), e_open, script);
                __builtin_unreachable();
            }
            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) {
        struct Ufunction *rp = FETCH_VT(np->nvalue, rp);
        shp->st.filename = strdup(rp->fname ? rp->fname : "");
    }
    nv_putval(SH_PATHNAMENOD, shp->st.filename, NV_NOFREE);
    shp->posix_fun = NULL;
    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(shp, (Shnode_t *)(nv_funtree(np)), sh_isstate(shp, SH_ERREXIT));
        } else {
            buffer = malloc(IOBSIZE + 1);
            iop = sfnew(NULL, buffer, IOBSIZE, fd, SF_READ);
            sh_offstate(shp, SH_NOFORK);
            sh_eval(shp, iop, sh_isstate(shp, SH_PROFILE) ? SH_FUNEVAL : 0);
        }
    }
    sh_popcontext(shp, &buff);
    if (buffer) free(buffer);
    if (!np) {
        free(shp->st.filename);
        shp->st.filename = NULL;
    }
    shp->dot_depth--;
    if ((np || argv[1]) && jmpval != SH_JMPSCRIPT) {
        sh_argreset(shp, (struct dolnod *)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(&shp->st, 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->buff, jmpval);
    return shp->exitval;
}