/* ber-dump.c - Tool to dump BER encoded data
 *      Copyright (C) 2001 g10 Code GmbH
 *
 * This file is part of KSBA.
 *
 * KSBA is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * KSBA is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see .
 */
#include 
#include 
#include 
#include 
#include 
#include 
#include "visibility.h"
#include "ksba.h"
#include "ber-decoder.h"
#define PGMNAME "ber-dump"
#if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 ))
# define  ATTR_PRINTF(a,b)  __attribute__ ((format (printf,a,b)))
#else
# define  ATTR_PRINTF(a,b)
#endif
/* keep track of parsing error */
static int error_counter;
static void print_error (const char *fmt, ... )  ATTR_PRINTF(1,2);
static void
print_error (const char *fmt, ... )
{
  va_list arg_ptr ;
  va_start (arg_ptr, fmt);
  fputs (PGMNAME ": ", stderr);
  vfprintf (stderr, fmt, arg_ptr);
  va_end (arg_ptr);
  error_counter++;
}
static void
fatal (const char *fmt, ... )
{
  va_list arg_ptr ;
  va_start (arg_ptr, fmt);
  fputs (PGMNAME ": fatal: ", stderr);
  vfprintf (stderr, fmt, arg_ptr);
  va_end (arg_ptr);
  exit (1);
}
static void
one_file (FILE *fp, const char *fname, ksba_asn_tree_t asn_tree)
{
  gpg_error_t err;
  ksba_reader_t r;
  BerDecoder d;
  (void)fname;  /* Not yet used in error messages.  */
  err = ksba_reader_new (&r);
  if (err)
    fatal ("out of core\n");
  err = ksba_reader_set_file (r, fp);
  if (err)
    fatal ("ksba_reader_set_file failed: rc=%d\n", err);
  d = _ksba_ber_decoder_new ();
  if (!d)
    fatal ("out of core\n");
  err = _ksba_ber_decoder_set_reader (d, r);
  if (err)
    fatal ("ksba_ber_decoder_set_reader failed: rc=%d\n", err);
  if (asn_tree)
    {
      err = _ksba_ber_decoder_set_module (d, asn_tree);
      if (err)
        fatal ("ksba_ber_decoder_set_module failed: rc=%d\n", err);
    }
  err = _ksba_ber_decoder_dump (d, stdout);
  if (err)
    print_error ("ksba_ber_decoder_dump failed: rc=%d\n", err);
  _ksba_ber_decoder_release (d);
  ksba_reader_release (r);
}
static void
usage (int exitcode)
{
  fputs ("usage: ber-dump [--module asnfile] [files]\n", stderr);
  exit (exitcode);
}
int
main (int argc, char **argv)
{
  const char *asnfile = NULL;
  ksba_asn_tree_t asn_tree = NULL;
  int rc;
  if (!argc || (argc > 1 &&
                (!strcmp (argv[1],"--help") || !strcmp (argv[1],"-h"))) )
    usage (0);
  argc--; argv++;
  if (argc && !strcmp (*argv,"--module"))
    {
      argc--; argv++;
      if (!argc)
        usage (1);
      asnfile = *argv;
      argc--; argv++;
    }
  if (asnfile)
    {
      rc = ksba_asn_parse_file (asnfile, &asn_tree, 0);
      if (rc)
        {
          print_error ("parsing `%s' failed: rc=%d\n", asnfile, rc);
          exit (1);
        }
    }
  if (!argc)
    one_file (stdin, "-", asn_tree);
  else
    {
      for (; argc; argc--, argv++)
        {
          FILE *fp;
          fp = fopen (*argv, "r");
          if (!fp)
              print_error ("can't open `%s': %s\n", *argv, strerror (errno));
          else
            {
              one_file (fp, *argv, asn_tree);
              fclose (fp);
            }
        }
    }
  ksba_asn_tree_release (asn_tree);
  return error_counter? 1:0;
}