8/09/2008

Implement Simple Shell - UNIX System Programming

I implemented a simple shell in programming language C with UNIX system calls. Now it has only following functions, but I will add some functions(Redirection, Pipe, Background running, ...) in future.
  1. Run inputed commands.
  2. "exit" command.
Code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>

#define MAX_ARGS 10
#define MAX_LEN  100

void child(int argc, char *argv[MAX_ARGS]);

int main()
{
  int argc, n = 0;
  int status;
  char input[MAX_LEN], *argv[MAX_ARGS], *cp;
  const char *delim = " \t\n"; /* delimiters of commands */

  while (1) {
    /* show a prompt */
    ++n;
    printf("command[%d] ", n); 

    /* read a line */
    if (fgets(input, sizeof(input), stdin) == NULL) {
      /* inputed EOF(Ctrl-D) */
      printf("Goodbye!\n");
      exit(0);
    }

    /* split the input to commands with blank and Tab */
    cp = input;
    for (argc = 0; argc < MAX_ARGS; argc++) {
      if ((argv[argc] = strtok(cp,delim)) == NULL)
        break;
      cp = NULL;
    }
    /* exit this shell when "exit" is inputed */
    if(strcmp(argv[0], "exit") == 0) {
      printf("Goodbye!\n");
      exit(0);
    }
    pid_t pid = fork();
    if(pid == -1) {
 /* failed to fork() */
      perror("fork");
      exit(1);
    } else if(pid == 0) {
 /* child process */
      child(argc, argv);
    } else {
 /* parent process */
      wait(&status);
    }
  }
}

void child(int argc, char *argv[MAX_ARGS]) {
  execvp(argv[0], argv);
}
Result
****@ubuntu-vm:~/work/os$ gcc -Wall s_shell.c
****@ubuntu-vm:~/work/os$ ./a.out
command[1] ls
#ex01.c#  execlp0.c   fileio1.c~  fileio4.c~  s_shell.c
a.out     execve0.c   fileio2.c   foo         system0.c
ex1.c     execve0.c~  fileio2.c~  fork0.c     wait0.c
ex1.c~    fileio0.c   fileio3.c   fork0.c~    wait0.c~
ex2.c     fileio0.c~  fileio3.c~  hello.c
ex2.c~    fileio1.c   fileio4.c   httpget.c
command[2] cat hello.c
#include <stdio.h>
int main() {
  printf("hello, world!\n");
  return 0;
}
command[3] gcc -Wall hello.c
command[4] ./a.out
hello, world!
command[5] exit
Goodbye!
****@ubuntu-vm:~/work/os$ 
Reference site Original Text(Japanese)

1 comment:

ish said...

wow. thanks for posting this. it helped me with my problem regarding execvp(). oh by the way, why did you created a function child() instead of just putting execvp() on the main?