I have been trying to replace getopt with argp in ping.c. Since I am
new to both inetutils and argp, I am curious to know whether I am
proceeding in the right direction or not.

Please find attached a 'diff -uNp' of ping.c showing what I have done
till now. This is not yet finished.

Happy hacking,
Debarshi
--
GPG key ID: 63D4A5A7
Key server: pgp.mit.edu
--- ../inetutils/ping/ping.c	2006-11-17 19:27:29.000000000 +0530
+++ ping/ping.c	2007-03-28 02:43:08.000000000 +0530
@@ -46,6 +46,7 @@
 #include <errno.h>
 #include <limits.h>
 
+#include <argp.h>
 #include <getopt.h>
 #include <icmp.h>
 #include <ping.h>
@@ -100,7 +101,175 @@ static int send_echo (PING * ping);
 
 #define MIN_USER_INTERVAL (200000/PING_PRECISION)
 
-char *program_name;
+const char *argp_program_bug_address = PACKAGE_BUGREPORT;
+const char *argp_program_version = "ping (" PACKAGE_NAME ") " PACKAGE_VERSION;
+
+const char args_doc[] = "ADDRESS";
+const char doc[] = "Send ICMP ECHO_REQUEST packets to network hosts.";
+
+static struct argp_option options[] = {
+  {"", '', 0, OPTION_DOC, "Options controlling ICMP request types:"},
+  {"echo", ICMP_ECHO, 0, 0, "Send ICMP_ECHO requests (default)"},
+  {"address*", ICMP_ADDRESS, 0, 0, "Send ICMP_ADDRESS packets"},
+  {"timestamp", ICMP_TIMESTAMP, 0, 0, "Send ICMP_TIMESTAMP packets"},
+  {"router", ICMP_ROUTERDISCOVERY, 0, 0, "Send ICMP_ROUTERDISCOVERY packets"},
+  {"", '', 0, OPTION_DOC, "Options valid for all request types:"},
+  {"count", 'c', "N", 0, "Stop after sending N packets (default: %d)"},
+  {"debug", 'd', 0, 0, "Set the SO_DEBUG option"},
+  {"interval", 'i', "N", 0, "Wait N seconds between sending each packet"},
+  {"numeric", 'n', 0, 0, "Do not resolve host addresses"},
+  {"ignore-routing", 'r', 0, 0, "Send directly to a host on an attached network"},
+  {"verbose", 'v', 0, 0, "Verbose output"},
+  {"", '', 0, OPTION_DOC, "Options valid for --echo requests:"},
+  {"flood*", 'f', 0, 0, "Flood ping"},
+  {"preload", 'l', "N", 0, "Send N packets as fast as possible before falling into\n
+    normal mode of behavior"},
+  {"pattern", 'p', "PAT", 0, "Fill ICMP packet with given pattern (hex)"},
+  {"quiet", 'q', 0, 0, "Quiet output"},
+  {"route", 'r', 0, 0, "Record route"},
+  {"size", 's', "N", 0, "Set number of data octets to send"},
+  {0}
+};
+
+struct arguments
+{
+  char *args[1];
+  u_char *patptr;
+  int count;
+  int socket_type;
+  int pattern;
+  int size;
+  unsigned int options;
+  unsigned long preload;
+  size_t interval;
+  int (*ping_type) (int argc, char **argv);
+};
+
+static error_t
+parse_opt (int key, char *arg, struct argp_state *state)
+{
+  char *endptr;
+  struct arguments *arguments = state->input;
+
+  arguments->patptr = NULL;
+  arguments->size = PING_DATALEN;
+  arguments->preload = 0;
+  arguments->interval = 0;
+  arguments->ping_type = ping_echo;
+  switch (key)
+    {
+    case 'c':
+      arguments->count = ping_cvt_number (arg, 0, 1);
+      break;
+
+    case 'd':
+      arguments->socket_type = SO_DEBUG;
+      break;
+
+    case 'r':
+      arguments->socket_type = SO_DONTROUTE;
+      break;
+
+    case 'i':
+      arguments->interval = strtod (arg, &endptr);
+      if (*endptr)
+        {
+          fprintf (stderr, "Invalid value (`%s' near `%s')\n",
+                   arg, endptr);
+          exit (1);
+        }
+
+      if ((arguments->interval *= PING_PRECISION) < MIN_USER_INTERVAL)
+        {
+          fprintf (stderr, "Option value too small: %s\n", arg);
+          exit (1);
+        }
+      arguments->options |= OPT_INTERVAL;
+      break;
+
+    case 'p':
+      decode_pattern (arg, &pattern_len, pattern);
+      arguments->patptr = pattern;
+      break;
+
+    case 's':
+      arguments->size = ping_cvt_number (arg, PING_MAX_DATALEN, 1);
+      break;
+
+    case 'n':
+      arguments->options |= OPT_NUMERIC;
+      break;
+
+    case 'q':
+      arguments->options |= OPT_QUIET;
+      break;
+
+    case 'R':
+      arguments->options |= OPT_RROUTE;
+      break;
+
+    case 'v':
+      arguments->options |= OPT_VERBOSE;
+      break;
+
+    case 'l':
+      arguments->preload = strtoul (arg, &endptr, 0);
+      if (*endptr ||   arguments->preload > INT_MAX)
+        {
+	  fprintf (stderr, "ping: invalid preload value (%s)\n", arg);
+          exit (1);
+        }
+      break;
+
+    case 'f':
+      arguments->options |= OPT_FLOOD;
+      break;
+
+    case 't':
+      arguments->ping_type = decode_type (arg);
+      break;
+
+    case ICMP_ECHO:
+      arguments->ping_type = decode_type ("echo");
+      break;
+
+    case ICMP_TIMESTAMP:
+      arguments->ping_type = decode_type ("timestamp");
+      break;
+
+    case ICMP_ADDRESS:
+      arguments->ping_type = decode_type ("address");
+      break;
+
+    case ICMP_ROUTERDISCOVERY:
+      arguments->ping_type = decode_type ("router");
+      break;
+
+    case ARGP_KEY_NO_ARGS:
+      argp_usage (state);
+      break;
+
+    case ARGP_KEY_ARG:
+      if (state->arg_num >= 1)
+        /* Too many arguments. */
+	argp_usage (state);
+      arguments->args[state->arg_num] = arg;
+      break;
+
+    case ARGP_KEY_END:
+      if (state->arg_num < 1)
+	/* Not enough arguments. */
+	argp_usage (state);
+      break;
+
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+
+  return 0;
+}
+
+static struct argp argp = {options, parse_opt, args_doc, doc};
 
 int
 main (int argc, char **argv)
@@ -117,8 +286,6 @@ main (int argc, char **argv)
   int socket_type = 0;
   size_t interval = 0;
 
-  program_name = argv[0];
-
   if (getuid () == 0)
     is_root = true;
 
@@ -302,9 +469,11 @@ main (int argc, char **argv)
 
 
 
-void
+int (*) (int argc, char **argv)
 decode_type (const char *optarg)
 {
+  int (*ping_type) (int argc, char **argv);
+
   if (strcasecmp (optarg, "echo") == 0)
     ping_type = ping_echo;
   else if (strcasecmp (optarg, "timestamp") == 0)
@@ -320,6 +489,8 @@ decode_type (const char *optarg)
       fprintf (stderr, "unsupported packet type: %s\n", optarg);
       exit (1);
     }
+
+ return ping_type;
 }
 
 int volatile stop = 0;
_______________________________________________
bug-inetutils mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/bug-inetutils

Reply via email to