Skip to content

Instantly share code, notes, and snippets.

@pattersongp
Created August 16, 2018 14:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pattersongp/2428581ed0144b790bdbd7fa71b0ed56 to your computer and use it in GitHub Desktop.
Save pattersongp/2428581ed0144b790bdbd7fa71b0ed56 to your computer and use it in GitHub Desktop.
Simple UNIX shell
/*
* 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