db7020cbce
This update includes support for shadow passwords, stored in /etc/master.passwd, as well as support for an /etc/passwd file containing user/uid/full name/shell associations, which are used by the shell to get your username for display purposes, as well as by whoami for the same reason. The login tool does not yet select the right shell though this is planned. * root's password is `toor` (a throwback to older times) * local's password is `local` (because it's obvious)
210 lines
4.2 KiB
C
210 lines
4.2 KiB
C
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
|
* E-Shell
|
|
*
|
|
* Test shell for ToAruOS
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <syscall.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <time.h>
|
|
|
|
DEFN_SYSCALL1(wait, 17, unsigned int);
|
|
|
|
DEFN_SYSCALL2(getcwd, 29, char *, size_t);
|
|
DEFN_SYSCALL1(chdir, 28, char *);
|
|
|
|
DEFN_SYSCALL0(getuid, 23);
|
|
|
|
#define LINE_LEN 4096
|
|
|
|
char cwd[1024] = {'/',0};
|
|
struct timeval {
|
|
unsigned int tv_sec;
|
|
unsigned int tv_usec;
|
|
};
|
|
|
|
char username[1024];
|
|
|
|
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);
|
|
}
|
|
|
|
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);
|
|
printf("\033[1m[\033[1;33m%s \033[1;32m%s \033[1;31m%s \033[1;34m%s\033[0m ",
|
|
username, "esh", date_buffer, time_buffer);
|
|
if (ret != 0) {
|
|
printf("\033[1;31m%d ", ret);
|
|
}
|
|
syscall_getcwd(cwd, 1024);
|
|
printf("\033[0m%s\033[1m]\033[0m\n\033[1;32m$\033[0m ", cwd);
|
|
fflush(stdout);
|
|
}
|
|
|
|
int readline(char * buf, size_t size) {
|
|
size_t collected = 0;
|
|
char * cmd = malloc(2);
|
|
while (collected < size - 1) {
|
|
size_t nread = fread(cmd, 1, 1, stdin);
|
|
if (nread > 0) {
|
|
if (cmd[0] == 8) {
|
|
/* Backspace */
|
|
if (collected > 0) {
|
|
collected--;
|
|
buf[collected] = '\0';
|
|
printf("%c", cmd[0]);
|
|
fflush(stdout);
|
|
}
|
|
continue;
|
|
}
|
|
if (cmd[0] < 10 || (cmd[0] > 10 && cmd[0] < 32) || cmd[0] > 126) {
|
|
continue;
|
|
}
|
|
buf[collected] = cmd[0];
|
|
printf("%c", cmd[0]);
|
|
fflush(stdout);
|
|
if (buf[collected] == '\n') {
|
|
collected++;
|
|
goto _done;
|
|
}
|
|
collected++;
|
|
}
|
|
}
|
|
_done:
|
|
buf[collected] = '\0';
|
|
return collected;
|
|
}
|
|
|
|
int main(int argc, char ** argv) {
|
|
int pid = getpid();
|
|
int nowait = 0;
|
|
int free_cmd = 0;
|
|
int last_ret = 0;
|
|
|
|
getusername();
|
|
|
|
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);
|
|
}
|
|
|
|
while (1) {
|
|
char * cmd = malloc(sizeof(char) * 1024);
|
|
|
|
draw_prompt(last_ret);
|
|
#if 0
|
|
fgets(cmd, 1024, stdin);
|
|
#endif
|
|
readline(cmd, 1024);
|
|
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;
|
|
if (!tokens[0] || strlen(tokens[0]) < 1) {
|
|
free(cmd);
|
|
continue;
|
|
}
|
|
if (!strcmp(tokens[0],"exit")) {
|
|
goto exit;
|
|
}
|
|
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);
|
|
continue;
|
|
}
|
|
nowait = (!strcmp(tokens[i-1],"&"));
|
|
|
|
/* Attempt to open the command */
|
|
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) {
|
|
printf("Command not found: %s\n", tokens[0]);
|
|
last_ret = 1;
|
|
free(cmd);
|
|
continue;
|
|
}
|
|
fclose(file);
|
|
} else {
|
|
file = fopen(tokens[0], "r");
|
|
if (!file) {
|
|
printf("Command not found: %s\n", tokens[0]);
|
|
last_ret = 1;
|
|
free(cmd);
|
|
continue;
|
|
}
|
|
fclose(file);
|
|
}
|
|
|
|
|
|
uint32_t f = fork();
|
|
if (getpid() != pid) {
|
|
int i = execve(cmd, tokens, NULL);
|
|
return i;
|
|
} else {
|
|
if (!nowait) {
|
|
last_ret = syscall_wait(f);
|
|
}
|
|
free(cmd);
|
|
}
|
|
}
|
|
exit:
|
|
|
|
return 0;
|
|
}
|