112 lines
2.1 KiB
C
112 lines
2.1 KiB
C
#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;
|
||
}
|
||
|
||
}
|