Metropoli BBS
VIEWER: finger.c MODE: TEXT (ASCII)
/*
	finger.c
	Provides a finger client services for NCSA 2.3.
        Reference: RFC 742

	By James Nau, College of Engineering,
	University of Nebraska--Lincoln
*/

#define FINGER_PORT 79

#define ALARM 128

#ifdef __TURBOC__
#include "turboc.h"
#endif
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
#include <dos.h>
#include <ctype.h>
#ifdef MSC
#include <signal.h>
#include <time.h>
#endif


#ifdef MEMORY_DEBUG
#include "memdebug.h"
#endif
#include "netevent.h"
#include "hostform.h"
#include "whatami.h"
#include "externs.h"

#include "netutils.h"

int debug = 0;          /* enable with -D option */
int timeout=300;        /* timeout period in clicks */
//int bypass_passwd=0;    /* whether to bypass the password check, not used */

unsigned char path_name[_MAX_DRIVE+_MAX_DIR],		/* character storage for the path name */
	temp_str[20],buf[_MAX_DIR],temp_data[30];

/* Function Prototypes */
int main(int argc, char *argv[]);
#ifndef __TURBOC__
static void randomize(void );
#endif
void usage(void);
int index (char *string, char ch);
void do_finger(char *host, char *line);
void filter(char *buffer, int buffer_len);

/*
   finger [-h filename] [-l | -w] [user]@hostname
   -h        filename is alternative CONFIG.TEL file
   -l -w     implements longer finger (whois)
   user      username to query
   hostname  the NAME (or Number?) of the host to finger
*/

int main(int argc, char *argv[])
{
   int i;
   char userinfo[128];  /* Ought not to be > 128 char usernames */
   int longform=0;      /* if 1, then try a long finger (whois) */
   int gotuser=0;       /* if 1, doing lookup on a particular user */
   int gothost=0;       /* if 1, we've found the host */
   int atsign;          /* location of @ */
   char *ptr=0;         /* pointer to CONFIG.TEL file */

   char remote_host[256];    /* address of remote host */

#ifdef __TURBOC__
	fnsplit(argv[0],path_name,buf,temp_str,temp_data);	 /* split path up */
#else
   _splitpath(argv[0],path_name,buf,temp_str,temp_data);   /* split path up */
#endif
   strcat(path_name,buf);         /* append the path name */
   strcat(path_name,temp_str);    /* append filename */

   userinfo[0] = '\0';  /* init to a null string */

/* get the command line arguments */
   for (i=1; i<argc; i++)
      if (argv[i][0] == '-')
      {
         switch (argv[i][1])
         {
            case 'D':
               debug = 1;
               if (debug) printf("Debugging now ON\n");
               break;
            case 'h':
               if (i+1 < argc)
                  ptr = argv[i+1];
               else
                  usage();
               if (debug) printf("Using config file [%s]\n",ptr);
               break;
            case 'l':
            case 'w':
               longform = 1;
               if (debug) printf("using long finger form\n");
               break;
			case 't':
			   i++;
			   timeout=atoi(argv[i]);
			   printf("Timeout set to %d clicks.\n",timeout);
			   break;
            default:
               usage ();   /* Tell user how to use it */
         }
         if (debug) printf("argv[%d][1]=-%c\n", i, argv[i][1]);
      }

   if (longform) strcpy(userinfo, "/W ");   /* long finger form, from RFC742 */

   if ((atsign = index(argv[argc-1], '@'))) /* find the host */
   {
      if (debug) printf("atsign [%d]\n", atsign);
      strcpy(remote_host,(argv[argc-1]+atsign));
      gothost++;
      if (atsign != 1)  /* Then, we have a username too */
      {
         strncat(userinfo, argv[argc-1], atsign-1); /* username */
         gotuser++;     /* Add 1 to users */
      }
   }
   else
      usage();     /* Tell them how to use it */

/* OK, we should have all the info we need to do the finger
   So, now let's go do it */

   if (debug) printf("remote_host [%s]\n", remote_host);
   if (debug) printf("userinfo    [%s]\n", userinfo);
   if (debug) printf("gothost [%d]\n", gothost);
   if (debug) printf("gotuser [%d]\n", gotuser);

/* exit (0); */  /* For debugging if you have no network! */

   signal(SIGINT,SIG_IGN);   /* Microsoft intercept of break */

/* Do session initialization.  Snetinit reads config file. */
   /* go find a valid CONFIG.TEL file */
   if (ptr == (char *)NULL) ptr = getenv("CONFIG.TEL");
   if (debug) printf("ptr after getenv [%s]\n",ptr);
   if (ptr != (char *)NULL) Shostfile(ptr);

   if (Snetinit()) /* Should return 0 if network is OK */
   {
      printf("network init failed\n");
      exit (1);
   }

   strcat(userinfo, "\x0d\x0a");  /* end with <CR><LF> as per RFC 742*/

   if (debug) printf("sending [%s] to [%s]\n",userinfo, remote_host);

/* Just Do It */
   do_finger(remote_host, userinfo);

   netshut();      /* shut down all network stuff */
   exit(0);
   return(0);
}


void do_finger(char *remote_host, char *sendline)
{
   int from_port;
   int conn_id;
   struct machinfo *finger_host;
   char buff[132]; /* text returned from the server */
   int bufflen=132;
   int len;        /* length of text read from server */
   int i;

   int theclass, dat;
   int event;

    /* pick a source port at random from the set of privileged ports */
    randomize();
    from_port = rand() % 1023;

    /* do name lookup for server */
    finger_host = gethostinfo(remote_host);
   if (finger_host == (struct machinfo *)NULL)     /* couldn't do it, message in gethostinfo */
   {
      printf("Couldn't lookup host [%s]\n", remote_host);
      return;
   }

/* print out the IP number of the destination host */
   	printf("[");
   	for (i=0; i<4; i++) {
      	printf("%d",finger_host->hostip[i]);
		if (i < 3)
			printf(".");
	}
   	printf("]\n");

        /* open the connection */
        conn_id = connect_sock(finger_host, from_port, FINGER_PORT);
        if (conn_id < 0)
        {
           netshut();
           printf("connect_sock returned %d, exiting\n",conn_id);
        }
        if (debug) printf("connection ident [%d]\n",conn_id);

        /* send the request */
        netwrite(conn_id, sendline, strlen(sendline));
        if (debug) printf("netwrite succeeded--flushing buffer\n");

        netpush(conn_id);
        if (debug) printf("buffer flushing\n");

        if (debug)
        if (!netest(conn_id))
           printf("Connection OK\n");
        else
           printf("nettest: %d\n", netest(conn_id));

/* OK, now, we'll attempt to set an alarm to time out in timeout seconds
   if we get a connection, but no response */

        Stimerset(USERCLASS, ALARM, 0, timeout);
        if (debug) printf("timer set to go off in %d seconds\n", timeout);
        theclass = 0;
        event = 0;
        while ((theclass != USERCLASS || event != ALARM) && !netest(conn_id))
                /* no alarm and good connection */
        {
           Stask();     /* I think I have to call this to post my alarm? */
           event = Sgetevent(CONCLASS | USERCLASS, &theclass, &dat);
           if (debug)
              printf("event[%d] theclass[%d] dat[%d]\n",event, theclass, dat);
           if (!event) continue;
           if (conn_id != dat) continue;

           if (event == CONDATA)
           {
              len = netread(conn_id, buff, bufflen);
              if (len == 0) continue;
              filter(buff, len);
              printf("%.*s", len, buff);
           }
                      
        }
        if (theclass == USERCLASS && event == ALARM)
        {
           printf("Connection timed out in %d clicks\n", timeout);
           netshut();
           exit (2);
        }

#ifdef OLD_WAY
  if (debug) printf("returning eof\n");
 return (EOF);
		while ((event = Sgetevent(CONCLASS,&theclass,&dat)) != CONDATA)
		{
		   printf("event [%d] [%d] [%d]\n",event, theclass, dat);
		   if (conn_id == dat)
		   {
		}
		if (debug) printf("got event CONDATA [%d]\n",CONDATA);
		printf("Event [%d] [%d] [%d]\n",event, theclass, dat);

		   len = netread(conn_id, buff, bufflen);
		   if (debug) printf("len is [%d]\n", len);
		   if (len <=0 ) break;
		   printf("%.*s",len,buff);
   }
   }
#endif
        if (debug) printf("Closing Connection\n");
        netclose(conn_id);
}


#ifdef MSC
#ifndef __TURBOC__
/******************************************************************
*
* randomize()
*
* replicates the randomize function of Turbo C
* MSC 5.1 does not contain it so we have to write it ourselves.
*
*/

static void randomize(void )
{
	srand((unsigned)time(NULL));
}
#endif
#endif


void filter (char *buffer, int buffer_len)
/* filter out control characters, escape sequences, etc
   keeps from reprogramming keys, ...
*/
{
   int i;
   char ch;

   for (i=0; i<buffer_len; i++)
   {
      ch = *(buffer+i);
      if (!(isprint(ch) || isspace(ch))) *(buffer+i) = '?';
   }
}


int index(char *string, char ch)
{
/* shouldn't there be one of these somewhere? */
   int i;

   for (i=0; i<(int)strlen(string); i++)
      if ( *(string+i) == ch) return (i+1);
   return (0);     /* if not found */
}

void usage()
{
   printf("Usage: %s [-h filename] [-t ##] [-l | -w] [user]@hostname\n\n", path_name);

   printf("   -h        filename is alternative CONFIG.TEL file\n");
   printf("   -t ##     set timeout period to ## clicks (default 300)\n");
   printf("   -l -w     implements longer finger (whois)\n");
   printf("   user      username to query\n");
   printf("   hostname  the NAME of the host to finger\n");
   exit (-1);
}

[ RETURN TO DIRECTORY ]