Untitled

 avatar
unknown
plain_text
a year ago
4.8 kB
3
Indexable
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>

#define MAX_INPUT_SIZE 1024
#define MAX_ARG_SIZE 100

// Function prototypes
void execute_command(char *command);
int handle_builtin(char **args);
void update_path(char *operation, char *dir);
void redirect_io(char **args, int *in_redir, int *out_redir);
char *find_command(char *command);

// Global variable to store the custom path environment
char *path_env[MAX_ARG_SIZE];
int path_count = 0;

int main() {
    char input[MAX_INPUT_SIZE];
    path_env[0] = NULL; // Initialize path environment to empty

    while (1) {
        // Display prompt
        printf("myshell> ");
        fflush(stdout);

        // Read user input
        if (fgets(input, MAX_INPUT_SIZE, stdin) == NULL) {
            perror("fgets failed");
            exit(1);
        }

        // Remove newline character
        input[strcspn(input, "\n")] = '\0';

        // Execute the command
        execute_command(input);
    }

    return 0;
}

void execute_command(char *input) {
    char *args[MAX_ARG_SIZE];
    char *token;
    int i = 0;
    int in_redir = -1, out_redir = -1;

    // Tokenize the input into arguments
    token = strtok(input, " ");
    while (token != NULL) {
        args[i++] = token;
        token = strtok(NULL, " ");
    }
    args[i] = NULL;

    // Handle built-in commands
    if (handle_builtin(args)) {
        return;
    }

    // Handle I/O redirection
    redirect_io(args, &in_redir, &out_redir);

    // Find the command in the custom path environment
    char *cmd_path = find_command(args[0]);
    if (cmd_path == NULL) {
        printf("Command not found: %s\n", args[0]);
        return;
    }

    // Fork and execute the command
    pid_t pid = fork();
    if (pid < 0) {
        perror("fork failed");
        exit(1);
    } else if (pid == 0) {
        if (in_redir != -1) {
            dup2(in_redir, STDIN_FILENO);
            close(in_redir);
        }
        if (out_redir != -1) {
            dup2(out_redir, STDOUT_FILENO);
            close(out_redir);
        }
        execv(cmd_path, args);
        perror("execv failed");
        exit(1);
    } else {
        wait(NULL);
    }
}

int handle_builtin(char **args) {
    if (strcmp(args[0], "cd") == 0) {
        if (args[1] == NULL) {
            fprintf(stderr, "cd: missing argument\n");
        } else if (chdir(args[1]) != 0) {
            perror("chdir failed");
        }
        return 1;
    } else if (strcmp(args[0], "path") == 0) {
        if (args[1] == NULL) {
            for (int i = 0; i < path_count; i++) {
                printf("%s:", path_env[i]);
            }
            printf("\n");
        } else {
            if (args[1][0] == '+') {
                update_path("+", args[1] + 1);
            } else if (args[1][0] == '-') {
                update_path("-", args[1] + 1);
            } else {
                fprintf(stderr, "path: invalid argument\n");
            }
        }
        return 1;
    } else if (strcmp(args[0], "quit") == 0) {
        exit(0);
    }
    return 0;
}

void update_path(char *operation, char *dir) {
    if (strcmp(operation, "+") == 0) {
        path_env[path_count++] = strdup(dir);
    } else if (strcmp(operation, "-") == 0) {
        for (int i = 0; i < path_count; i++) {
            if (strcmp(path_env[i], dir) == 0) {
                free(path_env[i]);
                for (int j = i; j < path_count - 1; j++) {
                    path_env[j] = path_env[j + 1];
                }
                path_env[--path_count] = NULL;
                break;
            }
        }
    }
}

void redirect_io(char **args, int *in_redir, int *out_redir) {
    for (int i = 0; args[i] != NULL; i++) {
        if (strcmp(args[i], "<") == 0) {
            *in_redir = open(args[i + 1], O_RDONLY);
            if (*in_redir == -1) {
                perror("open failed");
                exit(1);
            }
            args[i] = NULL;
        } else if (strcmp(args[i], ">") == 0) {
            *out_redir = open(args[i + 1], O_WRONLY | O_CREAT | O_TRUNC, 0644);
            if (*out_redir == -1) {
                perror("open failed");
                exit(1);
            }
            args[i] = NULL;
        }
    }
}

char *find_command(char *command) {
    char *cmd_path = malloc(MAX_INPUT_SIZE);
    for (int i = 0; i < path_count; i++) {
        snprintf(cmd_path, MAX_INPUT_SIZE, "%s/%s", path_env[i], command);
        if (access(cmd_path, X_OK) == 0) {
            return cmd_path;
        }
    }
    free(cmd_path);
    return NULL;
}
Editor is loading...
Leave a Comment