Pipex
42 Abu Dhabi

Pipex

Shell Pipe Implementation

3 weeks
Individual Project
CPipesProcess ManagementFile Descriptors

Implementation of shell pipe functionality in C, handling process communication, command execution, and inter-process data flow similar to shell pipe operations.

Key Features

Pipe Communication

Implemented pipe mechanism for inter-process communication, enabling data flow between commands.

Command Execution

Executes shell commands with proper argument parsing and environment variable handling.

File Redirection

Handles input and output redirection, reading from files and writing results to output files.

Process Management

Manages child processes using fork() and execve() with proper error handling and cleanup.

Development Journey

Phase 1

Process Architecture Design

Designed the process communication architecture and established the basic pipe mechanism for inter-process data flow.

Phase 2

Command Execution

Implemented command parsing and execution using fork() and execve() with proper argument handling and PATH resolution.

Phase 3

Pipe Communication

Established pipe communication between processes with proper file descriptor management and data flow control.

Challenges & Solutions

Process Synchronization

Problem:

Coordinating multiple processes and ensuring proper data flow through pipes without deadlocks or race conditions.

Solution:

Implemented proper process creation and waiting mechanisms with signal handling and systematic pipe management.

File Descriptor Management

Problem:

Managing file descriptors and ensuring proper cleanup to prevent resource leaks and maintain system stability.

Solution:

Developed systematic approach to file descriptor handling with proper closing and comprehensive error checking.

Command Execution

Problem:

Properly parsing and executing shell commands with argument handling and environment variable management.

Solution:

Implemented robust command parsing with PATH resolution and proper argument formatting for execve() calls.

pipex.c
c
// Main pipex function handling pipe communication
int main(int argc, char **argv, char **envp)
{
    int     pipe_fd[2];
    pid_t   pid1, pid2;
    
    if (argc != 5)
    {
        ft_putstr_fd("Usage: ./pipex file1 cmd1 cmd2 file2\n", 2);
        return (1);
    }
    
    if (pipe(pipe_fd) == -1)
        error_exit("Pipe creation failed");
    
    pid1 = fork();
    if (pid1 == 0)
        first_child(argv, envp, pipe_fd);
    
    pid2 = fork();
    if (pid2 == 0)
        second_child(argv, envp, pipe_fd);
    
    close(pipe_fd[0]);
    close(pipe_fd[1]);
    
    waitpid(pid1, NULL, 0);
    waitpid(pid2, NULL, 0);
    
    return (0);
}

// First child process handling
void first_child(char **argv, char **envp, int *pipe_fd)
{
    int infile;
    
    infile = open(argv[1], O_RDONLY);
    if (infile == -1)
        error_exit("Input file error");
    
    dup2(infile, STDIN_FILENO);
    dup2(pipe_fd[1], STDOUT_FILENO);
    
    close(pipe_fd[0]);
    close(pipe_fd[1]);
    close(infile);
    
    execute_command(argv[2], envp);
}

// Second child process handling
void second_child(char **argv, char **envp, int *pipe_fd)
{
    int outfile;
    
    outfile = open(argv[4], O_WRONLY | O_CREAT | O_TRUNC, 0644);
    if (outfile == -1)
        error_exit("Output file error");
    
    dup2(pipe_fd[0], STDIN_FILENO);
    dup2(outfile, STDOUT_FILENO);
    
    close(pipe_fd[0]);
    close(pipe_fd[1]);
    close(outfile);
    
    execute_command(argv[3], envp);
}