summaryrefslogblamecommitdiff
path: root/src/user/app/yosh/main.c
blob: f7ee7e73f761d0ba8b9529d1e6356a8655b6729a (plain) (tree)










































































































































































































































































                                                                                                                     
                                                           























                                                                                                          
#include <tce/syscall.h>
#include <tce/vfs.h>
#include <stdlib.h>
#include <stdio.h>
#include <readline.h>

char *cwd;

void about() {
	printf("Trivial/Computing Environment v0.1.4 - yosh 4.\n");
}

void help(char **args) {
	if (!args[1]) {
		printf("Available commands: about, help, exit, ls, cd, goto.\n");
	} else if (!strcmp(args[1], "about")) {
		printf("Usage:\tabout\nShows some info about yosh. Very usefull.\n");
	} else if (!strcmp(args[1], "help")) {
		printf("Usage:\thelp\n\thelp <command>\n");
		printf("Shows some info about the command you want, or commands in general.\n");
	} else if (!strcmp(args[1], "exit")) {
		printf("Usage:\texit\n");
		printf("Exits the shell.\nWill probably make your system panic if you only have a shell running.\n");
	} else if (!strcmp(args[1], "cd")) {
		printf("Usage:\tcd <location>\nGoes to the location specified.\n");
	} else if (!strcmp(args[1], "ls")) {
		printf("Usage:\tls\n\tls <location>...\nShows the content of the current/specified directory.\n");
	} else if (!strcmp(args[1], "goto")) {
		printf("Usage:\tgoto <vt name>\nSwitchs focus to specified virtual terminal.\n");
		printf("Type `ls /.ui` to see available terminals.\n");
	} else {
		printf("No such command: %s\n", args[1]);
	}
}

void cd(char **args) {
	if (!args[1]) {
		printf("Usage: cd <directory>\n");
	}
	if (!strcmp(args[1], ".")) return;

	char* newcwd = path_cat(cwd, args[1], 1);

	file_info f;
	int r = stat(newcwd, &f);
	if (r == E_NOT_FOUND) {
		printf("No such file or directory.\n");
	} else if (r != 0) {
		printf("Error stating: %i\n", r);
	} else if (!(f.type & FT_DIR)) {
		printf("Not a directory.\n");
	} else {
		free(cwd);
		cwd = newcwd;
		return;
	}
	free(newcwd);
}

void ls_dir(int fd) {
	char buf[256];
	int pos = 0;

	while (read(fd, pos++, 256, buf) > 0) {
		if ((!strcmp(buf, ".")) || (!strcmp(buf,  ".."))) continue;

		printf("  %s", buf);

		file_info info;
		stat_relative(fd, buf, &info);
		if (info.type & FT_DIR) printf("/");
		printf("   \t");

		if (info.type & FT_FILE) printf("file ");
		if (info.type & FT_DIR) printf("dir ");
		if (info.type & FT_SYMLINK) printf("symlink ");
		if (info.type & FT_DEV) printf("dev ");
		if (info.type & FT_TERMINAL) printf("term ");

		printf("\t");
		if (info.type & FT_TERMINAL) {
			printf("%ix%i", info.size >> 16, info.size & 0xFFFF);
		} else if ((info.type & FT_DEV) == 0) {
			printf("%i", info.size);
		}

		printf("\n");
	}
}

void ls(char **args) {
	if (!args[1]) {
		int fd = open(cwd, FM_READ);
		if (fd > 0) {
			ls_dir(fd);
			close(fd);
		} else {
			printf("  Could not open for read (%d).\n", fd);
		}
	} else {
		int i;
		for (i = 1; args[i]; i++) {
			printf("Contents of %s :\n", args[i]);
			char *d = path_cat(cwd, args[i], 1);

			file_info i;
			int r = stat(d, &i);

			if (r == E_NOT_FOUND) {
				printf("  No such file or directory\n");
			} else if (r != 0) {
				printf("  Error stating: %i\n", r);
			} else if (!(i.type & FT_DIR)) {
				printf("  Not a directory.\n");
			} else {
				int fd = open(d, FM_READ);
				if (fd > 0) {
					ls_dir(fd);
					close(fd);
				} else {
					printf("  Could not open for read (%d).\n", fd);
				}
			}
			free(d);
		}
	}
}

void cat(char **args) {
	int i;
	for (i = 1; args[i]; i++) {
		char *d = path_cat(cwd, args[i], 0);
		file_info info;
		int e = stat(d, &info);
		if (e == E_NOT_FOUND) {
			printf("No such file: %s\n", d);
		} else if (e < 0) {
			printf("Error stating %s : %i\n", d, e);
		} else if ((info.type & FT_FILE) == 0) {
			printf("Not a file: %s\n", d);
		} else {
			int ff = open(d, 0);
			char* buff = (char*)malloc(info.size);
			read(ff, 0, info.size, buff);
			close(ff);
			write(term.fd, 0, info.size, buff);
			free(buff);
		}
		free(d);
	}
}

void t_goto(char **args) {
	if (!args[1]) {
		printf("Usage: goto <vt_name>\n");
		return;
	}
	char *p = path_cat("/.ui/", args[1], 0);
	int i;
	if ((i = link(p, "/.dev/vgatxt", LM_OUTPUT_TO)) == 0) {
		link("/.dev/ps2kbd", p, LM_OUTPUT_TO);
	} else {
		printf("Error %i\n", i);
	}
	free(p);
}

int main(int argc, char **sh_args) {
	about();

	cwd = strdup("/");

	char *path = path_cat(sh_args[0], "..", 1);

	int bg_pr[128], bg_pr_c = 0;

	readline_history hist;
	hist.str = 0; hist.max = 10;

	while (1) {
		// check for background processes that may have finished
		int p = 0;
		while (p < bg_pr_c) {
			int ret = waitpid(bg_pr[p], 0);
			if (ret != E_NOT_FINISHED) {
				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
		printf("\x1b[33m %s  \x1b[1m", cwd);
		char *s = freadline(stdin, &hist);
		printf("\x1b[0m");
		if (s == NULL) break;
		if (strlen(s) == 0) continue;

		char *a_c = strdup(s);		// duplicate because we're gonna add '\0'es

		char *c_args[16];
		char *start = a_c, *pos = a_c;
		int argc = 0;
		while (*pos) {
			if (*pos == ' ') {
				if (pos == start) {
					start++;
				} else {
					*pos = 0;
					c_args[argc] = start;
					argc++;
					start = pos + 1;
					if (argc == 14) {
						break;
					}
				}
			}
			pos++;
		}
		c_args[argc++] = start;
		c_args[argc] = 0;

		if (!strcmp(c_args[0], "about")) {
			about();
		} else if (!strcmp(c_args[0], "help")) {
			help(c_args);
		} else if (!strcmp(c_args[0], "exit")) {
			printf("Exiting the shell. See you later!\n");
			break;
		} else if (!strcmp(c_args[0], "cd")) {
			cd(c_args);
		} else if (!strcmp(c_args[0], "ls")) {
			ls(c_args);
		} else if (!strcmp(c_args[0], "goto")) {
			t_goto(c_args);
		} else if (!strcmp(c_args[0], "cat")) {
			cat(c_args);
		} else {
			char **first_arg = c_args;

			char *term_s = NULL;
			int vt_fd = term.fd;

			if (!strcmp(c_args[0], "on")) {
				if (!c_args[1] || !c_args[2]) {
					printf("Usage:\ton <vt> <command>\n");
					continue;
				}
				term_s = path_cat("/.ui/", c_args[1], 1);
				vt_fd = open(term_s, 0);
				if (vt_fd < 0 || vt_fd == term.fd) {
					printf("Error: cannot open terminal %s (%i)\n", term_s, vt_fd);
					continue;
				}
				first_arg += 2;
			}

			char *c;
			if (strchr(*first_arg, '/')) {
				c = path_cat(cwd, *first_arg, 0);
			} else {
				c = path_cat(path, *first_arg, 0);
			}
			first_arg++;
			
			int pid = run(c, first_arg, vt_fd);
			if (pid <= 0) {
				if (pid == E_NOT_FOUND) {
					printf("Error: no such file %s\n", c);
				} else {
					printf("Error %i\n", pid);
				}
			} else {
				if (term_s == NULL) {
					int ret = waitpid(pid, 1);
					printf("(yosh) child (pid %i) exited with status %i\n", pid, ret);
				} else {
					printf("(yosh) running on terminal %s, pid:%i\n", term_s, pid);
					bg_pr[bg_pr_c++] = pid;
				}
			}
			free(c);
			if (term_s) free(term_s);
		}

		free(a_c);
	}

	return 0;
}