shell.c

Go to the documentation of this file.
00001 /*
00002    This partial code is a modified version of Marc Rochkind's A Real Shell,
00003    published in "Advanced UNIX Programming", Prentice Hall, 1985.
00004 */
00005 
00006 #include "shell.h"
00007 
00008 #define MAXARG 20
00009 #define MAXFNAME 500
00010 #define MAXWORD  100
00011 #define BADFD -2
00012 
00013 main()  /* real shell */
00014 {
00015    char *prompt;
00016    int pid, fd;
00017    TOKEN  term; 
00018    static TOKEN command();
00019    static void waitfor();
00020 
00021    ignoresig();
00022    if(!EVinit())
00023         fatal ("can't initialize environment");
00024    if( (prompt = EVget("PS2")) == NULL)
00025         prompt = ">";
00026    printf("%s", prompt);
00027 
00028    while(1){
00029         term = command(&pid, FALSE, NULL);
00030         if ( term != T_AMP && pid != 0)
00031              waitfor(pid);
00032         if ( term == T_NL)
00033              printf("%s", prompt);
00034         for(fd = 3; fd< 20; fd++)
00035              (void)close(fd);  /*ignore error */
00036       }
00037 }
00038 
00039 static TOKEN 
00040 command(int *waitpid, BOOLEAN  makepipe, int *pipefdp) /* do simple cmd */
00041 {
00042   
00043      TOKEN token, term ;
00044      int argc, srcfd, dstfd, pid, pfd[2];
00045      char *argv[MAXARG + 1], srcfile[MAXFNAME],dstfile[MAXFNAME];
00046      char word[MAXWORD], *malloc();
00047      BOOLEAN append;
00048      static int invoke( );
00049 
00050      argc = 0;
00051      srcfd = 0;
00052      dstfd = 1;
00053      while (1) {
00054          switch ( token = gettoken(word)) {
00055          case T_WORD:
00056               if (argc == MAXARG){
00057                   fprintf(stderr, "Too many args\n");
00058                   break;
00059                 }
00060               if (( argv[argc] = malloc(strlen(word) +1)) == NULL) {
00061                    fprintf(stderr, "Out of argmemory\n");
00062                    break;
00063                  }
00064               strcpy(argv[argc], word);
00065               argc ++;
00066               continue;
00067          case T_LT:
00068                if(makepipe){
00069                   fprintf(stderr, "Extra<\n");
00070                   break;
00071                 }
00072                if (gettoken(srcfile) != T_WORD){
00073                    fprintf(stderr, "Illegal <\n");
00074                    break;
00075                  }
00076                srcfd = BADFD;
00077                continue;
00078          case T_GT:
00079                if (dstfd !=1) {
00080                    fprintf(stderr, "Extra > or >> \n");
00081                    break;
00082                  }
00083                if (gettoken(dstfile) != T_WORD) {
00084                    fprintf(stderr, "Illegal > or >> \n");
00085                    break;
00086                  }
00087                dstfd = BADFD;
00088                append = FALSE;
00089                continue;
00090          case T_GTGT:
00091                if (dstfd != 1) {
00092                    fprintf(stderr, "Extra > or >>\n"); 
00093                    break;
00094                 }
00095                if (gettoken(dstfile) != T_WORD){
00096                    fprintf(stderr, "Illegal >or >>\n");
00097                    break;
00098                  }
00099                dstfd = BADFD;
00100                append = TRUE;
00101                continue;
00102          case T_BAR:
00103          case T_AMP:
00104          case T_SEMI:
00105          case T_NL:
00106                argv[argc] = NULL;
00107                if ( token == T_BAR) {
00108                     if ( dstfd !=1) {
00109                          fprintf(stderr, "> or >> conflicts with |\n");
00110                          break;
00111                        }
00112                     term = command ( waitpid, TRUE, &dstfd);
00113                   }
00114                else 
00115                     term = token;
00116                
00117                if ( makepipe ){
00118                      if ( pipe(pfd) == -1)
00119                           syserr("pipe");
00120                           *pipefdp = pfd[1];
00121                           srcfd = pfd[0];
00122                  }
00123                if(term == T_AMP)pid = invoke(argc, argv, srcfd, 
00124                             srcfile, dstfd, dstfile, append, TRUE);
00125                else pid=invoke(argc,argv,srcfd, srcfile,dstfd, dstfile,
00126                            append, FALSE);
00127 
00128                if (token != T_BAR)
00129                     *waitpid = pid;
00130                if (argc == 0 && (token != T_NL || srcfd >1))
00131                     fprintf(stderr, "Missing command\n");
00132                while (--argc >= 0)
00133                       free(argv[argc]);
00134                return(term);
00135              case T_EOF:
00136                   exit(0);
00137              }  
00138        }
00139 }
00140 
00141 static int invoke(int argc,char *argv[],int srcfd, char *srcfile,
00142           int dstfd,char *dstfile,BOOLEAN append, BOOLEAN bckgrnd) 
00143                               /* invoke simple command */
00144 {
00145 
00146     static void redirect();
00147     int pid;
00148     static BOOLEAN builtin();
00149   
00150     if (argc == 0  || builtin(argc, argv, srcfd, dstfd))
00151         return(0);
00152     switch (pid = fork()) {
00153     case -1:
00154          fprintf(stderr, "Can't create new process\n");
00155          return(0);
00156     case 0:
00157          if (!bckgrnd)
00158              entrysig();
00159          if (!EVupdate())
00160              fatal("can't update environment");
00161          redirect(srcfd, srcfile, dstfd, dstfile, append, bckgrnd);
00162          execvp(argv[0], argv);
00163          fprintf(stderr, "Can't execute %s\n", argv[0]);
00164          exit(0);
00165     default:
00166          if (srcfd > 0 && close(srcfd) == -1)
00167              syserr("close src");
00168          if (dstfd > 1 && close(dstfd) == -1)
00169              syserr("close dst");
00170          if (bckgrnd)
00171              printf("%d\n", pid);
00172          return(pid);
00173     }
00174 }
00175 /*     REDIRECCION ANULADA MOMENTANEAMENTE
00176 static void redirect(int srcfd, char *srcfile, int dstfd,char *dstfile,
00177              BOOLEAN append, BOOLEAN bckgrnd)  /* I/O redirection */
00178 {
00179    int flags, fd;
00180    long lseek();
00181 
00182    if (srcfd == 0 && bckgrnd) {
00183        strcpy(srcfile, "/dev/null");
00184        srcfd = BADFD;
00185     }
00186    
00187    if (srcfd !=0 ) {
00188        if ( close(0) == -1)
00189             syserr("close");
00190        if (srcfd > 0) {
00191             if ( dup(srcfd) !=0)
00192                  fatal("dup");
00193              }
00194        else if (open (srcfile, O_RDONLY, 0) == -1){
00195              fprintf(stderr, "Can't open %s\n", srcfile);
00196              exit(0);
00197        }
00198    }
00199  
00200    if (dstfd !=1) {
00201        if (close(1) == -1)
00202            syserr("close");
00203        if (dstfd > 1){
00204            if (dup(dstfd) != 1)
00205                fatal("dup");
00206             }
00207        else {
00208             flags = O_WRONLY | O_CREAT;
00209             if(!append)
00210                 flags |= O_TRUNC;
00211             if (open(dstfile, flags, 0666) == -1) {
00212                fprintf(stderr, "Can't create %s\n", dstfile);
00213                exit(0);
00214              }
00215             if(append)
00216                if(lseek(1, 0L,2) == -1)
00217                  syserr("lseek");
00218           }
00219      }
00220    for (fd =3; fd<20; fd++)
00221        (void)close(fd);  // ignore error
00222 }
00223 */
00224 static void waitfor(int pid)  /* wait for child */
00225 {
00226 
00227     int wpid, status;
00228 
00229     while( (wpid = wait(&status)) != pid && wpid !=-1 )
00230          statusprt(wpid, status);
00231     if (wpid == pid )
00232          statusprt(0, status);
00233 }
00234 
00235 static BOOLEAN builtin(int argc, char *argv[], int srcfd, int  dstfd) 
00236                               /* do built-in */
00237 {
00238      char *path;
00239 
00240      if (strchr(argv[0], '=') !=NULL)
00241          asg(argc, argv);
00242      else if (strcmp(argv[0], "export") == 0 )
00243           export(argc, argv);
00244      else if (strcmp(argv[0], "set") == 0 )
00245           set(argc, argv);
00246      else if (strcmp(argv[0], "cd") == 0 ){
00247           if ( argc >1)
00248               path = argv[1];
00249           else 
00250               if (( path = EVget("HOME")) ==NULL)
00251                     path = ".";
00252           if (chdir(path) ==-1)
00253               fprintf(stderr, "%s: bad directory\n", path);
00254         }
00255      else 
00256           return( FALSE);
00257      if (srcfd !=0 || dstfd !=1)
00258           fprintf(stderr, "Illegal redirection or pipeline\n");
00259 }

Generated on Sun May 30 18:38:35 2004 for Routix OS by doxygen 1.3.6