/* This file is part of GNU Pies testsuite.
   Copyright (C) 2019-2026 Sergey Poznyakoff

   GNU Pies 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, or (at your option)
   any later version.

   GNU Pies 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 GNU Pies.  If not, see <http://www.gnu.org/licenses/>. */

#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <locale.h>
#include <libpies.h>

char *progname;
int precision = 2;

void
usage (FILE *fp, int status)
{
  fprintf (fp, "usage: %s [-v] [-p PREC] URL\n", progname);
  fprintf (fp, "Reads time stamp from URL as per RFC868.\n");
  fprintf (fp, "Exits with status 0 if it is within PREC seconds from the current time.\n");
  fprintf (fp, "Default PREC is %d seconds.\n", precision);
  exit (status);
}

enum { SEVENTY_YEARS = (unsigned long)25567 * 24 * 60 * 60 };

int
main (int argc, char **argv)
{
  int c, fd;
  struct pies_url *url;
  time_t now;
  int human_time = 0;
  union
  {
    char s[80];
    uint32_t u;
  } buf;
  uint32_t t, d;
  ssize_t n;
  int verbose = 0;
  
  progname = argv[0];
  setlocale (LC_ALL, "C");

  while ((c = getopt (argc, argv, "Hhvp:")) != EOF)
    {
      switch (c)
	{
	case 'H':
	  human_time = 1;
	  break;
	  
	case 'h':
	  usage (stdout, 0);
	  break;

	case 'p':
	  precision = atoi (optarg);
	  if (precision <= 0)
	    {
	      fprintf (stderr, "%s: bad precision\n", progname);
	      exit (1);
	    }
	  break;

	case 'v':
	  verbose++;
	  break;
	  
	default:
	  exit (64);
	}
    }

  argc -= optind;
  argv += optind;

  if (argc != 1)
    usage (stderr, 64);
  
  if (pies_url_create (&url, argv[0]))
    {
      perror (argv[0]);
      return 64;
    }

  fd = url_connect (url, NULL);
  time (&now);
  n = read (fd, &buf, sizeof (buf));
  if (n == -1)
    {
      perror ("read");
      exit (1);
    }

  if (human_time)
    {
      struct tm daytime;
      char *p;
      
      if (buf.s[n-1] == '\n')
	{
	  buf.s[--n] = 0;
	  if (buf.s[n-1] == '\r')
	    buf.s[--n] = 0;
	}
      if (verbose > 1)
	printf ("got %*.*s\n", (int)n, (int)n, buf.s);
      p = strptime (buf.s, "%a %b %d %H:%M:%S %Y", &daytime);
      if (!p)
	{
	  fprintf (stderr, "%s: unable to parse time '%s'\n", progname, buf.s);
	  exit (1);
	}
      if (*p)
	{
	  fprintf (stderr, "%s: trailing garbage: '%s'\n", progname, p);
	}
      t = mktime (&daytime);
    }
  else
    {
      if (n < sizeof (buf.u))
	{
	  fprintf (stderr, "%s: read %d bytes\n", progname, (int)n);
	  exit (1);
	}
      t = ntohl (buf.u);
      if (verbose > 1)
	printf ("got %lu\n", (unsigned long) t);
      t -= SEVENTY_YEARS;
    }
  
  if (t > now)
    d = t - now;
  else
    d = now - t;
  
  if (d > precision)
    {
      fprintf (stderr, "%s: time diff %lu\n", progname, (unsigned long) d);
      exit (1);
    }
  else if (verbose)
    printf ("OK\n");
  return 0;
}
