]> git.itanic.dy.fi Git - log-plotter/blob - main.c
Fix another incorrect test against read() return value
[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;
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                 if (!start_time)
104                         start_time = time(NULL);
105
106                 ret = read_log_line(infd, buf, sizeof(buf), &offset);
107                 if (ret < 0)
108                         return ret;
109
110                 if (ret == 0)
111                         continue;
112
113                 cur_time = time(NULL);
114
115                 pr_info("%s\n", buf);
116
117                 if (!outfd)
118                         continue;
119
120                 len = snprintf(str, sizeof(str),
121                         "%ld;%s\n", cur_time - start_time, buf);
122
123                 ret = write(outfd, str, len);
124                 if (ret < 0) {
125                         pr_err("write: %m\n");
126                         break;
127                 }
128         }
129
130         return 0;
131 }
132
133 int main(int argc, char *argv[])
134 {
135         struct plotter_options options;
136         int fd, baud, ret = 0, out_fd = 0;
137
138         if (read_args(argc, argv, &options))
139                 return 1;
140
141         baud = options.baud_rate;
142         fd = open_at_baud(options.device_path, &baud);
143         if (fd < 0)
144                 return 1;
145
146         if (baud != options.baud_rate) {
147                 pr_err("Failed to set baudrate to %d, only got %d\n",
148                         options.baud_rate, baud);
149                 ret = 1;
150                 goto out;
151         }
152
153         if (options.output_path) {
154                 pr_debug("Opening %s for writing the log file\n",
155                         options.output_path);
156
157                 out_fd = open(options.output_path,
158                         O_CREAT | O_APPEND | O_WRONLY, 0664);
159                 if (out_fd < 0) {
160                         pr_err("Failed to open file %s for writing: %m\n",
161                                 options.output_path);
162                         ret = 1;
163                         goto out;
164                 }
165         }
166
167         read_data(fd, out_fd);
168
169 out:
170         close(fd);
171         return ret;
172 }