Files

191 lines
4.0 KiB
C

#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <unistd.h>
#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;
}