
Pipex
Shell Pipe Implementation
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
Process Architecture Design
Designed the process communication architecture and established the basic pipe mechanism for inter-process data flow.
Command Execution
Implemented command parsing and execution using fork() and execve() with proper argument handling and PATH resolution.
Pipe Communication
Established pipe communication between processes with proper file descriptor management and data flow control.
Challenges & Solutions
Process Synchronization
Coordinating multiple processes and ensuring proper data flow through pipes without deadlocks or race conditions.
Implemented proper process creation and waiting mechanisms with signal handling and systematic pipe management.
File Descriptor Management
Managing file descriptors and ensuring proper cleanup to prevent resource leaks and maintain system stability.
Developed systematic approach to file descriptor handling with proper closing and comprehensive error checking.
Command Execution
Properly parsing and executing shell commands with argument handling and environment variable management.
Implemented robust command parsing with PATH resolution and proper argument formatting for execve() calls.
// 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);
}