summaryrefslogblamecommitdiff
path: root/src/user/app/yosh/main.cpp
blob: fe3eeed9262587f636a9807c647af9041a6f7083 (plain) (tree)
1
2
3
4
5
6
7
8
9



                        
                     


                        
 
           


              
                                                                    



                           
                                                                                  
                                                   
                                                                                      
                                                  

                                                                                                   
                                                  

                                                                                                                        
                                                
                                                                                    
                                                
                                                                                                                   
                                                  

                                                                                                 
                
                                                               



















































                                                                            
                                                       













                                            
                                                 
                                   



                                       







                                              



                                                  




                           
                                                 


                                              
                                                 



                                    
                                                      

                             
                                                       

                                               
                                            


                                          
                             
                                                                


















                                                                              
                                          

                                             

                                                   
 




                                                              
 
                            
                                              
                                                                                   
                                                       
                                                      

                 
                            








                                                
                                                                    
                                                            


                                               
                                                                       
                                           
                                                                         
                                                               
                                                                     

                                                     
                                             
                                                                                  









                                                   






                                                    
                                                              
                                   
                                                                      
                                                        
                                                            











                                                              
                           
                                                 

                       
                                                



                                                               
                                              


         
                          



                             
 



                                                   




                                                   
 
                   
                                                          
 

                                           
                                      































                                                                     
                                           


                                                                       
                                                                                    



                                                                    

                                                                                                     







                                                                  


                                 


                                                                
                                




                                                                 
                                                                                    
                                        
                                                                        
                                 
                                
                                                     
                                                                  
                                                                                                                
                                        
                                                                                                        

                                                               
                                 
                         








                                                           
                                                                                                             




                                                          
                 



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

using namespace libc;

FILE cwd_f;
char *cwd;

void about() {
	stdio << "Trivial/Computing Environment v0.1.0 - yosh 3.\n";
}

void help(char *args[]) {
	if (args[1] == 0) {
		stdio << "Available commands: about, help, exit, ls, cd, goto.\n";
	} else if (strcmp(args[1], "about") == 0) {
		stdio << "Usage:\tabout\nShows some info about yosh. Very usefull.\n";
	} else if (strcmp(args[1], "help") == 0) {
		stdio << "Usage:\thelp\n\thelp <command>\n"
			<< "Shows some info about the command you want, or commands in general.\n";
	} else if (strcmp(args[1], "exit") == 0) {
		stdio << "Usage:\texit\n"
			<< "Exits the shell.\nWill probably make your system panic if you only have a shell running.\n";
	} else if (strcmp(args[1], "cd") == 0) {
		stdio << "Usage:\tcd <location>\nGoes to the location specified.\n";
	} else if (strcmp(args[1], "ls") == 0) {
		stdio << "Usage:\tls\n\tls <location>...\nShows the content of the current/specified directory.\n";
	} else if (strcmp(args[1], "goto") == 0) {
		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]);
	}
}

void simplify_path(char* p) {
	char *it = p;
	char *member = it;
	while (*it != 0) {
		if (*it == '/') {
			if (it == member && it != p) {
				// two consecutive slashes
				char *i = member;
				while (1) {
					i[0] = i[1];
					if (i[0] == 0) break;
					i++;
				}
			} else {
				*it = 0;
				if (strcmp(member, ".") == 0) {
					char *i = member;
					while (1) {
						i[0] = i[2];
						if (i[0] == 0) break;
						i++;
					}
				} else if (strcmp(member, "..") == 0) {
					*it = '/';
					char* start = member - 2;
					char* next = member + 3;
					while (start > p && *start != '/') {
						start--;
					}
					start++;
					it = member = start;
					while (1) {
						*start = *next;
						if (*start == 0) break;
						start++;
						next++;
					}
				} else {
					*it = '/';
					it++;
					member = it;
				}
			}
		} else {
			it++;
		}
	}
}

char* path_cat (char* a, char* b, int trailing_slash) {
	char* ret;
	if (b[0] == '/') {
		int lb = strlen(b);
		ret = (char*)malloc(lb + 2);
		memcpy(ret, b, lb);
		if (ret[lb - 1] != '/') {
			ret[lb] = '/';
			lb++;
		}
		ret[lb] = 0;
	} else {
		int la = strlen(a);
		int lb = strlen(b);

		ret = (char*)malloc(la + lb + 3);
		memcpy(ret, a, la);
		if (ret[la-1] != '/') {
			ret[la] = '/';
			la++;
		}
		memcpy(ret + la, b, lb);
		if (ret[la + lb - 1] != '/') {
			ret[la + lb] = '/';
			lb++;
		}
		ret[la + lb] = 0;
	}
	simplify_path(ret);
	if (!trailing_slash) {
		int l = strlen(ret);
		if (ret[l-1] == '/') ret[l-1] = 0;
	}
	return ret;
}

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

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

	file_info info;
	int i = stat(newcwd, &info);
	if (i == E_NOT_FOUND) {
		print("No such file or directory.\n");
		free(newcwd);
	} else if (i < 0) {
		stdio.printf("Error stating: %i\n", i);
		free(newcwd);
	} else if ((info.type & FT_DIR) == 0) {
		print("Not a directory.\n");
		free(newcwd);
	} else {
		FILE nf = open(newcwd, 0);
		if (nf < 0) {
			stdio.printf("Error opening: %i\n", nf);
			free(newcwd);
		} else {
			free(cwd);
			cwd = newcwd;
			close(cwd_f);
			cwd_f = nf;
		}
	}
}

void ls_dir(FILE f) {
	file_info info;
	int i = 0;
	char buf[256];
	while (read(f, i, 256, buf) > 0) {
		i++;

		if (strcmp(buf, ".") == 0 || strcmp(buf, "..") == 0) continue;

		stdio.printf("  %s", buf);

		stat_relative(f, buf, &info);
		if (info.type & FT_DIR) print("/");
		print("   \t");

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

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

		print("\n");
	}
}

void ls(char **args) {
	if (args[1] == 0) {
		ls_dir(cwd_f);
	} else {
		int i;
		for (i = 1; args[i] != 0; i++) {
			stdio.printf("Contents of %s :\n", args[i]);
			char* d = path_cat(cwd, args[i], 1);
			file_info info;
			int e = stat(d, &info);
			if (e == E_NOT_FOUND) {
				print("  No such file or directory\n");
			} else if (e < 0) {
				stdio.printf("  Error stating: %i\n", e);
			} else if ((info.type & FT_DIR) == 0) {
				stdio.printf("  Not a directory.\n");
			} else {
				FILE ff = open(d, 0);
				if (ff < 0) {
					stdio.printf("  Error opening: %i\n", ff);
				} else {
					ls_dir(ff);
					close(ff);
				}
			}
			free(d);
		}
	}
}

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

void t_goto(char** args) {
	if (args[1] == 0) {
		print("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 {
		stdio.printf("Error %i\n", i);
	}
}

int Main(char **sh_args) {
	about();

	cwd = strdup("/");
	cwd_f = open(cwd, 0);

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

	int bg_pr[128], bg_pr_c = 0;

	Term *term = stdio.term;
	if (term == 0) {
		stdio << "Error: no terminal...\n";
		return -1;
	}

	while (1) {
		stdio.printf("\x1b[33m %s  \x1b[1m", cwd);

		char *s = term->readline();
		stdio.printf("\x1b[0m");
		if (s == 0) return -1;
		if (*s == 0) continue;

		char *c_args[16] = {0}, *cmd;
		c_args[0] = s;
		int argc = 1;
		for (cmd = s; *cmd != 0; cmd++) {
			if (*cmd == ' ') {
				*cmd = 0;
				if (cmd[1] != ' ' && cmd[1] != 0) {
					c_args[argc] = cmd + 1;
					argc++;
					if (argc == 15) break;
				}
			}
		}

		if (strcmp(c_args[0], "about") == 0) {
			about();
		} else if (strcmp(c_args[0], "help") == 0) {
			help(c_args);
		} else if (strcmp(c_args[0], "exit") == 0) {
			print("Exiting the shell. See you later!\n");
			break;
		} else if (strcmp(c_args[0], "cd") == 0) {
			cd(c_args);
		} else if (strcmp(c_args[0], "ls") == 0) {
			ls(c_args);
		} else if (strcmp(c_args[0], "goto") == 0) {
			t_goto(c_args);
		} else if (strcmp(c_args[0], "cat") == 0) {
			cat(c_args);
		} else {
			FILE vt = term->fd;
			char *t = 0;
			if (strcmp(c_args[0], "on") == 0) {
				if (c_args[1] == 0 || c_args[2] == 0) {
					stdio.printf("Usage:\ton <vt> <command>\n");
					continue;
				}
				t = path_cat("/.ui/", c_args[1], 0);
				vt = open(t, 0);
				if (vt < 0 || vt == term->fd) {
					stdio.printf("Error: cannot open terminal %s (%i)\n", t, vt);
					free(t);
					continue;
				}
				int i = 0;
				while (1) {
					c_args[i] = c_args[i+2];
					if (c_args[i] == 0) break;
					i++;
				}
			}

			char *c;
			if (strchr(c_args[0], '/')) {
				c = path_cat(cwd, c_args[0], 0);
			} else {
				c = path_cat(path, c_args[0], 0);
			}
			int pid = run(c, c_args + 1, vt);
			if (pid <= 0) {
				if (pid == E_NOT_FOUND) {
					stdio.printf("Error: no such file %s\n", c);
				} else {
					stdio.printf("Error %i\n", pid);
				}
			} else {
				if (vt == term->fd) {
					int ret = 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, pid);
					bg_pr[bg_pr_c++] = pid;
					free(t);
				}
			}
			free(c);
		}

		for (; s < cmd; s++) if (*s == 0) *s = ' ';

		int i = 0;
		while (i < bg_pr_c) {
			int ret = waitpid(bg_pr[i], 0);
			if (ret != E_NOT_FINISHED) {
				stdio.printf("(yosh) child (pid %i) exited with status %i\n", bg_pr[i], ret);
				bg_pr_c--;
				bg_pr[i] = bg_pr[bg_pr_c];
			} else {
				i++;
			}
		}
	}

	return 0;
}