Today I want to talk about how to write a simple shell program.
First of all you should know that the shell program is an interact program in most mainstream Linux/Unix system. It performs a sequence of read/evaluate steps. The read step reads a command line from the user. The evaluate step parses the command and runs the program on behalf of the user. And I will show you a simple implement of the shell program, which called shell_simple.
The code is as follows, Here we omit the error check to simplify the code:
//shell_simple.c
void eval(const char *command);
bool parseline(char *buf, char *argv[]);
int main() {
char *command;
while(1) {
printf("> ");
fgets(command, MAXLINE, stdin))//never use gets
if(feof(stdin))
exit(0);
eval(command);
}
return 0;
}
void eval(const char *command) {
char buf[MAXLINE];
char *argv[MAXARGS];
strcpy(buf,command);
int bg; //if bg != 0, run in the background
bg = parseline(buf, argv);
if(strcmp(argv[0],"exit"))
exit(0);
pid_t pid;
if((pid = fork()) == 0) { // child process
if(0 > exectv(argv[0], argv, environ)) {
fprintf(stderr, "%s : Command not exist\n", argv[0]);
return;
}
}
if(!bg) { // parent wait for abort of child
int status;
waitpid(pid, &status, 0);
} else {
printf("[%d] %s\n",pid, command);
}
}
bool parseline(char *buf, char *argv[]) {
char *space_pointer;
buf[strlen(buf) - 1] = ' '; // replace the tailing '\n' with space
while(*buf == ' ') // ignore leading spaces
++ buf;
int argc = 0;
while(NULL != (space_pointer = strchr(buf, ' '))) { // find the pos of the first space
argv[argc++] = buf;
space_pointer = '\0';
buf = space_pointer + 1;
while(*buf == ' ')
++ buf;
}
argv[argc] = NULL;
if(argc == 0)
return 1;
int bg;
if((bg = (argv[argc - 1] == '&')) != 0) { // should run in background
argv[--argc] = NULL;
}
return bg;
}
This is the simple implement of shell program , it has some drawbacks e.g. it must use the full path to execute a command and it does not reap the child process. I will improve it in the future.
Welcome to communicate with me on this~