[vhffs-dev] [1346] Improved stsmon, added getopt() support and many options

[ Thread Index | Date Index | More vhffs.org/vhffs-dev Archives ]


Revision: 1346
Author:   gradator
Date:     2009-02-20 03:32:06 +0100 (Fri, 20 Feb 2009)

Log Message:
-----------
Improved stsmon, added getopt() support and many options

Modified Paths:
--------------
    trunk/vhffs-stsmon/stsmon.c


Modified: trunk/vhffs-stsmon/stsmon.c
===================================================================
--- trunk/vhffs-stsmon/stsmon.c	2009-02-20 00:06:24 UTC (rev 1345)
+++ trunk/vhffs-stsmon/stsmon.c	2009-02-20 02:32:06 UTC (rev 1346)
@@ -2,7 +2,7 @@
  *  STSMON: Quick and dirty tool to monitor dry contacts connected
  *          on serial port
  *
- *  Copyright 2008  Sylvain Rochet <gradator@xxxxxxxxxxxx>
+ *  Copyright 2008-2009  Sylvain Rochet <gradator@xxxxxxxxxxxx>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -48,16 +48,46 @@
 #include <sys/termios.h>
 #include <sys/ioctl.h>
 #include <signal.h>
+#include <time.h>
+#include <sys/time.h>
 #include <sys/socket.h>
 #include <netdb.h>
 #include <arpa/inet.h>
 #include <netinet/in.h>
+#include <getopt.h>
 
-#define SERIAL_DEVICE "/dev/ttyS0"
+#define FALSE 0
+#define TRUE !FALSE
 
 
-int stsmon_listentoport(uint16_t port) {
+void addlogline(char *line, char *logfile)  {
 
+	FILE *lf = NULL;
+
+	struct timeval tv;
+	char date[64];
+
+	gettimeofday(&tv, NULL);
+	ctime_r(&tv.tv_sec, date);
+	date[strlen(date)-1] = '\0';
+
+	if(logfile)  {
+		lf = fopen(logfile, "a");
+	}
+
+	if(lf)  {
+		fprintf(lf, "%s: %s\n", date, line);
+		fclose(lf);
+	}
+	else  {
+		// use stdout if logfile is not available
+		fprintf(stdout, "%s: %s\n", date, line);
+	}
+}
+
+
+int stsmon_listentoport(uint32_t bindaddr, uint16_t port) {
+
 	struct sockaddr_in src;
 	int fd, flags, opt;
 
@@ -80,7 +110,7 @@
 		fprintf(stderr, "setsockopt() failed on socket %d: %s\n", fd, strerror(errno));
 	}
 
-	src.sin_addr.s_addr = INADDR_ANY;
+	src.sin_addr.s_addr = bindaddr;
 	src.sin_family = AF_INET;
 	src.sin_port = htons(port);
 	if( bind(fd, (struct sockaddr*)&src, sizeof(src) ) < 0) {
@@ -99,6 +129,26 @@
 }
 
 
+static void usage_exit(int ret_code, char *progname)  {
+	printf ("Usage: %s [OPTION]...\n"
+		"Quick and dirty tool to monitor dry contacts connected on serial port\n\n"
+		"  -f, --foreground\t\tDo not daemonise, default is to daemonise\n"
+		"  -d, --device\t\t\tDevice to use, default to /dev/ttyS0\n"
+		"  -b, --bind=IP\t\t\tListen to the specified IP address\n"
+		"  -p, --baseport=PORT\t\tBase port, will listen from BASEPORT to BASEPORT+3, default to 13000\n"
+		"  -l, --logfile=LOGFILE\t\tPath to logfile, default is to log on stdout\n"
+		"  -i, --interval=SECONDS\tDelay between each probe, default to 1s\n"
+		"      --namects=NAME\t\tSet the name of the CTS(Clear To Send) input\n"
+		"      --namecd=NAME\t\tSet the name of the CD(Carrier Detected) input\n"
+		"      --nameri=NAME\t\tSet the name of the RI(Ring Indicator) input\n"
+		"      --namedsr=NAME\t\tSet the name of the DSR(Data Set Ready) input\n"
+		"  -h, --help\t\t\tDisplay this help and exit\n"
+		"  -v, --version\t\t\tOutput version information and exit\n",
+		progname);
+	exit(ret_code);
+}
+
+
 int main(int argc, char *argv[]) {
 	int serialfd;
 	int status;
@@ -107,18 +157,122 @@
 	int listencd = 0;
 	int listenri = 0;
 	int listendsr = 0;
-	int fd;
 
-	if(fork()) exit(0);
+	char *logfile = NULL;
+	char *device = "/dev/ttyS0";
+	int foreground = FALSE;
+	long waittime = 100;
+	uint32_t bindaddr = INADDR_ANY;
+	uint16_t baseport = 13000;
+	char *namects = "CTS";
+	char *namecd = "CD";
+	char *nameri = "RI";
+	char *namedsr = "DSR";
 
+	struct option long_options[] = {
+		{ "foreground", no_argument, NULL, 'f' },
+		{ "device", required_argument, NULL, 'd' },
+		{ "bind", required_argument, NULL, 'b' },
+		{ "baseport", required_argument, NULL, 'p' },
+		{ "logfile", required_argument, NULL, 'l' },
+		{ "interval", required_argument, NULL, 'i' },
+		{ "namects", required_argument, NULL, 1000 },
+		{ "namecd", required_argument, NULL, 1001 },
+		{ "nameri", required_argument, NULL, 1002 },
+		{ "namedsr", required_argument, NULL, 1003 },
+		{ "help", no_argument, NULL, 'h' },
+		{ "version", no_argument, NULL, 'v' },
+		{ 0, 0, 0, 0 }
+	};
+
+	while(1) {
+		int option_index = 0, c;
+		c = getopt_long(argc, argv, "fd:b:p:l:i:hv", long_options, &option_index);
+		if(c == -1)
+			break;
+
+		switch(c) {
+			case 'f':
+				foreground = TRUE;
+				break;
+
+			case 'd':
+				device = strdup(optarg);
+				break;
+
+			case 'b':
+				bindaddr = inet_addr(optarg);
+				break;
+
+			case 'p':
+				baseport = atoi(optarg);
+				break;
+
+			case 'l':
+				logfile = strdup(optarg);
+				break;
+
+			case 'i':
+				waittime = (long)(atof(optarg)*100.0);
+				break;
+
+			case 1000:
+				namects = strdup(optarg);
+				break;
+
+			case 1001:
+				namecd = strdup(optarg);
+				break;
+
+			case 1002:
+				nameri = strdup(optarg);
+				break;
+
+			case 1003:
+				namedsr = strdup(optarg);
+				break;
+
+			case 'h':
+				usage_exit(0, argv[0]);
+
+			case 'v':
+#ifdef VERSION
+				fputs("stsmon " VERSION "\n", stdout);
+#else
+				fputs("stsmon\n", stdout);
+#endif
+				exit(0);
+
+			case '?':
+				/* `getopt_long' already printed an error message. */
+				fprintf(stderr,"Try `%s --help' for more information.\n", argv[0]);
+				exit(1);
+
+			default:
+				abort();
+		}
+	}
+
+	if(optind != argc)
+		usage_exit(1, argv[0]);
+
 	signal(SIGPIPE, SIG_IGN);
 
-	serialfd = open(SERIAL_DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
+	serialfd = open(device, O_RDWR | O_NOCTTY | O_NONBLOCK);
 	if(serialfd < 0) {
-		perror(SERIAL_DEVICE);
+		perror(device);
 		exit(-1);
 	}
 
+	addlogline("Starting stsmon", logfile);
+
+	if(!foreground) {
+		close(STDIN_FILENO);
+		close(STDOUT_FILENO);
+		close(STDERR_FILENO);
+		if(fork()) exit(0);
+	}
+
 	// power-up DTR and power-down RTS
 	// can be used as a ~12v power source
 	ioctl(serialfd, TIOCMGET, &status);
@@ -127,6 +281,8 @@
 	ioctl(serialfd, TIOCMSET, &status);
 
 	while(1) {
+		char line[128];
+
 		ioctl(serialfd, TIOCMGET, &status);
 
 //		printf("%.2X\n", status);
@@ -136,18 +292,24 @@
 		if( status & TIOCM_CTS ) {
 //			puts("CTS (clear to send)");
 			if(!listencts) {
-				listencts = stsmon_listentoport(13000);
+				listencts = stsmon_listentoport(bindaddr, baseport+0);
 				if(listencts < 0) listencts = 0;
+
+				snprintf(line, 128, "%s on", namects);
+				addlogline(line, logfile);
 			}
 		}
 		else {
 			if(listencts) {
 				close(listencts);
 				listencts = 0;
+
+				snprintf(line, 128, "%s off", namects);
+				addlogline(line, logfile);
 			}
 		}
 		while(listencts) {
-			fd = accept(listencts, NULL, NULL);
+			int fd = accept(listencts, NULL, NULL);
 			if(fd < 0) break;
 			shutdown(fd, SHUT_RDWR);
 			close(fd);
@@ -156,18 +318,24 @@
 		if( status & TIOCM_CD ) {
 //			puts("DCD (data carrier detect)");
 			if(!listencd) {
-				listencd = stsmon_listentoport(13001);
+				listencd = stsmon_listentoport(bindaddr, baseport+1);
 				if(listencd < 0) listencd = 0;
+
+				snprintf(line, 128, "%s on", namecd);
+				addlogline(line, logfile);
 			}
 		}
 		else {
 			if(listencd) {
 				close(listencd);
 				listencd = 0;
+
+				snprintf(line, 128, "%s off", namecd);
+				addlogline(line, logfile);
 			}
 		}
 		while(listencd) {
-			fd = accept(listencd, NULL, NULL);
+			int fd = accept(listencd, NULL, NULL);
 			if(fd < 0) break;
 			shutdown(fd, SHUT_RDWR);
 			close(fd);
@@ -176,18 +344,24 @@
 		if( status & TIOCM_RI ) {
 //			puts("RI (ring)");
 			if(!listenri) {
-				listenri = stsmon_listentoport(13002);
+				listenri = stsmon_listentoport(bindaddr, baseport+2);
 				if(listenri < 0) listenri = 0;
+
+				snprintf(line, 128, "%s on", nameri);
+				addlogline(line, logfile);
 			}
 		}
 		else {
 			if(listenri) {
 				close(listenri);
 				listenri = 0;
+
+				snprintf(line, 128, "%s off", nameri);
+				addlogline(line, logfile);
 			}
 		}
 		while(listenri) {
-			fd = accept(listenri, NULL, NULL);
+			int fd = accept(listenri, NULL, NULL);
 			if(fd < 0) break;
 			shutdown(fd, SHUT_RDWR);
 			close(fd);
@@ -196,18 +370,24 @@
 		if( status & TIOCM_DSR ) {
 //			puts("DSR (data set ready)");
 			if(!listendsr) {
-				listendsr = stsmon_listentoport(13003);
+				listendsr = stsmon_listentoport(bindaddr, baseport+3);
 				if(listendsr < 0) listendsr = 0;
+
+				snprintf(line, 128, "%s on", namedsr);
+				addlogline(line, logfile);
 			}
 		}
 		else {
 			if(listendsr) {
 				close(listendsr);
 				listendsr = 0;
+
+				snprintf(line, 128, "%s off", namedsr);
+				addlogline(line, logfile);
 			}
 		}
 		while(listendsr) {
-			fd = accept(listendsr, NULL, NULL);
+			int fd = accept(listendsr, NULL, NULL);
 			if(fd < 0) break;
 			shutdown(fd, SHUT_RDWR);
 			close(fd);
@@ -235,7 +415,8 @@
 		}
 */
 
-		sleep(1);
+		if(waittime/100) sleep(waittime/100);
+		if(waittime%100) usleep((waittime%100)*10000);
 	}
 
 	close(serialfd);


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/