In keeping track of content changes on large numbers of files, I have
found that giving md5sum the ability to take the list of file names to be
processed from a file rather than from the command line argument list is
quite helpful.  I include the mods I made to the 2.0 version of the
source to implement this feature.

Please consider them for future releases.

Thanks very much,

/ken dawson

-------------------------------------------------------------------------
--- md5sum.c-orig       Sun Jul 30 11:36:19 2000
+++ md5sum.c    Sun Jul 30 11:34:14 2000
@@ -88,6 +88,7 @@
   { "string", required_argument, 0, 1 },
   { "text", no_argument, 0, 't' },
   { "warn", no_argument, 0, 'w' },
+  { "file", required_argument, 0, 'f' },
   { GETOPT_HELP_OPTION_DECL },
   { GETOPT_VERSION_OPTION_DECL },
   { NULL, 0, NULL, 0 }
@@ -115,6 +116,11 @@
       --status            don't output anything, status code shows success\n\
   -w, --warn              warn about improperly formated MD5 checksum lines\n\
 \n\
+The --file option is used to draw the list of files from a file; \"-\"\n\
+indicates the standard input.\n\
+\n\
+  -f file, --file file    names of files come from file\n\
+\n\
       --help              display this help and exit\n\
       --version           output version information and exit\n\
 \n\
@@ -446,6 +452,72 @@
           && n_open_or_read_failures == 0) ? 0 : 1);
 }
 
+char *
+get_next_filename (char *argv[], int argc, int *optindp,
+                   const char *name, char **bufp, size_t *buflenp)
+{
+  static int name_file_done;
+
+  if (name != NULL && !name_file_done)
+  {
+    /* take file names from the name file */
+
+    static FILE * name_handle;
+
+    if (name_handle == NULL)
+    {
+      if (STREQ (name, "-"))
+      {
+        name_handle = stdin;
+        have_read_stdin = 1;
+      }
+      else if ((name_handle = fopen(name, "r")) == NULL)
+      {
+        error(0, 0, _("%s: cannot open"), name);
+        name_file_done = 1;
+      }
+    }
+
+    if (!name_file_done)
+    {
+      if (getline(bufp, buflenp, name_handle) <= 0)
+      {
+        if (ferror(name_handle))
+        {
+          error(0, 0, _("%s: read error"), name);
+          (void) fclose(name_handle);
+          name_file_done = 1;
+        }
+        else if (feof(name_handle))
+        {
+          if (!STREQ (name, "-"))
+          {
+            if (fclose(name_handle) < 0)
+            {
+              error(0, 0, _("%s: close failed"), name);
+            }
+          }
+
+          name_file_done = 1;
+        }
+      }
+      else
+      {
+        if ((*bufp)[strlen(*bufp)-1] == '\n')
+        {
+          (*bufp)[strlen(*bufp)-1] = '\0';
+        }
+
+        return(*bufp);
+      }
+    }
+  }
+
+  /* take filenames from argv */
+
+  return((*optindp) >= argc ? NULL : argv[(*optindp)++]);
+}
+
 int
 main (int argc, char **argv)
 {
@@ -456,6 +528,7 @@
   size_t n_strings = 0;
   size_t err = 0;
   int file_type_specified = 0;
+  char *name_file = NULL;
 
 #if O_BINARY
   /* Binary is default on MSDOS, so the actual file contents
@@ -472,7 +545,7 @@
   bindtextdomain (PACKAGE, LOCALEDIR);
   textdomain (PACKAGE);
 
-  while ((opt = getopt_long (argc, argv, "bctw", long_options, NULL)) != -1)
+  while ((opt = getopt_long (argc, argv, "bctwf:", long_options, NULL)) != -1)
     switch (opt)
       {
       case 0:                  /* long option */
@@ -506,6 +579,9 @@
        status_only = 0;
        warn = 1;
        break;
+      case 'f':
+        name_file = optarg;
+        break;
       case_GETOPT_HELP_CHAR;
       case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
       default:
@@ -540,6 +616,21 @@
       usage (EXIT_FAILURE);
     }
 
+  if (name_file != NULL)
+  {
+    if (do_check)
+    {
+      error(0, 0, _("the --file and --check options are mutually exclusive"));
+      usage(EXIT_FAILURE);
+    }
+
+    if (n_strings > 0)
+    {
+      error(0, 0, _("the --file and --string options are mutually exclusive"));
+      usage(EXIT_FAILURE);
+    }
+  }
+
   if (n_strings > 0)
     {
       size_t i;
@@ -573,13 +664,20 @@
     }
   else
     {
-      if (optind == argc)
-       argv[argc++] = "-";
+    char * file;
+    char * buffer = NULL;
+    size_t  bufferlen = 0;
 
-      for (; optind < argc; ++optind)
+    while ((file = get_next_filename(argv, argc, &optind, name_file,
+                                     &buffer, &bufferlen)) != NULL)
        {
          int fail;
-         char *file = argv[optind];
+
+      if (STREQ (file, "-") && have_read_stdin)
+      {
+        error (0, 0, _("can only read from stdin once"));
+        continue;
+      }
 
          fail = md5_file (file, binary, md5buffer);
          err |= fail;
@@ -623,6 +721,11 @@
              putchar ('\n');
            }
        }
+
+    if (buffer != NULL)
+    {
+      free(buffer);
+    }
     }
 
   if (fclose (stdout) == EOF)
@@ -633,3 +736,4 @@
 
   exit (err == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
 }
+

Reply via email to