a bunch of stuff, i don't know
[puffcrash.git] / puffcrash.c
1 /*
2 * Copyright (c) 2017 Ian Sutton <ian@ce.gl>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include <string.h>
21 #include <limits.h>
22 #include <signal.h>
23
24 #define LINE_SIZE 4096
25
26 struct config {
27 char *obj_path;
28 char *tool_path;
29 char *src_path;
30 FILE *conf;
31 FILE *term;
32 } *gcfg;
33
34 struct sigaction sigact;
35 static void sigh(int);
36 static void sigc(void);
37
38 static void __dead
39 usage(void)
40 {
41 fprintf(stderr, "usage: puffcrash [-c config] [serial console log]\n");
42 exit(1);
43 }
44
45 void
46 sigh(int sig)
47 {
48 if (sig == SIGINT) sigc();
49 }
50
51 void
52 sigc(void)
53 {
54 if (gcfg->obj_path) free(gcfg->obj_path);
55 if (gcfg->tool_path) free(gcfg->tool_path);
56 if (gcfg->src_path) free(gcfg->src_path);
57
58 if (gcfg->conf) fclose(gcfg->conf);
59 if (gcfg->term && gcfg->term != stdin) fclose(gcfg->term);
60
61 exit(1);
62 }
63
64 int
65 parse_config(char *config_path, struct config *cfg)
66 {
67 char *line, *i;
68 int check = 0;
69
70 cfg->conf = fopen(config_path, "r");
71
72 if(!(line = calloc(1, 256)) || !cfg->conf)
73 return 1;
74
75 while ((fgets(line, 256, cfg->conf))) {
76 if (strstr(line, "obj_path")) {
77 i = strstr(line, "=") + 2;
78 strlcpy(cfg->obj_path, i, PATH_MAX);
79 check |= (1 << 0);
80 } else if (strstr(line, "tool_path")) {
81 i = strstr(line, "=") + 2;
82 strlcpy(cfg->tool_path, i, PATH_MAX);
83 check |= (1 << 1);
84 } else if (strstr(line, "src_path")) {
85 i = strstr(line, "=") + 2;
86 strlcpy(cfg->src_path, i, PATH_MAX);
87 check |= (1 << 2);
88 }
89 }
90
91 free(line);
92
93 if (check == 0x7)
94 return 0;
95 else
96 return 1;
97 }
98
99 void
100 watch_serial(void)
101 {
102 char *line;
103
104 if (!(line = calloc(1, LINE_SIZE))) {
105 printf("could not allocate memory\n");
106 sigc();
107 }
108
109 while ((fgets(line, LINE_SIZE, gcfg->term))) {
110 printf("%s", line);
111 }
112 }
113
114 int
115 main(int argc, char *argv[])
116 {
117 struct config cfg;
118 int ch;
119 char term_path[PATH_MAX], config_path[PATH_MAX];
120
121 bzero(&cfg, sizeof(struct config));
122 strlcpy(config_path, "/etc/puffcrash.conf", PATH_MAX);
123
124 atexit(sigc);
125 sigact.sa_handler = sigh;
126 sigemptyset(&sigact.sa_mask);
127 sigact.sa_flags = 0;
128 sigaction(SIGINT, &sigact, (struct sigaction *) NULL);
129
130 while ((ch = getopt(argc, argv, "c:")) != -1) {
131 switch (ch) {
132 case 'c':
133 strlcpy(config_path, optarg, PATH_MAX);
134 break;
135 default:
136 usage();
137 break;
138 }
139 }
140
141 argv += optind;
142 argc -= optind;
143
144 cfg.obj_path = calloc(1, PATH_MAX);
145 cfg.tool_path = calloc(1, PATH_MAX);
146 cfg.src_path = calloc(1, PATH_MAX);
147
148 gcfg = &cfg;
149
150 if (parse_config(config_path, &cfg)) {
151 printf("failed to parse config file %s.\n", config_path);
152 sigc();
153 }
154
155 if (argc) {
156 strlcpy(term_path, argv[0], PATH_MAX);
157 cfg.term = fopen(term_path, "r");
158 } else
159 cfg.term = stdin;
160
161 if (!cfg.term) {
162 printf("failed to open serial console output logfile \"%s\"\n", argv[0]);
163 sigc();
164 }
165
166 watch_serial();
167
168 return 0;
169 }