commit: r447 - trunk/daemon

[email protected] Fri, 06 Jan 2012 22:30:56 -0500
Newsgroups gmane.network.spread.cvs
Message-ID <[email protected]>
Author: jonathan
Date: 2012-01-06 22:30:56 -0500 (Fri, 06 Jan 2012)
New Revision: 447

Modified:
   trunk/daemon/Changelog
   trunk/daemon/monitor.c
Log:
Fix spmonitor parameter parsing to check for errors and print useful message instead of crashing. Patch provided by Neal Walfield.

Modified: trunk/daemon/Changelog
===================================================================
--- trunk/daemon/Changelog	2012-01-07 03:19:54 UTC (rev 446)
+++ trunk/daemon/Changelog	2012-01-07 03:30:56 UTC (rev 447)
@@ -1,3 +1,9 @@
+Fri Jan  6 22:28:53 2012  Jonathan Stanton  <[email protected]>
+
+	* monitor.c (Exit_Usage,Usage): Add Exit_Usage() function and 
+	clean up parameter handling and error checks so spmonitor does
+	not segfault on missing parameters. Patch provided by Neal Walfield. 
+
 Fri Jan  6 22:15:45 2012  John Schultz  <[email protected]>
 
 	* alarm.h, data_link.h, data_link.c (DL_init_channel,DL_send): 

Modified: trunk/daemon/monitor.c
===================================================================
--- trunk/daemon/monitor.c	2012-01-07 03:19:54 UTC (rev 446)
+++ trunk/daemon/monitor.c	2012-01-07 03:30:56 UTC (rev 447)
@@ -1073,8 +1073,27 @@
 
 }
 
+static void Exit_Usage(const char *exe, const char *msg1, const char *msg2)
+{
+	if (msg1 != NULL) {
+		Alarm( PRINT, "%s %s\n\n", msg1, (msg2 != NULL ? msg2 : ""));
+	}
+
+	Alarm( EXIT, 
+		"Usage: %s\n"
+		"\t[-p <port number>]    : specify port number\n"
+		"\t[-n <proc name>]      : force computer name\n"
+		"\t[-t <status timeout>] : specify number of seconds between status queries\n"
+		"\t[-c <file name>]      : specify configuration file\n\n",
+		exe );
+}
+
 static	void	Usage(int argc, char *argv[])
 {
+	const char *exe = argv[0];
+	char       *end;
+	long        tmp;
+	
 	My_name = 0; /* NULL */
 	My_port = 6543; 
 
@@ -1083,41 +1102,51 @@
 
 	strcpy( Config_file, "spread.conf" );
 
-	while( --argc > 0 )
-	{
-		argv++;
+	for ( --argc, ++argv; argc >= 2; argc -= 2, argv += 2) {  /* NOTE: all current parameters take only one additional input field */
 
-		if( !strncmp( *argv, "-p", 2 ) )
-		{
-			sscanf(argv[1], "%d", &My_port );
+		if ( !strncmp( *argv, "-p", 3 ) ) {
 
-			argc--; argv++;
+			errno = 0; tmp = strtol(argv[1], &end, 0);
 
-                }else if( !strncmp( *argv, "-n", 2 ) ) {
-			if( strlen( argv[1] ) > MAX_PROC_NAME-1 ) /* -1 for the null */
-				Alarm( EXIT, "Usage: proc name %s too long\n",
-					argv[1] );
+			if (errno != 0 || *end != 0 || end == argv[1] || tmp < 0 || tmp > UINT16_MAX) {
+				Exit_Usage(exe, "Port number must be in range [0, 65536):", argv[1]);
+			}
 
-			memcpy( My_name_buf, argv[1], strlen( argv[1] ) );
+			My_port = (int) tmp;
+
+       	        } else if ( !strncmp( *argv, "-n", 3 ) ) {
+
+			if ( strlen( argv[1] ) > MAX_PROC_NAME - 1 ) {  /* -1 for nul */
+				Exit_Usage(exe, "Proc name too long:", argv[1]);
+			}
+
+			strcpy(My_name_buf, argv[1]);
 			My_name = My_name_buf;
 
-			argc--; argv++;
+		} else if ( !strncmp( *argv, "-t", 3 ) ) {
 
-		}else if( !strncmp( *argv, "-t", 2 ) ){
-			sscanf( argv[1], "%ld", &Send_status_timeout.sec );
+			errno = 0; tmp = strtol(argv[1], &end, 0);
 
-			argc--; argv++;
+			if (errno != 0 || *end != 0 || end == argv[1] || tmp <= 0) {
+				Exit_Usage(exe, "Status query timeout must be a positive integer:", argv[1]);
+			}
 
-		}else if( !strncmp( *argv, "-c", 2 ) ){
+			Send_status_timeout.sec = tmp;
+
+		} else if ( !strncmp( *argv, "-c", 3 ) ) {
+
+			if (strlen(argv[1]) > sizeof(Config_file) - 1) {  /* -1 for nul */
+				Exit_Usage(exe, "Config file name too long:", argv[1]);
+			}
+
 			strcpy( Config_file, argv[1] );
 
-			argc--; argv++;
-		}else{
-			Alarm( EXIT, "Usage: spmonitor\n%s\n%s\n%s\n%s\n",
-				"\t[-p <port number>]: specify port number",
-				"\t[-n <proc name>]  : force computer name",
-				"\t[-t <status timeout>]: specify number of seconds between status queries",
-				"\t[-c <file name>]  : specify configuration file" );
+		} else {
+			Exit_Usage(exe, "Unknown parameter:", *argv);
 		}
 	}
+
+	if (argc != 0) {
+		Exit_Usage(exe, "Unknown or missing parameter:", *argv);
+	}
 }