7 /* -------- sh.c -------- */
16 char flags
['z'-'a'+1];
17 char *flag
= flags
-'a';
18 char *elinep
= line
+sizeof(line
)-5;
21 struct env e
={line
, iostack
, iostack
-1,
22 (xint
*)NULL
, FDBASE
, (struct env
*)NULL
};
24 extern char **environ
; /* environment pointer */
27 * default shell, search rules
29 char shellname
[] = "/bin/sh";
30 char search
[] = ":/bin:/usr/bin";
32 _PROTOTYPE(void (*qflag
), (int)) = SIG_IGN
;
34 _PROTOTYPE(int main
, (int argc
, char **argv
));
35 _PROTOTYPE(int newfile
, (char *s
));
36 _PROTOTYPE(static char *findeq
, (char *cp
));
37 _PROTOTYPE(static char *cclass
, (char *p
, int sub
));
38 _PROTOTYPE(void initarea
, (void));
51 if ((ap
= environ
) != NULL
) {
53 assign(*ap
++, !COPYV
);
54 for (ap
= environ
; *ap
;)
55 export(lookup(*ap
++));
60 shell
= lookup("SHELL");
61 if (shell
->value
== null
)
62 setval(shell
, shellname
);
65 homedir
= lookup("HOME");
66 if (homedir
->value
== null
)
70 setval(lookup("$"), itoa(getpid(), 5));
72 path
= lookup("PATH");
73 if (path
->value
== null
)
78 if (ifs
->value
== null
)
81 prompt
= lookup("PS1");
82 if (prompt
->value
== null
)
91 prompt
->status
&= ~EXPORT
;
93 cprompt
= lookup("PS2");
94 if (cprompt
->value
== null
)
95 setval(cprompt
, "> ");
101 if(argv
[0][0] == '-' && argv
[0][1] != '\0') {
102 for (s
= argv
[0]+1; *s
; s
++)
105 prompt
->status
&= ~EXPORT
;
106 cprompt
->status
&= ~EXPORT
;
111 PUSHIO(aword
, *++argv
, iof
= nlchar
);
123 prompt
->status
&= ~EXPORT
;
131 if (*s
>='a' && *s
<='z')
138 if (iof
== filechar
&& --argc
> 0) {
141 prompt
->status
&= ~EXPORT
;
142 cprompt
->status
&= ~EXPORT
;
143 if (newfile(name
= *++argv
))
148 if (e
.iop
< iostack
) {
149 PUSHIO(afile
, 0, iof
);
150 if (isatty(0) && isatty(1) && !cflag
)
153 signal(SIGQUIT
, qflag
);
154 if (name
&& name
[0] == '-') {
156 if ((f
= open(".profile", 0)) >= 0)
158 if ((f
= open("/etc/profile", 0)) >= 0)
162 signal(SIGTERM
, sig
);
163 if (signal(SIGINT
, SIG_IGN
) != SIG_IGN
)
164 signal(SIGINT
, onintr
);
169 for (ap
= ++argv
; --argc
> 0;)
170 if (assign(*ap
= *argv
++, !COPYV
))
171 dolc
--; /* keyword */
174 setval(lookup("#"), putn((--dolc
< 0) ? (dolc
= 0) : dolc
));
177 if (talking
&& e
.iop
<= iostack
)
186 register char *cp
, c
;
190 for (c
='a'; c
<='z'; c
++)
194 setval(lookup("-"), m
);
203 if (strcmp(s
, "-") != 0) {
207 err(": cannot open");
237 setjmp(failpt
= m1
); /* Bruce Evans' fix */
238 if (setjmp(failpt
= m1
) || yyparse() || intr
) {
242 if (!talking
&& intr
)
253 execute(outtree
, NOPIPE
, NOPIPE
, 0);
254 if (!talking
&& intr
) {
258 if ((i
= trapset
) != 0) {
308 e
.iop
= e
.iobase
= iostack
;
315 register struct env
*ep
;
321 ep
= (struct env
*) space(sizeof(*ep
));
336 register struct env
*ep
;
339 if ((ep
= e
.oenv
) != NULL
) {
342 /* should close `'d files */
344 while (--fd
>= e
.iofd
)
350 * Is any character from s1 in s2?
354 register char *s1
, *s2
;
363 * Is character c in s?
393 if (n
< 0 && (int) u
< 0) {
402 } while (--n
> 0 || u
);
412 PUSHIO(afile
, f
, filechar
);
417 int s
; /* ANSI C requires a parameter */
419 signal(SIGINT
, onintr
);
437 return((c
>= 'a' && c
<= 'z') || (c
>= 'A' && c
<= 'Z') || c
== '_');
444 return(c
>= '0' && c
<= '9');
451 return(letter(c
) || digit(c
));
460 if ((cp
= getcell(n
)) == 0)
461 err("out of string space");
470 register char *cp
, *xp
;
472 if ((cp
= space(strlen(s
)+1)) != NULL
) {
473 setarea((char *)cp
, a
);
474 for (xp
= cp
; (*xp
++ = *s
++) != '\0';)
504 if ((trapstr
= trap
[i
]) == NULL
)
508 RUN(aword
, trapstr
, nlchar
);
511 /* -------- var.c -------- */
512 /* #include "sh.h" */
515 * Find the given name in the dictionary
516 * and return its value. If the name was
517 * not previously there, enter it now and
518 * return a null value.
524 register struct var
*vp
;
527 static struct var dummy
;
531 for (c
= 0; digit(*n
) && c
< 1000; n
++)
533 dummy
.status
= RONLY
;
534 dummy
.value
= c
<= dolc
? dolv
[c
]: null
;
537 for (vp
= vlist
; vp
; vp
= vp
->next
)
538 if (eqname(vp
->name
, n
))
541 vp
= (struct var
*)space(sizeof(*vp
));
542 if (vp
== 0 || (vp
->name
= space((int)(cp
-n
)+2)) == 0) {
543 dummy
.name
= dummy
.value
= "";
546 for (cp
= vp
->name
; (*cp
= *n
++) && *cp
!= '='; cp
++)
551 setarea((char *)vp
, 0);
552 setarea((char *)vp
->name
, 0);
555 vp
->status
= GETCELL
;
561 * give variable at `vp' the value `val'.
568 nameval(vp
, val
, (char *)NULL
);
572 * if name is not NULL, it must be
573 * a prefix of the space `val',
575 * this is all so that exporting
576 * values is reasonably painless.
579 nameval(vp
, val
, name
)
580 register struct var
*vp
;
583 register char *cp
, *xp
;
587 if (vp
->status
& RONLY
) {
588 for (xp
= vp
->name
; *xp
&& *xp
!= '=';)
590 err(" is read-only");
595 xp
= space(strlen(vp
->name
)+strlen(val
)+2);
598 /* make string: name=value */
599 setarea((char *)xp
, 0);
601 for (cp
= vp
->name
; (*xp
= *cp
++) && *xp
!='='; xp
++)
606 for (cp
= val
; (*xp
++ = *cp
++) != '\0';)
611 if (vp
->status
& GETCELL
)
612 xfree(vp
->name
); /* form new string `name=value' */
622 vp
->status
|= EXPORT
;
629 if (letter(vp
->name
[0])) /* not an internal symbol ($# etc) */
637 if (!letter((int)*s
))
639 for (; *s
!= '='; s
++)
640 if (*s
== 0 || !letnum(*s
))
655 for (cp
= s
; *cp
!= '='; cp
++)
656 if (*cp
== 0 || !letnum(*cp
))
659 nameval(vp
, ++cp
, cf
== COPYV
? (char *)NULL
: s
);
661 vp
->status
&= ~GETCELL
;
681 register struct var
*vp
;
683 for (vp
= vlist
; vp
; vp
= vp
->next
)
684 if (vp
->status
& f
&& letter(*vp
->name
)) {
685 if (vp
->status
& EXPORT
)
686 write(out
, "export ", 7);
687 if (vp
->status
& RONLY
)
688 write(out
, "readonly ", 9);
689 write(out
, vp
->name
, (int)(findeq(vp
->name
) - vp
->name
));
696 register char *n1
, *n2
;
698 for (; *n1
!= '=' && *n1
!= 0; n1
++)
701 return(*n2
== 0 || *n2
== '=');
708 while (*cp
!= '\0' && *cp
!= '=')
713 /* -------- gmatch.c -------- */
715 * int gmatch(string, pattern)
716 * char *string, *pattern;
718 * Match a pattern as in sh(1).
723 #define QMASK (CMASK&~QUOTE)
724 #define NOT '!' /* might use ^ */
728 register char *s
, *p
;
732 if (s
== NULL
|| p
== NULL
)
734 while ((pc
= *p
++ & CMASK
) != '\0') {
738 if ((p
= cclass(p
, sc
)) == NULL
)
750 if (*p
== '\0' || gmatch(s
, p
))
752 } while (*s
++ != '\0');
756 if (sc
!= (pc
&~QUOTE
))
768 register int c
, d
, not, found
;
770 if ((not = *p
== NOT
) != 0)
775 return((char *)NULL
);
777 if (p
[1] == '-' && p
[2] != ']') {
782 if (c
== sub
|| (c
<= sub
&& sub
<= d
))
784 } while (*++p
!= ']');
785 return(found
? p
+1: (char *)NULL
);
788 /* -------- area.c -------- */
789 #define REGSIZE sizeof(struct region)
794 #define ALIGN (sizeof(int)-1)
796 /* #include "area.h" */
804 * All memory between (char *)areabot and (char *)(areatop+1) is
805 * exclusively administered by the area management routines.
806 * It is assumed that sbrk() and brk() manipulate the high end.
808 static struct region
*areabot
; /* bottom of area */
809 static struct region
*areatop
; /* top of area */
810 static struct region
*areanxt
; /* starting point of scan */
815 while ((int)sbrk(0) & ALIGN
)
817 areabot
= (struct region
*)sbrk(REGSIZE
);
818 areabot
->next
= areabot
;
819 areabot
->area
= BUSY
;
829 register struct region
*p
, *q
;
833 abort(); /* silly and defeats the algorithm */
835 * round upwards and add administration area
837 nregio
= (nbytes
+(REGSIZE
-1))/REGSIZE
+ 1;
838 for (p
= areanxt
;;) {
839 if (p
->area
> areanum
) {
843 while ((q
= p
->next
)->area
> areanum
&& q
!= areanxt
)
846 * exit loop if cell big enough
855 i
= nregio
>= GROWBY
? nregio
: GROWBY
;
856 p
= (struct region
*)sbrk(i
* REGSIZE
);
857 if (p
== (struct region
*)-1)
858 return((char *)NULL
);
861 abort(); /* allocated areas are contiguous */
870 * we found a FREE area big enough, pointed to by 'p', and up to 'q'
872 areanxt
= p
+ nregio
;
875 * split into requested area and rest
878 abort(); /* insufficient space left for admin */
880 areanxt
->area
= FREE
;
884 return((char *)(p
+1));
891 register struct region
*p
;
893 if ((p
= (struct region
*)cp
) != NULL
) {
905 register struct region
*p
, *top
;
908 for (p
= areabot
; p
!= top
; p
= p
->next
)
918 register struct region
*p
;
920 if ((p
= (struct region
*)cp
) != NULL
)
928 return ((struct region
*)cp
-1)->area
;
934 register struct region
*p
, *q
, *top
;
937 for (p
= areabot
; p
!= top
; p
= p
->next
) {
938 if (p
->area
> areanum
) {
939 while ((q
= p
->next
)->area
> areanum
)
945 if (areatop
>= q
+ SHRINKBY
&& q
->area
> areanum
) {