initial commit
[pfinal.git] / Routix / tareas / ush / shell.c
blob23ad61c350dea210121fc3e3ee21cda20fb247b2
1 /*
2 This partial code is a modified version of Marc Rochkind's A Real Shell,
3 published in "Advanced UNIX Programming", Prentice Hall, 1985.
4 */
6 #include "shell.h"
8 #define MAXARG 20
9 #define MAXFNAME 500
10 #define MAXWORD 100
11 #define BADFD -2
13 main() /* real shell */
15 char *prompt;
16 int pid, fd;
17 TOKEN term;
18 static TOKEN command();
19 static void waitfor();
21 ignoresig();
22 if(!EVinit())
23 fatal ("can't initialize environment");
24 if( (prompt = EVget("PS2")) == NULL)
25 prompt = ">";
26 printf("%s", prompt);
28 while(1){
29 term = command(&pid, FALSE, NULL);
30 if ( term != T_AMP && pid != 0)
31 waitfor(pid);
32 if ( term == T_NL)
33 printf("%s", prompt);
34 for(fd = 3; fd< 20; fd++)
35 (void)close(fd); /*ignore error */
39 static TOKEN
40 command(int *waitpid, BOOLEAN makepipe, int *pipefdp) /* do simple cmd */
43 TOKEN token, term ;
44 int argc, srcfd, dstfd, pid, pfd[2];
45 char *argv[MAXARG + 1], srcfile[MAXFNAME],dstfile[MAXFNAME];
46 char word[MAXWORD], *malloc();
47 BOOLEAN append;
48 static int invoke( );
50 argc = 0;
51 srcfd = 0;
52 dstfd = 1;
53 while (1) {
54 switch ( token = gettoken(word)) {
55 case T_WORD:
56 if (argc == MAXARG){
57 fprintf(stderr, "Too many args\n");
58 break;
60 if (( argv[argc] = malloc(strlen(word) +1)) == NULL) {
61 fprintf(stderr, "Out of argmemory\n");
62 break;
64 strcpy(argv[argc], word);
65 argc ++;
66 continue;
67 case T_LT:
68 if(makepipe){
69 fprintf(stderr, "Extra<\n");
70 break;
72 if (gettoken(srcfile) != T_WORD){
73 fprintf(stderr, "Illegal <\n");
74 break;
76 srcfd = BADFD;
77 continue;
78 case T_GT:
79 if (dstfd !=1) {
80 fprintf(stderr, "Extra > or >> \n");
81 break;
83 if (gettoken(dstfile) != T_WORD) {
84 fprintf(stderr, "Illegal > or >> \n");
85 break;
87 dstfd = BADFD;
88 append = FALSE;
89 continue;
90 case T_GTGT:
91 if (dstfd != 1) {
92 fprintf(stderr, "Extra > or >>\n");
93 break;
95 if (gettoken(dstfile) != T_WORD){
96 fprintf(stderr, "Illegal >or >>\n");
97 break;
99 dstfd = BADFD;
100 append = TRUE;
101 continue;
102 case T_BAR:
103 case T_AMP:
104 case T_SEMI:
105 case T_NL:
106 argv[argc] = NULL;
107 if ( token == T_BAR) {
108 if ( dstfd !=1) {
109 fprintf(stderr, "> or >> conflicts with |\n");
110 break;
112 term = command ( waitpid, TRUE, &dstfd);
114 else
115 term = token;
117 if ( makepipe ){
118 if ( pipe(pfd) == -1)
119 syserr("pipe");
120 *pipefdp = pfd[1];
121 srcfd = pfd[0];
123 if(term == T_AMP)pid = invoke(argc, argv, srcfd,
124 srcfile, dstfd, dstfile, append, TRUE);
125 else pid=invoke(argc,argv,srcfd, srcfile,dstfd, dstfile,
126 append, FALSE);
128 if (token != T_BAR)
129 *waitpid = pid;
130 if (argc == 0 && (token != T_NL || srcfd >1))
131 fprintf(stderr, "Missing command\n");
132 while (--argc >= 0)
133 free(argv[argc]);
134 return(term);
135 case T_EOF:
136 exit(0);
141 static int invoke(int argc,char *argv[],int srcfd, char *srcfile,
142 int dstfd,char *dstfile,BOOLEAN append, BOOLEAN bckgrnd)
143 /* invoke simple command */
146 static void redirect();
147 int pid;
148 static BOOLEAN builtin();
150 if (argc == 0 || builtin(argc, argv, srcfd, dstfd))
151 return(0);
152 switch (pid = fork()) {
153 case -1:
154 fprintf(stderr, "Can't create new process\n");
155 return(0);
156 case 0:
157 if (!bckgrnd)
158 entrysig();
159 if (!EVupdate())
160 fatal("can't update environment");
161 redirect(srcfd, srcfile, dstfd, dstfile, append, bckgrnd);
162 execvp(argv[0], argv);
163 fprintf(stderr, "Can't execute %s\n", argv[0]);
164 exit(0);
165 default:
166 if (srcfd > 0 && close(srcfd) == -1)
167 syserr("close src");
168 if (dstfd > 1 && close(dstfd) == -1)
169 syserr("close dst");
170 if (bckgrnd)
171 printf("%d\n", pid);
172 return(pid);
175 /* REDIRECCION ANULADA MOMENTANEAMENTE
176 static void redirect(int srcfd, char *srcfile, int dstfd,char *dstfile,
177 BOOLEAN append, BOOLEAN bckgrnd) /* I/O redirection */
179 int flags, fd;
180 long lseek();
182 if (srcfd == 0 && bckgrnd) {
183 strcpy(srcfile, "/dev/null");
184 srcfd = BADFD;
187 if (srcfd !=0 ) {
188 if ( close(0) == -1)
189 syserr("close");
190 if (srcfd > 0) {
191 if ( dup(srcfd) !=0)
192 fatal("dup");
194 else if (open (srcfile, O_RDONLY, 0) == -1){
195 fprintf(stderr, "Can't open %s\n", srcfile);
196 exit(0);
200 if (dstfd !=1) {
201 if (close(1) == -1)
202 syserr("close");
203 if (dstfd > 1){
204 if (dup(dstfd) != 1)
205 fatal("dup");
207 else {
208 flags = O_WRONLY | O_CREAT;
209 if(!append)
210 flags |= O_TRUNC;
211 if (open(dstfile, flags, 0666) == -1) {
212 fprintf(stderr, "Can't create %s\n", dstfile);
213 exit(0);
215 if(append)
216 if(lseek(1, 0L,2) == -1)
217 syserr("lseek");
220 for (fd =3; fd<20; fd++)
221 (void)close(fd); // ignore error
224 static void waitfor(int pid) /* wait for child */
227 int wpid, status;
229 while( (wpid = wait(&status)) != pid && wpid !=-1 )
230 statusprt(wpid, status);
231 if (wpid == pid )
232 statusprt(0, status);
235 static BOOLEAN builtin(int argc, char *argv[], int srcfd, int dstfd)
236 /* do built-in */
238 char *path;
240 if (strchr(argv[0], '=') !=NULL)
241 asg(argc, argv);
242 else if (strcmp(argv[0], "export") == 0 )
243 export(argc, argv);
244 else if (strcmp(argv[0], "set") == 0 )
245 set(argc, argv);
246 else if (strcmp(argv[0], "cd") == 0 ){
247 if ( argc >1)
248 path = argv[1];
249 else
250 if (( path = EVget("HOME")) ==NULL)
251 path = ".";
252 if (chdir(path) ==-1)
253 fprintf(stderr, "%s: bad directory\n", path);
255 else
256 return( FALSE);
257 if (srcfd !=0 || dstfd !=1)
258 fprintf(stderr, "Illegal redirection or pipeline\n");