Skip to content
Snippets Groups Projects
Commit b0467730 authored by Vanshika Mohan Bongade's avatar Vanshika Mohan Bongade
Browse files

Upload New File

parent 5541df10
Branches
No related tags found
No related merge requests found
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>
#include "dshlib.h"
int exec_local_cmd_loop() {
char cmd_buff[SH_CMD_MAX];
command_list_t clist;
while (1) {
// Suppress prompt during testing
if (isatty(STDIN_FILENO)) {
printf("%s", SH_PROMPT);
}
// Read user input
if (fgets(cmd_buff, SH_CMD_MAX, stdin) == NULL) {
printf("\n");
break; // Exit if EOF is reached
}
// Remove trailing newline character
cmd_buff[strcspn(cmd_buff, "\n")] = '\0';
// Ignore empty input
if (strlen(cmd_buff) == 0) {
continue;
}
// Exit command
if (strcmp(cmd_buff, EXIT_CMD) == 0) {
printf("exiting...\n");
return OK_EXIT;
}
// Parse the command into a list
int parse_status = build_cmd_list(cmd_buff, &clist);
// Error handling for parsing
if (parse_status < 0) {
continue;
}
// Execute the parsed commands
execute_pipeline(&clist);
// Free allocated memory
free_cmd_list(&clist);
}
return OK;
}
/**
* Parses the command buffer into a list of commands for execution, handling redirection.
*/
int build_cmd_list(char *cmd_line, command_list_t *clist) {
char *token;
int i = 0;
// Initialize command list
clist->num = 0;
// Tokenize input based on pipes (|)
token = strtok(cmd_line, "|");
while (token != NULL) {
// Trim leading spaces
while (*token == ' ') token++;
char *cmd_part = strtok(token, " ");
int j = 0;
clist->commands[i].infile = NULL;
clist->commands[i].outfile = NULL;
clist->commands[i].append = false;
while (cmd_part != NULL) {
if (strcmp(cmd_part, "<") == 0) {
cmd_part = strtok(NULL, " ");
if (cmd_part) {
clist->commands[i].infile = strdup(cmd_part);
}
} else if (strcmp(cmd_part, ">") == 0) {
cmd_part = strtok(NULL, " ");
if (cmd_part) {
clist->commands[i].outfile = strdup(cmd_part);
clist->commands[i].append = false;
}
} else if (strcmp(cmd_part, ">>") == 0) {
cmd_part = strtok(NULL, " ");
if (cmd_part) {
clist->commands[i].outfile = strdup(cmd_part);
clist->commands[i].append = true;
}
} else {
clist->commands[i].argv[j++] = cmd_part;
}
cmd_part = strtok(NULL, " ");
}
clist->commands[i].argv[j] = NULL; // Null-terminate argument list
clist->num++; // Increment command count
token = strtok(NULL, "|"); // Get next command
i++;
if (i >= CMD_MAX) {
fprintf(stderr, CMD_ERR_PIPE_LIMIT, CMD_MAX);
return ERR_TOO_MANY_COMMANDS;
}
}
return OK;
}
/**
* Executes commands using pipes and handles input/output redirection.
*/
int execute_pipeline(command_list_t *clist) {
int num_cmds = clist->num;
int pipes[num_cmds - 1][2]; // Pipes for communication between commands
pid_t pids[num_cmds]; // Array to store process IDs
for (int i = 0; i < num_cmds; i++) {
// Create pipes except for the last command
if (i < num_cmds - 1) {
if (pipe(pipes[i]) == -1) {
perror("pipe");
return ERR_MEMORY;
}
}
// Fork a child process
pids[i] = fork();
if (pids[i] < 0) {
perror("fork");
return ERR_MEMORY;
}
if (pids[i] == 0) { // Child process
// Handle input redirection
if (clist->commands[i].infile) {
int fd = open(clist->commands[i].infile, O_RDONLY);
if (fd < 0) {
perror("open infile");
exit(ERR_EXEC_CMD);
}
dup2(fd, STDIN_FILENO);
close(fd);
}
// Handle output redirection ONLY for the last command
if (i == num_cmds - 1 && clist->commands[i].outfile) {
int fd;
if (clist->commands[i].append) {
fd = open(clist->commands[i].outfile, O_WRONLY | O_CREAT | O_APPEND, 0644);
} else {
fd = open(clist->commands[i].outfile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
}
if (fd < 0) {
perror("open outfile");
exit(ERR_EXEC_CMD);
}
dup2(fd, STDOUT_FILENO);
close(fd);
}
// Redirect input/output for pipes
if (i > 0) {
dup2(pipes[i - 1][0], STDIN_FILENO);
}
if (i < num_cmds - 1) {
dup2(pipes[i][1], STDOUT_FILENO);
}
// Close all pipes
for (int j = 0; j < num_cmds - 1; j++) {
close(pipes[j][0]);
close(pipes[j][1]);
}
// **Fix: Ensure echo does not add extra quotes**
if (strcmp(clist->commands[i].argv[0], "echo") == 0) {
for (int j = 1; clist->commands[i].argv[j] != NULL; j++) {
printf("%s", clist->commands[i].argv[j]);
if (clist->commands[i].argv[j + 1] != NULL) {
printf(" "); // Ensure words are properly spaced
}
}
printf("\n"); // Print newline at the end
fflush(stdout);
exit(0);
}
execvp(clist->commands[i].argv[0], clist->commands[i].argv);
// Print error message before exiting
fprintf(stderr, "error: command not found: %s\n", clist->commands[i].argv[0]);
fflush(stderr);
exit(ERR_EXEC_CMD);
}
}
// Close all pipes in parent process
for (int i = 0; i < num_cmds - 1; i++) {
close(pipes[i][0]);
close(pipes[i][1]);
}
// Wait for all child processes to finish
for (int i = 0; i < num_cmds; i++) {
waitpid(pids[i], NULL, 0);
}
return OK;
}
/**
* Frees allocated memory for command list.
*/
int free_cmd_list(command_list_t *cmd_lst) {
for (int i = 0; i < cmd_lst->num; i++) {
if (cmd_lst->commands[i].infile) {
free(cmd_lst->commands[i].infile);
cmd_lst->commands[i].infile = NULL;
}
if (cmd_lst->commands[i].outfile) {
free(cmd_lst->commands[i].outfile);
cmd_lst->commands[i].outfile = NULL;
}
}
// Reset the command list
cmd_lst->num = 0;
return OK;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment