#include "argparser.h" #include #include #include #include #include #include #include #include #include struct router { unsigned char id; char model[256]; struct flag { int active; int wireless; int ghz5; int changenum; } flag; }; void router_print(struct router *r) { printf("ID: %i | Modell: %s\n", r->id, r->model); printf("\tAktiv: %i | Trådløs: %i | 5GHz: %i | Endringsnummer: %u\n", r->flag.active, r->flag.wireless, r->flag.ghz5, r->flag.changenum); } void router_read(struct router *r, FILE *f) { unsigned char modellen; unsigned char flag; fread(&r->id, sizeof(r->id), 1, f); fread(&flag, sizeof(flag), 1, f); fread(&modellen, sizeof(modellen), 1, f); fread(&r->model, sizeof(*r->model), modellen - 1, f); r->model[modellen - 1] = '\0'; r->flag.active = !!(flag & 0b00000001); r->flag.wireless = !!(flag & 0b00000010); r->flag.ghz5 = !!(flag & 0b00000100); r->flag.changenum = (flag & 0b11110000) >> 4; while (fgetc(f) != '\n'); } void router_write(struct router *r, FILE *f) { unsigned char id = r->id; unsigned char modellen = strlen(r->model) + 1; char* model = r->model; unsigned char flag = 0; if (r->flag.active) flag |= 0b00000001; if (r->flag.wireless) flag |= 0b00000010; if (r->flag.ghz5) flag |= 0b00000100; flag |= ((r->flag.changenum << 4) & 0b11110000); fwrite(&id, sizeof(id),1, f); fwrite(&flag, sizeof(flag), 1, f); fwrite(&modellen, sizeof(modellen), 1, f); fwrite(model, sizeof(*model), modellen - 1, f); char nl = '\n'; fwrite(&nl, sizeof(nl), 1, f); } // Our array of router pointers static struct router *routers[256]; // The biggest ID in the routers array static unsigned char maxid; // The name of the file we read from and write to static char *filename; void read_routers() { FILE *f; if ((f = fopen(filename, "r")) == NULL) { perror(filename); exit(1); } memset(routers, 0, sizeof(NULL)); int nrouters; fread(&nrouters, sizeof(nrouters), 1, f); // Skip to after newline while (fgetc(f) != '\n'); for (int i = 0; i < nrouters; ++i) { struct router *r = malloc(sizeof(*r)); router_read(r, f); routers[r->id] = r; if (r->id > maxid) maxid = r->id; } fclose(f); } void write_routers() { FILE *f; if ((f = fopen(filename, "w")) == NULL) { perror(filename); exit(1); } char nl = '\n'; int nrouters = 0; for (int i = 0; i <= maxid; ++i) { if (routers[i] != NULL) nrouters += 1; } fwrite(&nrouters, sizeof(nrouters), 1, f); fwrite(&nl, sizeof(nl), 1, f); for (int i = 0; i <= maxid; ++i) { if (routers[i] == NULL) continue; router_write(routers[i], f); } fclose(f); } void cmd_help() { printf("\thelp:\n\t\tShow this help text\n\n"); printf("\tprint [router id]:\n"); printf("\t\tPrint a router. If no router ID is provided, all will be printed.\n\n"); printf("\tchange :\n\t\tChange a value\n"); printf("\t\tkeys:\n"); printf("\t\t\tactive (int)\n"); printf("\t\t\twireless (int)\n"); printf("\t\t\t5ghz (int)\n"); printf("\t\t\tmodel (string)\n\n"); printf("\tcreate <5ghz> [id]:\n"); printf("\t\tCreate a new router.\n\n"); printf("\tdelete :\n"); printf("\t\tDelete a router\n\n"); printf("\tq:\n\t\tExit\n"); printf("\n"); } void cmd_print(char *router_id) { if (router_id == NULL) { for (int i = 0; i <= maxid; ++i) { if (routers[i] == NULL) continue; struct router *r = routers[i]; if (r == NULL) continue; router_print(r); printf("\n"); } } else { int rid = atoi(router_id); struct router *r; if ((r = routers[rid]) == NULL) { fprintf(stderr, "Unknown router: %s\n", router_id); return; } router_print(r); printf("\n"); } } void cmd_change(char *router_id, char* key, char* val) { if (router_id == NULL || key == NULL || val == NULL) { printf("Not enough arguments.\n"); return; } int rid = atoi(router_id); struct router *r; if ((r = routers[rid]) == NULL) { fprintf(stderr, "Unknown router: %s\n", router_id); return; } if (r->flag.changenum == 15) { fprintf(stderr, "Router %i has been changed 15 times already\n", rid); return; } if (strcmp(key, "active") == 0) r->flag.active = !!atoi(val); else if (strcmp(key, "wireless") == 0) r->flag.wireless = !!atoi(val); else if (strcmp(key, "5ghz") == 0) r->flag.ghz5 = !!atoi(val); else if (strcmp(key, "model") == 0) if (strlen(val) > 254) { fprintf(stderr, "Too long model name\n"); return; } else { strncpy(r->model, val, 256); } else { fprintf(stderr, "Unknown key: %s\n", key); return; } r->flag.changenum += 1; } void cmd_create(char *active, char *wireless, char *ghz5, char *model, char *id) { if (active == NULL || wireless == NULL || ghz5 == NULL || model == NULL) { printf("Not enough arguments.\n"); return; } if (strlen(model) > 254) { fprintf(stderr, "Too long model name\n"); return; } struct router *r = malloc(sizeof(*r)); unsigned char rid; if (id == NULL) { if ((int)maxid + 1 > 255) { fprintf(stderr, "ID %i is too big.\n", (int)maxid + 1); return; } maxid += 1; rid = maxid; } else { int irid = atoi(id); if (irid > 255) { fprintf(stderr, "ID %i is too big.\n", irid); return; } rid = (unsigned char)irid; if (routers[rid] != 0) { fprintf(stderr, "Router with ID %i alreday exists.\n", rid); return; } if (rid > maxid) maxid = rid; } r->flag.active = !!atoi(active); r->flag.wireless = !!atoi(wireless); r->flag.ghz5 = !!atoi(ghz5); r->flag.changenum = 0; r->id = rid; strncpy(r->model, model, 256); routers[rid] = r; } void cmd_delete(char *router_id) { if (router_id == NULL) { printf("Not enough arguments.\n"); return; } int rid = atoi(router_id); struct router *r = routers[rid]; if (r == NULL) { fprintf(stderr, "Unknown router: %s\n", router_id); return; } free(r); routers[rid] = NULL; while (routers[maxid] == NULL) maxid -= 1; } void cmd_exit() { clear_history(); // Write routers to disk printf("Writing changes to disk...\n"); write_routers(); // Free memory for (int i = 0; i < 256; ++i) { struct router *r = routers[i]; if (r == NULL) continue; free(r); } exit(0); } int eval(char *str) { char *argv[7]; argparser_parse(argv, 6, str); char *cmd = argv[0]; if (argv[0] == NULL) return 0; if (strcmp(cmd, "help") == 0) { cmd_help(); } else if (strcmp(cmd, "print") == 0) { cmd_print(argv[1]); } else if (strcmp(cmd, "change") == 0) { cmd_change(argv[1], argv[2], argv[3]); } else if (strcmp(cmd, "create") == 0) { cmd_create(argv[1], argv[2], argv[3], argv[4], argv[5]); } else if (strcmp(cmd, "delete") == 0) { cmd_delete(argv[1]); } else if (strcmp(cmd, "q") == 0) { free(str); cmd_exit(); } else { printf("Unknown command: '%s'. Type 'help' for help.\n", cmd); } free(str); return 1; } void term(int signum) { printf("\n"); // We don't want to print a message on the same line as ^C cmd_exit(); } int main(int argc, char **argv) { // SIGTERM and SIGINT listener struct sigaction action; memset(&action, 0, sizeof(action)); action.sa_handler = term; sigaction(SIGTERM, &action, NULL); sigaction(SIGINT, &action, NULL); if (argc != 2) { fprintf(stderr, "Usage: %s \n", argv[0]); return 1; } filename = argv[1]; read_routers(); while (1) { char *str = readline("> "); if (!str) continue; add_history(str); eval(str); } return 0; }