Skip to content

Instantly share code, notes, and snippets.

@bradley219
Last active May 24, 2018 08:33
Show Gist options
  • Save bradley219/c5f702c6ef1e0fce17faa5df6ce4022a to your computer and use it in GitHub Desktop.
Save bradley219/c5f702c6ef1e0fce17faa5df6ce4022a to your computer and use it in GitHub Desktop.
Simple utility for logging from serial port
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>
#include <sys/select.h>
#include <signal.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#define STDOUT 1
int fd = -1, logfd = -1;
size_t make_timestamp(char *restrict buf, size_t maxsize) {
time_t t = time(NULL);
struct tm tm;
localtime_r(&t, &tm);
return strftime(buf, maxsize, "%F %T", &tm);
}
void finish(void) {
if (fd > 0) {
fprintf(stderr, "Closing serial port\n");
close(fd);
}
// Write footer info
{
char footer[1024];
char timebuf[1024];
footer[0] = '\0';
strcat(footer, "\nLog end: ");
size_t i = make_timestamp(timebuf, 1024);
strcat(footer, timebuf);
strcat(footer, "\n--------------------------------------------------------\n");
write(STDOUT, footer, strlen(footer));
if (logfd > 0) {
write(logfd, footer, strlen(footer));
}
}
if (logfd > 0) {
fprintf(stderr, "Closing log file\n");
close(logfd);
}
}
void signal_handler(int signo) {
fprintf(stderr, "Caught signal %d\n", signo);
finish();
}
void usage(void) {
fprintf(stderr, "readserial: usage: readserial [-B baudrate] [-l logfile] device\n");
}
int main(int argc, char **argv) {
ssize_t len;
unsigned char buf[8192];
struct termios tio;
long baudrate = 115200;
char *logfile = NULL;
char *device = NULL;
int ch;
char *endptr;
while ((ch = getopt(argc, argv, "B:l:")) != -1) {
switch (ch) {
case 'B':
baudrate = strtol(optarg, &endptr, 10);
if (endptr[0] != '\0') {
fprintf(stderr, "Invalid baudrate argument `%s'\n", optarg);
usage();
return -1;
}
break;
case 'l':
logfile = optarg;
break;
case '?':
default:
break;
}
}
argc -= optind;
argv += optind;
if (argc == 0) {
fprintf(stderr, "No serial device specified\n");
usage();
return -1;
}
device = argv[0];
fd = open(device, O_RDONLY | O_NOCTTY | O_NONBLOCK);
if (fd < 0) {
perror("unable to open file");
return -1;
}
cfmakeraw(&tio);
cfsetispeed(&tio,baudrate);
cfsetospeed(&tio,baudrate);
tcsetattr(fd,TCSANOW,&tio);
int write_to_logfile = 0;
if (argc > 2) {
logfd = open(logfile, O_WRONLY | O_APPEND | O_CREAT | O_NONBLOCK, 0644);
if (fd < 0) {
perror("unable to open file for writing");
return -1;
} else {
write_to_logfile = 1;
}
}
// Write header info
{
char header[1024];
char timebuf[1024];
header[0] = '\0';
strcat(header, "--------------------------------------------------------\n");
strcat(header, "Log start: ");
make_timestamp(timebuf, 1024);
strcat(header, timebuf);
strcat(header, " Reading from `");
strcat(header, device);
strcat(header, "'\n\n");
write(STDOUT, header, strlen(header));
if (write_to_logfile) {
write(logfd, header, strlen(header));
}
}
signal(SIGINT, &signal_handler);
for(;;) {
fd_set read_fds, err_fds;
FD_SET(fd, &read_fds);
FD_SET(fd, &err_fds);
int ready = select(fd + 1, &read_fds, NULL, &err_fds, NULL);
if (ready == -1) {
perror("select()");
return -1;
} else if (ready == 0) {
fprintf(stderr, "select () returned 0\n");
return -1;
} else {
if (FD_ISSET(fd, &read_fds)) {
len = read(fd, &buf[0], 8192);
if (len > 0) {
write(STDOUT, buf, len);
if (write_to_logfile) {
write(logfd, buf, len);
}
} else {
fprintf(stderr, "read 0 bytes\n");
}
}
if (FD_ISSET(fd, &err_fds)) {
fprintf(stderr, "error with serial port\n");
break;
}
}
}
finish();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment