Skip to content

Instantly share code, notes, and snippets.

@vizv
Last active September 24, 2017 05:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vizv/9710508 to your computer and use it in GitHub Desktop.
Save vizv/9710508 to your computer and use it in GitHub Desktop.
vsh (VShell)
/*
* File: a1p1.c
* Author: Wenxuan Zhao 100108743
* Date: 2013/01/22
* Version: 1.0
*
* Purpose: vsh (V-Shell) first implementation! include only buildin function
* `exit`...
* TODO: > Simplify the error output message
* > Modulize the codes
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#define INIT_SIZE 1
#define ERR_NULL_POINTER -1
#define ERR_OUT_OF_MEMORY -1
#define STR_PROMPT "Yo? "
#define EXIT_CMD_NOT_FOUND 255
/* Abstract List */
typedef struct
{
void *els;
int n_used;
int n_alloc;
int els_size;
} lst_t, *lst_tp;
/*
* Name: new_lst
* Purpose: create a new abstruct list
* Arguments: given the pointer to the pointer of list, and the block size of
* one element
* Output: none
* Modifies: the pointer of list
* Returns: status code
* Assumptions: none
* Bugs: none
* Notes: none
*/
int
new_lst(lst_tp *l, size_t blocksize)
{
/* free existing list & elements in it */
if (*l != NULL)
{
if ((*l)->els != NULL)
free((*l)->els);
free(*l);
}
/* attampt to build a new list */
lst_tp lst = malloc(sizeof(lst_tp));
if (lst != NULL)
{
lst->els = malloc(blocksize * INIT_SIZE);
if (lst->els != NULL)
{
lst->n_used = 0;
lst->n_alloc = INIT_SIZE;
lst->els_size = blocksize;
*l = lst;
return 0;
}
}
return ERR_OUT_OF_MEMORY;
}
/*
* Name: lst_resize
* Purpose: resize the list according to it's current size
* Arguments: given the pointer of list to be resized
* Output: none
* Modifies: the size of list
* Returns: status code
* Assumptions: none
* Bugs: none
* Notes: none
*/
int
lst_resize(lst_tp l)
{
if (l == NULL)
return ERR_NULL_POINTER;
if (l->n_alloc > 3 * l->n_used || l->n_alloc == l->n_used)
{
void *newels = realloc(l->els, l->n_alloc * l->els_size * 2);
if (newels == NULL)
return ERR_OUT_OF_MEMORY;
l->n_alloc *= 2;
l->els = newels;
}
return 0;
}
/*
* Name: lst_append_char
* Purpose: append a char to the list
* Arguments: given the pointer of list, and the char to be append
* Output: none
* Modifies: the element in the list
* Returns: status code
* Assumptions: none
* Bugs: none
* Notes: none
*/
int
lst_append_char(lst_tp l, char c)
{
int ret;
if ((ret = lst_resize(l)))
return ret;
char *p = l->els;
p[l->n_used++] = c;
return 0;
}
/*
* Name: lst_get_char
* Purpose: get a char from the list
* Arguments: given the pointer of list, and index of the char
* Output: none
* Modifies: none
* Returns: the pointer to the char
* Assumptions: none
* Bugs: TODO index unchecked!
* Notes: none
*/
char *
lst_get_char(const lst_tp l, int i)
{
char *p = l->els;
return &p[i];
}
/*
* Name: lst_append_str
* Purpose: append a char string to the list
* Arguments: given the pointer of list, and the pointer of the char string
* to be append
* Output: none
* Modifies: the element in the list
* Returns: status code
* Assumptions: none
* Bugs: none
* Notes: none
*/
int
lst_append_str(lst_tp l, char *s)
{
int ret;
if ((ret = lst_resize(l)))
return ret;
char **p = l->els;
p[l->n_used++] = s;
return 0;
}
/*
* Name: lst_get_str
* Purpose: get the pointer to a char string from the list
* Arguments: given the pointer of list, and index of the char string
* Output: none
* Modifies: none
* Returns: the pointer to the pointer of char string
* Assumptions: none
* Bugs: TODO index unchecked!
* Notes: none
*/
char **
lst_get_str(const lst_tp l, int i)
{
char **p = l->els;
return &p[i];
}
/*
* Name: show_prompt
* Purpose: output the prompt to the standard output
* Arguments: none
* Output: the prompt
* Modifies: none
* Returns: none
* Assumptions: none
* Bugs: none
* Notes: TODO implement various prompt string using $PS1
*/
void
show_prompt()
{
printf(STR_PROMPT);
}
/*
* Name: run_builtin
* Purpose: attampt to run the builtin command
* Arguments: the executable file and the argument list
* Output: none
* Modifies: none
* Returns: none
* Assumptions: none
* Bugs: none
* Notes: TODO implement more builtin command
*/
int
run_builtin(const char *exec, char **argv)
{
if (!strcmp(exec, "exit"))
exit(0);
return 0;
}
int
main(int argc, char *argv[])
{
int i, ret;
pid_t pid;
lst_tp cmd_buffer = NULL, args_list = NULL;
if ((ret = new_lst(&cmd_buffer, sizeof(char))))
{
fprintf(stderr, "%s: FATAL ERROR - Cannot create "
"command buffer (%d).\n", argv[0], ret);
return EXIT_FAILURE;
}
show_prompt();
int c;
for (;;)
{
c = getchar();
switch(c)
{
case '\n':
/* skip if nothing was inputed */
if (!cmd_buffer->n_used)
{
show_prompt();
break;
}
/* make a valid char string */
if ((ret = lst_append_char(cmd_buffer, '\0')))
{
fprintf(stderr, "%s: FATAL ERROR - Something goes wrong "
"while handling input (%d).\n", argv[0], ret);
return EXIT_FAILURE;
}
/* make a new argument list */
if ((ret = new_lst(&args_list, sizeof(char *))))
{
fprintf(stderr, "%s: FATAL ERROR - Cannot create "
"arguments list (%d).\n", argv[0], ret);
return EXIT_FAILURE;
}
/* build exec and arguments */
lst_append_str(args_list, cmd_buffer->els);
for (i = 0; *lst_get_char(cmd_buffer, i) != '\0'; i++)
{
if (*lst_get_char(cmd_buffer, i) == ' ')
{
*lst_get_char(cmd_buffer, i) = '\0';
lst_append_str(args_list, lst_get_char(cmd_buffer, i + 1));
}
}
lst_append_str(args_list, NULL);
char *exec = cmd_buffer->els;
char **args = args_list->els;
/* run built-in commands */
if (!run_builtin(exec, args))
{
/* if failed, run external command */
pid = fork();
if (!pid)
return (ret = execvp(exec, args));
/* wait until finished */
waitpid(pid, &ret, 0);
if (WIFEXITED(ret))
{
if(WEXITSTATUS(ret) == EXIT_CMD_NOT_FOUND)
fprintf(stderr, "%s: command not found\n", exec);
}
}
show_prompt();
if ((ret = new_lst(&cmd_buffer, sizeof(char *))))
{
fprintf(stderr, "%s: FATAL ERROR - Cannot create "
"command buffer (%d).\n", argv[0], ret);
return EXIT_FAILURE;
}
break;
case EOF:
if (!cmd_buffer->n_used)
{
printf("exit\n");
return EXIT_SUCCESS;
}
break;
default:
if ((ret = lst_append_char(cmd_buffer, c)))
{
fprintf(stderr, "%s: FATAL ERROR - Something goes wrong "
"while handling input (%d).\n", argv[0], ret);
return EXIT_FAILURE;
}
}
}
fprintf(stderr, "%s: WARNING - Unexpected Closing.\n", argv[0]);
return EXIT_FAILURE;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment