#include #include #include #include #include #include #include #include #include #include #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; }