1 /*
2  * $Id: shell.c,v 1.7 2002/07/06 08:51:42 isizaka Exp isizaka $
3  *
4  * This file is part of "Ngraph for X11".
5  *
6  * Copyright (C) 2002, Satoshi ISHIZAKA. isizaka@msa.biglobe.ne.jp
7  *
8  * "Ngraph for X11" is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * "Ngraph for X11" is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  */
23 
24 /**
25  *
26  * $Log: shell.c,v $
27  * Revision 1.7  2002/07/06 08:51:42  isizaka
28  * change to GPL.
29  *
30  * Revision 1.5  2001/07/14 17:42:55  isizaka
31  * for 6.03.14
32  *
33  * Revision 1.4  2000/12/02 08:02:44  isizaka
34  * bug fix: pipe in cmdexec()
35  * thanks to Mr. H. Ito, hito@crl.go.jp
36  *
37  * Revision 1.3  1999/09/10 14:22:38  isizaka
38  * bug fix about '.' command
39  *
40  * Revision 1.2  1999/04/15 12:15:27  isizaka
41  * for release 6.03.01
42  *
43  * Revision 1.1  1999/03/17 13:46:09  isizaka
44  * Initial revision
45  *
46  *
47  **/
48 
49 /*
50  * SYNTAX:
51  *
52  *    name1=val1 name2=val2 ... command arg1 arg2 arg3 ...
53  *
54  *    # comment
55  *
56  *    keyword
57  *        for name [in word] do list done
58  *        case word in [patterm [|pattern] ...list;;] ... esac
59  *        if list then list [elif list then list]...[else list] fi
60  *        while list do list done
61  *        until list do list done
62  *        name() { list; } * { } is needed
63  *
64  *    command replacement
65  *        `command`
66  *
67  *    parameter replacement
68  *        name=value [ name=value ] ...
69  *        $# $? $num $* $@
70  *        ${parameter}
71  *        ${parameter:-word}
72  *        ${parameter:=word}
73  *        ${parameter:?word}
74  *        ${parameter:+word}
75  *        ${parameter#word}
76  *        ${parameter##word}
77  *        ${parameter%word}
78  *        ${parameter%%word}
79  *
80  *    object replacement
81  *        object:namelist:field=value
82  *        ${object:namelist:field=argument}
83  *
84  *     input & output
85  *        < file
86  *        << word
87  *        > file
88  *        >> file
89  *
90  *     special command
91  *        :
92  *        .file
93  *        break [n]
94  *        continue [n]
95  *        cd
96  *        echo
97  *        eval [arg]
98  *        exit [n]
99  *        export [name]
100  *        pwd
101  *        quit
102  *        read name ...
103  *        return [n]
104  *        set
105  *        shift [n]
106  *        test
107  *        unset
108  *        [
109  *        new      object [field:val, ...]
110  *        del      object namelist
111  *        exist    object namelist
112  *        get      object namelist field:argument ...
113  *        put      object namelist field:val ...
114  *        exe      object namelist field:argument ...
115  *        cpy      object sname dnamelist field
116  *        move     object sname dname
117  *        movetop  object name
118  *        moveup   object name
119  *        movedown object name
120  *        movelast object name
121  *        exch     object name1 name2
122  *        dexpr
123  *        iexpr
124  *
125  */
126 
127 #include <stdio.h>
128 #include <stdarg.h>
129 #include <stdlib.h>
130 #include <string.h>
131 #include <ctype.h>
132 #include <errno.h>
133 #include <sys/types.h>
134 #include <fcntl.h>
135 #include <signal.h>
136 #ifndef WINDOWS
137 #include <sys/wait.h>
138 #include <sys/ioctl.h>
139 #include <sys/time.h>
140 #include <unistd.h>
141 #else
142 #include <dos.h>
143 #include <dir.h>
144 #include <io.h>
145 #include <process.h>
146 #include <windows.h>
147 #endif
148 
149 #include "ngraph.h"
150 #include "object.h"
151 #include "nstring.h"
152 #include "ioutil.h"
153 #include "shell.h"
154 #include "shellcm.h"
155 #include "shellux.h"
156 
157 #define FALSE 0
158 #define TRUE 1
159 
160 #define TEMPPFX "NGS"
161 
162 #define ERRNUM 36
163 
164 char *cmderrorlist[ERRNUM]={
165   "unexpected EOF.",
166   "bad substitution.",
167   "syntax error near unexpected token",
168   "unexpected token",
169   "invalid identifier",
170   "command not found",
171   "system call",
172   "extra arguments.",
173   "not enouph argument.",
174   "too many arguments.",
175   "cannot open file",
176   "Use \"exit\" to leave the shell.",
177   "no such file",
178   "I/O error: read file",
179   "I/O error: open file",
180   "missing object argument.",
181   "missing instance argument.",
182   "new instance is specified",
183   "illegal field identifier",
184   "illegal type of argument",
185   "illegal number of specified instance.",
186   "no instance specified",
187   "no field identifier.",
188   "non-numeric argument",
189   "unknown option",
190   "illegal option",
191   "cannot unset",
192   "no such directory",
193   "syntax error for math.",
194   "not allowd function for math.",
195   "sum() or dif(): deep nest for math.",
196   "illegal argument for math.",
197   "fatal error for math.",
198   "deep nest.",
199   "syntax error.",
200   "security check.",
201 };
202 
203 extern char **mainenviron;
204 extern HANDLE consolefd;
205 int security=FALSE;
206 
207 #define WRITEBUFSIZE 4096
208 
209 char writebuf[WRITEBUFSIZE];
210 int writepo;
211 
unlinkfile(char ** file)212 void unlinkfile(char **file)
213 {
214   if (*file!=NULL) {
215     unlink(*file);
216     free(*file);
217     *file=NULL;
218   }
219 }
220 
221 #ifndef WINDOWS
222 
shellevloop(int sig)223 void shellevloop(int sig)
224 {
225   struct itimerval tval;
226 
227   signal(sig,SIG_IGN);
228   eventloop();
229   tval.it_interval.tv_sec=0;
230   tval.it_interval.tv_usec=0;
231   tval.it_value.tv_sec=0;
232   tval.it_value.tv_usec=100000;
233   setitimer(ITIMER_REAL,&tval,NULL);
234   signal(SIGALRM,shellevloop);
235 }
236 
shgetstdin()237 int shgetstdin()
238 {
239   char buf[2];
240   int byte;
241   struct itimerval tval;
242 
243   if (nisatty(stdinfd())) {
244     shellevloop(SIGALRM);
245     do {
246       byte=read(stdinfd(),buf,1);
247     } while (byte<0);
248     tval.it_interval.tv_sec=0;
249     tval.it_interval.tv_usec=0;
250     tval.it_value.tv_sec=0;
251     tval.it_value.tv_usec=0;
252     setitimer(ITIMER_REAL,&tval,NULL);
253     signal(SIGALRM,SIG_IGN);
254   } else {
255     do {
256       byte=read(stdinfd(),buf,1);
257       if (byte<=0) return EOF;
258     } while (buf[0]=='\r');
259   }
260   if (byte<=0) return EOF;
261   return buf[0];
262 }
263 
shget(struct nshell * nshell)264 int shget(struct nshell *nshell)
265 {
266   char buf[2];
267   int byte;
268   struct itimerval tval;
269 
270   if (nisatty(nshell->fd)) {
271     shellevloop(SIGALRM);
272     do {
273       byte=read(nshell->fd,buf,1);
274     } while (byte<0);
275     tval.it_interval.tv_sec=0;
276     tval.it_interval.tv_usec=0;
277     tval.it_value.tv_sec=0;
278     tval.it_value.tv_usec=0;
279     setitimer(ITIMER_REAL,&tval,NULL);
280     signal(SIGALRM,SIG_IGN);
281   } else {
282     do {
283       byte=read(nshell->fd,buf,1);
284       if (byte<=0) return EOF;
285     } while (buf[0]=='\r');
286   }
287   if (byte<=0) return EOF;
288   return buf[0];
289 }
290 
shputstdout(char * s)291 int shputstdout(char *s)
292 {
293   int len;
294 
295   len=strlen(s);
296   write(stdoutfd(),s,len);
297   write(stdoutfd(),"\n",1);
298   return len+1;
299 }
300 
shputstderr(char * s)301 int shputstderr(char *s)
302 {
303   int len;
304 
305   len=strlen(s);
306   write(stderrfd(),s,len);
307   write(stderrfd(),"\n",1);
308   return len+1;
309 }
310 
shprintfstdout(char * fmt,...)311 int shprintfstdout(char *fmt,...)
312 {
313   int len;
314   char buf[1024];
315   va_list ap;
316 
317   va_start(ap,fmt);
318   len=vsprintf(buf,fmt,ap);
319   va_end(ap);
320   write(stdoutfd(),buf,len);
321   return len;
322 }
323 
shprintfstderr(char * fmt,...)324 int shprintfstderr(char *fmt,...)
325 {
326   int len;
327   char buf[1024];
328   va_list ap;
329 
330   va_start(ap,fmt);
331   len=vsprintf(buf,fmt,ap);
332   va_end(ap);
333   write(stderrfd(),buf,len);
334   return len;
335 }
336 
337 #else
338 
339 typedef struct {
340   int pid;
341   int errlevel;
342   int done;
343 } WaitPidParam;
344 
WaitPidThread(LPVOID lpvWaitPidParam)345 DWORD WINAPI WaitPidThread(LPVOID lpvWaitPidParam)
346 {
347   WaitPidParam *pWP;
348 
349   pWP=(WaitPidParam *)lpvWaitPidParam;
350   cwait(&(pWP->errlevel),pWP->pid,WAIT_CHILD);
351   pWP->done=TRUE;
352   return 0;
353 }
354 
waitpid(WaitPidParam * pWP)355 int waitpid(WaitPidParam *pWP)
356 {
357   if (pWP->done) return pWP->pid;
358   else return 0;
359 }
360 
361 typedef struct {
362   int KeyInput;
363   int Ch;
364 } ThreadParam;
365 
GetKeyThread(LPVOID lpvThreadParam)366 DWORD WINAPI GetKeyThread(LPVOID lpvThreadParam)
367 {
368   ThreadParam *pTH;
369   char buf[2];
370   DWORD byte;
371 
372   pTH=(ThreadParam *)lpvThreadParam;
373   do {
374     ReadFile(stdinfd(),buf,1,&byte,NULL);
375     if (byte==0) {
376       pTH->KeyInput=TRUE;
377       pTH->Ch=EOF;
378       return 0;
379     }
380   } while (buf[0]=='\r');
381   pTH->KeyInput=TRUE;
382   pTH->Ch=buf[0];
383   return 0;
384 }
385 
shgetstdin()386 int shgetstdin()
387 {
388   char buf[2];
389   DWORD byte;
390   ThreadParam TH;
391   DWORD IDThread;
392 
393   if (stdinfd()==INVALID_HANDLE_VALUE) return EOF;
394   if (nisatty(stdinfd())) {
395     TH.KeyInput=FALSE;
396     CreateThread(NULL,0,GetKeyThread,&TH,0,&IDThread);
397     while (!TH.KeyInput) eventloop();
398     return TH.Ch;
399   } else {
400     do {
401       ReadFile(stdinfd(),buf,1,&byte,NULL);
402       if (byte==0) return EOF;
403     } while (buf[0]=='\r');
404     return buf[0];
405   }
406 }
407 
shget(struct nshell * nshell)408 int shget(struct nshell *nshell)
409 {
410   char buf[2];
411   DWORD byte;
412   ThreadParam TH;
413   DWORD IDThread;
414 
415   if (nshell->fd==INVALID_HANDLE_VALUE) return EOF;
416   if (nisatty(nshell->fd)) {
417     TH.KeyInput=FALSE;
418     CreateThread(NULL,0,GetKeyThread,&TH,0,&IDThread);
419     while (!TH.KeyInput) eventloop();
420     return TH.Ch;
421   } else if (nshell->readbuf!=NULL) {
422    while (TRUE) {
423      if (nshell->readpo>=nshell->readbyte) {
424        nshell->readpo=0;
425        if (!ReadFile(nshell->fd,nshell->readbuf,SHELLBUFSIZE,
426                     (LPDWORD)&(nshell->readbyte),NULL)) {
427          nshell->readbyte=0;
428        }
429        if (nshell->readbyte==0) return EOF;
430      }
431      if (nshell->readbuf[nshell->readpo]!='\r') {
432        nshell->readpo++;
433        return nshell->readbuf[nshell->readpo-1];
434      } else nshell->readpo++;
435    }
436   } else {
437    do {
438       if (!ReadFile(nshell->fd,buf,1,&byte,NULL)) return EOF;
439       if (byte==0) return EOF;
440     } while (buf[0]=='\r');
441     return buf[0];
442   }
443 }
444 
shputstdout(char * s)445 int shputstdout(char *s)
446 {
447   DWORD len,len2;
448   HANDLE h;
449   int i;
450 
451   len=strlen(s);
452   if ((h=stdoutfd())==INVALID_HANDLE_VALUE) return len+1;
453   for (i=0;i<len;i++) {
454     if (s[i]=='\n') WriteFile(h,"\r",1,&len2,NULL);
455     WriteFile(h,s+i,1,&len2,NULL);
456   }
457   WriteFile(h,"\r\n",2,&len2,NULL);
458   return len+1;
459 }
460 
shputstderr(char * s)461 int shputstderr(char *s)
462 {
463   DWORD len,len2;
464   HANDLE h;
465   int i;
466 
467   len=strlen(s);
468   if ((h=stderrfd())==INVALID_HANDLE_VALUE) return len+1;
469   for (i=0;i<len;i++) {
470     if (s[i]=='\n') WriteFile(h,"\r",1,&len2,NULL);
471     WriteFile(h,s+i,1,&len2,NULL);
472   }
473   WriteFile(h,"\r\n",2,&len2,NULL);
474   return len+1;
475 }
476 
shprintfstdout(char * fmt,...)477 int shprintfstdout(char *fmt,...)
478 {
479   DWORD len,len2;
480   HANDLE h;
481   char buf[1024];
482   va_list ap;
483   int i;
484 
485   va_start(ap,fmt);
486   len=vsprintf(buf,fmt,ap);
487   va_end(ap);
488 
489   if ((h=stdoutfd())==INVALID_HANDLE_VALUE) return len;
490   for (i=0;i<len;i++) {
491     if (buf[i]=='\n') WriteFile(h,"\r",1,&len2,NULL);
492     WriteFile(h,buf+i,1,&len2,NULL);
493   }
494   return len;
495 }
496 
shprintfstderr(char * fmt,...)497 int shprintfstderr(char *fmt,...)
498 {
499   DWORD len,len2;
500   HANDLE h;
501   char buf[1024];
502   va_list ap;
503   int i;
504 
505   va_start(ap,fmt);
506   len=vsprintf(buf,fmt,ap);
507   va_end(ap);
508 
509   if ((h=stderrfd())==INVALID_HANDLE_VALUE) return len;
510   for (i=0;i<len;i++) {
511     if (buf[i]=='\n') WriteFile(h,"\r",1,&len2,NULL);
512     WriteFile(h,buf+i,1,&len2,NULL);
513   }
514   return len;
515 }
516 
517 #endif
518 
519 struct cmdtabletype cmdtable[CMDNUM] = {
520                   {"cd",cmcd},
521                   {"echo",cmecho},
522                   {"eval",cmeval},
523                   {"exit",cmexit} ,
524                   {"export",cmexport},
525                   {"pwd",cmpwd},
526                   {"read",cmread},
527                   {"set",cmset},
528                   {"shift",cmshift},
529                   {"type",cmtype},
530                   {"unset",cmunset},
531                   {":",cmtrue},
532                   {"object",cmobject} ,
533                   {"derive",cmderive} ,
534                   {"new",cmnew} ,
535                   {"exist",cmexist} ,
536                   {"del",cmdel} ,
537                   {"get",cmget},
538                   {"put",cmput} ,
539                   {"cpy",cmcpy},
540                   {"move",cmmove},
541                   {"movetop",cmmovetop},
542                   {"moveup",cmmovetop},
543                   {"movedown",cmmovetop},
544                   {"movelast",cmmovetop},
545                   {"exch",cmmove},
546                   {"exe",cmexe},
547                   {"dexpr",cmdexpr},
548                   {"iexpr",cmdexpr},
549                   {"true",cmtrue},
550                   {"false",cmfalse},
551                   {"[",cmtest},
552                   {"sleep",cmsleep},
553                   {"test",cmtest},
554                  };
555 
556 char *cpcmdtable[CPCMDNUM] = {
557                   ";&|",
558                   "if",
559                   "then" ,
560                   "else",
561                   "elif",
562                   "fi",
563                   "case",
564                   "esac",
565                   "for",
566                   "while",
567                   "until",
568                   "do",
569                   "done",
570                   "{",
571                   "}" };
572 
573 enum {CPNULL=1,CPIF,CPTHEN,CPELSE,CPELIF,CPFI,CPCASE,CPESAC,
574       CPFOR,CPWHILE,CPUNTIL,CPDO,CPDONE,CPBI,CPBO,
575       CPPATI,CPPATO,CPFN,CPNO};
576 
577 enum {PPNULL=0,PPNO,PPSETV,PPSETO,PPSO1,PPSO2,PPSI1,PPSI2,PPPATOR,PPPIPE,
578       PPAND,PPEND};
579 
580 struct cmdstack {
581   int cmdno;
582   char *val;
583   int ival,iftrue,casetrue;
584   char *pat;
585   struct prmlist *prm;
586   struct cmdlist *cmd;
587   void *next;
588 };
589 
prmfree(struct prmlist * prmroot)590 void prmfree(struct prmlist *prmroot)
591 {
592   struct prmlist *prmcur,*prmdel;
593 
594   if (prmroot==NULL) return;
595   prmcur=prmroot;
596   while (prmcur!=NULL) {
597     prmdel=prmcur;
598     prmcur=prmcur->next;
599     memfree(prmdel->str);
600     memfree(prmdel);
601   }
602 }
603 
cmdfree(struct cmdlist * cmdroot)604 void cmdfree(struct cmdlist *cmdroot)
605 {
606   struct cmdlist *cmdcur,*cmddel;
607 
608   cmdcur=cmdroot;
609   while (cmdcur!=NULL) {
610     prmfree(cmdcur->prm);
611     cmddel=cmdcur;
612     cmdcur=cmdcur->next;
613     memfree(cmddel);
614   }
615 }
616 
cmdstackfree(struct cmdstack * stroot)617 void cmdstackfree(struct cmdstack *stroot)
618 {
619   struct cmdstack *stcur,*stdel;
620 
621   stcur=stroot;
622   while (stcur!=NULL) {
623     stdel=stcur;
624     stcur=stcur->next;
625     prmfree(stdel->prm);
626     memfree(stdel);
627   }
628 }
629 
cmdstackcat(struct cmdstack ** stroot,int cmdno)630 void *cmdstackcat(struct cmdstack **stroot,int cmdno)
631 {
632   struct cmdstack *stcur,*stnew;
633 
634   if ((stnew=memalloc(sizeof(struct cmdstack)))==NULL) return NULL;
635   stcur=*stroot;
636   if (stcur==NULL) *stroot=stnew;
637   else {
638     while (stcur->next!=NULL) stcur=stcur->next;
639     stcur->next=stnew;
640   }
641   stnew->next=NULL;
642   stnew->prm=NULL;
643   stnew->cmd=NULL;
644   stnew->cmdno=cmdno;
645   return stnew;
646 }
647 
cmdstackgetpo(struct cmdstack ** stroot)648 struct cmdstack *cmdstackgetpo(struct cmdstack **stroot)
649 {
650   struct cmdstack *stcur,*stprev;
651 
652   stcur=*stroot;
653   stprev=NULL;
654   while (stcur!=NULL) {
655     stprev=stcur;
656     stcur=stcur->next;
657   }
658   return stprev;
659 }
660 
cmdstackgetlast(struct cmdstack ** stroot)661 int cmdstackgetlast(struct cmdstack **stroot)
662 {
663   struct cmdstack *stcur,*stprev;
664 
665   stcur=*stroot;
666   stprev=NULL;
667   while (stcur!=NULL) {
668     stprev=stcur;
669     stcur=stcur->next;
670   }
671   if (stprev==NULL) return 0;
672   else return stprev->cmdno;
673 }
674 
cmdstackrmlast(struct cmdstack ** stroot)675 void cmdstackrmlast(struct cmdstack **stroot)
676 {
677   struct cmdstack *stcur,*stprev;
678 
679   stcur=*stroot;
680   stprev=NULL;
681   if (stcur==NULL) return;
682   while (stcur->next!=NULL) {
683     stprev=stcur;
684     stcur=stcur->next;
685   }
686   if (stprev==NULL) *stroot=NULL;
687   else stprev->next=NULL;
688   prmfree(stcur->prm);
689   memfree(stcur);
690 }
691 
addval(struct nshell * nshell,char * name,char * val)692 char *addval(struct nshell *nshell,char *name,char *val)
693 /* addval() returns NULL on error */
694 {
695   struct vallist *valcur,*valprev,*valnew;
696 
697   if ((valnew=memalloc(sizeof(struct vallist)))==NULL) return NULL;
698   if ((valnew->name=memalloc(strlen(name)+1))==NULL) {
699     memfree(valnew);
700     return NULL;
701   }
702   if ((valnew->val=memalloc(strlen(val)+1))==NULL) {
703     memfree(valnew->name);
704     memfree(valnew);
705     return NULL;
706   }
707   valnew->func=FALSE;
708   valnew->arg=FALSE;
709   strcpy(valnew->name,name);
710   strcpy(valnew->val,val);
711   valcur=nshell->valroot;
712   valprev=NULL;
713   while (valcur!=NULL) {
714     if (strcmp2(name,valcur->name)<=0) break;
715     valprev=valcur;
716     valcur=valcur->next;
717   }
718   if (valprev==NULL) nshell->valroot=valnew;
719   else valprev->next=valnew;
720   if (valcur==NULL) {
721     valnew->next=NULL;
722   } else if (strcmp0(name,valcur->name)==0) {
723     valnew->next=valcur->next;
724     memfree(valcur->name);
725     if (valcur->func) cmdfree(valcur->val);
726     else memfree(valcur->val);
727     memfree(valcur);
728   } else {
729     valnew->next=valcur;
730   }
731   return valnew->name;
732 }
733 
saveval(struct nshell * nshell,char * name,char * val,struct vallist ** newvalroot)734 char *saveval(struct nshell *nshell,char *name,char *val,
735               struct vallist **newvalroot)
736 /* saveval() returns NULL on error */
737 {
738   struct vallist *valcur,*valprev,*valnew;
739 
740   if ((valnew=memalloc(sizeof(struct vallist)))==NULL) return NULL;
741   if ((valnew->name=memalloc(strlen(name)+1))==NULL) {
742     memfree(valnew);
743     return NULL;
744   }
745   if ((valnew->val=memalloc(strlen(val)+1))==NULL) {
746     memfree(valnew->name);
747     memfree(valnew);
748     return NULL;
749   }
750   valnew->func=FALSE;
751   valnew->arg=TRUE;
752   strcpy(valnew->name,name);
753   strcpy(valnew->val,val);
754   valcur=nshell->valroot;
755   valprev=NULL;
756   while (valcur!=NULL) {
757     if (strcmp2(name,valcur->name)<=0) break;
758     valprev=valcur;
759     valcur=valcur->next;
760   }
761   if (valprev==NULL) nshell->valroot=valnew;
762   else valprev->next=valnew;
763   if (valcur==NULL) {
764     valnew->next=NULL;
765   } else if (strcmp0(name,valcur->name)==0) {
766     valnew->next=valcur->next;
767     valcur->next=*newvalroot;
768     if (*newvalroot==NULL) *newvalroot=valcur;
769     else (*newvalroot)->next=valcur;
770   } else {
771     valnew->next=valcur;
772   }
773   return valnew->name;
774 }
775 
restoreval(struct nshell * nshell,struct vallist * newvalroot)776 void restoreval(struct nshell *nshell,struct vallist *newvalroot)
777 /* restoreval() returns NULL on error */
778 {
779   struct vallist *valcur,*valprev,*valnext;
780   struct vallist *valcur2,*valprev2;
781 
782   valcur=nshell->valroot;
783   valprev=NULL;
784   while (valcur!=NULL) {
785     valnext=valcur->next;
786     if (valcur->arg==1) {
787       if (valprev==NULL) nshell->valroot=valcur->next;
788       else valprev->next=valcur->next;
789       memfree(valcur->name);
790       memfree(valcur->val);
791       memfree(valcur);
792     } else valprev=valcur;
793     valcur=valnext;
794   }
795   valcur=newvalroot;
796   while (valcur!=NULL) {
797     valnext=valcur->next;
798     valcur2=nshell->valroot;
799     valprev2=NULL;
800     while (valcur2!=NULL) {
801       if (strcmp2(valcur->name,valcur2->name)<=0) break;
802       valprev2=valcur2;
803       valcur2=valcur2->next;
804     }
805     if (valcur2==NULL) {
806       if (valprev2==NULL) nshell->valroot=valcur;
807       else valprev2->next=valcur;
808       valcur->next=NULL;
809     } else if (strcmp0(valcur->name,valcur2->name)==0) {
810       memfree(valcur->name);
811       if (valcur->func) cmdfree(valcur->val);
812       else memfree(valcur->val);
813       memfree(valcur);
814     } else {
815       if (valprev2==NULL) nshell->valroot=valcur;
816       else valprev2->next=valcur;
817       valcur->next=valcur2;
818     }
819     valcur=valnext;
820   }
821 }
822 
addexp(struct nshell * nshell,char * name)823 char *addexp(struct nshell *nshell,char *name)
824 /* addexp() returns NULL on error */
825 {
826   struct explist *valcur,*valprev,*valnew;
827   int cmp;
828 
829   valcur=nshell->exproot;
830   valprev=NULL;
831   while (valcur!=NULL) {
832     cmp=strcmp2(name,valcur->val);
833     if (cmp==0) return valcur->val;
834     else if (cmp<0) break;
835     valprev=valcur;
836     valcur=valcur->next;
837   }
838   if ((valnew=memalloc(sizeof(struct vallist)))==NULL) return NULL;
839   if ((valnew->val=memalloc(strlen(name)+1))==NULL) {
840     memfree(valnew);
841     return NULL;
842   }
843   if (valprev==NULL) nshell->exproot=valnew;
844   else valprev->next=valnew;
845   strcpy(valnew->val,name);
846   valnew->next=valcur;
847   return valnew->val;
848 }
849 
delval(struct nshell * nshell,char * name)850 int delval(struct nshell *nshell,char *name)
851 {
852   struct vallist *valcur,*valprev;
853 
854   valcur=nshell->valroot;
855   valprev=NULL;
856   while (valcur!=NULL) {
857     if (strcmp0(valcur->name,name)==0) {
858       if (valprev==NULL) nshell->valroot=valcur->next;
859       else valprev->next=valcur->next;
860       memfree(valcur->name);
861       if (valcur->func) cmdfree(valcur->val);
862       else memfree(valcur->val);
863       memfree(valcur);
864       return TRUE;
865     }
866     valprev=valcur;
867     valcur=valcur->next;
868   }
869   return FALSE;
870 }
871 
getval(struct nshell * nshell,char * name)872 char *getval(struct nshell *nshell,char *name)
873 {
874   struct vallist *valcur;
875 
876   valcur=nshell->valroot;
877   while (valcur!=NULL) {
878     if ((strcmp0(valcur->name,name)==0) && (!valcur->func)) return valcur->val;
879     valcur=valcur->next;
880   }
881   return NULL;
882 }
883 
getexp(struct nshell * nshell,char * name)884 int getexp(struct nshell *nshell,char *name)
885 {
886   struct explist *valcur;
887 
888   valcur=nshell->exproot;
889   while (valcur!=NULL) {
890     if (strcmp0(valcur->val,name)==0) return TRUE;
891     valcur=valcur->next;
892   }
893   return FALSE;
894 }
895 
newfunc(struct nshell * nshell,char * name)896 char *newfunc(struct nshell *nshell,char *name)
897 /* newfunc() returns NULL on error */
898 {
899   struct vallist *valcur,*valprev,*valnew;
900 
901   if ((valnew=memalloc(sizeof(struct vallist)))==NULL) return NULL;
902   if ((valnew->name=memalloc(strlen(name)+1))==NULL) {
903     memfree(valnew);
904     return NULL;
905   }
906   valnew->func=TRUE;
907   valnew->arg=FALSE;
908   strcpy(valnew->name,name);
909   valnew->val=NULL;
910   valcur=nshell->valroot;
911   valprev=NULL;
912   while (valcur!=NULL) {
913     if (strcmp2(name,valcur->name)<=0) break;
914     valprev=valcur;
915     valcur=valcur->next;
916   }
917   if (valprev==NULL) nshell->valroot=valnew;
918   else valprev->next=valnew;
919   if (valcur==NULL) {
920     valnew->next=NULL;
921   } else if (strcmp0(name,valcur->name)==0) {
922     valnew->next=valcur->next;
923     memfree(valcur->name);
924     if (valcur->func) cmdfree(valcur->val);
925     else memfree(valcur->val);
926     memfree(valcur);
927   } else {
928     valnew->next=valcur;
929   }
930   return valnew->name;
931 }
932 
addfunc(struct nshell * nshell,char * name,struct cmdlist * val)933 char *addfunc(struct nshell *nshell,char *name,struct cmdlist *val)
934 /* addfunc() returns NULL on error */
935 {
936   struct vallist *valcur;
937   struct cmdlist *cmdcur,*cmdprev,*cmdnew;
938   struct prmlist *prmcur,*prmprev,*prmnew;
939   char *snew;
940 
941   valcur=nshell->valroot;
942   while (valcur!=NULL) {
943     if ((strcmp0(valcur->name,name)==0) && (valcur->func)) {
944       cmdcur=valcur->val;
945       cmdprev=NULL;
946       while (cmdcur!=NULL) {
947         cmdprev=cmdcur;
948         cmdcur=cmdcur->next;
949       }
950       if ((cmdnew=memalloc(sizeof(struct cmdlist)))==NULL) {
951         delval(nshell,name);
952         return NULL;
953       }
954       if (cmdprev==NULL) valcur->val=cmdnew;
955       else cmdprev->next=cmdnew;
956       *cmdnew=*val;
957       cmdnew->prm=NULL;
958       cmdnew->next=NULL;
959       prmcur=val->prm;
960       prmprev=NULL;
961       while (prmcur!=NULL) {
962         if ((prmnew=memalloc(sizeof(struct prmlist)))==NULL) {
963           delval(nshell,name);
964           return NULL;
965         }
966         if (prmprev==NULL) cmdnew->prm=prmnew;
967         else prmprev->next=prmnew;
968         *prmnew=*prmcur;
969         prmnew->next=NULL;
970         if (prmcur->str!=NULL) {
971           if ((snew=memalloc(strlen(prmcur->str)+1))==NULL) {
972             delval(nshell,name);
973             return NULL;
974           }
975           strcpy(snew,prmcur->str);
976           prmnew->str=snew;
977         }
978         prmprev=prmnew;
979         prmcur=prmcur->next;
980       }
981       break;
982     }
983     valcur=valcur->next;
984   }
985   return valcur->name;
986 }
987 
getfunc(struct nshell * nshell,char * name)988 struct cmdlist *getfunc(struct nshell *nshell,char *name)
989 {
990   struct vallist *valcur;
991 
992   valcur=nshell->valroot;
993   while (valcur!=NULL) {
994     if ((strcmp0(valcur->name,name)==0) && (valcur->func)) return valcur->val;
995     valcur=valcur->next;
996   }
997   return NULL;
998 }
999 
gettok(char ** s,int * len,int * quote,int * bquote,int * cend,int * escape)1000 char *gettok(char **s,int *len,int *quote,int *bquote,int *cend,int *escape)
1001 {
1002   int i;
1003   char *po,*spo;
1004 
1005   if (*s==NULL) return NULL;
1006   *cend='\0';
1007   *escape=FALSE;
1008   po=*s;
1009 
1010   /* remove branck */
1011   for (i=0;(po[i]!='\0') && !*quote && (strchr(" \t",po[i])!=NULL);i++);
1012   /* token ends */
1013   if ((po[i]=='\0') || (!*quote && (po[i]=='#'))) {
1014     *len=0;
1015     return NULL;
1016   }
1017   spo=po+i;
1018   if (!*quote && !*bquote) {
1019     /* check speecial character */
1020     if (strchr(";&|^<>()",po[i])!=NULL) {
1021       if (strchr(";&)",po[i])!=NULL) *cend=po[i];
1022       if ((strchr("<>",po[i])!=NULL) && (po[i]==po[i+1])) i++;
1023       if ((po[i]==';') && (po[i]==po[i+1])) i++;
1024       *s+=(i+1);
1025       *len=*s-spo;
1026       return spo;
1027     }
1028   }
1029 
1030   for (;(po[i]!='\0') &&
1031        (*quote || *bquote || *escape || (strchr(";&|^<> \t()",po[i])==NULL));
1032         i++) {
1033     /* check escapse */
1034     if (*escape) *escape=FALSE;
1035     else if (po[i]=='\\') {
1036       if (!*quote
1037       || ((*quote=='"') && (strchr("\"\\'$",po[i+1])!=NULL))
1038       || *bquote ) *escape=TRUE;
1039     /* check back quote */
1040     } else if (*bquote) {
1041       if (po[i]=='`') *bquote='\0';
1042     } else if ((po[i]=='`') && (*quote!='\'')) *bquote='`';
1043     /* check quotation */
1044     else if ((*quote=='"') || (*quote=='\'')) {
1045       if (po[i]==*quote) *quote='\0';
1046     } else if (po[i]=='\'' || po[i]=='"') *quote=po[i];
1047   }
1048 
1049   if (*escape) i--;
1050   *s+=i;
1051   *len=*s-spo;
1052   return spo;
1053 }
1054 
getcmdline(struct nshell * nshell,struct cmdlist ** rcmdroot,struct cmdlist * cmd,char * str,int * istr)1055 int getcmdline(struct nshell *nshell,
1056                struct cmdlist **rcmdroot,struct cmdlist *cmd,
1057                char *str,int *istr)
1058 /* getcmdline() returns
1059      -2: unexpected eof detected
1060      -1: fatal error
1061       0: noerror
1062       1: eof detected */
1063 {
1064   struct cmdlist *cmdroot,*cmdcur;
1065   struct prmlist *prmcur,*prmnew;
1066   int quote,quote2,bquote,bquote2,escape,escape2;
1067   int cend,l,len;
1068   char *spo,*po,*prompt,*tok,*tok2;
1069   char *ignoreeof,*endptr;
1070   int ch;
1071   int i,eofnum;
1072   int err,eofcount;
1073 
1074   err=-1;
1075   escape=escape2=FALSE;
1076   quote=quote2=bquote=bquote2='\0';
1077   cend='\0';
1078   cmdroot=NULL;
1079   cmdcur=NULL;
1080   prmcur=NULL;
1081   tok=NULL;
1082   eofcount=0;
1083   do {
1084     memfree(tok);
1085     tok=NULL;
1086     if (str==NULL) {
1087       if ((tok=nstrnew())==NULL) goto errexit;
1088       if (nisatty(nshell->fd)) {
1089         if ((cmd==NULL) && (cmdroot==NULL)) prompt=getval(nshell,"PS1");
1090         else prompt=getval(nshell,"PS2");
1091         if (prompt!=NULL) printfconsole("%.256s",prompt);
1092       }
1093       do {
1094         ch=shget(nshell);
1095         if (ch==EOF) {
1096           if (strlen(tok)!=0) {
1097             if (!nisatty(nshell->fd)) break;
1098             else printfconsole("%c",(char )0x07);
1099           } else {
1100             if (!nisatty(nshell->fd)) {
1101               if ((cmd!=NULL) || (cmdroot!=NULL)) {
1102                 sherror(ERRUEXPEOF);
1103                 err=-2;
1104               } else err=1;
1105               goto errexit;
1106             } else {
1107               if ((cmd!=NULL) || (cmdroot!=NULL)) {
1108                 sherror(ERRUEXPEOF);
1109                 err=-2;
1110                 goto errexit;
1111               }
1112               eofcount++;
1113               if ((ignoreeof=getval(nshell,"IGNOREEOF"))==NULL) eofnum=0;
1114               else {
1115                 if (ignoreeof[0]=='\0') eofnum=10;
1116                 else {
1117                   eofnum=strtol(ignoreeof,&endptr,10);
1118                   if (endptr[0]!='\0') eofnum=10;
1119                 }
1120               }
1121               if (eofcount>eofnum) {
1122                 err=1;
1123                 putconsole("exit");
1124                 nshell->quit=TRUE;
1125                 goto errexit;
1126               } else {
1127                 sherror(ERREOF);
1128                 ch='\0';
1129               }
1130             }
1131           }
1132         } else {
1133           eofcount=0;
1134           if (ch=='\n') ch='\0';
1135           if ((tok=nstrccat(tok,ch))==NULL) goto errexit;
1136         }
1137       } while (ch!='\0');
1138     } else {
1139       if (str[*istr]=='\0') {
1140         if ((cmd!=NULL) || (cmdroot!=NULL)) {
1141           sherror(ERRUEXPEOF);
1142           err=-2;
1143         } else err=1;
1144         goto errexit;
1145       }
1146       for (i=*istr;(str[i]!='\0') && (str[i]!='\n');i++);
1147       if ((tok=memalloc(i-*istr+1))==NULL) goto errexit;
1148       strncpy(tok,str+*istr,i-*istr);
1149       tok[i-*istr]='\0';
1150       if (str[i]=='\n') *istr=i+1;
1151       else *istr=i;
1152     }
1153     tok2=tok;
1154     do {
1155       spo=gettok(&tok2,&len,&quote,&bquote,&cend,&escape);
1156       if (quote2 || bquote2 || escape2) {
1157         l=strlen(prmcur->str);
1158         if (quote2 || bquote2) l++;
1159         if ((po=memalloc(len+l+1))==NULL) goto errexit;
1160         strcpy(po,prmcur->str);
1161         if (quote2 || bquote2) *(po+l-1)='\n';
1162         if (spo!=NULL) strncpy(po+l,spo,len);
1163         *(po+len+l)='\0';
1164         memfree(prmcur->str);
1165         prmcur->str=po;
1166       } else if (spo!=NULL) {
1167         if (cmdroot==NULL) {
1168           if ((cmdcur=memalloc(sizeof(struct cmdlist)))==NULL) goto errexit;
1169           cmdroot=cmdcur;
1170           cmdcur->next=NULL;
1171           cmdcur->prm=NULL;
1172         }
1173         if ((prmnew=memalloc(sizeof(struct prmlist)))==NULL) goto errexit;
1174         if (cmdcur->prm==NULL) cmdcur->prm=prmnew;
1175         else prmcur->next=prmnew;
1176         prmcur=prmnew;
1177         prmcur->next=NULL;
1178         if ((prmcur->str=memalloc(len+1))==NULL) goto errexit;
1179         strncpy(prmcur->str,spo,len);
1180         prmcur->str[len]='\0';
1181       }
1182       if (cend) {
1183         if ((cmdcur->next=memalloc(sizeof(struct cmdlist)))==NULL)
1184           goto errexit;
1185         cmdcur=cmdcur->next;
1186         cmdcur->next=NULL;
1187         cmdcur->prm=NULL;
1188       }
1189       quote2=quote;
1190       bquote2=bquote;
1191       escape2=escape;
1192     } while ((spo!=NULL) && (!escape) && (!quote) && (!bquote));
1193   } while (quote || bquote || escape || (cmdroot==NULL));
1194   *rcmdroot=cmdroot;
1195   memfree(tok);
1196   return 0;
1197 
1198 errexit:
1199   cmdfree(cmdroot);
1200   memfree(tok);
1201   *rcmdroot=NULL;
1202   return err;
1203 }
1204 
quotation(struct nshell * nshell,char * s,int quote)1205 char *quotation(struct nshell *nshell,char *s,int quote)
1206 {
1207   int i,j,num;
1208   char *snew,*ifs;
1209 
1210   ifs=getval(nshell,"IFS");
1211   num=0;
1212   for (i=0;s[i]!='\0';i++) if (strchr("\"\\'$",s[i])!=NULL) num++;
1213   if ((snew=memalloc(strlen(s)+num+1))==NULL) return NULL;
1214   j=0;
1215   for (i=0;s[i]!='\0';i++) {
1216     if ((quote!='"') && (ifs!=NULL) && (ifs[0]!='\0')
1217     && (strchr(ifs,s[i])!=NULL)) snew[j++]=(char )0x01;
1218     else {
1219       if (strchr("\"\\'$",s[i])!=NULL) snew[j++]=(char )0x02;
1220       snew[j++]=s[i];
1221     }
1222   }
1223   snew[j]='\0';
1224   return snew;
1225 }
1226 
unquotation(char * s,int * quoted)1227 char *unquotation(char *s,int *quoted)
1228 {
1229   int escape,quote,i,j;
1230   char *snew,*po;
1231 
1232   if ((snew=memalloc(strlen(s)+1))==NULL) return NULL;
1233   *quoted=FALSE;
1234   po=s;
1235   escape=FALSE;
1236   quote='\0';
1237 
1238   j=0;
1239   for (i=0;po[i]!='\0';i++) {
1240     if (escape) {
1241       escape=FALSE;
1242       snew[j++]=po[i];
1243     } else if (po[i]=='\\') {
1244       if (!quote
1245       || ((quote=='"') && (strchr("\"\\'$",po[i+1])!=NULL))) escape=TRUE;
1246       else snew[j++]=po[i];
1247     } else if (po[i]==(char )0x02) escape=TRUE;
1248     else if (po[i]==(char )0x01) snew[j++]=' ';
1249     else if ((quote=='"') || (quote=='\'')) {
1250       if (po[i]==quote) quote='\0';
1251       else snew[j++]=po[i];
1252     } else if (po[i]=='\'' || po[i]=='"') {
1253       quote=po[i];
1254       *quoted=TRUE;
1255     } else snew[j++]=po[i];
1256   }
1257 
1258   snew[j]='\0';
1259   return snew;
1260 }
1261 
fnexpand(struct nshell * nshell,char * str)1262 char *fnexpand(struct nshell *nshell,char *str)
1263 {
1264   int escape,expand,noexpand,quote,i,j,len,num;
1265   char *po;
1266   char *s,*s2;
1267   char **namelist;
1268 
1269   po=str;
1270   escape=expand=noexpand=FALSE;
1271   quote='\0';
1272   if ((s=nstrnew())==NULL) return NULL;
1273   if ((s2=nstrnew())==NULL) return NULL;
1274   len=strlen(po);
1275   for (i=0;i<=len;i++) {
1276     if (escape && (po[i]!='\0')) {
1277       escape=FALSE;
1278       if ((s=nstrccat(s,po[i]))==NULL) goto errexit;
1279       if (strchr("*?[",po[i])!=NULL) noexpand=TRUE;
1280     } else if (po[i]=='\\') {
1281       if (!quote
1282       || ((quote=='"') && (strchr("\"\\'$",po[i+1])!=NULL))) escape=TRUE;
1283       else if ((s=nstrccat(s,po[i]))==NULL) goto errexit;
1284     } else if (po[i]==(char )0x02) escape=TRUE;
1285     else if ((po[i]==(char )0x01) || (po[i]=='\0')) {
1286       if (strlen(s)!=0) {
1287         if (!nshell->optionf && expand && !noexpand) {
1288           if ((num=nglob(s,&namelist))==-1) goto errexit;
1289           for (j=0;j<num;j++) {
1290             if (((s2=nstrcat(s2,(char *)(namelist[j])))==NULL)
1291             || ((s2=nstrccat(s2,(char )0x01))==NULL)) {
1292               arg_del(namelist);
1293               goto errexit;
1294             }
1295           }
1296           arg_del(namelist);
1297         } else {
1298           if ((s2=nstrcat(s2,s))==NULL) goto errexit;
1299           if ((s2=nstrccat(s2,(char )0x01))==NULL) goto errexit;
1300         }
1301       }
1302       expand=FALSE;
1303       if (po[i]==(char )0x01) for (;po[i+1]==(char )0x01;i++);
1304       memfree(s);
1305       if ((s=nstrnew())==NULL) goto errexit;
1306     } else if ((quote=='"') || (quote=='\'')) {
1307       if (po[i]==quote) quote='\0';
1308       else if ((s=nstrccat(s,po[i]))==NULL) goto errexit;
1309       if (strchr("*?[",po[i])!=NULL) noexpand=TRUE;
1310     } else if (po[i]=='\'' || po[i]=='"') quote=po[i];
1311     else {
1312       if ((s=nstrccat(s,po[i]))==NULL) goto errexit;
1313       if (strchr("*?[",po[i])!=NULL) expand=TRUE;
1314     }
1315   }
1316 
1317   memfree(s);
1318   memfree(po);
1319   len=strlen(s2);
1320   if ((len!=0) && (s2[len-1]==(char )0x01)) s2[len-1]='\0';
1321   return s2;
1322 
1323 errexit:
1324   memfree(s);
1325   memfree(po);
1326   memfree(s2);
1327   return NULL;
1328 }
1329 
wordsplit(struct prmlist * prmcur)1330 int wordsplit(struct prmlist *prmcur)
1331 {
1332   int i,num;
1333   char *po;
1334   struct prmlist *prmnew;
1335   char *s;
1336 
1337   num=0;
1338   po=prmcur->str;
1339   if (po==NULL) return 1;
1340   if ((s=nstrnew())==NULL) return -1;
1341   for (i=0;po[i]!='\0';i++) {
1342     if (po[i]==(char )0x02) {
1343       i++;
1344       if ((s=nstrccat(s,po[i]))==NULL) goto errexit;
1345     } else if (po[i]==(char )0x01) {
1346       prmcur->str=s;
1347       if ((s=nstrnew())==NULL) goto errexit;
1348       if ((prmnew=memalloc(sizeof(struct prmlist)))==NULL) goto errexit;
1349       prmnew->str=NULL;
1350       prmnew->next=prmcur->next;
1351       prmnew->prmno=prmcur->prmno;
1352       prmcur->next=prmnew;
1353       prmcur=prmnew;
1354       num++;
1355     } else if ((s=nstrccat(s,po[i]))==NULL) goto errexit;
1356   }
1357   prmcur->str=s;
1358   num++;
1359   memfree(po);
1360   return num;
1361 
1362 errexit:
1363   memfree(s);
1364   memfree(po);
1365   return -1;
1366 }
1367 
wordunsplit(char * str)1368 char *wordunsplit(char *str)
1369 {
1370   int i,j;
1371   char *po;
1372 
1373   po=str;
1374   j=0;
1375   for (i=0;po[i]!='\0';i++)
1376     if (po[i]==(char )0x01) po[j++]=' ';
1377     else if (po[i]!=(char )0x02) po[j++]=po[i];
1378   po[j]='\0';
1379   return po;
1380 }
1381 
expand(struct nshell * nshell,char * str,int * quote,int * bquote,int ifsexp)1382 char *expand(struct nshell *nshell,char *str,int *quote,int *bquote,
1383              int ifsexp)
1384 {
1385   char *po;
1386   int quote2,bquote2,escape;
1387   int i,j,k,num;
1388   char *c1,*c2,*name,*val,ch,valf,valf2,*ifs;
1389   char *s,*sb,*se;
1390   HANDLE sout,sout2;
1391   int rcode,dummy;
1392   int byte;
1393   char *tmpfil;
1394   struct objlist *sys;
1395   struct narray *sarray;
1396   char **sdata;
1397   int snum;
1398   char *tmp;
1399 
1400   if ((po=str)==NULL) return NULL;
1401   if ((s=nstrnew())==NULL) return NULL;
1402   name=NULL;
1403   sb=se=NULL;
1404   escape=FALSE;
1405   ifs=getval(nshell,"IFS");
1406 
1407   for (i=0;po[i]!='\0';i++) {
1408     /* check escapse */
1409     if (escape) {
1410       if (se==NULL) {
1411         if (sb!=NULL) {
1412           if ((sb=nstrccat(sb,po[i]))==NULL) goto errexit;
1413         } else {
1414           if ((s=nstrccat(s,po[i]))==NULL) goto errexit;
1415         }
1416       }
1417       escape=FALSE;
1418     } else if (po[i]=='\\') {
1419       if (!*quote
1420       || ((*quote=='"') && (strchr("\"\\'$",po[i+1])!=NULL))
1421       || *bquote ) {
1422         escape=TRUE;
1423         if ((se==NULL) && (sb==NULL)) {
1424           if ((s=nstrccat(s,po[i]))==NULL) goto errexit;
1425         }
1426       } else if (se==NULL) {
1427         if (sb!=NULL) {
1428           if ((sb=nstrccat(sb,po[i]))==NULL) goto errexit;
1429         } else {
1430           if ((s=nstrccat(s,po[i]))==NULL) goto errexit;
1431         }
1432       }
1433     } else if (po[i]==(char )0x02) {
1434       escape=TRUE;
1435       if ((se==NULL) && (sb==NULL)) {
1436         if ((s=nstrccat(s,po[i]))==NULL) goto errexit;
1437       }
1438     /* check back quote */
1439     } else if (*bquote) {
1440       if (po[i]=='`') {
1441         *bquote='\0';
1442         if (se==NULL) {
1443           /* command substitution */
1444           if ((sys=getobject("system"))==NULL) goto errexit;
1445           if ((tmpfil=tempnam(getval(nshell,"TMPDIR"),TEMPPFX))==NULL)
1446             goto errexit;
1447           sout=nopen(tmpfil,O_CREAT|O_TRUNC|O_RDWR,NFMODE);
1448           sout2=nredirect(1,sout);
1449           rcode=cmdexecute(nshell,sb);
1450           if ((rcode!=0) && (rcode!=1)) {
1451             nredirect2(1,sout2);
1452             unlink(tmpfil);
1453             free(tmpfil);
1454             goto errexit;
1455           }
1456           memfree(sb);
1457           if ((sb=nstrnew())==NULL) {
1458             nredirect2(1,sout2);
1459             unlink(tmpfil);
1460             free(tmpfil);
1461             goto errexit;
1462           }
1463           nlseek(stdoutfd(),0L,SEEK_SET);
1464           while ((byte=nread(stdoutfd(),writebuf,WRITEBUFSIZE-1))>0)  {
1465             writebuf[byte]='\0';
1466             if ((sb=nstrcat(sb,writebuf))==NULL) {
1467               nredirect2(1,sout2);
1468               unlink(tmpfil);
1469               free(tmpfil);
1470               goto errexit;
1471             }
1472           }
1473           nredirect2(1,sout2);
1474           unlink(tmpfil);
1475           if (byte==-1) {
1476             sherror2(ERRREAD,tmpfil);
1477             free(tmpfil);
1478             goto errexit;
1479           }
1480           free(tmpfil);
1481           for (j=0;j<strlen(sb);j++) if (sb[j]=='\n') sb[j]=' ';
1482           for (j=strlen(sb)-1;(j>=0) && (sb[j]==' ');j--);
1483           sb[j+1]='\0';
1484           if ((c1=quotation(nshell,sb,*quote))==NULL) goto errexit;
1485           s=nstrcat(s,c1);
1486           memfree(c1);
1487           if (s==NULL) goto errexit;
1488           memfree(sb);
1489           sb=NULL;
1490         }
1491       } else if (se==NULL) {
1492         if (sb!=NULL) {
1493           if ((sb=nstrccat(sb,po[i]))==NULL) goto errexit;
1494         } else {
1495           if ((s=nstrccat(s,po[i]))==NULL) goto errexit;
1496         }
1497       }
1498     } else if ((po[i]=='`') && (*quote!='\'')) {
1499       *bquote='`';
1500       if (se==NULL) {
1501         if ((sb=nstrnew())==NULL) goto errexit;
1502       }
1503     /* check constant variable */
1504     } else if ((po[i]=='$') && (po[i+1]!='\0')
1505     && (*quote!='\'') && (se==NULL)) {
1506       if (isdigit(po[i+1])) {
1507         for (j=i+1;(po[j]!='\0') && isdigit(po[j]);j++);
1508         memfree(name);
1509         if ((name=memalloc(j-i))==NULL) goto errexit;
1510         strncpy(name,po+i+1,j-i-1);
1511         name[j-i-1]='\0';
1512         num=atoi(name);
1513         if (num<nshell->argc) {
1514           if ((c1=quotation(nshell,(nshell->argv)[num],*quote))==NULL)
1515             goto errexit;
1516           s=nstrcat(s,c1);
1517           memfree(c1);
1518           if (s==NULL) goto errexit;
1519         }
1520         i=j-1;
1521       } else if (strchr("#?",po[i+1])!=NULL) {
1522         switch (po[i+1]) {
1523         case '#': memfree(name);
1524                   if ((name=memalloc(12))==NULL) goto errexit;
1525                   sprintf(name,"%d",nshell->argc-1);
1526                   break;
1527         case '?': memfree(name);
1528                   if ((name=memalloc(12))==NULL) goto errexit;
1529                   sprintf(name,"%d",nshell->status);
1530                   break;
1531         }
1532         if ((c1=quotation(nshell,name,*quote))==NULL) goto errexit;
1533         s=nstrcat(s,c1);
1534         memfree(c1);
1535         if (s==NULL) goto errexit;
1536         i++;
1537       } else if (strchr("*@",po[i+1])!=NULL) {
1538         val=getval(nshell,"IFS");
1539         if (val==NULL) ch='\0';
1540         else ch=val[0];
1541         for (j=1;j<nshell->argc;j++) {
1542           if ((c1=quotation(nshell,(nshell->argv)[j],*quote))==NULL)
1543             goto errexit;
1544           s=nstrcat(s,c1);
1545           memfree(c1);
1546           if (s==NULL) goto errexit;
1547           if (j!=(nshell->argc-1)) {
1548             if ((*quote=='"') && (po[i+1]=='*')) {
1549               if (ch!='\0') {
1550                 if (strchr("\"\\'$",ch)!=NULL) {
1551                   if ((s=nstrccat(s,'\\'))==NULL) goto errexit;
1552                 }
1553                 if ((s=nstrccat(s,ch))==NULL) goto errexit;
1554               }
1555             } else {
1556               if ((s=nstrccat(s,(char )0x01))==NULL) goto errexit;
1557             }
1558           }
1559         }
1560         i++;
1561       /* check variable */
1562       } else if (po[i+1]=='{') {
1563         for (j=i+2;(po[j]!='\0') && (isalnum(po[j]) || (po[j]=='_'));j++);
1564         if ((po[j]=='\0') || (strchr(":-=?+#%}",po[j])==NULL)
1565                           || (po[j-1]=='{')) {
1566           sherror(ERRBADSUB);
1567           goto errexit;
1568         }
1569         if (po[j]=='}') {
1570           memfree(name);
1571           if ((name=memalloc(j-i-1))==NULL) goto errexit;
1572           strncpy(name,po+i+2,j-i-2);
1573           name[j-i-2]='\0';
1574           val=getval(nshell,name);
1575           if (val!=NULL) {
1576             if ((c1=quotation(nshell,val,*quote))==NULL) goto errexit;
1577             s=nstrcat(s,c1);
1578             memfree(c1);
1579             if (s==NULL) goto errexit;
1580           }
1581           i=j;
1582         } else {
1583           if ((po[j]==':')
1584           && (po[j+1]!='\0') && (strchr("-=?+",po[j+1])==NULL)) {
1585             valf='o';
1586             if ((se=nstrnew())==NULL) goto errexit;
1587             i+=2;
1588           } else {
1589             memfree(name);
1590             if ((name=memalloc(j-i-1))==NULL) goto errexit;
1591             strncpy(name,po+i+2,j-i-2);
1592             name[j-i-2]='\0';
1593             val=getval(nshell,name);
1594             quote2=*quote;
1595             bquote2=*bquote;
1596             valf2=' ';
1597             if (po[j]==':') {
1598               valf2=':';
1599               j++;
1600             }
1601 	    if (strchr("-=?+",po[j])!=NULL) {
1602               valf=po[j];
1603               j++;
1604             } else if (strchr("#%",po[j])!=NULL) {
1605               if (po[j]==po[j+1]) {
1606                 valf2=po[j];
1607                 j++;
1608               }
1609               valf=po[j];
1610               j++;
1611             } else {
1612               sherror(ERRBADSUB);
1613               goto errexit;
1614             }
1615             if ((se=nstrnew())==NULL) goto errexit;
1616             i=j;
1617           }
1618         }
1619       } else {
1620         /* simple variable substitution */
1621         for (j=i+1;(po[j]!='\0') && (isalnum(po[j]) || (po[j]=='_'));j++);
1622         memfree(name);
1623         if ((name=memalloc(j-i))==NULL) goto errexit;
1624         strncpy(name,po+i+1,j-i-1);
1625         name[j-i-1]='\0';
1626         if (name[0]=='\0') val="$";
1627         else val=getval(nshell,name);
1628         if (val!=NULL) {
1629           if ((c1=quotation(nshell,val,*quote))==NULL) goto errexit;
1630           s=nstrcat(s,c1);
1631           memfree(c1);
1632           if (s==NULL) goto errexit;
1633         }
1634         i=j-1;
1635       }
1636     /* check variable end */
1637     } else if ((po[i]=='}') && (*quote!='\'') && (se!=NULL)) {
1638       if (valf=='o') {
1639       /* object replacement */
1640         if ((tmp=unquotation(se,&dummy))==NULL) goto errexit;
1641         memfree(se);
1642         se=NULL;
1643         sarray=sgetobj(tmp,FALSE,FALSE,FALSE);
1644         memfree(tmp);
1645         sdata=arraydata(sarray);
1646         snum=arraynum(sarray);
1647         for (j=0;j<snum;j++) {
1648           if ((c1=quotation(nshell,sdata[j],*quote))==NULL) {
1649             arrayfree2(sarray);
1650             goto errexit;
1651           }
1652           s=nstrcat(s,c1);
1653           memfree(c1);
1654           if (s==NULL) {
1655             arrayfree2(sarray);
1656             goto errexit;
1657           }
1658         }
1659         arrayfree2(sarray);
1660       /* variable substitution */
1661       } else {
1662         c1=NULL;
1663         switch (valf) {
1664         case '-':
1665           if ((val!=NULL) && ((valf2!=':') || (val[0]!='\0'))) {
1666             if ((c1=quotation(nshell,val,quote2))==NULL) goto errexit;
1667 	  } else {
1668             if ((c1=expand(nshell,se,&quote2,&bquote2,TRUE))==NULL)
1669               goto errexit;
1670           }
1671           break;
1672         case '=':
1673           if ((val!=NULL) && ((valf2!=':') || (val[0]!='\0'))) {
1674             if ((c1=quotation(nshell,val,quote2))==NULL) goto errexit;
1675           } else {
1676             if ((c1=expand(nshell,se,&quote2,&bquote2,TRUE))==NULL)
1677               goto errexit;
1678             memfree(se);
1679             if ((se=unquotation(c1,&dummy))==NULL) goto errexit;
1680             if (addval(nshell,name,se)==NULL) goto errexit;
1681           }
1682           break;
1683         case '?':
1684           if ((val!=NULL) && ((valf2!=':') || (val[0]!='\0'))) {
1685             if ((c1=quotation(nshell,val,quote2))==NULL) goto errexit;
1686           } else {
1687             if ((c1=expand(nshell,se,&quote2,&bquote2,TRUE))==NULL)
1688               goto errexit;
1689             printfstdout("%.256s: %.256s\n",name,c1);
1690             goto errexit;
1691           }
1692           break;
1693         case '+':
1694           if ((val!=NULL) && ((valf2!=':') || (val[0]!='\0'))) {
1695             if ((c1=expand(nshell,se,&quote2,&bquote2,TRUE))==NULL)
1696               goto errexit;
1697           }
1698           break;
1699         case '#':
1700           if ((val!=NULL) && (val[0]!='\0')) {
1701             if ((c2=nstrnew())==NULL) goto errexit;
1702             if ((c2=nstrcat(c2,val))==NULL) goto errexit;
1703             if ((c1=expand(nshell,se,&quote2,&bquote2,TRUE))==NULL) {
1704               memfree(c2);
1705               goto errexit;
1706             }
1707             if (valf2=='#') {
1708               for (k=strlen(c2);k>=0;k--) {
1709                 ch=c2[k];
1710                 c2[k]='\0';
1711                 if (wildmatch(c1,c2,WILD_PATHNAME)) {
1712                   c2[k]=ch;
1713                   break;
1714                 }
1715                 c2[k]=ch;
1716               }
1717             } else {
1718               for (k=0;k<=strlen(c2);k++) {
1719                 ch=c2[k];
1720                 c2[k]='\0';
1721                 if (wildmatch(c1,c2,WILD_PATHNAME)) {
1722                   c2[k]=ch;
1723                   break;
1724                 }
1725                 c2[k]=ch;
1726               }
1727             }
1728             if (k>strlen(c2)) k=0;
1729             memfree(c1);
1730             c1=quotation(nshell,c2+k,quote2);
1731             memfree(c2);
1732             if (c1==NULL) goto errexit;
1733           }
1734           break;
1735         case '%':
1736           if ((val!=NULL) && (val[0]!='\0')) {
1737             if ((c2=nstrnew())==NULL) goto errexit;
1738             if ((c2=nstrcat(c2,val))==NULL) goto errexit;
1739             if ((c1=expand(nshell,se,&quote2,&bquote2,TRUE))==NULL) {
1740               memfree(c2);
1741               goto errexit;
1742             }
1743             if (valf2=='%') {
1744               for (k=0;k<=strlen(c2)-1;k++) {
1745                 if (wildmatch(c1,c2+k,WILD_PATHNAME)) break;
1746               }
1747             } else {
1748               for (k=strlen(c2);k>=0;k--) {
1749                 if (wildmatch(c1,c2+k,WILD_PATHNAME)) break;
1750               }
1751             }
1752             if (k<0) k=strlen(c2);
1753             c2[k]='\0';
1754             memfree(c1);
1755             c1=quotation(nshell,c2,quote2);
1756             memfree(c2);
1757             if (c1==NULL) goto errexit;
1758           }
1759           break;
1760         }
1761         if (c1!=NULL) {
1762           s=nstrcat(s,c1);
1763           memfree(c1);
1764           if (s==NULL) goto errexit;
1765         }
1766         *quote=quote2;
1767         *bquote=bquote2;
1768         memfree(se);
1769         se=NULL;
1770       }
1771     /* check quotation */
1772     } else if ((*quote=='"') || (*quote=='\'')) {
1773       if (po[i]==*quote) *quote='\0';
1774       if (se==NULL) {
1775         if ((s=nstrccat(s,po[i]))==NULL) goto errexit;
1776       }
1777     } else if (po[i]=='\'' || po[i]=='"') {
1778       *quote=po[i];
1779       if (se==NULL) {
1780         if ((s=nstrccat(s,po[i]))==NULL) goto errexit;
1781       }
1782     } else {
1783       if (se==NULL) {
1784         if (ifsexp && (ifs!=NULL) && (ifs[0]!='\0')
1785         && (strchr(ifs,po[i])!=NULL)) {
1786           if ((s=nstrccat(s,(char )0x01))==NULL) goto errexit;
1787         } else {
1788           if ((s=nstrccat(s,po[i]))==NULL) goto errexit;
1789         }
1790       }
1791     }
1792     if (se!=NULL) {
1793       if ((se=nstrccat(se,po[i]))==NULL) goto errexit;
1794     }
1795   }
1796 
1797   if ((se!=NULL) || (sb!=NULL)) {
1798     sherror(ERRBADSUB);
1799     goto errexit;
1800   }
1801 
1802   memfree(name);
1803   memfree(sb);
1804   memfree(se);
1805   return s;
1806 
1807 errexit:
1808   memfree(name);
1809   memfree(sb);
1810   memfree(se);
1811   memfree(s);
1812   return NULL;
1813 }
1814 
checkcmd(struct nshell * nshell,struct cmdlist ** cmdroot)1815 int checkcmd(struct nshell *nshell,struct cmdlist **cmdroot)
1816 /* checkcmd() returns
1817      -1: fatal error
1818       0: noerror
1819       2: error */
1820 {
1821   struct cmdlist *cmdcur,*cmdprev,*cmddel,*cmdnew;
1822   struct prmlist *prmcur,*prmprev;
1823   int cmd,i;
1824   char *po;
1825   char *s,*eof;
1826   int quoted,ch;
1827   int eoflen,match,len;
1828   struct objlist *sys;
1829   char *tmpfil;
1830   HANDLE sout;
1831 
1832   cmdcur=*cmdroot;
1833   cmdprev=NULL;
1834   while (cmdcur!=NULL) {
1835     if (cmdcur->prm==NULL) {
1836       if (cmdprev==NULL) *cmdroot=cmdcur->next;
1837       else cmdprev->next=cmdcur->next;
1838       cmddel=cmdcur;
1839       cmdcur=cmdcur->next;
1840       memfree(cmddel);
1841     } else {
1842       /* remove zero length parameter */
1843       prmcur=cmdcur->prm;
1844       cmd=CPNO;
1845       while (prmcur->next!=NULL) prmcur=prmcur->next;
1846       if (prmcur->str[0]==')') cmd=CPPATI;
1847       prmcur=cmdcur->prm;
1848       if ((prmcur->str[0]!='\0')
1849       && (strchr(cpcmdtable[0],prmcur->str[0])!=NULL)) cmd=CPNULL;
1850       for (i=1;i<CPCMDNUM;i++)
1851         if (strcmp0(cpcmdtable[i],prmcur->str)==0) break;
1852       if (i!=CPCMDNUM) cmd=i+1;
1853       else {
1854         prmcur=prmcur->next;
1855         if ((prmcur!=NULL) && (prmcur->str[0]=='(')) {
1856           prmcur=prmcur->next;
1857           if ((prmcur!=NULL) && (prmcur->str[0]==')')) cmd=CPFN;
1858         }
1859       }
1860       cmdcur->cmdno=cmd;
1861       if ((cmd!=CPNO) && (cmd!=CPCASE) && (cmd!=CPPATI) && (cmd!=CPPATO)
1862       && (cmd!=CPFOR) && (cmd!=CPFN) && ((cmdcur->prm)->next!=NULL)) {
1863         if ((cmdnew=memalloc(sizeof(struct cmdlist)))==NULL) return -1;
1864         cmdnew->next=cmdcur->next;
1865         cmdcur->next=cmdnew;
1866         cmdnew->prm=(cmdcur->prm)->next;
1867         (cmdcur->prm)->next=NULL;
1868         cmdnew->cmdno=CPNO;
1869       }
1870 
1871       /* check pattern */
1872       if (cmdcur->cmdno==CPCASE) {
1873         prmcur=cmdcur->prm; /* case */
1874         if (prmcur->next!=NULL) {
1875           prmcur=prmcur->next; /* word */
1876           if (prmcur->next!=NULL) {
1877             prmprev=prmcur->next; /* in */
1878             if (prmprev->next!=NULL) {
1879               prmcur=prmprev->next;
1880               prmprev->next=NULL;
1881               if ((cmdnew=memalloc(sizeof(struct cmdlist)))==NULL) return -1;
1882               cmdnew->next=cmdcur->next;
1883               cmdcur->next=cmdnew;
1884               cmdnew->prm=prmcur;
1885             }
1886           }
1887         }
1888       }
1889 
1890       /* check redirect and pipe */
1891       cmdcur->cmdend=PPEND;
1892       cmdcur->pipefile=NULL;
1893       prmcur=cmdcur->prm;
1894       prmprev=NULL;
1895       while (prmcur!=NULL) {
1896         if (prmcur->str!=NULL) {
1897           if ((prmcur->str[0]=='>') || (prmcur->str[0]=='<')) {
1898             if ((prmcur->next==NULL) || ((prmcur->next)->str==NULL)
1899              || (strchr(";&|",(prmcur->next)->str[0])!=NULL)) {
1900               sherror2(ERRUEXPTOK,prmprev->str);
1901               return 2;
1902             }
1903             if (prmcur->str[0]==prmcur->str[1]) {
1904               if (prmcur->str[0]=='>')
1905                 prmcur->prmno=PPSO2;
1906               else {
1907                 prmcur->prmno=PPSI2;
1908                 if ((eof=unquotation((prmcur->next)->str,&quoted))==NULL)
1909                   return -1;
1910                 memfree((prmcur->next)->str);
1911                 (prmcur->next)->str=eof;
1912                 (prmcur->next)->quoted=quoted;
1913 
1914                 /* get << contents */
1915 
1916                 if ((sys=getobject("system"))==NULL) return -1;
1917                 if ((tmpfil=tempnam(getval(nshell,"TMPDIR"),TEMPPFX))==NULL)
1918                   return -1;
1919                 sout=nopen(tmpfil,O_CREAT | O_TRUNC | O_RDWR,NFMODE);
1920                 if ((quoted) && !nisatty(nshell->fd)) {
1921                   eoflen=strlen(eof);
1922                   match=0;
1923                   writepo=0;
1924                   while (TRUE) {
1925                     ch=shget(nshell);
1926                     if ((ch==EOF) || (ch=='\0')) break;
1927                     if (ch=='\n') {
1928                       if (match==eoflen) break;
1929                       writebuf[writepo]=ch;
1930                       writepo++;
1931                       if (writepo==WRITEBUFSIZE) {
1932                         nwrite(sout,writebuf,WRITEBUFSIZE);
1933                         writepo=0;
1934                       }
1935                       match=0;
1936                     } else if (match==-1) {
1937                       writebuf[writepo]=ch;
1938                       writepo++;
1939                       if (writepo==WRITEBUFSIZE) {
1940                         nwrite(sout,writebuf,WRITEBUFSIZE);
1941                         writepo=0;
1942                       }
1943                     } else if ((match==eoflen) || (ch!=eof[match])) {
1944                       for (i=0;i<match;i++) {
1945                         writebuf[writepo]=eof[i];
1946                         writepo++;
1947                         if (writepo==WRITEBUFSIZE) {
1948                           nwrite(sout,writebuf,WRITEBUFSIZE);
1949                           writepo=0;
1950                         }
1951                       }
1952                       writebuf[writepo]=ch;
1953                       writepo++;
1954                       if (writepo==WRITEBUFSIZE) {
1955                         nwrite(sout,writebuf,WRITEBUFSIZE);
1956                         writepo=0;
1957                       }
1958                       match=-1;
1959                     } else match++;
1960                   }
1961                   if (writepo!=0) nwrite(sout,writebuf,writepo);
1962                 } else {
1963                   do {
1964                     if ((s=nstrnew())==NULL) {
1965                       nclose(sout);
1966                       unlinkfile(&tmpfil);
1967                       return -1;
1968                     }
1969                     if (nisatty(nshell->fd))
1970                       printfconsole("%.256s",getval(nshell,"PS2"));
1971                     do {
1972                       ch=shget(nshell);
1973                       if (ch==EOF) {
1974                         if (strlen(s)!=0) {
1975                           if (!nisatty(nshell->fd)) break;
1976                           else printfconsole("%c",(char )0x07);
1977                         } else break;
1978                       } else {
1979                         if (ch=='\n') ch='\0';
1980                         if ((s=nstrccat(s,ch))==NULL) {
1981                           nclose(sout);
1982                           unlinkfile(&tmpfil);
1983                           return -1;
1984                         }
1985                       }
1986                     } while (ch!='\0');
1987                     if (strcmp0(eof,s)!=0) {
1988                       len=strlen(s);
1989                       s[len]='\n';
1990                       nwrite(sout,s,len+1);
1991                       memfree(s);
1992                     } else {
1993                       memfree(s);
1994                       break;
1995                     }
1996                   } while (ch!=EOF);
1997                 }
1998                 nclose(sout);
1999                 memfree((prmcur->next)->str);
2000                 (prmcur->next)->str=tmpfil;
2001               }
2002             } else {
2003               if (prmcur->str[0]=='>')
2004                 prmcur->prmno=PPSO1;
2005               else
2006                 prmcur->prmno=PPSI1;
2007             }
2008             (prmcur->next)->prmno=prmcur->prmno;
2009             prmcur=prmcur->next;
2010           } else if (prmcur->str[0]=='|') {
2011             if (cmdcur->cmdno==CPPATI) prmcur->prmno=PPPATOR;
2012             else {
2013               cmdcur->cmdend=PPPIPE;
2014               prmcur->prmno=PPPIPE;
2015               if ((prmcur->next==NULL) || ((prmcur->next)->str==NULL)
2016                || (strchr(";&|",(prmcur->next)->str[0])!=NULL)) {
2017                 sherror2(ERRUEXPTOK,prmcur->str);
2018                 return 2;
2019               }
2020               if ((cmdnew=memalloc(sizeof(struct cmdlist)))==NULL) return -1;
2021               cmdnew->next=cmdcur->next;
2022               cmdcur->next=cmdnew;
2023               cmdnew->prm=prmcur->next;
2024               prmcur->next=NULL;
2025               cmdnew->cmdno=CPNO;
2026             }
2027           } else if (prmcur->str[0]=='&') {
2028             prmcur->prmno=PPAND;
2029             cmdcur->cmdend=PPAND;
2030           } else if (prmcur->str[0]==';') {
2031             if (prmcur->str[1]==';') cmdcur->cmdno=CPPATO;
2032             else prmcur->prmno=PPEND;
2033           } else prmcur->prmno=PPNO;
2034         } else prmcur->prmno=PPNULL;
2035         prmprev=prmcur;
2036         prmcur=prmcur->next;
2037       }
2038 
2039       /* check variable setting command */
2040       prmcur=cmdcur->prm;
2041       while (prmcur!=NULL) {
2042         if (prmcur->prmno==PPNO) {
2043           po=prmcur->str;
2044           if (isobject(&po) && (po[0]=='=')) {
2045             prmcur->prmno=PPSETO;
2046           } else {
2047             po=prmcur->str;
2048             for (i=0;(po[i]!='\0') && (isalnum(po[i]) || (po[i]=='_'));i++);
2049             if ((i!=0) && (po[i]=='=')) prmcur->prmno=PPSETV;
2050           }
2051           if (prmcur->prmno==PPNO) break;
2052         }
2053         prmcur=prmcur->next;
2054       }
2055 
2056       cmdprev=cmdcur;
2057       cmdcur=cmdcur->next;
2058     }
2059   }
2060   return 0;
2061 }
2062 
syntax(struct nshell * nshell,struct cmdlist * cmdroot,int * needcmd,struct cmdstack ** sx)2063 int syntax(struct nshell *nshell,
2064            struct cmdlist *cmdroot,int *needcmd,struct cmdstack **sx)
2065 /* syntax() returns
2066      -1: fatal error
2067       0: noerror
2068       2: syntax error */
2069 {
2070   struct cmdlist *cmdcur;
2071   struct prmlist *prmcur;
2072   int i,cmd,c;
2073   char *s;
2074   struct cmdstack *st;
2075 
2076   cmdcur=cmdroot;
2077   while (cmdcur!=NULL) {
2078     cmd=cmdcur->cmdno;
2079     c=cmdstackgetlast(sx);
2080     if ((c==CPFOR) && (cmd!=CPDO)) {
2081       sherror2(ERRUEXPTOK,(cmdcur->prm)->str);
2082       return 2;
2083     }
2084     if ((c==CPCASE) && (cmd!=CPPATI) && (cmd!=CPESAC)) {
2085       sherror2(ERRUEXPTOK,(cmdcur->prm)->str);
2086       return 2;
2087     }
2088     if ((c==CPFN) && (cmd!=CPBI)) {
2089       sherror2(ERRUEXPTOK,(cmdcur->prm)->str);
2090       return 2;
2091     }
2092     if ((*needcmd) &&
2093        !((cmd==CPIF) || (cmd==CPCASE) || (cmd==CPFOR) || (cmd==CPWHILE)
2094      || (cmd==CPUNTIL) || (cmd==CPFN) || (cmd==CPNO))) {
2095       sherror2(ERRUEXPTOK,(cmdcur->prm)->str);
2096       return 2;
2097     }
2098     if ((cmd==CPIF) || (cmd==CPTHEN) || (cmd==CPELSE) || (cmd==CPELIF)
2099      || (cmd==CPWHILE) || (cmd==CPUNTIL) || (cmd==CPDO) || (cmd==CPBI))
2100       *needcmd=TRUE;
2101     else if (cmdcur->cmdend==PPPIPE) *needcmd=TRUE;
2102     else *needcmd=FALSE;
2103     switch (cmd) {
2104     case CPNULL:
2105       sherror2(ERRUEXPTOK,(cmdcur->prm)->str);
2106       return 2;
2107     case CPIF:
2108       if ((st=cmdstackcat(sx,CPIF))==NULL) return -1;
2109       st->cmd=cmdcur;
2110       break;
2111     case CPTHEN:
2112       if (cmdstackgetlast(sx)!=CPIF) {
2113         sherror2(ERRUEXPTOK,(cmdcur->prm)->str);
2114         return 2;
2115       }
2116       if ((st=cmdstackgetpo(sx))==NULL) return -1;
2117       (st->cmd)->done=cmdcur;
2118       cmdstackrmlast(sx);
2119       if ((st=cmdstackcat(sx,CPTHEN))==NULL) return -1;
2120       st->cmd=cmdcur;
2121       break;
2122     case CPELIF:
2123       if (cmdstackgetlast(sx)!=CPTHEN) {
2124         sherror2(ERRUEXPTOK,(cmdcur->prm)->str);
2125         return 2;
2126       }
2127       if ((st=cmdstackgetpo(sx))==NULL) return -1;
2128       (st->cmd)->done=cmdcur;
2129       cmdstackrmlast(sx);
2130       if ((st=cmdstackcat(sx,CPIF))==NULL) return -1;
2131       st->cmd=cmdcur;
2132       break;
2133     case CPELSE:
2134       if (cmdstackgetlast(sx)!=CPTHEN) {
2135         sherror2(ERRUEXPTOK,(cmdcur->prm)->str);
2136         return 2;
2137       }
2138       if ((st=cmdstackgetpo(sx))==NULL) return -1;
2139       (st->cmd)->done=cmdcur;
2140       cmdstackrmlast(sx);
2141       if ((st=cmdstackcat(sx,CPELSE))==NULL) return -1;
2142       st->cmd=cmdcur;
2143       break;
2144     case CPFI:
2145       c=cmdstackgetlast(sx);
2146       if ((c!=CPTHEN) && (c!=CPELSE)) {
2147         sherror2(ERRUEXPTOK,(cmdcur->prm)->str);
2148         return 2;
2149       }
2150       if ((st=cmdstackgetpo(sx))==NULL) return -1;
2151       (st->cmd)->done=cmdcur;
2152       cmdstackrmlast(sx);
2153       break;
2154     case CPCASE:
2155       if ((st=cmdstackcat(sx,CPCASE))==NULL) return -1;
2156       st->cmd=cmdcur;
2157       prmcur=(cmdcur->prm)->next;
2158       if ((prmcur==NULL) || (prmcur->next==NULL)) {
2159         sherror2(ERRSYNTAX,(cmdcur->prm)->str);
2160         return 2;
2161       }
2162       prmcur=prmcur->next;
2163       if ((prmcur->str==NULL) || (strcmp0("in",prmcur->str)!=0)) {
2164         sherror2(ERRSYNTAX,prmcur->str);
2165         return 2;
2166       }
2167       if (prmcur->next!=NULL) {
2168         sherror2(ERRUEXPTOK,(prmcur->next)->str);
2169         return 2;
2170       }
2171       break;
2172     case CPPATI:
2173       c=cmdstackgetlast(sx);
2174       if ((c!=CPCASE) && (c!=CPPATO)) {
2175         sherror2(ERRUEXPTOK,(cmdcur->prm)->str);
2176         return 2;
2177       }
2178       prmcur=cmdcur->prm;
2179       if (prmcur->str[0]==')') {
2180         sherror2(ERRUEXPTOK,prmcur->str);
2181         return 2;
2182       }
2183       prmcur=prmcur->next;
2184       while (TRUE) {
2185         if (prmcur->str[0]==')') break;
2186         if (prmcur->prmno!=PPPATOR) {
2187           sherror2(ERRUEXPTOK,prmcur->str);
2188           return 2;
2189         }
2190         if ((prmcur->next==NULL)
2191         || ((prmcur->next)->next==NULL)) {
2192           sherror2(ERRUEXPTOK,prmcur->str);
2193           return 2;
2194         }
2195         prmcur=(prmcur->next)->next;
2196       }
2197       if ((st=cmdstackgetpo(sx))==NULL) return -1;
2198       (st->cmd)->done=cmdcur;
2199       cmdstackrmlast(sx);
2200       if ((st=cmdstackcat(sx,CPPATI))==NULL) return -1;
2201       st->cmd=cmdcur;
2202       break;
2203     case CPPATO:
2204       if (cmdstackgetlast(sx)!=CPPATI) {
2205         sherror2(ERRUEXPTOK,(cmdcur->prm)->str);
2206         return 2;
2207       }
2208       if ((st=cmdstackgetpo(sx))==NULL) return -1;
2209       (st->cmd)->done=cmdcur;
2210       cmdstackrmlast(sx);
2211       if ((st=cmdstackcat(sx,CPPATO))==NULL) return -1;
2212       st->cmd=cmdcur;
2213       break;
2214     case CPESAC:
2215       c=cmdstackgetlast(sx);
2216       if ((c!=CPCASE) && (c!=CPPATI) && (c!=CPPATO)) {
2217         sherror2(ERRUEXPTOK,(cmdcur->prm)->str);
2218         return 2;
2219       }
2220       if ((st=cmdstackgetpo(sx))==NULL) return -1;
2221       (st->cmd)->done=cmdcur;
2222       cmdstackrmlast(sx);
2223       break;
2224     case CPFOR:
2225       if (cmdstackcat(sx,CPFOR)==NULL) return -1;
2226       prmcur=(cmdcur->prm)->next;
2227       if (prmcur==NULL) {
2228         sherror2(ERRSYNTAX,(cmdcur->prm)->str);
2229         return 2;
2230       }
2231       prmcur=prmcur->next;
2232       if (prmcur!=NULL) {
2233         if (strcmp0("in",prmcur->str)!=0) {
2234           sherror2(ERRSYNTAX,prmcur->str);
2235           return 2;
2236         }
2237         prmcur=prmcur->next;
2238         while (prmcur!=NULL) {
2239           if ((prmcur->prmno!=PPNO) && (prmcur->prmno!=PPEND)) {
2240             sherror2(ERRUEXPTOK,prmcur->str);
2241             return 2;
2242           }
2243           prmcur=prmcur->next;
2244         }
2245       }
2246       break;
2247     case CPWHILE:
2248       if (cmdstackcat(sx,CPWHILE)==NULL) return -1;
2249       break;
2250     case CPUNTIL:
2251       if (cmdstackcat(sx,CPUNTIL)==NULL) return -1;
2252       break;
2253     case CPDO:
2254       c=cmdstackgetlast(sx);
2255       if ((c!=CPFOR) && (c!=CPWHILE) && (c!=CPUNTIL)) {
2256         sherror2(ERRUEXPTOK,(cmdcur->prm)->str);
2257         return 2;
2258       }
2259       cmdstackrmlast(sx);
2260       if ((st=cmdstackcat(sx,CPDO))==NULL) return -1;
2261       st->cmd=cmdcur;
2262       break;
2263     case CPDONE:
2264       if (cmdstackgetlast(sx)!=CPDO) {
2265         sherror2(ERRUEXPTOK,(cmdcur->prm)->str);
2266         return 2;
2267       }
2268       if ((st=cmdstackgetpo(sx))==NULL) return -1;
2269       (st->cmd)->done=cmdcur;
2270       cmdstackrmlast(sx);
2271       break;
2272     case CPFN:
2273       s=(cmdcur->prm)->str;
2274       for (i=0;s[i]!='\0';i++) if (!isalnum(s[i]) && (s[i]!='_')) {
2275         sherror2(ERRIDENT,s);
2276         return 2;
2277       }
2278       if ((st=cmdstackcat(sx,CPFN))==NULL) return -1;
2279       st->cmd=cmdcur;
2280       break;
2281     case CPBI:
2282       if (cmdstackgetlast(sx)!=CPFN) {
2283         sherror2(ERRUEXPTOK,(cmdcur->prm)->str);
2284         return 2;
2285       }
2286       if ((st=cmdstackcat(sx,CPBI))==NULL) return -1;
2287       st->cmd=cmdcur;
2288       break;
2289     case CPBO:
2290       if (cmdstackgetlast(sx)!=CPBI) {
2291         sherror2(ERRUEXPTOK,(cmdcur->prm)->str);
2292         return 2;
2293       }
2294       if ((st=cmdstackgetpo(sx))==NULL) return -1;
2295       (st->cmd)->done=cmdcur;
2296       cmdstackrmlast(sx);
2297       cmdstackrmlast(sx);
2298       break;
2299     default:
2300       break;
2301     }
2302     cmdcur=cmdcur->next;
2303   }
2304   return 0;
2305 }
2306 
cmdexec(struct nshell * nshell,struct cmdlist * cmdroot,int namedfunc)2307 int cmdexec(struct nshell *nshell,struct cmdlist *cmdroot,int namedfunc)
2308 {
2309    struct cmdlist *cmdcur,*cmdnew,*cmd;
2310    struct prmlist *prmcur,*prmprev,*prm,*prmnewroot;
2311    struct vallist *valcur,*newvalroot;
2312    int err,quote,bquote,rcode,needcmd;
2313    char *str,*name,*val,*po,*cmdname;
2314    int i,j,num,pnum,errlevel,a,looplevel,len;
2315    char *arg,*endptr,**environ;
2316    struct cmdstack *stroot,*stcur,*st;
2317    char *fstdout,*fstdin;
2318    int istdout,istdin;
2319    HANDLE sout,sout2,sin,sin2,sin3,fd;
2320    int lastc;
2321    int pipef;
2322    struct objlist *sys;
2323    char *tmpfil,*tmpfil2;
2324    char *cmds;
2325    char *s;
2326    char **argv,**newenviron;
2327    char **argvsave,**argvnew;
2328    int quoted;
2329    int argcsave,argcnew;
2330    int iftrue,casetrue;
2331    char *pat;
2332    char *readbuf;
2333    int readpo;
2334    int readbyte;
2335    int ch;
2336    char buf[2];
2337 
2338 #ifndef WINDOWS
2339    pid_t pid;
2340 #else
2341    int pid;
2342    WaitPidParam WP;
2343    DWORD IDThread;
2344 #endif
2345 
2346    nshell->cmdexec++;
2347    err=-1;
2348    stroot=NULL;
2349    prmnewroot=NULL;
2350    fstdout=fstdin=NULL;
2351    environ=NULL;
2352    newenviron=NULL;
2353    newvalroot=NULL;
2354    cmdname=NULL;
2355    sout=sout2=sin=sin2=NOHANDLE;
2356    tmpfil2=NULL;
2357    if (nshell->optionv) {
2358      cmd=cmdroot;
2359      while (cmd!=NULL) {
2360        prm=cmd->prm;
2361        while (prm!=NULL) {
2362          printfconsole("%.256s ",prm->str);
2363          prm=prm->next;
2364        }
2365        printfconsole("\n");
2366        cmd=cmd->next;
2367      }
2368    }
2369    cmdcur=cmdroot;
2370    while ((cmdcur!=NULL) && (!(nshell->quit))) {
2371      if (ninterrupt()) goto errexit;
2372      stcur=cmdstackgetpo(&stroot);
2373      if ((stcur!=NULL) && (stcur->cmdno==CPBI) && (stcur->cmd!=cmdcur)) {
2374        if (addfunc(nshell,stcur->val,cmdcur)==NULL) goto errexit;
2375        cmdcur=cmdcur->next;
2376      } else
2377      switch (cmdcur->cmdno) {
2378      case CPNULL:
2379        cmdcur=cmdcur->next;
2380        break;
2381      case CPIF:
2382        if ((st=cmdstackcat(&stroot,CPIF))==NULL) goto errexit;
2383        st->iftrue=FALSE;
2384        cmdcur=cmdcur->next;
2385        break;
2386      case CPTHEN:
2387        if ((st=cmdstackgetpo(&stroot))==NULL) goto errexit;
2388        iftrue=st->iftrue;
2389        if (iftrue || nshell->status) cmdcur=cmdcur->done;
2390        else {
2391          iftrue=TRUE;
2392          cmdcur=cmdcur->next;
2393        }
2394        cmdstackrmlast(&stroot);
2395        if ((st=cmdstackcat(&stroot,CPTHEN))==NULL) goto errexit;
2396        st->iftrue=iftrue;
2397        break;
2398      case CPELIF:
2399        if ((st=cmdstackgetpo(&stroot))==NULL) goto errexit;
2400        iftrue=st->iftrue;
2401        if (iftrue) cmdcur=cmdcur->done;
2402        else cmdcur=cmdcur->next;
2403        cmdstackrmlast(&stroot);
2404        if ((st=cmdstackcat(&stroot,CPIF))==NULL) goto errexit;
2405        st->iftrue=iftrue;
2406        break;
2407      case CPELSE:
2408        if ((st=cmdstackgetpo(&stroot))==NULL) goto errexit;
2409        iftrue=st->iftrue;
2410        if (iftrue) cmdcur=cmdcur->done;
2411        else cmdcur=cmdcur->next;
2412        cmdstackrmlast(&stroot);
2413        if ((st=cmdstackcat(&stroot,CPELSE))==NULL) goto errexit;
2414        st->iftrue=iftrue;
2415        break;
2416      case CPFI:
2417        cmdstackrmlast(&stroot);
2418        cmdcur=cmdcur->next;
2419        break;
2420      case CPCASE:
2421        if ((st=cmdstackcat(&stroot,CPCASE))==NULL) return -1;
2422        st->casetrue=FALSE;
2423        prmcur=(cmdcur->prm)->next;
2424        quote='\0';
2425        bquote='\0';
2426        if ((str=expand(nshell,prmcur->str,&quote,&bquote,FALSE))==NULL)
2427          goto errexit;
2428        if (quote || bquote) {
2429          sherror(ERRUEXPEOF);
2430          goto errexit;
2431        }
2432        if ((str=fnexpand(nshell,str))==NULL) goto errexit;
2433        wordunsplit(str);
2434        st->pat=str;
2435        cmdcur=cmdcur->next;
2436        break;
2437      case CPPATI:
2438        if ((st=cmdstackgetpo(&stroot))==NULL) goto errexit;
2439        casetrue=st->casetrue;
2440        pat=st->pat;
2441        if (casetrue) cmdcur=cmdcur->done;
2442        else {
2443          prm=cmdcur->prm;
2444          while (prm!=NULL) {
2445            if (wildmatch(prm->str,pat,0)) break;
2446            prm=prm->next;
2447            prm=prm->next;
2448          }
2449          if (prm!=NULL) {
2450            casetrue=TRUE;
2451            cmdcur=cmdcur->next;
2452          } else cmdcur=cmdcur->done;
2453        }
2454        cmdstackrmlast(&stroot);
2455        if ((st=cmdstackcat(&stroot,CPPATI))==NULL) goto errexit;
2456        st->casetrue=casetrue;
2457        st->pat=pat;
2458        break;
2459      case CPPATO:
2460        if ((st=cmdstackgetpo(&stroot))==NULL) goto errexit;
2461        casetrue=st->casetrue;
2462        pat=st->pat;
2463        cmdstackrmlast(&stroot);
2464        if ((st=cmdstackcat(&stroot,CPPATO))==NULL) goto errexit;
2465        st->casetrue=casetrue;
2466        st->pat=pat;
2467        cmdcur=cmdcur->done;
2468        break;
2469      case CPESAC:
2470        if ((st=cmdstackgetpo(&stroot))==NULL) goto errexit;
2471        casetrue=st->casetrue;
2472        pat=st->pat;
2473        memfree(pat);
2474        cmdstackrmlast(&stroot);
2475        cmdcur=cmdcur->next;
2476        break;
2477      case CPFOR:
2478        if ((stcur=cmdstackcat(&stroot,CPFOR))==NULL) goto errexit;
2479        stcur->cmd=cmdcur;
2480        prmcur=(cmdcur->prm)->next;
2481        stcur->val=prmcur->str;
2482        prmcur=prmcur->next;
2483        if (prmcur==NULL) stcur->ival=0;
2484        else {
2485          stcur->ival=-1;
2486          prmnewroot=NULL;
2487          prmprev=NULL;
2488          prmcur=prmcur->next;
2489          while (prmcur!=NULL) {
2490            if ((prm=memalloc(sizeof(struct prmlist)))==NULL) goto errexit;
2491            if (prmprev==NULL) prmnewroot=prm;
2492            else prmprev->next=prm;
2493            prm->next=NULL;
2494            prm->str=NULL;
2495            prm->prmno=prmcur->prmno;
2496            quote='\0';
2497            bquote='\0';
2498            if ((str=expand(nshell,prmcur->str,&quote,&bquote,FALSE))==NULL)
2499              goto errexit;
2500            if (quote || bquote) {
2501              sherror(ERRUEXPEOF);
2502              goto errexit;
2503            }
2504            if (str[0]!='\0') {
2505              if ((prm->str=fnexpand(nshell,str))==NULL) goto errexit;
2506            } else {
2507              memfree(str);
2508              prm->str=NULL;
2509            }
2510            if ((num=wordsplit(prm))==-1) goto errexit;
2511            for (j=0;j<num;j++) {
2512              prmprev=prm;
2513              prm=prm->next;
2514            }
2515            prmcur=prmcur->next;
2516          }
2517          /* remove null parameter and command end */
2518          prmcur=prmnewroot;
2519          prmprev=NULL;
2520          while (prmcur!=NULL) {
2521            if ((prmcur->str==NULL) || (prmcur->prmno==PPEND)) {
2522              if (prmprev==NULL) prmnewroot=prmcur->next;
2523              else prmprev->next=prmcur->next;
2524              prm=prmcur;
2525              prmcur=prmcur->next;
2526              memfree(prm->str);
2527              memfree(prm);
2528            } else {
2529              prmprev=prmcur;
2530              prmcur=prmcur->next;
2531            }
2532          }
2533          prmfree(stcur->prm);
2534          stcur->prm=prmnewroot;
2535          prmnewroot=NULL;
2536        }
2537        cmdcur=cmdcur->next;
2538        break;
2539      case CPWHILE:
2540        if ((stcur=cmdstackcat(&stroot,CPWHILE))==NULL) goto errexit;
2541        stcur->cmd=cmdcur;
2542        cmdcur=cmdcur->next;
2543        break;
2544      case CPUNTIL:
2545        if ((stcur=cmdstackcat(&stroot,CPUNTIL))==NULL) goto errexit;
2546        stcur->cmd=cmdcur;
2547        cmdcur=cmdcur->next;
2548        break;
2549      case CPDO:
2550        if ((stcur=cmdstackgetpo(&stroot))==NULL) goto errexit;
2551        if (stcur->cmdno==CPFOR) {
2552          if (stcur->ival==-1) {
2553            prmcur=stcur->prm;
2554            if (prmcur==NULL) {
2555              cmdcur=cmdcur->done;
2556              cmdstackrmlast(&stroot);
2557              cmdcur=cmdcur->next;
2558              break;
2559            }
2560            if (addval(nshell,stcur->val,prmcur->str)==NULL) goto errexit;
2561            stcur->prm=prmcur->next;
2562            memfree(prmcur->str);
2563            memfree(prmcur);
2564          } else {
2565            stcur->ival++;
2566            if (stcur->ival<nshell->argc) {
2567              if (addval(nshell,stcur->val,nshell->argv[stcur->ival])==NULL)
2568                 goto errexit;
2569            } else {
2570              cmdcur=cmdcur->done;
2571              cmdstackrmlast(&stroot);
2572              cmdcur=cmdcur->next;
2573              break;
2574            }
2575          }
2576        } else if (stcur->cmdno==CPWHILE) {
2577          if (nshell->status) {
2578            cmdcur=cmdcur->done;
2579            cmdstackrmlast(&stroot);
2580            cmdcur=cmdcur->next;
2581            break;
2582          }
2583        } else if (stcur->cmdno==CPUNTIL) {
2584          if (!nshell->status) {
2585            cmdcur=cmdcur->done;
2586            cmdstackrmlast(&stroot);
2587            cmdcur=cmdcur->next;
2588            break;
2589          }
2590        }
2591        cmdcur=cmdcur->next;
2592        break;
2593      case CPDONE:
2594        if ((stcur=cmdstackgetpo(&stroot))==NULL) goto errexit;
2595        cmdcur=stcur->cmd;
2596        cmdcur=cmdcur->next;
2597        break;
2598      case CPFN:
2599        if ((stcur=cmdstackcat(&stroot,CPFN))==NULL) goto errexit;
2600        prmcur=cmdcur->prm;
2601        stcur->val=prmcur->str;
2602        if (newfunc(nshell,prmcur->str)==NULL) goto errexit;
2603        cmdcur=cmdcur->next;
2604        break;
2605      case CPBI:
2606        if ((st=cmdstackgetpo(&stroot))==NULL) goto errexit;
2607        if ((stcur=cmdstackcat(&stroot,CPBI))==NULL) goto errexit;
2608        stcur->val=st->val;
2609        stcur->cmd=cmdcur->done;
2610        cmdcur=cmdcur->next;
2611        break;
2612      case CPBO:
2613        cmdstackrmlast(&stroot);
2614        cmdstackrmlast(&stroot);
2615        cmdcur=cmdcur->next;
2616        break;
2617 
2618      case CPNO:
2619 
2620        prmnewroot=NULL;
2621        prmprev=NULL;
2622        prmcur=cmdcur->prm;
2623        while (prmcur!=NULL) {
2624          if (prmcur->prmno!=PPSI2) {
2625            quote='\0';
2626            bquote='\0';
2627            if ((str=expand(nshell,prmcur->str,&quote,&bquote,FALSE))==NULL)
2628              goto errexit;
2629            if (quote || bquote) {
2630              memfree(str);
2631              sherror(ERRUEXPEOF);
2632              goto errexit;
2633            }
2634            prmcur->quoted=FALSE;
2635          } else {
2636            if ((str=memalloc(strlen(prmcur->str)+1))==NULL) goto errexit;
2637            strcpy(str,prmcur->str);
2638          }
2639          if ((prmcur->prmno!=PPNO) || (str[0]!='\0')) {
2640            if ((prm=memalloc(sizeof(struct prmlist)))==NULL) goto errexit;
2641            if (prmprev==NULL) prmnewroot=prm;
2642            else prmprev->next=prm;
2643            prm->next=NULL;
2644            prm->prmno=prmcur->prmno;
2645            prm->quoted=prmcur->quoted;
2646            if (prmcur->prmno!=PPSI2) {
2647              if ((prm->str=fnexpand(nshell,str))==NULL) goto errexit;
2648              if (prm->prmno==PPNO) {
2649                if ((num=wordsplit(prm))==-1) goto errexit;
2650                for (j=0;j<num;j++) {
2651                  prmprev=prm;
2652                  prm->prmno=PPNO;
2653                  prm=prm->next;
2654                }
2655              } else {
2656                wordunsplit(prm->str);
2657                prmprev=prm;
2658              }
2659            } else {
2660              prm->str=str;
2661              prmprev=prm;
2662            }
2663          } else memfree(str);
2664          prmcur=prmcur->next;
2665        }
2666 
2667        /* remove null parameter & check redirect and pipe */
2668        istdout=istdin=PPNO;
2669        pipef=FALSE;
2670        prmcur=prmnewroot;
2671        prmprev=NULL;
2672        pnum=0;
2673        while (prmcur!=NULL) {
2674          if (prmcur->str==NULL) {
2675            if (prmprev==NULL) prmnewroot=prmcur->next;
2676            else prmprev->next=prmcur->next;
2677            prm=prmcur;
2678            prmcur=prmcur->next;
2679            memfree(prm->str);
2680            memfree(prm);
2681          } else if ((prmcur->prmno==PPSI1) || (prmcur->prmno==PPSI2)
2682                  || (prmcur->prmno==PPSO1) || (prmcur->prmno==PPSO2)) {
2683            if (prmprev==NULL) prmnewroot=prmcur->next;
2684            else prmprev->next=prmcur->next;
2685            prm=prmcur;
2686            prmcur=prmcur->next;
2687            memfree(prm->str);
2688            memfree(prm);
2689            switch (prmcur->prmno) {
2690            case PPSI1:
2691              memfree(fstdin);
2692              fstdin=prmcur->str;
2693              istdin=PPSI1;
2694              break;
2695            case PPSI2:
2696              memfree(fstdin);
2697              fstdin=prmcur->str;
2698              istdin=PPSI2;
2699              quoted=prmcur->quoted;
2700              break;
2701            case PPSO1:
2702              memfree(fstdout);
2703              fstdout=prmcur->str;
2704              istdout=PPSO1;
2705              break;
2706            case PPSO2:
2707              memfree(fstdout);
2708              fstdout=prmcur->str;
2709              istdout=PPSO2;
2710              break;
2711            }
2712            if (prmprev==NULL) prmnewroot=prmcur->next;
2713            else prmprev->next=prmcur->next;
2714            prm=prmcur;
2715            prmcur=prmcur->next;
2716            memfree(prm);
2717          } else if (prmcur->prmno==PPPIPE) {
2718            pipef=TRUE;
2719            if (prmprev==NULL) prmnewroot=prmcur->next;
2720            else prmprev->next=prmcur->next;
2721            prm=prmcur;
2722            prmcur=prmcur->next;
2723            memfree(prm->str);
2724            memfree(prm);
2725          } else if (prmcur->prmno==PPEND) {
2726            if (prmprev==NULL) prmnewroot=prmcur->next;
2727            else prmprev->next=prmcur->next;
2728            prm=prmcur;
2729            prmcur=prmcur->next;
2730            memfree(prm->str);
2731            memfree(prm);
2732          } else if ((prmcur->prmno!=PPSETV) && (prmcur->prmno!=PPSETO)) {
2733            pnum++;
2734            prmprev=prmcur;
2735            prmcur=prmcur->next;
2736          } else {
2737            prmprev=prmcur;
2738            prmcur=prmcur->next;
2739          }
2740        }
2741 
2742        /* set variable */
2743        prmcur=prmnewroot;
2744        prmprev=NULL;
2745        while (prmcur!=NULL) {
2746          if (prmcur->prmno==PPSETV) {
2747            po=strchr(prmcur->str,'=');
2748            if ((name=memalloc(po-prmcur->str+1))==NULL) goto errexit;
2749            strncpy(name,prmcur->str,po-prmcur->str);
2750            name[po-prmcur->str]='\0';
2751            if ((val=memalloc(strlen(prmcur->str)-(po-prmcur->str)))==NULL) {
2752              memfree(name);
2753              goto errexit;
2754            }
2755            strcpy(val,po+1);
2756            if (pnum==0) po=addval(nshell,name,val);
2757            else po=saveval(nshell,name,val,&newvalroot);
2758            memfree(name);
2759            memfree(val);
2760            if (po==NULL) goto errexit;
2761            memfree(prmcur->str);
2762            if (prmprev==NULL) prmnewroot=prmcur->next;
2763            else prmprev->next=prmcur->next;
2764            prm=prmcur;
2765            prmcur=prmcur->next;
2766            memfree(prm);
2767          } else if (prmcur->prmno==PPSETO) {
2768          /* set object */
2769            if (sputobj(prmcur->str)==-1) goto errexit;
2770            memfree(prmcur->str);
2771            if (prmprev==NULL) prmnewroot=prmcur->next;
2772            else prmprev->next=prmcur->next;
2773            prm=prmcur;
2774            prmcur=prmcur->next;
2775            memfree(prm);
2776          } else {
2777            prmprev=prmcur;
2778            prmcur=prmcur->next;
2779          }
2780        }
2781 
2782        prmcur=prmnewroot;
2783        if ((prmcur!=NULL) && (prmcur->prmno==PPNO)) {
2784 
2785          /* set environment variable */
2786          valcur=nshell->valroot;
2787          while (valcur!=NULL) {
2788            if (!valcur->func
2789            && (getexp(nshell,valcur->name) || valcur->arg ||
2790                (getenv(valcur->name)!=NULL))) {
2791              len=strlen(valcur->name);
2792              if (getexp(nshell,valcur->name) || valcur->arg) val=valcur->val;
2793              else val=getenv(valcur->name);
2794              if ((s=memalloc(len+strlen(val)+2))==NULL) goto errexit;
2795              strcpy(s,valcur->name);
2796              s[len]='=';
2797              strcpy(s+len+1,val);
2798              if (arg_add(&newenviron,s)==NULL) {
2799                memfree(s);
2800                goto errexit;
2801              }
2802            }
2803            valcur=valcur->next;
2804          }
2805 
2806          environ=mainenviron;
2807          mainenviron=(char **)newenviron;
2808          newenviron=NULL;
2809          sout=sin=NOHANDLE;
2810          if (istdin!=PPNO) {
2811            if (istdin==PPSI1) sin=nopen(fstdin,O_RDONLY,NFMODE);
2812            else if (istdin==PPSI2) {
2813              sin=nopen(fstdin,O_RDONLY,NFMODE);
2814              if (!quoted) {
2815                if ((tmpfil2=tempnam(getval(nshell,"TMPDIR"),TEMPPFX))==NULL) {
2816                  nclose(sin);
2817                  goto errexit;
2818                }
2819                fd=nopen(tmpfil2,O_CREAT | O_TRUNC | O_RDWR,NFMODE);
2820                do {
2821                  if ((s=nstrnew())==NULL) {
2822                    nclose(sin);
2823                    nclose(fd);
2824                    goto errexit;
2825                  }
2826                  do {
2827                    if (nread(sin,buf,1)>0) ch=buf[0];
2828                    else ch=EOF;
2829                    if (ch==EOF) break;
2830                    else {
2831                      if (ch=='\n') ch='\0';
2832                      if ((s=nstrccat(s,ch))==NULL) {
2833                        nclose(sin);
2834                        nclose(fd);
2835                        goto errexit;
2836                      }
2837                    }
2838                  } while (ch!='\0');
2839                  quote=bquote='\0';
2840                  str=s;
2841                  s=expand(nshell,str,&quote,&bquote,FALSE);
2842                  memfree(str);
2843                  if (s==NULL) {
2844                    nclose(sin);
2845                    nclose(fd);
2846                    goto errexit;
2847                  }
2848                  wordunsplit(s);
2849                  len=strlen(s);
2850                  if (ch!=EOF) {
2851                    s[len]='\n';
2852                    len++;
2853                  }
2854                  nwrite(fd,s,len);
2855                  memfree(s);
2856                } while (ch!=EOF);
2857                nclose(sin);
2858                nclose(fd);
2859                sin=nopen(tmpfil2,O_RDONLY,NFMODE);
2860              }
2861            }
2862          } else if (cmdcur->pipefile!=NULL) {
2863            sin=nopen(cmdcur->pipefile,O_RDONLY,NFMODE);
2864          }
2865          if (sin!=NOHANDLE) sin2=nredirect(0,sin);
2866 
2867          /* redirect : stdout */
2868          if (istdout!=PPNO) {
2869            if (security) {
2870              sherror(ERRSECURITY);
2871              goto errexit;
2872            }
2873            if (istdout==PPSO2)
2874              sout=nopen(fstdout,O_APPEND|O_CREAT|O_WRONLY,NFMODE);
2875            else sout=nopen(fstdout,O_CREAT|O_WRONLY|O_TRUNC,NFMODE);
2876          /* pipe */
2877          } else if (pipef) {
2878            if ((sys=getobject("system"))==NULL) goto errexit;
2879            if ((tmpfil=tempnam(getval(nshell,"TMPDIR"),TEMPPFX))==NULL)
2880              goto errexit;
2881            sout=nopen(tmpfil,O_CREAT | O_TRUNC | O_RDWR,NFMODE);
2882            unlinkfile(&((cmdcur->next)->pipefile));
2883            (cmdcur->next)->pipefile=tmpfil;
2884          }
2885          if (sout!=NOHANDLE) sout2=nredirect(1,sout);
2886 
2887          if (nshell->optionx) {
2888            for (i=0;i<nshell->cmdexec;i++) printfconsole("+");
2889            printfconsole(" ");
2890            prm=prmcur;
2891            while (prm!=NULL) {
2892              printfconsole("%.256s ",prm->str);
2893              prm=prm->next;
2894            }
2895            printfconsole("\n");
2896          }
2897 
2898          cmds=prmcur->str;
2899          /* exec named function */
2900          if ((cmdnew=getfunc(nshell,cmds))!=NULL) {
2901            needcmd=FALSE;
2902            st=NULL;
2903            rcode=syntax(nshell,cmdnew,&needcmd,&st);
2904            cmdstackfree(st);
2905            if ((rcode!=0) || (st!=NULL) || (needcmd)) goto errexit;
2906            argvnew=NULL;
2907            if ((s=memalloc(strlen((nshell->argv)[0])+1))==NULL)
2908              goto errexit;
2909            strcpy(s,(nshell->argv)[0]);
2910            if (arg_add(&argvnew,s)==NULL) {
2911              memfree(s);
2912              arg_del(argvnew);
2913              goto errexit;
2914            }
2915            prmcur=prmcur->next;
2916            while (prmcur!=NULL) {
2917              if ((s=memalloc(strlen(prmcur->str)+1))==NULL) {
2918                memfree(s);
2919                arg_del(argvnew);
2920                goto errexit;
2921              }
2922              strcpy(s,prmcur->str);
2923              if (arg_add(&argvnew,s)==NULL) {
2924                memfree(s);
2925                arg_del(argvnew);
2926                goto errexit;
2927              }
2928              prmcur=prmcur->next;
2929            }
2930            argcnew=getargc(argvnew);
2931            argcsave=nshell->argc;
2932            argvsave=nshell->argv;
2933            nshell->argc=argcnew;
2934            nshell->argv=argvnew;
2935            rcode=cmdexec(nshell,cmdnew,TRUE);
2936            arg_del(nshell->argv);
2937            nshell->argc=argcsave;
2938            nshell->argv=argvsave;
2939            if ((rcode==-1) || (rcode==1)) goto errexit;
2940          /* exec special command */
2941          /* . */
2942          } else if (strcmp0(".",cmds)==0) {
2943            prmcur=prmcur->next;
2944            if (prmcur!=NULL) {
2945              cmdname=nsearchpath(getval(nshell,"PATH"),prmcur->str,TRUE);
2946              if (cmdname!=NULL) {
2947                argvnew=NULL;
2948                if ((s=memalloc(strlen((nshell->argv)[0])+1))==NULL)
2949                  goto errexit;
2950                strcpy(s,(nshell->argv)[0]);
2951                if (arg_add(&argvnew,s)==NULL) {
2952                  memfree(s);
2953                  arg_del(argvnew);
2954                  goto errexit;
2955                }
2956                prmcur=prmcur->next;
2957                while (prmcur!=NULL) {
2958                  if ((s=memalloc(strlen(prmcur->str)+1))==NULL) {
2959                    memfree(s);
2960                    arg_del(argvnew);
2961                    goto errexit;
2962                  }
2963                  strcpy(s,prmcur->str);
2964                  if (arg_add(&argvnew,s)==NULL) {
2965                    memfree(s);
2966                    arg_del(argvnew);
2967                    goto errexit;
2968                  }
2969                  prmcur=prmcur->next;
2970                }
2971                argcnew=getargc(argvnew);
2972 
2973                sin=nopen(cmdname,O_RDONLY,NFMODE);
2974                memfree(cmdname);
2975                cmdname=NULL;
2976                if (sin==NOHANDLE) {
2977                  sherror2(ERROPEN,cmdname);
2978                  arg_del(argvnew);
2979                  goto errexit;
2980                }
2981                argcsave=nshell->argc;
2982                argvsave=nshell->argv;
2983                nshell->argc=argcnew;
2984                nshell->argv=argvnew;
2985                sin3=storeshhandle(nshell,sin,&readbuf,&readbyte,&readpo);
2986                rcode=cmdexecute(nshell,NULL);
2987                restoreshhandle(nshell,sin3,readbuf,readbyte,readpo);
2988                nclose(sin);
2989                arg_del(nshell->argv);
2990                nshell->argc=argcsave;
2991                nshell->argv=argvsave;
2992                if ((rcode!=0) && (rcode!=1)) goto errexit;
2993              } else {
2994                sherror2(ERRNOFIL,prmcur->str);
2995                goto errexit;
2996              }
2997            }
2998          /* break */
2999          } else if (strcmp0("break",cmds)==0) {
3000            if (pnum>2) {
3001              sherror(ERREXTARG);
3002              goto errexit;
3003            } else if (pnum==2) {
3004              arg=(prmcur->next)->str;
3005              a=strtol(arg,&endptr,10);
3006              if (endptr[0]!='\0') {
3007                sherror2(ERRNUMERIC,arg);
3008                goto errexit;
3009              }
3010            } else a=1;
3011            looplevel=0;
3012            stcur=stroot;
3013            while (stcur!=NULL) {
3014              if ((stcur->cmdno==CPFOR) || (stcur->cmdno==CPWHILE)
3015               || (stcur->cmdno==CPUNTIL)) looplevel++;
3016              stcur=stcur->next;
3017            }
3018            if (looplevel!=0) {
3019              while (a>0) {
3020                if ((stcur=cmdstackgetpo(&stroot))==NULL) break;
3021                if ((stcur->cmdno==CPFOR) && (stcur->ival==-1)) {
3022                  prmfree(stcur->prm);
3023                  stcur->prm=NULL;
3024                }
3025                if ((stcur->cmdno==CPFOR) || (stcur->cmdno==CPWHILE)
3026                 || (stcur->cmdno==CPUNTIL)) {
3027                  cmdcur=stcur->cmd;
3028                  while (cmdcur->cmdno!=CPDO) cmdcur=cmdcur->next;
3029                  cmdcur=cmdcur->done;
3030                  cmdstackrmlast(&stroot);
3031                  a--;
3032 	       } else cmdstackrmlast(&stroot);
3033 	     }
3034            }
3035          /* continue */
3036          } else if (strcmp0("continue",cmds)==0) {
3037            if (pnum>2) {
3038              sherror(ERREXTARG);
3039              goto errexit;
3040            } else if (pnum==2) {
3041              arg=(prmcur->next)->str;
3042              a=strtol(arg,&endptr,10);
3043              if (endptr[0]!='\0') {
3044                sherror2(ERRNUMERIC,arg);
3045                goto errexit;
3046              }
3047            } else a=1;
3048            looplevel=0;
3049            stcur=stroot;
3050            while (stcur!=NULL) {
3051              if ((stcur->cmdno==CPFOR) || (stcur->cmdno==CPWHILE)
3052               || (stcur->cmdno==CPUNTIL)) looplevel++;
3053              stcur=stcur->next;
3054            }
3055            if (looplevel!=0) {
3056              while (a>0) {
3057                if ((stcur=cmdstackgetpo(&stroot))==NULL) break;
3058                if ((stcur->cmdno==CPFOR) || (stcur->cmdno==CPWHILE)
3059                 || (stcur->cmdno==CPUNTIL)) {
3060                  cmdcur=stcur->cmd;
3061                  a--;
3062                  if (a>0) {
3063                    if ((stcur->cmdno==CPFOR) && (stcur->ival==-1)) {
3064                      prmfree(stcur->prm);
3065                      stcur->prm=NULL;
3066                    }
3067                    cmdstackrmlast(&stroot);
3068                  }
3069                } else cmdstackrmlast(&stroot);
3070              }
3071            }
3072          /* return */
3073          } else if (strcmp0("return",cmds)==0) {
3074            if (pnum>2) {
3075              sherror(ERREXTARG);
3076              goto errexit;
3077            } else if (pnum==2) {
3078              arg=(prmcur->next)->str;
3079              a=strtol(arg,&endptr,10);
3080              if (endptr[0]!='\0') {
3081                sherror2(ERRNUMERIC,arg);
3082                goto errexit;
3083              }
3084              nshell->status=a;
3085            }
3086            if (namedfunc) {
3087              err=0;
3088              goto errexit;
3089            }
3090          /* execute object */
3091          } else if (isobject(&cmds)) {
3092            len=0;
3093            prm=prmcur;
3094            while (prm!=NULL) {
3095              len+=strlen(prm->str)+1;
3096              prm=prm->next;
3097            }
3098            if ((str=memalloc(len))==NULL) goto errexit;
3099            str[0]='\0';
3100            prm=prmcur;
3101            while (prm!=NULL) {
3102              strcat(str,prm->str);
3103              if (prm->next!=NULL) strcat(str," ");
3104              prm=prm->next;
3105            }
3106            errlevel=sexeobj(str);
3107            memfree(str);
3108            if (errlevel==-1) goto errexit;
3109            nshell->status=errlevel;
3110            nshell->status=errlevel;
3111            lastc=cmdstackgetlast(&stroot);
3112            if ((lastc!=CPIF) && (lastc!=CPELIF)
3113             && (lastc!=CPWHILE) && (lastc!=CPUNTIL)
3114             && (nshell->optione) && (errlevel!=0)) {
3115              err=3;
3116              goto errexit;
3117            }
3118            nshell->status=errlevel;
3119            lastc=cmdstackgetlast(&stroot);
3120            if ((lastc!=CPIF) && (lastc!=CPELIF)
3121             && (lastc!=CPWHILE) && (lastc!=CPUNTIL)
3122             && (nshell->optione) && (errlevel!=0)) {
3123              err=3;
3124              goto errexit;
3125            }
3126            if (nshell->quit) break;
3127            if (nshell->quit) break;
3128          /* exec inner command */
3129          } else {
3130            for (i=0;i<CMDNUM;i++)
3131              if (strcmp0(prmcur->str,cmdtable[i].name)==0) break;
3132            if (i!=CMDNUM) {
3133              if (cmdtable[i].proc!=NULL) {
3134                argv=NULL;
3135                if (arg_add(&argv,NULL)==NULL) goto errexit;
3136                prm=prmnewroot;
3137                while (prm!=NULL) {
3138                  if (arg_add(&argv,prm->str)==NULL) {
3139                    memfree(argv);
3140                    goto errexit;
3141                  }
3142                  prm=prm->next;
3143                }
3144                errlevel=cmdtable[i].proc(nshell,pnum,(char **)argv);
3145                memfree(argv);
3146              } else errlevel=0;
3147            } else {
3148              cmdname=nsearchpath(getval(nshell,"PATH"),prmcur->str,FALSE);
3149              if (cmdname==NULL) {
3150                sherror2(ERRCFOUND,prmcur->str);
3151                goto errexit;
3152              } else {
3153                if (security) {
3154                  sherror(ERRSECURITY);
3155                  goto errexit;
3156                }
3157                argv=NULL;
3158                if (arg_add(&argv,NULL)==NULL) goto errexit;
3159                prm=prmnewroot;
3160                while (prm!=NULL) {
3161                  if (arg_add(&argv,prm->str)==NULL) {
3162                    memfree(argv);
3163                    goto errexit;
3164                  }
3165                  prm=prm->next;
3166                }
3167 #ifndef WINDOWS
3168                if ((pid=fork())<0) {
3169                  sherror2(ERRSYSTEM,"fork");
3170                  goto errexit;
3171                }
3172                if (pid==0) {
3173                  errlevel=execve(cmdname,(char **)argv,mainenviron);
3174                  printfstderr("shell: %.64s: %.64s",
3175                               argv[0],strerror(errno));
3176                  exit(errlevel);
3177                } else {
3178                  while (waitpid(pid,&errlevel,WNOHANG)==0) eventloop();
3179                }
3180 #else
3181                pid=spawnve(P_NOWAIT,cmdname,(char **)argv,mainenviron);
3182                if (pid==-1)
3183                  printfstderr("shell: %.64s: %.64s",
3184                               argv[0],strerror(errno));
3185                else {
3186                  WP.pid=pid;
3187                  WP.done=FALSE;
3188                  CreateThread(NULL,0,WaitPidThread,&WP,0,&IDThread);
3189                  while (waitpid(&WP)!=pid) eventloop();
3190                  errlevel=WP.errlevel;
3191                  errlevel=errlevel >>8;
3192                  nsetconsolemode();
3193                }
3194 #endif
3195                memfree(argv);
3196                memfree(cmdname);
3197                cmdname=NULL;
3198              }
3199            }
3200            nshell->status=errlevel;
3201            lastc=cmdstackgetlast(&stroot);
3202            if ((lastc!=CPIF) && (lastc!=CPELIF)
3203             && (lastc!=CPWHILE) && (lastc!=CPUNTIL)
3204             && (nshell->optione) && (errlevel!=0)) {
3205              err=3;
3206              goto errexit;
3207            }
3208            if (nshell->quit) break;
3209          }
3210 
3211          if (sout2!=NOHANDLE) {
3212            nredirect2(1,sout2);
3213            sout2=NOHANDLE;
3214          }
3215          if (sin2!=NOHANDLE) {
3216            nredirect2(0,sin2);
3217            sin2=NOHANDLE;
3218          }
3219          unlinkfile(&tmpfil2);
3220          arg_del(mainenviron);
3221          mainenviron=environ;
3222          environ=NULL;
3223        }
3224        restoreval(nshell,newvalroot);
3225        newvalroot=NULL;
3226 
3227        prmfree(prmnewroot);
3228        prmnewroot=NULL;
3229        memfree(fstdout);
3230        memfree(fstdin);
3231        fstdout=fstdin=NULL;
3232        unlinkfile(&(cmdcur->pipefile));
3233        cmdcur=cmdcur->next;
3234        break;
3235      default:
3236 
3237        unlinkfile(&(cmdcur->pipefile));
3238        cmdcur=cmdcur->next;
3239        break;
3240      }
3241    }
3242    err=0;
3243 
3244 errexit:
3245   cmdstackfree(stroot);
3246   prmfree(prmnewroot);
3247   memfree(fstdout);
3248   memfree(fstdin);
3249   memfree(cmdname);
3250   arg_del(newenviron);
3251   if (environ!=NULL) {
3252     arg_del(mainenviron);
3253     mainenviron=environ;
3254   }
3255   if (newvalroot!=NULL) restoreval(nshell,newvalroot);
3256   if (sout2!=NOHANDLE) nredirect2(1,sout2);
3257   if (sin2!=NOHANDLE) nredirect2(0,sin2);
3258   unlinkfile(&tmpfil2);
3259   cmdcur=cmdroot;
3260   while (cmdcur!=NULL) {
3261     prmcur=cmdcur->prm;
3262     while (prmcur!=NULL) {
3263       if ((prmcur->prmno==PPSI2) && (prmcur->next!=NULL)
3264       && ((prmcur->next)->str!=NULL)) {
3265         unlink((prmcur->next)->str);
3266         prmcur=prmcur->next;
3267       }
3268       prmcur=prmcur->next;
3269     }
3270     unlinkfile(&(cmdcur->pipefile));
3271     cmdcur=cmdcur->next;
3272   }
3273   nshell->cmdexec--;
3274   return err;
3275 }
3276 
cmdexecute(struct nshell * nshell,char * cline)3277 int cmdexecute(struct nshell *nshell,char *cline)
3278 /* return
3279      -2: unexpected eof detected
3280      -1: fatal error
3281       0: no error
3282       1: eof detected
3283       2: syntax error
3284       3: runtime error  */
3285 {
3286   struct cmdlist *cmdroot,*cmdcur,*cmdnew;
3287   struct cmdstack *stroot;
3288   int needcmd,rcode;
3289   int istr;
3290 
3291   istr=0;
3292   nshell->quit=FALSE;
3293   while (TRUE) {
3294     needcmd=FALSE;
3295     cmdroot=NULL;
3296     cmdcur=cmdroot;
3297     cmdnew=NULL;
3298     stroot=NULL;
3299     do {
3300       if ((rcode=getcmdline(nshell,&cmdnew,cmdroot,cline,&istr))!=0) break;
3301       if ((rcode=checkcmd(nshell,&cmdnew))!=0) break;
3302       if ((rcode=syntax(nshell,cmdnew,&needcmd,&stroot))!=0) break;
3303       if (cmdnew!=NULL) {
3304         if (cmdcur==NULL) cmdroot=cmdnew;
3305         else cmdcur->next=cmdnew;
3306         cmdcur=cmdnew;
3307         while (cmdcur->next!=NULL) cmdcur=cmdcur->next;
3308         cmdnew=NULL;
3309       }
3310     } while ((stroot!=NULL) || (needcmd));
3311     if (rcode!=0) {
3312       cmdfree(cmdnew);
3313       cmdfree(cmdroot);
3314       cmdstackfree(stroot);
3315       if (nshell->quit) rcode=0;
3316       break;
3317     } else if (cmdroot!=NULL) {
3318       rcode=cmdexec(nshell,cmdroot,FALSE);
3319       cmdfree(cmdroot);
3320       if (nshell->quit) {
3321         rcode=0;
3322         break;
3323       }
3324       if (rcode!=0) break;
3325     }
3326   }
3327   nshell->quit=FALSE;
3328   return rcode;
3329 }
3330 
setshhandle(struct nshell * nshell,HANDLE fd)3331 void setshhandle(struct nshell *nshell,HANDLE fd)
3332 {
3333   nshell->fd=fd;
3334   nshell->readbyte=0;
3335   nshell->readpo=0;
3336 }
3337 
storeshhandle(struct nshell * nshell,HANDLE fd,char ** readbuf,int * readbyte,int * readpo)3338 HANDLE storeshhandle(struct nshell *nshell,HANDLE fd,
3339                      char **readbuf,int *readbyte,int *readpo)
3340 {
3341   HANDLE sfd;
3342 
3343   sfd=nshell->fd;
3344   *readbuf=nshell->readbuf;
3345   *readbyte=nshell->readbyte;
3346   *readpo=nshell->readpo;
3347   nshell->readbuf=memalloc(SHELLBUFSIZE);
3348   nshell->readbyte=0;
3349   nshell->readpo=0;
3350   nshell->fd=fd;
3351   return sfd;
3352 }
3353 
restoreshhandle(struct nshell * nshell,HANDLE fd,char * readbuf,int readbyte,int readpo)3354 void restoreshhandle(struct nshell *nshell,HANDLE fd,
3355                      char *readbuf,int readbyte,int readpo)
3356 {
3357   memfree(nshell->readbuf);
3358   nshell->fd=fd;
3359   nshell->readbuf=readbuf;
3360   nshell->readbyte=readbyte;
3361   nshell->readpo=readpo;
3362 }
3363 
3364 
getshhandle(struct nshell * nshell)3365 HANDLE getshhandle(struct nshell *nshell)
3366 {
3367   return nshell->fd;
3368 }
3369 
newshell()3370 struct nshell *newshell()
3371 {
3372   struct nshell *nshell;
3373   char *name,**env,*tok;
3374   int i,len;
3375 
3376   if ((nshell=memalloc(sizeof(struct nshell)))==NULL) return NULL;
3377   nshell->valroot=NULL;
3378   nshell->exproot=NULL;
3379   env=mainenviron;
3380   i=0;
3381   while (env[i]!=NULL) {
3382     tok=env[i];
3383     name=getitok2(&tok,&len,"=");
3384     if (tok[0]=='=') tok++;
3385     if (addval(nshell,name,tok)==NULL) {
3386       memfree(name);
3387       delshell(nshell);
3388       return NULL;
3389     }
3390     memfree(name);
3391     i++;
3392   }
3393   if ((getval(nshell,"PATH")==NULL) && (getenv("Path")!=NULL)) {
3394     addval(nshell,"PATH",getenv("Path"));
3395   }
3396   nshell->argc=0;
3397   nshell->argv=NULL;
3398   nshell->cmdexec=0;
3399   nshell->status=0;
3400   nshell->quit=0;
3401   nshell->fd=stdinfd();
3402   nshell->options=TRUE;
3403   nshell->optionf=FALSE;
3404   nshell->optione=TRUE;
3405   nshell->optionv=FALSE;
3406   nshell->optionx=FALSE;
3407   nshell->readbuf=memalloc(SHELLBUFSIZE);
3408   nshell->readbyte=0;
3409   nshell->readpo=0;
3410   return nshell;
3411 }
3412 
delshell(struct nshell * nshell)3413 void delshell(struct nshell *nshell)
3414 {
3415   struct vallist *valcur,*valdel;
3416   struct explist *expcur,*expdel;
3417 
3418   if (nshell==NULL) return;
3419   valcur=nshell->valroot;
3420   while (valcur!=NULL) {
3421     memfree(valcur->name);
3422     if (valcur->func) cmdfree(valcur->val);
3423     else memfree(valcur->val);
3424     valdel=valcur;
3425     valcur=valcur->next;
3426     memfree(valdel);
3427   }
3428   expcur=nshell->exproot;
3429   while (expcur!=NULL) {
3430     memfree(expcur->val);
3431     expdel=expcur;
3432     expcur=expcur->next;
3433     memfree(expdel);
3434   }
3435   arg_del(nshell->argv);
3436   memfree(nshell->readbuf);
3437   memfree(nshell);
3438   return;
3439 }
3440 
sherror(int code)3441 void sherror(int code)
3442 {
3443   printfstderr("shell: %.64s\n",cmderrorlist[code-100]);
3444 }
3445 
sherror2(int code,char * mes)3446 void sherror2(int code,char *mes)
3447 {
3448   if (mes!=NULL) {
3449     printfstderr("shell: %.64s `%.64s'.\n",cmderrorlist[code-100],mes);
3450   } else {
3451     printfstderr("shell: %.64s.\n",cmderrorlist[code-100]);
3452   }
3453 }
3454 
sherror3(char * cmd,int code,char * mes)3455 void sherror3(char *cmd,int code,char *mes)
3456 {
3457   if (cmd==NULL) cmd="";
3458   if (mes!=NULL) {
3459     printfstderr("shell: %.64s: %.64s `%.64s'.\n",
3460                    cmd,cmderrorlist[code-100],mes);
3461   } else {
3462     printfstderr("shell: %.64s: %.64s.\n",cmd,cmderrorlist[code-100]);
3463   }
3464 }
3465 
sherror4(char * cmd,int code)3466 void sherror4(char *cmd,int code)
3467 {
3468   if (cmd==NULL) cmd="";
3469   printfstderr("shell: %.64s: %.64s\n",cmd,cmderrorlist[code-100]);
3470 }
3471 
shellsavestdio(struct nshell * nshell)3472 void shellsavestdio(struct nshell *nshell)
3473 {
3474   nshell->sgetstdin=getstdin;
3475   nshell->sputstdout=putstdout;
3476   nshell->sprintfstdout=printfstdout;
3477   getstdin=shgetstdin;
3478   putstdout=shputstdout;
3479   printfstdout=shprintfstdout;
3480 }
3481 
shellrestorestdio(struct nshell * nshell)3482 void shellrestorestdio(struct nshell *nshell)
3483 {
3484   getstdin=nshell->sgetstdin;
3485   putstdout=nshell->sputstdout;
3486   printfstdout=nshell->sprintfstdout;
3487 }
3488 
setshelloption(struct nshell * nshell,char * opt)3489 int setshelloption(struct nshell *nshell,char *opt)
3490 {
3491   int flag;
3492 
3493   if ((opt[0]!='-') && (opt[0]!='+')) return 1;
3494   if (opt[0]=='-') flag=TRUE;
3495   else flag=FALSE;
3496   switch (opt[1]) {
3497   case 's':
3498     nshell->options=flag;
3499     break;
3500   case 'e':
3501     nshell->optione=flag;
3502     break;
3503   case 'v':
3504     nshell->optionv=flag;
3505     break;
3506   case 'x':
3507     nshell->optionx=flag;
3508     break;
3509   case 'f':
3510     nshell->optionf=flag;
3511     break;
3512   default:
3513     sherror2(ERRILOPS,opt);
3514     return -1;
3515   }
3516   return 0;
3517 }
3518 
getshelloption(struct nshell * nshell,char opt)3519 int getshelloption(struct nshell *nshell,char opt)
3520 {
3521   switch (opt) {
3522   case 's':
3523     return nshell->options;
3524   case 'e':
3525     return nshell->optione;
3526   case 'v':
3527     return nshell->optionv;
3528   case 'x':
3529     return nshell->optionx;
3530   case 'f':
3531     return nshell->optionf;
3532   default:
3533     break;
3534   }
3535   return 0;
3536 }
3537 
setshellargument(struct nshell * nshell,int argc,char ** argv)3538 void setshellargument(struct nshell *nshell,int argc,char **argv)
3539 {
3540   arg_del(nshell->argv);
3541   nshell->argc=argc;
3542   nshell->argv=argv;
3543 }
3544 
ngraphenvironment(struct nshell * nshell)3545 void ngraphenvironment(struct nshell *nshell)
3546 {
3547   char *sver,*lib,*home;
3548   struct objlist *sobj;
3549   char *systemname;
3550   char *pathset;
3551 
3552   sobj=chkobject("system");
3553   getobj(sobj,"name",0,0,NULL,&systemname);
3554   getobj(sobj,"lib_dir",0,0,NULL,&lib);
3555   getobj(sobj,"home_dir",0,0,NULL,&home);
3556   sver=getobjver("system");
3557   addval(nshell,"NGRAPH",systemname);
3558   addval(nshell,"VERSION",sver);
3559   addval(nshell,"NGRAPHLIB",lib);
3560   addval(nshell,"NGRAPHHOME",home);
3561   if (getval(nshell,"PS1")==NULL) addval(nshell,"PS1","Ngraph$ ");
3562   if (getval(nshell,"PS2")==NULL) addval(nshell,"PS2",">");
3563   if (getval(nshell,"IFS")==NULL) addval(nshell,"IFS"," \t\n");
3564   if (getval(nshell,"IGNOREEOF")==NULL) addval(nshell,"IGNOREEOF","10");
3565   pathset="PATH=$NGRAPHLIB\\"PATHSEP".\\"PATHSEP"$PATH";
3566   cmdexecute(nshell,pathset);
3567 }
3568 
3569