800 lines
15 KiB
C
Executable File
800 lines
15 KiB
C
Executable File
#ident "@(#)args.c 1.14 95/04/10 SMI" /* From AT&T Toolchest */
|
||
|
||
/*
|
||
* UNIX shell
|
||
*
|
||
* S. R. Bourne
|
||
* Rewritten by David Korn
|
||
* AT&T Bell Laboratories
|
||
*
|
||
*/
|
||
|
||
#include "defs.h"
|
||
#ifdef DEVFD
|
||
# include "jobs.h"
|
||
#endif /* DEVFD */
|
||
#include "terminal.h"
|
||
#undef ESCAPE
|
||
#include "sym.h"
|
||
#include "builtins.h"
|
||
|
||
|
||
#ifdef DEVFD
|
||
void close_pipes();
|
||
#endif /* DEVFD */
|
||
|
||
extern void gsort();
|
||
extern int strcmp();
|
||
|
||
static int arg_expand();
|
||
static struct dolnod* copyargs();
|
||
static void print_opts();
|
||
static int split();
|
||
|
||
static char *null;
|
||
static struct dolnod *argfor; /* linked list of blocks to be cleaned up */
|
||
static struct dolnod *dolh;
|
||
static char flagadr[12];
|
||
static const char flagchar[] =
|
||
{
|
||
'i', 'n', 'v', 't', 's', 'x', 'e', 'r', 'k',
|
||
'u', 'f', 'a', 'm', 'h', 'p', 'c', 'b', 'C', 0
|
||
};
|
||
static const optflag flagval[] =
|
||
{
|
||
INTFLG, NOEXEC, READPR, ONEFLG, STDFLG, EXECPR, ERRFLG, RSHFLG, KEYFLG,
|
||
NOSET, NOGLOB, ALLEXP, MONITOR, HASHALL, PRIVM, CFLAG,
|
||
NOTIFY, NOCLOB, 0
|
||
};
|
||
|
||
/* ======== option handling ======== */
|
||
|
||
/*
|
||
* This routine turns options on and off
|
||
* The options "icr" are illegal from set command.
|
||
* The -o option is used to set option by name
|
||
* This routine returns the number of non-option arguments
|
||
*/
|
||
|
||
int arg_opts(argc,com,setflag)
|
||
char **com;
|
||
int argc;
|
||
int setflag;
|
||
{
|
||
register char *cp;
|
||
register int c;
|
||
register char *flagc;
|
||
register char **argv = com;
|
||
register optflag newflags=opt_flags;
|
||
register optflag opt;
|
||
int trace = is_option(EXECPR);
|
||
char minus;
|
||
struct namnod *np = (struct namnod*)0;
|
||
char sort = 0;
|
||
char minmin = 0;
|
||
while((cp= *++argv) && ((c= *cp) == '-' || c=='+'))
|
||
{
|
||
minus = (c == '-');
|
||
argc--;
|
||
if((c= *++cp)==0)
|
||
{
|
||
newflags &= ~(EXECPR|READPR);
|
||
trace = 0;
|
||
argv++;
|
||
break;
|
||
}
|
||
else if(c == '-')
|
||
{
|
||
minmin = 1;
|
||
argv++;
|
||
break;
|
||
}
|
||
while(c= *cp++)
|
||
{
|
||
if(setflag)
|
||
{
|
||
if(c=='s')
|
||
{
|
||
sort = 1;
|
||
continue;
|
||
}
|
||
else if(c=='A')
|
||
{
|
||
if(argv[1]==0)
|
||
sh_fail(*argv, e_argexp);
|
||
np = env_namset(*++argv,sh.var_tree,P_FLAG|V_FLAG);
|
||
argc--;
|
||
if(minus)
|
||
nam_free(np);
|
||
continue;
|
||
}
|
||
else if(strchr("icr",c))
|
||
sh_fail(*argv, e_option);
|
||
}
|
||
if(c=='c' && minus && argc>=2 && sh.comdiv==0)
|
||
{
|
||
sh.comdiv= *++argv;
|
||
argc--;
|
||
newflags |= CFLAG;
|
||
continue;
|
||
}
|
||
#ifdef apollo
|
||
/*
|
||
* New option(-D) allowing the user to define
|
||
* envirnoment variables on the command line.
|
||
*/
|
||
if (c == 'D') /* define env variable */
|
||
{
|
||
char *newenv;
|
||
|
||
if (minus)
|
||
{
|
||
if (cp && *cp)
|
||
{
|
||
if (strchr(cp, '='))
|
||
newenv = cp;
|
||
else
|
||
{
|
||
newenv = malloc(strlen(cp) + 2);
|
||
strcpy(newenv, cp);
|
||
strcat(newenv, "=");
|
||
}
|
||
env_namset(newenv,sh.var_tree,N_EXPORT|N_FREE);
|
||
}
|
||
} else
|
||
sh_fail(*argv, e_option);
|
||
argc--;
|
||
break;
|
||
}
|
||
#endif /* apollo */
|
||
if(flagc=strchr(flagchar,c))
|
||
opt = flagval[flagc-flagchar];
|
||
#ifdef WEXP
|
||
else if (c == '') { /* CTRL-E ? */
|
||
register int c;
|
||
char invchar[]=";|&<>(){}\n";
|
||
/* Start command substitution flag */
|
||
int lastc = 0;
|
||
int closeq = 0;
|
||
char *p=argv[1];
|
||
|
||
/* Prevent manual -CTRL-E */
|
||
if (is_option(INTFLG) || setflag)
|
||
sh_fail(com[0], e_option);
|
||
|
||
/* NULL argument */
|
||
if (p == (char *)NULL || *p == '\0')
|
||
cmd_shfail(com[0],e_wrde_badchar,WEXP_BADCHAR);
|
||
|
||
while (c=*p++) {
|
||
/*
|
||
* Scan for special token to skip the
|
||
* content in between " ", ` ` or $( )
|
||
*/
|
||
switch (c) {
|
||
case ESCAPE:
|
||
c = *p++;
|
||
continue;
|
||
case LITERAL:
|
||
case DQUOTE:
|
||
case SQUOTE:
|
||
closeq = c;
|
||
break;
|
||
case LPAREN:
|
||
if (lastc == DOLLAR)
|
||
closeq = RPAREN;
|
||
break;
|
||
case LBRACE:
|
||
if (lastc == DOLLAR)
|
||
closeq = RBRACE;
|
||
break;
|
||
}
|
||
|
||
/*
|
||
* If the start of command substitution
|
||
* is found, then skip until the end of
|
||
* it.
|
||
*/
|
||
if (closeq)
|
||
while (c=*p++)
|
||
if (c == closeq) {
|
||
closeq = 0;
|
||
c = *p++;
|
||
break;
|
||
}
|
||
|
||
/* The end of cmd subs. is also the end ? */
|
||
if (!c) {
|
||
if (closeq)
|
||
cmd_shfail(com[0],e_wrde_badchar,WEXP_BADCHAR);
|
||
break;
|
||
}
|
||
|
||
/*
|
||
* Check for unquoted illegal chars
|
||
* outside of command substitution context
|
||
*/
|
||
if (strchr(invchar, c))
|
||
cmd_shfail(com[0],e_wrde_badchar,WEXP_BADCHAR);
|
||
|
||
lastc = c;
|
||
}
|
||
|
||
newflags = WEXP_E;
|
||
|
||
while (cp && *cp) {
|
||
if (*cp == 'N')
|
||
/* No cmd substitution */
|
||
newflags |= WEXP_N;
|
||
else if (*cp == 'u') {
|
||
register int d = *cp;
|
||
|
||
flagc=strchr(flagchar,d);
|
||
newflags |= flagval[flagc-flagchar];
|
||
}
|
||
cp++;
|
||
}
|
||
|
||
/* Pad echo in front of the word */
|
||
sh.comdiv = malloc(strlen(*++argv)+12);
|
||
strcpy(sh.comdiv, "print -r -- ");
|
||
strcat(sh.comdiv, *argv);
|
||
argc--;
|
||
break; /* No other options */
|
||
}
|
||
#endif /* WEXP */
|
||
else if(c != 'o' || *cp)
|
||
sh_fail(*argv,e_option);
|
||
else
|
||
{
|
||
if(*++argv==NIL)
|
||
{
|
||
if(trace)
|
||
sh_trace(com,1);
|
||
trace = 0;
|
||
print_opts(newflags);
|
||
argv--;
|
||
continue;
|
||
}
|
||
else
|
||
{
|
||
argc--;
|
||
c=sh_lookup(*argv,tab_options);
|
||
opt = 1L<<c;
|
||
if(opt&(1|INTFLG|RSHFLG))
|
||
sh_fail(*argv,e_option);
|
||
}
|
||
}
|
||
if(minus)
|
||
{
|
||
#if ESH || VSH
|
||
if(opt&(EDITVI|EMACS|GMACS))
|
||
newflags &= ~ (EDITVI|EMACS|GMACS);
|
||
#endif
|
||
newflags |= opt;
|
||
}
|
||
else
|
||
{
|
||
if(opt==EXECPR)
|
||
trace = 0;
|
||
newflags &= ~opt;
|
||
}
|
||
}
|
||
}
|
||
/* cannot set -n for interactive shells since there is no way out */
|
||
if(is_option(INTFLG))
|
||
newflags &= ~NOEXEC;
|
||
#ifdef RAWONLY
|
||
if(is_option(EDITVI))
|
||
newflags |= VIRAW;
|
||
#endif /* RAWONLY */
|
||
if(!setflag)
|
||
goto skip;
|
||
if(sort)
|
||
{
|
||
if(argc>1)
|
||
gsort(argv,argc-1,strcmp);
|
||
else
|
||
gsort(st.dolv+1,st.dolc,strcmp);
|
||
}
|
||
if((newflags&PRIVM) && !is_option(PRIVM))
|
||
{
|
||
if((sh.userid!=sh.euserid && setuid(sh.euserid)<0) ||
|
||
(sh.groupid!=sh.egroupid && setgid(sh.egroupid)<0) ||
|
||
(sh.userid==sh.euserid && sh.groupid==sh.egroupid))
|
||
newflags &= ~PRIVM;
|
||
}
|
||
else if(!(newflags&PRIVM) && is_option(PRIVM))
|
||
{
|
||
setuid(sh.userid);
|
||
setgid(sh.groupid);
|
||
if(sh.euserid==0)
|
||
{
|
||
sh.euserid = sh.userid;
|
||
sh.egroupid = sh.groupid;
|
||
}
|
||
}
|
||
skip:
|
||
if(trace)
|
||
sh_trace(com,1);
|
||
opt_flags = newflags;
|
||
if(setflag)
|
||
{
|
||
argv--;
|
||
if(np)
|
||
env_arrayset(np,argc,argv);
|
||
else if(argc>1 || minmin)
|
||
arg_set(argv);
|
||
}
|
||
return(argc);
|
||
}
|
||
|
||
/*
|
||
* returns the value of $-
|
||
*/
|
||
|
||
char *arg_dolminus()
|
||
{
|
||
register const char *flagc=flagchar;
|
||
register char *flagp=flagadr;
|
||
while(*flagc)
|
||
{
|
||
if(opt_flags&flagval[flagc-flagchar])
|
||
*flagp++ = *flagc;
|
||
flagc++;
|
||
}
|
||
*flagp = 0;
|
||
return(flagadr);
|
||
}
|
||
|
||
/*
|
||
* set up positional parameters
|
||
*/
|
||
|
||
void arg_set(argi)
|
||
char *argi[];
|
||
{
|
||
register char **argp=argi;
|
||
register int size = 0; /* count number of bytes needed for strings */
|
||
register char *cp;
|
||
register int argn;
|
||
/* count args and number of bytes of arglist */
|
||
while((cp=(char*)*argp++) != ENDARGS)
|
||
{
|
||
size += strlen(cp);
|
||
}
|
||
/* free old ones unless on for loop chain */
|
||
argn = argp - argi;
|
||
arg_free(dolh,0);
|
||
dolh=copyargs(argi, --argn, size);
|
||
st.dolc=argn-1;
|
||
}
|
||
|
||
/*
|
||
* free the argument list if the use count is 1
|
||
* If count is greater than 1 decrement count and return same blk
|
||
* Free the argument list if the use count is 1 and return next blk
|
||
* Delete the blk from the argfor chain
|
||
* If flag is set, then the block dolh is not freed
|
||
*/
|
||
|
||
struct dolnod *arg_free(blk,flag)
|
||
struct dolnod * blk;
|
||
{
|
||
register struct dolnod* argr=blk;
|
||
register struct dolnod* argblk;
|
||
if(argblk=argr)
|
||
{
|
||
if((--argblk->doluse)==0)
|
||
{
|
||
argr = argblk->dolnxt;
|
||
if(flag && argblk==dolh)
|
||
dolh->doluse = 1;
|
||
else
|
||
{
|
||
/* delete from chain */
|
||
if(argfor == argblk)
|
||
argfor = argblk->dolnxt;
|
||
else
|
||
{
|
||
for(argr=argfor;argr;argr=argr->dolnxt)
|
||
if(argr->dolnxt==argblk)
|
||
break;
|
||
if(argr==0)
|
||
{
|
||
return(NULL);
|
||
}
|
||
argr->dolnxt = argblk->dolnxt;
|
||
argr = argblk->dolnxt;
|
||
}
|
||
free((char*)argblk);
|
||
}
|
||
}
|
||
}
|
||
return(argr);
|
||
}
|
||
|
||
/*
|
||
* grab space for arglist and link argblock for cleanup
|
||
* The strings are copied after the argment vector
|
||
*/
|
||
|
||
static struct dolnod *copyargs(from, n, size)
|
||
char *from[];
|
||
{
|
||
register struct dolnod *dp=new_of(struct dolnod,n*sizeof(char*)+size+n);
|
||
register char **pp;
|
||
register char *sp;
|
||
dp->doluse=1; /* use count */
|
||
/* link into chain */
|
||
dp->dolnxt = argfor;
|
||
argfor = dp;
|
||
pp= dp->dolarg;
|
||
st.dolv=pp;
|
||
sp = (char*)dp + sizeof(struct dolnod) + n*sizeof(char*);
|
||
while(n--)
|
||
{
|
||
*pp++ = sp;
|
||
sp = sh_copy(*from++,sp) + 1;
|
||
}
|
||
*pp = ENDARGS;
|
||
return(dp);
|
||
}
|
||
|
||
/*
|
||
* used to set new argument chain for functions
|
||
*/
|
||
|
||
struct dolnod *arg_new(argi,savargfor)
|
||
char *argi[];
|
||
struct dolnod **savargfor;
|
||
{
|
||
register struct dolnod *olddolh = dolh;
|
||
*savargfor = argfor;
|
||
dolh = NULL;
|
||
argfor = NULL;
|
||
arg_set(argi);
|
||
return(olddolh);
|
||
}
|
||
|
||
/*
|
||
* reset arguments as they were before function
|
||
*/
|
||
|
||
void arg_reset(blk,afor)
|
||
struct dolnod *blk;
|
||
struct dolnod *afor;
|
||
{
|
||
while(argfor=arg_free(argfor,0));
|
||
dolh = blk;
|
||
argfor = afor;
|
||
}
|
||
|
||
void arg_clear()
|
||
{
|
||
/* force `for' $* lists to go away */
|
||
while(argfor=arg_free(argfor,1));
|
||
argfor = dolh;
|
||
#ifdef DEVFD
|
||
close_pipes();
|
||
#endif /* DEVFD */
|
||
}
|
||
|
||
/*
|
||
* increase the use count so that an arg_set will not make it go away
|
||
*/
|
||
|
||
struct dolnod *arg_use()
|
||
{
|
||
register struct dolnod *dh;
|
||
if(dh=dolh)
|
||
dh->doluse++;
|
||
return(dh);
|
||
}
|
||
|
||
/*
|
||
* Print option settings on standard output
|
||
*/
|
||
|
||
static void print_opts(oflags)
|
||
#ifndef pdp11
|
||
register
|
||
#endif /* pdp11 */
|
||
optflag oflags;
|
||
{
|
||
register const struct sysnod *syscan = tab_options;
|
||
#ifndef pdp11
|
||
register
|
||
#endif /* pdp11 */
|
||
optflag value;
|
||
p_setout(st.standout);
|
||
p_str(e_heading,NL);
|
||
while(value=syscan->sysval)
|
||
{
|
||
value = 1<<value;
|
||
p_str(syscan->sysnam,SP);
|
||
p_nchr(SP,16-strlen(syscan->sysnam));
|
||
if(oflags&value)
|
||
p_str(e_on,NL);
|
||
else
|
||
p_str(e_off,NL);
|
||
syscan++;
|
||
}
|
||
}
|
||
|
||
#ifdef DEVFD
|
||
static int to_close[15];
|
||
static int indx;
|
||
|
||
void close_pipes()
|
||
{
|
||
register int *fd = to_close;
|
||
while(*fd)
|
||
{
|
||
close(*fd);
|
||
*fd++ = -1;
|
||
}
|
||
indx = 0;
|
||
}
|
||
#endif /* DEVFD */
|
||
|
||
#ifdef VPIX
|
||
# define EXTRA 2
|
||
#else
|
||
# define EXTRA 1
|
||
#endif /* VPIX */
|
||
|
||
/*
|
||
* build an argument list
|
||
*/
|
||
|
||
char **arg_build(nargs,comptr)
|
||
int *nargs;
|
||
struct comnod *comptr;
|
||
{
|
||
register struct argnod *argp;
|
||
{
|
||
register struct comnod *ac = comptr;
|
||
register struct argnod *schain;
|
||
/* see if the arguments have already been expanded */
|
||
if(ac->comarg==NULL)
|
||
{
|
||
*nargs = 0;
|
||
return(&null);
|
||
}
|
||
else if((ac->comtyp&COMSCAN)==0)
|
||
{
|
||
*nargs = ((struct dolnod*)ac->comarg)->doluse;
|
||
return(((struct dolnod*)ac->comarg)->dolarg+EXTRA);
|
||
}
|
||
schain = st.gchain;
|
||
st.gchain = NULL;
|
||
#ifdef DEVFD
|
||
close_pipes();
|
||
#endif /* DEVFD */
|
||
*nargs = 0;
|
||
if(ac)
|
||
{
|
||
argp = ac->comarg;
|
||
while(argp)
|
||
{
|
||
*nargs += arg_expand(argp);
|
||
argp = argp->argnxt.ap;
|
||
}
|
||
}
|
||
argp = st.gchain;
|
||
st.gchain = schain;
|
||
}
|
||
{
|
||
register char **comargn;
|
||
register int argn;
|
||
register char **comargm;
|
||
argn = *nargs;
|
||
argn += EXTRA; /* allow room to prepend args */
|
||
comargn=(char**)stakalloc((unsigned)(argn+1)*sizeof(char*));
|
||
comargm = comargn += argn;
|
||
*comargn = ENDARGS;
|
||
if(argp==0)
|
||
{
|
||
/* reserve an extra null pointer */
|
||
*--comargn = 0;
|
||
return(comargn);
|
||
}
|
||
while(argp)
|
||
{
|
||
struct argnod *nextarg = argp->argchn;
|
||
argp->argchn = 0;
|
||
*--comargn = argp->argval;
|
||
if((argp->argflag&A_RAW)==0)
|
||
sh_trim(*comargn);
|
||
if((argp=nextarg)==0 || (argp->argflag&A_MAKE))
|
||
{
|
||
if((argn=comargm-comargn)>1)
|
||
gsort(comargn,argn,strcmp);
|
||
comargm = comargn;
|
||
}
|
||
}
|
||
return(comargn);
|
||
}
|
||
}
|
||
|
||
/* Argument expansion */
|
||
|
||
static int arg_expand(argp)
|
||
register struct argnod *argp;
|
||
{
|
||
register int count = 0;
|
||
argp->argflag &= ~A_MAKE;
|
||
#ifdef DEVFD
|
||
if(*argp->argval==0 && (argp->argflag&A_EXP))
|
||
{
|
||
/* argument of the form (cmd) */
|
||
register struct argnod *ap;
|
||
int pv[2];
|
||
int fd;
|
||
ap = (struct argnod*)stakseek(ARGVAL);
|
||
ap->argnxt.ap = 0;
|
||
ap->argflag = A_MAKE;
|
||
count++;
|
||
stakputs(e_devfd);
|
||
io_popen(pv);
|
||
fd = argp->argflag&A_RAW;
|
||
stakputs(sh_itos(pv[fd]));
|
||
ap = (struct argnod*)stakfreeze(1);
|
||
ap->argchn= st.gchain;
|
||
st.gchain = ap;
|
||
sh.inpipe = sh.outpipe = 0;
|
||
if(fd)
|
||
{
|
||
sh.inpipe = pv;
|
||
sh_exec((union anynode*)argp->argchn,(int)(st.states&ERRFLG));
|
||
}
|
||
else
|
||
{
|
||
sh.outpipe = pv;
|
||
sh_exec((union anynode*)argp->argchn,(int)(st.states&ERRFLG));
|
||
}
|
||
#ifdef JOBS
|
||
job.pipeflag++;
|
||
#endif /* JOBS */
|
||
close(pv[1-fd]);
|
||
to_close[indx++] = pv[fd];
|
||
}
|
||
else
|
||
#endif /* DEVFD */
|
||
if((argp->argflag&A_RAW)==0)
|
||
{
|
||
register char *ap = argp->argval;
|
||
if(argp->argflag&A_MAC)
|
||
ap = mac_expand(ap);
|
||
count = split(ap,argp->argflag&(A_SPLIT|A_EXP));
|
||
}
|
||
else
|
||
{
|
||
argp->argchn= st.gchain;
|
||
st.gchain = argp;
|
||
argp->argflag |= A_MAKE;
|
||
count++;
|
||
}
|
||
return(count);
|
||
}
|
||
|
||
static int split(s,macflg) /* blank interpretation routine */
|
||
char *s;
|
||
{
|
||
register int c;
|
||
register int lastc = 0;
|
||
register struct argnod *ap;
|
||
int count=0;
|
||
int expflag = (!is_option(NOGLOB) && (macflg&A_EXP));
|
||
const char *seps;
|
||
if(macflg &= A_SPLIT)
|
||
seps = nam_fstrval(IFSNOD);
|
||
else
|
||
seps = e_nullstr;
|
||
if(seps==NULL)
|
||
seps = e_sptbnl;
|
||
while(1)
|
||
{
|
||
if(sh.trapnote&SIGSET)
|
||
sh_exit(SIGFAIL);
|
||
ap = (struct argnod*)stakseek(ARGVAL);
|
||
while(c= *s++)
|
||
{
|
||
if(c == ESCAPE)
|
||
{
|
||
c = *s++;
|
||
if(c!='/')
|
||
stakputc(ESCAPE);
|
||
}
|
||
else if(strchr(seps,c)) {
|
||
int d = *s;
|
||
if (!(macflg & A_SPLIT))
|
||
break;
|
||
if (!d || /* End of string ? */
|
||
/* 1st char is not white space */
|
||
(strchr(e_sptbnl, c) == (char *)NULL) ||
|
||
/* Start IFS white space sequence ? */
|
||
(strchr(seps, d) == (char *)NULL))
|
||
break;
|
||
|
||
/*
|
||
* IFS white space sequence
|
||
* c must be a leading white space.
|
||
* VSC/sh_05.sh(tp364)
|
||
*/
|
||
while (d=*s++) {
|
||
if (!strchr(seps, d) ||
|
||
!strchr(e_sptbnl, d))
|
||
break;
|
||
c = d;
|
||
}
|
||
/*
|
||
* Leading IFS white spaces sequence
|
||
* or trailing IFS sequence
|
||
*/
|
||
if (staktell()==ARGVAL) {
|
||
s--;
|
||
continue;
|
||
}
|
||
|
||
c = d;
|
||
if (!c)
|
||
break;
|
||
if (!strchr(seps, c))
|
||
s--;
|
||
break;
|
||
}
|
||
stakputc(c);
|
||
}
|
||
/* This allows contiguous visible delimiters to count as delimiters */
|
||
if(staktell()==ARGVAL)
|
||
{
|
||
if(c==0) {
|
||
/*
|
||
* The non white space del before end
|
||
* of string would be a del.
|
||
* VSC/sh_05.sh(tp311)
|
||
*/
|
||
if (macflg & A_SPLIT && !lastc) {
|
||
register char *p = --s;
|
||
p--;
|
||
if (strchr(seps, *p) &&
|
||
!strchr(e_sptbnl, *p))
|
||
lastc = *p;
|
||
|
||
if (lastc)
|
||
s--;
|
||
else
|
||
return(count);
|
||
} else
|
||
return(count);
|
||
}
|
||
if(macflg==0 || strchr(e_sptbnl,c))
|
||
continue;
|
||
}
|
||
else if(c==0)
|
||
{
|
||
s--;
|
||
}
|
||
/* file name generation */
|
||
ap = (struct argnod*)stakfreeze(1);
|
||
ap->argflag &= ~(A_RAW|A_MAKE);
|
||
#ifdef BRACEPAT
|
||
if(expflag)
|
||
count += expbrace(ap);
|
||
#else
|
||
if(expflag && (c=path_expand(ap->argval)))
|
||
count += c;
|
||
#endif /* BRACEPAT */
|
||
else
|
||
{
|
||
count++;
|
||
ap->argchn= st.gchain;
|
||
st.gchain = ap;
|
||
}
|
||
st.gchain->argflag |= A_MAKE;
|
||
}
|
||
}
|
||
|