From:	CSBVAX::MRGATE!/ADMD=/PRMD=BITNET/O=FHCRCVAX/PN=JOE/@US@SMTP 24-AUG-1988 16:59
To:	ARISIA::EVERHART
Subj:	status part 5 of 7


Received: from UWAVM.ACS.WASHINGTON.EDU by uwavm.acs.washington.edu ; Wed, 24 Aug 88 13:12:41 PDT
Received: from UWAVM.ACS.WASHINGTON.EDU by UWAVM.ACS.WASHINGTON.EDU (Mailer
 X1.24) with BSMTP id 7557; Wed, 24 Aug 88 13:12:37 PDT
P1-Message-Id: US**EDU;UWAVM.ACS.WASHINGTON.EDU:LUoUUI96
Date:         Wed, 24 Aug 88 13:07-0700
X400-Trace:   US**EDU; arrival Wed, 24 Aug 88 13:07-0700 action Relayed
X400-Trace:   US**EDU; arrival Wed, 24 Aug 88 13:12-0700 action Relayed
From:         Joe Meadows</ADMD=/PRMD=BITNET/O=FHCRCVAX/PN=JOE/@US>
Subject:      status part 5 of 7
To:           <Everhart%Arisia.decnet@GE-CRD.ARPA>
Message-Id:   <UWAVM.ACS.WASHINGTON.EDU:LUoUUI96*>
X-VMS-To: @SYS$LOGIN:GLENN.EVERHART

+-+-+-+ Beginning of part 5 +-+-+-+
X  fprintf(outfile,"globaldef int max_keywords = %d;\n",lines);
X  fprintf(outfile,"\n");
X  fprintf(outfile,"globaldef struct ItemNode keywords[] = {\n");
X  write_node(head_name);
X  fprintf(outfile,"    {\"\", 0, 0, format_literal}");
X  fprintf(outfile,"  };\n");
X  fprintf(outfile,"\n");
X  fprintf(outfile,"#else\n");
X  fprintf(outfile,"globalref struct ItemNode keywords[];\n");
X  fprintf(outfile,"globalref int max_keywords;\n");
X  fprintf(outfile,"#endif\n");
X  fclose(outfile);
X}
X
Xvoid write_node(node)
X  struct node *node;
X{
X  static int index = 0;
X
X  if (node->left)
X    write_node(node->left);
X
X  fprintf(outfile,"    {\"%s\", ",node->str);
X  dummy = lookup(&(*node).str[node->ptr[0]], head_init);
X  fprintf(outfile,"%s, ",dummy->str);
X  fprintf(outfile,"%s, ",&(*node).str[node->ptr[1]]);
X  dummy = lookup(&(*node).str[node->ptr[2]], head_format);
X  fprintf(outfile,"%s},\n",dummy->str);
X
X  if (node->right)
X    write_node(node->right);
X}
X
Xcompare(symstr,node,dummy)
X  unsigned char *symstr;
X  struct node *node;
X  unsigned int dummy;
X{
X  short int cmp;
X
X  cmp = strcmp(symstr, node->str);
X  if (cmp > 0) cmp = 1;
X  if (cmp < 0) cmp = -1;
X  return(cmp);
X}
X
Xallocate(symstr,node,dummy)
X  unsigned char *symstr;
X  struct node **node;
X  unsigned int dummy;
X{
X  static int numbytes = sizeof(struct node);
X  int i, j = 0;
X  int status;
X
X  /* allocate the node */
X  status = lib$get_vm(&numbytes, node);
X  if (!(status & 1)) return(status);
X
X  /* symstr is a BUFSIZ character string, with commas in it */
X  /* symstr actually should be 4 strings in 1, to get this */
X  /* effect, we replace all the commas with \0, and store the */
X  /* offset in the node.ptr[] array.. There should be 3 commas */
X  for (i = 0; i < strlen(symstr); i++)
X    if (symstr[i] == ',') {
X      (*node)->str[i] = '\0';
X      if (j < 3) /* ignore extra commas */
X        (*node)->ptr[j++] = i+1;
X    }
X    else
X      (*node)->str[i] = symstr[i];
X  return(1);
X}
X
Xtraverse_tree(node,indexval)
X  struct node *node;
X  int *indexval;
X{
X  if (node->left)
X    traverse_tree(node->left, indexval);
X
X  node->index = *indexval;
X  *indexval += 1;
X
X  if (node->right)
X    traverse_tree(node->right, indexval);
X}
X
Xlookup(key,node)
X  char *key;
X  struct node *node;
X{
X  int compare;
X
X  if (node == 0)
X    return(0);
X
X  compare = strncmp(key, (*node).str, strlen(key));
X  if (compare < 0)
X    return(lookup(key,node->left));
X  else if (compare > 0)
X    return(lookup(key,node->right));
X  else
X    return(node);
X}
Xvoid write_routines(node,zart)
X  struct node *node;
X  int zart;
X{
X  if (node->left)
X    write_routines(node->left,zart);
X
X  if (flag) {
X    fprintf(outfile,"  %s%s",node->str,zart?"()":"");
X    flag = 0;
X  }
X  else
X    fprintf(outfile,",\n  %s%s",node->str,zart?"()":"");
X
X  if (node->right)
X    write_routines(node->right,zart);
X}
X$EOD
X$ create/log PARSE.C
X$DECK
X#include iodef
X#include "starlet.h"
X#include "server.h"
X
Xint get_header();
Xint get_display();
Xint cleanup();
X
Xparse(indx)
X  int indx;
X{
X  static char zero = '\0';
X  char *buffer;
X  int status;
X
X  buffer = gbl_links[indx].buffer;
X
X  switch (buffer[0]) {
X    case HEADER:
X#ifdef DEBUG
Xprintf("In parse - HEADER, index = %d\n",indx);
X#endif
X      build_header(indx);
X      return(1);
X      break;
X    case DISPLAY:
X#ifdef DEBUG
Xprintf("In parse - DISPLAY, index = %d\n",indx);
X#endif
X      build_display(indx);
X      return(1);
X      break;
X    case SELECT:
X#ifdef DEBUG
Xprintf("In parse - SELECT, index = %d\n",indx);
X#endif
X      build_select(indx);
X      return(1);
X      break;
X    case REJECT:
X#ifdef DEBUG
Xprintf("In parse - REJECT, index = %d\n",indx);
X#endif
X      build_reject(indx);
X      return(1);
X      break;
X    case SORT:
X#ifdef DEBUG
Xprintf("In parse - SORT, index = %d\n",indx);
X#endif
X      build_sort(indx);
X      return(1);
X      break;
X    case GET_HEADER:
X#ifdef DEBUG
Xprintf("In parse - GET_HEADER, index = %d\n",indx);
X#endif
X      status = sys$dclast(&get_header,indx,0);
X      if (!(status & 1)) sys$exit(status);
X      return(0);
X      break;
X    case GET_DISPLAY:
X#ifdef DEBUG
Xprintf("In parse - GET_DISPLAY, index = %d\n",indx);
X#endif
X      status = sys$dclast(&get_display,indx,0);
X      if (!(status & 1)) sys$exit(status);
X      /* get_display handles queuing the completion byte */
X      /* it also handles queueing the next read */
X      return(0);
X      break;
X    case CLEANUP:
X#ifdef DEBUG
Xprintf("In parse - CLEANUP, index = %d\n",indx);
X#endif
X      if (gbl_links[indx].chan == 0) {
X        status = sys$dclast(&cleanup,indx,0);
X        gbl_links[indx].flags.connected = 0;
X      } else {
X        printf("Told to clean up while channel still existed?\n");
X      };
X      return(0);
X      break;
X    default:
X#ifdef DEBUG
Xprintf("In parse - UNKNOWN, index = %d\n",indx);
X#endif
X      /* send back a reply */
X      status = sys$qiow(0,gbl_links[indx].chan,IO$_WRITEVBLK,
X`009`009`009&gbl_links[indx].iosb,0,0,
X`009`009`009"UNKNOWN COMMAND",strlen("UNKNOWN COMMAND"),0,0,0,0);
X      if (!(status & 1)) sys$exit(status); /* couldn't queue? sanity check */
X      /* assume it worked okay, if it didn't, well, who gives a rip? */
X      return(1);
X      break;
X  };
X};
X$EOD
X$ create/log PCBDEF.H
X$DECK
X#define PCB$M_RES`0091
X#define PCB$M_DELPEN`0092
X#define PCB$M_FORCPEN`0094
X#define PCB$M_INQUAN`0098
X#define PCB$M_PSWAPM`00916
X#define PCB$M_RESPEN`00932
X#define PCB$M_SSFEXC`00964
X#define PCB$M_SSFEXCE`009128
X#define PCB$M_SSFEXCS`009256
X#define PCB$M_SSFEXCU`009512
X#define PCB$M_SSRWAIT`0091024
X#define PCB$M_SUSPEN`0092048
X#define PCB$M_WAKEPEN`0094096
X#define PCB$M_WALL`0098192
X#define PCB$M_BATCH`00916384
X#define PCB$M_NOACNT`00932768
X#define PCB$M_SWPVBN`00965536
X#define PCB$M_ASTPEN`009131072
X#define PCB$M_PHDRES`009262144
X#define PCB$M_HIBER`009524288
X#define PCB$M_LOGIN`0091048576
X#define PCB$M_NETWRK`0092097152
X#define PCB$M_PWRAST`0094194304
X#define PCB$M_NODELET`0098388608
X#define PCB$M_DISAWS`00916777216
X#define PCB$M_INTER`00933554432
X#define PCB$M_RECOVER`00967108864
X#define PCB$M_SECAUDIT`009134217728
X#define PCB$M_EPID_WILD`009-2147483648
X#define PCB$K_LENGTH`009288
X#define PCB$C_LENGTH`009288
X#define PCB$S_PCBDEF`009288
X#define PCB$L_SQFL`0090
X#define PCB$L_SQBL`0094
X#define PCB$W_SIZE`0098
X#define PCB$B_TYPE`00910
X#define PCB$B_PRI`00911
X#define PCB$B_ASTACT`00912
X#define PCB$B_ASTEN`00913
X#define PCB$W_MTXCNT`00914
X#define PCB$L_ASTQFL`00916
X#define PCB$L_ASTQBL`00920
X#define PCB$L_PHYPCB`00924
X#define PCB$L_OWNER`00928
X#define PCB$L_WSSWP`00932
X#define PCB$L_STS`00936
X#define PCB$V_RES`0090
X#define PCB$V_DELPEN`0091
X#define PCB$V_FORCPEN`0092
X#define PCB$V_INQUAN`0093
X#define PCB$V_PSWAPM`0094
X#define PCB$V_RESPEN`0095
X#define PCB$V_SSFEXC`0096
X#define PCB$V_SSFEXCE`0097
X#define PCB$V_SSFEXCS`0098
X#define PCB$V_SSFEXCU`0099
X#define PCB$V_SSRWAIT`00910
X#define PCB$V_SUSPEN`00911
X#define PCB$V_WAKEPEN`00912
X#define PCB$V_WALL`00913
X#define PCB$V_BATCH`00914
X#define PCB$V_NOACNT`00915
X#define PCB$V_SWPVBN`00916
X#define PCB$V_ASTPEN`00917
X#define PCB$V_PHDRES`00918
X#define PCB$V_HIBER`00919
X#define PCB$V_LOGIN`00920
X#define PCB$V_NETWRK`00921
X#define PCB$V_PWRAST`00922
X#define PCB$V_NODELET`00923
X#define PCB$V_DISAWS`00924
X#define PCB$V_INTER`00925
X#define PCB$V_RECOVER`00926
X#define PCB$V_SECAUDIT`00927
X#define PCB$L_WTIME`00940
X#define PCB$B_PRISAV`00940
X#define PCB$B_PRIBSAV`00941
X#define PCB$B_DPC`00942
X#define PCB$B_AUTHPRI`00943
X#define PCB$W_STATE`00944
X#define PCB$B_WEFC`00946
X#define PCB$B_PRIB`00947
X#define PCB$W_APTCNT`00948
X#define PCB$W_TMBU`00950
X#define PCB$W_GPGCNT`00952
X#define PCB$W_PPGCNT`00954
X#define PCB$W_ASTCNT`00956
X#define PCB$W_BIOCNT`00958
X#define PCB$W_BIOLM`00960
X#define PCB$W_DIOCNT`00962
X#define PCB$W_DIOLM`00964
X#define PCB$W_PRCCNT`00966
X#define PCB$S_TERMINAL`0098
X#define PCB$T_TERMINAL`00968
X#define PCB$L_PQB`00976
X#define PCB$L_EFWM`00976
X#define PCB$L_EFCS`00980
X#define PCB$L_EFCU`00984
X#define PCB$W_PGFLCHAR`00988
X#define PCB$B_PGFLINDEX`00990
X#define PCB$L_SWAPSIZE`00992
X#define PCB$L_EFC2P`00988
X#define PCB$L_EFC3P`00992
X#define PCB$L_PID`00996
X#define PCB$L_EPID`009100
X#define PCB$S_EPID_PROC`00921
X#define PCB$V_EPID_PROC`0090
X#define PCB$S_EPID_NODE_IDX`0098
X#define PCB$V_EPID_NODE_IDX`00921
X#define PCB$S_EPID_NODE_SEQ`0092
X#define PCB$V_EPID_NODE_SEQ`00929
X#define PCB$V_EPID_WILD`00931
X#define PCB$L_EOWNER`009104
X#define PCB$L_PHD`009108
X#define PCB$S_LNAME`00916
X#define PCB$T_LNAME`009112
X#define PCB$L_JIB`009128
X#define PCB$S_PRIV`0098
X#define PCB$Q_PRIV`009132
X#define PCB$L_ARB`009140
X#define PCB$L_UIC`009188
X#define PCB$W_MEM`009188
X#define PCB$W_GRP`009190
X#define PCB$L_ACLFL`009252
X#define PCB$L_ACLBL`009256
X#define PCB$L_LOCKQFL`009260
X#define PCB$L_LOCKQBL`009264
X#define PCB$L_DLCKPRI`009268
X#define PCB$L_IPAST`009272
X#define PCB$L_DEFPROT`009276
X#define PCB$L_WAITIME`009280
X#define PCB$L_PMB`009284
X$EOD
X$ create/log PSEUDO.C
X$DECK
X#include iodef
X#include descrip
X#include dvidef
X#include string
X
X#include "globals.h" /* for itmlst */
X
X#define TCP$INFO IO$_MODIFY
X#define GETHST IO$_SKIPFILE
X
Xstruct tcp_info {
X  unsigned char ForeignHostSize;
X  unsigned char LocalHostSize;
X  char ForeignHost[128];
X  long int ForeignPort;
X  short int unused;
X  char LocalHost[128];
X  long int LocalPort;
X  unsigned long int LocalAddress;
X  unsigned long int ForeignAddress;
X};
X
Xstruct gethst_info {
X  unsigned long int NameLen;
X  char Name[128];
X};
X
X
Xconvert_pseudo_terminal(terminal,where)
X  char *terminal,*where;
X{
X  char device[10]; /* that oughta hold the device name */
X  struct dsc$descriptor dev = {0,0,0,device};
X  static struct DevInfo {
X    long int pid;
X    short int len;
X    char name[64];
X  } devinfo[20];
X  static int devinfosize = sizeof(struct DevInfo);
X  static int class = -1, devinfocnt = 20;
X  int pid, status, i, indx, chan, notfound;
X  struct tcp_info info;
X  struct gethst_info host;
X  short int iosb[4];
X  struct itmlst dvilst[] = {4,DVI$_PID,&pid,0,0,0,0,0};
X
X  where[0] = '\0';
X
X  if ((strncmp(terminal,"TPA",3) != 0) && (strncmp(terminal,"TZA",3) != 0))
X    return(0);
X
X  strcpy(device,terminal);
X  device[0] = 'P';
X  device[1] = 'Y';
X  dev.dsc$w_length = strlen(device);
X
X  /* getdvi to find out who owns PYAnnn */
X  status = sys$getdviw(0,0,&dev,dvilst,iosb,0,0,0);
X  if (!(status & 1)) return(status);
X  if (!(iosb[0] & 1)) return(iosb[0]);
X
X  /* find all devices owned by this PID */
X  status = devices(&class, &pid, &devinfocnt, &devinfosize, devinfo);
X  if (status & 1) {
X    i = 0;
X    notfound = -1;
X    while (notfound && devinfo[i].len) {
X      if (devinfo[i].name[0] == '_' &&
X          devinfo[i].name[1] == 'I' &&
X          devinfo[i].name[2] == 'P')
X      {
X        dev.dsc$w_length = devinfo[i].len;
X        dev.dsc$a_pointer = devinfo[i].name;
X        notfound = 0;
X      }
X      else
X        ++i;
X    };
X    if (notfound) return(0);
X
X    status = sys$assign(&dev, &chan, 0, 0);
X    if (!(status & 1)) return(status);
X
X    status = sys$qiow(0,chan,TCP$INFO,iosb,0,0,&info,sizeof(info),0,0,0,0);
X    sys$dassgn(chan);
X    if (!(status & 1)) return(status);
X    if (!(iosb[0] & 1)) return(iosb[0]);
X
X    sprintf(where,"%.*s",info.ForeignHostSize, info.ForeignHost);
X    return(1);
X  };
X
X    /* viola .. */
X  /* else */
X    /* perhaps display owner username, imagname, or better - terminal ? */
X
X
X  return(0);
X}
X$EOD
X$ create/log READPORT.C
X$DECK
X#include descrip
X#define IO$_TTY_PORT 41
X#define IO$M_LT_READPORT 256
X
Xreadport(terminal,server,port)
X  char *terminal, *server, *port;
X{
X  short int chan;
X  short int iosb[4];
X  char portinfo[1+16+1+16];
X  struct dsc$descriptor term =
X    {strlen(terminal),DSC$K_DTYPE_T,DSC$K_CLASS_S,terminal} ;
X  long int status;
X  short int i,j;
X
X  status = sys$assign(&term ,&chan ,0 ,0);
X  if ((status & 1) == 0)
X    return(status);
X
X  status = sys$qiow(0 ,chan ,IO$_TTY_PORT | IO$M_LT_READPORT ,iosb
X                    ,0 ,0 ,portinfo ,sizeof(portinfo) ,0 ,0 ,0 ,0);
X
X  /* portinfo[] = (count byte), "port name", (count byte), "server name" */
X  for (i=0; i<portinfo[0]; ++i)
X    port[i] = portinfo[i+1];
X  port[i] = '\0';
X
X  j = i + 1;
X  for (i = 0; i<portinfo[j]; ++i)
X    server[i] = portinfo[i+j+1];
X  server[i] = '\0';
X
X  sys$dassgn(chan);
X
X  if (!(status & 1))
X    status = iosb[0];
X  if (!(status & 1))
X  {
X    port[0] = '\0';
X    server[0] = '\0';
X    return(status);
X  }
X}
X$EOD
X$ create/log RTPAD.C
X$DECK
X#include descrip
X#include iodef
X
X#define NFB$C_FC_SHOW`0090x00000022
X#define NFB$M_NOUPD`0090x00000004 /* don't update the database`009`009*/
X#define NFB$C_DB_LLI`0090x00000008 /* logical link information database */
X#define NFB$C_OP_EQL`0090x00000000 /* match the key exactly             */
X#define NFB$C_LLI_PID`0090x08010015 /* the key is PID of process         */
X#define NFB$C_WILDCARD`0090x00000001 /* search the whole database         */
X#define NFB$C_LLI_PNN`0090x08020043 /* partner's node name               */
X#define NFB$C_ENDOFLIST`0090x00000000
X
XGet_RTPAD_Destination(pid,site)
X  int pid;
X  char *site;
X{
X  $DESCRIPTOR(Net,"Net:");
X
X  struct {
X    unsigned char nfb$b_fct;
X    unsigned char nfb$b_flags;
X    unsigned char nfb$b_database;
X    unsigned char nfb$b_oper;
X    long int nfb$l_srch_key;
X    long int nfb$l_srch2_key;
X    unsigned char nfb$b_oper2;
X    unsigned char nfb$b_mbz1;
X    short int nfb$w_cell_size;
X    long int nfb$l_fldid; /* first of the fields */
X    long int f2;
X  } nfb =
X    {
X      NFB$C_FC_SHOW, NFB$M_NOUPD, NFB$C_DB_LLI, NFB$C_OP_EQL,
X      NFB$C_LLI_PID, NFB$C_WILDCARD,
X      0, 0, 0,
X      NFB$C_LLI_PNN, NFB$C_ENDOFLIST
X    };
X
X  struct {
X    short int len;
X    char name[6];
X  } buf;
X
X  struct {
X    long int k1;
X    long int k2;
X  } key = {0,pid};
X
X  struct dsc$descriptor nfbdesc = {sizeof(nfb), 0, 0, &nfb};
X  struct dsc$descriptor keydesc = {sizeof(key), 0, 0, &key};
X  struct dsc$descriptor bufdesc = {sizeof(buf), 0, 0, &buf};
X
X  int status;
X  short int chan, iosb[4];
X
X  site[0] = '\0';
X
X  status = sys$assign (&Net, &chan, 0, 0);
X  if (!( status & 1))
X  {
X    lib$signal(status);
X    return(status);
X  }
X
X  buf.len = 0;
X  status = sys$qiow (0,chan,IO$_ACPCONTROL,iosb,0,0,
X`009`009`009&nfbdesc,&keydesc,0,&bufdesc,0,0);
X  sys$dassgn(chan);
X  if ( status & 1)
X    status = iosb[0];
X
X  if (!( status & 1))
X  {
X    lib$signal(status);
X    return(status);
X  }
X
X  strncpy(site,buf.name,buf.len);
X  site[buf.len] = '\0';
X  return(1);
X}
X$EOD
X$ create/log SERVER.C
X$DECK
X#include iodef
X#include descrip
X#include dvidef
X#include msgdef
X#include nfbdef
X#include ssdef
X#include "starlet.h"
X#include "server.h"
X
X#define NETNAME "_NET:"
X#define MBXNAME "STATUS-SERVER-MBX"
X
Xint io_complete();
Xint connection_handler();
Xint get_idle();
X
Xmain()
X{
X  long int i,status, pendinglink;
X
X  for (i = 0; i < MAXLINKS; ++i)
X    gbl_links[i].buffer = gbl_buffers[i];
X  allocate_jpi_space();
X
X  init_server();
X  /* okay, we just loop forever */
X  while(1) {
X    sleep(60);
X    sys$canwak(0,0); /* in case there are any pending WAKEs left... */
X    /* hey, we woke up, better be a good reason */
X    pendinglink = 0;
X    for (i = 0; i <= gbl_net.maxlinks; i++) {
X      if (gbl_links[i].flags.pending) {
X        pendinglink = -1;
X        gbl_links[i].flags.pending = 0;
X        if (parse(i)) {
X          status = sys$qio(0,gbl_links[i].chan,IO$_READVBLK,
X`009`009`009&gbl_links[i].iosb,
X`009`009`009&io_complete,i,
X`009`009`009gbl_links[i].buffer,BUFFERSIZE,0,0,0,0);
X        } /* end if (parse(i)) */
X      } /* end if (gbl_links[i].flags.pending) */
X    } /* end for () */
X    /* okay, if we woke up for no reason, let's collect idle times.. */
X    if (!pendinglink)
X    {
X      status = sys$dclast(&get_idle,0,0);
X    }
X  } /* end while (1) */
X}
X
Xinit_server()
X{
X  $DESCRIPTOR(mbxname,MBXNAME);
X  $DESCRIPTOR(netname,NETNAME);
X  $DESCRIPTOR(task,"STATUS");
X  struct {
X    unsigned char type;
X    int end;
X  } nfb_block = {NFB$C_DECLNAME,0};
X  struct dsc$descriptor nfb = {sizeof(nfb_block),0,0,&nfb_block};
X  long int status;
X
X  /* initialize mailbox, assign a channel to NET, and associate the two */
X  status = sys$crembx(0,&gbl_net.mbx,0,0,0,0,&mbxname);
X  if (!(status & 1)) return(status);
X  status = sys$assign(&netname,&gbl_net.chan,0,&mbxname);
X  if (!(status & 1)) return(status);
X
X  /* declare the network task */
X  status = sys$qiow(0,gbl_net.chan,IO$_ACPCONTROL,&gbl_net.iosb,
X`009`0090,0,&nfb,&task,0,0,0,0);
X  if (!(status & 1)) return(status);
X  if (!(gbl_net.iosb.status & 1)) return(gbl_net.iosb.status);
X
X  /* set the ball rolling.. */
X  status = sys$qio(0,gbl_net.mbx,IO$_READVBLK,&gbl_net.iosb,
X`009`009&connection_handler,0,
X`009`009&gbl_net.msg_union.buffer,sizeof(gbl_net.msg_union.buffer),
X`009`0090,0,0,0);
X  return(status);
X}
X
Xconnection_handler()
X{
X  $DESCRIPTOR(netname,NETNAME);
X  $DESCRIPTOR(mbxname,MBXNAME);
X  struct dsc$descriptor ncb = {0,0,0,0};
X  long int i,found,status;
X
X  if (!(gbl_net.iosb.status & 1)) { /* something fatal has occured? */
X    sys$exit(gbl_net.iosb.status);
X  };
X
X  switch (gbl_net.msg_union.msg_struct.msgtype) {
X    case MSG$_CONFIRM:
X    case MSG$_INTMSG:
X    case MSG$_REJECT:
X#ifdef DEBUG
Xprintf("In connection handler - CONFIRM/INTMSG/REJECT\n");
X#endif
X      /* I don't know if I really need to handle these in any way */
X      /* I assume I can safely ignore them and continue happily along */
X      break;
X
X    case MSG$_ABORT:
X    case MSG$_DISCON:
X    case MSG$_EXIT:
X    case MSG$_PATHLOST:
X    case MSG$_PROTOCOL:
X    case MSG$_THIRDPARTY:
X    case MSG$_TIMEOUT:
X      /* These all pretty much mean the same thing, disconnect this link */
X
X      /* find the link that needs to get shut down */
X      for (i = 0;
X           (i <= gbl_net.maxlinks)
X`009   && (gbl_links[i].unit != gbl_net.msg_union.msg_struct.unit);
X`009   ++i);
X      status = sys$dassgn(gbl_links[i].chan);
X      if (!(status & 1)) sys$exit(status); /* fatal problem */
X
X#ifdef DEBUG
Xprintf("In connection handler ABORT-TIMEOUT, link %d\n",i);
X#endif
X      /* be sure to clear these suckers out.. */
X      --gbl_net.activelinks;
X      gbl_links[i].chan = 0;
X      gbl_links[i].unit = 0;
X
X      /* check to see if we've lowered the highest current link */
X      for (;gbl_links[gbl_net.maxlinks].flags.connected==0;
X           --gbl_net.maxlinks);
X      break;
X
X    case MSG$_NETSHUT:
X      /* the network is shutting down. I don't think I really have to do
X         any cleanup here, so I may as well just exit the program entirely */
X      sys$exit(1);
X      break;
X
X    case MSG$_CONNECT:
X#ifdef DEBUG
Xprintf("In connection handler CONNECT\n");
X#endif
X      ncb.dsc$w_length = gbl_net.msg_union.buffer[5 +
X`009`009`009`009gbl_net.msg_union.buffer[4]];
X      ncb.dsc$a_pointer = &gbl_net.msg_union.buffer[6 +
X`009`009`009   `009gbl_net.msg_union.buffer[4]];
X      if (gbl_net.activelinks >= MAXLINKS) {
X        /* we don't have any more room for any links, so reject it */
X        status = sys$qiow(0,gbl_net.chan,IO$_ACCESS | IO$M_ABORT,
X`009`009`009&gbl_net.iosb,0,0,0,&ncb,0,0,0,0);
X        if (!(status & 1)) sys$exit(status); /* fatal problem */
X        if (!(gbl_net.iosb.status & 1)) sys$exit(gbl_net.iosb.status);
X        break; /* just fall out of this mess */
X      }
X
X      /* find empty slot */
X      found = 0;
X      i = 0;
X      while ((found == 0) && (i < MAXLINKS)){
X        for (; (i < MAXLINKS) && gbl_links[i].chan; ++i);
X        if (gbl_links[i].flags.connected)
X          ++i;
X        else
X          found = -1;
X      };
X      if (i == MAXLINKS) { /* no links really available yet */
X        /* we don't have any more room for any links, so reject it */
X        status = sys$qiow(0,gbl_net.chan,IO$_ACCESS | IO$M_ABORT,
X`009`009`009&gbl_net.iosb,0,0,0,&ncb,0,0,0,0);
X        if (!(status & 1)) sys$exit(status); /* fatal problem */
X        if (!(gbl_net.iosb.status & 1)) sys$exit(gbl_net.iosb.status);
X        break; /* just fall out of this mess */
X      };
X
X      /* okay, an empty slot was found */
X      status = sys$assign(&netname,&gbl_links[i].chan,0,&mbxname);
X      if (!(status & 1)) sys$exit(status); /* fatal problem ? */
X
X      gbl_links[i].unit = get_unit(gbl_links[i].chan);
X      if (gbl_links[i].unit == 0) { /* huh? fatal flaw */
X        printf("Unable to get unit for channel %d\n",gbl_links[i].chan);
X        sys$exit(4);
X      };
X
X#ifdef DEBUG
Xprintf("-making connection, link %d\n",i);
X#endif
X      /* make the connection */
X      status = sys$qiow(0,gbl_links[i].chan,IO$_ACCESS,&gbl_net.iosb,
X`009`009`0090,0,0,&ncb,0,0,0,0);
X      if (!(status & 1)) sys$exit(status); /* fatal problem ? */
X      if (!(gbl_net.iosb.status & 1)) sys$exit(gbl_net.iosb.status);
X
X      /* save off the info */
X      gbl_links[i].flags.connected = 1;
X      gbl_links[i].flags.pending = 0;
X      if (i > gbl_net.maxlinks)
X        gbl_net.maxlinks = i;
X      ++gbl_net.activelinks;
X
X      /* get the ball rolling for this link */
X      status = sys$qio(0,gbl_links[i].chan,IO$_READVBLK,&gbl_links[i].iosb,
X`009`009`009&io_complete,i,
X`009`009`009gbl_links[i].buffer,BUFFERSIZE,0,0,0,0);
X      if (!(status & 1)) sys$exit(status); /* fatal problem ? */
X      break;
X
X    default:
X      printf("Unknown connection request %d\n",
X`009gbl_net.msg_union.msg_struct.msgtype);
X      sys$exit(4); /* fatal flaw I guess? */
X      break;
X  } /* end of switch */
X
X  status = sys$qio(0,gbl_net.mbx,IO$_READVBLK,&gbl_net.iosb,
X`009`009&connection_handler,0,
X`009`009&gbl_net.msg_union.buffer,sizeof(gbl_net.msg_union.buffer),
X`009`0090,0,0,0);
X  if (!(status & 1)) sys$exit(status);
X}
X
Xio_complete(indx)
X  int indx;
X{
X  if (!(gbl_links[indx].iosb.status & 1)) { /* problem completing read? */
X    *gbl_links[indx].buffer = CLEANUP;   /* let someone know to clean up */
X  };
X  gbl_links[indx].flags.pending = 1;
X  gbl_links[indx].iosb.status = 0;
X  sys$wake(0,0);
X};
X
Xget_unit(chan)
X  unsigned short int chan;
X{
X  unsigned short int unit;
X  struct itmlst unit_list[] = {{4,DVI$_UNIT,&unit,0},{0,0,0,0}};
X  long int status;
X
X  status = sys$getdviw(0,chan,0,unit_list,0,0,0,0);
X  if (!(status & 1)) unit = 0;
X
X  return (unit);
X};
X
Xallocate_jpi_space()
X{
X  struct itmlst syilst[] = {{4,SYI$_MAXPROCESSCNT,&system_jpi.maxprocs,0}
X`009`009`009   ,{0,0,0,0}};
X  int status,numbytes;
X
X  status = sys$getsyiw(0,0,0,syilst,0,0,0);
X  if (!(status & 1)) sys$exit(status);
X
X  numbytes = (JPIMAXBUFFLEN + (4 * JPIMAXITEMCNT)) * system_jpi.maxprocs;
X
X  if ((system_jpi.data = malloc(numbytes)) == 0) {
X    printf("Unable to allocate memory for %d processes\n",
X`009system_jpi.maxprocs);
X    sys$exit(4); /* die, should use an out of memory error */
X  };
X
X  status = add_jpi_item(JPI$_PROC_INDEX);
X  status = add_jpi_item(JPI$_PID);
X  status = add_jpi_item(JPI$_STS); /* used to see if PHDRES, or SUSPENDED */
X  status = add_jpi_item(JPI$_MASTER_PID); /* used to zap NULL & SWAPPER */
X  status = add_jpi_item(JPI$_CPUTIM); /* used to get idle times */
X}
X$EOD
X$ create/log SERVER.COM
X$DECK
X$ run/detached/process="Status Server" -
X`009/output=mass$disk:[decus.status.decnet]server.log -
X`009/priv=(tmpmbx,netmbx,sysnam,share,world,cmkrnl,readall,exquota) -
X`009server.exe
X$EOD
X$ create/log SERVER.H
X$DECK
X#include jpidef
X#include syidef
X
X#include "globals.h"
X#include "global_values.h"
X#include "jpicodes.h"
X#include "keywords.h"
X
X#ifndef GLOBAL
X#define GLOBAL globalref
X#endif
X
X#define MAXITEMS 50
X#define MAXSYI 50
X#define MAXJPI 50
X#define MAXLINKS 100
X#define BUFFERSIZE 512
X
Xstruct LinkedList {
X  short int length;
X  char *string;
X  struct LinkedList *next;
X};
X
Xstruct FmtItems {
X  int address;     /* either a real address or an offset, acc. to flag */
X  short int keyindx;
X  short int size;  /* size of data */
X  variant_union {
X    struct LinkedList *list;
X    variant_struct {
X      short int width; /* width of string (for format) */
X      short int just;  /* justification of string (for format) */
X    } dummy0;
X  } dummy1;
X  short int start; /* start of string (for format) */
X  struct {
X    unsigned type : 2;
X#define FLAGTYPEABS 0
X#define FLAGTYPEJPI 1
X#define FLAGTYPESYI 2
X  } flags;
X  short int jpicod_index; /* if type is jpi .. */
X};
X
Xstruct FmtItemsList {
X  int maxitems;
X  struct FmtItems item[MAXITEMS];
X};
X
Xstruct JPIdata {
X  unsigned int maxprocs;   /* max number of processes */
X  unsigned int previndex;  /* previous process index */
X  unsigned int currindex;  /* current process index */
X  unsigned int wildpid;    /* pid for use in next getjpi call */
X  unsigned char *data;`009  /* pointer to data */
X  unsigned int pcb_itemcnt;
X  unsigned int phd_itemcnt;
X  unsigned int ctl_itemcnt;
X  struct itmlst pcb_items[JPIMAXPCBCNT];
X  struct itmlst phd_items[JPIMAXPHDCNT];
X  struct itmlst ctl_items[JPIMAXCTLCNT];
X  unsigned short int refcnt[JPIMAXITEMCNT];
X  unsigned long int tried[JPIMAXITEMCNT];
X};
X
Xstruct Link {
X  unsigned short int chan;
X  unsigned short int unit;
X  struct iosbdef iosb;
X  unsigned char *buffer;
X  int pid;
X  struct {
X    unsigned pending : 1;
X    unsigned connected : 1;
X  } flags;
X};
X
Xstruct Net {
X  unsigned short int mbx;
X  unsigned short int chan;
X  unsigned short maxlinks;
X  unsigned short activelinks;
X  struct iosbdef iosb;
X  union {
X    unsigned char buffer[255];
X    struct {
X      unsigned short int msgtype;
X      unsigned short int unit;
X      unsigned char message[255-4];
X    } msg_struct;
X  } msg_union;
X};
X
XGLOBAL struct Net gbl_net;
XGLOBAL struct JPIdata system_jpi;
X
XGLOBAL struct Link gbl_links[MAXLINKS];
XGLOBAL char gbl_buffers[MAXLINKS][BUFFERSIZE];
XGLOBAL struct FmtItemsList gbl_headers[MAXLINKS];
XGLOBAL struct FmtItemsList gbl_displays[MAXLINKS];
XGLOBAL struct FmtItemsList gbl_select[MAXLINKS];
XGLOBAL struct FmtItemsList gbl_reject[MAXLINKS];
XGLOBAL struct FmtItemsList gbl_sort[MAXLINKS];
X
XGLOBAL struct itmlst syi_items[MAXLINKS][MAXSYI];
X$EOD
X$ create/log SHOWSYSTEM.COM
X$DECK
X$! To use, define a symbol as follows:
X$!   SS == "@disk:[dir]SHOWSYSTEM X
X$! The trailing "X" makes it easier to then say things like
X$!   SS/REJECT=STATE="hib"/INTERVAL=4
X$!
X$! You may want to remove these comments if you hate the speed of DCL
X$!
V$ STATUS/HEADER = "VAX/%node_swtype %node_swvers  on node %nodename %time   Up
t
Xime %13uptime" -
V    `009/HEADER = "  Pid    Process Name    State  Pri      I/O       CPU
X Page flts Ph.Mem" -
V`009/DISPLAY= "%pid %15prcnam %5state   %-2pri %-8io%cputim %-9pageflts %-6pag
e
Xs" -
X`009'p2' 'p3' 'p4' 'p5' 'p6' 'p7' 'p8'
X$EOD
X$ create/log SHOWUSERS.COM
X$DECK
X$! To use, define a symbol as follows:
X$!   SU == "@disk:[dir]SHOWUSERS X
X$! The trailing "X" makes it easier to then say things like
X$!   SU/INTERVAL=4
X$!
X$! You may want to remove these comments if you hate the speed of DCL
X$!
X$ STATUS/SELECT=TERMINAL=%* -
X`009/HEADER = "          VAX/VMS Interactive Users" -
X`009/HEADER = "           %time" -
X`009/HEADER = "    Total number of interactive users = %ijobcnt" -
X`009/HEADER = " " -
X`009/HEADER = " Username     Process Name      PID     Terminal" -
X`009/DISPLAY= " %12username %15prcnam %pid  %14terminal %where" -
X`009'p2' 'p3' 'p4' 'p5' 'p6' 'p7' 'p8'
X$EOD
X$ create/log SORT_SYSUAF.SPEC
X$DECK
X/field=(name=owner,position=1,size=21)
X/field=(name=username,position=22,size=12)
X/key=username
X/data=username
X/data=owner
X$EOD
X$ create/log STARLET.H
X$DECK
X/* Created by SDL V3.0-2     */
X/* Source: 24-APR-1988 09:21:15 SPUD$DISK:[JOE.STATUS.SERVER]STARLET.SDI;1 */
X
X/*** MODULE STARLET ***/
X#ifndef STARLET
Xlong int sys$add_holder(
X    const unsigned long int id,
X    const unsigned int  *holder [2],
X    const unsigned long int attrib
X    ) ;
Xlong int sys$add_ident(
X    const struct dsc$descriptor *name,
X    const unsigned long int id,
X    const unsigned long int attrib,
X    unsigned long int  *resid
X    ) ;
Xlong int sys$adjstk(
X    unsigned long int acmode,
X    short int adjust,
X    unsigned long int  *newadr
X    ) ;
Xlong int sys$adjwsl(
X    long int pagcnt,
X    unsigned long int  *wsetlm
X    ) ;
Xlong int sys$alloc(
X    const struct dsc$descriptor *devnam,
X    unsigned short int  *phylen,
X    struct dsc$descriptor *phybuf,
X    unsigned long int acmode,
X    unsigned long int flags
X    ) ;
Xlong int sys$ascefc(
X    unsigned long int efn,
X    const struct dsc$descriptor *name,
X    char prot,
X    char perm
X    ) ;
Xlong int sys$asctim(
X    unsigned short int  *timlen,
X    struct dsc$descriptor *timbuf,
X    const unsigned int  *timadr [2],
X    char cvtflg
X    ) ;
Xlong int sys$asctoid(
X    const struct dsc$descriptor *name,
X    unsigned long int  *id,
-+-+-+-+-+ End of part 5 +-+-+-+-+-
