/* --------------- cmd.c ------------------*/ #define CMD_H #include "cmd.h" /* Redirection of I/O: */ /* after redirect the caller has file descriptor 0 * for input, descriptor 1 for output, and 2 for stderr ! */ static void redirect(int srcfd, char * srcfile, int dstfd, char * dstfile, int errfd, char * errfile, BOOLEAN append, BOOLEAN bckgrnd) { int flags, fd; /* we expect for srcfd: * 0: nothing to do * -2: redirect 0 (stdin) to file * (-1 indicates error) * * we expect for dstfd: * 1: nothing to do * -2: redirect 1 (stdout) to file * (with respect to parameter `append' * * we expect for errfd: * 2: nothing to do * -2: redirect 2 (stderr) to file */ if (srcfd == 0 && bckgrnd) { strcpy(srcfile, "/dev/null"); /* /dev/null -> * there is nothing to read, only EOF * a background command couldn't get any * input from stdin; */ srcfd = BADFD; /* so redirect 0 to srcfile * set to /dev/null above */ } if (srcfd != 0) { /* 0 should point to file for input */ if (close(0) == -1) perror("close"); else if (open(srcfile, O_RDONLY, 0) == -1) { fprintf(stderr, "can't open %s\n", srcfile); exit(1); } } /*now file is referenced by file descriptor 0 */ /* now the same for std_output */ if (dstfd != 1) { /* output to file (>,>> (dstfd==-2) */ if (close(1) == -1) perror("close"); else { flags = O_WRONLY | O_CREAT; if (!append) /* > file */ flags |= O_TRUNC; else flags |= O_APPEND; if (open(dstfile, flags, 0666) == -1) { /* open returns the smallest * free file descriptor */ fprintf(stderr, "can't create %s\n", dstfile); exit(1); } } } /* now the same for std_error*/ if (errfd != 2) { /* output to file */ if (close(2) == -1) perror("close"); else { flags = O_WRONLY | O_CREAT | O_TRUNC; if (open(errfile, flags, 0664) == -1) { /* open returns the smallest * free file descriptor */ fprintf(stderr, "can't create %s\n", errfile); exit(1); } } } for (fd =3; fd < 20; fd++) (void) close(fd); /* the caller now only needs 0,1,2 !!!*/ } /* invoke() - execute simple command * in a new process */ static int invoke(int argc, char *argv[], int srcfd, char *srcfile, int dstfd, char *dstfile, int errfd, char *errfile, BOOLEAN append, BOOLEAN bckgrnd) { /* uses redirect() */ int pid; char *path; /* empty commandline??? */ if (argc == 0) return(0); if (!strcmp(argv[0], "cd")) { if (argc > 1) path = argv[1]; else if ((path = getenv("HOME")) == NULL) path = "."; /*HOME not defined*/ if (chdir(path) == -1) fprintf(stderr, "%s: bad dir\n", path); return(0); } /*if (!strcmp(argv[0], "cd")) { chdir(argv[1]); return(0); }*/ switch (pid = fork()) { case -1: fprintf(stderr, "Can't create new process\n"); return(0); case 0: /* CHILD */ redirect(srcfd, srcfile, dstfd, dstfile, errfd, errfile, append, bckgrnd); /* install signal handler for background: */ if (bckgrnd) { if (ignoresig_bg(SIGINT) == SIG_ERR) { perror("ignorsig_bg - SIGINT"); exit(1); } } execvp(argv[0], argv); /* this shouldn't be reached */ fprintf(stderr, "can't execute %s\n", argv[0]); exit(1); default: /* PARENT */ if (srcfd > 0 && close(srcfd) == -1) perror("close src"); if (dstfd > 1 && close(dstfd) == -1) perror("close dst"); if (errfd > 2 && close(errfd) == -1) perror("close error"); if (bckgrnd) printf("%d\n", pid); return (pid); } } TOKEN command(int *waitpid) { /* int * waitpid: perhaps we have to wait * for the command * * return value: T_NL or T_AMP on success, T_ERR on error * * uses: gettoken(), invoke() */ TOKEN token, term; int argc, srcfd, dstfd, errfd, pid; char * argv[MAXARG+1]; char srcfile[MAXFNAME+1]; char dstfile[MAXFNAME+1]; char errfile[MAXFNAME+1]; char word[MAXWORD], *malloc(); BOOLEAN append; argc = 0; srcfd = 0; dstfd = 1; errfd = 2; /* defaults */ while (1) { switch (token = gettoken(word)) { case T_WORD: if (argc == MAXARG) { fprintf(stderr, "Too many args\n"); break; } if ((argv[argc]=malloc(strlen(word)+1))==NULL) { fprintf(stderr,"Out of arg memory\n"); break; } strcpy(argv[argc],word); argc++; continue; case T_LT: if (srcfd != 0) { fprintf(stderr, "syntax error: EXTRA <\n"); //skip_line(); return T_ERR; } if (gettoken(srcfile) != T_WORD) { fprintf(stderr, "syntax error: Illegal <\n"); //skip_line(); return T_ERR; } /* we have to redirect 0 to a file */ srcfd = BADFD; continue; case T_GT: case T_GTGT: if (dstfd != 1) { fprintf(stderr, "syntax error: EXTRA > or >>\n"); //skip_line(); return T_ERR; } if (gettoken(dstfile) != T_WORD) { fprintf(stderr, "syntax error: Illegal > or >>\n"); //skip_line(); return T_ERR; } dstfd = BADFD; append = (token == T_GTGT); continue; case T_TWO_GT: if (errfd != 2) { fprintf(stderr, "syntax error: EXTRA 2>\n"); //skip_line(); return T_ERR; } if (gettoken(errfile) != T_WORD) { fprintf(stderr, "syntax error: Illegal 2>\n"); //skip_line(); return T_ERR; } errfd = BADFD; continue; case T_PIPE: fprintf(stderr, "Pipes have not been implemented :-(\n"); //skip_line(); return T_ERR; case T_OR: case T_AND: case T_AMP: case T_NL: term = token; /* one simple command is read */ argv[argc] = NULL; /* Eingabe von '> file' allein: loeschen / anlegen * einer Datei: */ if((argc == 0) && (dstfd == BADFD) && (!append)) { dstfd = open(dstfile, O_WRONLY | O_CREAT | O_TRUNC, 0664); close(dstfd); return T_NL; } pid = invoke(argc,argv,srcfd, srcfile,dstfd, dstfile, errfd, errfile, append, term == T_AMP); *waitpid = pid; while (--argc >= 0) free(argv[argc]); return(term); case T_EOF: printf("\n\n"); exit(0); default: } }; return T_ERR; }