-
-
Save ramlaxman/69d732f435613f5ac476ba2bd995899a to your computer and use it in GitHub Desktop.
A basic command interpreter. (For teaching purposes.)
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
#include <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <sys/wait.h> | |
void my_system(char **); | |
int my_builtins(char *); | |
int main(void) | |
{ | |
unsigned int i, j, arr_count; | |
char c, *cmd, **cmd_args; | |
while(printf("> ")) | |
{ | |
arr_count = (int) (cmd = (char *) (cmd_args = (char **) 0)); | |
for(i = 0; (c = getchar()) != '\n'; i++) | |
{ | |
if(!cmd) | |
{ | |
if(!(cmd = (char *) malloc(1))) goto err; | |
*cmd = c; | |
continue; | |
} | |
if(!(cmd = (char *) realloc(cmd, i + 1))) goto err; | |
cmd[i] = c; | |
} | |
if(cmd) | |
{ | |
cmd = (char *) realloc(cmd, i + 1); | |
cmd[i] = 0; | |
} | |
else continue; | |
for(i = 0; cmd[i]; i++) | |
{ | |
if(cmd[i] != ' ') | |
{ | |
for(j = 0; cmd[i] && cmd[i] != ' '; j++) | |
i++; | |
if(!cmd_args) | |
{ | |
if(!(cmd_args = (char **) malloc(sizeof(char *)))) goto err; | |
} | |
else if(!(cmd_args = (char **) realloc(cmd_args, sizeof(char *) * (arr_count + 1)))) goto err; | |
cmd_args[arr_count] = (char *) malloc(j + 1); | |
snprintf(cmd_args[arr_count++], j + 1, "%s", cmd + i - j); | |
} | |
if(!cmd[i]) | |
{ | |
if(!(cmd_args = (char **) realloc(cmd_args, sizeof(char *) * (arr_count + 1)))) goto err; | |
cmd_args[arr_count] = (char *) 0; | |
break; | |
} | |
} | |
switch(my_builtins(*cmd_args)) | |
{ | |
case 1: | |
exit(0); | |
case 2: | |
if(!cmd_args[1]) | |
{ | |
if(chdir(getenv("HOME")) < 0) | |
fprintf(stderr, "chdir: Cannot change to HOME.\n"); | |
} | |
else if(chdir(cmd + strlen(*cmd_args) + 1) < 0) | |
fprintf(stderr, "chdir: Cannot change to %s.\n", cmd + strlen(*cmd_args) + 1); | |
break; | |
default: | |
my_system(cmd_args); | |
} | |
for(i = 0; cmd_args[i]; i++) | |
free(cmd_args[i]); | |
free(cmd_args); | |
free(cmd); | |
} | |
return 0; | |
err: | |
fprintf(stderr, "Failed to allocate memory.\n"); | |
return -1; | |
} | |
void my_system(char **param) | |
{ | |
if(fork()) wait(NULL); | |
else if(execvp(*param, param) < 0) | |
{ | |
fprintf(stderr, "%s: Command not found.\n", *param); | |
exit(0); | |
} | |
} | |
int my_builtins(char *param) | |
{ | |
int i, ret = 0; | |
for(i = 0; param[i] && "exit"[i]; i++) | |
{ | |
if(param[i] == "exit"[i]) ret++; | |
else | |
{ | |
ret = 0; | |
break; | |
} | |
} | |
if(strlen(param) == ret && strlen("exit") == ret) return ret = 1; | |
else for(i = 0; param[i] && "chdir"[i]; i++) | |
{ | |
if(param[i] == "chdir"[i]) ret++; | |
else | |
{ | |
ret = 0; | |
break; | |
} | |
} | |
if(strlen(param) == ret && strlen("chdir") == ret) return ret = 2; | |
else return ret = 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment