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