csnotes/334/homework/3/msh.c
2019-09-17 00:25:55 -07:00

112 lines
2.1 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <time.h>
#include <sys/types.h>
#define PROMPT "msh> "
#define EXIT_CMD "exit"
#define MAX_BUF 121
// Statuses from builtin responses
#define RESP_HELP 1
#define RESP_DATE 2
#define RESP_ECHO 3
#define RESP_SHELL 4
void echo(const char*);
void remove_newline(char*);
void exit_branch(const char*);
int builtin_response(char*);
int main(void) {
char buffer[MAX_BUF];
while(1) {
printf("%s", PROMPT);
fgets(buffer, MAX_BUF, stdin);
// Deal with EOF input
if(!strlen(buffer)) {
exit(0);
}
exit_branch(buffer);
remove_newline(buffer);
int status = builtin_response(buffer);
// the switch in case we need to add more response flags later
switch(status) {
case RESP_ECHO:
echo(buffer);
case RESP_SHELL: // shell command handler was used
continue;
}
memset(buffer, 0x00, MAX_BUF); // reset buffer after each usage
}
return 0;
}
void echo(const char* buf) {
printf("%s\n", buf);
}
void remove_newline(char* buf) {
char* c = buf;
while(*c != '\n') { c++; }
*c='\0';
}
void exit_branch(const char* buf) {
if(!strcmp(buf, EXIT_CMD)) {
exit(0);
}
}
int builtin_response(char* buffer) {
#define STRING_DELIMITER " "
#define TIME_FMT "%D"
exit_branch(buffer); // exit is builtin so here we are
if(!strcmp(buffer, "help")) {
echo("enter Linux commands, or exit to exit");
return RESP_HELP;
}
// Printout the date today
if(!strcmp(buffer, "date")) {
static char date[64];
time_t now = time(0);
strftime(date, sizeof(date), TIME_FMT, localtime(&now));
echo(date);
return RESP_DATE;
}
char *tokens[64];
int idx = 0;
for(char* cur = strtok(buffer, STRING_DELIMITER); cur != NULL; cur=strtok(NULL, STRING_DELIMITER)) {
#ifdef DBG_LINE
printf("%s ", cur);
#endif
tokens[idx] = cur;
idx++;
}
// Execute child process
pid_t child = fork();
if(child != 0) {
int status_child = wait(NULL);
if(status_child == 127) {
printf("msh: %s: %d", tokens[0], status_child);
}
}
else {
execvp(tokens[0], tokens);
}
// Cleanup pointers
for(int i = 0; i< 64; i++) {
tokens[i] = NULL;
}
}