Created
August 16, 2018 14:20
-
-
Save pattersongp/2428581ed0144b790bdbd7fa71b0ed56 to your computer and use it in GitHub Desktop.
Simple UNIX shell
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment