]> git.ipfire.org Git - thirdparty/nettle.git/commitdiff
Improvements to sexp-conv --hash option.
authorNiels Möller <nisse@lysator.liu.se>
Wed, 8 Oct 2025 08:08:53 +0000 (10:08 +0200)
committerNiels Möller <nisse@lysator.liu.se>
Wed, 8 Oct 2025 08:08:53 +0000 (10:08 +0200)
ChangeLog
tools/sexp-conv.c

index 2ad86a9fdf3cd26f8d0a815a0d41b09995c76729..8b49111f6533d80d5bf37d1e076c5b7b45f9a165 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2025-10-08  Niels Möller  <nisse@lysator.liu.se>
+
+       * tools/sexp-conv.c (list_hashes): New function.
+       (parse_options): Make --hash option use nettle_lookup_hash, and
+       change default to sha256. New option --list-hashes. Delete
+       obsolete option --raw-hash.
+
 2025-10-03  Niels Möller  <nisse@lysator.liu.se>
 
        * tools/output.c (sexp_output_init): Add hash argument, allocate
index 883e83399bfa08f14d2382bc54515f6eb9dc2abf..3062f0130df2552e93340191817b08705dcf51a4 100644 (file)
@@ -211,7 +211,7 @@ struct conv_options
   const struct nettle_hash *hash;
 };
 
-enum { OPT_ONCE = 300, OPT_HASH, OPT_LOCK, OPT_HELP };
+enum { OPT_ONCE = 300, OPT_HASH, OPT_LIST, OPT_LOCK, OPT_HELP };
 
 static int
 match_argument(const char *given, const char *name)
@@ -221,10 +221,38 @@ match_argument(const char *given, const char *name)
   return !strcmp(given, name);
 }
 
+static void
+list_hashes (void)
+{
+  unsigned i;
+  const struct nettle_hash *alg;
+  printf ("Available hash algorithms:\n");
+
+  for (i = 0; (alg = nettle_hashes[i]); i++)
+    printf ("  %s\n", alg->name);
+};
+
 static void
 parse_options(struct conv_options *o,
              int argc, char **argv)
-{  
+{
+  static const struct option options[] =
+    {
+      /* Name, args, flag, val */
+      { "help", no_argument, NULL, OPT_HELP },
+      { "version", no_argument, NULL, 'V' },
+      { "once", no_argument, NULL, OPT_ONCE },
+      { "syntax", required_argument, NULL, 's' },
+      { "hash", optional_argument, NULL, OPT_HASH },
+      { "list-hashes", no_argument, NULL, OPT_LIST },
+      { "width", required_argument, NULL, 'w' },
+#if HAVE_FCNTL_LOCKING
+      { "lock", no_argument, NULL, OPT_LOCK },
+#endif
+      { NULL, 0, NULL, 0 }
+    };
+  int c;
+
   o->mode = SEXP_ADVANCED;
   o->prefer_hex = 0;
   o->once = 0;
@@ -232,142 +260,100 @@ parse_options(struct conv_options *o,
   o->hash = NULL;
   o->width = 72;
   
-  for (;;)
-    {
-      static const struct nettle_hash *hashes[] =
-       { &nettle_md5, &nettle_sha1, &nettle_sha256, NULL };
-  
-      static const struct option options[] =
-       {
-         /* Name, args, flag, val */
-         { "help", no_argument, NULL, OPT_HELP },
-         { "version", no_argument, NULL, 'V' },
-         { "once", no_argument, NULL, OPT_ONCE },
-         { "syntax", required_argument, NULL, 's' },
-         { "hash", optional_argument, NULL, OPT_HASH },
-         { "raw-hash", optional_argument, NULL, OPT_HASH },
-         { "width", required_argument, NULL, 'w' },
-#if HAVE_FCNTL_LOCKING
-         { "lock", no_argument, NULL, OPT_LOCK },
-#endif
-#if 0
-         /* Not yet implemented */
-         { "replace", required_argument, NULL, OPT_REPLACE },
-         { "select", required_argument, NULL, OPT_SELECT },
-         { "spki-hash", optional_argument, NULL, OPT_SPKI_HASH },
-#endif
-         { NULL, 0, NULL, 0 }
-       };
-      int c;
-      int option_index = 0;
-      unsigned i;
-     
-      c = getopt_long(argc, argv, "Vs:w:", options, &option_index);
-
-      switch (c)
-       {
-       default:
-         abort();
+  while ((c = getopt_long(argc, argv, "Vs:w:", options, NULL)) != -1)
+    switch (c)
+      {
+      default:
+       abort();
          
-       case -1:
-         if (optind != argc)
-           die("sexp-conv: Command line takes no arguments, only options.\n");
-         return;
+      case -1:
+       break;
 
-       case '?':
-         exit(EXIT_FAILURE);
+      case '?':
+       exit(EXIT_FAILURE);
          
-       case 'w':
-         {
-           char *end;
-           int width;
-           assert(optarg != NULL);
+      case 'w':
+       {
+         char *end;
+         int width;
+         assert(optarg != NULL);
 
-           width = strtol(optarg, &end , 0);
-           if (!*optarg || *end || width < 0)
-             die("sexp-conv: Invalid width `%s'.\n", optarg);
+         width = strtol(optarg, &end , 0);
+         if (!*optarg || *end || width < 0)
+           die("sexp-conv: Invalid width `%s'.\n", optarg);
 
-           o->width = width;
-           break;
-         }
-       case 's':
-         if (o->hash)
-           werror("sexp-conv: Combining --hash and -s usually makes no sense.\n");
-         if (match_argument(optarg, "advanced"))
-           o->mode = SEXP_ADVANCED;
-         else if (match_argument(optarg, "transport"))
-           o->mode = SEXP_TRANSPORT;
-         else if (match_argument(optarg, "canonical"))
-           o->mode = SEXP_CANONICAL;
-         else if (match_argument(optarg, "hex"))
-           {
-             o->mode = SEXP_ADVANCED;
-             o->prefer_hex = 1;
-           }
-         else
-           die("Available syntax variants: advanced, transport, canonical\n");
+         o->width = width;
          break;
+       }
+      case 's':
+       if (match_argument(optarg, "advanced"))
+         o->mode = SEXP_ADVANCED;
+       else if (match_argument(optarg, "transport"))
+         o->mode = SEXP_TRANSPORT;
+       else if (match_argument(optarg, "canonical"))
+         o->mode = SEXP_CANONICAL;
+       else if (match_argument(optarg, "hex"))
+         {
+           o->mode = SEXP_ADVANCED;
+           o->prefer_hex = 1;
+         }
+       else
+         die("Available syntax variants: advanced, hex (also advanced), transport, canonical\n");
+       break;
 
-       case OPT_ONCE:
-         o->once = 1;
-         break;
+      case OPT_ONCE:
+       o->once = 1;
+       break;
        
-       case OPT_HASH:
-         o->mode = SEXP_CANONICAL;
-         if (!optarg)
-           o->hash = &nettle_sha1;
-         else
-           for (i = 0;; i++)
-             {
-               if (!hashes[i])
-                 die("sexp_conv: Unknown hash algorithm `%s'\n",
-                     optarg);
-             
-               if (match_argument(optarg, hashes[i]->name))
-                 {
-                   o->hash = hashes[i];
-                   break;
-                 }
-             }
-         break;
+      case OPT_HASH:
+       if (!optarg)
+         o->hash = &nettle_sha256;
+       else
+         {
+           o->hash = nettle_lookup_hash (optarg);
+           if (!o->hash)
+             die("sexp_conv: Unknown hash algorithm `%s'\n", optarg);
+         }
+       break;
+      case OPT_LIST:
+       list_hashes ();
+       exit (EXIT_SUCCESS);
+
 #if HAVE_FCNTL_LOCKING
-       case OPT_LOCK:
-         o->lock = 1;
-         break;
+      case OPT_LOCK:
+       o->lock = 1;
+       break;
 #endif
-       case OPT_HELP:
-         printf("Usage: sexp-conv [OPTION...]\n"
-                "  Conversion:     sexp-conv [OPTION...] <INPUT-SEXP\n"
-                "  Fingerprinting: sexp-conv --hash=HASH <INPUT-SEXP\n\n"
-                "Reads an s-expression on stdin, and outputs the same\n"
-                "sexp on stdout, possibly with a different syntax.\n\n"
-                "       --hash[=ALGORITHM]   Outputs only the hash of the expression.\n"
-                "                            Available hash algorithms:\n"
-                "                            ");
-         for(i = 0; hashes[i]; i++)
-           {
-             if (i) printf(", ");
-             printf("%s", hashes[i]->name);
-           }
-         printf(" (default is sha1).\n"
-                "   -s, --syntax=SYNTAX      The syntax used for the output. Available\n"
-                "                            variants: advanced, hex, transport, canonical\n"
-                "       --once               Process only the first s-expression.\n"
-                "   -w, --width=WIDTH        Linewidth for base64 encoded data.\n"
-                "                            Zero means no limit.\n"
+      case OPT_HELP:
+       printf("Usage: sexp-conv [OPTION...]\n"
+              "  Conversion:     sexp-conv [OPTION...] <INPUT-SEXP\n"
+              "  Fingerprinting: sexp-conv --hash=HASH <INPUT-SEXP\n\n"
+              "Reads an s-expression on stdin, and outputs the same\n"
+              "sexp on stdout, possibly with a different syntax.\n\n"
+              "       --hash[=ALGORITHM]   Outputs only the hash of the expression (default is sha256)\n"
+              "       --list-hashes        List available algorithms for --hash.\n"
+              "   -s, --syntax=SYNTAX      The syntax used for the output. Available\n"
+              "                            variants: advanced, hex, transport, canonical\n"
+              "       --once               Process only the first s-expression.\n"
+              "   -w, --width=WIDTH        Linewidth for base64 encoded data.\n"
+              "                            Zero means no limit.\n"
 #if HAVE_FCNTL_LOCKING
-                "       --lock               Lock output file.\n"
+              "       --lock               Lock output file.\n"
 #endif
-                "       --raw-hash           Alias for --hash, for compatibility\n"
-                "                            with lsh-1.x.\n\n"
-                "Report bugs to " BUG_ADDRESS ".\n");
-         exit(EXIT_SUCCESS);
-
-       case 'V':
-         printf("sexp-conv (" PACKAGE_STRING ")\n");
-         exit (EXIT_SUCCESS);
-       }
-    }
+              "   -V, --version            Display version.\n"
+              "       --help               Display this help.\n"
+              "Report bugs to " BUG_ADDRESS ".\n");
+       exit(EXIT_SUCCESS);
+
+      case 'V':
+       printf("sexp-conv (" PACKAGE_STRING ")\n");
+       exit (EXIT_SUCCESS);
+      }
+  if (optind != argc)
+    die("sexp-conv: Command line takes no arguments, only options.\n");
+  if (o->hash)
+    /* Always use canonical mode when hashing. */
+    o->mode = SEXP_CANONICAL;
 }
 
 int