#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <wait.h>
#include <malloc.h>

#include <rand.h>

#include "libpgp5.h"

/*------------*/

FILE *inf, *outf;

int split()
{
  int passpipe[2];

  pipe(passpipe);

  if (!(fork())) {
    inf = fdopen(passpipe[0], "rb");
    close(passpipe[1]);
    return 1;
  }
  outf = fdopen(passpipe[1], "wb");
  close(passpipe[0]);
  return 0;
}

int main(int argc, char *argv[])
{
  unsigned char keybuf[256], *pp = NULL;
  int i, j, ll;
  int armorflg = 0;
  extern char *optarg;

  inf = stdin, outf = stdout;

  memset(keybuf, 0, 256);
  while ((i = getopt(argc, argv, "p:r:o:i:")) != -1) {

    if (i == 'p')               /* password */
      strcpy(keybuf, optarg), pp = keybuf;
    else if (i == 'r')
      setkeyring5(optarg);
    else if (i == 'o')
      outf = fopen(optarg, "wb");
    else if (i == 'i')
      inf = fopen(optarg, "rb");
    else {
      fprintf(stderr, "usage: pgpv [-p passphrase] [-r ring] plain [-o outf]\n"
              "or pipe, e.g. cat inf | pgpv [opts] >outf\n");
      exit(-1);
    }
  }
  if (!inf || !outf)
    exit(-1);

  /* ========================= */

  while (1) {
    ll = fgetc(inf);
    ungetc(ll, inf);
    if (ll < 0x80) {
      if (armorflg)
        return -1;
      armorflg++;
      if (split())
        continue;
      dearmor(inf, outf);
      fclose(outf);
      wait(&ll);
      return 0;
    }
    if (ll < 0xc0)
      ll = 0xc0 + ((ll & 0x3c) >> 2);
    ll -= 0xc0;
    switch (ll) {
    case 8:
      if (split())
        continue;
      pgpdcom5(inf, outf);
      fclose(outf);
      wait(&ll);
      return 0;
    case 10:                   /* 0xa8,3,PGP */
    case 1:
    case 3:
      if (split())
        continue;
      decrypt5(inf, outf, pp);
      fclose(outf);
      wait(&ll);
      return 0;
    case 9:                    /* from 0xa4 */
      if (split())
        continue;
      {
        unsigned char xfix[] =
        {4, 1, 0, 1}, *xp = xfix;
        void *np;
        getcfbkey(&xp, pp, &np);
        cnvdec5(inf, outf, np);
      }
      fclose(outf);
      wait(&ll);
      return 0;
    case 4:
    case 2:
    case 11:
      i = dlitck5(inf, outf, &j);
      if (j)
        fprintf(stderr, i ? "FAILED SIGNATURE CHECK\n" : "good signature\n");
      return 0;
    }
  }
  return -1;
}
