134 lines
2.4 KiB
C
134 lines
2.4 KiB
C
#include <luna.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/wait.h>
|
|
#include <unistd.h>
|
|
|
|
typedef struct
|
|
{
|
|
char* buffer;
|
|
long size;
|
|
long capacity;
|
|
} command;
|
|
|
|
void show_prompt()
|
|
{
|
|
printf("> ");
|
|
}
|
|
|
|
void command_expand(command* cmd, long new_capacity)
|
|
{
|
|
char* buffer = realloc(cmd->buffer, new_capacity);
|
|
if (!buffer)
|
|
{
|
|
perror("realloc");
|
|
exit(1);
|
|
}
|
|
cmd->buffer = buffer;
|
|
cmd->capacity = new_capacity;
|
|
}
|
|
|
|
void command_push(command* cmd, char c)
|
|
{
|
|
if (cmd->size == cmd->capacity) command_expand(cmd, cmd->capacity + 8);
|
|
cmd->buffer[cmd->size] = c;
|
|
cmd->size++;
|
|
}
|
|
|
|
void command_pop(command* cmd)
|
|
{
|
|
cmd->size--;
|
|
}
|
|
|
|
void command_init(command* cmd)
|
|
{
|
|
cmd->buffer = malloc(5);
|
|
cmd->capacity = 5;
|
|
cmd->size = 0;
|
|
}
|
|
|
|
void command_clear(command* cmd)
|
|
{
|
|
free(cmd->buffer);
|
|
return command_init(cmd);
|
|
}
|
|
|
|
void command_execute(command* cmd)
|
|
{
|
|
command_push(cmd, '\0');
|
|
pid_t child = fork();
|
|
if (child < 0)
|
|
{
|
|
perror(cmd->buffer);
|
|
command_clear(cmd);
|
|
show_prompt();
|
|
return;
|
|
}
|
|
if (child == 0)
|
|
{
|
|
execv(cmd->buffer, NULL);
|
|
perror(cmd->buffer);
|
|
exit(127);
|
|
}
|
|
int status;
|
|
pid_t result;
|
|
while ((result = waitpid(child, &status, 0)) == 0) { msleep(20); }
|
|
if (result < 0)
|
|
{
|
|
perror("waitpid");
|
|
command_clear(cmd);
|
|
show_prompt();
|
|
return;
|
|
}
|
|
if (WEXITSTATUS(status) != 0) { printf("Exited with code %d\n", WEXITSTATUS(status)); }
|
|
command_clear(cmd);
|
|
show_prompt();
|
|
}
|
|
|
|
void command_concat(command* cmd, const char* str)
|
|
{
|
|
while (*str)
|
|
{
|
|
putchar(*str);
|
|
if (*str == '\b') { command_pop(cmd); }
|
|
else if (*str == '\n') { command_execute(cmd); }
|
|
else
|
|
command_push(cmd, *str);
|
|
str++;
|
|
}
|
|
}
|
|
|
|
int main()
|
|
{
|
|
FILE* fp = fopen("/dev/kbd", "r");
|
|
if (!fp)
|
|
{
|
|
perror("fopen");
|
|
return 1;
|
|
}
|
|
|
|
show_prompt();
|
|
|
|
char buffer[33];
|
|
|
|
command shell_command;
|
|
command_init(&shell_command);
|
|
|
|
while (1)
|
|
{
|
|
size_t nread = fread(buffer, sizeof(buffer) - 1, 1, fp);
|
|
if (ferror(fp))
|
|
{
|
|
perror("fread");
|
|
return 1;
|
|
}
|
|
if (feof(fp))
|
|
{
|
|
clearerr(fp);
|
|
msleep(20);
|
|
continue;
|
|
}
|
|
buffer[nread] = 0;
|
|
command_concat(&shell_command, buffer);
|
|
}
|
|
} |