/*
 * 5799-WZQ (C) COPYRIGHT = NONE
 * LICENSED MATERIALS - PROPERTY OF IBM
 */
/* $Header:servername.c 12.0$ */
/* $ACIS:servername.c 12.0$ */
/* $Source: /ibm/acis/usr/src/ibm/rvd/client/RCS/servername.c,v $ */

#ifndef lint
static char *rcsid = "$Header:servername.c 12.0$";
#endif

/* This file is part of the Project Athena Remote Virtual Disk (RVD) libraries.
 *
 *	$Source: /ibm/acis/usr/src/ibm/rvd/client/RCS/servername.c,v $
 *	$Author: root $
 *	$Header:servername.c 12.0$
 *	$ACIS:servername.c 12.0$
 */

#ifndef lint
static char rcsid_servername_c[] = "$Header:servername.c 12.0$";
#endif lint

/* Copyright 1984 by the Massachusetts Institute of Technology */
/* See permission and disclaimer notice in the file "notice.h" */
#include "notice.h"


#include <setjmp.h>
#include <stdio.h>
#include <sys/types.h>
#include <errno.h>
#include <signal.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>

#define	NOHOST		"(unclaimed)"

#ifndef	SHIFTNAME
#define	SHIFTNAME	3
#endif	SHIFTNAME
#ifndef	DROPDOMAIN
#define	DROPDOMAIN	1
#endif	DROPDOMAIN

#define	tolower(c)	(('A' <= (c) && (c) <= 'Z') ? (c) + ' ' : (c))

#define RESOLVETIMEOUT 13
#define INVERSETIMEOUT 20

/* Resolve the specified host name into an internet address.  The "name" may
 * be either a character string name, or an address in the form a.b.c.d where
 * the pieces are octal, decimal, or hex numbers.  Returns a pointer to a
 * sockaddr_in struct (note this structure is statically allocated and must
 * be copied), or NULL if the name is unknown or we didn't hear from the
 * nameserver in the allotted time.
 */

static jmp_buf jmpenv;

static
timed_out()
{
    longjmp(jmpenv, 1);
}

struct sockaddr_in *
serverbyname(name, timeout)
    char *name;
    int timeout;
{
    register struct hostent *fhost = (struct hostent *)NULL;
    static struct sockaddr_in sa;

    if ((sa.sin_addr.s_addr = inet_addr(name)) != -1) {
        sa.sin_family = AF_INET;	/* grot */
        sa.sin_port = 0;
    } else {
        if (setjmp(jmpenv))
            goto noWait;
        /* arrange to be impatient... */
        alarmClock((timeout ? timeout : RESOLVETIMEOUT), timed_out);
        fhost = gethostbyname(name);
noWait: alarmClock(0, NULL);
        if (fhost == NULL)
            return(NULL);
        sa.sin_family = fhost->h_addrtype;
        sa.sin_port = 0;
        bcopy(fhost->h_addr, &sa.sin_addr, fhost->h_length);
    }
    return(&sa);
}

/*
 *	get host name and pretty it up for presentation...
 */

char *
serverbyaddr(a, timeout)
    struct in_addr a;
    int timeout;
{
    static char	buf[16];
    char *p, *s, shift;
    struct hostent *hp = (struct hostent *)NULL;

    if (setjmp(jmpenv))
        goto noWait;
    /* arrange to be impatient... */
    alarmClock((timeout ? timeout : INVERSETIMEOUT), timed_out);

    hp = gethostbyaddr(& a, sizeof(struct in_addr), AF_INET);

noWait:
    alarmClock(0, NULL);

    if(!hp) {
        sprintf(buf, "[%s]", inet_ntoa(a.s_addr));
        return(buf);
    }

    p = hp->h_name;

    s = buf;
    shift = 1&SHIFTNAME;

    for(; *p; ++p) {
#if DROPDOMAIN
        if(*p == '.')
            break;
#endif
        if(shift)
            *(s++) = tolower(*p);
        else
            *(s++) = *p;
        shift = 2&SHIFTNAME;
    }
    *s = '\0';
    return(buf);
}
