# include <ctype.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <unistd.h>
# ifdef HAS_SYSLOG
#  include <syslog.h>
# endif
# include <sys/types.h>

# include "getopt.h"
# include "lutil.h"
# include "nodelist.h"
# include "nlindex.h"
# include "config.h"
# include "version.h"
# include "trap.h"

#ifndef BLANK_SUBS
#define BLANK_SUBS '.'
#endif

static int Verbose = 0;

void usage(void)
{
	confusage(" -v ADDR\n"
			  "\n"
			  "    Copyright (c) 1995 by Boris Tobotras, 2:5020/510\n"
			  "\n"
			  "-v  returns full information from nodelist entry\n"
			  "\n"
			  "ADDR can be incompete. Syntax is following:\n"
			  "\n"
			  "    [[[ZZZ:]NNNN/]FFF][.PPP]\n" );
}

void Lookup( char *Address )
{
	faddr addr;
	char *p;
	node *nlent;

	static char space = '\0';

	if ( space )
		putchar( Verbose ? '\n' : ' ' );
	else
		space = ' ';

	addr.name = NULL;
	addr.domain = whoami->addr->domain;

	p = Address;

	{ 
		char *eol = Address + strlen( Address ) - 1;
		while ( eol > Address + 1 && isspace( eol[ -1 ] ) )
			--eol;
		eol[ 1 ] = '\0';
	}

	if ( isdigit( *p ) ) {
		int n = strtol( p, &p, 10 );
		switch ( *p ) {
		  case '\0':
			addr.zone = whoami->addr->zone;
			addr.net  = whoami->addr->net;
			addr.node = n;
			addr.point= 0;
			break;
		  case ':':
			addr.zone = n;
			++p;			
			addr.net = strtol( p, &p, 10 );
			if ( *p++ != '/' ) {
			  Syntax:
				printf( Address );
				return;
			}
		  ParseNodeAndPoint:
			addr.node = strtol( p, &p, 10 );
			addr.point = 0;
			if ( *p ) {
				if ( *p++ != '.' )
					goto Syntax;
				addr.point = atoi( p );
			}
			break;
				
		  case '.':
			addr.zone = whoami->addr->zone;
			addr.net  = whoami->addr->net;
			addr.node = n;
			addr.point = atoi( ++p );
			break;
		  case '/':
			addr.zone = whoami->addr->zone;
			addr.net = n;
			++p;
			goto ParseNodeAndPoint;
		}
	}
	else {
		if ( *p++ != '.' )
			goto Syntax;
		addr.zone = whoami->addr->zone;
		addr.net  = whoami->addr->net;
		addr.node = whoami->addr->node;
		addr.point= atoi( p );
	}

	nlent = getnlent( &addr ); 

	if ( !nlent )
		puts( Address );
	else {
		char *period, *name;
		dom_trans *trans;
		char *p, buf[128];
		
		if ( Verbose )
			printf( "Internet address: " );

		name = strdup( nlent->sysop );
		while ( ( period = strchr( name, ' ' ) ) )
			*period	= BLANK_SUBS;
		printf( "%s@", name );
		free( name );
		buf[0]='\0';
		if ( nlent->addr.point )
			sprintf( buf, "p%u.f%u.n%u.z%u", nlent->addr.point,
				nlent->addr.node, nlent->addr.net,
				nlent->addr.zone );
		else sprintf( buf , "f%u.n%u.z%u", nlent->addr.node,
				nlent->addr.net, nlent->addr.zone );
		if ( !nlent->addr.domain )
			nlent->addr.domain = whoami->addr->domain;
		sprintf( buf, "%s.%s", buf, nlent->addr.domain );
		for ( trans = domtrans; trans; trans = trans->next ) {
			if ((p=strstr(buf,trans->ftndom))) {
				*p='\0';
				break;
			}
		}
		strcat( buf, trans ? trans->intdom : "<no domain - error!>" );
		printf( "%s", buf );
		if ( Verbose ) {
			unsigned long mask;
			int firstFlag = 1;
			
			printf( "\nFidoNet address: %u:%u/%u", nlent->addr.zone, nlent->addr.net,
				   nlent->addr.node );
			if ( nlent->addr.point > 0 )
				printf( ".%u", nlent->addr.point );
			printf( "@%s", nlent->addr.domain );
			
			if ( nlent->pflag & NL_DOWN )
				printf( ", DOWN" );
			if ( nlent->pflag & NL_HOLD )
				printf( ", HOLD" );
			if ( nlent->pflag & NL_PVT )
				printf( ", PVT" );
			printf( "\nName: %s\n", nlent->name );
			printf( "Location: %s\n", nlent->location );
			printf( "SysOp: %s\n", nlent->sysop );
			printf( "Phone: %s\n", nlent->phone );
			printf( "Speed: %u\nFlags: ", nlent->speed );
			for ( mask = 1L; mask; mask <<= 1 )
				if ( nlent->flags & ~RQMODE & mask ) {
					switch ( mask )	{
					  case CM:
						p = "CM"; break;
					  case MO:
						p = "MO"; break;
					  case LO:
						p = "LO"; break;
					  case V21:
						p = "V21"; break;
					  case V22:
						p = "V22"; break;
					  case V29:
						p = "V29"; break;
					  case V32:
						p = "V32"; break;
					  case V32B:
						p = "V32B"; break;
					  case V33:
						p = "V33"; break;
					  case V34:
						p = "V34"; break;
					  case V42:
						p = "V42"; break;
					  case V42B:
						p = "V42B"; break;
					  case MNP:
						p = "MNP"; break;
					  case H96:
						p = "H96"; break;
					  case HST:
						p = "HST"; break;
					  case H14:
						p = "H14"; break;
					  case H16:
						p = "H16"; break;
					  case NL_MAX:
						p = "MAX"; break;
					  case PEP:
						p = "PEP"; break;
					  case CSP:
						p = "CSP"; break;
					  case ZYX:
						p = "ZYX"; break;
					  case MN:
						p = "MN"; break;
					  default: {
						  static char bug[ 30 ];
						  sprintf( bug, "%08lx", mask );
						  p = bug; break;
						}
					}
					if ( firstFlag )
						firstFlag = 0;
					else
						printf( ", " );
					printf( p );
				}
			if ( nlent->flags & RQMODE ) {
				switch ( nlent->flags & RQMODE ) {
				  case XA:
					p = "XA"; break;
				  case XB:
					p = "XB"; break;
				  case XC:
					p = "XC"; break;
				  case XP:
					p = "XP"; break;
				  case XR:
					p = "XR"; break;
				  case XW:
					p = "XW"; break;
				  case XX:
					p = "XX"; break;
				  default: {
					static char bug[ 30 ];
					sprintf( bug, "%08lx", nlent->flags & RQMODE );
					p = bug; break;
					}
				}
				if ( firstFlag )
					firstFlag = 0;
				else
					printf( ", " );
				printf( p );
			}
			{
				int i;
				for ( i = 0; i < MAXUFLAGS && nlent->uflags[ i ]; ++i ) {
					if ( firstFlag )
						firstFlag = 0;
					else
						printf( ", " );
					printf( nlent->uflags[ i ] );
				}
			}
			putchar( '\n' );
		}
	}
}

int main( int argc, char *argv[] )
{
	int c, rc;

#if defined( HAS_SYSLOG ) && defined( MAILLOG )
	logfacility = MAILLOG;
#endif

	setmyname( argv[ 0 ] );
	catch( myname );
	while ( ( c = getopt( argc, argv, "x:I:hv" ) ) != -1 )
		if ( confopt( c, optarg ) )
			switch ( c ) {
			  case 'v':
				Verbose = 1;
				break;
			  default:
				usage(); 
				exit(1);
			}

	if ( optind == argc ) {
		usage();
		exit( 1 );
	}
	
	if ( ( rc = readconfig() ) )
		{
			fprintf( stderr, "Error getting configuration, aborting\n" );
			return rc;
		}

	while ( optind < argc )
		Lookup( argv[ optind++ ] );

	putchar( '\n' );

	return 0;
}
