191 lines
4.0 KiB
C
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;
|
||
|
|
}
|