From:	CRDGW2::CRDGW2::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX" 14-SEP-1989 11:15
To:	MRGATE::"ARISIA::EVERHART"
Subj:	re: vms command line buffer

Message-Id:  <8909141334.AA27227@crdgw1.ge.com>
Received: From COLORM.GATECH.EDU by CRVAX.SRI.COM with TCP; Thu, 14 SEP 89 06:03:00 PDT
Date: Thu, 14 Sep 89 09:03 EDT
From: SYSMIKE@colorm.gatech.edu
Subject: re: vms command line buffer
To: info-vax@crvax.sri.COM
X-Vms-To: IN%"info-vax@crvax.sri.com"

>	For all those who asked, Mike Sieweke was kind enough to send
>me the source to extract the recall buffer.  Below is his version.
>Be warned that Mike also noted, in a followup mail message, that there
>is a problem with the recall buffer wrapping at the end.

That version of the program has serious problems, which I discovered after
a small amount of testing.  Here is a somewhat better version.  Use and
enjoy.  I apologize to anyone who had trouble with the other one.

If anyone is curious about the format of the recall buffer, send me mail.

/*
  getline.c - retrieves the command line from the DCL recall buffer

  Who: 
    Mike Sieweke
    Georgia Tech Research Institute

  When: 
    September, 1989

  What: 
    Peeks into the DCL data structures to find the exact text that was
    typed on the command line.  Preserves case as typed.

  Known problems: 
    o - doesn't check to be sure we're in DCL
    o - may break under VMS later than 5.0-2
    o - needs a basic sanity check (i.e. check that all addresses are in range)

*/

#include syidef
#include stdio
#include ssdef
#include string

typedef struct {
   unsigned short buflen;
   unsigned short item_code;
   char           *buf_adr;
   int            *retlenadr;
} item;

typedef struct {
   item    list;
   int     terminator;
} jpi_item_list;

jpi_item_list jpi_list;
char          version[9];
int           version_len;
int           status;
char          v40[] = "V4.0";
char          v50[] = "V5.0";
char          v60[] = "V6.0";
char          *base = 0;
char          *first;
char          *cmd;
int           cmdlen;
char          temp[256];
int           i;
int           offset;
int           cmdoffset;

main()
{

  jpi_list.list.buflen = 8;
  jpi_list.list.item_code = SYI$_VERSION;
  jpi_list.list.buf_adr = version;
  jpi_list.list.retlenadr = &version_len;

  jpi_list.terminator = 0;

  status = sys$getsyiw( 0, 0, 0, &jpi_list, 0,0,0 );
  version[version_len] = 0;

  if ( strcmp( version, v40 ) >= 0 && strcmp( version, v50 ) < 0 )
    base = 0x7ffe350f;
  if ( strcmp( version, v50 ) >= 0 )
    base = 0x7ffe2d0f;
  if ( strcmp( version, v40 ) < 0 || strcmp( version, v60 ) >= 0 ) {
    printf( "VMS version %s not supported.\n", version );
    return;
  }

  /* address of end of list is right before the buffer */

  first = *(int *)( base - 4 );
  offset = first - base;

  /* the buffer is 0x401 bytes, and it wraps around at the end */

  cmdlen = *( base + (( offset + 0x400 ) % 0x401 ));
  cmdoffset = ( offset - cmdlen - 1 + 0x401 ) % 0x401;
  cmd = base + cmdoffset;
  for ( i = 0; i < cmdlen; i++) {
    temp[i] = *cmd;
    cmdoffset = ( cmdoffset + 1 ) % 0x401;
    cmd = base + cmdoffset;
  }
  temp[cmdlen] = 0;
  printf( "first command was %s\n", temp );
}


I hope this helps.

Mike Sieweke                           Internet: sysmike@colorm.gatech.edu
Georgia Tech Research Institute        Bitnet:   msieweke@gtri01
Atlanta, Georgia                       Usenet:   uunet!gatech!colorm!sysmike


