#include #include #include #include #include #include #include #include struct cmd_t { char *cmdfile; char *ifile, *ofile; char *argv[32]; int argvidx; int mode; }; int stripslashn(char *in); int setel(int el, char *val, struct cmd_t *incmd); int tokenize(char *in, struct cmd_t *mycmds); int printcmd(struct cmd_t *incmd); int initcmd(struct cmd_t *incmd); int runcmd(struct cmd_t *mycmds); int main() { int done=0, i, rc; char buf[1024]; struct cmd_t mycmds[2]; /* blank out cmd structs */ for (i=0; i<2; i++) { initcmd(&mycmds[i]); } /* start main prompt loop */ while(!done) { /* display prompt, read input */ printf("> "); fgets(buf, 1024, stdin); /* strip off the '\n' */ stripslashn(buf); /* did they type in 'exit'? */ if (!strcmp(buf, "exit")) { exit(0); } /* tokenize buf, store in mycmds */ rc=tokenize(buf, mycmds); if (rc < 0) { fprintf(stderr, "ERROR: tokenize()\n"); } else { /* tokenize worked, run the cmd(s) */ rc = runcmd(mycmds); if (rc < 0) { fprintf(stderr, "ERROR: runcmd()\n"); } } /* reset cmds */ for (i=0; i<2; i++) { initcmd(&mycmds[i]); } } } int runcmd(struct cmd_t *mycmds) { int pid; int rc; int status; int ofd, ifd; int cmdidx=0; int fds[2]; pid = fork(); if (pid < 0) { fprintf(stderr, "ERROR: cannot fork!\n"); return(-1); } else if (pid) { /* parent */ /* wait for the child to exit */ pid = wait(&status); /* printf("waited for %d\n", pid); */ } else { /* child */ /* if i am in pipe mode */ if (mycmds[cmdidx].mode) { rc=pipe(fds); pid = fork(); if (pid) { close(fds[1]); dup2(fds[0], STDIN_FILENO); cmdidx++; } else { close(fds[0]); dup2(fds[1], STDOUT_FILENO); } } /* if i am not in pipe mode and an ifile is specified */ if ((mycmds[cmdidx].ifile != NULL) && !mycmds[cmdidx].mode) { /* open the ifile for read */ ifd = open(mycmds[cmdidx].ifile, O_RDONLY, 0); if (ifd < 0) { fprintf(stderr, "ERROR: cannot open file %s for read\n", mycmds[cmdidx].ifile); exit(1); } /* redirect stdin from file */ dup2(ifd, STDIN_FILENO); } /* if i am not in pipe mode and an ofile is specified */ if ((mycmds[cmdidx].ofile != NULL) && !mycmds[cmdidx].mode) { /* open ofile for write */ ofd = open(mycmds[cmdidx].ofile, O_WRONLY | O_CREAT | O_TRUNC, 0644); if (ofd < 0) { fprintf(stderr, "ERROR: cannot open file %s for write\n", mycmds[cmdidx].ofile); exit(1); } /* redirect stdout to file */ dup2(ofd, STDOUT_FILENO); } /* pipe mode or not, i'm execvping */ rc = execvp(mycmds[cmdidx].cmdfile, mycmds[cmdidx].argv); /* if there was a problem, report */ if (rc < 0) { perror("execvp: "); } exit(1); } return(1); } int initcmd(struct cmd_t *incmd) { int i, j; incmd->cmdfile = NULL; incmd->ifile = NULL; incmd->ofile = NULL; incmd->argvidx = -1; incmd->mode = 0; for (i=0; i<32; i++) { incmd->argv[i] = NULL; } return(1); } int printcmd(struct cmd_t *incmd) { int i; printf("CMD: %s\n", incmd->cmdfile); for (i=0; i<=incmd->argvidx; i++) { printf("ARG %d: %s\n", i, incmd->argv[i]); } if (incmd->ifile != NULL) { printf("IFILE: %s\n", incmd->ifile); } if (incmd->ofile != NULL) { printf("OFILE: %s\n", incmd->ofile); } return(1); } int tokenize(char *in, struct cmd_t *mycmds) { char *idx, *start; int el=0; int count=0; int rc; int cmdidx = 0; /* el is the current 'mode' i'm in, cmd=0, args=1, redir ifile=2, redir ofile=3 */ /* initialize all pointers to point to in */ start = idx = in; /* start tokenize loop */ idx = strchr(start, ' '); while(idx != NULL) { count++; *idx = '\0'; if (!strcmp(start, "<")) { el = 3; } else if (!strcmp(start, ">")) { el = 2; } else if (!strcmp(start, "|")) { /* mode=1 means i'm in pipe mode */ mycmds[cmdidx].mode = 1; cmdidx++; mycmds[cmdidx].mode = 1; el = 0; } else { rc = setel(el, start, &mycmds[cmdidx]); if (rc < 0) { printf("Malformed Command\n"); return(-1); } el = 1; } start = idx + 1; idx = strchr(start, ' '); } /* last token in string */ rc = setel(el, start, &mycmds[cmdidx]); if (rc < 0) { printf("Malformed Command\n"); return(-1); } return(0); } int setel(int el, char *val, struct cmd_t *incmd) { if ((*val == '\0') || (val == NULL) || (*val == '>') || (*val == '<') || (*val == '|')) { return(-1); } if (el == 0) { incmd->cmdfile = (char *)strdup(val); incmd->argvidx++; incmd->argv[incmd->argvidx] = (char *)strdup(val); } else if (el == 1) { incmd->argvidx++; incmd->argv[incmd->argvidx] = (char *)strdup(val); } else if (el == 2) { incmd->ofile = (char *)strdup(val); } else if (el == 3) { incmd->ifile = (char *)strdup(val); } return(0); } int stripslashn(char *in) { char *idx; idx = strchr(in, '\n'); if (idx != NULL) { *idx = '\0'; } return(0); }