|
CS 456 - Systems Programming
Spring 2024
|
Displaying ./code/shell/shell.c
// a very basic shell
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#define TOKBUF 64
#define TOKDELIM " \t\r\n\a"
//shell stuff
void run_shell(void);
char *readLine(void);
char **splitLine(char *line);
int launch(char **args);
int execute(char **args);
int num_builtins();
//shell commands
int shell_cd(char **args);
int shell_help(char **args);
int shell_exit(char **args);
char *builtin_str[] = {
"cd",
"help",
"exit"
};
int (*builtin_func[]) (char **) = {
&shell_cd,
&shell_help,
&shell_exit
};
int main(int argc, char **argv){
//put config files here
run_shell();
//perform shutdown stuff here
return 0;
}
void run_shell(void){
//some declarations
char *line;
char **args;
int status;
do{
printf("> ");
line = readLine();
args = splitLine(line);
status = execute(args);
} while(status);
}
char *readLine(void){
char *line = NULL;
ssize_t bufsize = 0;
//getline allocates a buffer for us
if(getline(&line, &bufsize, stdin) == -1){
if (feof(stdin)){ //we hit EOF
exit(0);
} else {
perror("readLine");
exit(-1);
}
}
return line;
}
char **splitLine(char *line){
int bufsize = TOKBUF;
int position = 0;
char **tokens = malloc(bufsize * sizeof(char*));
char *token;
if(!tokens){
perror("splitLine: allocation error before while loop");
exit(-1);
}
token = strtok(line, TOKDELIM);
while(token != NULL){
tokens[position] = token;
position++;
if(position >= bufsize){
bufsize += TOKBUF;
tokens = realloc(tokens, bufsize* sizeof(char*));
if(!tokens){
perror("splitLine: allocation error in while loop");
exit(-1);
}
}
token = strtok(NULL, TOKDELIM);
}
tokens[position] = NULL;
return tokens;
}
int launch(char **args){
pid_t pid, wpid;
int status;
pid = fork();
if(pid == 0){
//child process
if (execvp(args[0], args) == -1){
perror("execute: Error in Child Process");
}
exit(-1);
} else if (pid < 0){
perror("execute: Error forking");
} else {
//parent process
do {
wpid = waitpid(pid, &status, WUNTRACED);
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
}
return 1;
}
int num_builtins() {
return sizeof(builtin_str) / sizeof(char *);
}
int shell_cd(char **args){
if (args[1] == NULL) {
fprintf(stderr, "shell: expected argument to \"cd\"\n");
} else {
if (chdir(args[1]) != 0) {
perror("shell:");
}
}
return 1;
}
int shell_help(char **args){
printf("Current Builtins\n");
for (int i = 0; i < num_builtins(); i++) {
printf(" %s\n", builtin_str[i]);
}
}
int shell_exit(char **args){
return 0;
}
int execute(char **args){
int i;
if (args[0] == NULL) {
// An empty command was entered.
return 1;
}
for (i = 0; i < num_builtins(); i++) {
if (strcmp(args[0], builtin_str[i]) == 0) {
return (*builtin_func[i])(args);
}
}
return launch(args);
}
|