chk_self_sigs (const char *fname, kbnode_t keyblock,
	       PKT_public_key *pk, u32 *keyid, int *non_self )
{
  kbnode_t n, knode = NULL;
  PKT_signature *sig;
  int rc;
  u32 bsdate=0, rsdate=0;
  kbnode_t bsnode = NULL, rsnode = NULL;

  (void)fname;
  (void)pk;

  for (n=keyblock; (n = find_next_kbnode (n, 0)); )
    {
      if (n->pkt->pkttype == PKT_PUBLIC_SUBKEY)
	{
	  knode = n;
	  bsdate = 0;
	  rsdate = 0;
	  bsnode = NULL;
	  rsnode = NULL;
	  continue;
	}

      if ( n->pkt->pkttype != PKT_SIGNATURE )
        continue;

      sig = n->pkt->pkt.signature;
      if ( keyid[0] != sig->keyid[0] || keyid[1] != sig->keyid[1] )
        {
          *non_self = 1;
          continue;
        }

      /* This just caches the sigs for later use.  That way we
         import a fully-cached key which speeds things up. */
      if (!opt.no_sig_cache)
        check_key_signature (keyblock, n, NULL);

      if ( IS_UID_SIG(sig) || IS_UID_REV(sig) )
        {
          KBNODE unode = find_prev_kbnode( keyblock, n, PKT_USER_ID );
          if ( !unode )
            {
              log_error( _("key %s: no user ID for signature\n"),
                         keystr(keyid));
              return -1;  /* The complete keyblock is invalid.  */
            }

          /* If it hasn't been marked valid yet, keep trying.  */
          if (!(unode->flag&1))
            {
              rc = check_key_signature (keyblock, n, NULL);
              if ( rc )
                {
                  if ( opt.verbose )
                    {
                      char *p = utf8_to_native
                        (unode->pkt->pkt.user_id->name,
                         strlen (unode->pkt->pkt.user_id->name),0);
                      log_info (gpg_err_code(rc) == G10ERR_PUBKEY_ALGO ?
                                _("key %s: unsupported public key "
                                  "algorithm on user ID \"%s\"\n"):
                                _("key %s: invalid self-signature "
                                  "on user ID \"%s\"\n"),
                                keystr (keyid),p);
                      xfree (p);
                    }
                }
              else
                unode->flag |= 1; /* Mark that signature checked. */
            }
        }
      else if (IS_KEY_SIG (sig))
        {
          rc = check_key_signature (keyblock, n, NULL);
          if ( rc )
            {
              if (opt.verbose)
                log_info (gpg_err_code (rc) == G10ERR_PUBKEY_ALGO ?
                          _("key %s: unsupported public key algorithm\n"):
                          _("key %s: invalid direct key signature\n"),
                          keystr (keyid));
              n->flag |= 4;
            }
        }
      else if ( IS_SUBKEY_SIG (sig) )
        {
          /* Note that this works based solely on the timestamps like
             the rest of gpg.  If the standard gets revocation
             targets, this may need to be revised.  */

          if ( !knode )
            {
              if (opt.verbose)
                log_info (_("key %s: no subkey for key binding\n"),
                          keystr (keyid));
              n->flag |= 4; /* delete this */
            }
          else
            {
              rc = check_key_signature (keyblock, n, NULL);
              if ( rc )
                {
                  if (opt.verbose)
                    log_info (gpg_err_code (rc) == G10ERR_PUBKEY_ALGO ?
                              _("key %s: unsupported public key"
                                " algorithm\n"):
                              _("key %s: invalid subkey binding\n"),
                              keystr (keyid));
                  n->flag |= 4;
                }
              else
                {
                  /* It's valid, so is it newer? */
                  if (sig->timestamp >= bsdate)
                    {
                      knode->flag |= 1;  /* The subkey is valid.  */
                      if (bsnode)
                        {
                          /* Delete the last binding sig since this
                             one is newer */
                          bsnode->flag |= 4;
                          if (opt.verbose)
                            log_info (_("key %s: removed multiple subkey"
                                        " binding\n"),keystr(keyid));
                        }

                      bsnode = n;
                      bsdate = sig->timestamp;
                    }
                  else
                    n->flag |= 4; /* older */
                }
            }
        }
      else if ( IS_SUBKEY_REV (sig) )
        {
          /* We don't actually mark the subkey as revoked right now,
             so just check that the revocation sig is the most recent
             valid one.  Note that we don't care if the binding sig is
             newer than the revocation sig.  See the comment in
             getkey.c:merge_selfsigs_subkey for more.  */
          if ( !knode )
            {
              if (opt.verbose)
                log_info (_("key %s: no subkey for key revocation\n"),
                          keystr(keyid));
              n->flag |= 4; /* delete this */
            }
          else
            {
              rc = check_key_signature (keyblock, n, NULL);
              if ( rc )
                {
                  if(opt.verbose)
                    log_info (gpg_err_code (rc) == G10ERR_PUBKEY_ALGO ?
                              _("key %s: unsupported public"
                                " key algorithm\n"):
                              _("key %s: invalid subkey revocation\n"),
                              keystr(keyid));
                  n->flag |= 4;
                }
              else
                {
                  /* It's valid, so is it newer? */
                  if (sig->timestamp >= rsdate)
                    {
                      if (rsnode)
                        {
                          /* Delete the last revocation sig since
                             this one is newer.  */
                          rsnode->flag |= 4;
                          if (opt.verbose)
                            log_info (_("key %s: removed multiple subkey"
                                        " revocation\n"),keystr(keyid));
                        }

                      rsnode = n;
                      rsdate = sig->timestamp;
                    }
                  else
                    n->flag |= 4; /* older */
                }
            }
        }
    }

  return 0;
}