/* =============================================================================
// RCSfile: fromhost.c,v
// Revision: 1.5
// Date: 1998/09/29 04:29:47
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// returns the name of the host from which the user has logged in.  Note that
// this is the most immediate host only, not necessarily the host at which
// the user is sitting.
//   ie.  A --rlogin to--> B --rlogin to--> C
// fromhost on B returns A, fromhost on C returns B
//
// original by Paul Schoening (pas@medicine.wustl.edu)
// rewritten by Reece Hart to use the utmpx files, accept full device
// paths (i.e., /dev/ttyq5), work with longer host names, get tty from
// poppen, and other minor changes.
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// LICENSE
// This source code is hereby released to the public domain and is unsupported.
// You are encouraged to copy and modify this file.  Please clearly document
// modifications with authorship and motivation.  Bug reports, code
// contributions, and suggestions are appreciated.
// 
// SOURCE
// New versions of this file may be obtained from (as of 1998/11/08)
// http://www.in-machina.com/~reece/src/fromhost.c
// ftp://in-machina.com/pub/reece/src/fromhost.c
// 
// AUTHOR
// Reece Hart, http://www.in-machina.com/~reece/, PGP:0xD178AAF9
// Do not send unsolicited bulk email.  Boycott companies which do so.
// =========================================|=================================*/

static const char
RCSId[]="Id: fromhost.c,v 1.5 1998/09/29 04:29:47 reece Exp";

#include <stdlib.h>
#include <stdio.h>
#include <memory.h>
#include <string.h>

#ifdef __sgi
#define USE_UTMPX
#endif

#ifdef USE_UTMPX
#include    <utmpx.h>
#define UTMPFN  UTMPX_FILE
#define UTMP_T  struct utmpx
#else
#include    <utmp.h>
#define UTMPFN  UTMP_FILE
#define UTMP_T  struct utmp
#endif

#define UTMP_HOST_LENGTH 30

#define TTY_LEN 20
#define TTY_CMD "tty"

void    usage(const char* applname);

int
main(int argc, char** argv)
  {
  FILE* utmpfile;
  char  hoststr[UTMP_HOST_LENGTH]={'\0'};
  char* host = hoststr;
  char* colon;
  UTMP_T utmprec;
  char  ttystring[TTY_LEN];
  char* tty;
  char* applname=argv[0];
  
  argc--;
  if ( (argc>1) )
    {
    usage(applname);
    exit(EXIT_FAILURE);
    }
  if ( (argc==1) && (strcmp(argv[1],"-help")==0) )
    {
    usage(applname);
    exit(EXIT_SUCCESS);
    }
  if ( (argc==1) && (strcmp(argv[1],"-version")==0) )
    {
    printf("%s (%s)\n",applname,RCSId);
    exit(EXIT_SUCCESS);
    }

  if (argc == 1)
    /* tty provided on the command line */
    strcpy(ttystring,argv[1]);
  else
    /* get it from a pipe */
    {
    FILE* strm;
    strm=popen(TTY_CMD,"r");
    fscanf(strm,"%s",ttystring);
    pclose(strm);
    }

  /* If we get something like /dev/ttyq5, chop it to ttyq5 */
  if ((tty = strrchr(ttystring,'/')) == NULL )
    tty = ttystring;                        /* no / found; use entire string */
  else
    tty += 1;                               /* we want first char AFTER '/' */

  utmpfile = fopen(UTMPFN, "r");            /* open utmp file */
  if (utmpfile == NULL) 
    {
    fprintf(stderr,"fromhost: unable to open %s; aborting.\n",UTMPFN);
    exit(EXIT_FAILURE);
    }

#if DEBUG
  printf("%-15s\t%-15s\t%-15s\n",
         "user", 
         "tty", 
         "host");
#endif
  while (fread(&utmprec,sizeof(UTMP_T),1,utmpfile))
    {
#if DEBUG
    printf("%-15s\t%-15s\t%-15s\n",
           utmprec.ut_user, 
           utmprec.ut_line, 
           utmprec.ut_host);
#endif
    if (strcmp(tty,utmprec.ut_line) == 0)
      {
      /* we've found the appropriate line and we're done with the utmp file */
      fclose(utmpfile);

      /* copy the host field from this utmp record */
      /* anybody know why this doesn't work? (SGI, IRIX5.2)
         strncpy(host,utmprec.ut_host,utmprec.ut_syslen); */
      strncpy(hoststr,utmprec.ut_host,UTMP_HOST_LENGTH);

      /* some machines prepend <user>@ to the hostname, so fast
         forward to the first @ */
      if ( (host=strchr(hoststr, '@')) == NULL )
        /* @ not found found */
        host = hoststr;
      else
        host += 1;

      /* terminate the string at the first colon (i.e. boohoo:0.0) */
      if ( (colon=strrchr(host, ':')) != NULL )
        /* : found */
        *colon='\0';

      if ( host != NULL )
        {
        printf("%s\n",host);
        exit(EXIT_SUCCESS);
        }
      else
        {
        fprintf(stderr,"%s: %s is not in use\n",
                argv[0], tty);
        exit(EXIT_FAILURE);
        }
      }
    }
  /* For valid ttys, I don't think we ever get to here, but just in case... */
  fprintf(stderr,"%s: %s wasn't found in %s: no such device or not in use\n",
         argv[0], tty, UTMPFN);
  exit(EXIT_FAILURE);
  }

void
usage(const char* applname)
  {
  printf("%s: USAGE: %s [<line or device file>]\n",applname,applname);
  printf("  get hostname from which the terminal is connected\n");
  printf("  i.e.,  %s, %s ttyq5, or %s `tty`\n",applname,applname,applname);
  }
