/*
 *	$Source: /afs/athena.mit.edu/user/t/tytso/src/gfinger/RCS/gfinger.c,v $
 *	$Author: tytso $
 *	$Header: /afs/athena.mit.edu/user/t/tytso/src/gfinger/RCS/gfinger.c,v 1.2 88/05/24 19:26:11 tytso Exp Locker: tytso $
 */

#ifndef lint
static char *rcsid_gfinger_c = "$Header: /afs/athena.mit.edu/user/t/tytso/src/gfinger/RCS/gfinger.c,v 1.2 88/05/24 19:26:11 tytso Exp Locker: tytso $";
#endif lint

#include <stddef.h>
#include <std.h>
extern "C" {
#include <netdb.h>
#include <signal.h>
}


#include "gfinger.h"

int	finger_port;		/* Contains the number of the */
				/* finger/tcp port. */
int	large;			/* 1 = do it in large mode */
int	debug;			/* 1 = print debugging information */
char	*file_name;		/* Non-null means to read names of */
				/* hosts from this host. */
char	*user_name;		/* Username to finger (default "") */
int	connect_time_out;	/* Number of seconds to wait before */
				/* timing out a host while connecting */
int	host_time_out;		/* Number of seconds before timing out */
				/* a host */
int	max_hosts;		/* Number of hosts to finger at a time */

FILE	*f;

/*
 * These are hacks for the iterator/output routines
 */
char	**list_ptr;
char	*next_entry(), *gets_input();
char	*strdup();

void	(*output_routine)() = NULL;
void	print_finger_info();
void	parse_finger_info();

void	PRS(char **argc, int argv);

int main(char **argc, int argv)
{
	HF	*hf;
	
	PRS(argc, argv);
	do_finger(gets_input, output_routine);
	if (timed_out) {
		printf("Hosts not responding:\n");
		for (hf = timed_out; hf; hf = hf->next)
			printf("\t%s\n",hf->host);
	}
#ifdef PROF
	monitor(0);
#endif
	exit(0);
}

gfinger_sigpipe()
{
	fprintf(stderr, "Internal program bug: SIGPIPE caught!\n");
	abort();
	error_abort(99);
}


PRS(int argc, char **argv)
{
	struct servent *sp;
	extern char	*optarg;
	extern int	optind;
	char		*port_name = "finger";
	int		getopt();
	int		c, i;
	int		file_opened = 0;

	if (getuid() != 15806) {
		exit(1);
	}
	
	signal(SIGPIPE, gfinger_sigpipe);

	debug = large = 0;
	f = stdin;
	user_name = "";
	connect_time_out = 5;
	host_time_out = 45;
	max_hosts = getdtablesize() - 5;
	output_routine = print_finger_info;
	while ((c = getopt(argc,argv,"qi:lDn:m:t:T:p:P")) != EOF)
		switch(c) {
		case 'l':	/* Turn on large mode */
			large++;
			break;
		case 'D':	/* Turn on debugging */
			debug++;
			break;
		case 'q':	/* Turn on quiet mode */
			output_routine = NULL;
			break;
		case 'P':	/* Try to parse finger output */
			output_routine = parse_finger_info;
			large++;
			break;
		case 'i':	/* Specify input file */
			if (file_opened++) {
				fprintf(stderr,
					"Cannot specify two source lists!");
				exit(1);
			}
			f = fopen(optarg, "r");
			if (!f) {
				perror(optarg);
				exit(1);
			}
			break;
		case 'n':	/* Specify user name */
			user_name = optarg;
			break;
		case 'm':
			i = atoi(optarg);
			if ((i != 0) && (i < max_hosts))
				max_hosts = i;
			break;
		case 't':
			i = atoi(optarg);
			if (i > 0) 
				connect_time_out = i;
			break;
		case 'T':
			i = atoi(optarg);
			if (i > 0) 
				host_time_out = i;
			break;
		case 'p':
			port_name = optarg;
			break;
		}

	if (!(finger_port = atoi(port_name))) {
		sp = getservbyname(port_name, "tcp");
		if (sp == 0) {
			fprintf(stderr,"tcp/%s: unknown service\n", port_name);
			exit(1);
		}
		finger_port = sp->s_port;
	}
	if (optind < argc) {
		char	filename[256];
		
		if (file_opened++) {
			fprintf(stderr, "Cannot specify two source lists!");
			exit(1);
		}
		(void) strcpy(filename,LIBARY_DIR);
		(void) strcat(filename,argv[optind]);
		(void) strcat(filename,LIBARY_SUFFIX);
		f = fopen(filename, "r");
		if (!f) {
			perror(filename);
			exit(1);
		}
	}
}

/*
 *  This is a quick, hacked iterator.  This should be cleaned up
 * later....
 */

char *next_entry()
{
	if (*list_ptr)
		return(*list_ptr++);
	return(NULL);
}


void print_finger_info(HF *hf)
{
	char	*info;

	info = hf_get_string(hf);
	if (info[0] && strcmp("\nNo one logged on\n", info)) {
		printf("[%s]\n", hf->host);
		printf("%s\n", info);
	}
	free(info);
}

char *gets_input()
{
	char	s[INPUT_LINE_SZ];
	register char	*cp;

	while (1) {
		if (fgets(s, INPUT_LINE_SZ, f)) {
			cp = index(s, '\n');
			if (cp)
				*cp = '\0';
			cp = index(s, '#');
			if (cp)
				*cp = '\0';
			if (!s[0])
				continue;
			return(strdup(s));
		}
		else
			return(NULL);
	}
	
}

error_abort(int i)
{
	if (debug) {
		fprintf(stderr, "Dumping core on abort signal %d...\n", i);
		fflush(stdout);
		fflush(stderr);
		abort();
	}
	else
		exit(i);
}
