wordexp.c revision 3f54fd611f536639ec30dd53c48e5ec1897cc7d9
7abd0c58a5ce51db13f93de82407b2188d55d298Christian Maeder/***********************************************************************
7abd0c58a5ce51db13f93de82407b2188d55d298Christian Maeder* *
94ceeb2edbd25b4697ddd9f63c94377924352cf4Christian Maeder* This software is part of the ast package *
97018cf5fa25b494adffd7e9b4e87320dae6bf47Christian Maeder* Copyright (c) 1985-2011 AT&T Intellectual Property *
7abd0c58a5ce51db13f93de82407b2188d55d298Christian Maeder* and is licensed under the *
b4fbc96e05117839ca409f5f20f97b3ac872d1edTill Mossakowski* Eclipse Public License, Version 1.0 *
7abd0c58a5ce51db13f93de82407b2188d55d298Christian Maeder* by AT&T Intellectual Property *
7abd0c58a5ce51db13f93de82407b2188d55d298Christian Maeder* *
08faa81d4dd8409cd923b334064f64f802ecc33dChristian Maeder* A copy of the License is available at *
94ceeb2edbd25b4697ddd9f63c94377924352cf4Christian Maeder* http://www.eclipse.org/org/documents/epl-v10.html *
08faa81d4dd8409cd923b334064f64f802ecc33dChristian Maeder* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
08faa81d4dd8409cd923b334064f64f802ecc33dChristian Maeder* *
e8ffec0fa3d3061061bdc16e44247b9cf96b050fChristian Maeder* Information and Software Systems Research *
08faa81d4dd8409cd923b334064f64f802ecc33dChristian Maeder* AT&T Research *
e8ffec0fa3d3061061bdc16e44247b9cf96b050fChristian Maeder* Florham Park NJ *
bbae6e6ca0de7f2ffbb44d2c8da179f2b717237fChristian Maeder* *
e8ffec0fa3d3061061bdc16e44247b9cf96b050fChristian Maeder* Glenn Fowler <gsf@research.att.com> *
e8ffec0fa3d3061061bdc16e44247b9cf96b050fChristian Maeder* David Korn <dgk@research.att.com> *
e8ffec0fa3d3061061bdc16e44247b9cf96b050fChristian Maeder* Phong Vo <kpv@research.att.com> *
f71a8dcf94fd9eb3c9800e16dcdc5e5ff74e5c22Christian Maeder* *
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder***********************************************************************/
e8ffec0fa3d3061061bdc16e44247b9cf96b050fChristian Maeder#pragma prototyped
7abd0c58a5ce51db13f93de82407b2188d55d298Christian Maeder/*
94ceeb2edbd25b4697ddd9f63c94377924352cf4Christian Maeder * POSIX 1003.2 wordexp implementation
94ceeb2edbd25b4697ddd9f63c94377924352cf4Christian Maeder */
36c6cc568751e4235502cfee00ba7b597dae78dcChristian Maeder
36c6cc568751e4235502cfee00ba7b597dae78dcChristian Maeder#include <ast.h>
36c6cc568751e4235502cfee00ba7b597dae78dcChristian Maeder#include <wordexp.h>
81946e2b3f6dde6167f48769bd02c7a634736856Christian Maeder#include <stak.h>
36c6cc568751e4235502cfee00ba7b597dae78dcChristian Maeder
36c6cc568751e4235502cfee00ba7b597dae78dcChristian Maederstruct list
81946e2b3f6dde6167f48769bd02c7a634736856Christian Maeder{
81946e2b3f6dde6167f48769bd02c7a634736856Christian Maeder struct list *next;
81946e2b3f6dde6167f48769bd02c7a634736856Christian Maeder};
81946e2b3f6dde6167f48769bd02c7a634736856Christian Maeder
81946e2b3f6dde6167f48769bd02c7a634736856Christian Maeder/*
c18e9c3c6d5039618f1f2c05526ece84c7794ea3Christian Maeder * elimnates shell quoting as inserted with sh_fmtq
94ceeb2edbd25b4697ddd9f63c94377924352cf4Christian Maeder * result relaces <string>
94ceeb2edbd25b4697ddd9f63c94377924352cf4Christian Maeder * length of resulting string is returned.
94ceeb2edbd25b4697ddd9f63c94377924352cf4Christian Maeder */
81946e2b3f6dde6167f48769bd02c7a634736856Christian Maederstatic int sh_unquote(char* string)
94ceeb2edbd25b4697ddd9f63c94377924352cf4Christian Maeder{
94ceeb2edbd25b4697ddd9f63c94377924352cf4Christian Maeder register char *sp=string, *dp;
94ceeb2edbd25b4697ddd9f63c94377924352cf4Christian Maeder register int c;
94ceeb2edbd25b4697ddd9f63c94377924352cf4Christian Maeder while((c= *sp) && c!='\'')
94ceeb2edbd25b4697ddd9f63c94377924352cf4Christian Maeder sp++;
35597678f1c9da703de8d0b6b66ea63247ebe884Christian Maeder if(c==0)
94ceeb2edbd25b4697ddd9f63c94377924352cf4Christian Maeder return(sp-string);
94ceeb2edbd25b4697ddd9f63c94377924352cf4Christian Maeder if((dp=sp) > string && sp[-1]=='$')
94ceeb2edbd25b4697ddd9f63c94377924352cf4Christian Maeder {
94ceeb2edbd25b4697ddd9f63c94377924352cf4Christian Maeder register int n=stresc(sp+1);
81946e2b3f6dde6167f48769bd02c7a634736856Christian Maeder /* copy all but trailing ' */
81946e2b3f6dde6167f48769bd02c7a634736856Christian Maeder while(--n>0)
94ceeb2edbd25b4697ddd9f63c94377924352cf4Christian Maeder *dp++ = *++sp;
94ceeb2edbd25b4697ddd9f63c94377924352cf4Christian Maeder }
94ceeb2edbd25b4697ddd9f63c94377924352cf4Christian Maeder else
94ceeb2edbd25b4697ddd9f63c94377924352cf4Christian Maeder {
94ceeb2edbd25b4697ddd9f63c94377924352cf4Christian Maeder while((c= *++sp) && c!='\'')
81946e2b3f6dde6167f48769bd02c7a634736856Christian Maeder *dp++ = c;
81946e2b3f6dde6167f48769bd02c7a634736856Christian Maeder }
81946e2b3f6dde6167f48769bd02c7a634736856Christian Maeder *dp=0;
94ceeb2edbd25b4697ddd9f63c94377924352cf4Christian Maeder return(dp-string);
94ceeb2edbd25b4697ddd9f63c94377924352cf4Christian Maeder}
94ceeb2edbd25b4697ddd9f63c94377924352cf4Christian Maeder
94ceeb2edbd25b4697ddd9f63c94377924352cf4Christian Maederint wordexp(const char *string, wordexp_t *wdarg, register int flags)
94ceeb2edbd25b4697ddd9f63c94377924352cf4Christian Maeder{
7feac39f792f587cffdc8b63b0e7c5a7d2de292eChristian Maeder register Sfio_t *iop;
36c6cc568751e4235502cfee00ba7b597dae78dcChristian Maeder register char *cp=(char*)string;
36c6cc568751e4235502cfee00ba7b597dae78dcChristian Maeder register int c,quoted=0,literal=0,ac=0;
36c6cc568751e4235502cfee00ba7b597dae78dcChristian Maeder int offset;
36c6cc568751e4235502cfee00ba7b597dae78dcChristian Maeder char *savebase,**av;
36c6cc568751e4235502cfee00ba7b597dae78dcChristian Maeder if(offset=staktell())
36c6cc568751e4235502cfee00ba7b597dae78dcChristian Maeder savebase = stakfreeze(0);
36c6cc568751e4235502cfee00ba7b597dae78dcChristian Maeder if(flags&WRDE_REUSE)
36c6cc568751e4235502cfee00ba7b597dae78dcChristian Maeder wordfree(wdarg);
36c6cc568751e4235502cfee00ba7b597dae78dcChristian Maeder else if(!(flags&WRDE_APPEND))
94ceeb2edbd25b4697ddd9f63c94377924352cf4Christian Maeder {
36c6cc568751e4235502cfee00ba7b597dae78dcChristian Maeder wdarg->we_wordv = 0;
36c6cc568751e4235502cfee00ba7b597dae78dcChristian Maeder wdarg->we_wordc = 0;
36c6cc568751e4235502cfee00ba7b597dae78dcChristian Maeder }
94ceeb2edbd25b4697ddd9f63c94377924352cf4Christian Maeder if(flags&WRDE_UNDEF)
36c6cc568751e4235502cfee00ba7b597dae78dcChristian Maeder stakwrite("set -u\n",7);
81946e2b3f6dde6167f48769bd02c7a634736856Christian Maeder if(!(flags&WRDE_SHOWERR))
81946e2b3f6dde6167f48769bd02c7a634736856Christian Maeder stakwrite("exec 2> /dev/null\n",18);
81946e2b3f6dde6167f48769bd02c7a634736856Christian Maeder stakwrite("print -f \"%q\\n\" ",16);
81946e2b3f6dde6167f48769bd02c7a634736856Christian Maeder if(*cp=='#')
81946e2b3f6dde6167f48769bd02c7a634736856Christian Maeder stakputc('\\');
36c6cc568751e4235502cfee00ba7b597dae78dcChristian Maeder while(c = *cp++)
36c6cc568751e4235502cfee00ba7b597dae78dcChristian Maeder {
81946e2b3f6dde6167f48769bd02c7a634736856Christian Maeder if(c=='\'' && !quoted)
81946e2b3f6dde6167f48769bd02c7a634736856Christian Maeder literal = !literal;
81946e2b3f6dde6167f48769bd02c7a634736856Christian Maeder else if(!literal)
81946e2b3f6dde6167f48769bd02c7a634736856Christian Maeder {
81946e2b3f6dde6167f48769bd02c7a634736856Christian Maeder if(c=='\\' && (!quoted || strchr("\\\"`\n$",c)))
81946e2b3f6dde6167f48769bd02c7a634736856Christian Maeder {
81946e2b3f6dde6167f48769bd02c7a634736856Christian Maeder stakputc('\\');
81946e2b3f6dde6167f48769bd02c7a634736856Christian Maeder if(c= *cp)
81946e2b3f6dde6167f48769bd02c7a634736856Christian Maeder cp++;
36c6cc568751e4235502cfee00ba7b597dae78dcChristian Maeder else
81946e2b3f6dde6167f48769bd02c7a634736856Christian Maeder c = '\\';
81946e2b3f6dde6167f48769bd02c7a634736856Christian Maeder }
36c6cc568751e4235502cfee00ba7b597dae78dcChristian Maeder else if(c=='"')
94ceeb2edbd25b4697ddd9f63c94377924352cf4Christian Maeder quoted = !quoted;
36c6cc568751e4235502cfee00ba7b597dae78dcChristian Maeder else if(c=='`' || (c=='$' && *cp=='('))
94ceeb2edbd25b4697ddd9f63c94377924352cf4Christian Maeder {
94ceeb2edbd25b4697ddd9f63c94377924352cf4Christian Maeder if(flags&WRDE_NOCMD)
81946e2b3f6dde6167f48769bd02c7a634736856Christian Maeder {
94ceeb2edbd25b4697ddd9f63c94377924352cf4Christian Maeder c=WRDE_CMDSUB;
94ceeb2edbd25b4697ddd9f63c94377924352cf4Christian Maeder goto err;
94ceeb2edbd25b4697ddd9f63c94377924352cf4Christian Maeder }
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski /* only the shell can parse the rest */
36c6cc568751e4235502cfee00ba7b597dae78dcChristian Maeder stakputs(cp-1);
36c6cc568751e4235502cfee00ba7b597dae78dcChristian Maeder break;
c18e9c3c6d5039618f1f2c05526ece84c7794ea3Christian Maeder }
36c6cc568751e4235502cfee00ba7b597dae78dcChristian Maeder else if(!quoted && strchr("|&\n;<>"+ac,c))
c18e9c3c6d5039618f1f2c05526ece84c7794ea3Christian Maeder {
36c6cc568751e4235502cfee00ba7b597dae78dcChristian Maeder c=WRDE_BADCHAR;
05e2a3161e4589a717c6fe5c7306820273a473c5Christian Maeder goto err;
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder }
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder else if(c=='(') /* allow | and & inside pattern */
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder ac=2;
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder }
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder stakputc(c);
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder }
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder stakputc(0);
81946e2b3f6dde6167f48769bd02c7a634736856Christian Maeder if(!(iop = sfpopen((Sfio_t*)0,stakptr(0),"r")))
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder {
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder c = WRDE_NOSHELL;
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder goto err;
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder }
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder stakseek(0);
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder ac = 0;
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder while((c=sfgetc(iop)) != EOF)
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder {
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder if(c=='\'')
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder quoted = ! quoted;
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder else if(!quoted && (c==' ' || c=='\n'))
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder {
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder ac++;
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder c = 0;
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder }
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder stakputc(c);
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder }
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder if(c=sfclose(iop))
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder {
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder if(c==3 || !(flags&WRDE_UNDEF))
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder c=WRDE_SYNTAX;
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder else
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder c=WRDE_BADVAL;
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder goto err;
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder }
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder c = ac+2;
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder if(flags&WRDE_DOOFFS)
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder c += wdarg->we_offs;
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder if(flags&WRDE_APPEND)
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder av = (char**)realloc((void*)&wdarg->we_wordv[-1], (wdarg->we_wordc+c)*sizeof(char*));
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder else if(av = (char**)malloc(c*sizeof(char*)))
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder {
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder if(flags&WRDE_DOOFFS)
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder memset((void*)av,0,(wdarg->we_offs+1)*sizeof(char*));
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder else
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder av[0] = 0;
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder }
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder if(!av)
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder 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);
}