Skip to content

Instantly share code, notes, and snippets.

@gceylan
Created April 1, 2013 04:46
Show Gist options
  • Save gceylan/5283280 to your computer and use it in GitHub Desktop.
Save gceylan/5283280 to your computer and use it in GitHub Desktop.
simple shell
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <libgen.h>
#include <readline/readline.h>
#include <readline/history.h>
#define ARGV_SIZE 1<<16
#define TRUE 1
#define FALSE 0
const char *history = "/.gceylan_sheel_history/history";
const int history_count = 20;
void parse_args(char *buffer, char **args, int args_size, int *nargs)
{
char *buffer_args[args_size];
char **p;
char *wbuf;
int i, j;
wbuf = buffer;
buffer_args[0] = buffer;
args[0] = buffer;
i = 0, j = 0;
for (p = buffer_args; (*p = strsep(&wbuf, " \n\t")) != NULL; )
{
if ((*p != '\0') && (++p >= &buffer_args[args_size]))
break;
}
for (i = 0, j = 0; buffer_args[i] != NULL; i++)
{
if (strlen(buffer_args[i]) > 0)
args[j++] = buffer_args[i];
}
*nargs = j;
args[j] = NULL;
}
int main(void)
{
char *input, shell_prompt[100];
rl_bind_key('\t', rl_complete);
char *argv[ARGV_SIZE];
int ret;
int argc;
pid_t pid;
// readline entegre kodları
char *cp, *history_filename;
char tmp_filename[200];
struct stat st;
using_history(); /* initial readline history */
rl_initialize(); /* initial readline */
stifle_history(history_count); /* maximum of 20 history commands */
rl_inhibit_completion = TRUE;
strcpy(tmp_filename, getenv("HOME"));
strcat(tmp_filename, history);
history_filename = strdup(tmp_filename);
if (!history_filename)
{
perror("strdup");
exit(EXIT_FAILURE);
}
cp = dirname(tmp_filename);
/* Create '$HOME/.readline' directory if it doesn' t exist */
if (lstat(cp, &st))
{
if (mkdir(cp, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH))
{
perror("mkdir");
exit(EXIT_FAILURE);
}
}
else if (!S_ISDIR(st.st_mode))
{
printf("Fatal - File %s exists and is not a directory\n", cp);
exit(EXIT_FAILURE);
}
if (!read_history(history_filename))
printf("Using the %d last commands you entered\n", history_count);
else
printf("History file %s created\n", history_filename);
while (TRUE)
{
snprintf(shell_prompt, sizeof(shell_prompt), "%s:%s $ ", getenv("USER"), getcwd(NULL, 1024));
input = readline(shell_prompt);
// EOF
if (!input) break;
if (*input)
add_history(input);
parse_args(input, argv, ARGV_SIZE, &argc);
if (argc == 0) continue;
if (!strcmp(argv[0], "exit")) break;
pid = fork();
if (pid)
pid = wait(&ret);
else if (pid == -1)
{
perror("fork");
exit(EXIT_FAILURE);
}
else
{
if (execvp(argv[0], argv))
{
perror("execvp");
exit(EXIT_FAILURE);
}
}
free(input);
}
free(input);
printf("Exiting...\n");
if (write_history(history_filename))
{
perror("write_history");
exit(EXIT_FAILURE);
}
free(history_filename);
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment