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