#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/event.h>
#include <sys/signal.h>
#include <sys/time.h>
#include <termios.h>
#include <unistd.h>
#include <syslog.h>
int logfd,portfd;
char *log_name = NULL;
char *pidfile_name = NULL;
FILE *pidfd = NULL;
int main (int argc, char *argv[])
{
int i,rc,nread,kq,fflag,flag;
pid_t pid;
struct kevent ke[4];
struct termios options;
char s[512];
char *speed = NULL;
char *dev_name = NULL;
pidfile_name = "/var/run/logserial.pid";
opterr = 0;
fflag = 0;
speed = "9600";
while ((flag = getopt(argc, argv, "d:s:l:p:f")) != -1) {
switch (flag) {
case 'd':
dev_name = optarg;
break;
case 's':
speed = optarg;
break;
case 'l':
log_name = optarg;
break;
case 'p':
pidfile_name = optarg;
break;
case 'f':
fflag = 1;
break;
case '?':
if (isprint(optopt))
fprintf(stderr,
"Unknown option -%c'.\n", optopt);
else
fprintf(stderr,
"Unknown option character `\\x%x'.\n", optopt);
return 1;
default:
break;
}
}
for (; optind < argc; optind++)
printf("%s", argv [optind]);
if ((dev_name == NULL) | (log_name == NULL)) {
printf("usage: logserial -d device name [-s speed of connection] -l logfile name [-f run in foreground][-p pid file]\n");
exit(1);
}
if (fflag == 0)
if (daemon(0, 0) == -1) {
openlog("logserial", LOG_PID, LOG_DAEMON);
syslog(LOG_ERR, strerror(errno));
exit(1);
}
pid = getpid();
printf("%d\n", pid);
pidfd = fopen(pidfile_name, "w+");
if (pidfd == NULL) {
openlog("logserial", LOG_PID, LOG_DAEMON);
syslog(LOG_ERR, strerror(errno));
exit(1);
}
fprintf(pidfd, "%d\n", pid);
fclose(pidfd);
portfd = open(dev_name, O_RDONLY | O_NOCTTY | O_NDELAY );
if (portfd == -1) {
syslog(LOG_ERR, strerror(errno));
exit(1);
}
tcgetattr(portfd, &options);
if (cfsetspeed(&options,strtol(speed, NULL, 10)) == -1) {
syslog(LOG_ERR, strerror(errno));
exit(1);
}
options.c_lflag &= ~ICANON;
if (tcsetattr(portfd, TCSANOW, &options) != 0) {
syslog(LOG_ERR, strerror(errno));
exit(1);
}
if ((kq = kqueue())== -1) {
syslog(LOG_ERR, strerror(errno));
exit(1);
}
bzero(&ke, sizeof(ke));
EV_SET(&ke[0], portfd, EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, NULL);
EV_SET(&ke[1], SIGHUP, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
EV_SET(&ke[2], SIGTERM, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
EV_SET(&ke[3], SIGINT, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
if (kevent(kq, ke, 4, NULL, 0, NULL) == -1 ) {
syslog(LOG_ERR, strerror(errno));
exit(1);
}
bzero(&ke, sizeof(ke));
if (fcntl(portfd, F_SETFL, FNDELAY | O_NONBLOCK) == -1) {
syslog(LOG_ERR, strerror(errno));
exit(1);
}
logfd = open(log_name, O_RDWR | O_APPEND | O_CREAT, 0666);
if (logfd == -1) {
syslog(LOG_ERR, strerror(errno));
exit(1);
}
signal(SIGHUP,SIG_IGN);
signal(SIGTERM,SIG_IGN);
signal(SIGINT,SIG_IGN);
for (;;) {
if ((rc=kevent(kq, NULL, 0, ke, 1, NULL)) == -1) {
if (errno == EINTR) {
syslog(LOG_ERR, "Interrupted kevent call. Strange.");
continue;
} else {
syslog(LOG_ERR, strerror(errno));
exit(1);
}
}
for (i=0; i<rc; ++i) {
if (ke[i].filter == EVFILT_READ && ke[i].ident == portfd) {
nread = read(portfd, s, sizeof(s));
if (nread < 0) {
syslog(LOG_ERR, strerror(errno));
exit(1);
}
write(logfd, s, nread);
} else if (ke[i].filter == EVFILT_SIGNAL && ke[0].ident == SIGHUP) {
close(logfd);
logfd = open(log_name, O_RDWR | O_APPEND | O_CREAT, 0666);
if (logfd < 0) {
syslog(LOG_ERR, strerror(errno));
exit(1);
}
} else if (ke[i].filter == EVFILT_SIGNAL &&
(ke[0].ident == SIGTERM || ke[0].ident == SIGINT)) {
close(logfd);
close(portfd);
remove(pidfile_name);
exit(0);
}
}
}
return (0);
}
syntax highlighted by Code2HTML, v. 0.9.1