/* time_chk.c    R.E. Schmidt, TS, US Naval Observatory, March 1992
 *
 * Check local system clock against the timer server host.
 * This program requests a service called "timesrv".  In order for
 * it to function, an entry for it needs to exist in the
 * /etc/services file.  The port address for this service can be
 * any port number that is likely to be unused, such as 22375,
 * for example.  The host on which the server will be running
 * must also have the same entry (same port number) in its
 * /etc/services file.
 *
 * The name of the system to which the requests will be sent is given
 * as a parameter to the command.
 */


#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <netdb.h>
#include <time.h>

#ifdef AMIGA
  #include <stdlib.h>
  #include <string.h>
#endif

#define LEN     sizeof(long)

int s;                          /* connected socket descriptor */
struct hostent *rh;             /* pointer to host info for remote host */
struct servent *sport;          /* pointer to service information */
long timevar;                   /* contains time returned by time() */
char *(ctime)();                /* declare time formatting routine */
struct sockaddr_in pad_in;      /* for peer socket address */

void main(argc, argv)
  int argc;
  char *argv[];
{
  auto int xcode = 1;
  auto long tsecs;
  auto char myname[40];

  if (argc == 2)
  {
    /* Get local host name
     */
    gethostname(myname, 40);

    /* clear out address structures
     */
    memset((char *) &pad_in, 0, sizeof(struct sockaddr_in));

    /* Set up the peer address to which we will connect.
     */
    pad_in.sin_family = AF_INET;

    /* Get the host information for the hostname that the user passed in.
     */
    if ((rh = gethostbyname(argv[1])) != NULL)
    {
      pad_in.sin_addr.s_addr = ((struct in_addr *) (rh->h_addr))->s_addr;

      /* Find the information for the "timesrv" server in order to get the needed
       * port number.
       */
      if ((sport = getservbyname("timesrv", "tcp")) != NULL)
      {
        pad_in.sin_port = sport->s_port;

        /* Create the socket.
         */
        if ((s = socket(AF_INET, SOCK_STREAM, 0)) != -1)
        {
          /* Try to connect to the remote server at the address which was just built
           * into peeraddr.
           */
          if (connect(s, (struct sockaddr const *) &pad_in, sizeof(struct sockaddr_in)) != -1)
          {
            if (recv(s,(unsigned char *) &tsecs, LEN, 0) != -1)
            {
              tsecs = ntohl(tsecs);

              /* Get local time
               */
              time(&timevar);

              /* Print message indicating completion of task.
               */
              printf("Local Time.....: %24.24s at %s\n",ctime(&timevar),myname );
              printf("Remote Time....: %24.24s at %s\n",ctime(&tsecs  ),argv[1]);  /* GMT string */
              printf("Local - Server.: %d secs\n", timevar - tsecs);

              /* return OK on exit.
               */
              xcode = 0;
            }
            else
            {
              perror(argv[0]);
              fprintf(stderr, "%s: error reading result\n", argv[0]);
            }
          }
          else
          {
            perror(argv[0]);
            fprintf(stderr, "%s: unable to connect to remote\n", argv[0]);
          }
        }
        else
        {
          perror(argv[0]);
          fprintf(stderr, "%s: unable to create socket\n", argv[0]);
        }
      }
      else
        fprintf(stderr, "%s: timesrv not found in /etc/services\n", argv[0]);
    }
    else
      fprintf(stderr, "%s: %s not found in /etc/hosts\n", argv[0], argv[1]);
  }
  else
  {
    fprintf(stderr, "Usage: %s <remote host>\n", argv[0]);
    fprintf(stderr, "Hosts: tick.usno.navy.mil\n");
    fprintf(stderr, "       tock.usno.navy.mil\n");
  }

  exit(xcode);
}
