From:	CSBVAX::MRGATE!JOE%FHCRCVAX.BITNET@CUNYVM.CUNY.EDU@SMTP  8-JUN-1988 06:05
To:	ARISIA::EVERHART
Subj:	STATUS mods - %physical displays internet address if using CMU TC


Received: from UWAVM.ACS.WASHINGTON.EDU by oly.acs.washington.edu ; Wed, 08 Jun 88 03:03:18 PDT
Received: from UWAVM.ACS.WASHINGTON.EDU by UWAVM.ACS.WASHINGTON.EDU (Mailer
 X1.24) with BSMTP id 3934; Wed, 08 Jun 88 03:03:13 PDT
P1-Message-Id: US**EDU;UWAVM.ACS.WASHINGTON.EDU:LOjw7kYM
Date:         Tue, 7 Jun 88 15:48-0700
X400-Trace:   US**EDU; arrival Tue, 7 Jun 88 15:48-0700 action Relayed
X400-Trace:   US**EDU; arrival Wed, 8 Jun 88 03:03-0700 action Relayed
From:         Joe Meadows<JOE%FHCRCVAX.BITNET@oly.acs.washington.edu>
Subject:      STATUS mods - %physical displays internet address if using CMU TC
 P/IP
To:           <Everhart%Arisia.decnet@GE-CRD.ARPA>, <MANAGER@UWAPHAST.BITNET>,
              <KC@CPAC.BITNET>, <MARKUS@LOYVAX.BITNET>, <HORN@SHSU.BITNET>,
              <R1ECGF@AKRONVM.BITNET>, <SKAPUR@SBCCMAIL.BITNET>, <PETERSON@
              UWACHEM.BITNET>, <MARTIN@UNCVAX1.BITNET>, <nilsson@
              DKNBI51.BITNET>, <CAL@VTHCL.BITNET>, <ACCESS@ALCANKTN.BITNET>,
              <eakmm@TTACS.BITNET>, <JWILKINSON@HMCVAX.BITNET>, <KHAN@
              QCVAX.BITNET>, <BISSON@MITBATES.BITNET>, <BRUCE@UWALOCKE.BITNET>,
              <BEN@TECHMAX.BITNET>, <EBAIREAD@IRLEARN.BITNET>, <SYSHKF@
              ULKYVX.BITNET>, <WALDMAN@TMPLCIS.BITNET>, <PALTER@UBVMS.BITNET>,
              <S211KENO@HTIKUB5.BITNET>
Message-Id:   <UWAVM.ACS.WASHINGTON.EDU:LOjw7kYM*>
X-VMS-To: @SYS$LOGIN:GLENN.EVERHART,@STATUS

Hello everyone,

Included are some mods you might want to apply if you have CMU TCP/IP.
These enable you to see where an incoming Telnet session is coming from.

FORMAT_MOD.C is just a replacement for a routine in FORMAT.C,
CONVERT_PSEUDO_TERMINAL.C is the module that converts a pseudo
terminal (TPAnnn) into an internet address (i.e. MAX.ACS.WASHINGTON.EDU).
Ideas for extending this module are welcome. Currently it assumes a TPAnnn
terminal is a TELNET session, but obviously that's not always the case,
for example BOSS, and PHOTO both use TPA devices I believe. It works
by finding out who owns the associated PYAnnn device, and getting a list
of devices owned by that process. If it includes an IPnnn device, than
I do a QIOW to that device to get the internet address.

For other purposes though, what should I display? I.E. for BOSS and
PHOTO sessions.. Should I just display the terminal of the owner of
the PYAnn device?

A new MAKEFILE is included at the end. If you are using COMPILE.COM and
LINK.COM be sure to add the module CONVERT_PSEUDO_TERMINAL..

Cheers,
Joe Meadows

$ create/log FORMAT_MOD.C
$DECK
cvt$physical_terminal(items,itm,string,link)
  struct FmtItemsList *items;
  int itm;
  char *string;
  int link;
{
  struct FmtItems *item;
  char buff[64];
  char node[128];
  int status,len, i;
  struct itmlst dvi[2];
  struct dsc$descriptor devname = {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,0} ;
  struct TermInfo {
    long int duetim;
    long int pid;
    unsigned short int rtt_link;
  } terminfo;
  char *ptr,*start;

  item = &(items->item[itm]);

  dvi[0].length = sizeof(buff);
  dvi[0].code = DVI$_TT_PHYDEVNAM;
  dvi[0].bufadr = buff;
  dvi[0].retlen = &len;
  dvi[1].code = 0;
  dvi[1].length = 0;

  /* figure out length of string */
  len = item->size;
  start = get_address(item,link);
  ptr = start + len;
  while ((--ptr >= start) && ((*ptr == ' ') || (*ptr == '\0')))
    --len;

  ptr = start;
  if (*ptr == '_') {
    ++ptr;
    --len;
  };

  for (i=0; i < len; i++) {
    string[i] = *ptr++;
  };
  string[len] = '\0';

  if (string[len - 1] == ':')
    string[--len] = '\0';

  devname.dsc$w_length = len;
  devname.dsc$a_pointer = string;

  status = term_info(&devname,&terminfo); /* get rtt_link if remote */
  if ((status & 1) && terminfo.rtt_link)
  {
    for (i=0; i < 10; ++i) node[i] = '\0';
    /* here we need to call decnetinfo passing it the link number */
    status = Get_DECnet_Node(terminfo.rtt_link,node);
    if (status & 1)
    {
      /* trim off trailing spaces */
      for( i = strlen(node);
           (i > 0) && ((node[i] == ' ') || (node[i] == '\0'));
           --i)
      {
        node[i] = '\0';
      }
      strcpy(string,node);
      strcat(string,".decnet");
    }
  } else { /* not a remote terminal, let's see if its a TPA device */
    if (string[0] == 'T' && string[1] == 'P' && string[2] == 'A')
    {
      if (convert_pseudo_terminal(string,node) & 1)
      {
        strcpy(string,node);
      }
    }
    else
    {
      if ((status = sys$getdviw(0,0,&devname,dvi,0,0,0,0)) & 1) {
        if (len) {
          buff[len] = '\0';
          if (buff[len - 1] == ':')
            buff[--len] = '\0';
          if (buff[0] == '_')
            sprintf(string,"%s",&buff[1]);
          else
            sprintf(string,"%s",buff);
        } else {
          sprintf(string,"<disconnected>");
        }
      }
    }
  }
}
$EOD
$ create/log CONVERT_PSEUDO_TERMINAL.C
$DECK
#include iodef
#include descrip
#include dvidef

#include "globals.h" /* for itmlst */

#define TCP$INFO IO$_MODIFY
#define GETHST IO$_SKIPFILE

struct tcp_info {
  unsigned char ForeignHostSize;
  unsigned char LocalHostSize;
  char ForeignHost[128];
  long int ForeignPort;
  short int unused;
  char LocalHost[128];
  long int LocalPort;
  unsigned long int LocalAddress;
  unsigned long int ForeignAddress;
};

struct gethst_info {
  unsigned long int NameLen;
  char Name[128];
};


convert_pseudo_terminal(terminal,where)
  char *terminal,*where;
{
  char device[10]; /* that oughta hold the device name */
  struct dsc$descriptor dev = {0,0,0,device};
  static struct DevInfo {
    long int pid;
    short int len;
    char name[64];
  } devinfo[20];
  static int devinfosize = sizeof(struct DevInfo);
  static int class = -1, devinfocnt = 20;
  int pid, status, i, indx, chan, notfound;
  struct tcp_info info;
  struct gethst_info host;
  short int iosb[4];
  struct itmlst dvilst[] = {4,DVI$_PID,&pid,0,0,0,0,0};

  if (terminal[0] != 'T' || terminal[1] != 'P' || terminal[2] != 'A')
    return(0);

  strcpy(device,terminal);
  device[0] = 'P';
  device[1] = 'Y';
  dev.dsc$w_length = strlen(device);

  /* getdvi to find out who owns PYAnnn */
  status = sys$getdviw(0,0,&dev,dvilst,iosb,0,0,0);
  if (!(status & 1)) return(status);
  if (!(iosb[0] & 1)) return(iosb[0]);

  /* find all devices owned by this PID */
  status = devices(&class, &pid, &devinfocnt, &devinfosize, devinfo);
  if (status & 1) {
    i = 0;
    notfound = -1;
    while (notfound && devinfo[i].len) {
      if (devinfo[i].name[0] == '_' &&
          devinfo[i].name[1] == 'I' &&
          devinfo[i].name[2] == 'P')
      {
        dev.dsc$w_length = devinfo[i].len;
        dev.dsc$a_pointer = devinfo[i].name;
        notfound = 0;
      }
      else
        ++i;
    };
    if (notfound) return(0);

    status = sys$assign(&dev, &chan, 0, 0);
    if (!(status & 1)) return(status);

    status = sys$qiow(0,chan,TCP$INFO,iosb,0,0,&info,sizeof(info),0,0,0,0);
    if (!(status & 1)) return(status);
    if (!(iosb[0] & 1)) return(iosb[0]);

    sprintf(where,"%.*s",info.ForeignHostSize, info.ForeignHost);
    return(1);
  };

    /* viola .. */
  /* else */
    /* perhaps display owner username, imagname, or better - terminal ? */


  return(0);
}
$EOD
$ create/log MAKEFILE.
$DECK
C_MOD = server build cleanup compare decnet format get init\
        parse readport lookup_terminal convert_pseudo_terminal
MACRO_MOD = devices terminal epid_to_ipid

all : status server

debug : statusd serverd

status.exe : status.obj window.obj
        link $?, c/option

statusd : status.obj window.obj
        link/debug $?, c/option

server.exe : globaldef.obj $(C_MOD).obj $(MACRO_MOD).obj
        link $(C_MOD), globaldef, $(MACRO_MOD), c/option, \
                sys\$system:sys.stb/sel

serverd : $(C_MOD).obj $(MACRO_MOD).obj
        link/debug $(C_MOD), globaldef, $(MACRO_MOD), c/option, \
                sys\$system:sys.stb/sel

..c.obj :
        cc/debug $*

..mar.obj :
        macro/debug $*

status.obj : $*.c globals.h

$(MACRO_MOD).obj : $*.mar

globaldef.obj : $*.c globals.h server.h keywords.h jpicodes.h

$(C_MOD).obj : $*.c globals.h server.h jpicodes.h

# keywords.h is built by order_keywords, using keywords.dat
keywords.h : keywords.dat order_keywords.exe
        run order_keywords

# jpicodes.h is built by the program jpicodes
jpicodes.h : jpicodes.exe
        run jpicodes

# order_keywords reads keywords.dat and creates keywords.h
order_keywords.exe : order_keywords.obj
        link order_keywords,c/option

order_keywords.obj : order_keywords.c

jpicodes.exe : jpicodes.obj
        link jpicodes,c/option

jpicodes.obj : jpicodes.c
$EOD
