--- snmpget.c.org	2004-09-29 18:52:52.403756900 -0700
+++ snmpget.c	2004-09-29 18:48:13.986255800 -0700
@@ -42,6 +42,7 @@
 #endif
 #include <stdio.h>
 #include <ctype.h>
+#include <assert.h>
 #if TIME_WITH_SYS_TIME
 # ifdef WIN32
 #  include <sys/timeb.h>
@@ -72,11 +73,22 @@
 #include <net-snmp/utilities.h>
 
 #include <net-snmp/net-snmp-includes.h>
+#include "range.h"
 
 int             failures = 0;
 
+static char *inputfile = NULL;
+
 #define NETSNMP_DS_APP_DONT_FIX_PDUS 0
 
+static int get_next_addr(FILE *fp, struct in_addr *next_in_addr);
+
+static int getoptArg(int argc, char *const *argv);
+
+void log_objid(const oid * objid, size_t objidlen);
+
+static void log_variable(const oid * objid,size_t objidlen,
+				  const netsnmp_variable_list * variable);
 static void
 optProc(int argc, char *const *argv, int opt)
 {
@@ -88,8 +100,19 @@
                 netsnmp_ds_toggle_boolean(NETSNMP_DS_APPLICATION_ID, 
 					  NETSNMP_DS_APP_DONT_FIX_PDUS);
                 break;
+	    case 'i':
+		if (getoptArg(argc,argv)) {
+		    optind++;
+		}
+		if (!optarg) {
+		    snmp_log(LOG_ERR, "Missing input file\n");
+		    exit(1);
+		}
+		inputfile = optarg;
+		optarg += strlen(inputfile);
+		break;
             default:
-                fprintf(stderr, "Unknown flag passed to -C: %c\n",
+                snmp_log(LOG_ERR, "Unknown flag passed to -C: %c\n",
                         optarg[-1]);
                 exit(1);
             }
@@ -109,6 +132,8 @@
             "  -C APPOPTS\t\tSet various application specific behaviours:\n");
     fprintf(stderr,
             "\t\t\t  f:  do not fix errors and retry the request\n");
+    fprintf(stderr,
+	   "  i: inputfile\n");
 }
 
 int
@@ -118,6 +143,8 @@
     netsnmp_pdu    *pdu;
     netsnmp_pdu    *response;
     netsnmp_variable_list *vars;
+    struct in_addr  next_in_addr;
+    struct timeval	start_time,end_time;
     int             arg;
     int             count;
     int             current_name = 0;
@@ -126,6 +153,8 @@
     size_t          name_length;
     int             status;
     int             exitval = 0;
+    char	*hostrange;
+    FILE	*fp;
 
     /*
      * get the common command line arguments 
@@ -141,13 +170,13 @@
     }
 
     if (arg >= argc) {
-        fprintf(stderr, "Missing object name\n");
+        snmp_log(LOG_ERR, "Missing object name\n");
         usage();
         exit(1);
     }
     if ((argc - arg) > SNMP_MAX_CMDLINE_OIDS) {
-        fprintf(stderr, "Too many object identifiers specified. ");
-        fprintf(stderr, "Only %d allowed in one request.\n", SNMP_MAX_CMDLINE_OIDS);
+        snmp_log(LOG_ERR, "Too many object identifiers specified. ");
+        snmp_log(LOG_ERR, "Only %d allowed in one request.\n", SNMP_MAX_CMDLINE_OIDS);
         usage();
         exit(1);
     }
@@ -160,7 +189,35 @@
 
     SOCK_STARTUP;
 
-
+    fp = NULL;
+    if (inputfile) {
+	fp = fopen(inputfile,"r");
+	if (!fp) {
+	    snmp_log(LOG_ERR,"Unable to open file %s\n",inputfile);
+	    SOCK_CLEANUP;
+	    exit(1);
+	}
+    }
+    else {
+    /*
+     * Get the ip address range and convert to start ip and end ip
+     */
+    hostrange = session.peername;
+    if(!set_range(hostrange))
+    {
+        snmp_log(LOG_ERR,"%s not a valid ip or range\n",hostrange);
+        snmp_sess_perror("snmpget", &session);
+        clean_range();
+        SOCK_CLEANUP;
+        exit(1);
+    }
+    }
+    gettimeofday(&start_time,NULL);
+    /*
+     * send GET request for every next ip address
+     */
+    while (get_next_addr(fp,&next_in_addr)) {
+	session.peername = inet_ntoa(next_in_addr);
     /*
      * Open an SNMP session.
      */
@@ -170,11 +227,13 @@
          * diagnose snmp_open errors with the input netsnmp_session pointer 
          */
         snmp_sess_perror("snmpget", &session);
+	    clean_range();
+	    if (fp) {
+	     fclose(fp);
+	    }
         SOCK_CLEANUP;
         exit(1);
     }
-
-
     /*
      * Create PDU for GET request and add object names to request.
      */
@@ -189,10 +248,13 @@
     }
     if (failures) {
         SOCK_CLEANUP;
+	    clean_range();
+	    if (fp) {
+		fclose(fp);
+	    }
         exit(1);
     }
 
-
     /*
      * Perform the request.
      *
@@ -203,24 +265,28 @@
     status = snmp_synch_response(ss, pdu, &response);
     if (status == STAT_SUCCESS) {
         if (response->errstat == SNMP_ERR_NOERROR) {
+		snmp_log(LOG_NOTICE,"\nThe snmp result of %s: \n",
+			 session.peername);
+
             for (vars = response->variables; vars;
-                 vars = vars->next_variable)
-                print_variable(vars->name, vars->name_length, vars);
+		     vars = vars->next_variable) {
+		    log_variable(vars->name, vars->name_length, vars);
+		}
 
         } else {
-            fprintf(stderr, "Error in packet\nReason: %s\n",
+		snmp_log(LOG_ERR, "Error in packet\nReason: %s\n",
                     snmp_errstring(response->errstat));
 
             if (response->errindex != 0) {
-                fprintf(stderr, "Failed object: ");
+		    snmp_log(LOG_ERR, "Failed object: ");
                 for (count = 1, vars = response->variables;
                      vars && count != response->errindex;
                      vars = vars->next_variable, count++)
                     /*EMPTY*/;
                 if (vars) {
-                    fprint_objid(stderr, vars->name, vars->name_length);
+			log_objid(vars->name, vars->name_length);
 		}
-                fprintf(stderr, "\n");
+		    snmp_log(LOG_ERR, "\n");
             }
             exitval = 2;
 
@@ -239,7 +305,7 @@
         }                       /* endif -- SNMP_ERR_NOERROR */
 
     } else if (status == STAT_TIMEOUT) {
-        fprintf(stderr, "Timeout: No Response from %s.\n",
+	    snmp_log(LOG_ERR, "\nTimeout: No Response from %s.\n",
                 session.peername);
         exitval = 1;
 
@@ -253,7 +319,152 @@
     if (response)
         snmp_free_pdu(response);
     snmp_close(ss);
+    }
+    gettimeofday(&end_time,NULL);
+    snmp_log(LOG_NOTICE,"\nsnmpget completed in %u seconds\n",
+	     (end_time.tv_sec)-(start_time.tv_sec));
+    clean_range();
+    if (fp) {
+	fclose(fp);
+    }
     SOCK_CLEANUP;
     return exitval;
 
 }                               /* end main() */
+
+/**
+ * logs the variable to a file or stdout
+ *
+ * @param objid     The object id.
+ * @param objidlen  The length of the object id.
+ * @param variable  The variable to print.
+ */
+static void
+log_variable(   const oid * objid,
+                size_t objidlen, const netsnmp_variable_list * variable)
+{
+    u_char         *buf = NULL;
+    size_t          buf_len = 256, out_len = 0;
+
+    assert(objid);
+    assert(variable);
+
+	if ((buf = (u_char *) calloc(buf_len, 1)) == NULL) {
+        snmp_log(LOG_NOTICE, "[TRUNCATED]\n");
+        return;
+    }
+    if (sprint_realloc_variable(&buf, &buf_len, &out_len, 1,
+				objid, objidlen, variable)) {
+	snmp_log(LOG_NOTICE, "%s\n", buf);
+    } else {
+	snmp_log(LOG_NOTICE, "%s [TRUNCATED]\n", buf);
+    }
+
+    SNMP_FREE(buf);
+}
+
+/**
+ * get optarg
+ *
+ * @param argc  argument count
+ * @param argv  array of arguments
+ */
+static int
+getoptArg(int argc, char *const *argv) {
+    /*
+     * Support '... -Lx=value ....' syntax
+     */
+    if (*optarg == '=') {
+        optarg++;
+    }
+    /*
+     * and '.... "-Lx value" ....'  (*with* the quotes)
+     */
+    while (*optarg && isspace(*optarg)) {
+        optarg++;
+    }
+    /*
+     * Finally, handle ".... -Lx value ...." syntax
+     *   (*without* surrounding quotes)
+     */
+    if (!*optarg) {
+        /*
+         * We've run off the end of the argument
+         *  so move on to the next.
+         * But we might not actually need it, so don't
+	 *  increment optind just yet!
+         */
+        optarg = argv[optind];
+        return 1;
+    }
+    return 0;
+}
+
+/**
+ * Get next address from the ip range or from the file
+ *
+ * @param objid      The oid to print
+ * @param objidlen   The length of oidid.
+ *
+ * returns 1 on success and 0 on failure
+ */
+static int
+get_next_addr(FILE *fp, struct in_addr *next_in_addr) {
+
+    char	buf[80]; /* size of the buffer to read from file */
+
+    assert(next_in_addr);
+    memset(buf,0,sizeof(buf));
+
+    if (fp) {
+	while(fgets(buf,sizeof(buf),fp)) {
+	    /*
+	     * get next ip address from the file. if error, read the next
+	     * ipaddress from the file
+	     */
+	    if (strlen(buf) > 0) {
+		if(!inet_aton(buf, next_in_addr)) {
+		    snmp_log(LOG_ERR,"%s - bad IP address\n", buf);
+		    memset(buf,0,sizeof(buf));
+		    continue;
+		}
+		return 1;
+	    }
+	}
+    }
+    else if (next_address(next_in_addr)) {
+	/*
+	 * get next ip address in the range.
+	 */
+	return 1;
+    }
+    return 0;
+}
+
+/**
+ * Log an oid to the standard out or log file
+ *
+ * @param objid      The oid to print
+ * @param objidlen   The length of oidid.
+ */
+void
+log_objid(const oid * objid, size_t objidlen)
+{                             /* number of subidentifiers */
+    u_char         *buf = NULL;
+    size_t          buf_len = 256, out_len = 0;
+    int             buf_overflow = 0;
+
+	if ((buf = (u_char *) calloc(buf_len, 1)) == NULL) {
+        snmp_log(LOG_NOTICE, "[TRUNCATED]\n");
+        return;
+    }
+    netsnmp_sprint_realloc_objid_tree(&buf, &buf_len, &out_len, 1,
+				      &buf_overflow, objid, objidlen);
+    if (buf_overflow) {
+	snmp_log(LOG_NOTICE, "%s [TRUNCATED]\n", buf);
+    } else {
+	snmp_log(LOG_NOTICE, "%s\n", buf);
+    }
+
+	SNMP_FREE(buf);
+}
