/* This file is part of the Project Athena Zephyr Notification System.
 * It contains source for the ZSetLocation, ZUnsetLocation, and
 * ZFlushMyLocations functions.
 *
 *	Created by:	Robert French
 *
 *	Copyright (c) 1987,1988,1991 by the Massachusetts Institute of Technology.
 *	For copying and distribution information, see the file
 *	"mit-copyright.h". 
 */

#include <internal.h>

RCSID("$Id: ZLocations.c,v 1.11 2000/09/27 18:14:06 assar Exp $");

#include <pwd.h>

static char host[MAXHOSTNAMELEN], mytty[MAXPATHLEN];
static int location_info_set = 0;

Code_t
ZInitLocationInfo(char *hostname, char *tty)
{
    char *ttyp, *p;
    struct hostent *hent;

    if (hostname) {
	strlcpy(host, hostname, sizeof(host));
    } else {
	if (gethostname(host, sizeof(host)) < 0)
	    return (errno);
	hent = gethostbyname(host);
	if (hent)
	    strlcpy(host, hent->h_name, sizeof(host));
    }
    if (tty) {
	strlcpy(mytty, tty, sizeof(mytty));
    } else {
	ttyp = ttyname(0);
	if (ttyp) {
	    p = strrchr(ttyp, '/');
	    strlcpy(mytty, (p) ? p + 1 : ttyp, sizeof(mytty));
	} else {
	    strlcpy(mytty, "unknown", sizeof(mytty));
	}
    }
    location_info_set = 1;
    return (ZERR_NONE);
}

Code_t
ZSetLocation(char *realm, char *exposure)
{
    return (Z_SendLocation(realm, LOGIN_CLASS, exposure, ZAUTH, 
			   "$sender logged in to $1 on $3 at $2"));
}

Code_t ZUnsetLocation(char *realm)
{
    return (Z_SendLocation(realm, LOGIN_CLASS, LOGIN_USER_LOGOUT, ZNOAUTH, 
			   "$sender logged out of $1 on $3 at $2"));
}

Code_t
ZFlushMyLocations(char *realm)
{
    return (Z_SendLocation(realm, LOGIN_CLASS, LOGIN_USER_FLUSH, ZAUTH, ""));
}

const char *
ZParseExposureLevel (const char *text)
{
    if (text == NULL)
	return (EXPOSE_REALMANN);
    if (!strcasecmp(text, EXPOSE_NONE))
	return (EXPOSE_NONE);
    else if (!strcasecmp(text, EXPOSE_OPSTAFF))
	return (EXPOSE_OPSTAFF);
    else if (!strcasecmp(text, EXPOSE_REALMVIS))
	return (EXPOSE_REALMVIS);
    else if (!strcasecmp(text, EXPOSE_REALMANN))
	return (EXPOSE_REALMANN);
    else if (!strcasecmp(text, EXPOSE_NETVIS))
	return (EXPOSE_NETVIS);
    else if (!strcasecmp(text, EXPOSE_NETANN))
	return (EXPOSE_NETANN);
    else
	return(NULL);
}

Code_t
Z_SendLocation(char *realm, char *class, char *opcode, 
	       Z_AuthProc auth, char *format)
{
    int retval;
    time_t ourtime;
    ZNotice_t notice, retnotice;
    char *bptr[3];
    short wg_port = ZGetWGPort();

    if (!location_info_set)
	ZInitLocationInfo(NULL, NULL);

    memset((char *)&notice, 0, sizeof(notice));
    notice.z_kind = ACKED;
    notice.z_port = (u_short) ((wg_port == -1) ? 0 : wg_port);
    notice.z_class = class;
    notice.z_class_inst = ZGetSender();
    notice.z_opcode = opcode;
    notice.z_sender = 0;
    notice.z_recipient = "";
    notice.z_num_other_fields = 0;
    notice.z_default_format = format;
    notice.z_dest_realm = realm;

    bptr[0] = host;
    ourtime = time((time_t *)0);
    bptr[1] = ctime(&ourtime);
    bptr[1][strlen(bptr[1])-1] = '\0';
    bptr[2] = mytty;

    if ((retval = ZSendList(&notice, bptr, 3, auth)) != ZERR_NONE)
	return (retval);

    retval = Z_WaitForNotice (&retnotice, ZCompareUIDPred, &notice.z_uid,
			      SRV_TIMEOUT);
    if (retval != ZERR_NONE)
      return retval;

    if (retnotice.z_kind == SERVNAK) {
	if (!retnotice.z_message_len) {
	    ZFreeNotice(&retnotice);
	    return (ZERR_SERVNAK);
	}
	if (!strcmp(retnotice.z_message, ZSRVACK_NOTSENT)) {
	    ZFreeNotice(&retnotice);
	    return (ZERR_AUTHFAIL);
	}
	if (!strcmp(retnotice.z_message, ZSRVACK_FAIL)) {
	    ZFreeNotice(&retnotice);
	    return (ZERR_LOGINFAIL);
	}
	ZFreeNotice(&retnotice);
	return (ZERR_SERVNAK);
    } 
	
    if (retnotice.z_kind != SERVACK) {
	ZFreeNotice(&retnotice);
	return (ZERR_INTERNAL);
    }

    if (!retnotice.z_message_len) {
	ZFreeNotice(&retnotice);
	return (ZERR_INTERNAL);
    }

    if (strcmp(retnotice.z_message, ZSRVACK_SENT) &&
	strcmp(retnotice.z_message, ZSRVACK_NOTSENT)) {
	ZFreeNotice(&retnotice);
	return (ZERR_INTERNAL);
    }

    ZFreeNotice(&retnotice);
	
    return (ZERR_NONE);
}
