/* * Copyright (c) 2017 Ian Sutton * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include #include #define LINE_SIZE 4096 struct config { char *obj_path; char *tool_path; char *src_path; FILE *conf; FILE *term; } *gcfg; struct sigaction sigact; static void sigh(int); static void sigc(void); static void __dead usage(void) { fprintf(stderr, "usage: puffcrash [-c config] [serial console log]\n"); exit(1); } void sigh(int sig) { if (sig == SIGINT) sigc(); } void sigc(void) { if (gcfg->obj_path) free(gcfg->obj_path); if (gcfg->tool_path) free(gcfg->tool_path); if (gcfg->src_path) free(gcfg->src_path); if (gcfg->conf) fclose(gcfg->conf); if (gcfg->term && gcfg->term != stdin) fclose(gcfg->term); exit(1); } int parse_config(char *config_path, struct config *cfg) { char *line, *i; int check = 0; cfg->conf = fopen(config_path, "r"); if(!(line = calloc(1, 256)) || !cfg->conf) return 1; while ((fgets(line, 256, cfg->conf))) { if (strstr(line, "obj_path")) { i = strstr(line, "=") + 2; strlcpy(cfg->obj_path, i, PATH_MAX); check |= (1 << 0); } else if (strstr(line, "tool_path")) { i = strstr(line, "=") + 2; strlcpy(cfg->tool_path, i, PATH_MAX); check |= (1 << 1); } else if (strstr(line, "src_path")) { i = strstr(line, "=") + 2; strlcpy(cfg->src_path, i, PATH_MAX); check |= (1 << 2); } } free(line); if (check == 0x7) return 0; else return 1; } void watch_serial(void) { char *line; if (!(line = calloc(1, LINE_SIZE))) { printf("could not allocate memory\n"); sigc(); } while ((fgets(line, LINE_SIZE, gcfg->term))) { printf("%s", line); } } int main(int argc, char *argv[]) { struct config cfg; int ch; char term_path[PATH_MAX], config_path[PATH_MAX]; bzero(&cfg, sizeof(struct config)); strlcpy(config_path, "/etc/puffcrash.conf", PATH_MAX); atexit(sigc); sigact.sa_handler = sigh; sigemptyset(&sigact.sa_mask); sigact.sa_flags = 0; sigaction(SIGINT, &sigact, (struct sigaction *) NULL); while ((ch = getopt(argc, argv, "c:")) != -1) { switch (ch) { case 'c': strlcpy(config_path, optarg, PATH_MAX); break; default: usage(); break; } } argv += optind; argc -= optind; cfg.obj_path = calloc(1, PATH_MAX); cfg.tool_path = calloc(1, PATH_MAX); cfg.src_path = calloc(1, PATH_MAX); gcfg = &cfg; if (parse_config(config_path, &cfg)) { printf("failed to parse config file %s.\n", config_path); sigc(); } if (argc) { strlcpy(term_path, argv[0], PATH_MAX); cfg.term = fopen(term_path, "r"); } else cfg.term = stdin; if (!cfg.term) { printf("failed to open serial console output logfile \"%s\"\n", argv[0]); sigc(); } watch_serial(); return 0; }