]> git.itanic.dy.fi Git - log-plotter/blob - main.c
Add missing initialization
[log-plotter] / main.c
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <fcntl.h>
4 #include <string.h>
5 #include <time.h>
6 #include <sys/epoll.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9
10 #include "options.h"
11 #include "baud.h"
12 #include "debug.h"
13
14 /**
15  * Read data from a slow device
16  *
17  * return 1 when a complete NULL terminated line has been read
18  *
19  * return 0 when a partial line has been read and appended to the
20  *               buffer at @offset
21  *
22  * return negative on error
23  */
24 static int read_log_line(int infd, char *buf, size_t bufsize, int *offset)
25 {
26         int ret;
27         int i;
28
29         ret = read(infd, buf + *offset, bufsize - *offset - 1);
30         if (ret < 0) {
31                 pr_err("read: %m\n");
32                 return -1;
33         }
34
35         if (ret == 0) {
36                 pr_err("Read EOF, stopping\n");
37                 return -1;
38         }
39         buf[*offset + ret] = 0;
40
41         for (i = 0; i < ret; i++) {
42                 if (buf[i + *offset] == '\n' ||
43                     buf[i + *offset] == '\r') {
44                         /*
45                          * Got a complete line when there is a newline
46                          * at the end. Remove the newline and possible
47                          * other junk, such as '\r'
48                          */
49                         buf[i + *offset] = 0;
50                         *offset = 0;
51
52                         return 1;
53                 }
54
55                 /*
56                  * Fixme! Nothing guarantees that there isn't actually
57                  * more data (a part of a new log entry perhaps) after
58                  * the newline. So in rare cases (we are prevented
59                  * from reading the serial line in very long time) we
60                  * might lose data from the stream..
61                  */
62         }
63
64         *offset += ret;
65         return 0;
66 }
67
68 static int read_data(int infd, int outfd)
69 {
70         struct epoll_event ev;
71         time_t start_time = 0, cur_time;
72         int epoll_fd;
73         int ret;
74         char buf[256];
75         int offset = 0;
76
77         epoll_fd = epoll_create(1);
78         if (epoll_fd < 0) {
79                 pr_err("Failed to create epoll socket: %m\n");
80                 return -1;
81         }
82
83         ev.events = EPOLLIN;
84         ev.data.fd = infd;
85         if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, infd, &ev) == -1) {
86                 pr_err("epoll_ctl: %m\n");
87                 return 1;
88         }
89
90         while (1) {
91                 char str[320];
92                 int len;
93
94                 ret = epoll_wait(epoll_fd, &ev, 1, -1);
95                 if (ret == 0)
96                         continue;
97
98                 if (ret < 0) {
99                         pr_err("epoll: %m\n");
100                         return -1;
101                 }
102
103                 ret = read_log_line(infd, buf, sizeof(buf), &offset);
104                 if (ret < 0)
105                         return ret;
106
107                 if (ret == 0)
108                         continue;
109
110                 if (strlen(buf) < 5) {
111                         pr_debug("discarding truncated log entry\n");
112                         offset = 0;
113                         continue;
114                 }
115
116                 if (!start_time)
117                         start_time = time(NULL);
118
119                 cur_time = time(NULL);
120
121                 pr_info("%s\n", buf);
122
123                 if (!outfd)
124                         continue;
125
126                 len = snprintf(str, sizeof(str),
127                         "%ld;%s\n", cur_time - start_time, buf);
128
129                 ret = write(outfd, str, len);
130                 if (ret < 0) {
131                         pr_err("write: %m\n");
132                         break;
133                 }
134         }
135
136         return 0;
137 }
138
139 int main(int argc, char *argv[])
140 {
141         struct plotter_options options;
142         int fd, baud, ret = 0, out_fd = 0;
143
144         if (read_args(argc, argv, &options))
145                 return 1;
146
147         baud = options.baud_rate;
148         fd = open_at_baud(options.device_path, &baud);
149         if (fd < 0)
150                 return 1;
151
152         if (baud != options.baud_rate) {
153                 pr_err("Failed to set baudrate to %d, only got %d\n",
154                         options.baud_rate, baud);
155                 ret = 1;
156                 goto out;
157         }
158
159         if (options.output_path) {
160                 pr_debug("Opening %s for writing the log file\n",
161                         options.output_path);
162
163                 out_fd = open(options.output_path,
164                         O_CREAT | O_APPEND | O_WRONLY, 0664);
165                 if (out_fd < 0) {
166                         pr_err("Failed to open file %s for writing: %m\n",
167                                 options.output_path);
168                         ret = 1;
169                         goto out;
170                 }
171         }
172
173         read_data(fd, out_fd);
174
175 out:
176         close(fd);
177         return ret;
178 }