/*
 *	$Source: /afs/athena.mit.edu/astaff/project/xmit/Xcluster/snmp/RCS/netfinger.c,v $
 *	$Author: tom $
 *	$Locker:  $
 *	$Header: /afs/athena.mit.edu/astaff/project/xmit/Xcluster/snmp/RCS/netfinger.c,v 1.1 93/08/03 12:58:09 tom Exp $
 */

#ifdef lint
static char *rcsid_finger_c = "$Header: /afs/athena.mit.edu/astaff/project/xmit/Xcluster/snmp/RCS/netfinger.c,v 1.1 93/08/03 12:58:09 tom Exp $";
#endif lint

/*
 * Copyright (c) 1980 Regents of the University of California.
 * All rights reserved.  The Berkeley software License Agreement
 * specifies the terms and conditions for redistribution.
 */

#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1980 Regents of the University of California.\n\
 All rights reserved.\n";
#endif not lint

#ifndef lint
static char sccsid[] = "@(#)finger.c	5.8 (Berkeley) 3/13/86";
#endif not lint

#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <utmp.h>
#include <sys/signal.h>
#include <pwd.h>
#include <stdio.h>
#include <lastlog.h>
#include <ctype.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#include <errno.h>
#include <signal.h>
#include <setjmp.h>


char *strcpy();

struct timeval tv;
struct timezone tz;
char buffer[512];
jmp_buf top_level;
int hiccup();
int ping();

main(argc, argv)
	int argc;
	register char **argv;
{
  int ret;
  int used=0, free=0;
  int i;

  for (i = 1; i < argc; i++)
    {
      ret = ping(argv[i]);
      if (ret == 0)
        ret = netfinger(argv[i]);
      if (ret == 0)
	free++;
      if (ret == 1)
	used++;
    }
  printf("%d %d\n", free, used);
  exit(0);
}


int netfinger(name)
     char *name;
{
  struct hostent *hp;
  struct servent *sp;
  struct sockaddr_in sin;
  int s;
  register FILE *f;
  register int c;
  register int lastc;
  char retval[17];
  int count = 0;

  bzero(retval, 17);

  hp = gethostbyname(name);
  if (hp == NULL)
    {
      static struct hostent def;
      static struct in_addr defaddr;
      static char *alist[1];
      static char namebuf[128];
      int inet_addr();

      defaddr.s_addr = inet_addr(name);
      if (defaddr.s_addr == -1)
	{
	  return (-1);
	}
      strcpy(namebuf, name);
      def.h_name = namebuf;
      def.h_addr_list = alist, def.h_addr = (char *)&defaddr;
      def.h_length = sizeof (struct in_addr);
      def.h_addrtype = AF_INET;
      def.h_aliases = 0;
      hp = &def;
    }
  sp = getservbyname("finger", "tcp");
  if (sp == 0)
    {
      return (-2);
    }
  sin.sin_family = hp->h_addrtype;
  bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length);
  sin.sin_port = sp->s_port;
  s = socket(hp->h_addrtype, SOCK_STREAM, 0);
  if (s < 0)
    {
      return (-3);
    }
  if (connect(s, (char *)&sin, sizeof (sin)) < 0)
    {
      close(s);
      return (-4);
    }
  write(s, "\r\n", 2);
  f = fdopen(s, "r");

  while ((c = getc(f)) != EOF && count < 17)
    {
      switch(c)
	{
	case 0210:
	case 0211:
	case 0212:
	case 0214:
	  c -= 0200;
	  break;
	case 0215:
	  c = '\n';
	  break;
	}

      if (!(isspace(c) || c == '\n'))
	{
	  retval[count] = c;
	  count++;
	}

/*
      if (isprint(c) || isspace(c))
	putchar(c);
      else
	putchar(c ^ 0100);
*/
    }
  (void)fclose(f);

  if (!strcmp(retval, "Nooneloggedon")  ||  !strcmp(retval, ""))
    return(0);

  return (1);
}


ping(hostname)
     char *hostname;
{
	struct sockaddr_in sin;
	struct servent *sp;
	struct hostent *host;
	register int i;
	register int s;
	int attempts = 0, cc;
	
	sp = getservbyname("time", "udp");
	if (sp == 0) {
		fprintf (stderr, "time/udp: unknown service.\n");
		exit (1);
	}
	host = gethostbyname(hostname);
	if (host == NULL) {
		return (2);
	}
	sin.sin_family = host->h_addrtype;
	bcopy (host->h_addr, (caddr_t)&sin.sin_addr,
			host->h_length);
	sin.sin_port = sp->s_port;
	s = socket(AF_INET, SOCK_DGRAM, 0);
	if (s < 0) {
		return (3);
	}
	if (connect (s, (caddr_t)&sin, sizeof (sin)) < 0) {
		return (4);
	}
	setjmp(top_level);
	if (attempts++ > 1) {
		close (s);
		return (10);
	}
	alarm(0);
	signal(SIGALRM, hiccup);
	alarm(3);
	send (s, buffer, 40, 0); /* Send an empty packet */
	if (gettimeofday (&tv, &tz) < 0) {
		return (5);
	}
	cc = recv (s, buffer, 512, 0);
	if (cc < 0) {
		close(s);
		return (7);
	}
	if (cc != 4) {
		close(s);
		return(8);
	}
	close (s);
	return (0);
}

hiccup() {
	longjmp (top_level,0);
}
