#include #include #include #include #include #include #include #include #include #define P_ALL 0 #define P_PID 1 #define P_PGID 2 #define P_PIDFD 3 #if !WEXITED #define WEXITED 0x00000004 #endif void parseInput(char *input, char *command, char **argv) { bool reachedArgv = false; char arg[32] = {0}; int idx = 0; int argvIdx = 1; for (int i = 0; i < strlen(input); i++) { char *a = {&(input[i])}; if (reachedArgv) { if (input[i] == ' ') { arg[idx] = '\0'; argv[argvIdx] = strdup(arg); memset(arg, 0, sizeof(arg)); argvIdx++; idx = 0; continue; } arg[idx] = input[i]; idx++; continue; } if (input[i] == ' ') { arg[idx] = '\0'; strcpy(command, arg); reachedArgv = true; memset(arg, 0, sizeof(arg)); idx = 0; continue; } arg[idx] = input[i]; idx++; } argv[0] = command; if (reachedArgv) { arg[idx] = '\0'; argv[argvIdx] = strdup(arg); } else { arg[idx] = '\0'; strcpy(command, arg); } } void joinPath(char *result, const char *base, const char *rel) { strcpy(result, base); strcat(result, "/"); strcat(result, rel); } const char *get_env_var(const char *name, char *const *env) { size_t len = strlen(name); for (char *const *e = env; *e; e++) { // loop over every env if (strncmp(*e, name, len) == 0 && (*e)[len] == '=') { //if starts with name return *e + len + 1; // return shit after = } } return NULL; } int main() { char input[255] = {0}; char command[128] = {0}; char *argv[32] = {0}; char *env[32] = {"PATH=/bin"}; char path[128] = "/"; while (!false) { memset(input, 0, sizeof(input)); memset(command, 0, sizeof(command)); memset(argv, 0, sizeof(argv)); write(1, path, strlen(path)); write(1, " $ ", 3); int len = read(1, input, sizeof(input)); input[len - 1] = '\0'; parseInput(input, command, argv); if (!strcmp(command, "cd")) { char newpath[128] = {0}; char newresolvedpath[128] = {0}; if (argv[1][0] == '/') { strcpy(newresolvedpath, argv[1]); } else { joinPath(newpath, path, argv[1]); realpath(newpath, newresolvedpath); } if (!access(newresolvedpath, F_OK)) { struct stat statResult; stat(newresolvedpath, &statResult); if (S_ISDIR(statResult.st_mode)) { strcpy(path, newresolvedpath); } else { write(1, "uuuuh das not a dir\n", 21); } } else { write(1, "uuuuh das not a dir\n", 21); } continue; } chdir(path); __pid_t forkResult = fork(); if (forkResult == 0) { // algorithm from old shel since i made it on my own const char* pathV = get_env_var("PATH", env); struct stat path_stat; if (stat(command, &path_stat) == 0 && access(command, X_OK)){ execve(command, argv, 0); } else { bool found = false; char currPath[32] = {0}; int i = 0; int c = 0; char newPath[128] = {0}; while (i < strlen(pathV) && !found) { if (pathV[i] == ':') { currPath[i] = '\0'; memset(newPath, 0, sizeof(newPath)); joinPath(newPath, currPath, command); realpath(newPath, newPath); if(stat(newPath, &path_stat) == 0 && path_stat.st_mode & S_IXUSR) { found = true; continue; } c = 0; } else { currPath[c] = pathV[i]; } i++;c++; } if (!found) { currPath[i] = '\0'; memset(newPath, 0, sizeof(newPath)); joinPath(newPath, currPath, command); realpath(newPath, newPath); if(stat(newPath, &path_stat) == 0 && path_stat.st_mode & S_IXUSR) { found = true; } } if (found) { execve(newPath, argv, 0); } } } else { waitid(P_ALL, 0, 0, WEXITED); } } }