summaryrefslogtreecommitdiff
path: root/src/lib/libast/comp/wordexp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libast/comp/wordexp.c')
-rw-r--r--src/lib/libast/comp/wordexp.c217
1 files changed, 217 insertions, 0 deletions
diff --git a/src/lib/libast/comp/wordexp.c b/src/lib/libast/comp/wordexp.c
new file mode 100644
index 0000000..33016dc
--- /dev/null
+++ b/src/lib/libast/comp/wordexp.c
@@ -0,0 +1,217 @@
+/***********************************************************************
+* *
+* 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;
+};
+
+/*
+ * elimnates shell quoting as inserted with sh_fmtq
+ * result relaces <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);
+}