/* Redirects the output of a given CMD, as specified by toType and toFile. If * the environment variable noclobber is set, > and >& may not redirect to * existing files and >> and >>& must redirect to existing files; the ! versions * of these redirection operators are not subject to these limitations. * * @simple = CMD to be redirected * * Returns: 0 on success, -1 on error */ int redirect_output(CMD* simple) { assert(simple->toFile); int fdout; int output_type = simple->toType; int mode = O_WRONLY; if (getenv("noclobber") && !(ISCLOBBER(output_type))) { if (ISAPPEND(output_type)) { mode |= O_APPEND; } else { mode |= O_CREAT | O_EXCL; } } else { mode |= O_CREAT; if (ISAPPEND(output_type)) { mode |= O_APPEND; } else { mode |= O_TRUNC; } } if ((fdout = open(simple->toFile, mode, 0755)) < 0) { perror(simple->toFile); return -1; } dup2(fdout, 1); if (ISREDERR(simple->toType)) dup2(fdout, 2); close(fdout); return 0; }
// Redirects using dup2() based on the given command's redirection // fields. Returns 0 for success, -1 for failure. errno is set if -1 is returned int redirect(CMD* cmd) { if(!cmd) return 0; fflush(stdout); fflush(stderr); int fd; if(cmd->fromType == RED_IN) { if((fd = open(cmd->fromFile, O_RDONLY)) < 0) { perror(EXEC_NAME); return -1; } if(fd != STDIN_FD) { dup2(fd, STDIN_FD); close(fd); } } else if(cmd->fromType == RED_HERE) { // use a pipe for HERE documents; a child process will write the doc // to a pipe, which the parent process will read int fd[2]; int pid; if(pipe(fd) || (pid = fork()) < 0) { perror(EXEC_NAME); return -1; } else if(pid == 0) { // child close(fd[0]); if(fd[1] != STDOUT_FD) { dup2(fd[1], STDOUT_FD); close(fd[1]); } for(char* c = cmd->fromFile; *c != '\0'; c++) { putchar(*c); } exit(EXIT_SUCCESS); } else { // parent close(fd[1]); if(fd[0] != STDIN_FD) { dup2(fd[0], STDIN_FD); close(fd[0]); } } } if(cmd->toType != NONE) { int options = O_WRONLY; if(ISAPPEND(cmd->toType)) { options |= O_APPEND; if(!getenv("noclobber") || ISCLOBBER(cmd->toType)) { options |= O_CREAT; } } else { options |= O_CREAT | O_TRUNC; if(getenv("noclobber") && !ISCLOBBER(cmd->toType)) { options |= O_EXCL; } } if((fd = open(cmd->toFile, options, (mode_t)0666)) < 0) { perror(EXEC_NAME); return -1; } dup2(fd, STDOUT_FD); if(ISERROR(cmd->toType)) { dup2(fd, STDERR_FD); } close(fd); } return 0; }