toaruos/userspace/esh.c

198 lines
4.1 KiB
C
Raw Normal View History

/* vim: tabstop=4 shiftwidth=4 noexpandtab
2011-12-07 05:46:35 +04:00
* E-Shell
*
* This is the "experimental shell". It provides
* a somewhat unix-like shell environment, but does
* not include a parser any advanced functionality.
* It simply cuts its input into arguments and executes
* programs.
2011-12-07 05:46:35 +04:00
*/
#include <stdio.h>
#include <stdint.h>
#include <syscall.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
2011-12-07 05:46:35 +04:00
#define LINE_LEN 4096
char cwd[1024] = {'/',0};
struct timeval {
unsigned int tv_sec;
unsigned int tv_usec;
};
char username[1024];
2012-01-30 22:10:53 +04:00
char _hostname[256];
void getusername() {
FILE * passwd = fopen("/etc/passwd", "r");
char line[LINE_LEN];
int uid = syscall_getuid();
while (fgets(line, LINE_LEN, passwd) != NULL) {
line[strlen(line)-1] = '\0';
char *p, *tokens[10], *last;
int i = 0;
for ((p = strtok_r(line, ":", &last)); p;
(p = strtok_r(NULL, ":", &last)), i++) {
if (i < 511) tokens[i] = p;
}
tokens[i] = NULL;
if (atoi(tokens[2]) == uid) {
memcpy(username, tokens[0], strlen(tokens[0]) + 1);
}
}
fclose(passwd);
}
2012-01-30 22:10:53 +04:00
void gethostname() {
char buffer[256];
size_t len = syscall_gethostname(buffer);
memcpy(_hostname, buffer, len);
}
2012-01-26 00:57:27 +04:00
void draw_prompt(int ret) {
struct tm * timeinfo;
struct timeval now;
syscall_gettimeofday(&now, NULL); //time(NULL);
timeinfo = localtime((time_t *)&now.tv_sec);
char date_buffer[80];
strftime(date_buffer, 80, "%m/%d", timeinfo);
char time_buffer[80];
strftime(time_buffer, 80, "%H:%M:%S", timeinfo);
2012-01-26 00:57:27 +04:00
printf("\033[1m[\033[1;33m%s \033[1;32m%s \033[1;31m%s \033[1;34m%s\033[0m ",
2012-01-30 22:10:53 +04:00
username, _hostname, date_buffer, time_buffer);
2012-01-26 00:57:27 +04:00
if (ret != 0) {
printf("\033[1;31m%d ", ret);
}
2012-01-27 23:10:58 +04:00
syscall_getcwd(cwd, 1024);
2012-01-26 00:57:27 +04:00
printf("\033[0m%s\033[1m]\033[0m\n\033[1;32m$\033[0m ", cwd);
2012-03-17 02:09:00 +04:00
printf("\033]1;%s@%s:%s\007", username, _hostname, cwd);
fflush(stdout);
}
2012-02-08 12:40:44 +04:00
uint32_t child = 0;
void sig_int(int sig) {
2012-02-08 22:04:03 +04:00
static uint32_t times = 1;
2012-02-08 12:40:44 +04:00
if (child) {
syscall_send_signal(child, sig);
} else {
2012-02-08 22:04:03 +04:00
printf("stop that! you've interrupted me %d time%s!\n", times, (times > 1) ? "s" : "");
times++;
2012-02-08 12:40:44 +04:00
}
}
2011-12-07 05:46:35 +04:00
int main(int argc, char ** argv) {
int pid = getpid();
2011-12-08 01:08:40 +04:00
int nowait = 0;
int free_cmd = 0;
2012-01-26 00:57:27 +04:00
int last_ret = 0;
2012-02-08 22:01:25 +04:00
syscall_signal(2, sig_int);
2012-02-08 12:40:44 +04:00
getusername();
2012-01-30 22:10:53 +04:00
gethostname();
FILE * motd = fopen("/etc/motd", "r");
if (motd) {
size_t s = 0;
fseek(motd, 0, SEEK_END);
s = ftell(motd);
fseek(motd, 0, SEEK_SET);
char * m = malloc(sizeof(char) * s);
fread(m, s, 1, motd);
fwrite(m, s, 1, stdout);
fprintf(stdout, "\n");
fflush(stdout);
free(m);
}
2011-12-07 05:46:35 +04:00
while (1) {
2011-12-08 01:08:40 +04:00
char * cmd = malloc(sizeof(char) * 1024);
2012-01-26 00:57:27 +04:00
draw_prompt(last_ret);
2011-12-07 05:46:35 +04:00
fgets(cmd, 1024, stdin);
cmd[strlen(cmd)-1] = '\0';
char *p, *tokens[512], *last;
int i = 0;
for ((p = strtok_r(cmd, " ", &last)); p;
(p = strtok_r(NULL, " ", &last)), i++) {
if (i < 511) tokens[i] = p;
}
tokens[i] = NULL;
2011-12-07 06:36:40 +04:00
if (!tokens[0] || strlen(tokens[0]) < 1) {
2011-12-08 01:08:40 +04:00
free(cmd);
2011-12-07 06:36:40 +04:00
continue;
2011-12-07 05:46:35 +04:00
}
if (!strcmp(tokens[0],"exit")) {
goto exit;
}
2012-01-27 23:10:58 +04:00
if (!strcmp(tokens[0],"cd")) {
if (i > 1) {
if (syscall_chdir(tokens[1]) != 0) {
printf("cd: Could not cd to '%s'.\n", tokens[1]);
last_ret = 1;
}
} else {
printf("cd: expected argument\n");
last_ret = 1;
}
free(cmd);
2012-01-27 23:10:58 +04:00
continue;
}
2011-12-08 01:08:40 +04:00
nowait = (!strcmp(tokens[i-1],"&"));
2012-03-09 09:36:40 +04:00
if (nowait) {
tokens[i-1] = NULL;
}
2011-12-08 01:08:40 +04:00
/* Attempt to open the command */
2012-01-27 23:10:58 +04:00
FILE * file = NULL; //fopen(tokens[0], "r");
if (!strstr(tokens[0],"/")) {
cmd = malloc(sizeof(char) * (strlen(tokens[0]) + strlen("/bin/") + 1));
sprintf(cmd, "%s%s", "/bin/", tokens[0]);
file = fopen(cmd,"r");
if (!file) {
2011-12-08 01:08:40 +04:00
printf("Command not found: %s\n", tokens[0]);
2012-01-27 23:10:58 +04:00
last_ret = 1;
2011-12-08 01:08:40 +04:00
free(cmd);
continue;
}
2012-01-27 23:10:58 +04:00
fclose(file);
2011-12-08 01:08:40 +04:00
} else {
2012-01-27 23:10:58 +04:00
file = fopen(tokens[0], "r");
if (!file) {
printf("Command not found: %s\n", tokens[0]);
last_ret = 1;
free(cmd);
continue;
}
2011-12-08 01:08:40 +04:00
fclose(file);
}
2011-12-07 05:46:35 +04:00
uint32_t f = fork();
if (getpid() != pid) {
2011-12-08 01:08:40 +04:00
int i = execve(cmd, tokens, NULL);
2011-12-07 06:36:40 +04:00
return i;
2011-12-07 05:46:35 +04:00
} else {
2011-12-08 01:08:40 +04:00
if (!nowait) {
2012-02-08 12:40:44 +04:00
child = f;
2012-01-26 00:57:27 +04:00
last_ret = syscall_wait(f);
child = 0;
2011-12-07 06:36:40 +04:00
}
2011-12-08 01:08:40 +04:00
free(cmd);
2011-12-07 05:46:35 +04:00
}
}
exit:
return 0;
}