Tapestries/
Tapestries/area/
Tapestries/area/current/
Tapestries/area/helps/
Tapestries/area/tmp/
Tapestries/ideas/
Tapestries/log/
Tapestries/player/
Tapestries/player/b/
Tapestries/player/d/
Tapestries/player/e/
Tapestries/player/h/
Tapestries/player/j/
Tapestries/player/k/
Tapestries/player/l/
Tapestries/player/m/
Tapestries/player/n/
Tapestries/player/r/
Tapestries/player/s/
Tapestries/player/t/
Tapestries/player/u/
Tapestries/player/z/
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define MAXLINE	4096
#define SIZ	500

extern	int	errno;
char	*auth_tcpuser(	register long unsigned int in,
			register short unsigned int local,
			register short unsigned int remote );
unsigned short auth_tcpport = 113;

void err_sys( const char *str )
{
    FILE	*log_file;

    if( !( log_file = fopen( "./getnameauth_err.log", "a+t" ) ) )
    {
	perror( "can't open Error log!" );
	return;
    }    
    fprintf( log_file, "%s\n", str );
    fclose( log_file );

    return;
}

int main( void ) 
{	
    int		n;
    int		int1;
    int		int2;
    int		addr;
    int		server_port;
    struct	hostent	*from;
    char	*user;
    char	line[ MAXLINE ];
    char	addr_buff[ 64 ];
    char	name_buff[ 64 ];

    while( ( n = read( STDIN_FILENO, line, MAXLINE ) ) > 0 )
    {
	line[ n ] = '\0';
	if( sscanf( line, "%s %d %d %d",
	    &name_buff[ 0 ], &int1, &int2, &server_port ) == 4 )
	{
	    from = gethostbyaddr( ( char* )&int1, sizeof( int1 ), AF_INET );     
	    user = auth_tcpuser( int1, server_port, int2 );
	    addr = ntohl( int1 );

	    sprintf( addr_buff, "%d.%d.%d.%d port %d",
		( addr >> 24 ) & 0xFF,
		( addr >> 16 ) & 0xFF,
		( addr >>  8 ) & 0xFF,
		( addr       ) & 0xFF,
		int2 );

	    sprintf( line, "%s:%s:%s",
		name_buff,
		user,
		from ? from->h_name : addr_buff );

	    n = strlen( line );
	    if( write( STDOUT_FILENO, line, n ) != n )
		err_sys( "Error writing to pipe" );
	}
	else
	{
	    if( write( STDOUT_FILENO, "Invalid Query\n", 14 ) != 14 )
		err_sys( "Error writing to pipe" );
	}
    }
    exit( 0 ); 
}


static	char	ruser[ SIZ ];
static	char	realbuf[ SIZ ];
static	char	*buf;

/* This was taken from public domain source that I managed to dredge up,
 * I changed a little of it, but I can't claim that I wrote it all.  I don't
 * know who the original author is, so I can't give him/her credit. */ 

char *auth_tcpuser(
	register long unsigned int in,
	register short unsigned int local,
	register short unsigned int remote )
{
    struct	sockaddr_in	sa;
    register	int		s;
    register	int		buflen;
    register	int		w;
    register	int		saveerrno;
		char		ch;
    unsigned	short		rlocal;
    unsigned	short		rremote;

    if( ( s = socket( AF_INET, SOCK_STREAM, 0 ) ) == -1 )
	return 0;

    sa.sin_family	= AF_INET;
    sa.sin_port		= htons( auth_tcpport );
    sa.sin_addr.s_addr	= in;

    if( connect( s, ( struct sockaddr * )&sa, sizeof( sa ) ) == -1 )
    {
	saveerrno = errno;
	close( s );
	errno = saveerrno;
	return( "(Unknown)" );
    }
    buf	= realbuf;
    sprintf( buf, "%u , %u\r\n",
	( unsigned int )remote,
	( unsigned int )local );

    /*
     * note the reversed order, the example in the RFC is misleading
     */
    buflen = strlen( buf );
    while( ( w = write( s, buf, buflen ) ) < buflen )
	if( w == -1 )	/* should we worry about 0 as well? */
	{
	    saveerrno = errno;
	    close( s );
	    errno = saveerrno;
	    return( "(Send Error)" );
	}
	else
	{
	    buf += w;
	    buflen -= w;
	}

    buf = realbuf;
    while( ( w = read( s, &ch, 1 ) ) == 1 )
    {
	*buf = ch;
	if( ( ch != ' ' )
	 && ( ch != '\t' )
	 && ( ch != '\r' ) )
	    ++buf;
	if( ( buf - realbuf == sizeof( realbuf ) - 1 )
	 || ( ch == '\n' ) )
	    break;
    }
    if( w == -1 )
    {
	saveerrno = errno;
	close( s );
	errno = saveerrno;
	return( "(Read Error)" );
    }
    *buf = '\0';
    bzero( ruser, SIZ );
    if( sscanf( realbuf, "%hd,%hd: USERID :%*[^:]:%s",
		    &rremote, &rlocal, ruser ) < 3 )
    {
	close( s );
	errno = EOF;
	/*
	 * Makes sense, right? well, not when USERID failed to match ERROR
	 * but there's no good error to return in that case
	 */
	fprintf( stderr, realbuf );
	return( "(Auth Error)" );
    }
    if( ( remote != rremote )
     || ( local != rlocal ) )
    {
	close( s );
	errno = EOF;
	return( "REMOTE/LOCAL" );
    }
    close( s );

    return ruser;
}