Example #1
0
/* 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;
}
Example #2
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;
}