mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
These are minor fixes I've accumulated over time. The following
changes are somewhat notable:
- Added a missing entry for 'typeset -s' to the man page.
- Add strftime(3) to the 'see also' section. This and the date(1)
addition are meant to add onto the documentation for 'printf %T'.
- Removed the man page the entry for ksh reading $PWD/.profile on
login. That feature was removed in commit aa7713c2.
- Added date(1) to the 'see also' section of the man page.
- Note that the 'hash' command can be used instead of 'alias -t' to
workaround one of the caveats listed in the man page.
- Use an 'out of memory' error message rather than 'out of space'
when memory allocation fails.
- Replaced backticks with quotes in some places for consistency.
- Added missing documentation for the %P date format.
- Added missing documentation for the printf %Q and %p formats
(backported from ksh2020: https://github.com/att/ast/pull/1032).
- The comments that show each builtin's options have been updated.
217 lines
4.9 KiB
C
217 lines
4.9 KiB
C
/***********************************************************************
|
|
* *
|
|
* This software is part of the ast package *
|
|
* Copyright (c) 1985-2011 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 *
|
|
* *
|
|
* Glenn Fowler <gsf@research.att.com> *
|
|
* David Korn <dgk@research.att.com> *
|
|
* Phong Vo <kpv@research.att.com> *
|
|
* *
|
|
***********************************************************************/
|
|
#pragma prototyped
|
|
/*
|
|
* POSIX 1003.2 wordexp implementation
|
|
*/
|
|
|
|
#include <ast.h>
|
|
#include <wordexp.h>
|
|
#include <stak.h>
|
|
|
|
struct list
|
|
{
|
|
struct list *next;
|
|
};
|
|
|
|
/*
|
|
* eliminates shell quoting as inserted with sh_fmtq
|
|
* result replaces <string>
|
|
* length of resulting string is returned.
|
|
*/
|
|
static int sh_unquote(char* string)
|
|
{
|
|
register char *sp=string, *dp;
|
|
register int c;
|
|
while((c= *sp) && c!='\'')
|
|
sp++;
|
|
if(c==0)
|
|
return(sp-string);
|
|
if((dp=sp) > string && sp[-1]=='$')
|
|
{
|
|
register int n=stresc(sp+1);
|
|
/* copy all but trailing ' */
|
|
while(--n>0)
|
|
*dp++ = *++sp;
|
|
}
|
|
else
|
|
{
|
|
while((c= *++sp) && c!='\'')
|
|
*dp++ = c;
|
|
}
|
|
*dp=0;
|
|
return(dp-string);
|
|
}
|
|
|
|
int wordexp(const char *string, wordexp_t *wdarg, register int flags)
|
|
{
|
|
register Sfio_t *iop;
|
|
register char *cp=(char*)string;
|
|
register int c,quoted=0,literal=0,ac=0;
|
|
int offset;
|
|
char *savebase,**av;
|
|
if(offset=staktell())
|
|
savebase = stakfreeze(0);
|
|
if(flags&WRDE_REUSE)
|
|
wordfree(wdarg);
|
|
else if(!(flags&WRDE_APPEND))
|
|
{
|
|
wdarg->we_wordv = 0;
|
|
wdarg->we_wordc = 0;
|
|
}
|
|
if(flags&WRDE_UNDEF)
|
|
stakwrite("set -u\n",7);
|
|
if(!(flags&WRDE_SHOWERR))
|
|
stakwrite("exec 2> /dev/null\n",18);
|
|
stakwrite("print -f \"%q\\n\" ",16);
|
|
if(*cp=='#')
|
|
stakputc('\\');
|
|
while(c = *cp++)
|
|
{
|
|
if(c=='\'' && !quoted)
|
|
literal = !literal;
|
|
else if(!literal)
|
|
{
|
|
if(c=='\\' && (!quoted || strchr("\\\"`\n$",c)))
|
|
{
|
|
stakputc('\\');
|
|
if(c= *cp)
|
|
cp++;
|
|
else
|
|
c = '\\';
|
|
}
|
|
else if(c=='"')
|
|
quoted = !quoted;
|
|
else if(c=='`' || (c=='$' && *cp=='('))
|
|
{
|
|
if(flags&WRDE_NOCMD)
|
|
{
|
|
c=WRDE_CMDSUB;
|
|
goto err;
|
|
}
|
|
/* only the shell can parse the rest */
|
|
stakputs(cp-1);
|
|
break;
|
|
}
|
|
else if(!quoted && strchr("|&\n;<>"+ac,c))
|
|
{
|
|
c=WRDE_BADCHAR;
|
|
goto err;
|
|
}
|
|
else if(c=='(') /* allow | and & inside pattern */
|
|
ac=2;
|
|
}
|
|
stakputc(c);
|
|
}
|
|
stakputc(0);
|
|
if(!(iop = sfpopen((Sfio_t*)0,stakptr(0),"r")))
|
|
{
|
|
c = WRDE_NOSHELL;
|
|
goto err;
|
|
}
|
|
stakseek(0);
|
|
ac = 0;
|
|
while((c=sfgetc(iop)) != EOF)
|
|
{
|
|
if(c=='\'')
|
|
quoted = ! quoted;
|
|
else if(!quoted && (c==' ' || c=='\n'))
|
|
{
|
|
ac++;
|
|
c = 0;
|
|
}
|
|
stakputc(c);
|
|
}
|
|
if(c=sfclose(iop))
|
|
{
|
|
if(c==3 || !(flags&WRDE_UNDEF))
|
|
c=WRDE_SYNTAX;
|
|
else
|
|
c=WRDE_BADVAL;
|
|
goto err;
|
|
}
|
|
c = ac+2;
|
|
if(flags&WRDE_DOOFFS)
|
|
c += wdarg->we_offs;
|
|
if(flags&WRDE_APPEND)
|
|
av = (char**)realloc((void*)&wdarg->we_wordv[-1], (wdarg->we_wordc+c)*sizeof(char*));
|
|
else if(av = (char**)malloc(c*sizeof(char*)))
|
|
{
|
|
if(flags&WRDE_DOOFFS)
|
|
memset((void*)av,0,(wdarg->we_offs+1)*sizeof(char*));
|
|
else
|
|
av[0] = 0;
|
|
}
|
|
if(!av)
|
|
return(WRDE_NOSPACE);
|
|
c = staktell();
|
|
if(!(cp = (char*)malloc(sizeof(char*)+c)))
|
|
{
|
|
c=WRDE_NOSPACE;
|
|
goto err;
|
|
}
|
|
((struct list*)cp)->next = (struct list*)(*av);
|
|
*av++ = (char*)cp;
|
|
cp += sizeof(char*);
|
|
wdarg->we_wordv = av;
|
|
if(flags&WRDE_APPEND)
|
|
av += wdarg->we_wordc;
|
|
wdarg->we_wordc += ac;
|
|
if(flags&WRDE_DOOFFS)
|
|
av += wdarg->we_offs;
|
|
memcpy((void*)cp,stakptr(offset),c);
|
|
while(ac-- > 0)
|
|
{
|
|
*av++ = cp;
|
|
sh_unquote(cp);
|
|
while(c= *cp++);
|
|
}
|
|
*av = 0;
|
|
c=0;
|
|
err:
|
|
if(offset)
|
|
stakset(savebase,offset);
|
|
else
|
|
stakseek(0);
|
|
return(c);
|
|
}
|
|
|
|
/*
|
|
* free fields in <wdarg>
|
|
*/
|
|
int wordfree(register wordexp_t *wdarg)
|
|
{
|
|
struct list *arg, *argnext;
|
|
if(wdarg->we_wordv)
|
|
{
|
|
argnext = (struct list*)wdarg->we_wordv[-1];
|
|
while(arg=argnext)
|
|
{
|
|
argnext = arg->next;
|
|
free((void*)arg);
|
|
}
|
|
free((void*)&wdarg->we_wordv[-1]);
|
|
wdarg->we_wordv = 0;
|
|
}
|
|
wdarg->we_wordc=0;
|
|
return(0);
|
|
}
|