|
|
1.1 root 1: /* shell.c - shell */
2:
3: #include <conf.h>
4: #include <kernel.h>
5: #include <proc.h>
6: #include <shell.h>
7: #include <cmd.h>
8: #include <tty.h>
9:
10: struct shvars Shl; /* globals used by Xinu shell */
11: struct cmdent cmds[] = {CMDS}; /* shell commands */
12: LOCAL char errhd[] = "Syntax error\n";/* global error messages */
13: LOCAL char fmt[] = "Cannot open %s\n";
14: LOCAL char fmt2[] = "[%d]\n";
15:
16: /*------------------------------------------------------------------------
17: * shell - Xinu shell with file redirection and background processing
18: *------------------------------------------------------------------------
19: */
20: shell(dev)
21: int dev;
22: {
23: int ntokens;
24: int i, j, len;
25: int com;
26: char *outnam, *innam;
27: int stdin, stdout, stderr;
28: Bool backgnd;
29: char ch, mach[SHMLEN];
30: int child;
31:
32: Shl.shncmds = sizeof(cmds)/sizeof(struct cmdent);
33: for (getname(mach) ; TRUE ; ) {
34: fprintf(dev, "%s %% ", mach);
35: getutim(&Shl.shlast);
36: if ( (len = read(dev, Shl.shbuf, SHBUFLEN)) == 0)
37: len = read(dev, Shl.shbuf, SHBUFLEN);
38: if (len == EOF)
39: break;
40: Shl.shbuf[len-1] = NULLCH;
41: if ( (ntokens=lexan(Shl.shbuf)) == SYSERR) {
42: fprintf(dev, errhd);
43: continue;
44: } else if (ntokens == 0)
45: continue;
46: outnam = innam = NULL;
47: backgnd = FALSE;
48:
49: /* handle '&' */
50:
51: if (Shl.shtktyp[ntokens-1] == '&') {
52: ntokens-- ;
53: backgnd = TRUE;
54: }
55:
56: /* scan tokens, accumulating length; handling redirect */
57:
58: for (len=0,i=0 ; i<ntokens ; ) {
59: if ((ch = Shl.shtktyp[i]) == '&') {
60: ntokens = -1;
61: break;
62: } else if (ch == '>') {
63: if (outnam != NULL || i >= --ntokens) {
64: ntokens = -1;
65: break;
66: }
67: outnam = Shl.shtok[i+1];
68: for (ntokens--,j=i ; j<ntokens ; j++) {
69: Shl.shtktyp[j] = Shl.shtktyp[j+2];
70: Shl.shtok [j] = Shl.shtok [j+2];
71: }
72: continue;
73: } else if (ch == '<') {
74: if (innam != NULL || i >= --ntokens) {
75: ntokens = -1;
76: break;
77: }
78: innam = Shl.shtok[i+1];
79: for (ntokens--,j=i ; j < ntokens ; j++) {
80: Shl.shtktyp[j] = Shl.shtktyp[j+2];
81: Shl.shtok [j] = Shl.shtok [j+2];
82: }
83: continue;
84: } else {
85: len += strlen(Shl.shtok[i++])+1;
86: }
87: }
88: if (ntokens <= 0) {
89: fprintf(dev, errhd);
90: continue;
91: }
92: stdin = stdout = stderr = dev;
93:
94: /* Look up command in table */
95:
96: for (com=0 ; com<Shl.shncmds ; com++) {
97: if (strcmp(cmds[com].cmdnam,Shl.shtok[0]) == 0)
98: break;
99: }
100: if (com >= Shl.shncmds) {
101: fprintf(dev, "%s: not found\n", Shl.shtok[0]);
102: continue;
103: }
104:
105: /* handle built-in commands with procedure call */
106:
107: if (cmds[com].cbuiltin) {
108: if (innam != NULL || outnam != NULL || backgnd)
109: fprintf(dev, errhd);
110: else if ( (*cmds[com].cproc)(stdin, stdout,
111: stderr, ntokens, Shl.shtok) == SHEXIT)
112: break;
113: continue;
114: }
115:
116: /* Open files and redirect I/O if specified */
117:
118: if (innam != NULL && (stdin=open(NAMESPACE,innam,"ro"))
119: == SYSERR) {
120: fprintf(dev, fmt, innam);
121: continue;
122: }
123: if (outnam != NULL && (stdout=open(NAMESPACE,outnam,"w"))
124: == SYSERR) {
125: fprintf(dev, fmt, outnam);
126: continue;
127: }
128:
129: /* compute space needed for string args. (in bytes) */
130:
131: len += (ntokens+2) * sizeof(char *);
132: len = (len+sizeof(int)-1)&(~(sizeof(int)-1));
133: control(dev, TCINT, getpid());
134:
135: /* create process to execute conventional command */
136:
137: if ( (child = create(cmds[com].cproc, SHCMDSTK, SHCMDPRI,
138: Shl.shtok[0],(len/sizeof(int)) + 4,
139: stdin, stdout, stderr, ntokens))
140: == SYSERR) {
141: fprintf(dev, "Cannot create\n");
142: close(stdout);
143: close(stdin);
144: continue;
145: }
146: addarg(child, ntokens, len);
147: setdev(child, stdin, stdout);
148: if (backgnd) {
149: fprintf(dev, fmt2, child);
150: resume(child);
151: } else {
152: setnok(getpid(), child);
153: recvclr();
154: resume(child);
155: if (receive() == INTRMSG) {
156: setnok(BADPID, child);
157: fprintf(dev, fmt2, child);
158: }
159: }
160: }
161: return(OK);
162: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.