#include #include #include #include #include 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); } }