#include <tce/syscall.h>
#include <tce/vfs.h>
#include <stdlib.h>
#include <stdio.h>
#include <readline.h>
#include <IO/IOStream.h>
#include <IO/Dir.h>
Dir *cwd_f;
String cwd;
void about() {
stdio << "Trivial/Computing Environment v0.1.0 - yosh 3.\n";
}
void help(String *args) {
if (!args[1]) {
stdio << "Available commands: about, help, exit, ls, cd, goto.\n";
} else if (args[1] == "about") {
stdio << "Usage:\tabout\nShows some info about yosh. Very usefull.\n";
} else if (args[1] == "help") {
stdio << "Usage:\thelp\n\thelp <command>\n"
<< "Shows some info about the command you want, or commands in general.\n";
} else if (args[1] == "exit") {
stdio << "Usage:\texit\n"
<< "Exits the shell.\nWill probably make your system panic if you only have a shell running.\n";
} else if (args[1] == "cd") {
stdio << "Usage:\tcd <location>\nGoes to the location specified.\n";
} else if (args[1] == "ls") {
stdio << "Usage:\tls\n\tls <location>...\nShows the content of the current/specified directory.\n";
} else if (args[1] == "goto") {
stdio << "Usage:\tgoto <vt name>\nSwitchs focus to specified virtual terminal.\n"
<< "Type `ls /.ui` to see available terminals.\n";
} else {
stdio.printf("No such command: %s\n", args[1].c_str());
}
}
void cd(String *args) {
if (!args[1]) {
stdio << "Usage: cd <directory>\n";
}
if (args[1] == ".") return;
String newcwd = path_cat(cwd, args[1]);
Dir *newdir = new Dir(newcwd.c_str(), 0);
if (newdir->error == E_NOT_FOUND) {
stdio << "No such file or directory.\n";
} else if (newdir->error == E_INVALID_TYPE) {
stdio << "Not a directory.\n";
} else if (newdir->error != 0) {
stdio.printf("Error stating: %i\n", newdir->error);
} else {
cwd_f->close();
cwd = newcwd;
cwd_f = newdir;
}
}
void ls_dir(Dir *d) {
if (d->error != 0) {
return;
}
d->pos = 0;
for (String name = d->read_ent(); name; name = d->read_ent()) {
if (name == "." || name == "..") continue;
stdio.printf(" %s", name.c_str());
Node child(d->fd, name.c_str(), 0);
if (child.info.type & FT_DIR) stdio << "/";
stdio << " \t";
if (child.info.type & FT_FILE) stdio << "file ";
if (child.info.type & FT_DIR) stdio << "dir ";
if (child.info.type & FT_SYMLINK) stdio << "symlink ";
if (child.info.type & FT_DEV) stdio << "dev ";
if (child.info.type & FT_TERMINAL) stdio << "term ";
stdio << "\t";
if (child.info.type & FT_TERMINAL) {
stdio.printf("%ix%i", child.info.size >> 16, child.info.size & 0xFFFF);
} else if ((child.info.type & FT_DEV) == 0) {
stdio.printf("%i", child.info.size);
}
stdio << "\n";
}
}
void ls(String *args) {
if (!args[1]) {
ls_dir(cwd_f);
} else {
int i;
for (i = 1; args[i]; i++) {
stdio.printf("Contents of %s :\n", args[i].c_str());
String d = path_cat(cwd, args[i].c_str());
Dir dir(d.c_str(), 0);
if (dir.error == E_NOT_FOUND) {
stdio << " No such file or directory\n";
} else if (dir.error == E_INVALID_TYPE) {
stdio.printf(" Not a directory.\n");
} else if (dir.error < 0) {
stdio.printf(" Error stating: %i\n", dir.error);
} else {
ls_dir(&dir);
dir.close();
}
}
}
}
void cat(String *args) {
int i;
for (i = 1; args[i]; i++) {
String d = path_cat(cwd, args[i], false);
file_info info;
int e = libc::stat(d.c_str(), &info);
if (e == E_NOT_FOUND) {
stdio.printf("No such file: %s\n", d.c_str());
} else if (e < 0) {
stdio.printf("Error stating %s : %i\n", d.c_str(), e);
} else if ((info.type & FT_FILE) == 0) {
stdio.printf("Not a file: %s\n", d.c_str());
} else {
FILE ff = libc::open(d.c_str(), 0);
char* buff = (char*)malloc(info.size);
libc::read(ff, 0, info.size, buff);
libc::close(ff);
libc::write(stdio.term->fd, 0, info.size, buff);
free(buff);
}
}
}
void t_goto(String *args) {
if (!args[1]) {
stdio << "Usage: goto <vt_name>\n";
return;
}
String p = path_cat("/.ui/", args[1], false);
int i;
if ((i = libc::link(p.c_str(), "/.dev/vgatxt", LM_OUTPUT_TO)) == 0) {
libc::link("/.dev/ps2kbd", p.c_str(), LM_OUTPUT_TO);
} else {
stdio.printf("Error %i\n", i);
}
}
int Main(String *sh_args) {
about();
cwd = "/";
cwd_f = new Dir("/", 0);
String path = path_cat(sh_args[0], "..");
int bg_pr[128], bg_pr_c = 0;
Term *term = stdio.term;
if (term == 0) {
stdio << "Error: no terminal...\n";
return -1;
}
while (1) {
// check for background processes that may have finished
int p = 0;
while (p < bg_pr_c) {
int ret = libc::waitpid(bg_pr[p], 0);
if (ret != E_NOT_FINISHED) {
stdio.printf("(yosh) child (pid %i) exited with status %i\n", bg_pr[p], ret);
bg_pr_c--;
bg_pr[p] = bg_pr[bg_pr_c];
} else {
p++;
}
}
// show prompt
stdio.printf("\x1b[33m %s \x1b[1m", cwd.c_str());
String s = term->readline();
stdio.printf("\x1b[0m");
if (s.size() == 0) continue;
String c_args[16];
int argc = 0, start = 0;
for (int i = 0; i < s.size(); i++) {
if (s[i] == ' ') {
if (start == i) {
start++;
} else {
c_args[argc] = s.substr(start, i - start);
argc++;
start = i + 1;
if (argc == 15) {
break;
}
}
}
}
c_args[argc++] = s.substr(start, s.size() - start);
if (c_args[0] == "about") {
about();
} else if (c_args[0] == "help") {
help(c_args);
} else if (c_args[0] == "exit") {
stdio << "Exiting the shell. See you later!\n";
break;
} else if (c_args[0] == "cd") {
cd(c_args);
} else if (c_args[0] == "ls") {
ls(c_args);
} else if (c_args[0] == "goto") {
t_goto(c_args);
} else if (c_args[0] == "cat") {
cat(c_args);
} else {
FILE vt = term->fd;
String *first_arg = c_args ;
String t;
if (c_args[0] == "on") {
if (!c_args[1] || !c_args[2]) {
stdio.printf("Usage:\ton <vt> <command>\n");
continue;
}
t = path_cat("/.ui/", c_args[1], false);
vt = libc::open(t.c_str(), 0);
if (vt < 0 || vt == term->fd) {
stdio.printf("Error: cannot open terminal %s (%i)\n", t.c_str(), vt);
continue;
}
first_arg += 2;
}
String c;
if (libc::strchr(first_arg->c_str(), '/')) {
c = path_cat(cwd, *first_arg, false);
} else {
c = path_cat(path, *first_arg, false);
}
first_arg++;
const char *run_args[15] = {0};
for (int i = 0; first_arg[i]; i++) run_args[i] = first_arg[i].c_str();
int pid = libc::run(c.c_str(), run_args, vt);
if (pid <= 0) {
if (pid == E_NOT_FOUND) {
stdio.printf("Error: no such file %s\n", c.c_str());
} else {
stdio.printf("Error %i\n", pid);
}
} else {
if (vt == term->fd) {
int ret = libc::waitpid(pid, 1);
stdio.printf("(yosh) child (pid %i) exited with status %i\n", pid, ret);
} else {
stdio.printf("(yosh) running on terminal %s, pid:%i\n", t.c_str(), pid);
bg_pr[bg_pr_c++] = pid;
}
}
}
}
return 0;
}