/*******************************************************************-*-C-*-
 *
 * loginhost - Copyright (C) 1997 Pat Thoyts <Pat.Thoyts@bbsrc.ac.uk>
 *
 * Searches through utmp(5) for the controlling terminal and returns 
 * the login hostname entry. We might need some checks for validity
 * and to ensure we don't screw up when we are at the console.
 * 
 * This is for use setting the DISPLAY envar properly at login.
 * We use something like this in /etc/zshrc or /etc/bashrc:
 *
 * if [ -z "$DISPLAY" ]; then
 *   LOGINADDR="`/usr/local/bin/loginhost`"
 *   if [ ! $LOGINADDR = "0.0.0.0" ]; then
 *     export DISPLAY="$LOGINADDR:0.0"
 *   fi
 * fi
 *
 *
 * gcc -Wall loginhost.c -o loginhost
 * Works on Linux with libc5 and glibc 2.0.
 *
 **************************************************************************/

#include <sys/types.h>
#include <unistd.h>
#include <utmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>

#ifndef UTMP_FILE
#  define UTMP_FILE "/var/run/utmp"
#endif

char* getipaddr(unsigned long addr);

int
main ( int argc, char** argv )
{
  struct utmp utmp;
  int fd = 0, size = 0;
  char* my_tty;

  my_tty = ttyname(0);
  my_tty += 5;

  fd = open(UTMP_FILE, O_RDONLY);
  if (fd == -1) {
    fprintf(stderr, "Oops. Failed to open %s\n", UTMP_FILE);
    exit(1);
  }
  
  size = read(fd, &utmp, sizeof(struct utmp));
  do {
    if ( utmp.ut_type == USER_PROCESS &&
	 strncmp(utmp.ut_line, my_tty, UT_LINESIZE + 1) == 0) {
      printf("%s", getipaddr(utmp.ut_addr));
    }
    size = read(fd, &utmp, sizeof(struct utmp));
  } while ( size == sizeof(struct utmp) );
  
  close(fd);
  
  return 0;
}

char*
getipaddr(unsigned long addr)
{

  typedef union {
    unsigned long ul;
    unsigned char uc[5];
  } ad_t;

  ad_t ad = {0};
  char* ans = NULL;
  
  ad = addr;
  ans = (char*)malloc(sizeof(char) * 255);
  if (ans == NULL)
    exit(1);

  sprintf(ans, "%d.%d.%d.%d", (int)ad.uc[0], (int)ad.uc[1],
           (int)ad.uc[2], (int)ad.uc[3]);
  return ans;
}

