123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430 |
- #include "argparser.h"
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <string.h>
- #include <ctype.h>
- #include <unistd.h>
- #include <signal.h>
- #include <readline/readline.h>
- #include <readline/history.h>
-
- 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 <router id> <key> <val>:\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 <active> <wireless> <5ghz> <model> [id]:\n");
- printf("\t\tCreate a new router.\n\n");
-
- printf("\tdelete <router id>:\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 <file>\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;
- }
|