Squash commits for public release
This commit is contained in:
5
userland/shell/xsh/.info.mk
Normal file
5
userland/shell/xsh/.info.mk
Normal file
@@ -0,0 +1,5 @@
|
||||
APPS += XSH
|
||||
|
||||
XSH_NAME = xsh
|
||||
XSH_LIBS = c
|
||||
XSH_INSTALL_PATH = bin/
|
||||
8
userland/shell/xsh/BUILD.gn
Normal file
8
userland/shell/xsh/BUILD.gn
Normal file
@@ -0,0 +1,8 @@
|
||||
import("//build/userland/TEMPLATE.gni")
|
||||
|
||||
xOS_executable("xsh") {
|
||||
install_path = "bin/"
|
||||
sources = [ "main.c" ]
|
||||
configs = [ "//build/userland:userland_flags" ]
|
||||
deplibs = [ "libc" ]
|
||||
}
|
||||
190
userland/shell/xsh/main.c
Normal file
190
userland/shell/xsh/main.c
Normal file
@@ -0,0 +1,190 @@
|
||||
#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;
|
||||
}
|
||||
Reference in New Issue
Block a user