#include #include #include #include #include #include #include #include #define true (1) #define false (0) char* _cmd_app; char* _cmd_buffer; char** _cmd_parsed_buffer; static int _cmd_buffer_position = 0; static int _cmd_parsed_buffer_position = 0; static int running_job = 0; uint32_t _is_cmd_internal(); void _cmd_buffer_clear(); void _cmd_loop(); void _cmd_loop_start(); void _cmd_loop_end(); void _cmd_input(); void _cmd_processor(); char _cmd_is_ascii(uint32_t key); char _cmd_cmp_command(const char*); int16_t _cmd_find_cmd_handler(); uint32_t _cmd_getkeycode(); enum internal_cmd_code { CMD_NONE = 0, CMD_CD, CMD_SET, CMD_UNSET, CMD_ENV, }; uint32_t _is_cmd_internal() { if (memcmp(_cmd_buffer, "cd", 2) == 0) { return CMD_CD; } if (memcmp(_cmd_buffer, "set", 3) == 0) { return CMD_SET; } if (memcmp(_cmd_buffer, "env", 3) == 0) { return CMD_ENV; } if (memcmp(_cmd_buffer, "unset", 5) == 0) { return CMD_UNSET; } return CMD_NONE; } int _cmd_do_internal(uint32_t code) { if (code == CMD_CD) { return chdir(_cmd_parsed_buffer[1]); } if (code == CMD_SET) { char* eqpos = strchr(_cmd_parsed_buffer[1], '='); if (!eqpos) { return 0; } *eqpos = '\0'; return setenv(_cmd_parsed_buffer[1], (char*)(eqpos + 1), 1); } if (code == CMD_UNSET) { return unsetenv(_cmd_parsed_buffer[1]); } if (code == CMD_ENV) { for (int i = 0; environ[i]; i++) { const char* envv = environ[i]; char* eqpos = strchr(envv, '='); if (!eqpos) { continue; } size_t len = strlen(envv); write(STDOUT, envv, len); write(STDOUT, "\n", 1); } } return 0; } void _cmd_buffer_clear() { _cmd_buffer_position = 0; } void _cmd_loop() { for (;;) { _cmd_loop_start(); _cmd_input(); _cmd_processor(); _cmd_loop_end(); } } void _cmd_input() { _cmd_buffer_position = read(STDIN, _cmd_buffer, 256); while (_cmd_buffer_position < 0) _cmd_buffer_position = read(STDIN, _cmd_buffer, 256); } void _cmd_processor() { _cmd_parsed_buffer_position = 0; char is_prev_space = true; for (int i = 0; i < _cmd_buffer_position; i++) { if (_cmd_buffer[i] == ' ') { if (is_prev_space == false) { /* null terminator when args are sent */ _cmd_buffer[i] = '\0'; } is_prev_space = true; } else { if (is_prev_space) { _cmd_parsed_buffer[_cmd_parsed_buffer_position++] = (char*)((char*)_cmd_buffer + i); } is_prev_space = false; } } /* Remove \n */ _cmd_buffer[_cmd_buffer_position - 1] = '\0'; _cmd_parsed_buffer[_cmd_parsed_buffer_position] = 0; /* We try to launch an app */ uint32_t cmd = _is_cmd_internal(); if (cmd == CMD_NONE) { uint32_t namelen = strlen(_cmd_parsed_buffer[0]); memcpy(_cmd_app + 5, _cmd_buffer, namelen + 1); int res = fork(); if (!res) { // We don't pass an app name to args. execve(_cmd_app, &_cmd_parsed_buffer[0], environ); exit(-1); } else { running_job = res; wait(res); } } else { _cmd_do_internal(cmd); } } void _cmd_loop_start() { write(1, "> ", 2); } void _cmd_loop_end() { _cmd_buffer_clear(); write(1, "\n", 1); } char _cmd_is_ascii(uint32_t key) { return 32 <= key && key <= 126; } void inter(int no) { kill(running_job, 9); return; } int main() { sigaction(3, inter); ioctl(0, TIOCSPGRP, getpgid(getpid())); ioctl(0, TIOCGPGRP, 0); _cmd_app = malloc(256); _cmd_buffer = malloc(256); _cmd_parsed_buffer = malloc(256 * sizeof(char*)); memcpy(_cmd_app, "/bin/", 5); _cmd_loop(); return 0; }