From:	CSBVAX::MRGATE!KARNEY%PPC.MFENET@NMFECC.ARPA@SMTP  8-AUG-1988 14:58
To:	ARISIA::EVERHART
Subj:	BOSS 2.5 4/4


Received: from ppc.mfenet by ccc.mfenet with Tell via MfeNet ;
	Mon, 8 Aug 88 11:20:57 PDT
Date:	  Mon, 8 Aug 88 11:20:57 PDT
From:     KARNEY%PPC.MFENET@NMFECC.ARPA
Message-Id: <880808112057.20200218@NMFECC.ARPA>
Subject:   BOSS 2.5 4/4
To:       Everhart%Arisia.decnet@ge-crd.arpa
Comment: From KARNEY@PPC.MFENET on  8-AUG-1988 13:27:40.39 EDT

+-+-+-+ Beginning of part 4 +-+-+-+
X`009  break;
X`009case P1_FN_OSELW:`009/* shouldn't ever occur */
X`009  break;
X`009case P1_FN_META:
X`009  uw_meta = 1;
X`009  break;
X`009case P1_FN_CTLCH:
X`009  dismiss = 0;
X`009  switch (arg) {
X`009  case P1_CC_IAC:
X`009    input_char = P1_IAC;
X`009    break;
X`009  case P1_CC_XON:
X`009    input_char = XON;
X`009    break;
X`009  case P1_CC_XOFF:
X`009    input_char = XOFF;
X`009    break;
X`009  default:
X`009    dismiss = 1;
X`009    break;
X`009  }`009 `032
X`009  break;
X`009case P1_FN_MAINT:
X`009  switch (arg) {
X`009  case P1_MF_ENTRY:`009/* Shouldn't get this */
X`009    break;
X`009  case P1_MF_ASKPCL:
X`009    uw_fun(P1_FN_MAINT | P1_MF_CANPCL, 040, 1);
X`009    break;
X`009  case P1_MF_CANPCL:`009/* Shouldn't get this */
X`009    uw_state = UW_CANPCL;
X`009    break;
X`009  case P1_MF_SETPCL:
X`009    uw_state = UW_SETPCL;
X`009    break;
X`009  case P1_MF_EXIT:
X`009    exit(SS$_NORMAL);
X`009    break;
X`009  }
X`009  break;
X`009case UW_CANPCL:
X`009  if (input_char == 040) uw_fun(P1_MF_SETPCL, 040, 1);
X`009  else uw_fun(P1_MF_CANPCL, 040, 1);
X`009  uw_state = UW_NORMAL;
X`009  break;
X`009case UW_SETPCL:
X`009  if (input_char != 040) {
X`009    sprintf(buf,"%s[Don't understand this protocol: %d]%s",
X`009`009    bos,input_char,ceoln);
X`009  }
X`009  uw_state = UW_NORMAL;
X`009  break;
X`009}
X      }
X    }
X    if (uw_meta && !dismiss) {
X      uw_meta = 0;
X      input_char = 0200 | input_char;
X    }
X    mac_command = 0;
X  }
X  if (!dismiss) {
X    if (input_char == 0177) input_char = delete_char;
X    else if (input_char == delete_char) input_char = 0177;
X    if (input_state == NORMAL && cur < 0) input_state = PENDING;
X    switch (input_state) {
X    case NORMAL:
X      if (input_char == ctlchar) input_state = PENDING;
X      else {
X`009check(SYS$QIOW(0,py_chn[cur],IO$_WRITEVBLK,&tiosb,0,0,
X`009`009       &input_char,1,0,0,0,0));
X`009if (tiosb.stats != SS$_DATAOVERUN) check(tiosb.stats);
X      }
X      break;
X    case PENDING:
X      if (input_char == ctlchar) {
X`009if (cur >=0) {
X`009  check(SYS$QIOW(0,py_chn[cur],IO$_WRITEVBLK,&tiosb,0,0,
X`009`009`009 &input_char,1,0,0,0,0));
X`009  if (tiosb.stats != SS$_DATAOVERUN) check(tiosb.stats);
X`009  input_state = NORMAL;
X`009}
X`009break;
X      }
X      switch (input_char) {
X      case '\016':
X`009input_state = CREATE;
X`009break;
X      case '\024':
X`009input_state = TOP;
X`009break;
X      case '\032':
X`009if (count_processes()) {
X`009  diag();
X`009  sprintf(buf,"[Do you really want to quit (y or n)?]%s\007",ceol);
X`009  term_msg(buf);
X`009  input_state = END;
X`009}
X`009else exit(SS$_NORMAL);
X`009break;
X      case '\013':
X`009if (cur < 0) term_msg("\007");
X`009else {
X`009  sprintf(buf,
X`009`009  "%s[Do you really want to kill process %c (y or n)?]%s\007",
X`009`009  bos, name[cur], ceol);
X`009  term_msg(buf);
X`009  kill_proc = cur;
X`009  input_state = KILL;
X`009}
X`009break;
X      case '\010':
X`009print_help();
X`009input_state = NORMAL;
X`009break;
X      case '?':
X`009diag();
X`009input_state = NORMAL;
X`009break;
X      case '\002':
X      case '\017':
X      case '\020':
X      case '\027':
X`009if (input_char == '\002') desc = "Buffer";
X`009else if (input_char == '\017') desc = "Discard";
X`009else if (input_char == '\020') desc = "Print";
X`009else if (input_char == '\027') desc = "Stop";
X`009nmode = input_char + 0140;
X`009if (cur < 0) {
X`009  defmode = nmode;
X`009  sprintf(buf,"%s[%s output by default]%s",bos,desc,ceoln);
X`009}
X`009else {
X`009  mode[cur] = nmode;
X`009  pmode[cur] = nmode;
X`009  sprintf(buf,"%s[%s output from process %c]%s",bos,desc,
X`009`009  name[cur],ceoln);
X`009}
X`009term_msg(buf);
X`009input_state = NORMAL;
X`009break;
X      case '\177':
X`009input_state = NORMAL;
X`009break;
X      default:
X`009nname = toupper(input_char);
X`009if (nname >= first_name && nname <= last_name) {
X`009  mov_to(nname,uw ? 0 : input_char < 'a',"",
X`009`009 switch_create ? defproc : SWITCH);
X`009} else term_msg("\007");
X`009input_state = NORMAL;
X`009break;
X      }
X      break;
X    case CREATE:
X    case TOP:
X      switch (input_char) {
X      case '\016':
X`009input_state = CREATE;
X`009break;
X      case '\024':
X`009input_state = TOP;
X`009break;
X      case '\010':
X`009print_help();
X`009input_state = NORMAL;
X`009break;
X      case '?':
X`009diag();
X`009input_state = NORMAL;
X`009break;
X      case '\177':
X`009input_state = NORMAL;
X`009break;
X      default:
X`009nname = toupper(input_char);
X`009if (nname >= first_name && nname <= last_name) {
X`009  mov_to(nname,uw ? 0 : input_char < 'a',"",input_state);
X`009} else term_msg("\007");
X`009input_state = NORMAL;
X`009break;
X      }
X      break;
X    case END:
X      if (toupper(input_char) == 'Y') {
X`009term_msg(" Yes\r");
X`009exit(SS$_NORMAL);
X      } else {
X`009term_msg(" No\r\n");
X      }
X      input_state = NORMAL;
X      break;
X    case KILL:
X      if (toupper(input_char) == 'Y') {
X`009if (kill_proc >= 0 && name[kill_proc] > 0) {
X`009  st = SYS$DELPRC(&pid[kill_proc],0);
X`009  if (bad(st))
X`009    sprintf(buf,"%s[Couldn't kill process %c]%s",
X`009`009    bos,name[kill_proc],ceoln);
X`009  else
X`009    sprintf(buf,"%s[Killed process %c]%s",bos,name[kill_proc],ceoln);
X`009}
X`009else sprintf(buf,"%s[Process already killed]%s",bos,ceoln);
X`009term_msg(buf);
X`009break;
X      } else {
X`009term_msg(" No\r\n");
X      }
X      input_state = NORMAL;
X      kill_proc = -1;
X      break;
X    }
X  }
X                               /* re-post read AST on real term */
X  check(SYS$QIO(0,tt_chn,IO$_READVBLK,&tiosb,&tt_srv,0,
X                &input_char,1,0,0,0,0));
X}
X
Xuw_fun(code,arg,count)
Xchar code,arg;
Xint count;
X{
X  term_buf[0] = P1_IAC;
X  term_buf[1] = P1_DIR_HTOM | code;
X  if (count > 0) term_buf[2] = arg;
X  check(SYS$QIOW(0,tt_chn,IO$_WRITEVBLK,&tiosb,0,0,term_buf,2+count,0,0,0,0));
X}
X
Xget_tt_info()
X{
X  $DESCRIPTOR(d_tt, "SYS$COMMAND");
X                                /* Get a channel & mailbox of terminal */
X  check(LIB$ASN_WTH_MBX(&d_tt,&ttmbsiz,&ttmaxsiz,&tt_chn,&tt_mb_chn));
X                                /* Get the terminal characteristics. */
X  check(SYS$QIOW(0,tt_chn,IO$_SENSEMODE,0,0,0,&tt_chr,ttchrlen,0,0,0,0));
X  tt_sav_chr = tt_chr;
X  tt_chr.ttchr |= TT$M_NOECHO;  /* term will be Noecho */
X  tt_chr.ttchr &= `126TT$M_HOSTSYNC; /* no host sync */
X  if (flow_control) tt_chr.ttchr |= TT$M_TTSYNC; /* do sync at BOSS level */
X  else tt_chr.ttchr &= `126TT$M_TTSYNC; /* do sync at subprocess level */
X  tt_chr.xchar |= TT2$M_PASTHRU; /* it will be PASTRHU */
X  if (brkthru) {
X    tt_chr.ttchr |= TT$M_MBXDSABL; /* no hangup messages */
X    tt_chr.ttchr |= TT$M_NOBRDCST; /* disable direct broadcast */
X    tt_chr.xchar |= TT2$M_BRDCSTMBX; /* send them to mailbox instead */
X  }
X  check(SYS$QIOW(0,tt_chn,IO$_SETMODE,0,0,0,&tt_chr,ttchrlen,0,0,0,0));
X}
X
Xfix_a_tp(n)                             /* Set up a Pseudo term */
Xint n;
X{
X  int dev_depend, tp_chn;
X  struct CHARBLK tw_chr;
X  struct IOSBBLK iosb;
X  struct DVIBLK  dvi_stuff = {4, DVI$_DEVDEPEND, &dev_depend, 0, 0};
X
X  $DESCRIPTOR(d_pynam,"PYA0:"); /* Template. */
X  $DESCRIPTOR(d_finaltp, &finaltp[n]);
X                                /* Assign a mailbox to PYA */
X  check(LIB$ASN_WTH_MBX(&d_pynam,&mbsiz,&maxsiz,&py_chn[n],&py_mb_chn[n]));
X/*
X * Use $GETDVI to get the device dependent characteristics, which
X * contains the associated terminal device's unit number.
X */
X  check(SYS$GETDVI(0,py_chn[n],0,&dvi_stuff,&iosb,0,0,0));
X  check(iosb.stats);
X  tw_chr= tt_sav_chr;
X  tw_chr.xchar|= TT2$M_HANGUP;
X  sprintf(&finaltp[n],"TWA%d:",dev_depend);
X  d_finaltp.dsc$w_length = strlen(&finaltp[n]);
X`009`009`009`009/* Get a channel on this TWA */
X  if (bad(SYS$ASSIGN(&d_finaltp,&tp_chn,0,0))) {
X    sprintf(&finaltp[n],"TPA%d:",dev_depend); /* TWA doesn't work; try TPA */
X    d_finaltp.dsc$w_length = strlen(&finaltp[n]);
X    check(SYS$ASSIGN(&d_finaltp,&tp_chn,0,0));
X  }
X  if (no_phy_io) check(SYS$SETPRV(1,&priv,0,0));
X`009`009`009`009/* Make it look like a terminal */
X  if (bad(SYS$QIOW(0,tp_chn,IO$_SETCHAR,0,0,0, /* This needs PHY_IO priv */
X                   &tw_chr,ttchrlen,0,0,0,0)))
X    check(SYS$QIOW(0,tp_chn,IO$_SETMODE,0,0,0,
X                   &tw_chr,ttchrlen,0,0,0,0));
X  if (no_phy_io) check(SYS$SETPRV(0,&priv,0,0));
X  check(SYS$DASSGN(tp_chn));    /* We don't need it. only the mailbox */
X                                /* in fact keeping it kills us. */
X}
X
Xbroadcast_handler()`009`009/* handle broadcasts to BOSS */
X{
X  int j, len;
X
X  $DESCRIPTOR(d_tt_mb,tt_mb);
X  $DESCRIPTOR(d_finaltp,finaltp[cur]);
X
X  check(tiosbmb.stats);`009`009/* Check status */
X  len = ((0377 & tt_mb[21]) << 8) + (0377 & tt_mb[20]); /* message length */
X  if (cur < 0) {
X    term_msg("\r\n");
X    to_term(&(tt_mb[22]),len,1);
X    term_msg("\r");
X  }
X  else {
X    d_tt_mb.dsc$w_length = len;
X    d_tt_mb.dsc$a_pointer = &(tt_mb[22]);
X    if (no_oper) check(SYS$SETPRV(1,&privs,0,0));
X    check(SYS$BRKTHRU(0,&d_tt_mb,&d_finaltp,
X`009`009      BRK$C_DEVICE,0,32,0,BRK$C_USER16,0,0,0));
X    if (no_oper) check(SYS$SETPRV(0,&privs,0,0));
X  }
X  check(SYS$QIO(0,tt_mb_chn,IO$_READVBLK,&tiosbmb,&broadcast_handler,0,
X                &tt_mb,ttmbsiz,0,0,0,0));
X}
X
Xpost_term_reads()                           /* Read AST on real term */
X{
X  if (brkthru)
X    check(SYS$QIO(0,tt_mb_chn,IO$_READVBLK,&tiosbmb,&broadcast_handler,0,
X`009`009  &tt_mb,ttmbsiz,0,0,0,0));
X  else
X    check(SYS$QIO(0,tt_mb_chn,IO$_READVBLK,&tiosbmb,0,0,
X`009`009  &tt_mb,ttmbsiz,0,0,0,0));
X  check(SYS$QIO(0,tt_chn,IO$_READVBLK,&tiosb,&tt_srv,0,
X                &input_char,1,0,0,0,0));
X}
X
Xpost_pty_reads(n)                          /* Read AST on Pseudo-term */
Xint n;
X{
X  char cr = '\r';
X
X  if (init) return(0);
X  py_post[n] = 1;
X  check(SYS$QIO(0,py_mb_chn[n],IO$_READVBLK,&miosb[n],&mb_srv,n,
X                &py_mb[n],mbsiz,0,0,0,0));
X  check(SYS$QIO(0,py_chn[n],IO$_READVBLK,&piosb[n],&py_srv,n,
X                &tpline[n],linesz,0,0,0,0));
X  if (proc_type[n] == TOP) {
X    check(SYS$QIOW(0,py_chn[n],IO$_WRITEVBLK,&tiosb,0,0,
X                   &cr,1,0,0,0,0));
X    if (tiosb.stats != SS$_DATAOVERUN) check(tiosb.stats);
X  }
X}
X
Xint
Xfire_up(n,nname,proc_mode)                /* Fire up subprocess n */
Xint n,proc_mode;
Xchar nname;
X{
X  int val;
X  name[n] = nname;
X  procno[nname - first_name] = n;
X  count[n] = 0;                 /* Initialize buffer count */
X  blocked[n] = 0;               /* It starts unblocked */
X  py_post[n] = 0;
X  mode[n] = defmode;
X  pmode[n] = defmode;
X  buflen[n] = 0;
X  proc_type[n] = proc_mode;
X  enable_hangup[n] = 0;
X  pid[n] = 0;
X  fix_a_tp(n);                  /* Set a pseudo terminal by TT info */
X  check(SYS$CANCEL(py_chn[n])); /* Don't need this Half of pseudo-ter */
X  val = (proc_type[n] == TOP) ? 1 :
X    low_lib_spawn(n,&finaltp[n],&pid[n],name[n]); /* Spawn a subprocess. */
X  if (!bad(val)) {
X    post_pty_reads(n); /* Set up AST */
X    if (uw && !mac_command) uw_fun(P1_FN_NEWW | ((n + 1) & P1_WINDOW), 0, 0);
X  }
X  else comp_srv(n);             /* Mark the process as non-existent */
X  return(val);
X}
X
Xinitialize()                    /* Initialize everything */
X{
X  int j,item;
X  $DESCRIPTOR(d_boss_id,"BOSS$ID");
X  $DESCRIPTOR(d_lnm_process,"LNM$PROCESS");
X
X  nalph = last_name - first_name + 1;
X  for (j = 0; j < nproc; j++) name[j] = '\0'; /* Initialize variables */
X  for (j = 0; j < nalph; j++) procno[j] = -1;
X`009`009`009`009/* Save old value of BOSS$ID */
X  j = SYS$TRNLNM(0,&d_lnm_process,&d_boss_id,&super_ac_mode,&trnlnm_item);
X  if (!bad(j) && trnlnm_string_len == 1) {
X    oboss_id = trnlnm_string[0];
X    j = LIB$DELETE_LOGICAL(&d_boss_id,0);
X  }
X
X  item = JPI$_PROCPRIV;`009`009/* Check whether have PHY_IO & OPER */
X  check(LIB$GETJPI(&item,0,0,&priv,0,0));
X  no_phy_io = !(priv[0] & PRV$M_PHY_IO);
X  no_oper = !(priv[0] & PRV$M_OPER);
X  item = JPI$_IMAGPRIV;`009`009/* Check whether we can do BRKTHRU */
X  check(LIB$GETJPI(&item,0,0,&priv,0,0));
X  brkthru = ((priv[0] & PRV$M_OPER) || !no_oper);
X  priv[0] = PRV$M_PHY_IO; priv[1] = 0;
X  privs[0] = PRV$M_OPER; privs[1] = 0;
X  if (no_phy_io) check(SYS$SETPRV(0,&priv,0,0));
X  if (no_oper) check(SYS$SETPRV(0,&privs,0,0));
X  get_tt_info();                /* Initialize terminal */
X  if (uw) uw_fun(P1_FN_MAINT | P1_MF_ENTRY,0,0);
X  start_up();`009`009`009/* Start up processes */
X  post_term_reads();
X}
X
X/* Next two routines taken from FILE program by Joe Meadows Jr. */
X
Xlong int cli_present(s)
X  char *s;
X{
X  static struct dsc$descriptor s_desc = {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};
X
X  s_desc.dsc$w_length = strlen(s);
X  s_desc.dsc$a_pointer = s;
X  return(cli$present(&s_desc));
X}
X
Xlong int cli_get_value(s1,s2)
X  char *s1,**s2;
X{
X  static struct dsc$descriptor s1_desc={0,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};
X  static struct dsc$descriptor s2_desc={0,DSC$K_DTYPE_T,DSC$K_CLASS_D,0};
X  static char null = '\0';
X  static struct dsc$descriptor null_desc={1,DSC$K_DTYPE_T,DSC$K_CLASS_S,&null};
X  long int status;
X
X  s1_desc.dsc$w_length = strlen(s1);
X  s1_desc.dsc$a_pointer = s1;
X
X  status = cli$get_value(&s1_desc,&s2_desc);
X
X  if (status & 1)
X    {
X    str$append(&s2_desc,&null_desc);
X    *s2 = s2_desc.dsc$a_pointer;
X    }
X  else
X    *s2 = 0;
X  return(status);
X}
X
Xprocess_command_line()
X{
X  long int status,boss_len;
X  short int length;
X  $DESCRIPTOR(d_line,buf);
X  $DESCRIPTOR(d_cldline,buf);
X  $DESCRIPTOR(d_boss_term,"BOSS$TERM");
X  $DESCRIPTOR(d_lnm_file_dev,"LNM$FILE_DEV");
X
X  strcpy(buf,"BOSS ");
X  boss_len = strlen(buf);
X  d_line.dsc$w_length =  d_line.dsc$w_length - boss_len;
X  d_line.dsc$a_pointer = d_line.dsc$a_pointer + boss_len;
X  check(lib$get_foreign(&d_line,0,&length,0));
X  buf[length + boss_len] = '\0';
X  d_cldline.dsc$w_length = length + boss_len;
X  status = cli$dcl_parse(&d_cldline,BOSS_CLD,0,0,0);
X  if (bad(status)) exit(STS$K_ERROR+STS$M_INHIB_MSG);
X
X  status = cli_present("UW");
X  uw = !bad(status);
X
X  if (!uw) {
X    nproc = nprocmax;
X    defmode = 'b';
X    first_name = 'A';
X    last_name = 'Z';
X  }
X  else {
X    nproc = P1_NWINDOW;
X    defmode = 'p';
X    first_name = '1';
X    last_name = '7';
X  }
X
X  status = cli_get_value("COMMAND_CHARACTER",&retval);
X  if (bad(status)) {
X    if (!uw) ctlchar = 034;
X    else ctlchar = -1;
X  }
X  else sscanf(retval,"%d",&ctlchar);
X  if (ctlchar < (uw ? -1 : 0) || ctlchar > 0177 || ctlchar == 032) {
X    printf("[Illegal command character (%d); using C-\\ instead]\n",ctlchar);
X    ctlchar = 034;
X`009`009`009`009/* disallow C-z as a command character */
X  }
X  if (ctlchar >= 0 && ctlchar < 040)
X    sprintf(ctlchar_str,"C-%c",tolower(ctlchar+0100));
X  else if (ctlchar == 040) strcpy(ctlchar_str,"SPC");
X  else if (ctlchar == 0177) strcpy(ctlchar_str,"DEL");
X  else if (ctlchar == -1) strcpy(ctlchar_str,"---");
X  else sprintf(ctlchar_str,"%c",ctlchar);
X
X  status = cli_get_value("BEGIN_PROMPT",&retval);
X  if (bad(status)) strcpy(prompt_begin,"");
X  else strcpy(prompt_begin,retval);
X
X  status = cli_get_value("END_PROMPT",&retval);
X  if (bad(status)) strcpy(prompt_end,"");
X  else strcpy(prompt_end,retval);
X
X  status = cli_get_value("DEFAULT_OUTPUT_FLAG",&retval);
X  if (!bad(status)) defmode = tolower(retval[0]);
X
X  status = cli_get_value("PROCESS_DEFAULT",&retval);
X  if (bad(status)) defproc = CREATE;
X  else defproc = ((retval[0] == 'T') ? TOP : CREATE);
X
X  status = cli_present("SWITCH_CREATE");
X  switch_create = !bad(status);
X
X  status = cli_present("FLOW_CONTROL");
X  flow_control = !bad(status) || uw;
X
X  status = cli_get_value("DELETE_CHARACTER",&retval);
X  if (bad(status)) delete_char = 0177;
X  else sscanf(retval,"%d",&delete_char);
X  if (delete_char < 0 || delete_char > 0177) {
X    printf("[Illegal delete character (%d); using DEL instead]\n",delete_char);
X    delete_char = 0177;
X  }
X
X  status = SYS$TRNLNM(0,&d_lnm_file_dev,&d_boss_term,0,&trnlnm_item);
X  if (bad(status)) strcpy(trnlnm_string,"VT100");
X  else trnlnm_string[trnlnm_string_len] = '\0';
X  if (strcmp(trnlnm_string,"VT100") == 0) { /* VT100 */
X    clr = "\033[r\033[4l\033[H\033[2J"; /* Clear screen reset scroll */
X    bos = "\033[r\033[4l\033[99;1H\n"; /* Go to bottom of screen */
X    ceol = "\033[K";`009`009/* Clear to end-of-line */
X    ceoln = "\033[K\r\n";`009/* Clear to end-of-line and newline */
X  } else if (strcmp(trnlnm_string,"VT52") == 0) { /* VT52 */
X    clr = "\033H\033J";
X    bos = "\033Y7 \n";
X    ceol = "\033K";
X    ceoln = "\033K\r\n";
X  } else if (strcmp(trnlnm_string,"ADM3A") == 0) { /* ADM3A */
X    clr = "\032";
X    bos = "\033=7 \n";
X    ceol = "   \010\010\010";
X    ceoln = "   \r\n";
X  } else {`009`009`009/* UNKNOWN */
X    clr = "\r\n";
X    bos = "\r\n";
X    ceol = "";
X    ceoln = "\r\n";
X  }
X}
X
Xint start_up()
X{
X  long int status,j,n;
X  char nname[30], output_flags[30], stuff_flag, odefmode;
X
X  cur = -1;
X  if (!uw) input_state = PENDING;
X  init = 1;
X
X  status = cli_present("START_PROCESS");
X  if (!bad(status)) {
X    stuff_flag = 1;
X    j = 0;
X    while (j < 30 && !bad(cli_get_value("START_PROCESS",&retval))) {
X      if (strlen(retval) != 1) break;
X      nname[j] = toupper(retval[0]);
X      if (nname[j] < first_name || nname[j] > last_name) break;
X      j++;
X    }
X    n = j;
X    j = 0;
X    while (j < n && !bad(cli_get_value("OUTPUT_FLAGS",&retval))) {
X      output_flags[j] = tolower(retval[0]);
X      j++;
X    }
X    while (j < n) {
X      output_flags[j] = defmode;
X      j++;
X    }
X    for (j = 0; j < n; j++) {
X      if (stuff_flag) {
X`009status = cli_get_value("STUFF_STRING",&retval);
X`009if (bad(status)) {
X`009  stuff_flag = 0;
X`009  strcpy(stuff_buf,"");
X`009} else {
X`009  strcpy(stuff_buf,retval);
X`009  if (strlen(retval) > 0) strcat(stuff_buf,"\015");
X`009}
X      }
X      odefmode = defmode;
X      defmode = output_flags[j];
X      status = mov_to(nname[j],0,stuff_buf,defproc);
X      defmode = odefmode;
X      if (bad(status)) break;
X      input_state = NORMAL;
X    }
X  }
X  init = 0;
X  for (j = 0; j < nproc; j++) if (name[j] > 0) post_pty_reads(j);
X}
X
Xmain( )
X{
X  int  exit_handler[4] = {0,quit,0,&st};
X
X  process_command_line();
X  check(SYS$DCLEXH(&exit_handler)); /* Define Exit handler (quit) */
X  if (ctlchar >= 0 && ctlchar < 040)
X    printf("Begin BOSS %s\nType control-%c control-h for information\n",
X`009   VERSION,tolower(ctlchar+0100));
X  else if (ctlchar < 0)
X    printf("Begin BOSS %s\n",VERSION);
X  else
X    printf("Begin BOSS %s\nType %s control-h for information\n",
X`009   VERSION,ctlchar_str);
X  initialize();
X  sys$hiber();
X}
$ GOSUB UNPACK_FILE
$ FILE_IS = "BOSS_CLD.CLD"
$ CHECKSUM_IS = 1382472693
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
Xmodule boss_cld
Xdefine verb boss
X`009qualifier command_character, negatable, default,
X`009`009value(default="28",type=$number)
X`009qualifier delete_character, nonnegatable, default,
X`009`009value(default="127",type=$number)
X`009qualifier start_process, nonnegatable,
X`009`009value(required,list)
X`009qualifier stuff_string, nonnegatable,
X`009`009value(required,list)
X`009qualifier output_flags, nonnegatable,
X`009`009value(required,list,type=output_flag)
X`009qualifier begin_prompt, negatable,
X`009`009value
X`009qualifier end_prompt, negatable, default,
X`009`009value(default="> ")
X`009qualifier default_output_flag, nonnegatable,
X`009`009value(type=output_flag)
X`009qualifier switch_create, negatable
X`009qualifier process_default, nonnegatable, default,
X`009`009value(required,type=process_type)
X`009qualifier flow_control, negatable
X`009qualifier uw, negatable
X
Xdefine type output_flag
X`009keyword b
X`009keyword o
X`009keyword p
X`009keyword w
X
Xdefine type process_type
X`009keyword top_level
X`009keyword subprocess, default
$ GOSUB UNPACK_FILE
$ FILE_IS = "BOSS_BUILD.COM"
$ CHECKSUM_IS = 855795594
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
X$! Procedure for compiling and linking BOSS.
X$!
X$ cc boss
X$ set command/object boss_cld
X$ link/notraceback boss,boss_cld,sys$input/opt
Xsys$library:vaxcrtl/share
$ GOSUB UNPACK_FILE
$ FILE_IS = "BOSS_INSTALL.COM"
$ CHECKSUM_IS = 1029728184
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
X$! Procedure for installing BOSS.  This goes into the system startup file.
X$!
X$ boss_dir = "usr:[utility]"`009! Edit to point to where BOSS.EXE resides
X$ install = "$install/command_mode"
X$ if  f$file("''boss_dir'boss.exe","known") then install delete 'boss_dir'boss
X$ install create 'boss_dir'boss/priv=(phy_io,oper)/header/open/shared
$ GOSUB UNPACK_FILE
$ EXIT
-+-+-+-+-+ End of part 4 +-+-+-+-+-

CC:
        hydrovax%nmt@relay.cs.net
        BUHLE@XRT.UPENN.EDU
        UNOCC07%ZEUS.DNET@FERGVAX.UNL.EDU
        MARK%ISIS@MITVMA.MIT.EDU
        eric@geology.tn.cornell.edu
        Everhart%Arisia.decnet@ge-crd.arpa
        gkn@Sds.MFEnet
        ROBIN%CSVA.SAINET@NMFECC.ARPA
        LUNDIN@URVAX.BITNET
