-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
eb98032
commit cf96645
Showing
5 changed files
with
196 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
*.o | ||
vsh | ||
*~ |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
CC=gcc | ||
CFLAGS=-Wall -Werror -std=c99 | ||
OBJS=argbuild.o vsh.o | ||
BINARY=vsh | ||
|
||
.PHONY: clean all debug release | ||
|
||
all: debug | ||
|
||
release: $(BINARY) | ||
|
||
debug: CFLAGS += -g | ||
debug: $(BINARY) | ||
|
||
$(BINARY): $(OBJS) | ||
$(CC) -o $@ $(CFLAGS) $(OBJS) $(LDLIBS) | ||
|
||
%.o: %.c %.h | ||
$(CC) -c $< -o $@ $(CFLAGS) | ||
|
||
clean: | ||
rm $(OBJS) $(BINARY) |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
#include "argbuild.h" | ||
|
||
#include <stdlib.h> | ||
#include <string.h> | ||
|
||
void add_arg(char* argument, arg_t* args){ | ||
arg_elt_t* toadd = malloc(sizeof(arg_elt_t)); | ||
toadd->arg = argument; | ||
toadd->next = NULL; | ||
if(args->end != NULL){ | ||
args->end->next = toadd; | ||
} | ||
args->end = toadd; | ||
if(args->first == NULL){ | ||
args->first = toadd; | ||
} | ||
++(args->argc); | ||
} | ||
|
||
arg_t* build_args(char* cmd, unsigned int cmd_max_len){ | ||
arg_t* to_return = malloc(sizeof(arg_t)); | ||
to_return->first = NULL; | ||
to_return->end = NULL; | ||
to_return->argc = 0; | ||
|
||
int sub_start = 0; | ||
int sub_end = 0; | ||
|
||
for(unsigned int i = 0; i < cmd_max_len; ++i){ | ||
if(cmd[i] == '\0'){ | ||
break; | ||
} | ||
if(cmd[i] == ' ' || cmd[i] == '\n'){ | ||
|
||
//Ignore multiple spaces between arguments | ||
if(cmd[i] == ' ' && cmd[i + 1] == ' '){ | ||
continue; | ||
} | ||
|
||
char delineate = cmd[i]; | ||
|
||
sub_end = i; | ||
int new_str_siz = (sub_end - sub_start) + 1; | ||
|
||
//Make sure the string is not empty | ||
if(new_str_siz > 1){ | ||
//Temporarily add a null terminator in the cmd string to make | ||
//strncpy's job easier | ||
cmd[i] = '\0'; | ||
char* arg_str = malloc(sizeof(char) * new_str_siz); | ||
//Copy the argument into the new string | ||
strncpy(arg_str, &cmd[sub_start], new_str_siz); | ||
//Add back in the space char that was replaced by null | ||
//terminator | ||
cmd[i] = delineate; | ||
//Now add the string to our linked list of arg elts | ||
add_arg(arg_str, to_return); | ||
//Make sub_start point to the next char after cmd[i], which is | ||
//a space | ||
sub_start = i + 1; | ||
} | ||
} | ||
} | ||
|
||
return to_return; | ||
} | ||
|
||
char** get_args(arg_t* args, int* numargs){ | ||
if(args->argc <= 0){ | ||
return NULL; | ||
} | ||
|
||
char** to_return = malloc(sizeof(char) * (args->argc + 1)); | ||
*numargs = 0; | ||
for(arg_elt_t* it = args->first; it != NULL; it = it->next){ | ||
to_return[(*numargs)++] = it->arg; | ||
} | ||
|
||
//The last elt in this array is a null pointer | ||
to_return[args->argc] = '\0'; | ||
|
||
return to_return; | ||
} | ||
|
||
void free_args(arg_t* tofree){ | ||
arg_elt_t* it = tofree->first; | ||
while(it != NULL){ | ||
arg_elt_t* next = it->next; | ||
if(it != NULL){ | ||
free(it->arg); | ||
} | ||
free(it); | ||
it = next; | ||
} | ||
free(tofree); | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
#ifndef ARG_BUILD_H | ||
#define ARG_BUILD_H | ||
|
||
typedef struct arg_elt{ | ||
struct arg_elt* next; | ||
char* arg; | ||
} arg_elt_t; | ||
|
||
typedef struct args{ | ||
arg_elt_t* first; | ||
arg_elt_t* end; | ||
int argc; | ||
} arg_t; | ||
|
||
arg_t* build_args(char* cmd, unsigned int cmd_max_len); | ||
char** get_args(arg_t* args, int* numargs); | ||
void free_args(arg_t* tofree); | ||
|
||
#endif |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
#include <stdio.h> | ||
#include <unistd.h> | ||
#include <stdlib.h> | ||
#include <sys/wait.h> | ||
#include <assert.h> | ||
|
||
#include "argbuild.h" | ||
|
||
#define DIR_STR_SIZ 1024 | ||
|
||
int main(int argc, char** argv, char** envp){ | ||
char running = 1; | ||
char pwd[DIR_STR_SIZ]; | ||
const long ARG_MAX = sysconf(_SC_ARG_MAX); | ||
char cmdbuf[ARG_MAX]; | ||
|
||
char user_prompt = '$'; | ||
if(geteuid() == 0) | ||
user_prompt = '#'; | ||
|
||
puts("Welcome to vsh, the Vukelich Shell.\n"); | ||
|
||
|
||
while(running){ | ||
|
||
//Get the current working directory. If an error occurs, then | ||
//set the pwd string to empty | ||
if(getcwd(pwd, DIR_STR_SIZ) != pwd){ | ||
pwd[0] = '\0'; | ||
} | ||
|
||
printf("%s %c ", pwd, user_prompt); | ||
|
||
if(fgets(cmdbuf, ARG_MAX, stdin) != cmdbuf){ | ||
puts("\nExiting"); | ||
running = 0; | ||
continue; | ||
} | ||
|
||
arg_t* args = build_args(cmdbuf, ARG_MAX); | ||
int child_argc; | ||
char** arg_ary = get_args(args, &child_argc); | ||
|
||
if(!fork()){ | ||
execve(arg_ary[0], arg_ary, envp); | ||
printf("%s: %s: Command not found\n", argv[0], arg_ary[0]); | ||
return 1; | ||
} | ||
wait(NULL); | ||
free(arg_ary); | ||
free_args(args); | ||
|
||
} | ||
|
||
return 0; | ||
} |