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>

#define INPUTBUFFER_INITIAL_CAPACITY 0x100
#define ARGV_INITIAL_CAPACITY 0x10

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

/*  A dynamic implementation of readline(), which I don't use as it is a
    GNU extension and no part of the Ansi-C standard.
    This function basically reads data from stdin until encountering a newline
    and returns an allocated buffer which shall be freed by the caller */
static char* read_input()
{
  char cur; /* Most recently read char from stdin */
  char* buf; /* Buffer to store bytes read from stdin */
  unsigned int buflen; /* Length of the allocated buffer */
  unsigned int put = 0; /* Current put position of the buffer */
 
  /* Allocate buffer */
  buf = malloc(INPUTBUFFER_INITIAL_CAPACITY);
  if(!buf)
    CRITICAL_ERROR("read_input() : malloc error."); 
  buflen = INPUTBUFFER_INITIAL_CAPACITY;

  /* Loop reading characters from stdin until encountering newline */ 
  while( (cur = getchar()) != '\n')
  {
    /* If we reached capacity, double buffersize */
    if(put >= buflen - 1) /* -1 because we need to store a nullbyte */
    {
      buf = realloc(buf, buflen * 2);
      if(!buf)
        CRITICAL_ERROR("read_input() : realloc error."); 
      buflen *= 2;
    }

    /* Append character to buffer */
    buf[put++] = cur;
  }

  /* We are done, append nullbyte and return */
  buf[put] = 0;
  return buf;
}

/*  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 of 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 */

  /* Loop until an error occurs */
  while(1)
  {
    /* Print prompt :) */
    printf("Mastershell > ");

    /* Retrieve data from stdin, parse it and free input buffer */
    input = read_input();
    avector = parse_args(input, &acount;);
    free(input);

    /* 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: