gpg: Do not pre-check keys given on the command line.
[gnupg.git] / g10 / gpg.c
index c18edd0..2b48421 100644 (file)
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -303,6 +303,7 @@ enum cmd_and_opt_values
     oEncryptTo,
     oHiddenEncryptTo,
     oNoEncryptTo,
+    oEncryptToDefaultKey,
     oLoggerFD,
     oLoggerFile,
     oUtf8Strings,
@@ -390,6 +391,8 @@ enum cmd_and_opt_values
     oTOFUDefaultPolicy,
     oTOFUDBFormat,
     oWeakDigest,
+    oUnwrap,
+    oOnlySignTextIDs,
 
     oNoop
   };
@@ -500,6 +503,7 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_s (oEncryptTo,      "encrypt-to", "@"),
   ARGPARSE_s_n (oNoEncryptTo, "no-encrypt-to", "@"),
   ARGPARSE_s_s (oHiddenEncryptTo, "hidden-encrypt-to", "@"),
+  ARGPARSE_s_n (oEncryptToDefaultKey, "encrypt-to-default-key", "@"),
   ARGPARSE_s_s (oLocalUser, "local-user",
                 N_("|USER-ID|use USER-ID to sign or decrypt")),
 
@@ -751,6 +755,8 @@ static ARGPARSE_OPTS opts[] = {
                                          "personal-compress-preferences", "@"),
   ARGPARSE_s_s (oFakedSystemTime, "faked-system-time", "@"),
   ARGPARSE_s_s (oWeakDigest, "weak-digest","@"),
+  ARGPARSE_s_n (oUnwrap, "unwrap", "@"),
+  ARGPARSE_s_n (oOnlySignTextIDs, "only-sign-text-ids", "@"),
 
   /* Aliases.  I constantly mistype these, and assume other people do
      as well. */
@@ -1037,7 +1043,7 @@ build_list (const char *text, char letter,
   if (maybe_setuid)
     gcry_control (GCRYCTL_INIT_SECMEM, 0, 0);  /* Drop setuid. */
 
-  indent = utf8_charcount (text);
+  indent = utf8_charcount (text, -1);
   len = 0;
   init_membuf (&mb, 512);
 
@@ -1962,26 +1968,37 @@ parse_trust_model(const char *model)
 }
 #endif /*NO_TRUST_MODELS*/
 
+
 static int
-parse_tofu_policy (const char *policy)
+parse_tofu_policy (const char *policystr)
 {
 #ifdef USE_TOFU
-  if (ascii_strcasecmp (policy, "auto") == 0)
-    return TOFU_POLICY_AUTO;
-  else if (ascii_strcasecmp (policy, "good") == 0)
-    return TOFU_POLICY_GOOD;
-  else if (ascii_strcasecmp (policy, "unknown") == 0)
-    return TOFU_POLICY_UNKNOWN;
-  else if (ascii_strcasecmp (policy, "bad") == 0)
-    return TOFU_POLICY_BAD;
-  else if (ascii_strcasecmp (policy, "ask") == 0)
-    return TOFU_POLICY_ASK;
-  else
-#endif /*USE_TOFU*/
+  struct { const char *keyword; int policy; } list[] = {
+    { "auto",    TOFU_POLICY_AUTO },
+    { "good",    TOFU_POLICY_GOOD },
+    { "unknown", TOFU_POLICY_UNKNOWN },
+    { "bad",     TOFU_POLICY_BAD },
+    { "ask",     TOFU_POLICY_ASK }
+  };
+  int i;
+
+  if (!ascii_strcasecmp (policystr, "help"))
     {
-      log_error (_("unknown TOFU policy '%s'\n"), policy);
+      log_info (_("available TOFU policies:\n"));
+      for (i=0; i < DIM (list); i++)
+        log_info ("  %s\n", list[i].keyword);
       g10_exit (1);
     }
+
+  for (i=0; i < DIM (list); i++)
+    if (!ascii_strcasecmp (policystr, list[i].keyword))
+      return list[i].policy;
+#endif /*USE_TOFU*/
+
+  log_error (_("unknown TOFU policy '%s'\n"), policystr);
+  if (!opt.quiet)
+    log_info (_("(use \"help\" to list choices)\n"));
+  g10_exit (1);
 }
 
 static int
@@ -1994,15 +2011,22 @@ parse_tofu_db_format (const char *db_format)
     return TOFU_DB_SPLIT;
   else if (ascii_strcasecmp (db_format, "flat") == 0)
     return TOFU_DB_FLAT;
+  else if (ascii_strcasecmp (db_format, "help") == 0)
+    {
+      log_info ("available TOFU DB fomats: auto, split, flat\n");
+      g10_exit (1);
+    }
   else
 #endif /*USE_TOFU*/
     {
       log_error (_("unknown TOFU DB format '%s'\n"), db_format);
+      if (!opt.quiet)
+        log_info (_("(use \"help\" to list choices)\n"));
       g10_exit (1);
     }
 }
 
-/* This fucntion called to initialized a new control object.  It is
+/* This function called to initialized a new control object.  It is
    assumed that this object has been zeroed out before calling this
    function. */
 static void
@@ -2078,6 +2102,248 @@ get_default_configname (void)
 }
 
 
+static gpg_error_t
+check_user_ids (strlist_t *sp,
+                int warn_possibly_ambiguous,
+                int error_if_not_found)
+{
+  strlist_t s = *sp;
+  strlist_t s2 = NULL;
+  strlist_t t;
+
+  gpg_error_t rc = 0;
+  gpg_error_t err;
+
+  KEYDB_HANDLE hd = NULL;
+
+  /* A quick check to avoid allocating a new strlist if we can skip
+     all keys.  Handles also the case of !SP.  See below for details.  */
+  for (t = s; t && (!(t->flags & PK_LIST_CONFIG)
+                    && !(t->flags & PK_LIST_ENCRYPT_TO)); t = t->next)
+    ;
+  if (!t)
+    return 0;
+
+  for (t = s; t; t = t->next)
+    {
+      const char *option;
+
+      KEYDB_SEARCH_DESC desc;
+      KBNODE kb;
+      PKT_public_key *pk;
+      char fingerprint_bin[MAX_FINGERPRINT_LEN];
+      size_t fingerprint_bin_len = sizeof (fingerprint_bin);
+      /* We also potentially need a ! at the end.  */
+      char fingerprint[2 * MAX_FINGERPRINT_LEN + 1 + 1];
+
+      /* If the key has been given on the command line and it has not
+         been given by one of the encrypt-to options, we skip the
+         checks.  The reason is that the actual key selection code
+         does its own checks and provides proper status message to the
+         caller to detect the wrong keys.  */
+      if (!(t->flags & PK_LIST_CONFIG) && !(t->flags & PK_LIST_ENCRYPT_TO))
+        {
+          add_to_strlist (&s2, t->d);
+          s2->flags = t->flags;
+          continue;
+        }
+
+      switch (t->flags >> PK_LIST_SHIFT)
+        {
+        case oDefaultKey: option = "--default-key"; break;
+        case oEncryptTo: option = "--encrypt-to"; break;
+        case oHiddenEncryptTo: option = "--hidden-encrypt-to"; break;
+        case oEncryptToDefaultKey: option = "--encrypt-to-default-key"; break;
+        case oRecipient: option = "--recipient"; break;
+        case oHiddenRecipient: option = "--hidden-recipient"; break;
+        case oLocalUser: option = "--local-user"; break;
+        default:
+          log_bug ("Unsupport option: %d\n", (t->flags >> PK_LIST_SHIFT));
+        }
+
+      if (DBG_LOOKUP)
+        {
+          log_debug ("\n");
+          log_debug ("%s: Checking %s=%s\n", __func__, option, t->d);
+        }
+
+      err = classify_user_id (t->d, &desc, 1);
+      if (err)
+        {
+          if (! rc)
+            rc = err;
+
+          log_error (_("key \"%s\" not found: %s\n"),
+                       t->d, gpg_strerror (err));
+          if (!opt.quiet)
+            log_info (_("(check argument of option '%s')\n"), option);
+          continue;
+        }
+
+      if (warn_possibly_ambiguous
+          && ! (desc.mode == KEYDB_SEARCH_MODE_LONG_KID
+                || desc.mode == KEYDB_SEARCH_MODE_FPR16
+                || desc.mode == KEYDB_SEARCH_MODE_FPR20
+                || desc.mode == KEYDB_SEARCH_MODE_FPR))
+        log_info (_("Warning: value '%s' for option '%s'"
+                    " should be a long key ID or a fingerprint\n"),
+                  t->d, option);
+
+      if (! hd)
+        {
+          hd = keydb_new ();
+          if (!hd)
+            {
+              rc = gpg_error_from_syserror ();
+              break;
+            }
+        }
+      else
+        keydb_search_reset (hd);
+
+      err = keydb_search (hd, &desc, 1, NULL);
+      if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
+        {
+          if (DBG_LOOKUP)
+            log_debug ("%s: '%s' not found.\n", __func__, t->d);
+
+          if (error_if_not_found)
+            {
+              if (! rc)
+                rc = err;
+
+              log_error (_("key \"%s\" not found\n"), t->d);
+              if (!opt.quiet)
+                log_info (_("(check argument of option '%s')\n"), option);
+            }
+          continue;
+        }
+      if (err)
+        {
+          if (! rc)
+            rc = err;
+
+          log_error (_("key \"%s\" not found: %s\n"), t->d, gpg_strerror (err));
+          break;
+        }
+
+      err = keydb_get_keyblock (hd, &kb);
+      if (err)
+        {
+          if (! rc)
+            rc = err;
+
+          log_error (_("error reading keyblock: %s\n"), gpg_strerror (err));
+          continue;
+        }
+
+      pk = kb->pkt->pkt.public_key;
+      if ((desc.mode == KEYDB_SEARCH_MODE_SHORT_KID
+           || desc.mode == KEYDB_SEARCH_MODE_LONG_KID
+           || desc.mode == KEYDB_SEARCH_MODE_FPR16
+           || desc.mode == KEYDB_SEARCH_MODE_FPR20)
+          && strchr (t->d, '!'))
+        /* Exact search.  In this case we want to set FINGERPRINT not
+           to the primary key, but the key (primary or sub) that
+           matched the search criteria.  Note: there will always be
+           exactly one match.  */
+        {
+          kbnode_t n = kb;
+          PKT_public_key *match = NULL;
+          int i;
+
+          do
+            {
+              if ((n->flag & 1))
+                /* The matched node.  */
+                {
+                  assert (! match);
+                  match = n->pkt->pkt.public_key;
+                }
+            }
+          while ((n = find_next_kbnode (n, PKT_PUBLIC_SUBKEY)));
+          assert (match);
+
+          fingerprint_from_pk (match, fingerprint_bin, &fingerprint_bin_len);
+          assert (fingerprint_bin_len == sizeof (fingerprint_bin));
+          bin2hex (fingerprint_bin, MAX_FINGERPRINT_LEN, fingerprint);
+
+          i = strlen (fingerprint);
+          fingerprint[i] = '!';
+          fingerprint[i + 1] = '\0';
+        }
+      else
+        {
+          fingerprint_from_pk (pk, fingerprint_bin, &fingerprint_bin_len);
+          assert (fingerprint_bin_len == sizeof (fingerprint_bin));
+          bin2hex (fingerprint_bin, MAX_FINGERPRINT_LEN, fingerprint);
+        }
+
+      add_to_strlist (&s2, fingerprint);
+      s2->flags = s->flags;
+
+      release_kbnode (kb);
+
+      /* Continue the search.  */
+      if (DBG_LOOKUP)
+        log_debug ("%s: Check for duplicates for %s='%s'\n",
+                   __func__, option, t->d);
+      err = keydb_search (hd, &desc, 1, NULL);
+      if (! err)
+        /* Another result!  */
+        {
+          char fingerprint_bin2[MAX_FINGERPRINT_LEN];
+          size_t fingerprint_bin2_len = sizeof (fingerprint_bin2);
+          char fingerprint2[2 * MAX_FINGERPRINT_LEN + 1];
+
+          log_error (_("key specification '%s' is ambiguous\n"), t->d);
+          if (!opt.quiet)
+            log_info (_("(check argument of option '%s')\n"), option);
+
+          if (! rc)
+            rc = GPG_ERR_AMBIGUOUS_NAME;
+
+          err = keydb_get_keyblock (hd, &kb);
+          if (err)
+            log_error (_("error reading keyblock: %s\n"), gpg_strerror (err));
+          else
+            {
+              pk = kb->pkt->pkt.public_key;
+              fingerprint_from_pk (pk, fingerprint_bin2, &fingerprint_bin2_len);
+              assert (fingerprint_bin2_len == sizeof (fingerprint_bin2));
+              bin2hex (fingerprint_bin2, MAX_FINGERPRINT_LEN, fingerprint2);
+
+              /* TRANSLATORS: The %s prints a key specification which
+                 for example has been given at the command line.  Two
+                 lines with fingerprints are printed after this message.  */
+              log_info (_("'%s' matches at least:\n"), t->d);
+              log_info ("  %s\n", fingerprint);
+              log_info ("  %s\n", fingerprint2);
+
+              release_kbnode (kb);
+            }
+        }
+      else if (! (gpg_err_code (err) == GPG_ERR_NOT_FOUND
+                  || gpg_err_code (err) == GPG_ERR_EOF))
+        /* An error (other than "not found").  */
+        {
+          log_error (_("error searching the keyring: %s\n"),
+                     gpg_strerror (err));
+          if (! rc)
+            rc = err;
+        }
+    }
+
+  strlist_rev (&s2);
+
+  keydb_release (hd);
+
+  free_strlist (s);
+  *sp = s2;
+  return rc;
+}
+
+
 int
 main (int argc, char **argv)
 {
@@ -2089,7 +2355,9 @@ main (int argc, char **argv)
     const char *fname;
     char *username;
     int may_coredump;
-    strlist_t sl, remusr= NULL, locusr=NULL;
+    strlist_t sl;
+    strlist_t remusr = NULL;
+    strlist_t locusr = NULL;
     strlist_t nrings = NULL;
     armor_filter_context_t *afx = NULL;
     int detached_sig = 0;
@@ -2577,10 +2845,16 @@ main (int argc, char **argv)
          case oTrustDBName: trustdb_name = pargs.r.ret_str; break;
 
 #endif /*!NO_TRUST_MODELS*/
-         case oDefaultKey: opt.def_secret_key = pargs.r.ret_str; break;
+         case oDefaultKey:
+            sl = add_to_strlist (&opt.def_secret_key, pargs.r.ret_str);
+            sl->flags = (pargs.r_opt << PK_LIST_SHIFT);
+            break;
          case oDefRecipient:
             if( *pargs.r.ret_str )
-              opt.def_recipient = make_username(pargs.r.ret_str);
+             {
+               xfree (opt.def_recipient);
+               opt.def_recipient = make_username(pargs.r.ret_str);
+             }
             break;
          case oDefRecipientSelf:
             xfree(opt.def_recipient); opt.def_recipient = NULL;
@@ -2765,19 +3039,32 @@ main (int argc, char **argv)
          case oNoEncryptTo: opt.no_encrypt_to = 1; break;
          case oEncryptTo: /* store the recipient in the second list */
            sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings );
-           sl->flags = 1;
+           sl->flags = ((pargs.r_opt << PK_LIST_SHIFT) | PK_LIST_ENCRYPT_TO);
+            if (configfp)
+              sl->flags |= PK_LIST_CONFIG;
            break;
          case oHiddenEncryptTo: /* store the recipient in the second list */
            sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings );
-           sl->flags = 1|2;
+           sl->flags = ((pargs.r_opt << PK_LIST_SHIFT)
+                         | PK_LIST_ENCRYPT_TO|PK_LIST_HIDDEN);
+            if (configfp)
+              sl->flags |= PK_LIST_CONFIG;
            break;
+          case oEncryptToDefaultKey:
+            opt.encrypt_to_default_key = 1;
+            break;
          case oRecipient: /* store the recipient */
-           add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings );
+           sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings );
+           sl->flags = (pargs.r_opt << PK_LIST_SHIFT);
+            if (configfp)
+              sl->flags |= PK_LIST_CONFIG;
             any_explicit_recipient = 1;
            break;
          case oHiddenRecipient: /* store the recipient with a flag */
            sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings );
-           sl->flags = 2;
+           sl->flags = ((pargs.r_opt << PK_LIST_SHIFT) | PK_LIST_HIDDEN);
+            if (configfp)
+              sl->flags |= PK_LIST_CONFIG;
             any_explicit_recipient = 1;
            break;
 
@@ -2820,7 +3107,10 @@ main (int argc, char **argv)
          case oAskCertLevel: opt.ask_cert_level = 1; break;
          case oNoAskCertLevel: opt.ask_cert_level = 0; break;
          case oLocalUser: /* store the local users */
-           add_to_strlist2( &locusr, pargs.r.ret_str, utf8_strings );
+           sl = add_to_strlist2( &locusr, pargs.r.ret_str, utf8_strings );
+            sl->flags = (pargs.r_opt << PK_LIST_SHIFT);
+            if (configfp)
+              sl->flags |= PK_LIST_CONFIG;
            break;
          case oCompress:
            /* this is the -z command line option */
@@ -3137,6 +3427,12 @@ main (int argc, char **argv)
           case oWeakDigest:
            additional_weak_digest(pargs.r.ret_str);
            break;
+          case oUnwrap:
+            opt.unwrap_encryption = 1;
+            break;
+          case oOnlySignTextIDs:
+            opt.only_sign_text_ids = 1;
+            break;
 
           case oDisplay:
             set_opt_session_env ("DISPLAY", pargs.r.ret_str);
@@ -3391,7 +3687,7 @@ main (int argc, char **argv)
     /* Do these after the switch(), so they can override settings. */
     if(PGP6)
       {
-        /* That does not anymore work becuase we have no more support
+        /* That does not anymore work because we have no more support
            for v3 signatures.  */
        opt.disable_mdc=1;
        opt.escape_from=1;
@@ -3493,6 +3789,9 @@ main (int argc, char **argv)
          case aSign:
            cmdname="--sign";
            break;
+         case aSignEncr:
+           cmdname="--sign --encrypt";
+           break;
          case aClearsign:
            cmdname="--clearsign";
            break;
@@ -3722,6 +4021,37 @@ main (int argc, char **argv)
         break;
       }
 
+    {
+      int have_def_secret_key = opt.def_secret_key != NULL;
+
+      rc = check_user_ids (&locusr, 1, 1);
+      if (rc)
+        g10_exit (1);
+      rc = check_user_ids (&remusr, 0, 1);
+      if (rc)
+        g10_exit (1);
+      rc = check_user_ids (&opt.def_secret_key, 1, 0);
+      if (rc)
+        g10_exit (1);
+
+      if (opt.encrypt_to_default_key)
+        {
+          const char *default_key = parse_def_secret_key (ctrl);
+          if (default_key)
+            {
+              sl = add_to_strlist2 (&remusr, default_key, utf8_strings);
+              sl->flags = ((oEncryptToDefaultKey << PK_LIST_SHIFT)
+                           | PK_LIST_ENCRYPT_TO);
+            }
+          else if (have_def_secret_key)
+            log_info (_("option '%s' given, but no valid default keys given\n"),
+                      "--encrypt-to-default-key");
+          else
+            log_info (_("option '%s' given, but option '%s' not given\n"),
+                      "--encrypt-to-default-key", "--default-key");
+        }
+    }
+
     /* The command dispatcher.  */
     switch( cmd )
       {
@@ -3862,7 +4192,7 @@ main (int argc, char **argv)
       case aSignSym: /* sign and conventionally encrypt the given file */
        if (argc > 1)
            wrong_args(_("--sign --symmetric [filename]"));
-       rc = sign_symencrypt_file (fname, locusr);
+       rc = sign_symencrypt_file (ctrl, fname, locusr);
         if (rc)
           {
             write_status_failure ("sign-symencrypt", rc);
@@ -3874,7 +4204,7 @@ main (int argc, char **argv)
       case aClearsign: /* make a clearsig */
        if( argc > 1 )
            wrong_args(_("--clearsign [filename]"));
-       if( (rc = clearsign_file(fname, locusr, NULL)) )
+       if( (rc = clearsign_file (ctrl, fname, locusr, NULL)) )
           {
             write_status_failure ("sign", rc);
            log_error("%s: clearsign failed: %s\n",
@@ -4099,7 +4429,12 @@ main (int argc, char **argv)
        else if( cmd == aRecvKeys )
             rc = keyserver_import (ctrl, sl );
        else
-            rc = export_pubkeys (ctrl, sl, opt.export_options);
+          {
+            export_stats_t stats = export_new_stats ();
+            rc = export_pubkeys (ctrl, sl, opt.export_options, stats);
+            export_print_stats (stats);
+            export_release_stats (stats);
+          }
        if(rc)
          {
            if(cmd==aSendKeys)
@@ -4165,7 +4500,12 @@ main (int argc, char **argv)
        sl = NULL;
        for( ; argc; argc--, argv++ )
            add_to_strlist2( &sl, *argv, utf8_strings );
-       export_seckeys (ctrl, sl);
+        {
+          export_stats_t stats = export_new_stats ();
+          export_seckeys (ctrl, sl, stats);
+          export_print_stats (stats);
+          export_release_stats (stats);
+        }
        free_strlist(sl);
        break;
 
@@ -4173,7 +4513,12 @@ main (int argc, char **argv)
        sl = NULL;
        for( ; argc; argc--, argv++ )
            add_to_strlist2( &sl, *argv, utf8_strings );
-       export_secsubkeys (ctrl, sl);
+        {
+          export_stats_t stats = export_new_stats ();
+          export_secsubkeys (ctrl, sl, stats);
+          export_print_stats (stats);
+          export_release_stats (stats);
+        }
        free_strlist(sl);
        break;
 
@@ -4431,16 +4776,13 @@ main (int argc, char **argv)
          KEYDB_HANDLE hd;
 
          if (argc < 2)
-           wrong_args("--tofu-policy POLICY KEYID [KEYID...]");
+           wrong_args ("--tofu-policy POLICY KEYID [KEYID...]");
 
          policy = parse_tofu_policy (argv[0]);
 
          hd = keydb_new ();
          if (! hd)
-           {
-             log_error (_("Failed to open the keyring DB.\n"));
-             g10_exit (1);
-           }
+            g10_exit (1);
 
          for (i = 1; i < argc; i ++)
            {
@@ -4450,7 +4792,8 @@ main (int argc, char **argv)
              rc = classify_user_id (argv[i], &desc, 0);
              if (rc)
                {
-                 log_error (_("Failed to parse '%s'.\n"), argv[i]);
+                 log_error (_("error parsing key specification '%s': %s\n"),
+                             argv[i], gpg_strerror (rc));
                  g10_exit (1);
                }
 
@@ -4462,7 +4805,7 @@ main (int argc, char **argv)
                     || desc.mode == KEYDB_SEARCH_MODE_KEYGRIP))
                {
                  log_error (_("'%s' does not appear to be a valid"
-                              " key id, fingerprint or key grip.\n"),
+                              " key ID, fingerprint or keygrip\n"),
                             argv[i]);
                  g10_exit (1);
                }
@@ -4470,27 +4813,26 @@ main (int argc, char **argv)
              rc = keydb_search_reset (hd);
              if (rc)
                {
-                 log_error (_("Failed to reset keyring handle.\n"));
+                  /* This should not happen, thus no need to tranalate
+                     the string.  */
+                  log_error ("keydb_search_reset failed: %s\n",
+                             gpg_strerror (rc));
                  g10_exit (1);
                }
 
              rc = keydb_search (hd, &desc, 1, NULL);
-             if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY)
-               {
-                 log_error (_("Key '%s' is not available\n"), argv[i]);
-                 g10_exit (1);
-               }
-             else if (rc)
+             if (rc)
                {
-                 log_error (_("Failed to find key '%s'\n"), argv[i]);
+                 log_error (_("key \"%s\" not found: %s\n"), argv[i],
+                             gpg_strerror (rc));
                  g10_exit (1);
                }
 
              rc = keydb_get_keyblock (hd, &kb);
              if (rc)
                {
-                 log_error (_("Failed to read key '%s' from the keyring\n"),
-                            argv[i]);
+                 log_error (_("error reading keyblock: %s\n"),
+                             gpg_strerror (rc));
                  g10_exit (1);
                }