From 4e291984f494ab898902ffd6c240e190ebb50942 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Gendre?= <seb@k-7.ch> Date: Mon, 18 May 2020 21:31:24 +0200 Subject: [PATCH] Jobs: Add management of stdout redirection to file --- src/jobs.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/jobs.h | 40 ++++++++++++++++++++++++++++++- 2 files changed, 108 insertions(+), 1 deletion(-) diff --git a/src/jobs.c b/src/jobs.c index fd9411d..45e0cd1 100644 --- a/src/jobs.c +++ b/src/jobs.c @@ -5,6 +5,56 @@ #include <unistd.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <fcntl.h> + + +/* Search file redirection argument ('>') in argv */ +int job_write_redirection_position_in_argv(int argc, char *argv[]) { + // Check each argument in the argv + for (int i = 0; i < argc; ++i) { + if (strcmp(argv[i], ">") == 0) { + // If ">" found, return its position + return i; + } + } + return -1; +} + + +/* See if argv has an redirection symbole '>' and return its position */ +char* job_write_redirection_path_in_argv(int argc, char *argv[]) { + int redirect_pos = job_write_redirection_position_in_argv(argc, argv); + if (redirect_pos == -1) { + return NULL; + } else { + return argv[redirect_pos + 1]; + } + +} + + +/* Clean arguments after stdout redirection */ +int job_clean_argv_after_redirection_char(int *argc, char **argv) { + int redirect_arg_pos = job_write_redirection_position_in_argv(*argc, argv); + // If the redirection char argument position are beyound argv length, return error + // code + if (redirect_arg_pos >= *argc) { + return -1; + } + /* // Free all arguments after the redirection argument position */ + /* for (int i = redirect_arg_pos; i < *argc; ++i) { */ + /* free(argv[i]); */ + /* } */ + // Place a NULL at the redirection argument position + argv[redirect_arg_pos] = NULL; + // Define the new argc value + *argc = redirect_arg_pos; + // Reduce argv length + argv = realloc(argv, (*argc+1)*sizeof(char*)); + return 0; +} // Execute a given command as job @@ -13,6 +63,9 @@ int job_exec_command(int argc, char *argv[]) { pid_t pid; int child_process_status; int exec_status; + char *redirection_path = NULL; + int redirection_file; + int stdout_new_desc = -1; pid = fork(); @@ -20,6 +73,21 @@ int job_exec_command(int argc, char *argv[]) { // In case of fork error } else if (pid == 0) { // I'm the child process + // Check if the redirection of stdout to file is requested by user + redirection_path = job_write_redirection_path_in_argv(argc, argv); + if (redirection_path) { + // If yes, open the file path + redirection_file = open(redirection_path, O_WRONLY | O_CREAT, 0640); + // Replace stdout file descriptor by a copy of the file + // descriptor of the openned file + stdout_new_desc = dup2(redirection_file, STDOUT_FILENO); + if (stdout_new_desc == -1) { + perror("Cannot redirect stdout"); + } else { + // Remove all arguments after the '>' + job_clean_argv_after_redirection_char(&argc, argv); + } + } // Exec the command found in PATH env by using execvpe() exec_status = execvpe(argv[0], argv, NULL); if (exec_status == -1) { @@ -44,3 +112,4 @@ int job_exec_command(int argc, char *argv[]) { } } } + diff --git a/src/jobs.h b/src/jobs.h index 1350561..ac8ee6a 100644 --- a/src/jobs.h +++ b/src/jobs.h @@ -11,7 +11,8 @@ /* Execute a given command as job * * Parameters: - * - cmd: The command to execute + * - argc: The command arguments counter + * - argv: The command arguments * * Return: * - The command return code (0 is success) @@ -19,4 +20,41 @@ */ int job_exec_command(int argc, char *argv[]); + +/* Search file redirection argument ('>') in argv + * + * Parameters: + * - argc: The command arguments counter + * - argv: The command arguments + * + * Return: + * The position of '>' argument in the argv, -1 if not found +*/ +int job_write_redirection_position_in_argv(int argc, char *argv[]); + +/* Get file path where user ask to redirect stdout, if defined by the + * user with a '>' + * + * Parameters: + * - argc: The command arguments counter + * - argv: The command arguments + * + * Return: + * The file path where user ask to redirect stdout + * If not defined, return NULL +*/ +char* job_write_redirection_path_in_argv(int argc, char *argv[]); + +/* Clean arguments after stdout redirection + * + * Parameters: + * - argc: The command arguments counter + * - argv: The command arguments + * + * Return: + * 0 if success, -1 if error +*/ +int job_clean_argv_after_redirection_char(int *argc, char **argv); + + #endif /* JOBS_H */ -- GitLab