#include #include #include #include #include #include #include struct list { int fd; char *filename; int mode; struct list *next; } *top; char *prog; extern void buildlist(), getprog(), executeit(), freelist(struct list *p); extern char *mygetline(), *estrsave(char *s); int main() { while (1) { buildlist(); getprog(); executeit(); freelist(top); } } void buildlist() { int fd; top = NULL; while (printf( "Which file descriptor do you want to redirect? -1 to end the list.\n") , (fd = atoi(mygetline())) >= 0) { struct list *p = malloc(sizeof(struct list)); if (p == NULL) { fprintf(stderr, "out of memory!\n"); exit(1); } p->next = top; top = p; p->fd = fd; printf("Where do you want to redirect file descriptor %d to/from?\n", p->fd); p->filename = estrsave(mygetline()); printf("Is %s to be opened for read or write? ('r' or 'w')\n", p->filename); p->mode = (mygetline()[0] == 'r') ? O_RDONLY : (O_WRONLY|O_CREAT|O_TRUNC); } } void getprog() { printf("What program do you want to execute?\n"); prog = mygetline(); } void executeit() { int pid; printf("Executing:\n"); fflush(stdout); if ((pid = fork()) < 0) { perror("fork"); exit(1); } else if (pid == 0) { for (; top; top = top->next) { int fd; if ((fd = open(top->filename, top->mode, 0666)) < 0) { perror(top->filename); exit(126); } if (fd != top->fd) { dup2(fd, top->fd); close(fd); } } execl("/bin/sh", "sh", "-c", prog, (char *)NULL); perror("/bin/sh"); exit(125); } else { int status; if (wait(&status) < 0) { perror("wait"); exit(1); } printf("exit status %d\n", WEXITSTATUS(status)); } } void freelist(struct list *p) { if (p) { free(p->filename); freelist(p->next); free(p); } } char *mygetline() { static char buf[500]; char *p; if (fgets(buf, sizeof buf, stdin) == NULL) exit(0); if ((p = strchr(buf, '\n'))) *p = '\0'; return(buf); } char *estrsave(char *s) { char *q; if (!s) return(NULL); if ((q = malloc(strlen(s) + 1)) == NULL) { fprintf(stderr, "out of memory\n"); exit(1); } strcpy(q, s); return(q); }