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,"e,&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,"e2,&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,"e2,&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,"e2,&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,"e2,&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,"e2,&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,"e2,&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,"ed))==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,"e,&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,"e,&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,"e,&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,"e,&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