University stuff.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ruterdrift.c 7.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. #include "argparser.h"
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <errno.h>
  5. #include <string.h>
  6. #include <ctype.h>
  7. #include <unistd.h>
  8. #include <signal.h>
  9. #include <readline/readline.h>
  10. #include <readline/history.h>
  11. struct router
  12. {
  13. unsigned char id;
  14. char model[256];
  15. struct flag
  16. {
  17. int active;
  18. int wireless;
  19. int ghz5;
  20. int changenum;
  21. } flag;
  22. };
  23. void router_print(struct router *r)
  24. {
  25. printf("ID: %i | Modell: %s\n", r->id, r->model);
  26. printf("\tAktiv: %i | Trådløs: %i | 5GHz: %i | Endringsnummer: %u\n",
  27. r->flag.active,
  28. r->flag.wireless,
  29. r->flag.ghz5,
  30. r->flag.changenum);
  31. }
  32. void router_read(struct router *r, FILE *f)
  33. {
  34. unsigned char modellen;
  35. unsigned char flag;
  36. fread(&r->id, sizeof(r->id), 1, f);
  37. fread(&flag, sizeof(flag), 1, f);
  38. fread(&modellen, sizeof(modellen), 1, f);
  39. fread(&r->model, sizeof(*r->model), modellen - 1, f);
  40. r->model[modellen - 1] = '\0';
  41. r->flag.active = !!(flag & 0b00000001);
  42. r->flag.wireless = !!(flag & 0b00000010);
  43. r->flag.ghz5 = !!(flag & 0b00000100);
  44. r->flag.changenum = (flag & 0b11110000) >> 4;
  45. while (fgetc(f) != '\n');
  46. }
  47. void router_write(struct router *r, FILE *f)
  48. {
  49. unsigned char id = r->id;
  50. unsigned char modellen = strlen(r->model) + 1;
  51. char* model = r->model;
  52. unsigned char flag = 0;
  53. if (r->flag.active)
  54. flag |= 0b00000001;
  55. if (r->flag.wireless)
  56. flag |= 0b00000010;
  57. if (r->flag.ghz5)
  58. flag |= 0b00000100;
  59. flag |= ((r->flag.changenum << 4) & 0b11110000);
  60. fwrite(&id, sizeof(id),1, f);
  61. fwrite(&flag, sizeof(flag), 1, f);
  62. fwrite(&modellen, sizeof(modellen), 1, f);
  63. fwrite(model, sizeof(*model), modellen - 1, f);
  64. char nl = '\n';
  65. fwrite(&nl, sizeof(nl), 1, f);
  66. }
  67. // Our array of router pointers
  68. static struct router *routers[256];
  69. // The biggest ID in the routers array
  70. static unsigned char maxid;
  71. // The name of the file we read from and write to
  72. static char *filename;
  73. void read_routers()
  74. {
  75. FILE *f;
  76. if ((f = fopen(filename, "r")) == NULL)
  77. {
  78. perror(filename);
  79. exit(1);
  80. }
  81. memset(routers, 0, sizeof(NULL));
  82. int nrouters;
  83. fread(&nrouters, sizeof(nrouters), 1, f);
  84. // Skip to after newline
  85. while (fgetc(f) != '\n');
  86. for (int i = 0; i < nrouters; ++i)
  87. {
  88. struct router *r = malloc(sizeof(*r));
  89. router_read(r, f);
  90. routers[r->id] = r;
  91. if (r->id > maxid)
  92. maxid = r->id;
  93. }
  94. fclose(f);
  95. }
  96. void write_routers()
  97. {
  98. FILE *f;
  99. if ((f = fopen(filename, "w")) == NULL)
  100. {
  101. perror(filename);
  102. exit(1);
  103. }
  104. char nl = '\n';
  105. int nrouters = 0;
  106. for (int i = 0; i <= maxid; ++i)
  107. {
  108. if (routers[i] != NULL)
  109. nrouters += 1;
  110. }
  111. fwrite(&nrouters, sizeof(nrouters), 1, f);
  112. fwrite(&nl, sizeof(nl), 1, f);
  113. for (int i = 0; i <= maxid; ++i)
  114. {
  115. if (routers[i] == NULL) continue;
  116. router_write(routers[i], f);
  117. }
  118. fclose(f);
  119. }
  120. void cmd_help()
  121. {
  122. printf("\thelp:\n\t\tShow this help text\n\n");
  123. printf("\tprint [router id]:\n");
  124. printf("\t\tPrint a router. If no router ID is provided, all will be printed.\n\n");
  125. printf("\tchange <router id> <key> <val>:\n\t\tChange a value\n");
  126. printf("\t\tkeys:\n");
  127. printf("\t\t\tactive (int)\n");
  128. printf("\t\t\twireless (int)\n");
  129. printf("\t\t\t5ghz (int)\n");
  130. printf("\t\t\tmodel (string)\n\n");
  131. printf("\tcreate <active> <wireless> <5ghz> <model> [id]:\n");
  132. printf("\t\tCreate a new router.\n\n");
  133. printf("\tdelete <router id>:\n");
  134. printf("\t\tDelete a router\n\n");
  135. printf("\tq:\n\t\tExit\n");
  136. printf("\n");
  137. }
  138. void cmd_print(char *router_id)
  139. {
  140. if (router_id == NULL)
  141. {
  142. for (int i = 0; i <= maxid; ++i)
  143. {
  144. if (routers[i] == NULL) continue;
  145. struct router *r = routers[i];
  146. if (r == NULL)
  147. continue;
  148. router_print(r);
  149. printf("\n");
  150. }
  151. }
  152. else
  153. {
  154. int rid = atoi(router_id);
  155. struct router *r;
  156. if ((r = routers[rid]) == NULL)
  157. {
  158. fprintf(stderr, "Unknown router: %s\n", router_id);
  159. return;
  160. }
  161. router_print(r);
  162. printf("\n");
  163. }
  164. }
  165. void cmd_change(char *router_id, char* key, char* val)
  166. {
  167. if (router_id == NULL || key == NULL || val == NULL)
  168. {
  169. printf("Not enough arguments.\n");
  170. return;
  171. }
  172. int rid = atoi(router_id);
  173. struct router *r;
  174. if ((r = routers[rid]) == NULL)
  175. {
  176. fprintf(stderr, "Unknown router: %s\n", router_id);
  177. return;
  178. }
  179. if (r->flag.changenum == 15)
  180. {
  181. fprintf(stderr, "Router %i has been changed 15 times already\n", rid);
  182. return;
  183. }
  184. if (strcmp(key, "active") == 0)
  185. r->flag.active = !!atoi(val);
  186. else if (strcmp(key, "wireless") == 0)
  187. r->flag.wireless = !!atoi(val);
  188. else if (strcmp(key, "5ghz") == 0)
  189. r->flag.ghz5 = !!atoi(val);
  190. else if (strcmp(key, "model") == 0)
  191. if (strlen(val) > 254)
  192. {
  193. fprintf(stderr, "Too long model name\n");
  194. return;
  195. }
  196. else
  197. {
  198. strncpy(r->model, val, 256);
  199. }
  200. else
  201. {
  202. fprintf(stderr, "Unknown key: %s\n", key);
  203. return;
  204. }
  205. r->flag.changenum += 1;
  206. }
  207. void cmd_create(char *active, char *wireless, char *ghz5, char *model, char *id)
  208. {
  209. if (active == NULL || wireless == NULL || ghz5 == NULL || model == NULL)
  210. {
  211. printf("Not enough arguments.\n");
  212. return;
  213. }
  214. if (strlen(model) > 254)
  215. {
  216. fprintf(stderr, "Too long model name\n");
  217. return;
  218. }
  219. struct router *r = malloc(sizeof(*r));
  220. unsigned char rid;
  221. if (id == NULL)
  222. {
  223. if ((int)maxid + 1 > 255)
  224. {
  225. fprintf(stderr, "ID %i is too big.\n", (int)maxid + 1);
  226. return;
  227. }
  228. maxid += 1;
  229. rid = maxid;
  230. }
  231. else
  232. {
  233. int irid = atoi(id);
  234. if (irid > 255)
  235. {
  236. fprintf(stderr, "ID %i is too big.\n", irid);
  237. return;
  238. }
  239. rid = (unsigned char)irid;
  240. if (routers[rid] != 0)
  241. {
  242. fprintf(stderr, "Router with ID %i alreday exists.\n", rid);
  243. return;
  244. }
  245. if (rid > maxid)
  246. maxid = rid;
  247. }
  248. r->flag.active = !!atoi(active);
  249. r->flag.wireless = !!atoi(wireless);
  250. r->flag.ghz5 = !!atoi(ghz5);
  251. r->flag.changenum = 0;
  252. r->id = rid;
  253. strncpy(r->model, model, 256);
  254. routers[rid] = r;
  255. }
  256. void cmd_delete(char *router_id)
  257. {
  258. if (router_id == NULL)
  259. {
  260. printf("Not enough arguments.\n");
  261. return;
  262. }
  263. int rid = atoi(router_id);
  264. struct router *r = routers[rid];
  265. if (r == NULL)
  266. {
  267. fprintf(stderr, "Unknown router: %s\n", router_id);
  268. return;
  269. }
  270. free(r);
  271. routers[rid] = NULL;
  272. while (routers[maxid] == NULL) maxid -= 1;
  273. }
  274. void cmd_exit()
  275. {
  276. clear_history();
  277. // Write routers to disk
  278. printf("Writing changes to disk...\n");
  279. write_routers();
  280. // Free memory
  281. for (int i = 0; i < 256; ++i)
  282. {
  283. struct router *r = routers[i];
  284. if (r == NULL)
  285. continue;
  286. free(r);
  287. }
  288. exit(0);
  289. }
  290. int eval(char *str)
  291. {
  292. char *argv[7];
  293. argparser_parse(argv, 6, str);
  294. char *cmd = argv[0];
  295. if (argv[0] == NULL)
  296. return 0;
  297. if (strcmp(cmd, "help") == 0)
  298. {
  299. cmd_help();
  300. }
  301. else if (strcmp(cmd, "print") == 0)
  302. {
  303. cmd_print(argv[1]);
  304. }
  305. else if (strcmp(cmd, "change") == 0)
  306. {
  307. cmd_change(argv[1], argv[2], argv[3]);
  308. }
  309. else if (strcmp(cmd, "create") == 0)
  310. {
  311. cmd_create(argv[1], argv[2], argv[3], argv[4], argv[5]);
  312. }
  313. else if (strcmp(cmd, "delete") == 0)
  314. {
  315. cmd_delete(argv[1]);
  316. }
  317. else if (strcmp(cmd, "q") == 0)
  318. {
  319. free(str);
  320. cmd_exit();
  321. }
  322. else
  323. {
  324. printf("Unknown command: '%s'. Type 'help' for help.\n", cmd);
  325. }
  326. free(str);
  327. return 1;
  328. }
  329. void term(int signum)
  330. {
  331. printf("\n"); // We don't want to print a message on the same line as ^C
  332. cmd_exit();
  333. }
  334. int main(int argc, char **argv)
  335. {
  336. // SIGTERM and SIGINT listener
  337. struct sigaction action;
  338. memset(&action, 0, sizeof(action));
  339. action.sa_handler = term;
  340. sigaction(SIGTERM, &action, NULL);
  341. sigaction(SIGINT, &action, NULL);
  342. if (argc != 2)
  343. {
  344. fprintf(stderr, "Usage: %s <file>\n", argv[0]);
  345. return 1;
  346. }
  347. filename = argv[1];
  348. read_routers();
  349. while (1)
  350. {
  351. char *str = readline("> ");
  352. if (!str) continue;
  353. add_history(str);
  354. eval(str);
  355. }
  356. return 0;
  357. }