#include <zephyr/zephyr.h>
#include <zephyr/zephyr_internal.h>
#include <pwd.h>
#include <sys/file.h>
#include <sys/param.h>
#include <netdb.h>

extern char *getenv();
extern int errno;

main(argc, argv)
  int argc;
  char *argv[];
{
  int retval;
  
  if(argc < 3)
  {
    printf("Bad number of arguments\n");
    exit(1);
  }
  ZInitialize();
  
  if(argc == 4 && !strcmp(argv[1], "-login"))
  {
    if((retval = ZHackSetLocation(argv[2], argv[3])) != ZERR_NONE)
    {
      com_err(argv[0], retval, "while sending login message");
    }
    printf("Sending login message\n");
  }
  if(argc == 3 && !strcmp(argv[1], "-logout"))
  {
    if((retval = ZHackUnsetLocation(argv[2])) != ZERR_NONE)
    {
      com_err(argv[0], retval, "while sending logout message");
    }
    printf("Sending logout message\n");
  }
  if(argc == 3 && !strcmp(argv[1], "-flush"))
  {
    if((retval = ZHackFlushMyLocations(argv[2])) != ZERR_NONE)
    {
      com_err(argv[0], retval, "while flushing locations");
    }      
    printf("Flushing locations\n");
  }
}
Code_t ZHackSetLocation(exposure, fakeloc)
    char *exposure;
    char *fakeloc;
{
    return (Z_HackSendLocation(LOGIN_CLASS, exposure, ZAUTH, 
			   "$sender logged in to $1 on $3 at $2",
			    fakeloc));
}

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

Code_t ZHackFlushMyLocations(fakeloc)
    char *fakeloc;
{
    return (Z_HackSendLocation(LOGIN_CLASS, LOGIN_USER_FLUSH, ZAUTH, "",
			       fakeloc));
}

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

Z_HackSendLocation(class, opcode, auth, format, hackhost)
    char *class;
    char *opcode;
    int (*auth)();
    char *format;
    char *hackhost;
{
    char *ttyname(), *ctime();

    int retval;
    long ourtime;
    ZNotice_t notice, retnotice;
    char *bptr[3];
#ifdef X11
    char *display;
#endif /* X11 */
    char *ttyp;
    struct hostent *hent;
    short wg_port = ZGetWGPort();

    (void) bzero((char *)&notice, 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;

    /*
      keep track of what we said before so that we can be consistent
      when changing location information.
      This is done mainly for the sake of the WindowGram client.
     */

    if (!reenter) {
#if 0
	    if (gethostname(host, MAXHOSTNAMELEN) < 0)
		    return (errno);
#endif
	    hent = gethostbyname(hackhost);
	    if (hent)
		    (void) strcpy(host, hent->h_name);
	    bptr[0] = host;
#ifdef X11
	    if ((display = getenv("DISPLAY")) && *display) {
		    (void) strcpy(mytty, display);
		    bptr[2] = mytty;
	    } else {
#endif /* X11 */
		    ttyp = ttyname(0);
		    if (ttyp) {
			bptr[2] = rindex(ttyp, '/');
			if (bptr[2])
			    bptr[2]++;
			else
			    bptr[2] = ttyp;
		    }
		    else
			bptr[2] = "unknown";
		    (void) strcpy(mytty, bptr[2]);
#ifdef X11
	    }
#endif /* X11 */
	    reenter = 1;
    } else {
	    bptr[0] = host;
	    bptr[2] = mytty;
    }

    ourtime = time((long *)0);
    bptr[1] = ctime(&ourtime);
    bptr[1][strlen(bptr[1])-1] = '\0';

	
    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);
}
