Skip to content

Instantly share code, notes, and snippets.

@pattersongp
Created August 16, 2018 14:20
Show Gist options
  • Select an option

  • Save pattersongp/2428581ed0144b790bdbd7fa71b0ed56 to your computer and use it in GitHub Desktop.

Select an option

Save pattersongp/2428581ed0144b790bdbd7fa71b0ed56 to your computer and use it in GitHub Desktop.

Revisions

  1. pattersongp created this gist Aug 16, 2018.
    116 changes: 116 additions & 0 deletions seashell.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,116 @@
    /*
    * Graham Patterson
    * Simple shell program
    */
    #include <unistd.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>

    #define MAX_SIZE 256

    void parse_command(char *cmd, char **parsed);
    void die(char *message);
    int exec_cmd(char **cmd_args);
    int cd(char *path);

    int main(int argc, char **argv)
    {
    char command[MAX_SIZE];
    char *parsed[MAX_SIZE/sizeof(char *)];

    while(1)
    {
    printf("SeaShell--> ");
    if (fgets(command, sizeof(command), stdin) == NULL) {
    die("fgets failed");
    }

    // skip execution if just pressing enter
    if (strcmp(command, "\n")) {
    parse_command(command, parsed);

    if (!strcmp(*parsed, "cd")) {
    cd(parsed[1]);
    } else {
    exec_cmd(parsed);
    }
    }
    }
    }


    /*
    * Execute the command { cmd_args }
    */
    int exec_cmd(char **cmd_args)
    {
    if (cmd_args == NULL) {
    die("exec_cmd failed");
    }

    pid_t pid = fork();
    if (pid < 0) {
    die("fork failed");
    } else if (pid == 0) {
    execvp(*cmd_args, cmd_args);
    die("Error! Unknown command");
    } else {
    waitpid(pid, 0, 0);
    }

    return 0;
    }


    /*
    * kill a process on failure
    */
    void die(char *message)
    {
    fprintf(stderr, "%s\n", message);
    exit(-1);
    }


    /*
    * Implementing cd because without changing
    * the directory of the shell, ie the parent
    * process, you'll only change the directory
    * of some child process. In this case, we're
    * never even calling exec
    */
    int cd(char *path) { return chdir(path); }


    /*
    * Parses up to 32 space delimited
    * command and options
    *
    * Fills in the {parsed} paramter with the parsed commands
    * from {input}
    */
    void parse_command(char *input, char **parsed)
    {
    char *sep = " ";
    char *cmd;
    int i = 0;

    cmd = strtok(input, sep);
    while(cmd != NULL)
    {
    // make sure that cmd is null terminated
    if (cmd[strlen(cmd)-1] == '\n') {
    cmd[strlen(cmd)-1] = '\0';
    }

    // only add a command if it isn't a space
    if (strcmp(cmd,"") && strcmp(cmd," ") && strcmp(cmd, "\n")) {
    parsed[i++] = cmd;
    }

    cmd = strtok(NULL, sep);
    }
    parsed[i] = NULL;
    }