#include #include #include #include #include #include #include #include #include #include "stlfile.h" #include "util.h" #define MAXFILESIZE 7000 struct command { const char *name; void (*func)(const char *); const char *desc; }; int save_submission(struct parseinfo *info, char *data, int len); void cat_cmd(const char *arg); void help_cmd(const char *arg); void exit_cmd(const char *arg); void echo_cmd(const char *arg); void upload_cmd(const char *arg); void search_cmd(const char *arg); void list_cmd(const char *arg); void auth_cmd(const char *arg); void cleanexit(); struct command commands[] = { { "cat", cat_cmd, "Cat cmd go prrrrr." }, { "help", help_cmd, "You already know what this does." }, { "exit", exit_cmd, "Closes the session." }, { "echo", echo_cmd, "Repeat after me!" }, { "upload", upload_cmd, "Upload an STL file to analyze." }, { "search", search_cmd, "Search for an STL file by model name." }, { "list", list_cmd, "List your uploaded files." }, { "auth", auth_cmd, "Login to upload files to a private dir." } }; struct parseinfo cached; char *resultdir; int echo = 0, loggedin = 0; int save_submission(struct parseinfo *info, char *stldata, int stlsize) { DIR *d; FILE *f = NULL; char *dirpath = NULL, *infopath = NULL, *modelpath = NULL; if (loggedin) dirpath = aprintf("%s/.%s-%i", resultdir, info->hash, time(NULL)); else dirpath = aprintf("%s/%s-%i", resultdir, info->hash, time(NULL)); if (mkdir(dirpath, S_IRWXU | S_IRWXG | S_IRWXO)) goto fail; modelpath = aprintf("%s/%s", dirpath, "model"); if (!(f = fopen(modelpath, "w+"))) goto fail; if (fwrite(stldata, 1, stlsize, f) != stlsize) goto fail; fclose(f); f = NULL; infopath = aprintf("%s/%s", dirpath, "info"); if (!(f = fopen(infopath, "w+"))) goto fail; if (save_info(info, f) != OK) goto fail; fclose(f); f = NULL; free(dirpath); free(modelpath); free(infopath); return OK; fail: if (f) fclose(f); if (infopath) remove(infopath); if (modelpath) remove(modelpath); if (dirpath) remove(dirpath); free(dirpath); free(modelpath); free(infopath); return FAIL; } int access_authorized(const char *file) { return (loggedin && file[0] == '.' && file[1] != '.') || (!loggedin && file[0] != '.'); } void cat_cmd(const char *arg) { if (arg && !strncmp(arg, "flag", 4)) dump("msgs/cat_flag"); else printf("meow\n"); } void help_cmd(const char *arg) { int i; for (i = 0; arg && i < ARRSIZE(commands); i++) { if (!strcmp(commands[i].name, arg)) { printf("%s\n", commands[i].desc); return; } } printf("Available commands:\n"); for (i = 0; i < ARRSIZE(commands); i++) printf("%s%s", i ? " " : "", commands[i].name); printf("\n"); } void exit_cmd(const char *arg) { printf("bye!\n"); exit(0); } void echo_cmd(const char *arg) { echo ^= 1; printf("Echo is %s\n", echo ? "enabled" : "disabled"); } void upload_cmd(const char *arg) { const char *bufp; char *end, *contents; size_t len; bufp = ask("How large is your file? "); len = strtoul(bufp, &end, 10); if (len <= 0 || len >= MAXFILESIZE || *end) { fprintf(stderr, "Invalid file length!\n"); return; } printf("Ok! Im listening..\n"); contents = checkp(malloc(len + 1)); if (fread(contents, 1, len, stdin) != len) { fprintf(stderr, "Hm, I'm missing some bytes.. try again!\n"); goto cleanup; } contents[len] = '\0'; if ((cached.valid = parse_file(&cached, contents, len))) { if (save_submission(&cached, contents, len) != OK) fprintf(stderr, "Failed to save your submission!\n"); else printf("Your file was saved with ID %s!\n", cached.hash); } cleanup: free(contents); } void search_cmd(const char *arg) { char *end, *scandir = NULL, *infopath = NULL, *modelpath = NULL, **paths = NULL; int i, which, dirstart, ishidden, pathc, pathcap = 100; const char *hash, *name; struct dirent *de; DIR *d = NULL; FILE *f = NULL; size_t size; if (arg && !strcmp(arg, "last")) { if (!cached.valid) { fprintf(stderr, "No cached info report available\n"); return; } hash = cached.hash; } else { hash = mhash(arg ? arg : ask("Model name: "), -1); } if (!(d = opendir(resultdir))) { fprintf(stderr, "Unable to access upload directory!\n"); return; } paths = checkp(malloc(pathcap * sizeof(char*))); dirstart = telldir(d); for (pathc = 0; (de = readdir(d));) { if (access_authorized(de->d_name) && !strpfcmp(hash, de->d_name + (loggedin ? 1 : 0))) { printf("%i : %s\n", pathc, de->d_name); paths[pathc++] = checkp(strdup(de->d_name)); if (pathc == pathcap) { pathcap *= 2; paths = checkp(realloc(paths, pathcap * sizeof(char*))); } } } closedir(d); if (pathc == 0) { fprintf(stderr, "Sorry, couldnt find a matching scan result!\n"); goto cleanup; } which = strtoul(ask("Which of these results? "), &end, 10); if (which >= pathc || which < 0 || *end) { fprintf(stderr, "Invalid index!\n"); goto cleanup; } scandir = aprintf("%s/%s", resultdir, paths[which]); infopath = aprintf("%s/%s", scandir, "info"); if (!(f = fopen(infopath, "r"))) { fprintf(stderr, "Selected result is missing!\n"); goto cleanup; } free_info(&cached); if (load_info(&cached, f) != OK) { fprintf(stderr, "Failed to parse info file!\n"); goto cleanup; } fclose(f); f = NULL; print_info(&cached); if (strchr(ask("Download the model? "), 'y')) { modelpath = aprintf("%s/%s", scandir, "model"); if (!(f = fopen(modelpath, "r"))) { fprintf(stderr, "Failed to access file!\n"); goto cleanup; } fseek(f, 0, SEEK_END); size = ftell(f); fseek(f, 0, SEEK_SET); if (size > MAXFILESIZE) { fprintf(stderr, "File is too large to send!\n"); goto cleanup; } printf("Here you go.. (%liB)\n", size); while ((i = getc(f)) != EOF) putc(i, stdout); fclose(f); f = NULL; } cleanup: if (f) fclose(f); free(scandir); free(infopath); free(modelpath); for (i = 0; i < pathc; i++) free(paths[i]); free(paths); } void list_cmd(const char *arg) { struct dirent *de; struct parseinfo info; char *path; FILE *f; DIR *d; if (!loggedin) { fprintf(stderr, "Not logged in!\n"); return; } if (!(d = opendir(resultdir))) return; while ((de = readdir(d))) { if (*de->d_name == '.' && !strchr(".", de->d_name[1])) { printf(">> %s\n", de->d_name); path = aprintf("%s/%s/info", resultdir, de->d_name); if ((f = fopen(path, "r"))) { if (load_info(&info, f) != OK) fprintf(stderr, "Failed to read saved file info!\n"); else print_info(&info); fclose(f); } free(path); } } } void auth_cmd(const char *arg) { const char *hash; char *ndir; int ret; if (loggedin) { fprintf(stderr, "Already logged in!\n"); return; } hash = mhash(arg ? arg : ask("Enter a password: "), -1); ndir = aprintf("%s/.%s", resultdir, hash); ret = mkdir(ndir, S_IRWXU | S_IRWXG | S_IRWXO); if (!ret) { printf("Success!\n"); } else if (ret && errno == EEXIST) { printf("Success!\nWelcome back!\n"); } else { fprintf(stderr, "Auth failed!\n"); return; } free(resultdir); resultdir = ndir; loggedin = 1; cached.valid = 0; } void cleanexit() { printf("see you later!\n"); free_info(&cached); free(resultdir); } int main() { const char *cmd, *envstr; char *cp, *arg; int exit, i, cmdlen; if (!(envstr = getenv("RESULTDIR"))) { fprintf(stderr, "RESULTDIR not defined\n"); return 1; } resultdir = checkp(strdup(envstr)); setvbuf(stdin, NULL, _IONBF, 0); setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stderr, NULL, _IONBF, 0); atexit(cleanexit); dump("msgs/welcome"); exit = 0; while (!exit) { errno = 0; cmd = ask("$ "); if (!*cmd && errno == EBADMSG) break; if (!*cmd) continue; cp = strchr(cmd, ' '); arg = cp ? cp + 1 : NULL; cmdlen = cp ? cp - cmd : strlen(cmd); for (i = 0; i < ARRSIZE(commands); i++) { if (!strncmp(commands[i].name, cmd, cmdlen) && cmdlen == strlen(commands[i].name)) { commands[i].func(arg); break; } } if (i == ARRSIZE(commands) && strlen(cmd) != 0) fprintf(stderr, "No such command!\n"); } }