Welcome, guest! Login / Register - Why register?
Psst.. new poll here.
Psst.. new forums here.
Microsoft is blocking us again (TY IP Reputation!) so just use oauth login instead. :)

Paste

Pasted as C by flo ( 15 years ago )
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
 
#define INPUTBUFFER_INITIAL_CAPACITY 0x100
#define ARGV_INITIAL_CAPACITY 0x10
#define PROMPT_BUFFER_SIZE 0x400

#define CRITICAL_ERROR(x) { printf(x); exit(1); }

/* Builds prompt to be displayed */
char g_prompt[PROMPT_BUFFER_SIZE];
const char* g_default_prompt = "Enter command: ";
int build_prompt(void)
{
 unsigned int len = 0;
 int ec;
 ec = getlogin_r(g_prompt, PROMPT_BUFFER_SIZE);
 if(ec)
 {
  strcpy(g_prompt, g_default_prompt);
  return;
 }
 strcat(g_prompt, " on ");
 
 len = strlen(g_prompt);
 ec = gethostname(g_prompt + (len), PROMPT_BUFFER_SIZE - len - 1);
 if(ec == -1)
 {
  strcpy(g_prompt, g_default_prompt);
  return;
 }
 strcat(g_prompt, " : ");
 
 len = strlen(g_prompt);
 if(!getcwd(g_prompt + (len), PROMPT_BUFFER_SIZE - len - 1))
 {
  strcpy(g_prompt, g_default_prompt);
  return;
 }
 strcat(g_prompt, " ~> ");
}

/* Returns the current prompt */
const char* get_prompt(void)
{
 return g_prompt;
}

/* Changes to the specified directory */
int builtin_cd(const char* dir)
{
 int res = chdir(dir) == 0 ? 1 : 0;
 if(res)
  build_prompt();
  
 return res;
}
 
/*  This function parses an input string and generates argument vector and
    argument count for them.
    The buffer returned shall be freed by the caller  */
char** parse_args(char* data, int* out_argc)
{
  char** buf; /* Buffer to store argv items */
  unsigned int buflen; /* Length of the allocated buffer */
  unsigned int put = 0; /* Current put position into the buffer */
  char* token; /* Stores an extracted token */
 
  /* Allocate buffer */
  buf = malloc(ARGV_INITIAL_CAPACITY * sizeof(char*));
  if(!buf)
    CRITICAL_ERROR("parse_args() : malloc error.");
  buflen = ARGV_INITIAL_CAPACITY;
 
  /* Extract first argument and add it to buffer */
  token = strtok(data, " ");
  buf[put] = malloc(strlen(token) + 1); /* +1 for nullbyte */
  strcpy(buf[put], token);
  ++put;
  *out_argc = 1;
 
  /* Extract further arguments */
  while( (token = strtok(NULL, " ")) != NULL)
  {
    /* If we reached capacity, double buffersize */
    if(put >= buflen - 1) /* -1 because we need to store a nullbyte */
    {
      buf = realloc(buf, buflen * sizeof(char*) * 2);
      if(!buf)
        CRITICAL_ERROR("parse_args() : realloc error.");
      buflen *= 2;
    }
 
    /* Add argument to buffer */
    buf[put] = malloc(strlen(token) + 1); /* +1 for nullbyte */
    strcpy(buf[put], token);
    ++put;
    ++(*out_argc);
  }
 
  /* We are done, append nullptr (for execvp) and return */
  buf[put] = NULL;
  return buf;
}
 
/*  Function freeing buffer returned by parse_args */
void free_ptrvector(char** vec, int size)
{
  int i; /* Index into the vector */
 
  /* Free every single item */
  for(i = 0; i < size; ++i)
    free(vec[i]);
 
  /* Free storage */
  free(vec);
}
 
int main(int argc, char** argv)
{
  char* input; /* Input read from stdin */
  char** avector; /* Parsed arguments */
  int acount; /* Amount of parsed arguments */
  int pid; /* fork() return value */
  int result;
  
  /* Loop until an error occurs */
  build_prompt();
  while(1)
  {
    /* Retrieve data from stdin, parse it and free input buffer */
  input = readline(get_prompt());
  if(!strlen(input))
  {
   free(input);
   continue;
  }
  
    avector = parse_args(input, &acount;);
    free(input);
    
   /* Handle cd command */
   if(strcmp(avector[0], "cd"))
   {
    if(acount < 2 || !builtin_cd(avector[1]))
     printf("%", "Could not change directory\n");
     
    free_ptrvector(avector, acount);
    continue;
   }  
    
    /* Fork! */
    if( (pid = fork()) == -1)
    {
      /* -1 means fork() failed !
          Free buffer and exit */
 
      free_ptrvector(avector, acount);
      CRITICAL_ERROR("fork() failed.");
    }
    else if(pid == 0)
    {
      /*  Child !
          execvp() and pass all passed arguments */
      if(execvp(avector[0], avector) == -1)
      {
        /*  execvp() returned, so an error occurred !
            Free buffer and exit */
 
        free_ptrvector(avector, acount);
        CRITICAL_ERROR("execvp() failed.")
      }
    }
    else
    {
      /*  Parent !
          Wait until child terminates */
      errno = 0;
      if(wait(pid) != pid)
      {
        /*  -1 means wait() failed !
            Free buffer and exit */
        int error = errno;
        printf("%d", error);
        free_ptrvector(avector, acount);
        CRITICAL_ERROR("wait() failed.")
       
      }
 
      free_ptrvector(avector, acount);
    }
  }
}

 

Revise this Paste

Your Name: Code Language: