



		    autoload.c                      08/07/87  1520.6rew 08/07/87  1437.7       18963



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-10-10,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION

Perform the autoload of all specified capabilities, capabilities are specified
for autoload through the /L option to the MOWSE command.  These are destined
to be executed when MOWSE has entered packet mode.
*/

/* : NOTES

The capabilities specified must be in the PC PATH search list.
*/

#include <stdio.h>
#include <ws.h>
#include <ws_auto.h>
#include <ws_dcls.h>

#define CHAR_SHIFT   8

AUTO   load_list[AUTO_LIMIT];          /* List of capabilities to be loaded */
int    load_list_pending;              /* Indicates load list is not empty */

int autoload ()
{
int    i;
int    error;
struct putbg_struc error_msg;          /* Error message struct for reporting */

   error_msg.type = WSINFO;
   error_msg.sender_major =(int)(((int)WSIBMPC << CHAR_SHIFT) | (int)WSMAJCAP);

   for (i = 0; (i < AUTO_LIMIT) && (load_list[i].flags & AUTO_ON); i++)
   {  set_dta();                       /* use Mowse's DTA */
      set_trap();                      /* use MOWSE's trap rotuines */
      error = system(load_list[i].name);
      rst_trap();
      rst_dta();

      if (error)
         sprintf (error_msg.bgmsg, "autoload: %s failed.\n", load_list[i].name);
      else
         sprintf (error_msg.bgmsg, "autoload: %s attempted.\n", load_list[i].name);

/* : Send a background message to indicate what has happened */

      error_msg.length = strlen (error_msg.bgmsg);
      i_putbgm (&error_msg);
   }
}




		    buffer.asm                      08/07/87  1521.0rew 08/07/87  1438.7      105714



; ***********************************************************
; *                                                         *
; * Copyright, (C) Honeywell Bull Inc., 1987                *
; *                                                         *
; * Copyright, (C) Honeywell Information Systems Inc., 1986 *
; *                                                         *
; ***********************************************************

page 55,132

; HISTORY COMMENTS:
;  1) change(86-04-01,McGinn), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Created.
;  2) change(86-04-27,Westcott), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Support macros.
;  3) change(86-09-09,Flegel), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Support for checking for length field in test
;     for protocol mode.
;  4) change(86-09-15,Flegel), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Change check for checksum to look for CRC char
;     of reset request packet.
;  5) change(86-12-09,Flegel), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Removed packetize flag setting so that it can
;     be left to mio to set when all is peachy.
;  6) change(87-03-24,Flegel), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Changed to look for r_EOP character as the
;     EOP rather than hardcoding a <LF>
;  7) change(87-04-03,Flegel), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Corrected reset packet testing in get_inbuff
;     to account for error characters in inbuff
;                                                      END HISTORY COMMENTS

;/* : FUNCTION
;
;This is a collection of routines which are used for buffer manipulations.
;*/

include dos.mac
include mowsdefs.mac
include ws_buf.mac              ; circular buffer macros
include rs232err.mac

SOP          = 1                ; definition of a reset packet
RSTREQ       = 32               ;    type field
LENCHR       = 37               ;    length field
CRCCHAR      = 58               ;    CRC field
dseg

;---------- Public Declarations

public put_inbuff
public get_inbuff
public len_inbuff
public init_inbuff

extrn inbuff:word
extrn packet_mode:word
extrn r_EOP:byte
extrn datab:word
endds

page

pseg

;/* : PROCEDURE FUNCTION (init_inbuff):
;
;Initialize the input buffer, and place/remove an initial character to "get
;the buffer going".
;*/

init_inbuff proc near

        init_buf inbuff                     ; Initialization macro
        mov     al,'a'
        xor     ah,ah
        call    put_inbuff                  ; Put a test character in
        call    get_inbuff                  ; Get it out

init_inbuff endp


;/* : PROCEDURE FUNCTION (put_inbuff):
;
;Puts the character in AL in the input buffer.
;*/

;/* RETURNS:
;
;    ax = 0 for no error
;    ax = 1 for buffer overflow
;*/

put_inbuff proc near

        push    si                          ; save registers
        push    bx

        mov     bx,offset inbuff            ; bx = inbuff
        mov     si, bin[bx]                 ; si = buffer_in
        or      ah,ah                       ; error prefix?
        jz      nopfx                       ;  YES - abort
        mov     byte ptr ds:[si],ah         ;   NO - process character

;/* : inbuff = inbuff + 1
;     if (inbuff is at end of buffer)
;     - inbuff = start of buffer */

        inc     si                          ; inc counter
        cmp     si,blast[bx]                ; buffer wrapping ?
        jbe     short nae1                  ;   NO - continue
        mov     si,bfirst[bx]               ;  YES - wrap counter

;/* : if (not overflow) store inbuff, clear error code, and return */

nae1:
        cmp     si, bout[bx]
        je      ovf1                        ; if buffer full

; /* : inbuff = inbuff + 1
;      if (inbuff is at end of buffer)
;      - inbuff = start of buffer */

nopfx:
        cmp     datab,DATA7                 ; if data7 then mask bit 8
        jne     no_mask
        and     al,7Fh                      ; mask data8 bit

no_mask:
        mov     byte ptr ds:[si],al

        inc     si                          ; inc counter
        cmp     si,blast[bx]                ; wrapped buffer ?
        jbe     short nae2                  ;   NO - continue
        mov     si,bfirst[bx]               ;  YES - wrap counter

;/* : if (not overflow) store inbuff, and return */

nae2:
        cmp     si, bout[bx]                ; buffer full ?
        je      ovf1                        ;  YES - overflow error

        mov     bin[bx],si                  ; reset the in counter

        pop     bx                          ; restore registers
        pop     si
        ret

;/* : else store overflow flag in buffer */

ovf1:
        mov     si,bin[bx]                  ; restore original in pointer
        dec     si
        cmp     si,bfirst[bx]
        ja      ovf2
        mov     si,blast[bx]

ovf2:
        mov     byte ptr ds:[si],5          ; overflow flag = 5
        pop     bx
        pop     si
        ret

put_inbuff endp

; : END put_buffer

;/* : PROCEDURE FUNCTION (get_inbuff):
;
;Get the next character from the rsr232 input circular buffer if MOWSE is not 
;in packet mode and a SOP character is received, return with no data to the 
;user until 4 characters have been accumulated in the buffer. If these 4 
;characters constitute a valid MOWSE RST packet, enter packet mode and give 
;the characters to the caller. If no SOP is found or if the SOP is not the 
;start of a RST packet, then just give the current charcter to the caller.
;*/

;/* RETURNS:
;
;   Carry flag SET, if data available
;   Carry flag CLEAR, if no data available
;*/

get_inbuff proc near

;/* : check for empty buffer */

        push    si
        push    bx
        mov     bx, offset inbuff
        mov     si,bout[bx]
        cmp     si,bin[bx]
        jne     bnemp1
        jmp     bemp2

;/* : if (buffer not empty) get character into AX */

bnemp1:
        mov     al,byte ptr ds:[si]

;/* : outbuff = outbuff + 1
;     - if (outbuff = end of buffer) outbuff = start of buffer
;     - if not in packet mode, look for reset packet */

        inc     si
        cmp     packet_mode,0
        jne     in_packet_mode

        cmp     al,SOP
        jne     in_packet_mode              ; if not a start of (reset) packet

        mov     ax,bin[bx]
        sub     ax,bout[bx]
        jge     rst99
        add     ax,bsize[bx]

rst99:  cmp     ax,5                        ; must be at least 5 characters in reset packet
        jl      bemp2                       ; return nothing to caller until 4 chars available

        cmp     si,blast[bx]
        jbe     rst1
        mov     si,bfirst[bx]

rst1:
        call    next_char                   ; get next valid char
        call    chk_index                   ; make sure valid character
        jnc     bemp2
        cmp     al,RSTREQ
        jne     givechar                    ; not a reset packet
        inc     si
        cmp     si,blast[bx]
        jbe     rst2
        mov     si,bfirst[bx]

rst2:
        call    next_char                   ; get next valid char
        call    chk_index                   ; make sure valid character
        jnc     bemp2
        cmp     al,LENCHR
        jne     givechar                    ; not a reset packet
        inc     si
        cmp     si,blast[bx]
        jbe     rst3
        mov     si,bfirst[bx]

rst3:
        call    next_char                   ; get next valid char
        call    chk_index                   ; make sure valid character
        jnc     bemp2
        cmp     al,CRCCHAR
        jne     givechar                    ; not a reset packet
        inc     si
        cmp     si,blast[bx]
        jbe     rst4
        mov     si,bfirst[bx]

rst4:
        call    next_char                   ; get next valid char
        call    chk_index                   ; make sure valid character
        jnc     bemp2
        cmp     al,r_EOP
        jne     givechar                    ; not a reset packet
        mov     packet_mode,1               ; reset received, enter packet mode

givechar:
        mov     si,bout[bx]
        mov     al,byte ptr ds:[si]
        inc     si

in_packet_mode:
        cmp     si,blast[bx]
        jbe     nae4
        mov     si,bfirst[bx]

nae4:
        mov     bout[bx],si
        jmp     bnemp2

;/* : if (buffer empty) clear AX, and return */

bemp2:
        pop     bx
        pop     si
        clc                                 ; CLEAR carry flag to indicate no data
        ret

bnemp2:
        pop     bx
        pop     si
        stc                                 ; SET carry flag to indicate data available
        ret

get_inbuff endp

;/* : END get_buffer */

;/* : PROCEDURE FUNCTION (len_inbuff):
;
; Returns the number of characters in the buffer in AX.
;*/

len_inbuff proc near

        len_buf inbuff
        ret

len_inbuff endp

;/* : END get_length */

;/* : PROCEDURE FUNCTION (chk_index):
;
; Test if the current value of si is within the current inbuffer.
;
; carry flag = 1: valid index
;            = 0: invalid index
;*/

chk_index proc near

        push    ax
        mov     ax,bin[bx]
        cmp     ax,bout[bx]                 ; in < out ?
        jb      reverse_test                ;  YES - reverse test

        cmp     si,bout[bx]                 ; ?????O----Ixxxxx
        jb      invalid_test                ; ^^^^^

        cmp     si,bin[bx]                  ; xxxxxO----I?????
        jb      valid_test                  ; ^^^^^^^^^^
        jmp     invalid_test

reverse_test:

        cmp     si,bin[bx]                  ; -----I????O-----
        jb      valid_test                  ; ^^^^^

        cmp     si,bout[bx]                 ; -----I????O-----
        jb      invalid_test                ; ^^^^^^^^^^

valid_test:
        stc                                 ; Carry = 1, passed
        pop     ax
        ret

invalid_test:
        clc                                 ; Carry = 0, failed
        pop     ax
        ret

chk_index endp

;/* : END get_length */

;/* : PROCEDURE FUNCTION (next_char)
;
; Returns the next valid character in the inbuff thus skipping over error escape
; characters.
;*/

next_char proc near

try_char:
        mov     al,byte ptr ds:[si]         ; get current char

        cmp     al,ESCAPE_STATUS            ; escape char ?
        ja      valid_char                  ;   NO - then current is OK
        je      esc_chr                     ;  YES - then next char is valid

        cmp     al,LINE_STATUS              ; line_status char ?
        jb      valid_char                  ;   NO - then current is OK

skip_2:
        inc     si                          ; increment index
        cmp     si,blast[bx]
        jbe     skip_1
        mov     si,bfirst[bx]

skip_1:
        inc     si                          ; increment index
        cmp     si,blast[bx]
;       jbe     next_char
        jbe     try_char
        mov     si,bfirst[bx]

        jmp     try_char                    ; repeat as this may be another escape
;       jmp     next_char                   ; repeat as this may be another escape

esc_chr:
        inc     si                          ; increment index
        cmp     si,blast[bx]
        jbe     no_wrap
        mov     si,bfirst[bx]
no_wrap:
        mov     al,byte ptr ds:[si]         ; get current char


valid_char:

        ret

next_char endp

;/* : END next_char */

        endps
        end




		    callmows.c                      08/07/87  1520.6rew 08/07/87  1437.6       35901



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-05-09,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
     install(87-08-07,MR12.1-1072):
     Created.
  2) change(86-05-20,Westcott), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Provided a return code mechanism.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (call_mowse_int)

Calls one of the MOWSE's interrupt handlers, passing it a parameter
structure containing all the required data; all data in the parameter
structure is input data as this structure is copied into MOWSE's space 
(i.e. passing the structure by value).  It is up to the caller to ensure 
that the structure passed is the same as the structure expected by the 
interrupt handler.  This provides a general parameter passing mechanism
between applications and MOWSE interrupt handlers.
*/

/* : NOTES

This is the first inklink of MOWSE that the application sees.
*/

#include <dos.h>
#include <ws.h>
#include <ws_error.h>

#define INTRPT_VECTOR_TABLE   1023     /* Where DOS interrupt vectors live */
#define INTRPT_ADDRESS_SIZE   4        /* Number of bytes to the transfer vector */
#define SIGNATURE_SIZE        8        /* Size of signature */
#define SIGNATURE_ID_OFFSET   4        /* Offset into signature of MOWSE id */

int USER_INTERRUPT = 0;                /* user interrupt number (/I to mowse) */
                                       /*    must be set here at "process" init */
int local_system;                      /* system id for local system */

call_mowse_int (p_mowse_minor, p_param_addr, p_param_size)

int  p_mowse_minor;                    /* Internal function to execute */
char *p_param_addr;                    /* Parameter structure for the function */
int  p_param_size;                     /* Length of parameter structure */
{
int segment;                           /* MOWSE code segment */
int intoff;                            /* Interrupt address offset */
int offset;                            /* Interrupt vectors */
union sigun
{  int  signature[SIGNATURE_ID_OFFSET];/* MOWSE signature */
   char csig[SIGNATURE_SIZE];          /* Signature information */
} sig;
union REGS inregs, outregs;            /* Register information */

/* : if USER_INTERRUPT not set (=0 )
     - scan low memory for user_interrupt_handler signature which signifies
       where MOWSE resides as a user_interrupt, or does not reside at all */

   if (USER_INTERRUPT == 0)
   {  for (offset = 0; offset < INTRPT_VECTOR_TABLE; offset += INTRPT_ADDRESS_SIZE)
      {  peek (0, offset, &sig.csig[0], SIGNATURE_SIZE);
         segment = sig.signature[1];
         intoff  = sig.signature[0] + SIGNATURE_ID_OFFSET;
         peek (segment, intoff, &sig.csig[0], SIGNATURE_SIZE);
         if (strcmp (&sig.csig[1],"MOWSE") == 0) break;
      }

/* : If passed the whole table, then MOWSE not found */

      if (offset > INTRPT_VECTOR_TABLE)
         return (WSNOTRES);

/* : Otherwise convert the address of the offset to an iterrupt number */

      USER_INTERRUPT = offset >> 2;
      local_system = (int) sig.csig[0];
   }

/* : Generate the interrupt */

   inregs.h.ah = p_mowse_minor;                  /* ah = MOWSE minor */
   inregs.x.si = (short)p_param_addr;            /* si = parameter structure address */
   inregs.x.cx = p_param_size;                   /* cx = size of parameter */
   int86(USER_INTERRUPT, &inregs, &outregs);
   return (outregs.x.ax);                        /* ax = return code */
}




		    capabil.c                       08/07/87  1520.6rew 08/07/87  1437.6       38898



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-05-05,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
     install(87-08-07,MR12.1-1072):
     Created.
                                                   END HISTORY COMMENTS */
/* : PROCEDURE FUNCTION (init_cat)

Initialize the local and remote Capability Address Tables (CAT) to a state 
which indicates that there are NO current entries in the tables. This is 
done by setting the "mcb" field of local table to "NULL". And setting the
"major_capability" field of the remote table to "0".
*/

/* : NOTES:

A call must be made to this routine before any accessing of the CAT tables 
can be made. Also a call to this routine will wipe out any entries that may
currently exist in the Tables.
*/

#include <dos.h>
#include <ws.h>
#include <cat.h>
#include <ws_error.h>

#define LOW_8_BITS  0x00FF
#define NULL 0

#ifndef TRUE
#define TRUE 1
#endif

#ifndef FALSE
#define FALSE 0
#endif

extern char       MYSYSTEM;            /* System ID */
extern local_cat  l_CAT[];             /* Local CAT */
extern remote_cat r_CAT[];             /* Remote CAT */
extern local_cat  *sleepq;             /* Sleeping queue */

init_cat ()
{
int  i;

/* : Empty the sleepq */

   sleepq = NULL;

/* : for each entry in the cat tables
     - set the mcb pointer in the local cat entry to NULL
     - set the major capability number in remote cat entry to 0 */

   for (i = 0; i < NUMBER_OF_CAT_ENTRIES; i++)
   {  l_CAT[i].mcb_ptr            = NULL;
      l_CAT[i].flags              = 0;
      l_CAT[i].next_cat           = NULL;
      l_CAT[i].sleep_time         = 0;
      l_CAT[i].waitreg            = 0;
      l_CAT[i].ws_entry           = NULL;

      r_CAT[i].major_capability   = 0;
      r_CAT[i].system_id          = 0;
      r_CAT[i].capability_name[0] = 0;
      r_CAT[i].flags              = 0;
   }
}

/* : PROCEDURE FUNCTION (find_free_cat)

Find a free entry into the local CAT table, i.e one that is not being used. 
Return the index for this local CAT entry if one is found, otherwise return 
an error code.
*/

find_free_cat ()
{
int  cat_entry_index;
int  i;

/* : search local cat from 1st entry to last entry
     - if the mcb pointer is NULL (not being used)
     -- set output parameter cat entry index to current entry
     -- free cat entry found, set code to 0 and return */

   for (i = 0; i < NUMBER_OF_CAT_ENTRIES; i++)
   {  if (l_CAT[i].mcb_ptr == NULL)
      {  cat_entry_index = i;
         return(cat_entry_index);
      }
   }

/* : else search for free cat entry fails, set code for failed */

   return(WSCNTCRE);
}

/* : PROCEDURE FUNCTION (add_to_remote_cat)

Used to update the remote CAT entry, this is an internal MOWSE function call.
*/

add_to_remote_cat (p_system_id, p_major_capability_number, p_capability_name)

char p_system_id;
char p_major_capability_number;
char *p_capability_name;
{
int  cap_num;
int  i;
int  pad;

/* : if system_id is not 'remote', set error code and return */

   cap_num = (int) p_major_capability_number - MIN_CAPABILITY_NUMBER;
   if ((cap_num < 0) || (cap_num > NUMBER_OF_CAT_ENTRIES))
      return (WSINVNUM);

   if (p_system_id == MYSYSTEM)
      return (WSINVSYS);

/* : if capability is already used, set error code and return */

   if (r_CAT[cap_num].major_capability != 0)
      return(WSINVNUM);

/* : - initialize the remote cat entry with given data */

   r_CAT[cap_num].major_capability = p_major_capability_number;
   r_CAT[cap_num].system_id = p_system_id;

/* : copy the capability name into the remote cat, padding nulls on the
     right of the string */

   i = stccpy (r_CAT[cap_num].capability_name, p_capability_name, CAPABILITY_NAME_LENGTH);
   for (i = i; i < CAPABILITY_NAME_LENGTH; r_CAT[cap_num].capability_name[i++] = 0);

/* : reset all flags */

   r_CAT[cap_num].flags = 0;

/* : - no errors, set code returned to 0 */

   return (0);
}




		    conresp.c                       08/07/87  1520.6rew 08/07/87  1437.5       15975



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-07-06,Westcott), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (conresp)

Sends a "CONNECT_REPONSE" minor capability message to the addressed major 
capability. This message is used by the major capability to either accept 
or reject a requested connection.
*/

#include <stdio.h>
#include <ws.h>
#include <wsmincap.h>
#include <ws_mcb.h>
#include <ws_error.h>

conresp (p_status, p_cap_num, p_mcb_ptr)

int p_status;                          /* WSACCEPT or WSREJECT */
int p_cap_num;                         /* Capability number to respond to */
mcb *p_mcb_ptr;                        /* MCB of caller */
{
int sysid;
int major;

/* : call execap to send message to application */

   sysid = ((p_cap_num & 0xff00) >> 8);
   major = (p_cap_num & 0xff);

   if (p_mcb_ptr == NULL)
      return (WSINVMCB);

   if ((sysid != WSIBMPC) && (sysid != WSMULTICS))
      return(WSINVSYS);

   if ((major < WSMAJCAP) && (major > MAX_CAPABILITY_NUMBER))
      return(WSINVNUM);

   if ((p_status != WSACCEPT) && (p_status != WSREJECT))
      return (WSINVCON);
        
   return (execap (p_cap_num, RESPONSE_CONNECT, &p_status, 1, p_mcb_ptr));
}




		    conrqst.c                       08/07/87  1520.5rew 08/07/87  1437.5       23841



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-06-06,Westcott), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
  2) change(86-10-21,ASmith), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Changed format to connect to a name rather than
     a number and to supply args to the connect.
  3) change(86-10-29,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Reduced to generate a message to the internal
     MOWSE function to handle connect request.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (conrqst)

Send a REQUEST_CONNECT minor capability to the application specified.  If the
application does not exist, it will be created through an execom with the
name provided and the args specified.  The REQUEST_CONNECT message will then
be generated if the name became active (CAT).
*/

#include <dos.h>
#include <cat.h>
#include <stdio.h>
#include <ws_func.h>
#include <wsmincap.h>
#include <ws_error.h>
#include <ws_dcls.h>

#define HEADER_LENGTH 4

conrqst(p_cap_name,p_args,p_system,p_mcb_ptr)

char p_cap_name[];                     /* Name of capability to connect ot */
char p_args[];                         /* Argument string */
int  p_system;                         /* System of capability to connect to */
mcb  *p_mcb_ptr;                       /* MCB of caller */
{
int  system;
int  length;
struct i_connect_request xparam;

/* : Check system value */

   if (p_system == WSLOCAL)
      system = WSIBMPC;
   else if (p_system == WSREMOTE)
      system = WSMULTICS;
   else 
      return(WSINVSYS);

/* : Check mcb_ptr */

   if (p_mcb_ptr == NULL)
      return(WSINVMCB);

/*  : set up parameters to be passed to user interrupt handler */

   xparam.system        = system;
   xparam.source_system = p_mcb_ptr->system_id;
   xparam.source_major  = p_mcb_ptr->major_capability;
   sprintf (xparam.connect_command, "%.32s %s", p_cap_name, p_args);
   length = strlen (xparam.connect_command) + HEADER_LENGTH;

/* : generate user interrupt */

   return (call_mowse_int (I$CONNECT,&xparam,length));
}




		    cretinst.c                      08/07/87  1520.5rew 08/07/87  1437.5       66105



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-05-06,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
     install(87-08-07,MR12.1-1072):
     Created.
  2) change(86-05-12,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
     install(87-08-07,MR12.1-1072):
     global variable holding address of application
     routine now replaced by field in mcb called application_entry.
  3) change(86-07-07,Westcott), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Support linked lists for inbuff and outbuff.
  4) change(86-11-14,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Initialized the mcb_flag field.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (cretinst)

Register the calling routine with MOWSE by assigning it a major capability 
number and adding it to MOWSE's capability table. The calling routine must 
supply the name by which it is to be known to MOWSE, and a pointer to the 
function to be invoked when a message is received.

Allocates and initializes the mcb in the caller's address space.

Allocates and initializes the input and output buffers in the caller's 
address space.
*/

/* : NOTES:

All applications which expect to receive messages must have registered with 
MOWSE (through create_instance) in order to receive messages. A message is 
provided to the application when a the destination of the message specifies 
the major capability number of the application. The application will then be 
invoked at the entry name provided with the message (argument data), its 
length, and a pointer to the applications data_block as follows:

   process_event (minor_capability, major_sender, arg_ptr,
                  arg_length, mcb_ptr, data_block_ptr);

The buffers inbuff and outbuff allow MOWSE to send and receive messages longer 
than one communications packet (defined by WSPAKSIZ) in a manner transparent 
to the capability.
*/

#include <dos.h>
#include <ws.h>
#include <cat.h>
#include <ws_dcls.h>
#include <ws_error.h>
#include <ws_func.h>

#define NULL 0

cretinst (capability_name, entry_name, inbuff_length, outbuff_length, data_block_ptr, mcb_ptr)

char *capability_name;
int  (*entry_name)();
int  inbuff_length;                    /* Length of input buffer */
int  outbuff_length;                   /* Length of output buffer */
char *data_block_ptr;                  /* Application data to be saved */
mcb  **mcb_ptr;                        /* Address of new mcb_ptr */
{
int  i;
int  inbuff_size;
int  outbuff_size;
int  cap_num;
int  code;
mcb *lmcb_ptr;                         /* local mcb pointer */
struct SREGS segregs;
struct allocstr *allocp;
struct cretinst_param_struct cips;

int  pe_entry();                       /* pointer to function to receive messages */

   code = 0;

/* : allocate and initialize the mcb */

   lmcb_ptr = (mcb *) malloc (sizeof (mcb));
   if (lmcb_ptr == NULL)
      return (WSCNTCRE);

/* : initialize the capability name field of mcb with capability name passed */

   cips.mcb_ptr = lmcb_ptr;
   stccpy (lmcb_ptr -> capability_name, capability_name, CAPABILITY_NAME_LENGTH);
   i = stccpy (cips.capability_name, capability_name, CAPABILITY_NAME_LENGTH);
   for (i = i; i < CAPABILITY_NAME_LENGTH; i++)
   {  lmcb_ptr -> capability_name[i] = 0;
      cips.capability_name[i] = 0;
   }

/* : store address of application routine (if it was NULL, then set the
     appropriate mcb_flag) to be called and the application's data block
     pointer in the mcb, clear the flags */

   lmcb_ptr -> data_block_ptr = data_block_ptr;
   lmcb_ptr -> mcb_flag = 0;

   if (!((int)(entry_name)))
   {  lmcb_ptr -> application_entry = NULL;
      lmcb_ptr -> mcb_flag |= MCB_NULL_ROUTINE;
   }
   else
      lmcb_ptr -> application_entry = entry_name;

/* : determine the actual input buffer size. The input buffer size must be
     at least as large as the minimum packet size.  We must also allow
     space for the linked list overhead */

   if (inbuff_length < WSPAKSIZ)
      inbuff_size = WSPAKSIZ;
   else
      inbuff_size = inbuff_length;

   inbuff_size += (sizeof (struct allocstr))*2;
   inbuff_size += (sizeof (struct linklst))*2;
   inbuff_size += WSPAKSIZ;

/* : allocate the input buffer and initialize fields associated with the
     input buffer.  If cant allocate, then clean up and return error */

   lmcb_ptr -> inbuff_length = inbuff_length;
   allocp = (struct allocstr *) malloc (inbuff_size);
   if (allocp != NULL)
   {  lmcb_ptr -> inalloc = allocp;
      allocp -> memory_used = 0;
      allocp -> memory = (char *) ((int)allocp + sizeof (struct allocstr));
      allocp -> m_allocp = NULL;
      allocp -> memory_size = inbuff_size - sizeof (struct allocstr);
      lmcb_ptr -> inbuff = NULL;
   }
   else
   {  free (lmcb_ptr);
      *mcb_ptr = NULL;
      return (WSINVBUF);
   }

/* : determine the actual output buffer size. We must allow space for the
     overhead required to store enough packets to save the requested number
     of characters, plus space for the allocation structure. */

   outbuff_size = 1 + outbuff_length / WSPAKSIZ;
   outbuff_size = outbuff_size * (WSPAKSIZ + sizeof(struct linklst));
   outbuff_size += sizeof (struct allocstr);

/* : allocate the output buffer and initialize the fields associated with
     the output buffer.  If cant allocate it hten clean up and return error */

   lmcb_ptr -> outbuff_length = outbuff_length;
   allocp = (struct allocstr  *) malloc (outbuff_size);
   if (allocp != NULL) {
      lmcb_ptr -> outalloc = allocp;
      allocp -> memory_used = 0;
      allocp -> memory = (char *) ((int)allocp + sizeof (struct allocstr));
      allocp -> m_allocp = NULL;
      allocp -> memory_size = outbuff_size - sizeof (struct allocstr);
      lmcb_ptr -> outbuff = NULL;
   }
   else {
      free (lmcb_ptr -> inalloc);
      free (lmcb_ptr);
      *mcb_ptr = NULL;
      return (WSINVBUF);
   }

/* : set the low and high memory values get the segment register so we can
     save it in the CAT store address of entry_pt routine in mowse
     structure */

   segread(&segregs);
   cips.cs_reg = segregs.cs;
   cips.entry_pt = NULL;
   if (!(lmcb_ptr -> mcb_flag & MCB_NULL_ROUTINE))
      cips.entry_pt = pe_entry;

/* : call the interrupt handler in mowse,  if an error occurred free up 
     allocated buffers and pass back NULL pointer to caller */

   if (code = call_mowse_int (I$CRETINST, &cips, sizeof(cips)))
   {  if (lmcb_ptr -> inalloc != NULL)
         free (lmcb_ptr -> inalloc);
      if (lmcb_ptr -> outalloc != NULL) 
         free (lmcb_ptr -> outalloc);
      free (lmcb_ptr);
      *mcb_ptr = NULL;
   }
   else
   {  lmcb_ptr -> major_capability = cips.major_capability;
      lmcb_ptr -> system_id = cips.system_id;
      *mcb_ptr = lmcb_ptr;
   }
   return (code);
}




		    curpos.c                        08/07/87  1520.5rew 08/07/87  1437.5       13671



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-09-05,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
     install(87-08-07,MR12.1-1072):
     Created.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (get_cursor_pos)

Return the absolute coordinates of the cursor in x,y
*/

#include <dos.h>
#include <emulator.h>

#define VIDEO_IO    0x10
#define GET_CURSOR  0x03
#define GET_WIDTH   0x0F

#if EM_DEBUG                           /* Do NOT compile if !EM_DEBUG */

get_cursor_pos(x,y)

int *x;
int *y;
{
union REGS inregs;
union REGS outregs;

   inregs.h.ah = GET_CURSOR;
   inregs.h.bh = 0;

   int86(VIDEO_IO,&inregs,&outregs);

   *x = outregs.h.dh;
   *y = outregs.h.dl;
}

/* : PROCEDURE FUNCTION (get_screen_width)

Return the width of screen in columns
*/

get_screen_width()
{
union REGS inregs;
union REGS outregs;
int screen_width;

   inregs.h.ah = GET_WIDTH;
   int86(VIDEO_IO,&inregs,&outregs);
   screen_width = outregs.h.ah;

   return(screen_width);
}

#else
get_cursor_pos()
{}
get_screen_width()
{}
#endif




		    dbgetkbl.c                      08/07/87  1520.5rew 08/07/87  1437.5       64638



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-07-23,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
     install(87-08-07,MR12.1-1072):
     Created.
  2) change(86-07-24,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
     install(87-08-07,MR12.1-1072):
     Added function key handling.
  3) change(86-08-22,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
     install(87-08-07,MR12.1-1072):
     Passed all function key handling to call routine;
     a -1 is returned if a function key was pressed and the parameter 'option'
     will contain the key pressed for the special function.
  4) change(86-09-07,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
     install(87-08-07,MR12.1-1072):
     Added local editing
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (get_kb_line)

If data exists in the keyboard buffer, this routine will echo
the data and wait for additional data until a carriage return is
entered; the line entered will be passed back and the length of
the line is returned.  If nothing exists in the keyboard buffer,
this routine just returns 0.  If a function key press was detected,
a -1 is returned and the value of the function key press is put in
the parameter 'option'.  While in this routine, the user may use
the backspace key to erase the previous character entered.  If the
entire line is erased, the routine will return immediately with the
value 0. (This allows the emulator in the main loop to poll for
foreground data again.)  The local_edit flag determines whether
the \, @, # and ESC keys have special editing functions.  If
local_edit is TRUE, ESC and @ will kill the entire line, # will also
serve as a backspace and the \ serves to escape all four keys.
If the local_edit key is FALSE, all characters will be passed back
unchanged.  Note that tabs will expand when the tab key is pressed
(according to the size in em_tab_size) but the tab character is passed
back to the caller unaltered.

*/

#include <ctype.h>
#include <ws.h>
#include <keydefs.h>
#include <emulator.h>

#if EM_DEBUG                           /* Do NOT compile if !EM_DEBUG */

extern int bg_sender_stack[NUMBER_OF_CAT_ENTRIES];
extern int packetize_flag;
extern int em_print_mode;
extern int em_tab_size;
extern int local_edit;


db_get_kb_line(kb_buffer,kb_stack,option)

/* INPUT */
   char kb_buffer[];
   char kb_stack[];

/* OUTPUT */
   int *option;
{

/* MISC */
   int done;
   int ch;
   int buff_char;
   int i;
   int counter;
   int kb_index;
   int kb_posit;
   int kb_tstptr;
   int hidden_pos;

/* INITIALIZATION */

   done = 0;
   kb_index = 0;
   kb_posit = 0;
   kb_tstptr = 0;
   hidden_pos = 0;

/* : initialize function key value and buffer */

   *option = -1;
   *kb_buffer = '\0';

/* : loop unconditionally */

   while (1) {

/* : - if a key was pressed, process that character
     -- filter special characters if in local edit mode */

      if (get_kb_key(&ch)) {
         if (local_edit) {
            switch (ch) {
               case '#': ch = BS;        break;
               case '@': ch = DEL_LINE;  break;
               case ESC: ch = DEL_LINE;  break;

/* : -- handle escaping of special characters
     --- '\' pressed, wait for another key
     --- if not function key or special character put '\' in buffer and pass 
         new key on otherwise discard '\' and pass new key on */

               case '\\':
                  while(!get_kb_key(&ch));

                  if (ch < 256 && ch != '#' && ch != '@' && ch != ESC && ch != '\\') {
                     if (kb_index < KB_BUFFERSIZE) {
                        kb_buffer[kb_index++] = '\\';
                        kb_posit++;
                        putch('\\');
                     }
                     else
                        beep();
                  }
                  break;
            }
         }

/* : -- check for extended ascii code */

         if (ch > 255 && ch < 512) {
            if (kb_index == 0) {
               *option = ch;
               return(-1);
            }
         }

/* : -- process normal keyboard data */

         else {
            switch (ch) {

/* : --- handle carriage return pressed
     ---- terminate line with a linefeed
     ---- return the length of keyboard input */

               case CR:
                  kb_buffer[kb_index++] = LF;
                  putch(LF);
                  putch(CR);
                  return(kb_index);

/* : --- handle backspace
     ---- if something in keyboard buffer
     ---- else nothing in keyboard buffer, return to allow scanning of
          incoming data */

               case BS:
                  if (kb_index > 0) {
                     buff_char = kb_buffer[--kb_index];
                     if (buff_char == TAB) {
                        counter = Pop (&kb_tstptr,kb_stack);
                        for (i = 0; i < counter; i++)
                           Screen_Erase_Char();
                     }
                     else 
                        Screen_Erase_Char();
                  }
                  else 
                     return(0);
                  break;

/* : --- wipe out entire line and return(0)
     ---- for each character entered */

               case DEL_LINE:
                  while (kb_index > 0) {
                     buff_char = kb_buffer[--kb_index];

                     if (buff_char == TAB) {
                        counter = Pop (&kb_tstptr,kb_stack);
                        for (i = 0; i < counter; i++)
                           Screen_Erase_Char();
                     }
                     else 
                        Screen_Erase_Char();
                  }
                  return(0);


/* : --- handle tabs */

               case TAB:
                  if (kb_index < KB_BUFFERSIZE) {
                     kb_buffer[kb_index++] = TAB;
                     counter = em_tab_size - (kb_posit % em_tab_size);
                     kb_posit += counter;
                     Push (counter,&kb_tstptr,kb_stack);
                     for (i = 0; i < counter; i++)
                        putch(' ');
                  }
                  else
                     beep();
                  break;

/* : --- handle normal keyboard character */
               default:
                  if (kb_index < KB_BUFFERSIZE) {
                    kb_buffer[kb_index++] = ch;
                    kb_posit++;
                    putch(ch);
                  }
                  else
                     beep();
            }
         }
      }

/* : -- if keyboard buffer empty, return to allow scanning of incoming data */

      else if (kb_index <= 0) return(0);
   }
}

#else
db_get_kb_line ()
{}
#endif




		    dbprocop.c                      08/07/87  1520.5rew 08/07/87  1437.4       35946



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-08-22,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
     install(87-08-07,MR12.1-1072):
     Created.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (proc_op)

Processes options in the emulator, depending on the key pressed.  The value 
of the terminate flag passed will always be FALSE unless the 'exit emulator' 
key was pressed.  This routine is called the MOWSE dumb emulator in the 
debug version.
*/


#include <ctype.h>
#include <ws.h>
#include <ws_dcls.h>
#include <wsmincap.h>
#include <keydefs.h>
#include <emulator.h>

#if EM_DEBUG                           /* Do NOT compile if !EM_DEBUG */

extern char *print_mode_type[];
extern char *on_off_status[];
extern int em_print_mode;
extern int em_tab_size;
extern int local_edit;
extern int fg_data_only;
extern int bg_sender_in;
extern int bg_sender_out;
extern int bg_sender_buff[];
extern int dbgpkts;                    /* Debug packet flag */
extern int dbgrejs;                    /* Debug rejected packetsflag */
extern int dbgxchr;                    /* Debug extra chars flag */
extern char *buff;

db_process_options(option,terminate_flag)

/* INPUT */
   int option;

/* OUTPUT */
   int *terminate_flag;
{

/* : process special options */

   switch(option) {

/* : - sit in a tight loop until any key is pressed */
      
      case F1:
         freeze();
         break;

/* : - select a different display mode; the flag em_print_mode is used by 
       the em_put and em_print_str routines */

      case F2:
         em_print_mode = (em_print_mode + 1) % 3;
         printf ("$$ print mode = %s $$\n",
         print_mode_type[em_print_mode]);
         break;

/* : - display summary of function key functions */

      case F3:
         menu();
         break;

/* : - toggle local_edit option flag; local_edit flag is used by get_kb_line */

      case F4: 
         local_edit = !local_edit;
         printf ("$$ local edit = %s $$\n", on_off_status[local_edit]);
         break;

/* : - toggle foreground terminal data only/any foreground data;
       fg_data_only flag is used in the main emulator routine */

      case F5: 
         fg_data_only = !fg_data_only;
         printf ("$$ terminal data only = %s $$\n", on_off_status[fg_data_only]);
         break;

/* : - display the status of the background query queue */

      case F6: 
         sender_query_status();
         break;

/* : - display or set a new tab size; used by em_print_str and
       get_kb_line routines */

      case F7: 
         set_tab_size();
         break;

/* : - pass a command to the command interpreter */

      case F8: 
         execute_dos_cmd();
         break;

/* : - send a foreground break */
      
      case F9:
         puttdata(FG_BREAK,0,0);
         break;

/* : - set flag to exit the emulator */

      case F10:
         *terminate_flag = FALSE;
         break;

/* : - toggle debug packets */

      case ALT_F1: 
         dbgpkts = !dbgpkts;
         printf ("$$ DBG Show Packets = %s $$\n", on_off_status[dbgpkts]);
         break;

/* : - toggle reject packets */

      case ALT_F2: 
         dbgrejs = !dbgrejs;
         printf ("$$ DBG Diagnose Rejects = %s $$\n", on_off_status[dbgrejs]);
         break;

/* : - toggle extra character debug */

      case ALT_F3: 
         dbgxchr = !dbgxchr;
         printf ("$$ DBG Show Extraneous Receive Characters = %s $$\n", on_off_status[dbgxchr]);
         break;
   }
}

#else
db_process_options()
{}
#endif




		    dbtoggle.c                      08/07/87  1520.5rew 08/07/87  1437.3       11745



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(87-03-10,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
                                                   END HISTORY COMMENTS */

#include <ws_error.h>

#define PACKETS 125
#define REJECTS 126
#define EXTRA   127

extern int dbgpkts;
extern int dbgrejs;
extern int dbgxchr;

/* : PROCEDURE FUNCTION (toggle_debug_switches)

Toggle the debug switches packet (125), rejects (126), and extr-chars (127)
*/

toggle_debug_switches (db_switch)

int  db_switch;
{

   switch (db_switch)
   {
      case PACKETS:
         dbgpkts = !dbgpkts;
         return (0);

      case REJECTS:
         dbgrejs = !dbgrejs;
         return (0);

      case EXTRA:
         dbgxchr = !dbgxchr;
         return (0);

      default:
         return (WSERROR);
   }

   return (0);
}




		    debug.c                         08/07/87  1520.4rew 08/07/87  1437.3       15813



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-05-05,Westcott), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (sdbgnum)

Display a number directly to the screen (bypassing DOS print functions).
*/

#define LF 10
#define CR 13

static int  row = 0,
            col = 0;
static char temp[2] = " ";

sdbgnum (p_num)

int p_num;
{
char temp[32];

   sprintf(temp,"\nNUM = %x\n",p_num);
   sdbgmsg(temp);
}

/* : PROCEDURE FUNCTION (sstmsg)

Send a status message to the screen (for /g MOWSE command option)
*/

sstmsg (p_msg)

char p_msg[];
{
int  i;
char chr;

/* : Send CR/LF and a reverse video '('. */

   sdbgchr(CR);
   sdbgchr(LF);

/* : Send the message, if character is not printable convert it to octal */

   for (i = 0; p_msg[i] != '\000'; i += 1) {
      chr = p_msg[i];
      if (chr >= ' ' && chr <= '~')
         sdbgchr(chr);
      else {
         sdbgchr('\\');                     /* Escape character */
         sdbgchr(((chr>>6) & 3) + '0');     /* High order octal */
         sdbgchr(((chr>>3) & 7) + '0');     /* Med. order octal */
         sdbgchr((chr & 7) + '0');          /* Low  order octal */
      }
   }

   sdbgchr(CR);
   sdbgchr(LF);
}




		    destinst.c                      08/07/87  1520.4rew 08/07/87  1437.3       21483



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-05-09,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
     install(87-08-07,MR12.1-1072):
     Created.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (destinst)

Removes the reference to the application from the CAT, deallocates the message 
buffers, and generates a message to remove reference to the in the remote 
system's CAT.
*/

#include <dos.h>
#include <cat.h>
#include <ws_func.h>
#include <ws_dcls.h>
#include <ws_error.h>

#define NULL 0

extern int local_system;               /* Local system id */

destinst (mcb_ptr)

mcb **mcb_ptr;                         /* MCB to be destroyed */
{
int  sysid;                            /* System ID of capability */
int  cap_index;                        /* Index into CAT */
int  code;
struct destinst_param_struct param;    /* Parameter structure to i_desins */

/* : if mcb_ptr passed is NULL  return error_code = WSINVMCB */

   if (*mcb_ptr == NULL)
      return (WSINVMCB);

/* : otherwise
     - get the system id and index into the CAT table.
     - if invalid capability index or not the local system
     -- set the error code */

   sysid = (int)((*mcb_ptr) -> system_id);
   cap_index = (int)((*mcb_ptr) -> major_capability) - MIN_CAPABILITY_NUMBER;

   if (cap_index < 0 || cap_index >= NUMBER_OF_CAT_ENTRIES)
      return (WSINVMCB);
   if (sysid != local_system)
      return (WSINVMCB);

/* : Call into i_desins which accesses MOWSE data segment to let MOWSE know
     of the destruction */

   param.cap_index = cap_index;
   param.mcb_ptr = *mcb_ptr;
   if (code = call_mowse_int (I$DESTINST, &param, sizeof(param)))
      return (code);

/* : free up buffers allocated by create_instance and set mcb pointer passed 
     from caller to NULL */

   free ((*mcb_ptr) -> inalloc);
   free ((*mcb_ptr) -> outalloc);
   free (*mcb_ptr);

   *mcb_ptr = NULL;

   return (0);
}




		    disresp.c                       08/07/87  1520.4rew 08/07/87  1437.3       13707



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-07-08,Westcott), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (disresp)

Sends a "DISCONNECT_REPONSE" minor capability message to the addressed major 
capability. This message is used by the major capability to inform the caller 
whether the request has been accepted or rejected.
*/

#include <stdio.h>
#include <ws.h>
#include <wsmincap.h>
#include <ws_mcb.h>
#include <ws_error.h>

disresp (p_status, p_cap_num, p_mcb_ptr)

int p_status;                          /* WSACCEPT/WSREJECT */
int p_cap_num;                         /* Capability to send response to */
mcb *p_mcb_ptr;                        /* Caller's MCB */
{
   if ((p_status != WSACCEPT) && (p_status != WSREJECT))
      return (WSINVCON);

   if (p_mcb_ptr == NULL)
      return (WSINVMCB);

/* : Send the message out through MOWSE */

   return (execap (p_cap_num, RESPONSE_DISCONNECT, &p_status, 1, p_mcb_ptr));
}




		    disrqst.c                       08/07/87  1520.4rew 08/07/87  1437.3       12132



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-07-06,Westcott), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (disrqst)

Sends a "DISCONNECT_REQUEST" minor capability message to the addressed 
major capability. This message is used by the major capability to destroy 
the instance indicated by the major capability number.
*/

#include <stdio.h>
#include <ws.h>
#include <wsmincap.h>
#include <ws_mcb.h>
#include <ws_error.h>

disrqst(p_cap_num,p_mcb_ptr)

int p_cap_num;                           /* Capability to send request to */
mcb *p_mcb_ptr;                          /* Caller's MCB */
{
   if (p_mcb_ptr == NULL)
      return (WSINVMCB);

/* : Pass the message through MOWSE */

   return (execap (p_cap_num,REQUEST_DISCONNECT,NULL,0,p_mcb_ptr));
}




		    dtm_mows.c                      08/07/87  1520.4rew 08/07/87  1437.1       17784



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-11-07,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (dtm_mowse)

When MOWSE receives information from Multics that MOWSE on Multics is detached
then MOWSE must be cleaned up on the PC.
*/

#include <stdio.h>
#include <dos.h>
#include <mowse.h>
#include <cat.h>
#include <ws_msg.h>

extern local_cat l_cat[];              /* Currently loaded applications */
extern char      mysystem;             /* PC system id */

dtm_mowse ()
{
int  i;
struct input_msg message;              /* Terminate message to capability */

/* : For each loaded application (mcb_ptr is not NULL)
     - send TERMINATE_APPLICATION to it */

   message.source_system = mysystem;
   message.source_major  = WSMAJCAP;
   message.msg_data[0]   = 0;
   message.system        = mysystem;
   message.minor         = TERMINATE_APPLICATION;

/* For each of the capabilities which are loaded in the CAT, generate a
   terminate_application message and release the memory to the system. */

   for (i = 0; i < NUMBER_OF_CAT_ENTRIES; i++)
   {  if (l_cat[i].mcb_ptr)
      {  message.major = i + MIN_CAPABILITY_NUMBER;
         if (!(l_cat[i].flags & NULL_BIT))
         {  wsexecap (&l_cat [i], &message, sizeof (struct input_msg) - 1);
            free_cat_program (&l_cat[i]);
         }
      }
   }

/* Reinitialize the CATS */

   init_cat ();

   return (0);
}




		    em_put.c                        08/07/87  1520.3rew 08/07/87  1437.1       24705



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-08-26,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
     install(87-08-07,MR12.1-1072):
     Created.
  2) change(86-09-07,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
     install(87-08-07,MR12.1-1072):
     Tab handling.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (em_print_buff)

Displays the contents of a buffer to the display.  Tabs are expanded according 
to the position of the cursor on the screen.  The size of the tabs are 
determined by the 'em_tab_size' variable.  Three print modes exist:

    Printable ASCII only: any non-printable ascii characters.

    Octal non-printables: any non-printable ascii characters are
      displayed as 3 digit octal values preceeded by a backslash.

    Any character: all characters are displayed with the machine's
      character set.

    NOTE: the linefeed, tab, backsapce and carriage return characters
        are not treated as non-printable and are always processed.

    The print mode is determined by the variable em_print_mode.
*/ 

#include <ctype.h>
#include <keydefs.h>
#include <emulator.h>

#if EM_DEBUG                           /* Do NOT compile if !EM_DEBUG */

extern int em_print_mode;
extern int em_tab_size;

em_print_buff(data,datalen)

char *data;
int  datalen;
{
int i;

   for (i = 0; i < datalen; i++)
      em_putch(data[i]);
}

/* : PROCEDURE FUNCTION (em_putch)

See above.
*/

em_putch(ch)

int ch;
{
int x, y;
int i,pad;

   ch &= 0xff;

/* : filter and process printable control characters */

   switch (ch) {
      case CR:
      case LF:
      case BS:
         putch(ch);
         return;

      case TAB:
         get_cursor_pos(&x,&y);
         pad = em_tab_size - (y % em_tab_size);
         for (i = 0; i < pad; i++)
            putch(SPACE);
         return;

   }

/* : anything that filters through is ASCII data */

   switch(em_print_mode) {
      case ASCII_ONLY:
         if (isprint(ch))
            putch(ch);
         break;

      case NON_ASCII_OCTAL:
         if (isprint(ch))
            putch(ch);
         else
            printf("\\%03o",ch);
         break;

      case ANY_CHAR:
         putch(ch);
         break;
   }
}

#else
em_print_buff ()
{}
em_putch ()
{}
#endif




		    em_routs.c                      08/07/87  1520.3rew 08/07/87  1437.1       16182



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-07-07,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
     install(87-08-07,MR12.1-1072):
     Created.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (Push)

This routine pushes a value onto the keyboard tab stack to keep track of 
how many blanks were used to replace a particular tab.
*/

#include <keydefs.h>
#include <emulator.h>

#if EM_DEBUG                           /* Do NOT compile if !EM_DEBUG */

Push (value,kb_tstptr,kb_stack)

int  value;
int  *kb_tstptr;
char kb_stack[];
{
   if (*kb_tstptr < KB_STACKSIZE)
      kb_stack[(*kb_tstptr)++] = value;
}



/* : PROCEDURE FUNCTION (Pop)

This function pops a value off the keyboard tab stack.
*/

Pop (kb_tstptr,kb_stack)

int  *kb_tstptr;
char kb_stack[];
{
int return_value;

   if (*kb_tstptr > 0)
      return_value = kb_stack[--(*kb_tstptr)];

   return(return_value);
}

/* : PROCEDURE FUNCTION (beep)

This function causes a beep to sound.
*/

beep()
{
   putch(BELL);
}



/* : PROCEDURE FUNCTION (Screen_Erase_Char)

This function prints out a backspace on the screen that erases the previous 
character (displaying a blank in its place).
*/

Screen_Erase_Char()
{
   putch(BS);
   putch(SPACE);
   putch(BS);
}

#else
Push ()
{}
Pop ()
{}
beep ()
{}
Screen_Erase_Char ()
{}
#endif




		    emulator.c                      08/07/87  1520.3rew 08/07/87  1437.1       99333



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-06-23,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
     install(87-08-07,MR12.1-1072):
     Created.
  2) change(86-07-25,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
     install(87-08-07,MR12.1-1072):
     Modifed command line args, saves to script file
  3) change(86-08-24,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
     install(87-08-07,MR12.1-1072):
     Added menus
  4) change(86-09-07,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
     install(87-08-07,MR12.1-1072):
     Added tab handling, local editing
  5) change(86-09-11,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
     install(87-08-07,MR12.1-1072):
     DOS commands, query status
  6) change(86-09-26,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
     install(87-08-07,MR12.1-1072):
     Split emulator into two versions, a debugging
     and a non-debugging version; change the define EM_DEBUG in emulator.h
     to 0 for non-debugging version, change to 1 for debugging version
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (emulator)

Allows a user to interact through MOWSE foreground and background channels 
through a simple terminal interface.  This terminal emulator treats foreground
data as would a normal emulator.  However, to distinguish background data from 
foreground data, all background data is preceeded by a carat (^).  Thus any
background data going onto the screen will be preceeded by a carat.  Similarly, 
if keyboard input is preceed by a carat, then it will be sent to the background 
channel. No priority will be given to either channel, information that is
displayed first will be displayed.  If there are several background queries, 
then background data from the keyboard will go to each background query in
sequence.

Unless otherwise specified, all function keys may be invoked in either
packet or non-packet mode (i.e. after or before attaching to MOWSE).

F1 - debugging mode only;
     Suspend processing of terminal data; when this key is pressed
     while foreground or background data is being received and displayed,
     the emulator will sit in a tight loop, resulting in temporary
     stoppage in the handling of terminal data.  Hitting any other key
     will resume processing.

F2 - Debugging mode only. Toggle display mode; there are 3 modes:
        Printable ASCII only - only printable ascii characters except
            for the linefeed, carriage return and tab characters will
            be discarded.
        Non-printable octal - any non-printable ascii character except
            for linefeed, carriage return and tab characters will be
            displayed as a 3 digit octal value preceeded by a backslash.
            Any backslash character as terminal data will appear as
            a double backslash.
        Any character - displays all characters with character image in the
            character set of the machine

F3 - debugging mode only. Help menu.
     Summary of what function keys do, how to handle background data

F4 - debugging mode only. Toggle local editting flag;
     the flag is only used when in packet-mode.
     When local editting is enabled, pressing ESC or @ will kill and erase
     the current line of input; pressing BACKSPACE or # will erase the
     previous character and the \ key will serve to escape the @, #, ESC
     and \ keys.  With local editting disabled, key values are entered
     as straight data.

F5 - Toggle between foreground terminal data only or any foreground data;
     debugging mode only;
     By default, foreground terminal data only is enabled.

F6 - debugging mode, CTRL-]R - non-debugging mode;
     Show query status; when background queries are received by the
     emulator, they are displayed immediately but the senders' capability
     are saved in a queue until the user responds to these queries
     (by preceeding the input with the ^ character).  Thus, any data
     entered as a response to background queries will be sent to
     the earliest background query in the queue.  Once, a background
     message has been responded to, the capability is removed from the
     queue.  The F6 key will display the system id and the major
     capability of the sender of all unanswered background queries.

F7 - debugging mode only;
     Set tab size; used to change or examine the tab size.  This tab
     value determines both the amount of padding to use for displaying
     and for the tab key (i.e. it is used in both packet and non-packet
     mode).

F8 - debugging mode, CTRL-]C - non-debugging mode;
     Execute DOS command; pass a command to the command interpreter on
     the PC and resume normal terminal emulation upon completion.
     Note that the F1 key will not work since the command interpreter
     has control; however, ^S and ^Q will serve to suspend and resume
     while control is not passed back to the emulator.

F9 - debugging mode; CTRL-]B - non-debugging mode;
     Send foreground break; a foreground break is sent through the
     foreground channel.  This works only when MOWSE is attached on
     the other side.

F10 - debugging mode; CTRL-]Q - non-debugging mode;
     Exit the terminal emulator.

CTRL-]R - non-debugging mode only
     Send a query reply

CTRL-]0 - non-debugging mode only
     Send a null over the foreground channel

CTRL-]CTRL-] - non-debugging mode only
     Send a CTRL-] over the foreground channel

Local editing is always on for non-debugging version; the # functions
the same as backspace and the @ functions the same as the ESC key
which wipes out the line.  These may be escaped by the \ key.

*/

#include <ws.h>
#include <ws_dcls.h>
#include <wsmincap.h>
#include <keydefs.h>
#include <emulator.h>

#if EM_DEBUG                           /* Do NOT compile if !EM_DEBUG */

char NULLBYTE;
char *print_mode_type[] = {            /* Message strings */
   "PRINTABLE ASCII ONLY",
   "OCTAL NON-PRINTABLE ASCII",
   "ANY ASCII"
};

char *on_off_status[] = {              /* Status message strings */
   "OFF",
   "ON"
};

struct get_struc gettdatas;
char buff[KB_BUFFERSIZE];
char kb_stack[KB_STACKSIZE];
int  bg_sender_buff[BG_SENDBUFF_SIZE];
int bg_sender_in = 0;
int bg_sender_out = 0;
extern int packetize_flag;
int em_print_mode;
int em_tab_size;
int local_edit;
int fg_data_only;

em()
{

/* MISC */
   int str_len;
   int i;
   int sender_major;
   int message_type;
   int bg_query_flag;
   int j;
   int err_code;
   int option;
   int do_te_loop = TRUE;
   int delay_i;
   int ch;
   int sys;
   int major;

/* INITIALIZATION */
   str_len = 0;
   bg_query_flag = 0;

/* : set default modes */

   local_edit = TRUE;
   em_print_mode = ANY_CHAR;
   fg_data_only = TRUE;
   em_tab_size = KB_TABSIZE;

/* : initialize the structure for getting terminal data */

   gettdatas.local_buffer_pointer = &buff[0];
   gettdatas.local_buffer_size = sizeof(buff);

/* : print out terminal emulator banner and instructions */

   printf("===== MOWSE Terminal Emulator\n");
   printf("===== Hit F3 to display emulator functions.\n");

/* : While (not asked to quit by user) */

   while (do_te_loop) {

/* : - check terminal buffer for data character from the remote machine 
       and display it if it exists */

      str_len = gettdata(&gettdatas);
      if (gettdatas.minor_capability == FG_TERMINAL_DATA || !fg_data_only)
         em_print_buff(buff,str_len);

/* : - loop for a while here to allow clock interrupt time to happen */

      for (delay_i = 0; delay_i < DELAY_INTERVAL; delay_i++);

/* : - check for background messages
     - if there is background data then */

      while (gettdatas.background_pending_flag > 0) {
         err_code = getbgmes(buff, &message_type, &sender_major);

/* : -- display the data preceeded by a carat (^) */

         if (message_type == WSINFO || message_type == WSQUERY) {
            c_unpack(&sys, &major, sender_major);
            printf("^[%2d:%2d]%s\n",sys,major,buff);
         }

/* : -- if it was a query message, save sender's major in the FIFO
     --- check for queue overflow */

         if (message_type == WSQUERY) {
            if (bg_sender_out == ((bg_sender_in+1) % BG_SENDBUFF_SIZE))
               printf ("$$ query buffer overflow $$\n");
            else {
               bg_sender_buff[bg_sender_in] = sender_major;
               bg_sender_in = (bg_sender_in + 1) % BG_SENDBUFF_SIZE;
            }
         }

/* : -- decrement count of background messages left */

         gettdatas.background_pending_flag--;
      }


/* : - check for input from the user
     - if in packet-mode */

      if (packetize_flag) {

/* : -- check for a line of input from user */

         str_len = db_get_kb_line(buff, kb_stack, &option);
         if (str_len > 0) {

/* : --- if input is not preceeded by ^, destined for foreground */

            if (buff[0] != '^')
               puttdata(FG_TERMINAL_DATA,buff,str_len);

/* : --- if user wants to send input with ^ as the first character over 
         foreground, he enters ^^ and the first one is stripped, rest is 
         sent to foreground */

            else if (str_len > 1 && buff[0] == '^' && buff[1] == '^')
               puttdata(FG_TERMINAL_DATA,buff+1,str_len-1);

/* : --- data is destined for background, get the sender major off stack and 
         send back the response */

            else if (bg_sender_in != bg_sender_out) {
               buff[str_len] = '\0';
               sendqrep (buff+1,bg_sender_buff[bg_sender_out]);
               c_unpack(&sys,&major,bg_sender_buff[bg_sender_out]);
               printf ("$$ Reply sent to [%d:%d]\n", sys, major);
               bg_sender_out = (bg_sender_out + 1) % BG_SENDBUFF_SIZE;
            }
            else
               printf ("$$ No queries pending $$\n");
         }

/* : -- check if special function key was pressed */

         else if (option >= 0)
         db_process_options(option,&do_te_loop);
      }

/* : -- else in non-packet mode
     --- check if a key was pressed
     ---- check and handle any special function key
     ---- otherwise send character over foreground channel */

      else {
         if (get_kb_key(&ch)) {
            if (ch > 255)
               db_process_options(ch,&do_te_loop);
            else
               puttdata(FG_TERMINAL_DATA,&ch,1);
         }
      }
   }

/* : print message to indicate exit from terminal emulator */

   printf("\n==== MOWSE Terminal Emulator returning to DOS ====\n");
}

#else
em ()
{}
#endif




		    execap.c                        08/07/87  1520.3rew 08/07/87  1437.0       66447



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-07-05,Westcott), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
                                                   END HISTORY COMMENTS */

/* PROCEDURE FUNCTION (execap):

Sends a minor capability message to the specified major capability with the
arguments provided.
*/

#include <stdio.h>
#include <ws.h>
#include <alloc.h>
#include <ws_mcb.h>
#include <ws_error.h>
#include <ws_func.h>
#include <ws_dcls.h>
#include <wsmincap.h>

#define HEADER_LENGTH 6                /* Header information length */

extern char local_system;              /* Identity of PC system */

execap (p_major_num, p_minor_num, p_arg_ptr, p_arg_len, p_mcb_ptr)

int  p_major_num;                      /* Destination major capability number */
int  p_minor_num;                      /* Destination minor capability number */
char *p_arg_ptr;                       /* Pointer to argument data */
int  p_arg_len;                        /* Length of argument data */
mcb  *p_mcb_ptr;                       /* Pointer to application's MCB */
{
struct xcap_struc xcap;
char              *c1;
char              *c2;
char              *temp_p_arg_ptr;
int               i;
int               code;
int               copylen;
int               header_size;
struct linklst    *new_msg_portion;
struct linklst    *dead_buffer;
struct linklst    *pending_msg_buffer;
struct linklst    *pending_msg_link;
struct linklst    *portion;
struct linklst    *buffer_portion();
int j;

   code = 0;

/* Validate the mcb pointer */

   if (p_mcb_ptr == NULL)
      return (WSINVMCB);

/* Move and validate the passed arguments into the execap structure */

   xcap.system =  (p_major_num >> 8);
   if ((xcap.system != WSIBMPC) && (xcap.system != WSMULTICS))
      return (WSINVSYS);

   xcap.major = (char) (0xff & p_major_num);
   if ((xcap.major < WSMAJCAP) || (xcap.major > MAX_CAPABILITY_NUMBER - 1))
      return (WSINVNUM);

/* If there are any pending messages from the caller and the message to
   be sent is longer than on packet, then return WSBUFOVR because we can't
   have multiple long messages pending due to protocol */

   if ((p_arg_len > WSPAKSIZ) && (p_mcb_ptr -> outbuff != NULL))
      return (WSBUFOVR);

/* Copy the argument string into the structure. If the string is longer than
   the maximum packet size, then copy the first portion of the string to the
   structure, and the remainder of the string into as many buffers as are
     required to contain the entire message. */

/* Find end of buffer list */

   pending_msg_buffer = p_mcb_ptr -> outbuff;
   if (pending_msg_buffer != NULL)
       while (pending_msg_buffer->nextbuf != NULL)
          pending_msg_buffer = pending_msg_buffer -> nextbuf;
      
   pending_msg_link = NULL;
   temp_p_arg_ptr = p_arg_ptr;

/* Split the message into portions */

   while (p_arg_len >= 0)
   {  if (p_arg_len > (WSPAKSIZ - HEADER_LENGTH))
      {  copylen = WSPAKSIZ - HEADER_LENGTH;
         xcap.minor = PARTIAL_MESSAGE;
         xcap.source_system = p_minor_num;
         xcap.source_major = p_mcb_ptr->system_id;
         xcap.xcapstr[0] = p_mcb_ptr->major_capability;
         header_size = HEADER_LENGTH;
      }
      else
      {  copylen = p_arg_len;
         xcap.minor = p_minor_num;
         xcap.source_system = p_mcb_ptr->system_id;
         xcap.source_major = p_mcb_ptr->major_capability;
         header_size = 5;
         p_arg_len = -1;                                /* terminate loop */
      }

/* Copy data from user space into his message buffer space */

      new_msg_portion = 
         (struct linklst *) wsalloc (p_mcb_ptr -> outalloc, header_size+copylen+sizeof(struct linklst));
      
/* Copy header information */

      if (new_msg_portion != NULL)
      {  c1 = (char *) &xcap;
         c2 = &(new_msg_portion -> lldata[0]);
         for (i = 0; i < header_size; i++)
            c2[i] = c1[i];

/* Copy data information */

         c1 = temp_p_arg_ptr;
         for (i = 0; i < copylen; i++)
            c2[i + header_size] = c1[i];

         p_arg_len = p_arg_len - copylen;
         temp_p_arg_ptr = &(c1[i]);

/* Initialize link to hold portion of message */

         new_msg_portion->nextbuf = NULL;
         new_msg_portion->nextlink = NULL;
         new_msg_portion->linkused = copylen + header_size;


/* Insert buffer into linked list */

         if (pending_msg_buffer == NULL)              /* First in chain */
         {  p_mcb_ptr->outbuff = new_msg_portion;
            pending_msg_buffer = new_msg_portion;
            pending_msg_link = new_msg_portion;
         }
         else
         {  if (pending_msg_link == NULL)             /* Last in chain */
            {  pending_msg_link = pending_msg_buffer;
               while (pending_msg_link->nextlink != NULL)
                  pending_msg_link = pending_msg_link->nextlink;
            }
            pending_msg_link->nextlink = new_msg_portion;
            pending_msg_link = new_msg_portion;
         }
      }

/* If can't copy into message buffer space then return all buffers back to
       free queue */

      else
      {  dead_buffer = p_mcb_ptr->outbuff;
         while (dead_buffer != NULL)
         {  pending_msg_buffer = dead_buffer->nextlink;
            llpfree(p_mcb_ptr -> outalloc,&p_mcb_ptr->outbuff,dead_buffer);
            dead_buffer = pending_msg_buffer;
         }
         return (WSBUFOVR);
      }
   }

/* Extract the first portion of the message to send */

   portion = buffer_portion(p_mcb_ptr, pending_msg_buffer);
   code = call_mowse_int (I$EXECAP, portion->lldata, portion->linkused);
   wsfree (p_mcb_ptr -> outalloc, portion);
   if (code)
      llpfree (p_mcb_ptr -> outalloc, &(p_mcb_ptr -> outbuff), portion -> nextlink);
   return (code);
}

/* PROCEDURE FUNCTION (buffer_portion)

Extract a portion of a message from the head of the pending portion queue.
*/

struct linklst *buffer_portion(p_mcb_ptr, p_buffer)

mcb *p_mcb_ptr;
struct linklst *p_buffer;
{
struct linklst *portion;
struct linklst *msg_buffer_prev;

/* If p_mcb_ptr is null then return */

   if (p_mcb_ptr == NULL)
      return(NULL);

/* If buffer is null then return */

   if (p_buffer == NULL)
      return(NULL);

/* Get portion of buffer to send */

   portion = p_buffer;

/* Fix up chain from which portion was taken */

   msg_buffer_prev = p_mcb_ptr->outbuff;
   if (msg_buffer_prev == NULL)
      return(NULL);

/* Search for either an equality to the current buffer, or NULL which signals
   the trailing end of the message. */

   while (msg_buffer_prev->nextbuf != p_buffer)
      if ((msg_buffer_prev = msg_buffer_prev->nextbuf) == NULL)
         break;

   if (msg_buffer_prev == NULL)
      p_mcb_ptr->outbuff = p_buffer->nextlink;
   else
   {  msg_buffer_prev->nextbuf = p_buffer->nextlink;
      p_buffer->nextlink->nextbuf = p_buffer->nextbuf;
   }

   return(portion);
}    




		    execom.c                        08/07/87  1520.3rew 08/07/87  1437.0       17100



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-04-04,ASmith), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (execom)

Performs the execution of a command on either the remote or local systems.
*/

#include <stdio.h>
#include <ws.h>
#include <ws_mcb.h>
#include <ws_error.h>
#include <ws_func.h>
#include <ws_dcls.h>

extern char local_system;

execom (p_command, p_ws_system, p_cmd_id, p_mcb_ptr)

char *p_command;                       /* Command to execute */
int p_ws_system;                       /* System to execute on */
unsigned *p_cmd_id;                    /* Command id */
mcb *p_mcb_ptr;                        /* Caller's MCB */
{
struct execom_struc param;


   if ((p_ws_system != WSLOCAL) && (p_ws_system != WSREMOTE))
      return(WSINVSYS);

   if (p_mcb_ptr == NULL) 
      return(WSINVMCB);

   param.com_len = strlen(p_command);
   if (param.com_len > WSPAKSIZ)
      return (WSINVBUF);
   strcpy(&param.command[0],p_command);

   if (p_ws_system == WSLOCAL) 
      p_ws_system = local_system;
   else if (p_ws_system == WSREMOTE) 
      p_ws_system = WSMULTICS;

   param.system = p_ws_system;
   param.major = p_mcb_ptr->major_capability;

   call_mowse_int(I$EXECOM,&param,sizeof(param));

/* : Return p_command id and status */

   *p_cmd_id = param.cmd_id;
   return(param.status);
}




		    exitmows.c                      08/07/87  1520.3rew 08/07/87  1436.9       29097



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-08-12,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
  2) change(86-08-27,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Modified error display.
  3) change(87-01-22,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Added /F(orce) option.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION

Destroy the MOWSE environment on the PC if Multics has detached (dtm).

Arguments:

   /F - (Force) destruction whether or not Multics has detached.
*/

#include <stdio.h>
#include <ws_error.h>
#include <ws_func.h>

#define EXTRA_ARG   -1                 /* Unexpected argument */
#define BAD_ARG     -2                 /* Invalid argument */

#define TIME_OUT        1              /* Disconnect timed out */
#define DISCONNECT_OUT  2              /* Disconnect verified */

#define FORCE        0x01              /* Force requested */

main (argc, argv)

int  argc;                             /* Argument count */
char *argv[];                          /* Argument strings */
{
int  code;                             /* Error code */
int  i;
char flag;                             /* Force flag */

/* INITIALIZATION */

/* : Parse through the arguments */

   for (i = 1, code = 0, flag = 0; (i < argc) && (!code); i++)
   {  if (argv[i][0] != '/')
         code = BAD_ARG;
      else switch (argv[i][1])
      {  
         case 'F': case 'f':           /* FORCE */
            if (argv[i][2])
               code = BAD_ARG;
            else
               flag |= FORCE;
            break;

         default:                      /* ERROR */
            code = BAD_ARG;
            break;
      }
   }

/* : Call mowse_interrupt to disconnect mowse */

   if (!code)
   {  printf ("EXITMOWS ...");
      while ((code = call_mowse_int (I$DISCONNECT, &flag, 1)) == WSDISPEN);
      if (code == DISCONNECT_OUT)
         code = WSACTIVE;
      else if (code == TIME_OUT)
      {  flag = FORCE;
         code = call_mowse_int (I$DISCONNECT, &flag, 1);
      }
   }


/* : Parse the error codes */

   switch (code)
   {
      case BAD_ARG:
         printf ("exitmows: bad argument %s.", argv[i-1]);
         break;

      case EXTRA_ARG:
         printf ("exitmows: unexpected option %s.", argv[i-1]);
         break;

      case 0:
         printf (" MOWSE terminated.");
         break;

      case WSACTIVE:
         printf (" MOWSE is not detached on Multics.");
         break;

      case WSNOTACT:
         printf (" MOWSE is not resident.");
         break;

      default:
         printf (" error %d.", code);
         break;
   }
}




		    exitmows.mak                    08/07/87  1522.9rew 08/07/87  1246.0        4077



#  BEGIN MAKEFILE: EXITMOWS.MAK
#
#  Created June 29, 1986 by Flegel
#  Makefile for compose using MICROSOFT MAKE
#   MACROS
#
#  EXITMOWS
#
exitmows.obj: exitmows.c ws_error.h
        lc1 exitmows.c -d -n32 -i\lc\
        lc2 exitmows.q
        
 
exitmows.com: exitmows.obj mowslib.lib
        link \lc\c\c exitmows,exitmows,exitmows,MOWSLIB+\lc\s\lc/map
        exe2bin exitmows exitmows.com
        del exitmows.exe

#   END MAKEFILE: EXITMOWS.MAK




		    external.c                      08/07/87  1520.2rew 08/07/87  1436.9       42939



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-11-11,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (external)

Examine the application's message in MOWSE's address space to reset appropriate
flags (stored in MOWSE data space).
*/

#include <stdio.h>
#include <dos.h>
#include <wsmincap.h>
#include <cat.h>
#include <ws_msg.h>
#include <ws_error.h>

#define MESSAGE_HEADER_LENGTH 5

extern char mysystem;
extern local_cat l_cat[];
extern remote_cat r_cat[];

external_mowse (p_cat, p_message, p_message_len)

local_cat *p_cat;                      /* Pointer to applciation cat entry */
char *p_message;                       /* Message */
int  p_message_len;                    /* Length of message */
{
struct input_msg *message;

   message = (struct input_msg *) p_message;

/* : Switch to the appropriate handler for each minor */

   switch (message -> minor)
   {
      case TERMINATE_APPLICATION:

         return (extern_terminate (p_cat, message, p_message_len));

      case RESET_APPLICATION:

         return (extern_reset (p_cat, p_message, p_message_len));

      case SUSPEND_APPLICATION:

         return (extern_suspend (p_cat, p_message, p_message_len));

      case RESUME_APPLICATION:

         return (extern_resume (p_cat, p_message, p_message_len));

      default:

         return (wsexecap (p_cat, p_message, p_message_len));
   }
}
/**/
/* : PROCEDURE FUNCTION (extern_reset)

Perform the operations necessary to handle resetting the application.
*/

extern_reset (p_cat, p_message, p_message_len)

local_cat *p_cat;
struct input_msg *p_message;
int p_message_len;
{
struct input_msg message;

/* : Pass the message on to the application */

   wsexecap (p_cat, p_message, p_message_len);

/* : Send the reset reply to the source only if it is from a remote system */

   if (p_message -> source_system == mysystem)
   {  p_cat -> flags &= ~RESET_BIT;
      return (0);
   }

   message.system        = WSMULTICS;
   message.major         = WSMAJCAP;
   message.minor         = RESET_REPLY;
   message.source_system = mysystem;
   message.source_major  = p_message -> major;
   message.msg_data[0]   = 0;

   return (send_i_mess (&message, MESSAGE_HEADER_LENGTH, NULL, 0));
}
/**/
/* : PROCEDURE FUNCTION (extern_suspend)

Perform the operations necessary to suspending the application.
*/

/* : NOTES

POTENTIAL PROBLEM:  if a suspended application is refused messages then
a calling application which is not aware of this will not see an answer
until this is resumed.
*/

extern_suspend (p_cat, p_message, p_message_len)

local_cat *p_cat;                      /* CAT entry of application */
struct input_msg *p_message;           /* Message */
int  p_message_len;                    /* Length of message */
{
int major_sender;

/* : Set the suspend bit in the flags */

   p_cat -> flags |= SUSPENDED_BIT;

/* : Send the message on to the application */

   return (wsexecap (p_cat, p_message, p_message_len));
}
/**/
/* : PROCEDURE FUNCTION (extern_resuem)

Perform the operations necessary to resuming the application.
*/

/* : NOTES

POTENTIAL PROBLEM:  if a suspended application is refused messages then
a calling application which is not aware of this will not see an answer
until this is resumed.
*/

extern_resume (p_cat, p_message, p_message_len)

local_cat *p_cat;                      /* CAT entry of application */
struct input_msg *p_message;           /* Message */
int  p_message_len;                    /* Length of message */
{
int major_sender;

/* : Set the suspend bit in the flags */

   p_cat -> flags &= ~SUSPENDED_BIT;

/* : Send the message on to the application */

   return (wsexecap (p_cat, p_message, p_message_len));
}
/**/
/* : PROCEDURE FUNCTION (extern_terminate)

Perform the operations necessary to terminating the application.
*/

extern_terminate (p_cat, p_message, p_message_len)

local_cat *p_cat;                      /* CAT entry of application */
struct input_msg *p_message;           /* Message */
int  p_message_len;                    /* Length of message */
{

   p_cat -> flags |= MCB_TERMINATE;
   p_cat -> flags &= ~MCB_SUSPEND;

   return (wsexecap (p_cat, p_message, p_message_len));
}




		    findname.c                      08/07/87  1520.2rew 08/07/87  1436.9       19512



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-05-06,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
     install(87-08-07,MR12.1-1072):
     Created.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (findname)

Find the name of a capability given its major capability number.  The 
code for this routine sits in the application's memory space and simply 
passes its parameters to the internal mowse interrupt routine which finds 
and returns the return code and capability name.
*/

#include <dos.h>
#include <cat.h>
#include <ws_dcls.h>
#include <ws_func.h>

#define NULL 0

extern char local_system;              /* Local system ID */

findname (p_capability_number, p_capability_name)

int  p_capability_number;              /* Capability number to find */
char *p_capability_name;               /* Name of found capability */
{
struct findname_param_struct param;    /* parameter structure for user interrupt */
int code;                              /* return code from user interrupt */
char *s1;                              /* pointer to source string */
char *d1;                              /* pointer to destination string */
int i;                                 /* counter for copy */

   param.major_capability_number = p_capability_number;

/* : call the mowse interrupt routine for finding capability name
     - if the capability name was found
     -- copy capability name into caller's buffer */

   code = call_mowse_int (I$FINDNAME, &param, sizeof(param));
   if (code)
      return (code);

   s1 = &(param.capability_name[0]);
   d1 = p_capability_name;
   for (i = 0; i < CAPABILITY_NAME_LENGTH; i++) {
      *d1++ = *s1++;
   }

   return(0);
}




		    findnumb.c                      08/07/87  1520.2rew 08/07/87  1436.9       19359



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-05-10,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
     install(87-08-07,MR12.1-1072):
     Created.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (findnumb):

Find the major capability number of an application given a capability name.
*/

/* : RETURNS

     0, if major capability number found
     WSINVNAM, if major capability number not found
     WSINVSYS, if the system id is not valid.
*/

#include <dos.h>
#include <cat.h>
#include <ws_dcls.h>
#include <ws_func.h>

#define LOW_8_BITS  0x00FF

findnumb (capability_name,system_id ,major_capability_number)

char *capability_name;                 /* Name of capability to find */
int  system_id;                        /* Id of system to find capability on */
int  *major_capability_number;         /* Address of retrun value for capability number */
{
struct findnumb_param_struct param;    /* structure for user interrupt call */
int  code;                             /* return code */
int  cap_num;                          /* major capability extracted from major_capability */

/* : create major capability number, where system id occupies high 8 bits, 
     major_number low 8 bits */

   cap_num = *major_capability_number & LOW_8_BITS;
   param.major_capability_number = (system_id << 8) | cap_num;

/* : call the mowse interrupt routine to find the capability number */

   strncpy (param.capability_name, capability_name, CAPABILITY_NAME_LENGTH);
   if (code = call_mowse_int (I$FINDNUMB, &param, sizeof(param)))
      return (code);

   *major_capability_number = param.major_capability_number;

   return(0);
}

/* : END findnumb */




		    freeprog.asm                    08/07/87  1521.0rew 08/07/87  1438.5       36450



; ***********************************************************
; *                                                         *
; * Copyright, (C) Honeywell Bull Inc., 1987                *
; *                                                         *
; * Copyright, (C) Honeywell Information Systems Inc., 1986 *
; *                                                         *
; ***********************************************************

; HISTORY COMMENTS:
;  1) change(87-04-30,Flegel), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Created.
;                                                      END HISTORY COMMENTS

;/* : PROCEDURE FUNCTION (free_program)
;
; Release the memory occupied by a program which is resident.  This consists
; of releasing the environment block and the program block of memory.
;
; Environment memory block paragraph:  [PSP + 2Ch]
; Program memory block paragraph:      CS
;
; Arguments:  ES - CS of program
; Returns:    ax - error code from DOS free function (49h)
;*/

include dos.mac          ;Lattice include file
include xoscall.mac      ;Bios and Dos Call macros
include ws.mac           ;MOWSE definitions
include cat.mac          ;CAT structure

env_addr equ 2Ch         ; location of address of environment string on PSP

page
;*****************************************************************************
;                                       DATA
;*****************************************************************************
dseg

;------- External Declarations -----------------------------------------------

;------- Public Declarations -------------------------------------------------

public  free_program
public  free_cat_program

endds

page
;*****************************************************************************
;                               Program mainline
;*****************************************************************************
pseg

free_program proc near

; Free environment block

        push    ES                       ; ES = CS of program

        mov     ax,ES:[env_addr]         ; ax = environment block segment
        mov     ES,ax                    ; argument in ES

        mov     ah,49h
        xor     al,al
        int     21h                      ; free environment block

        cmp     ax,7                     ; error on free (destroyed block) ?
        je      error_return             ;  YES - return
        cmp     ax,9                     ; error on free (invalid block) ?
        je      error_return             ;  YES - return

; Free program block

        pop     ES                       ; Get ES = CS again
        push    ES

        mov     ah,49h
        xor     al,al
        int     21h                      ; free program memory

        cmp     ax,7                     ; error on free (destroyed block) ?
        je      error_return             ;  YES - return
        cmp     ax,9                     ; error on free (invalid block) ?
        je      error_return             ;  YES - return

        xor     ax,ax                    ; All worked, no error

error_return:
        pop     ES
        ret

free_program endp

;/* : PROCEDURE FUNCTION (free_cat_program)
;
; Release the memory occupied by a program which is resident.  This consists
; of releasing the environment block and the program block of memory.
;
; Arguments:  CAT pointer of program to be terminated
; Returns:    ax - error code from DOS free function (49h)
;*/

free_cat_program proc near

        push    bp                       ; save registers
        mov     bp,sp
        push    ES
        push    bx

        mov     bx,[bp+4]                ; bx = CAT pointer
        mov     ax,csreg[bx]             ; ax = CS of program
        mov     ES,ax                    ; argument in ES
        call    free_program             ; free application memory

        pop     bx
        pop     ES                       ; restore registers
        pop     bp
        ret

free_cat_program endp

endps
        end




		    getbgmes.c                      08/07/87  1520.2rew 08/07/87  1436.9       18378



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-07-06,Westcott), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
                                                   END HISTORY COMMENTS */


/* : PROCEDURE FUNCTION (getbgmes)

Retrieves a background message from the MOWSE background message queue. 
A background message is one which is sent to the foreground application by 
a background application.  There are two types of background messages, those 
that do require a response (WSINFO), and those that require a response 
(WSQUERY) from the foreground application.
*/

#include <dos.h>
#include <ws.h>
#include <ws_dcls.h>
#include <ws_func.h>

getbgmes (p_string, p_type, p_sender_major)

char *p_string;                        /* Message */
int *p_type;                           /* Type of message */
int *p_sender_major;                   /* Sender of message */
{
int code;
int i;
char *c1;
char *c2;
struct gbgmsg_struc gbgmsgs;

/* : call user_interrupt to get data returning on any errors */

   gbgmsgs.bg_type = 0;  /* ask for any background message, except status */
   code = call_mowse_int (I$GETBGMES,&gbgmsgs,sizeof(gbgmsgs));
   if (code)
      return (code);

/* : copy the message into the caller's buffer and
     set the last position in buffer to null. */

   c1 = &gbgmsgs.bgmsg[0];
   c2 = p_string;
   for (i= 0; i<gbgmsgs.length; i++)
      *c2++ = *c1++;

   *c2 = '\0';

/* : return the message type and sender major to the caller */

   *p_type = gbgmsgs.bg_type;
   *p_sender_major = gbgmsgs.sender_major;

   return(0);
}




		    getkbkey.c                      08/07/87  1520.2rew 08/07/87  1436.8       10512



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-08-22,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
     install(87-08-07,MR12.1-1072):
     Created.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (get_kb_key)

returns 0 if no key was pressed
returns 1 if a key was pressed; the value of the key will be
   placed in 'ch'; an extended ASCII character code is encoded
   by adding 256
*/

#include <emulator.h>

#if EM_DEBUG

get_kb_key (ch)

int *ch;
{
   if (!kbhit()) 
      return(0);
   *ch = getch();

/* : if extended character, added 256 to next character */

   if (*ch == 0 && kbhit())
      *ch = 0x100 | getch();
   return(1);
}
#else
get_kb_key ()
{}
#endif




		    getkblin.c                      08/07/87  1520.2rew 08/07/87  1436.8       67977



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-07-23,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
     install(87-08-07,MR12.1-1072):
     Created.
  2) change(86-07-24,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
     install(87-08-07,MR12.1-1072):
     added function key handling
  3) change(86-08-22,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
     install(87-08-07,MR12.1-1072):
     passed all function key handling to call routine;
     a -1 is returned if a function key was pressed and the parameter 'option'
     will contain the key pressed for the special function.
  4) change(86-09-07,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
     install(87-08-07,MR12.1-1072):
     added local editing
                                                   END HISTORY COMMENTS */


/* : PROCEDURE FUNCTION (get_kb_lin)

If data exists in the keyboard buffer, this routine will echo
the data and wait for additional data until a carriage return is
entered; the line entered will be passed back and the length of
the line is returned.  If nothing exists in the keyboard buffer,
this routine just returns 0.  If a function key press was detected,
a -1 is returned and the value of the function key press is put in
the parameter 'option'.  While in this routine, the user may use
the backspace key to erase the previous character entered.  If the
entire line is erased, the routine will return immediately with the
value 0. (This allows the emulator in the main loop to poll for
foreground data again.)  The local_edit flag determines whether
the \, @, # and ESC keys have special editing functions.  If
local_edit is TRUE, ESC and @ will kill the entire line, # will also
serve as a backspace and the \ serves to escape all four keys.
If the local_edit key is FALSE, all characters will be passed back
unchanged.  Note that tabs will expand when the tab key is pressed
(according to the size in em_tab_size) but the tab character is passed
back to the caller unaltered.

*/

#include <ctype.h>
#include <ws.h>
#include <keydefs.h>
#include <emulator.h>

extern int bg_sender_stack[NUMBER_OF_CAT_ENTRIES];
extern int packetize_flag;
extern int em_tab_size;

get_kb_line(kb_buffer,kb_stack,option)

char kb_buffer[];
char kb_stack[];
int *option;
{
int done = 0;
int ch, buff_char;
int i, counter;
int kb_index = 0;
int kb_posit = 0;
int kb_tstptr = 0;
int hidden_pos = 0;

/* : initialize function key value and buffer */

   *option = -1;
   *kb_buffer = '\0';

/* : loop unconditionally */

   while (1) {

/* : if a key was pressed, process that character
     - filter special characters if in local edit mode */

      if (get_kb_key(&ch) && ch < 256) {
         switch (ch) {
            case '#': 
               ch = BS;
               break;

            case '@': 
               ch = DEL_LINE;
               break;

            case ESC: 
               ch = DEL_LINE;
               break;

/* : -- handle escaping of special characters
     --- '\' pressed, wait for another key
     --- if not function key or special character put '\' in buffer and pass 
         new key on otherwise discard '\' and pass new key on */

            case '\\':
               while(!get_kb_key(&ch) && ch < 256);

               if (ch != '#' && ch != CTRL_S && ch != '@' && ch != ESC && ch != '\\') {
                  if (kb_index < KB_BUFFERSIZE) {
                     kb_buffer[kb_index++] = '\\';
                     kb_posit++;
                     putch('\\');
                  }
                  else 
                     beep();
               }
               break;
         }

         switch (ch) {

/* : -- handle carriage return pressed
     --- terminate line with a linefeed
     --- return the length of keyboard input */

            case CR:
               kb_buffer[kb_index++] = LF;
               putch(LF);
               putch(CR);
               return(kb_index);

/* : -- handle backspace
     --- if something in keyboard buffer
     --- else nothing in keyboard buffer, return to allow scanning of 
         incoming data */

            case BS:
               if (kb_index > 0) {
                  buff_char = kb_buffer[--kb_index];
                  if (buff_char == TAB) {
                     counter = Pop (&kb_tstptr,kb_stack);
                     for (i = 0; i < counter; i++)
                        Screen_Erase_Char();
                  }
                  else 
                     Screen_Erase_Char();
               }
               else 
                  return(0);
               break;

/* : -- wipe out entire line and return(0)
     --- for each character entered */

            case DEL_LINE:
               while (kb_index > 0) {
                  buff_char = kb_buffer[--kb_index];
                  if (buff_char == TAB) {
                     counter = Pop (&kb_tstptr,kb_stack);
                     for (i = 0; i < counter; i++)
                        Screen_Erase_Char();
                  }
                  else 
                     Screen_Erase_Char();
               }
               return(0);

/* : -- handle local escape sequences */

            case CTRL_RSB:
               while(!get_kb_key(&ch) && ch < 256);
               switch (ch) {
                  case 'B':
                  case 'b':
                     *option = OP_BREAK;
                     return(-1);

                  case 'C':
                  case 'c':
                     *option = OP_EXEDOSCMD;
                     return(-1);

                  case 'R':
                  case 'r':
                     *option = OP_BG_REPLY;
                     return (-1);

                  case 'Q':
                  case 'q':
                     *option = OP_EXIT;
                     return(-1);

                  case '0':
                     kb_buffer[kb_index++] = 0;
                     kb_posit++;
                     putch(0);
                     break;

                  case CTRL_RSB:
                     kb_buffer[kb_index++] = CTRL_RSB;
                     kb_posit++;
                     putch(CTRL_RSB);
                     break;
               }
               break;

/* : -- handle tabs */

            case TAB:
               if (kb_index < KB_BUFFERSIZE) {
                  kb_buffer[kb_index++] = TAB;
                  counter = em_tab_size - (kb_posit % em_tab_size);
                  kb_posit += counter;
                  Push (counter,&kb_tstptr,kb_stack);
                  for (i = 0; i < counter; i++)
                     putch(' ');
               }
               else 
                  beep();
               break;

/* : -- handle normal keyboard character */

            default:
               if (kb_index < KB_BUFFERSIZE) {
                  kb_buffer[kb_index++] = ch;
                  kb_posit++;
                  putch(ch);
               }
               else 
                  beep();
         }
      }
        
/* : - else if keyboard buffer empty, return to allow scanning of incoming 
       data */

      else if (kb_index <= 0) 
         return(0);
   }
}




		    getmcbv.c                       08/07/87  1520.2rew 08/07/87  1436.8       18495



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-05-09,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
     install(87-08-07,MR12.1-1072):
     Created
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (get_mcb_values)

get the major capability number and capability name from the mcb in the 
application's memory space given a pointer to a local cat entry
*/

#include <dos.h>
#include <cat.h>
#include <ws_error.h>

#define NULL 0

extern local_cat l_CAT[];

get_mcb_values (l_cat_ptr, entry_name, entry_number)

local_cat *l_cat_ptr;                  /* Local CAT table */
char *entry_name;                      /* Name of entry */
int *entry_number;                     /* Number of entry */
{
int  data_segment;
char *segment_offset;

/* : if the cat pointer is valid then
     - get the data segment of the mcb in the cat entry
     - if the mcb pointer in the cat entry is valid then
     -- copy the value of the major capability from the mcb
     -- copy the value of the capability name from the mcb
     -- set code to no error and return */

   if (l_cat_ptr != NULL) {
      data_segment = l_cat_ptr->sregs.ds;
      if (l_cat_ptr->mcb_ptr != NULL) {
         segment_offset = (char *) &(l_cat_ptr->mcb_ptr->major_capability);
         peek (data_segment, segment_offset, entry_number, sizeof(int));
         segment_offset = l_cat_ptr->mcb_ptr->capability_name;
         peek (data_segment, segment_offset, entry_name, CAPABILITY_NAME_LENGTH);
         return(0);
      }
      else
         return(WSINVMCB);
   }
   else
      return(WSINVNUM);
}




		    getstat.c                       08/07/87  1520.1rew 08/07/87  1436.8       30456



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-07-12,Westcott), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
  2) change(86-12-10,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Numerous minor changes to get it to work.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (getstat)

Sends a message to the specified background application requesting status.
*/

/* : NOTES

This routine will loop while waiting for a reply and can therefore only be 
called by a foreground application.
*/

#include <dos.h>
#include <ws.h>
#include <ws_msg.h>
#include <ws_dcls.h>
#include <ws_func.h>
#include <ws_error.h>
#include <wsmincap.h>

#define  POLL_TIMER   4000

getstat (p_major_num, p_status_request, p_status_reply)

int  p_major_num;                        /* Capability number to get status from */
char *p_status_request;                  /* Request string */
char *p_status_reply;                    /* Reply string */
{
int code;                              /* return code */
int i;                                 /* loop counter*/
int system;                            /* System of destination */
int major;                             /* Major index of destination */
int msg_len;                           /* Length of status request */
char *s1;                              /* pointer to source string for copy */
char *d1;                              /* pointer to destination string for copy */
struct packet_msg msg;                 /* structure for message */
struct gbgmsg_struc smsg;              /* status reply structure */

/* : copy reply string to mowse buffer and extract destination system and cap */

   msg_len = stccpy (msg.msg_data, p_status_request, WSPAKSIZ);
   c_unpack (&system, &major, p_major_num);

   msg.system = (char)(system);
   msg.major = (char)(major);
   msg.minor = GET_STATUS;
   msg.source_system = WSIBMPC;
   msg.source_major = WSMAJCAP;

/* : call user_interrupt to send data afet getting the length of the message
     (128 is the number of chars in the data field, 2 removes the address 
     overhead) */

   msg_len = msg_len + sizeof (struct packet_msg) - 128 - 2;
   if (code = call_mowse_int (I$SENDBG, &msg , msg_len))
      return (code);

/* : Now ask MOWSE to give us the status message when it arrives. This involves 
     looping in a request loop for status. In order to allow MOWSE interrupts, 
     there is a "do nothing" loop. */

   smsg.bg_type = STATUS_REPLY;
   code = WSNOMESS;
   while (code == WSNOMESS) {
      for (i = 0; i < POLL_TIMER; i++);
      code = call_mowse_int (I$GETBGMES, &smsg , sizeof (struct gbgmsg_struc));
   }

/* : Copy reply status back to caller's buffer */

   s1 = smsg.bgmsg;
   d1 = p_status_reply;
   for (i= 0; i < smsg.length; i++)
      *d1++ = *s1++;

   *d1++ = 0;

   return(0);
}




		    gettdata.c                      08/07/87  1520.1rew 08/07/87  1436.7       15201



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-01-01,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
  2) change(86-01-20,ASmith), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Documentation and added call to getc_buff
     and allocated space for unions.
  3) change(86-05-26,Westcott), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Support call to call_mowse_int.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (gettdata)

Copies a number of characters from the display buffer (the buffer containing 
information to be displayed on the screen) to a user specified buffer 
*/

#include <dos.h>
#include <ws.h>
#include <ws_dcls.h>
#include <ws_func.h>

gettdata (p_buffer_ptr)

struct get_struc *p_buffer_ptr;
{
int length;

/* : call user_interrupt to get data */

   length = call_mowse_int (I$GETTDATA,p_buffer_ptr,sizeof(struct get_struc));

/* : set the last position in buffer to null and return the number of 
     characters read. */

   if (length >= 0)
      *(p_buffer_ptr->local_buffer_pointer + length) = '\0';

   return(length);
}




		    hard_int.asm                    03/15/88  1602.0rew 03/15/88  1545.9       70245



; ***********************************************************
; *                                                         *
; * Copyright, (C) Honeywell Bull Inc., 1987                *
; *                                                         *
; * Copyright, (C) Honeywell Information Systems Inc., 1986 *
; *                                                         *
; ***********************************************************

PAGE 55,132
; HISTORY COMMENTS:
;  1) change(85-12-18,Flegel), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Created.
;  2) change(86-01-30,Flegel), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Handle 4 types of interrupts: receive data,
;      transmit holding empty, break character/framing error, change in modem
;      status.
;  3) change(86-04-26,Westcott), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Installed circular input buffer (inbuff) to
;      store error messages.
;  4) change(86-08-29,Flegel), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Check line status for DR (data ready) when
;      done current interrupt.
;  5) change(86-09-12,Flegel), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Removed calls to stack alteration routines and
;     left interrupts masked in order to provide faster service to comm line
;     thus removing numerous line overrun errors on the line.
;  6) change(88-01-27,Flegel), approve(88-02-29,MCR7853),
;     audit(88-03-10,Nakaska):
;     Added test in MODEM interrupt section to look for a delta_CTS so that
;     transmitting will begin when a modem connection completes a dial-up
;     and CTS is finally raised.
;                                                      END HISTORY COMMENTS

; PROCEDURE FUNCTION (hardware_interrupt_handler):
;
; Handle all hardware interrupts which are generated by the RS232 port (pass
; control to message handler).

; NOTES:
;
; ES register will be set to contain the DS of the routine which was
; interrupted.

include dos.mac                 ; Lattice include file
include mowsdefs.mac            ; Assembler Definitions
include rs232err.mac            ; Error definitions
include wsmincap.mac            ; Predefined mincaps
include ws_buf.mac              ; Circular buffer definitions
include util.mac                ; macros for saving registers

page
;**************************************************************
;                                       DATA
;**************************************************************
dseg

;--------- External Declarations

extrn transmit_active:word
extrn COM_PORT:word
extrn send_buffer:word

;--------- Structures

dbgs    struc                          ; Debugging structure
old_bp  dw     ?
dbgret  dw     ?
arg1    dw     ?
dbgs    ends

endds

page
;**************************************************************
;                                       MAIN
;**************************************************************
pseg

;-------- External Procedures
extrn   packet_mode:word
extrn   data_seg:word                  ; MOWSE data segment
extrn   put_inbuff:near
extrn   RS232_OUT:near

;-------- Publics

public  sdbgchr
public  hardware_interrupt_handler

hardware_interrupt_handler proc near

        push    ax                     
        push    ds                     ; save interrupted DS register
        SAVEALL                        ; save all registers (except ax)
        mov     ds,CS:data_seg         ; swap in MOWSE's DS

; /* Get interrupt identification

        mov     dx,IIR
        add     dx,COM_PORT
        in      al,dx

; If break character interrupt (BI)
;     - Read LSR to reset interrupt

process_int:
        and     al,MASKBREAK
        cmp     al,LSR_LSTATUS
        jne     test_rcv

break_int:
        push    ax
        mov     dx,LSR                 ;Read the LSR to reset the interrupt
        add     dx,COM_PORT
        in      al,dx
        shr     al,1
        and     al,0fh                 ; mask non_error bits
        mov     ah,LINE_STATUS         ; store LSR error
        call    put_inbuff
        pop     ax
        jmp     done_int

; Else if Data ready (DR)
;      - get character
;      - if (char = ESCAPE_STATUS or LINE_STATUS) escape the character
;        (this is necessary for recording errors received)
;      - store char in buffer

test_rcv:
        cmp     al,LSR_RCV
        jne     sending_int

        mov     dx,RBR                 ;Receive buffer
        add     dx,COM_PORT
        in      al,dx                  ;the char in al

        xor     ah,ah
        cmp     al,ESCAPE_STATUS
        ja      rcv_ok                 ; if received a reserved byte

        cmp     al,LINE_STATUS
        jb      rcv_ok

        mov     ah,ESCAPE_STATUS

rcv_ok:
        call put_inbuff
        jmp  done_int

; Else if transmit holding register clear (THRE)
;      - If character in send buffer, transmit the character

sending_int:
        cmp     al,LSR_THRE
        jne     modem_int

        push    ax

delta_cts_send:                        ; From modem interrupt

        get_buf send_buffer            ; get another character from send buffer
        jnc     done_trans             ; if send buffer empty

        call    RS232_OUT              ; send the character
        pop     ax
        jmp     done_int

; - Else clear transmit active flag

done_trans:
        mov     transmit_active,0
        pop     ax
        jmp     done_int

; Else if Modem error (OE | PE | FE)
;      - Read MSR to reset interrupt
;      - Store the status character into receive buffer

modem_int:
        cmp     al,MASKMCHNG
        jne     done_int

; What happened on the modem

        push    ax
        mov     dx,MSR                 ;Read the MSR to reset the interrupt
        add     dx,COM_PORT
        in      al,dx
        and     al,0fh                 ; mask non_error bits

; If it was a delta CTS and CTS went high, then try and send data

        test    al,00000001b           ; Delta CTS (change in CTS) ?
        je      no_delta_cts           ;  NO - an error

        test    al,MSRCTS              ; Clear to send?
        jne     delta_cts_send         ; YES - try and send something

no_delta_cts:

        mov     ah,MODEM_STATUS
        call    put_inbuff             ; store modem status
        pop     ax

; Check the IIR if there is a pending interrupt

done_int:
        mov     dx,IIR                 ;IIR register
        add     dx,COM_PORT
        in      al,dx
        test    al,IIR_PENDING         ; test pending flag
        jne     test_dr
        jmp     process_int

; Check DR from the LSR

test_dr:
        mov     dx,LSR
        add     dx,COM_PORT
        in      al,dx
        test    al,1
        je      finished_int
        jmp     process_int

; Signal 8259 that we are done

finished_int:
        mov     al,MASKEOI             ;Non-Specific EOI (end-of-interrupt)
        out     OMR8259,al             ;Send it out port 20h ie 8259 INT CON

        RESTOREALL                     ; restore all registers (except ax)
        pop     ds
        pop     ax
        iret

;END hardware_interrupt_handler

hardware_interrupt_handler endp


; INTERNAL PROCEDURE FUNCTION (sdbgchr):
;
; Write debug char to screen

sdbgchr proc near
        push    bp
        mov     bp,sp
        mov     ax,arg1[bp]
        mov     ah,0Eh          ;Force character to screen function
        and     al,7fh          ;ensure highlight bit is off
        xor     bx,bx
        int     10h             ;send char to screen
        pop     bp
        ret

sdbgchr endp
        endps
        end




		    i_con.c                         08/07/87  1520.1rew 08/07/87  1436.7       21240



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-10-21,ASmith), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
  2) change(86-10-29,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Reduced to a simple send message to the
     appropriate internal MOWSE on the necessary system.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (i_connect)

Generate a message to the appropriate system for connect request.
*/

#include <dos.h>
#include <stdio.h>
#include <ws_msg.h>
#include <wsmincap.h>
#include <cat.h>
#include <ws_dcls.h>

#define INTERNAL         32            /* MOWSE's capability number */
#define HEADER_LENGTH    5             /* Length of message header */

extern local_cat l_CAT[];

i_connect (p_params)

struct i_connect_request *p_params;
{
struct null_msg message;

   message.system        = p_params -> system;
   message.major         = INTERNAL;
   message.minor         = REQUEST_CONNECT;
   message.source_system = p_params -> source_system;
   message.source_major  = p_params -> source_major;

   return (send_i_mess (&message,HEADER_LENGTH,p_params->connect_command,strlen(p_params->connect_command)));
}

/* : PROCEDURE FUNCTION (find_local_capability)

Find the number of the capability given its name from within the user's 
data space.
*/

find_local_capability (p_name)

char *p_name;                          /* Name of capability to find */
{
int i,j;
char cap_name[CAPABILITY_NAME_LENGTH];
int  cap_num;
int  code;

   for (i = 0; i < CAPABILITY_NAME_LENGTH; i++)
   {  code = get_mcb_values (&l_CAT[i],cap_name,&cap_num);
      if (code == 0)
      {  for (j = 0; (p_name[j] == cap_name[j]) && (j < CAPABILITY_NAME_LENGTH); j++)
         {  if (p_name[j] == NULL)
               return(cap_num);
         }
      }
   }
   return(0);
}




		    i_creins.c                      08/07/87  1520.1rew 08/07/87  1436.6       35199



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-05-09,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
     install(87-08-07,MR12.1-1072):
     Created.
  2) change(86-06-10,Westcott), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Changed to support ws_stack.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (i_creins):

Create an instance of the calling application within MOWSE.
Interrupt routine to service a request from the caller for putting its mcb 
into an entry in the local CAT.  Upon successfully finding a free entry in 
the local cat, the fields in the entry are initialized, the mcb pointer field 
in the local CAT is set to the one passed from the caller and the major
capability number (obtained from searching the local CAT for a free entry 
and from the local system id) is placed in the major capability field of 
the mcb in the caller.
*/

/* : NOTES
*/

#include <dos.h>
#include <cat.h>
#include <ws_dcls.h>
#include <ws_stack.h>
#include <ws_error.h>
#include <ws_msg.h>
#include <wsmincap.h>

extern local_cat l_CAT[];              /* Local cat table */
extern char      mysystem;             /* IBMPC system id */
extern int       packet_mode;          /* Flags that mowse is active on remote */

i_creins (p_ws_ptr,p_cips)

ws_stack *p_ws_ptr;                    /* Callers registers */
struct cretinst_param_struct *p_cips;  /* Create instance information */
{
int cap_index;                         /* Cat index */
int cap_num;                           /* Capability number */
int code;                              /* Error code */
int namelen;                           /* character counter */
struct alter_cat_msg alter_cat;

/* : If MOWSE is not active on the remote, return error */

   if (!packet_mode)
      return (WSNOTACT);

/* : find an unused CAT entry in the local CAT
     - if no available entry in local CAT, return the error code */

   if ((cap_index = find_free_cat() ) < 0)
      return(cap_index);

   p_cips -> system_id = WSIBMPC;
   p_cips -> major_capability = cap_index + MIN_CAPABILITY_NUMBER;

/* : reset all flags */

   l_CAT[cap_index].flags = 0;
   l_CAT[cap_index].pad = 0;

   if (!(p_cips -> entry_pt))
      l_CAT[cap_index].flags |= NULL_BIT;

/* : initialize sleep time to 0 */

   l_CAT[cap_index].sleep_time = 0;

/* : initialize the mcb pointer with the one passed from caller */

   l_CAT[cap_index].mcb_ptr = p_cips -> mcb_ptr;
   l_CAT[cap_index].ws_entry = p_cips -> entry_pt;
   l_CAT[cap_index].sregs.cs = p_cips -> cs_reg;;

/* : initialize the register values */

   l_CAT[cap_index].sregs.es = p_ws_ptr -> esreg;
   l_CAT[cap_index].sregs.ds = p_ws_ptr -> dsreg;
   l_CAT[cap_index].sregs.ss = p_ws_ptr -> ssreg;
   l_CAT[cap_index].bpreg = p_ws_ptr -> bpreg;
   l_CAT[cap_index].spreg = p_ws_ptr -> spreg;
   l_CAT[cap_index].waitreg  = 0;

/* : SEND A MESSAGE TO REMOTE MACHINE TO ADD TO ITS REMOTE CAT */

   alter_cat.system = WSMULTICS;
   alter_cat.major = WSMAJCAP;
   alter_cat.minor = WS_ADD_TO_RAT;
   alter_cat.source_system = mysystem;
   alter_cat.source_major = WSMAJCAP;
   alter_cat.rat_major = cap_index + MIN_CAPABILITY_NUMBER;

   for(namelen=0; namelen < 32; namelen++) {
      if (p_cips -> capability_name[namelen] < ' ')
         break;
   }
   send_i_mess(&alter_cat, sizeof(struct alter_cat_msg) - 2,
   &p_cips -> capability_name[0],namelen);

   return(WSNOERR);
}




		    i_desins.c                      08/07/87  1520.1rew 08/07/87  1436.6       26532



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-09-14,ASmith), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Fixed CAT table.
  2) change(86-12-08,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Check for sleep queue.
                                                   END HISTORY COMMENTS */
/* :  PROCEDURE FUNCTION (i_desins)

Interrupt routine to free up the cat entry in the local CAT for a given 
capability and to send a message to the remote machine to get rid of the 
same capability in its CAT table.
*/

#include <dos.h>
#include <cat.h>
#include <ws_dcls.h>
#include <ws_error.h>
#include <ws_msg.h>
#include <wsmincap.h>

#define NULL 0

extern local_cat l_CAT[];              /* Local CAT */
extern char mysystem;                  /* System id */
extern local_cat *sleepq;              /* List of sleepers */

i_desins (param)

struct destinst_param_struct *param;
{
int cap_index;                         /* Index into CAT */
struct alter_cat_msg alter_cat;        /* Message to remote */
local_cat *catp;                       /* For traversiong the cat */
int  code;                             /* Error code */

/* : if mcb pointer passed is not the same as the mcb pointer in the cat entry 
     given by the derived index, return with code for invalid mcb */

   cap_index = param -> cap_index;
   if ((cap_index < 0) || (cap_index >= NUMBER_OF_CAT_ENTRIES))
      return(WSINVMCB);
   if (l_CAT[cap_index].mcb_ptr == NULL)
      return(WSINVMCB);
   if (l_CAT[cap_index].mcb_ptr != param -> mcb_ptr)
      return(WSINVMCB);

/* : Null out the mcb_ptr in the CAT (destinst will free it)
     Adjust the sleeping queue (this capability might have been in it) */

   l_CAT[cap_index].mcb_ptr = NULL;

   for (catp = sleepq; catp != NULL; catp = catp -> next_cat)
   {  if (catp -> next_cat == &(l_CAT[cap_index]))
      {  catp -> next_cat = catp -> next_cat -> next_cat;
         break;
      }
   }

/* : Send the message to the remote */

   alter_cat.system = WSMULTICS;
   alter_cat.major = WSMAJCAP;
   alter_cat.minor = WS_DELETE_FROM_RAT;
   alter_cat.source_system = mysystem;
   alter_cat.source_major = WSMAJCAP;
   alter_cat.rat_major = cap_index + MIN_CAPABILITY_NUMBER;

   code = send_i_mess (&alter_cat, sizeof(alter_cat) - 2,NULL,0);

/* : Release the program memory */

   if (!(l_CAT[cap_index].flags & NULL_BIT))
      free_cat_program (&l_CAT[cap_index]);

   return (code);
}




		    i_execap.c                      08/07/87  1520.1rew 08/07/87  1436.6        9693



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-07-07,Westcott), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (i_execap)

Software interrupt handler for execap user call.
*/

#include <stdio.h>
#include <ws.h>
#include <ws_error.h>
#include <ws_dcls.h>

i_execap (p_param, p_length)

struct xcap_struc *p_param;            /* Execap paramter structure */
int               p_length;            /* Length of structure */
{
   return (send_i_mess (&p_param->system, p_length, NULL, 0));
}




		    i_execom.c                      08/07/87  1520.1rew 08/07/87  1436.5       15228



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-06-01,ASmith), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
  2) change(86-07-24,Westcott), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Call to send_i_mess.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (i_execom)

User interrupt routine that creates an execute_command message.
*/

#include <ws.h>
#include <ws_error.h>
#include <ws_dcls.h>
#include <ws_msg.h>
#include <wsmincap.h>

#define MAX_CMD_LEN     128

extern char mysystem;

i_execom (p_param)

struct execom_struc *p_param;
{
static int CMD_ID_CNT;
struct execom_msg exemsg;

/* : Increment command counter  */

   p_param -> cmd_id = ++CMD_ID_CNT;

/* : Initialize message */

   exemsg.system = (char) p_param -> system;
   exemsg.major = WSMAJCAP;
   exemsg.minor = WS_EXECUTE_COMMAND;
   exemsg.source_major = (char) p_param -> major;
   exemsg.source_system = mysystem;
   exemsg.cmd_id = p_param -> cmd_id;

/* : Send message */

   p_param -> status = send_i_mess (&exemsg.system, sizeof(exemsg) - 1,
      &p_param -> command,p_param -> com_len);

   return (p_param -> status);
}




		    i_fndcna.c                      08/07/87  1520.0rew 08/07/87  1436.5       26388



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-05-07,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
     install(87-08-07,MR12.1-1072):
     Created.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (i_fndcna)

Interrupt routine which searches either the local or remote CAT for the 
capability name given the capability number.  Encoded in the capability
number will be the system to search.
*/

/* : RETURNS

Returns 0 if successful, an ws_error otherwise.
*/

#include <dos.h>
#include <cat.h>
#include <ws_dcls.h>
#include <ws_error.h>

#define NULL 0

extern local_cat l_CAT[];
extern remote_cat r_CAT[];
extern char mysystem;

i_fndcna (p_param)

struct findname_param_struct *p_param;
{
int sysid;              /* system id of CAT entry to be used     */
int cap_num;            /* CAT entry to be found                 */
int code;               /* return code                           */
int maj_number;         /* major capability number stored in mcb */

/* : extract the system id and CAT index
     - if error in extracting, return the error code */

   code = c_unpack (&sysid, &cap_num, p_param -> major_capability_number);
   if (code != 0)
      return (code);

/* : if local cat then
     - check for validity of capability found
     - if invalid, set error code to invalid capability and return
     -- copy the capability name into the output parameter */

   if (sysid == mysystem) {
      cap_num = cap_num - MIN_CAPABILITY_NUMBER;

      if (cap_num < 0 || cap_num >= NUMBER_OF_CAT_ENTRIES)
         return (WSINVNUM);            /* OUT OF RANGE */

      if (l_CAT[cap_num].mcb_ptr == NULL)
         return (WSINVNUM);            /* MCB NOT ALLOCATED */

      code = get_mcb_values (&(l_CAT[cap_num]),&(p_param -> capability_name[0]),
         &maj_number);
      return(code);
   }

/* : else search the remote cat
     - check for validity of capability found
     - if invalid, set error code to invalid capability and return
     -- copy capability name into caller's buffer */

   else {
      cap_num = cap_num - MIN_CAPABILITY_NUMBER;

      if ((cap_num < 0) || (cap_num >= NUMBER_OF_CAT_ENTRIES))
         return (WSINVNUM);            /* OUT OF RANGE */

      if (r_CAT[cap_num].major_capability == 0 ) 
         return (WSINVNUM);            /* MOWSE HAS NO INFORMATION */

      stccpy (p_param -> capability_name, r_CAT[cap_num].capability_name, CAPABILITY_NAME_LENGTH);
      return(0);
   }
}




		    i_fndcnu.c                      08/07/87  1520.0rew 08/07/87  1436.5       32706



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-05-09,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
     install(87-08-07,MR12.1-1072):
     Created.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (i_fndcnu):

Interrupt routine to find a major capability number from the local and remote 
CAT in mowse's memory space given a capability name.
*/

/* : NOTES

MOWSE looks for the capability name in its capability table in the following 
fashion:

     1) If the provided major capability number is 0, MOWSE will search the 
        specified system from the top of the CAT.
     2) If the major capability number is valid and not 0, MOWSE will search
        the specified system from the NEXT position in the CAT.
     3) If the provided system_id is invalid, MOWSE will search the local 
        system CAT.

If MOWSE does not find the name between its starting point and the end of the
CAT, an error code will be returned.

param points to a structure containing 
   char capability_name [CAPABILITY_NAME_LENGTH]; /* Name to be searchedfor */
   int  major_capability_number;                  /* Return value of name */
*/

#include <dos.h>
#include <ws.h>
#include <cat.h>
#include <ws_dcls.h>
#include <ws_error.h>

#define NULL 0

extern local_cat  l_CAT[];
extern remote_cat r_CAT[];
extern char mysystem;

i_fndcnu (param)

struct findnumb_param_struct *param;  /* Parameter structure */
{
int  sysid;              /* system ID specified by caller */
int  cap_num;            /* capability number specified by caller */
int  cap_index;          /* temporary count of cat entries examined */
int  entry_number;       /* major capability number found        */
char entry_name[CAPABILITY_NAME_LENGTH];  /* major name found */
int  code;               /* return codes */

/* : if invalid major capability number, start at top of CAT */

   if (code = c_unpack (&sysid, &cap_num, param->major_capability_number))
      cap_num = 0;

/* : if index specified is not 0, search next entry */

   cap_num = (cap_num < MIN_CAPABILITY_NUMBER) 
      ? 0 
      : cap_num + 1 - MIN_CAPABILITY_NUMBER;

/* : If searching local table */

    if ((sysid == mysystem) || (sysid == WSLOCAL))
    {  for (cap_index = cap_num; cap_index < NUMBER_OF_CAT_ENTRIES; cap_index++)
       {  if (l_CAT[cap_index].mcb_ptr != NULL)
          {  if (code = get_mcb_values (&l_CAT[cap_index],entry_name,&entry_number))
                return (code);
             if (!strncmp (entry_name,param->capability_name,CAPABILITY_NAME_LENGTH))
             {  c_pack (mysystem,cap_index + MIN_CAPABILITY_NUMBER,&param->major_capability_number);
                return(0);
             }
         }
      }
      return (WSINVNAM);
   }

/* : Else search remote CAT */

   for (cap_index = cap_num, sysid = WSMULTICS; cap_index < NUMBER_OF_CAT_ENTRIES; cap_index++)
   {  if (strncmp(param->capability_name,r_CAT[cap_index].capability_name,CAPABILITY_NAME_LENGTH) == 0)
      {  c_pack(sysid,cap_index + MIN_CAPABILITY_NUMBER,&param->major_capability_number);
         return(0);
      }
   }

/* : Nothing found, set code to indicate this */

   return (WSINVNAM);
}




		    i_getbgm.c                      08/07/87  1520.0rew 08/07/87  1436.4       29682



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-07-11,Westcott), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (i_getbgm)

Get the next enqueued message from a background application that was sent 
to the foreground application. This routine should only be called by a 
foreground application since the messages are assumed to be intended for 
a human being.
*/

#include <dos.h>
#include <alloc.h>
#include <cat.h>
#include <ws_dcls.h>
#include <ws_error.h>
#include <ws_msg.h>
#include <ws_fgb.h>
#include <wsmincap.h>

#define NULL 0

extern struct fgbstr *bgbfptr;         /* first buffer on linked list */
extern struct fgbstr *bgblptr;         /* last buffer on linked list */
extern struct fgbstr *sgbfptr;         /* first buffer on linked list */
extern struct fgbstr *sgblptr;         /* last buffer on linked list */
extern struct allocstr *bgaptr;        /* allocation data for linked list*/
extern int bgcount;                    /* count of bg messages in linked list */

i_getbgm (p_param)

struct gbgmsg_struc *p_param;
{
int i;                  /* copy counter */
char *s1;               /* pointer to source for copy */
char *d1;               /* pointer to destination of copy */
struct fgbstr *bgbp;    /* pointer to current message structure */
struct query_msg *qrp;  /* definition of query/reply message */

/* : if a status message is desired
     - If no status messages on queue return WSNOMESS
     - Remove bg buffer from queue    */

   if (p_param -> bg_type == STATUS_REPLY) {
      if (sgbfptr == NULL) {
         sgblptr = NULL;
         return (WSNOMESS);
      }

      bgbp = sgbfptr;
      sgbfptr = bgbp -> fgb_next;
      if (sgbfptr == NULL)
         sgblptr = NULL;
   }

/* : else if a background message is desired
     - If no bg messages on queue, reset bgcount, and return WSNOMESS
     - Remove bg buffer from queue    */

   else {
      if (bgbfptr == NULL) {
         bgcount = 0;
         bgblptr = NULL;
         return (WSNOMESS);
      }

      bgbp = bgbfptr;
      bgbfptr = bgbp -> fgb_next;
      --bgcount;
      if (bgbfptr == NULL) {
         bgcount = 0;
         bgblptr = NULL;
      }
   }

/* : copy buffer contents to p_param     */

   p_param -> length = bgbp -> fgb_length - 2;        /* Subtract out sysid, cap */
   qrp = (struct query_msg *) &bgbp -> fgb_minor;
   d1 = &p_param -> bgmsg[0];
   s1 = &qrp -> msg_data[0];
   for(i = 0; i < p_param -> length; i++)
      *d1++ = *s1++;
 
/* : insert sender major and type into structure */

   c_pack (qrp -> source_system, qrp -> source_major, &p_param -> sender_major);
   p_param -> bg_type = (int) bgbp -> fgb_minor;

/* : Free the buffer */

   wsfree(bgaptr,bgbp);

   return(0);
}




		    i_putbgm.c                      08/07/87  1520.0rew 08/07/87  1436.4       33300



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-07-11,Westcott), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
  2) change(86-12-10,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     When called with a status_reply, place message
     into status list.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (i_putbgm)

Places a message on the background message queue for subsequent retrieval by 
a foreground program. In addition to placing the message on the queue, a 
count of the number of messages on the queue is incremented.
*/

#include <dos.h>
#include <alloc.h>
#include <cat.h>
#include <ws_dcls.h>
#include <ws_error.h>
#include <ws_msg.h>
#include <ws_fgb.h>
#include <wsmincap.h>

#define NULL 0

extern struct fgbstr *bgbfptr;         /* first buffer on linked list */
extern struct fgbstr *bgblptr;         /* last buffer on linked list */
extern struct fgbstr *sgbfptr;         /* first buffer on Status linked list */
extern struct fgbstr *sgblptr;         /* last buffer on Status linked list */
extern struct allocstr *bgaptr;        /* allocation data for linked list*/
extern int bgcount;                    /* count of bg messages in linked list */

i_putbgm (p_param)

struct putbg_struc *p_param;
{
int i;                  /* copy counter */
char *s1;               /* pointer to source for copy */
char *d1;               /* pointer to destination of copy */
struct fgbstr *bufp;    /* pointer to current message structure */
struct fgbstr *fgbp1;   /* temporary pointer to  message structure */
struct query_msg *qrp;  /* definition of query/reply message */
int sysid;              /* system id extracted from sender major */
int cap_num;            /* capability number extracted from sender major */

/* : Allocate a buffer and place it on the linked list, 1 extra for message type */

   bufp = (struct fgbstr *) wsalloc (bgaptr,p_param -> length + 1 + sizeof(struct fgbstr));

/* : if allocation successful
     - copy to background message buffer     */

   if (bufp != NULL) {
      d1 = &bufp -> fgb_minor;
      *d1++ = (char) p_param -> type;
      c_unpack (&sysid, &cap_num, p_param -> sender_major);
      *d1++ = (char) sysid;
      *d1++ = (char) cap_num;
      s1 = p_param -> bgmsg;
      for (i = 0;i < p_param -> length;i++) {
         *d1++ =  *s1++;
      }
      bufp -> fgb_length = p_param -> length + 2;     /* add in sysid, cap_num */

/* : - link to previous status buffers OR background buffers  */

      bufp -> fgb_next = NULL;

      if (p_param -> type == STATUS_REPLY)
      {  if (sgbfptr == NULL) {
            sgbfptr = bufp;
            sgblptr = bufp;
         }
         else {
            fgbp1 = bgblptr;
            fgbp1 -> fgb_next = bufp;
            sgblptr = bufp;
         }
      }
      else
      {  if (bgbfptr == NULL) {
            bgbfptr = bufp;
            bgblptr = bufp;
            bgcount = 1;
         }
         else {
            fgbp1 = bgblptr;
            fgbp1 -> fgb_next = bufp;
            bgblptr = bufp;
            bgcount++;
         }
      }
   }

/* : return parameter structure to caller */

   return(0);
}




		    i_reset.c                       08/07/87  1520.0rew 08/07/87  1436.3       28791



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-07-13,Westcott), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
  2) change(86-11-11,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Moved buffer clearing to when the destination is
     called to be compatible with same message type from remote.
  3) change(86-11-21,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Added message for RESET_SUSPEND to the remote
     to be generated.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (i_reset)

Send a reset or resume message to a background application from a
foreground program.
*/

#include <dos.h>
#include <stdio.h>
#include <ws.h>
#include <ws_error.h>
#include <ws_msg.h>
#include <ws_dcls.h>
#include <ws_fgb.h>
#include <cat.h>
#include <wsmincap.h>

extern local_cat  l_CAT[];
extern remote_cat r_CAT[];
extern char mysystem;

i_reset (p_msg, p_length)

struct xcap_struc *p_msg;
int p_length;
{
int cap_num;                           /* capability number of caller */
char *flags;                           /* Address of flags to adjust */
struct input_msg message;              /* Extrac message to be generated */
int  code;

/* : Verify that major capability number is valid */

   cap_num = p_msg -> major - MIN_CAPABILITY_NUMBER;
   if ((cap_num < 0) || (cap_num >= NUMBER_OF_CAT_ENTRIES))
      return(WSINVNUM);

   if (p_msg -> system == mysystem)
   {  if (l_CAT[cap_num].mcb_ptr  == NULL )
         return (WSINVNUM);
   }
   else
   {  if (r_CAT[cap_num].major_capability == 0)
         return (WSINVNUM);
   }

/* : Set the appropriate reset bit for the destination capability */

   if (p_msg -> system == mysystem )
      flags = &(l_CAT[cap_num].flags);
   else
      flags = &(r_CAT[cap_num].flags);

   if (p_msg -> minor == RESET_APPLICATION)
      *flags |= RESET_BIT;
   else if (p_msg -> minor == RESUME_APPLICATION)
   {  if (*flags & SUSPENDED_BIT)
         *flags &= ~SUSPENDED_BIT;
      else
         return (WSNOSPND);
   }

/* : Send the message */

   if (code = send_i_mess (p_msg, p_length, NULL, 0))
      return (code);

/* : If it was a RESUME for a local capability, send a RESET_SUSPEND to
     the remote */

   if ((p_msg -> minor == RESUME_APPLICATION) && (p_msg -> system == mysystem))
   {  message.minor         = RESET_SUSPEND;
      message.major         = WSMAJCAP;
      message.system        = WSMULTICS;
      message.source_system = mysystem;
      message.source_major  = p_msg -> major;
      message.msg_data[0]   = 0;
      code = send_i_mess (&message, 5, NULL, 0);
   }

   return (code);
}




		    i_sendbg.c                      08/07/87  1520.0rew 08/07/87  1436.2       10782



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-07-13,Westcott), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (i_sendbg)

Sends a message over the back ground channel from a foreground program.
*/

#include <stdio.h>
#include <ws.h>
#include <ws_error.h>
#include <ws_msg.h>

extern char mysystem;                  /* ID of this system */

i_sendbg (p_msg, p_length)

struct packet_msg *p_msg;
int p_length;
{

   if ((p_msg -> system == 0) || (p_msg -> major == 0))
   {  p_msg -> source_system = mysystem;
      p_msg -> source_major = WSMAJCAP;
   }

   return (send_i_mess (p_msg, p_length, NULL, 0));
}




		    i_sleep.c                       08/07/87  1519.9rew 08/07/87  1436.2       39312



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-06-13,Westcott), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
  2) change(86-10-04,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Corrected Q management.
  3) change(86-11-24,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Make sure source is not already sleeping.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (i_sleep):

Places the caller's CAT entry onto a queue of entries that are sleeping. The 
entry's position on the queue will be in ascending order of the time remaining 
until wakeup. The SLEEPING_BIT flag in the CAT will also be set.  A
SET_SLEEP_FLAG minor capability message will be sent to the remote system 
indicating the change of status.
*/

/* : RETURNS:

       0, if no error
       WSNOTACT, if MOWSE not active
       WSINVCAT, if CAT entry not correct
*/

#include <dos.h>
#include <stdio.h>
#include <ws.h>
#include <ws_error.h>
#include <ws_msg.h>
#include <ws_dcls.h>
#include <ws_fgb.h>
#include <cat.h>
#include <wsmincap.h>

extern int       packet_mode;   /* determines if MOWSE is attached */
extern local_cat *sleepq;       /* pointer to queue of sleeping CATs */
extern local_cat l_CAT[];       /* CAT table for local capabilities */
extern char      mysystem;      /* system id of PC */
           
i_sleep (p_sleep_ptr)
struct sleep_struc *p_sleep_ptr;  /* Pointer to the sleep info structure */
{
int  sysid;                 /* system id extracted from param->sender_major */
int  major;                 /* Major index of caller */
unsigned int wtime;         /* time when wakeup will occur */
local_cat *scat1;           /* pointer to queue of sleeping CATs */
local_cat *scat2;           /* pointer to queue of sleeping CATs */
local_cat *mycat;           /* pointer to this caller's CAT */
struct null_msg  sleep_msg; /* message to update remote sleep info */
unsigned int wstime();      /* returns current value of tick counter */

/* : Return if MOWSE not active */

   if (packet_mode == 0)
      return (WSNOTACT);

/* : Verify that the CAT is in use */

   major = p_sleep_ptr -> source_major - MIN_CAPABILITY_NUMBER;
   if ((major < 0) || (major > NUMBER_OF_CAT_ENTRIES))
      return (WSINVNUM);

   mycat = &l_CAT[major];
   if (mycat -> mcb_ptr  == NULL)
      return (WSINVMCB);

/* : Make sure caller is not already sleeping */

   if (mycat -> flags & SLEEPING_BIT)
      return (WSSLPING);

   mycat -> flags |= SLEEPING_BIT;

/* : Insert the information into the sleep queue */

   wtime = p_sleep_ptr -> time;
   wtime += wstime();
   mycat -> flags |= SLEEPING_BIT;
   mycat -> sleep_time = wtime;

/* : - If queue is empty insert at top */

   if (sleepq == NULL)
   {  sleepq = mycat;
      mycat -> next_cat = NULL;
   }

/* : - Head of list */

   else if (sleepq -> sleep_time > wtime)
   {  mycat -> next_cat = sleepq;
      sleepq = mycat;
   }

/* : Elsewhere in list */

   else for (scat1 = sleepq, scat2 = NULL; scat1 != NULL;)
   {  if (scat1 -> sleep_time > wtime)             /* Middle */
      {  mycat -> next_cat = scat1;
         scat2 -> next_cat = mycat;
         scat1 = NULL;
      }

      else if (scat1 -> next_cat == NULL)          /* Tail */
      {  scat1 -> next_cat = mycat;
         scat1 = NULL;
      }

      else                                         /* Elsewhere */
      {  scat2 = scat1;
         scat1 = scat2 -> next_cat;
      }
   }

/* : Send message to remote system to set sleep flag */

   sleep_msg.system = WSMULTICS;
   sleep_msg.major  = WSMAJCAP;
   sleep_msg.minor  = WS_SET_SLEEP_FLAG;
   sleep_msg.source_major = p_sleep_ptr -> source_major;
   sleep_msg.source_system = mysystem;
   return (send_i_mess(&sleep_msg, sizeof(struct null_msg)-1, NULL, 0));
}




		    i_suspnd.c                      08/07/87  1519.9rew 08/07/87  1436.1       29934



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-07-11,Westcott), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
  2) change(86-11-15,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Removed removal of pending messages for
     the application to be suspended.
  3) change(86-11-21,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Added message for SET_SUSPEND to remote.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (i_suspnd)

Perform the necessary action to suspend an application, setting its suspend 
flag and forwarding a message to the remote system indicating the change.
*/

#include <dos.h>
#include <stdio.h>
#include <ws.h>
#include <ws_error.h>
#include <ws_msg.h>
#include <ws_dcls.h>
#include <ws_fgb.h>
#include <cat.h>
#include <wsmincap.h>

#define HEADER_LENGTH    5             /* Length of message header */

extern local_cat  l_CAT[];             /* Local CAT */
extern remote_cat r_CAT[];             /* Remote CAT */
extern char mysystem;

i_suspnd (p_suspend_message)

struct xcap_struc *p_suspend_message;
{
char *flags;                           /* Pointer to flags field in CAT */
int  cap_num;                          /* Capability index */
int  code;
struct input_msg message;              /* Message to remote to set bit */

/* : Verify that major capability number is valid */

   cap_num = p_suspend_message -> major - MIN_CAPABILITY_NUMBER;
   if ((cap_num < 0) || (cap_num > NUMBER_OF_CAT_ENTRIES))
      return(WSINVNUM);

/* : Verify that the application that the capability number refers to exists
     and get the flag field */

   if (p_suspend_message -> system == mysystem)
   {  if (l_CAT[cap_num].mcb_ptr  == NULL)
         return (WSINVNUM);
      flags = &(l_CAT[cap_num].flags);
   }
   else
   {  if (r_CAT[cap_num].major_capability == 0)
         return (WSINVNUM);
      flags = &(r_CAT[cap_num].flags);
   }

/* : Verify that the application is not already suspended */

   if (*flags & SUSPENDED_BIT)
      return (WSSUSPND);

/* : Set and send suspend message to the remote MOWSE */

   *flags |= SUSPENDED_BIT;
   if (code = send_i_mess (p_suspend_message, HEADER_LENGTH, NULL, 0))
      return (code);

/* : If the destination of the message is local, then send a message to the
     remote indicating the application is suspended */

   if (p_suspend_message -> system == mysystem)
   {  message.system        = WSMULTICS;
      message.major         = WSMAJCAP;
      message.minor         = SET_SUSPEND;
      message.source_system = mysystem;
      message.source_major  = p_suspend_message -> major;
      message.msg_data[0]   = 0;
      code = send_i_mess (&message, HEADER_LENGTH, NULL, 0);
   }

   return (code);
}




		    initmows.asm                    08/23/88  0817.7rew 08/23/88  0817.3      145503



; ***********************************************************
; *                                                         *
; * Copyright, (C) Honeywell Bull Inc., 1987                *
; *                                                         *
; * Copyright, (C) Honeywell Information Systems Inc., 1986 *
; *                                                         *
; ***********************************************************
 page    55,132

; HISTORY COMMENTS:
;  1) change(85-12-22,Flegel), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Created.
;  2) change(86-02-15,Westcott), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Support of software interrupts.
;  3) change(88-01-26,Flegel), approve(88-02-29,MCR7853),
;     audit(88-03-10,Nakaska):
;     MOWSE made to drop DTR (disconnect) by default unless /H option
;     requested by user at command line.
;  4) change(88-02-10,Lee), approve(88-02-29,MCR7853),
;     audit(88-03-10,Nakaska):
;     Made parameter "lineparm" public so routine line_break() could
;     access it
;  5) change(88-06-17,Lee), approve(88-07-18,MCR7936), audit(88-08-10,Flegel):
;     Added support for Mark and Space parity
;                                                      END HISTORY COMMENTS

; PROCEDURE FUNCTION (initialize_mowse):
;
;Initialize the appropriate hardware and software interrupt vectors to enable 
;the MOWSE environment on the PC.  This also includes enabling the RS232 port 
;in preparation for PC<=>multics communications.

; NOTES
;
;Arguments:
;       lineparm - rs232 line parameters. This parameter is identical to
;                  the parameter required for the ROM-BIOS interrupt 14H
;                  except when parity is Mark or Space. 
;
;   7       6       5        4       3        2        1       0
;   ----- Baud Rate --       -Parity--      Stopbit    --Word Length
;   000 - 110                X0 - NONE        0 - 1     10 - 7 Bits
;   001 - 150                01 - ODD         1 - 2     11 - 8 Bits
;   010 - 300                11 - EVEN
;   011 - 600
;   100 - 1200
;   101 - 2400
;   110 - 4800
;   111 - 9600
;
; (*) - for Mark or Space, bits 8 to 10 of lineparm are used as follows:
;
;  10       9        8
; - Mark/Space parity -
;    101 - Mark parity
;    111 - Space parity
;
;
;Mowse is a '.com' file which will terminate and stay resident.  All interrupt 
;handlers and their associated modules also remain resident.
;
;        Interrupt vectors:
;                0Ch     hardware (RS232)
;                0Bh     software (MOWSE functions calls)
;                1Ch     timer interrupt
;                28h     console I/O interrupt


include dos.mac                 ;Lattice include file
include xoscall.mac             ;Bios and Dos Call macros
include mowsdefs.mac
include ws.mac
include ws_buf.mac

page
;*******************************************************************
;                                       DATA
;*******************************************************************
dseg

;-------- External Declarations

extrn   _TOP:word
extrn   _BASE:word
extrn   data_seg:word
extrn   stackseg:word
extrn   sp_base:word
extrn   SOFTNO:word
extrn   COM_NO:word
extrn   COM_PORT:word
extrn   HARDINTRPT:word                      ; hardware interrupt number
extrn   MASK8259:byte
extrn   startup_flags:word                   ; startup control options

;--------- Public Declarations
public  terminal_over
public  initialize_mowse
public  send_buffer
public  transmit_active
public  packet_mode
public  bg_in_use
public  mysystem;
public  fg_buf
public  bg_sav_buf
public  inbuff
public  in_protocol
public  sleepq
public  tikpermin
public  lineparm

;----------- Messages ---------------

divword     dw   60

lineparm    commparm <B9600,even_parity,stop1,data7>


;------------ Received data buffer and associated pointers
;------------ Used for debugging

        def_buf inbuff,1000

;------------ Transmitted data buffer and associated pointers
;------------ Used for debugging

        def_buf fg_buf,WSPAKSIZ+10

;------------ Transmit buffer
;------------ Contains all data to be transmitted over rs232 link

        def_buf send_buffer,BUFSIZE

;------------ Foreground buffer

terminal_over    db      0                   ;terminal buffer overflow flag

transmit_active  dw      0                   ; =1, if transmit interrupt active
send_buffer_over db      0                   ;send buffer overflow flag
mysystem         db      0                   ; system ID fo this mowse
packet_mode      dw      0                   ; =1, if in protocol running
in_protocol      dw      0                   ; set if protocol module is active
sleepq           dw      0                   ; pointer to first CAT entry on sleep queue
tikpermin        dw      0                   ; number of clock ticks per minute
bg_in_use        dw      0                   ; =1, if bg_sav_buf full
bg_sav_buf       db      WSPAKSIZ+10 dup (?)
ms_parity        db      0

endds

page
;**************************************************************************
;                               Program mainline
;**************************************************************************

pseg

;-------- External Procedures

extrn   user_interrupt_handler:near
extrn   hardware_interrupt_handler:near
extrn   int13ep:near
extrn   int1cep:near
extrn   int28ep:near
extrn   init_inbuff:near
extrn   uisystem:word
public  INTSOFT,INT13,INT1C,INT28,IN_DOS, INTHARD
public  IN_SOFT,IN_NARC,IN_INT28
public  advance_count
public  time_count
public  mowse_time
public  ticpersec
public  calladvtmr

initialize_mowse proc near

        push    bp
        push    es

;get parameters to control the com port into variable lineparm

        mov     bp,sp
        mov     ax,[bp+6]
        mov     lineparm,al
        mov     ms_parity,ah

;Test the interrupt vectors to see if they are already initialized

        mov     ax, SOFTNO
        mov     ah, GETVECTOR
        int     DOSFUNCTION
        cmp     bx, offset user_interrupt_handler
        jne     nonres

        mov     ax, HARDINTRPT
        mov     ah, GETVECTOR
        int     DOSFUNCTION
        cmp     bx, offset hardware_interrupt_handler
        jne     nonres

;If address of interrupt service routines are already in place then
;- return with a 0 return value

        pop     es
        pop     bp
        xor     ax,ax                        ; indicate MOWSE already resident
        ret

nonres:

;complete initialization, initialize circular buffers

        init_buf send_buffer
        init_buf inbuff
        init_buf fg_buf

;save the pointers to the stack to be used when servicing an interrupt

        cli
        push     DS                          ;save DS
        push     SS                          ;save SS

;save parameters which define stack to be used during interrupts

        mov     ax,sp
        sub     ax,FRAMESIZE
        mov     CS:sp_base,ax                ;bottom of MOWSE stack
        pop     CS:stackseg                  ;SS of MOWSE
        pop     CS:data_seg                  ;DS of MOWSE

        mov     byte ptr mysystem,WSIBMPC
        mov     byte ptr cs:uisystem,WSIBMPC

;set up Interrupt Vector for RS232 Interrupt

        push    DS
        mov     ax,HARDINTRPT
        mov     ah,35h
        int     DOSFUNCTION
        mov     word ptr CS:INTHARD+2,es
        mov     word ptr CS:INTHARD,bx       ;save old vector address
        mov     DX, offset hardware_interrupt_handler
        mov     ax,HARDINTRPT                ;Set interrupt vector RS232
        push    CS
        pop     DS                           ;Point to RS232 ISR in DS:DX
        mov     ah,25h
        int     DOSFUNCTION
        pop     DS

;initialize interrupt flags

        mov     ax, 1
        mov     CS:IN_INT28,ax
        mov     CS:IN_NARC,ax
        mov     CS:IN_SOFT,ax
        mov     transmit_active,ax
        mov     in_protocol,0
        mov     sleepq,0

;setup software interrupt vector

        mov     ax,SOFTNO
        mov     ah,35h
        int     DOSFUNCTION
        mov     word ptr CS:INTSOFT+2,es
        mov     word ptr CS:INTSOFT,bx       ;save old vector address
        mov     dx, offset user_interrupt_handler
        mov     ax,SOFTNO
        push    ds
        push    cs
        pop     ds
        mov     ah,25h
        int     DOSFUNCTION

;trap INT13 interrupt

        mov     al,13h
        mov     ah,35h
        int     DOSFUNCTION
        mov     word ptr CS:INT13+2,es
        mov     word ptr CS:INT13,bx         ;save old vector address
        mov     dx, offset int13ep
        mov     al,13h
        mov     ah,25h
        int     DOSFUNCTION

;trap INT1C interrupt *

        mov     al,1Ch
        mov     ah,35h
        int     DOSFUNCTION
        mov     word ptr CS:INT1C+2,es
        mov     word ptr CS:INT1C,bx         ;save old vector address
        mov     dx, offset int1Cep
        mov     al,1Ch
        mov     ah,25h
        int     DOSFUNCTION

;trap INT28 interrupt

        mov     al,28h
        mov     ah,35h
        int     DOSFUNCTION
        mov     word ptr CS:INT28+2,es
        mov     word ptr CS:INT28,bx         ;save old vector address
        mov     dx, offset int28ep
        mov     al,28h
        mov     ah,25h
        int     DOSFUNCTION
        pop     ds

;get address of in-dos flag

        mov     ah,34h
        int     DOSFUNCTION
        mov     word ptr CS:IN_DOS+2,es
        mov     word ptr CS:IN_DOS,bx

;initialize interrupt flags

        xor     ax,ax
        mov     CS:IN_INT28,ax
        mov     CS:IN_NARC,ax
        mov     CS:IN_SOFT,ax
        mov     transmit_active,ax
        mov     word ptr CS:time_count,ax
        mov     word ptr CS:time_count+2,ax
        mov     CS:advance_count,ax

;If hold_dtr (/H) option requested, then skip.  Otherwise default to dropping 
;DTR for disconnection

        mov     ax,startup_flags
        and     ax,OPTION_H                  ; Hold DTR ?
        jne     dtr_raise                    ;  YES, don't drop it

        mov     al,MASKMCR_DROP              ; Disable OUT2, drop DTR, RTS active low
        mov     DX,MCR                       ; Address MCR
        add     DX,COM_PORT
        out     DX,AL
dtr_raise:

;Determine the number of clock ticks in every second, minute, and hour.
;Count the number that occur in a 10 second interval and calculate the
;rest.

        sti
        mov     ah,2ch
        int     DOSFUNCTION                  ; get time
        push    word ptr CS:time_count+2     ; save current tick count
        add     dh,10
        cmp     dh,60
        jl      tick1                        ; if more than 60 seconds
        sub     dh,60
        inc     cl
        cmp     cl,60                        ; if more than 60 minutes
        jl      tick1
        xor     cl,cl
        inc     ch
        cmp     ch,24                        ; if more than 23 hours
        jl      tick1
        xor     ch,ch

tick1:
        mov     bx,cx                        ; save hours,minutes
        mov     si,dx                        ; save seconds

tick2:
        mov     ah,2ch
        int     DOSFUNCTION                  ; get time
        cmp     ch,bh
        jne     tick2                        ; if hours are not the same
        cmp     cl,bl
        ja      tick3
        jb      tick2
        cmp     dx,si
        jl      tick2                        ; if 10 seconds hasn't elapsed

tick3:
        mov     ax,word ptr CS:time_count+2
        pop     cx
        sub     ax,cx                        ; ax = number of ticks in 10 seconds
        shl     ax,1                         ; ax = number of ticks in 20 seconds
        mov     dx,ax
        shl     dx,1                         ; dx = number of ticks in 40 seconds
        add     ax,dx                        ; dx = number of ticks in 60 seconds
        mov     tikpermin,ax

;Calculate ticpersec = tikpermin / 60

        mov     ax,tikpermin
        cwd
        div     divword
        mov     CS:ticpersec,ax

;set up RS232 port to paramters in lineparam

        mov     dx, COM_NO                   ;COMM port 1
        mov     al, lineparm
        @bioscall RS232,0

;check for handling SPACE and MARK parity

        mov     ah,ms_parity   ; al = 101b for MARK, 111b for SPACE
        sal     ah,1           ; create parity bits mask for LCR
        jz      not_ms_parity  ; ms_parity is 0, parity not mark or space

        sal     ah,1           ; complete creating LCR parity mask, 
        sal     ah,1           ;  00101000b for MARK, 00111000b for SPACE

        mov     dx,LCR         ; get offset into LCR
        add     dx,COM_PORT    ; add base address of comm port
        in      al,dx          ; get current LCR status
        and     al,MASKLCR     ; reset DLAB
        or      al,ah          ; set appropriate LCR parity control bits
        out     dx,al          ; send to LCR

not_ms_parity:
        cli

;Enable DTR,RTS,OUT1,OUT2 on 8250 to get it into a known state

        mov     al,MASKMCR                   ;Disable OUT2, leave DTR, RTS active low
        mov     DX,MCR                       ;Address MCR
        add     DX,COM_PORT
        out     DX,AL

;enable IRQ(3 4) on 8259 interrupt controller

        in      al,IMR8259                   ;Get current masks
        and     al,MASK8259                  ;Reset IRQ(3 4) mask
        out     IMR8259,al                   ;And restore to Interrupt Mask
                                             ;Register


;enable 8250 data ready interrupt

        cli
        mov     dx,LCR                       ;Address LCR
        add     dx,COM_PORT

        in      al,dx                        ;Reset DLAB for IER access
        and     al,MASKLCR
        out     dx,al

        mov     dx,IER                       ;Address IER
        add     dx,COM_PORT

        xor     al,al                        ;Clear the IER
        out     dx,al

        mov     al,MASKIER                   ;Enable 'Data Ready' Interrupt and
        out     dx,al                        ;   Transmit holding register empty and
                                             ;   Break Characters and
                                             ;   Change in modem status

;enable Out2 on 8250

        mov     dx,MCR                       ;Address MCR
        add     dx,COM_PORT

        mov     al,MASKMCR                   ;Enable OUT2
        out     dx,al

;Allow interrupts

        mov     dx,MCR
        add     dx,COM_PORT                  ; dx = COM_PORT
        mov     al,MASKMCR                   ; al = enable OUT2
        out     dx,al                        ; enable MCR
        sti

;Return

        mov     ax, 1                        ; mowse initialized successfully
        pop     es
        pop     bp
        ret

initialize_mowse endp

page
;***********************************************************************
;       Static storage for interrupt vectors
;***********************************************************************
INT13         dd 0       ; Diskette services vector
INT1C         dd 0       ; Timer interrupt vector
INT28         dd 0       ; Console I/O vector
IN_DOS        dd 0       ; Address of in-dos flag
INTSOFT       dd 0       ; Old software Interrupt vector
INTHARD       dd 0       ; Old hardware interrupt vector
;***********************************************************************
;       Static storage for flags
;***********************************************************************
IN_SOFT       dw 0       ; =1, if in software interrupt
IN_NARC       dw 0       ; =1, if in MOWSE
IN_INT28      dw 0       ; =1, if in Console I/O
advance_count dw 0       ;counter to tell if one second has passed
time_count    dd 0       ; tick counter for MOWSE timing
                         ;so that Hal's "advtmr()" can be called
mowse_time    dw 0       ;seconds elapsed since startup
ticpersec     dw 0       ; number of clock ticks per second
calladvtmr    dw 0       ; flag indicating to call advtmr routine

endps
      end




		    internal.c                      08/07/87  1519.9rew 08/07/87  1436.1       70542



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(85-12-26,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
  2) change(86-06-06,Westcott), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     remove puttdata support.
  3) change(86-10-21,ASmith), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     connect request support.
  4) change(86-10-22,ASmith), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     handle invalid requests.
  5) change(86-11-14,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     handle set/reset sleep bit
                                                   END HISTORY COMMENTS */
/* : PROCEDURE FUNCTION (internal_mowse)
                                                                
Determine the destination of the internal mowse message depending on the 
minor capability number and direct control appropriately.
*/

#include <dos.h>
#include <stdio.h>
#include <ws.h>
#include <ws_msg.h>
#include <ws_error.h>
#include <wsmincap.h>
#include <cat.h>

#define HEADER_LENGTH 5                /* Length of message header */

extern remote_cat r_CAT[];
extern local_cat l_CAT[];

internal_mowse(length,mowse_msgp)

int     length;                        /* Length of message */
struct input_msg *mowse_msgp;          /* message */
{
int  err_code;
int  i;
int  cap_index;
char return_status;
char capname[33];
int  capname_length;
int  cap_num;
int  connect_request_len;
char connect_request_string[WSPAKSIZ];

struct alter_cat_msg *acp;
struct null_msg connect_response_msg;
struct null_msg mowse_message;

/* : switch(minor_capability) */

   switch(mowse_msgp -> minor)
   {

/* : - case EXECUTE_COMMAND   */

      case WS_EXECUTE_COMMAND :

         EXECUTE_COMMAND(length,mowse_msgp);
         break;

/* : - case ADD_TO_REMOTE_CAT           */

      case WS_ADD_TO_RAT:

         acp = (struct alter_cat_msg *) mowse_msgp;
         return (add_to_remote_cat(acp -> source_system,acp -> rat_major,&acp -> major_name[0]));

/* : DELETE_FROM_REMOTE_CAT */

      case WS_DELETE_FROM_RAT:

         acp = (struct alter_cat_msg *) mowse_msgp;
         if (acp -> source_system == WSIBMPC)
            return(WSINVSYS);
         cap_index = acp -> rat_major - MIN_CAPABILITY_NUMBER;
         if ((cap_index < 0) || (cap_index > NUMBER_OF_CAT_ENTRIES))
            return(WSINVNUM);
         r_CAT[cap_index].major_capability = 0;
         r_CAT[cap_index].system_id = 0;
         r_CAT[cap_index].flags = 0;
         i = 0;
         while (r_CAT[cap_index].capability_name[i] != 0)
            r_CAT[cap_index].capability_name[i++] = 0;
         return(0);

/* : - case WS_SET_SLEEP_FLAG
     -- set the sleep flag on the appropriate remote appllcation */

      case WS_SET_SLEEP_FLAG:

         cap_index = (int)mowse_msgp -> source_major - MIN_CAPABILITY_NUMBER;
         if ((cap_index < 0) || (cap_index > NUMBER_OF_CAT_ENTRIES))
            return (0);
         r_CAT[cap_index].flags |= SLEEPING_BIT;
         return (0);

/* : - case WS_RESET_SLEEP_FLAG
     -- set the sleep flag on the appropriate remote appllcation */

      case WS_RESET_SLEEP_FLAG:

         cap_index = (int)mowse_msgp -> source_major - MIN_CAPABILITY_NUMBER;
         if ((cap_index < 0) || (cap_index > NUMBER_OF_CAT_ENTRIES))
            return (0);
         r_CAT[cap_index].flags &= ~SLEEPING_BIT;
         return (0);

/* : - case RESET_REPLY
     -- clear the flag on the source capability (message always comes
        from remote) */

      case RESET_REPLY:

         cap_index = mowse_msgp -> source_major - MIN_CAPABILITY_NUMBER;
         if ((cap_index < 0) || (cap_index > NUMBER_OF_CAT_ENTRIES))
            return (0);
         r_CAT[cap_index].flags &= ~RESET_BIT;
         return (0);

/* : - case REQUEST_CONNECT
     -- get the name of the capability to send connect request to */

      case REQUEST_CONNECT:

         capname_length = min(length - HEADER_LENGTH, CAPABILITY_NAME_LENGTH);
         for (i=0; i < capname_length && mowse_msgp -> msg_data[i] != ' '; i++)
            capname[i] = mowse_msgp -> msg_data[i];
         capname[i] = '\0';

         connect_request_len = min(length-HEADER_LENGTH,WSPAKSIZ);

         for (i=0; i < connect_request_len; i++)
            connect_request_string[i] = mowse_msgp -> msg_data[i];
         connect_request_string[i] = '\0';

/* : - try to find the capability
     - If it is not found then create it */

         cap_num = find_local_capability(capname);
         err_code = 0;
         if (cap_num == 0) {
            set_dta();
            set_trap();
            err_code = system(connect_request_string);
            rst_trap();
            rst_dta();
            cap_num = find_local_capability(capname);
         }

/* : - If the capability still can't be found then send a message
       back to the capability requesting the connection indicating
       that the connect request has failed */

         if ((cap_num == 0) || (err_code != 0)) {
            connect_response_msg.system = mowse_msgp -> source_system;
            connect_response_msg.major = mowse_msgp -> source_major;
            connect_response_msg.minor = RESPONSE_CONNECT;
            connect_response_msg.source_system = WSIBMPC;
            connect_response_msg.source_major = WSMAJCAP;
            return_status = WSREJECT;
            return (send_i_mess(&connect_response_msg,HEADER_LENGTH,&return_status,1));
         }

/* : otherwise send the connect request message onto the capability
     found locally */

         mowse_message.system = WSIBMPC;
         mowse_message.major = cap_num & 0xff;
         mowse_message.minor = REQUEST_CONNECT;
         mowse_message.source_system = mowse_msgp -> source_system;
         mowse_message.source_major = mowse_msgp -> source_major;
         return (send_i_mess(&mowse_message,HEADER_LENGTH,NULL,0));

/* : case SET_SUSPEND
     - set the suspend flag in the remote cat for the sepcified cap */

      case SET_SUSPEND:

         cap_index = mowse_msgp -> source_major - MIN_CAPABILITY_NUMBER;
         if ((cap_index < 0) || (cap_index > NUMBER_OF_CAT_ENTRIES))
            return (0);
         r_CAT[cap_index].flags |= SUSPENDED_BIT;
         return (0);

/* : case RESET_SUSPEND
     - reset the suspend flag in the remote cat for the sepcified cap */

      case RESET_SUSPEND:

         cap_index = mowse_msgp -> source_major - MIN_CAPABILITY_NUMBER;
         if ((cap_index < 0) || (cap_index > NUMBER_OF_CAT_ENTRIES))
            return (0);
         r_CAT[cap_index].flags &= ~SUSPENDED_BIT;
         return (0);

/* : case FAIL CAPABILITY:
     - ignore the message */

      case FAIL_CAPABILITY:

         return (0);

/* : default: Return (invalid minor capability) only if source was not internal */

      default:

         if (mowse_msgp -> source_major == WSMAJCAP)
            return (0);
         mowse_message.system = mowse_msgp -> source_system;
         mowse_message.major = mowse_msgp -> source_major;
         mowse_message.minor = FAIL_CAPABILITY;
         mowse_message.source_system = WSIBMPC;
         mowse_message.source_major = WSMAJCAP;
         return (send_i_mess(&mowse_message,HEADER_LENGTH,NULL,0));
   }
   return(0);
}




		    linebrk.asm                     03/15/88  1602.0rew 03/15/88  1545.9       71703



; ***********************************************************
; *                                                         *
; * Copyright, (C) Honeywell Bull Inc., 1987                *
; *                                                         *
; * Copyright, (C) Honeywell Information Systems Inc., 1986 *
; *                                                         *
; ***********************************************************

; HISTORY COMMENTS:
;  1) change(87-07-04,Flegel), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Created.
;  2) change(88-02-11,Lee), approve(88-02-29,MCR7853),
;     audit(88-03-10,Nakaska):
;     BREAK period made to be based on calculated number of characters
;     sent to the RS232 port while the break bit is set
;                                                      END HISTORY COMMENTS
;
;FUNCTION (line_break)
;
; Send a hard break out the rs232port.  This is used when Multics MOWSE has
; not been attached.

;*/


include dos.mac                   ;Lattice include file
include mowsdefs.mac              ;Constant values
include ws_buf.mac                ; circular buffer macros

;*******************************************************************
;                            DATA
;*******************************************************************
dseg

; ----- Constants ------------------------------------------------------------

MCROUT2_MASK = 11110111b          ; Mask for the out 2 bit in MCR
BRKVAL  = 01000000b               ; Break bit in Line control register
DATA_BITS = 8
START_BITS = 1

; ----- Data Segment ---------------------------------------------------------

frame_bits  dw  11                ; holds number of bits in frame per character

;-------- External declarations

extrn  COM_PORT:word
extrn  lineparm:byte              ; line parameter values from initialize_mowse

;-------- Public Declarations

public frame_bits

endds

page
;*******************************************************************
;                             MAIN
;*******************************************************************
pseg

;--------- External Procedures

public line_break

line_break proc near
        push    ax                ; save registers
        push    bx
        push    cx
        push    dx

; /* determine the baud rate by extracting from the lineparm variable */

        mov     al,lineparm       ; get line parameter values
        mov     cl,5              ; extract highest 3 bits of line parameter
        ror     al,cl             ;   (which specifies the baud)
        and     al,7              ; clear all but lowest 3 bits and see if zero
        jnz     calc_baud         ; 0=B110, 1=B150, 2=B300, ... 7=B9600
   
        mov     ax,110            ; baud is 110, set ax to baud 110
        jmp     short line_break_next

calc_baud:
        mov     cl,al             ; baud is calculated = 75 * (2 ** cl)
        mov     ax,75
        shl     ax,cl

; /* now ax contains the baud number */
; /* determine bytes per quarter second from bits per second (baud) */
; /* determine number of bits per byte assuming: */
; /* 1 start bit, 8 data (or 7 data and 1 parity) bits, N stop */
; /* bits where N is taken from the line parameter value */

line_break_next:
        push    ax                ; save baud
                                  ; bit 2 specifies number of stop bits:
                                  ;   clear is 1 stop bit, set is 2 stop bits
        mov     al,lineparm       ; get line parameter values
        ror     al,1              ; shift til stop bit is least significant bit
        ror     al,1
        and     al,1              ; mask out all other bits
        inc     al                ; convert to actual number of stop bits

        mov     bx,DATA_BITS+START_BITS ; calculate bits per frame
        mov     ah,0
        add     bx,ax             ; add number of stop bits
        shl     bx,1            ; multiply divisor by 4 to get bits per 1/4 sec
        shl     bx,1 
        mov     frame_bits,bx     ; save in divisor location

        pop     ax                ; restore baud rate in ax
        cwd                       ; sign extend ax into dx for division
        div     frame_bits        ; divide to get characters per 1/4 second

        mov     cx,ax             ; load character count into loop counter

; disable modem interrupts which are normally generated when a character
; is sent; the interrupts are handled by MOWSE which looks at the
; output buffer for more characters to send

        mov     dx,COM_PORT       ; get modem control register to turn
        add     dx,MCR            ;     modem interrupts off while doing
        in      al,dx             ;     break

        push    ax                ; save current modem control setting
        and     al,MCROUT2_MASK   ; clear the OUT 2 bit to disable ints.
        out     dx,al             ; disable modem interrupts

        mov     dx,COM_PORT       ; port address in DX
        add     dx,LCR
        in      al,dx             ; get current setting
        or      al,BRKVAL         ; set the send-break bits
        out     dx,al             ; start the break

        push    ax                ; save LCR flags in al

        mov     al,0              ; set arbitrary character to send

line_break_loop:
        call    out_a_byte        ; send until specified number of
        loop    line_break_loop   ;    characters reached

        pop     ax                ; restore LCR flags in al
        xor     al,BRKVAL         ; clear the send-break bits
        out     dx,al             ; stop the break

        pop     ax                ; restore modem control settings
        mov     dx,COM_PORT       ; get address of MCR for
        add     dx,MCR            ;    current COMM port
        out     dx,al             ; restore the MCR settings

        pop     dx                ; restore registers
        pop     cx
        pop     bx
        pop     ax
        ret
line_break endp


;FUNCTION (out_a_byte)
;
; Send a character out to the rs232port.  This routine simply returns 
; on a time out of the send.
; 

out_a_byte proc near

        push ax
        push bx
        push cx
        push dx


;/* : Set up RS232 */

        mov     bl,al             ;Save char to bl temporarily
        mov     dx,MCR            ;Modem control Register
        add     dx,COM_PORT
        mov     al,MCRREAD        ;Out2, DTR, RTS
        out     dx,al
        mov     dx,MSR            ;Modem status Register
        add     dx,COM_PORT

;/* : Wait for CTS (Clear to send) */

OB150:  
        sub     cx,cx             ;timeout count

TIME_LOOP:  
        in      al,dx
        test    al,MSRCTS         ;Clear to send?
        jnz     SEND_CLEAR        ;yes
        loop    TIME_LOOP         ;No, loop til timeout

;/* : Too long, exit */
        jmp     short OBEXIT      ;And QUIT

;/* : Wait for THRE (Transmit Holding Register Empty) */

SEND_CLEAR:
        mov     dx,LSR            ;Line Status register
        add     dx,COM_PORT
        sub     cx,cx             ;Another time out

STATUS_TIMING:
        in      al,dx             ;LSR status
        test    al,LSRTHRE        ;Transmit holding reg empty
        jnz     SEND_CHAR         ;Yes
        loop    STATUS_TIMING     ;No, loop til timeout

;/* : Too long, exit */
        jmp     short OBEXIT      ;And QUIT

;/* : Get line status , send char */

SEND_CHAR:
        mov     ah,al             ;Get line status for return
        and     ah,MASK7          ;mask bit 7
        mov     al,bl             ;restore char to al
        mov     dx,THR            ;transmit holding register
        add     dx,COM_PORT
        out     dx,al             ;Output it to RS232

OBEXIT:  
        pop     dx                ;Restore Registers
        pop     cx
        pop     bx
        pop     ax
        ret

out_a_byte endp

        endps
        end





		    mio.c                           08/07/87  1519.9rew 08/07/87  1435.9      349686



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-01-27,Hoover), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
  2) change(86-09-15,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Changed check-sum from character addition to
     CRC-6.
  3) change(86-09-24,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Changed sndpkt to allow only DisConnect packets
     to be sent when a disconnect is in progress.
  4) change(86-10-15,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Added FastDis for fast (non-confirmed)
     disconnects.
  5) change(86-12-25,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Moved setting of the packetize_flag from
     get_inbuff to prsrst to ensure that it is set only when entire protocol is
     set.
                                                   END HISTORY COMMENTS */

/* : PROGRAM FUNCTION

MIO is the PC module of MOWSE which controls packet communications between
Multics and the PC in order to guarantee error free communications.
*/

/* : NOTES

The following is a description of a packet:

    --------------------------------------------------
   | SOP | TYPE | ... {data} ... | LENGTH | CRC | EOP |
    --------------------------------------------------

Supervisory packets (those which do not carry data) all are of length 5 and
carry no data (ACK, NAK, RST, BRK, and there associated types)
*/

#include <ws_error.h>

/* Special constants */
#define TIME_OUT       1               /* Disconnect timed out */
#define DISCONNECT_OUT 2               /* Disconnect completed */

/* logical Constants */
#define False   0
#define True    1

/* ASCII Control Characters */
#define NULL         0
#define CR           13
#define ESC          27
#define LF           10
#define SI           15
#define SO           14
#define SOH          1
#define MIN_ASCII    32
#define REV_VIDEO    0200
#define Null_Convert 20
#define MASK_ALL     0377
#define MASK_SIX     077

/* Protocol Bit-field Constants */
#define ChnCnt  2                      /* Number of channels */
#define SeqFld  2                      /* Number of bits in sequence field */
#define SeqCnt  4                      /* 2**SeqFld */
#define SeqMsk  3                      /* SeqCnt - 1 */

/* Protocol Byte-field Constants */
#define SOPLen          1              /* Characters in SOP field */
#define TypLen          1              /* Characters in TYPE field */
#define MaxDatLen       124            /* Maximum number of data chars */
#define ChkLen          1              /* Characters in CHECKSUM field */
#define EOPLen          1              /* Characters in EOP field */
#define LenLen          1              /* Characters in Length field */
#define MinPktLen (SOPLen+TypLen+LenLen+ChkLen+EOPLen) /* Minimum chars in Packet */
#define MaxPktLen (MinPktLen+MaxDatLen) /* Maximum chars in Packet */

/* Protocol Packet Constants */
#define BG      0                      /* Background Channel */
#define FG      1                      /* Foreground Channel */
#define RstOff  ' '                    /* <SPACE> */
#define Request 0                      /* Packet request */
#define Confirm 1                      /* Packet confirmation */
#define RstCnt  (Confirm+1)            /* Number of types of reset packets */
#define BrkOff  (RstOff+RstCnt)        /* Break packet base */
#define BrkCnt  (ChnCnt*(Confirm+1))   /* Number of types of break packet */
#define DisCon  (BrkOff+(2*BG))        /* Disconnect packet */
#define FGBrk   (BrkOff+(2*FG))        /* Foreground break packet */
#define DatOff  (BrkOff+BrkCnt)        /* Data packet base */
#define DatCnt  (ChnCnt*SeqCnt*SeqCnt) /* Number of types of data packets */
#define AckOff  (38+DatCnt)            /* Ack packet base */
#define AckCnt  (ChnCnt*SeqCnt)        /* Number of types of Ack packets */
#define NakOff  (AckOff+AckCnt)        /* Nak packet base */
#define NakCnt  (ChnCnt*SeqCnt)        /* Number of types of Nak packets */
#define FastDis (NakOff+NakCnt)        /* Fast disconnect packet */

/* Protocol Parameters */
#define Debug           True
#define RQS             2              /* 'rcvchr's receive queue size */
#define RWS             3              /* Receiver's window size */
#define SWS             3              /* Sender's windo size */
#define LimRTmr         7              /* Limit for receiver timer */
#define LimSTmr         15             /* Limit for sender timer */
#define LimPTmr         30             /* Limit for pending timer */
#define InitDis         1              /* PC initiated disconnection */
#define RespDis         2              /* Multics initiated disconnection */
#define InitRst         1              /* PC initiated reset */
#define RespRst         2              /* Multics initiated reset */
#define REVPOLY         051            /* bit N is coeff of x**(5-N) of CRC generator */
#define INIT_CRC        63             /* Initial value for seed in calculating CRC */
#define Reset_Timer_X   0              /* pending_timer index for reset resends */
#define Dis_Timer_X     1              /* pending_timer index for disconnect resends */
#define Break_Timer_X   2              /* pending_timer index for break resends */

/* Debugging Switches */
#if Debug
   int  dbgpkts = False;               /* show packets */
   int  dbgrejs = False;               /* diagnose rejects */
   int  dbgxchr = False;               /* show extraneous received chars */
#endif

/* Task Control Variables */
int  apv_locked = False;               /* Approving a packet */
int  ds_pending = 0;                   /* Process of disconnecting */
int  ds_timeout = 0;                   /* PC initiation of disconnect timeout */
int  rs_pending = 0;                   /* Process of resetting */
int  br_pending = 0;                   /* Process of a FG break */
int  pending_timer[3] = {0,0,0};       /* Timer on reset/disconnect/break */

/* Receiver Global Variables */
char r_EOP          = LF;              /* End Of Packet char */
char r_ESC[3]       = {ESC, SI, SO};   /* Receiver's 3 ESCape chars */
int  r_ESC_count    = 0;               /* Number of ESCape chars read in */
char r_SOP          = SOH;             /* Start Of Packet char */
int  r_asn[ChnCnt]  = {0, 0};          /* Acked sequence numbers */
char r_esckey       = '\000';          /* Key to decoding 2nd char of esc */
int  r_ignoring[ChnCnt] = {False, False}; /* Ignoring data pending resync */
int  r_pktin        = 0;               /* Next free slot in receive Q */
int  r_pktout       = 0;               /* Head of receive Q */
int  r_psn[ChnCnt]  = {0, 0};          /* Receive packet sequence number */
int  r_timer[ChnCnt] = {0, 0};         /* Time since last ack */
char r_dat[ChnCnt][SeqCnt][1+MaxDatLen];  /* receive data Q */
char r_pkt[RQS+1][1+MaxPktLen];        /* Receive packet */

/* Sender Global Variables */
char s_EOP          = LF;              /* End Of Packet Char */
char s_ESC[3]       = {ESC, SI, SO};   /* Sender's 3 esc chars */
char s_SOP          = SOH;             /* Start Of Packet Char */
int  s_lasn[ChnCnt] = {0, 0};          /* Last Acked sequence number */
int  s_nasn[ChnCnt] = {0, 0};          /* Next Ack to send */
int  s_psn[ChnCnt]  = {0, 0};          /* Packet sequence number */
int  s_timer[ChnCnt] = {0, 0};         /* Time since last ack */
char s_escreq[256]  = {0,1,0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,1,
                       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,
                       1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
                       1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
                       1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
                       1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
                       1,1,1,1};       /* Chars to be esc'ed when sent */
char s_dat[ChnCnt][SeqCnt][1+MaxDatLen]; /* Senders data Q */

/* Current execution modes */
extern int packet_mode;                /* Indicates that packet mode is on */
extern int packetize_flag;             /* Indicates to TE to accumulate packets */
int mowse_terminating = 0;             /* Indicates that MOWSE is terminating */

/**/

/* : PROCEDURE FUNCTION (advtmr)

Advance various timers.  If a timer reaches its limit, it is reset and the
associated time-out action is performed.
*/

advtmr()
{
int  chn;                              /* Channel number */
int  i;
char type;                             /* Type field of packet */

/* : For each channel
     - If receive time limit exceeded then send an ack */

   for (chn = 0; chn < ChnCnt; chn++)
   {  r_timer[chn]++;
      if (r_timer[chn] > LimRTmr)
      {  r_timer[chn] = 0;
         if (s_nasn[chn] != s_lasn[chn])
            sndack(chn);
      }

/* : - If send time limit exceeded then send an ack */

      s_timer[chn]++;
      if (s_timer[chn] > LimSTmr)
      {  s_timer[chn] = 0;
         resend(chn);
      }
   }

/* : Increment the pending timer */

   for (i = 0; i < 3; pending_timer[i++]++);

/* : If limit exceeded on reset packet, then resend */

   if ((rs_pending & InitRst) && (pending_timer[Reset_Timer_X] > LimPTmr))
   {  pending_timer[Reset_Timer_X] = 0;
      type = RstOff + Request;
      sndpkt(type,"");
   }
   if ((rs_pending & RespRst) && (pending_timer[Reset_Timer_X] > LimPTmr))
   {  pending_timer[Reset_Timer_X] = 0;
      type = RstOff + Confirm;
      sndpkt(type,"");
   }

/* : If limit exceeded on disconnect packet
     - set timeout flag if PC initiated, else resend reply */

   if ((ds_pending & InitDis) && (pending_timer[Dis_Timer_X] > LimPTmr))
   {  ds_pending &= ~InitDis;
      ds_timeout = TIME_OUT;
   }

   if ((ds_pending & RespDis) && (pending_timer[Dis_Timer_X] > LimPTmr))
   {  pending_timer[Dis_Timer_X] = 0;
      type = DisCon + Confirm;
      sndpkt(type,"");
   }

/* : If limit exceeded on break packet, then resend */

   if ((br_pending) && (pending_timer[Break_Timer_X] > LimPTmr))
   {  pending_timer[Break_Timer_X] = 0;
      type = FGBrk + Request;
      sndpkt(type,"");
   }
}

/**/

/* : PROCEDURE FUNCTION (apvpkt)

Approve packet.  If packet appears valid, dispatch it to the appropriate
routine; otherwise, reject it.
*/

apvpkt (pkt)

char pkt[];     /* The packet to be approved */
{
int  chkidx;    /* Check index for checksum character */
int  lenidx;    /* Length index for length character */
int  pktl;      /* Packet length */
int  type;      /* Packet type */
int  i;


/* : If packet is too short or too long, reject it. */

   pktl = pkt[0] & MASK_ALL;
   if (pktl < MinPktLen || pktl > MaxPktLen)
   {
#if Debug
      if (dbgrejs)
      {  if (dbgpkts)
            sdbgpkt("RcvPkt/", &pkt[1], pktl);
         sdbgmsg("RejPkt/length");
      }
#endif
      return;
   }

/* : If check-length is incorrect, reject packet */

   lenidx = pktl - EOPLen - ChkLen - LenLen + 1;
   if (check_len (pktl + r_ESC_count) != pkt[lenidx])
   {
#if Debug
      if (dbgrejs)
      {  if (!dbgpkts)
            sdbgpkt("RcvPkt/", &pkt[1], pktl);
         sdbgmsg("RejPkt/chklen");
      }
#endif
      return;
   }

/* : If check-sum is incorrect, reject packet. */

   chkidx = lenidx + LenLen;
   if (chkcrc(&pkt[1], chkidx-1) != pkt[chkidx])
   {
#if Debug
      if (dbgrejs)
      {  if (!dbgpkts)
            sdbgpkt("RcvPkt/", &pkt[1], pktl);
         sdbgmsg("RejPkt/chksum");
      }
#endif
      return;
   }

/* : If packet type is valid, dispatch accordingly; else reject packet. */

   type = pkt[SOPLen + 1];
   if ((DatOff <= type && type < DatOff+DatCnt) && !rs_pending)
      prsdat(pkt);
   else if ((AckOff <= type && type < AckOff+AckCnt) && !rs_pending)
      prsack(pkt);
   else if ((NakOff <= type && type < NakOff+NakCnt) && !rs_pending)
      prsnak(pkt);
   else if ((BrkOff <= type && type < BrkOff+BrkCnt) && !rs_pending)
      prsbrk(pkt);
   else if (RstOff <= type && type < RstOff+RstCnt)
      prsrst(pkt);
   else if (FastDis == type)
      disconnect_confirm (True);
   else
   {
#if Debug
      if (dbgrejs)
      {  if (!dbgpkts)
            sdbgpkt("RcvPkt/", &pkt[1], pktl);
         sdbgmsg("RejPkt/type");
      }
#endif
      return;
   }
}

/**/

/* : PROCEDURE FUNCTION (check_len)

Calculate the checklength character based on the length of the entire packet
strip the upper bits, and  add 32 to make it printable.
*/

/* : RETURNS:

The calculated check length chartacter.
*/

int check_len(length)

int  length;    /* Length to be converted */
{

   return ((length & MASK_SIX) + MIN_ASCII);
}

/**/

/* : PROCEDURE FUNCTION

Calculate a 6-bit CRC for a character based on a generator polynomial of

           x**6 + x**5 + x**2 + x**0
*/

/* : RETURNS

A value in range of 0-63 which is the desired CRC.
*/

/* : NOTES

The result of this function is the remainder produced by synthetic division
modulo 2 of a 7-bit integer (whose bits are the coefficients of the generator
polynomial) into a 14-bit integer (whose top 8 bits are those of the character,
in reverse order, and whose low 6 bits are the low 6 bits of the seed).

The CRC for a string of characters is calculated by calling 'crc_char' once for
each character inthe block, from first character to last.  The seed for the
first character is the 0 and the seed for each remaining character is the CRC
produced for the previous character.  The CRC produced for the last character
is the CRC for the whole string.
*/

int crc_char (p_chr, p_seed)

int  p_seed;   /* Value in range of 0-63 which is the seed for the CRC calc */
char p_chr;    /* Char for which CRC is to be calced */
{
int  b;        /* Bit counter */
int  crc;      /* accumulator for CRC */
int  q;        /* next quotient bit of the division */
int  schr;     /* rank of 'chr' shifted right 'b' times */

   crc = p_seed;
   schr = p_chr;

/* : For each of the 8 bits in the character
     - q = low bit, if q set then right shift crc
     - right shift schr */

   for (b = 0; b < 8; b++)
   {  q = (crc + schr) & 1;
      crc >>= 1;
      if (q)
         crc ^= REVPOLY;
      schr >>= 1;
   }
   return (crc);
}

/**/

/* : PROCEDURE FUNCTION (chkcrc)

Calculate the printable ascii value of the CRC for the packet provided.
*/

/* : RETURNS

The desired CRC.
*/

int chkcrc(str, strl)

char str[];     /* Address of string */
int  strl;      /* Length of string */
{
int  i;
int  crc;       /* Accumulating CRC */

/* : CRC the ranks of the characters in the string. */

   crc = INIT_CRC;
   for (i = 0; i < strl; i++)
   {  crc = crc_char (str[i], crc);
   }

/* : Make it ASCII character between ' ' and '\177'. */

     return (crc + MIN_ASCII);
}

/**/

/* : PROCEDURE FUNCTION (disconnect_confirm)

Set up all necessary flags to indicate that disconnection has been accepted and
send a confirm to the confirm if one is needed.
*/

disconnect_confirm(p_fast)

int  p_fast;    /* Set to true for a fast (non-confirmed) disconnect */
{
char type;      /* Packet type to send */

/* : If PC initiated disconnection, then send confirm to confirm */

   if ((ds_pending & InitDis) && (!p_fast))
   {  ds_timeout = DISCONNECT_OUT;
      ds_pending = 0;
      type = DisCon + Confirm;
      sndpkt (type,"");
      return (0);
   }

/* : Set up the terminating flags accordingly */

   mowse_terminating = True;
   ds_pending = 0;
   packet_mode = False;
   packetize_flag = False;
   reset();
}

/**/

/* : PROCEDURE FUNCTION (getdat)

Get any available received data.
*/

/* : RETURNS

The number of characters stored in the buffer (between 0 and MaxDatLen,
inclusive).
*/

int getdat(chn, data)

int  chn;       /* Channel */
char *data;     /* Address off buffer to receive data */
{
char *rdat;     /* Data string */
int  i;
int  rdatl;     /* Length of receive data */

/* : If the received data queue is empty, there is nothing to do. */

   if (r_psn[chn] == s_nasn[chn])
      return 0;

/* : Extract the data in the head element of the queue. */

   rdat = &r_dat[chn][s_nasn[chn]][1];
   rdatl = rdat[-1] & MASK_ALL;
   for (i = 0; i < rdatl; i++)
   {  data[i] = rdat[i];
   }
   s_nasn[chn] = (s_nasn[chn] + 1) & SeqMsk;

/* : If the receive window is nearly full, send an Ack to keep it open. */

   if (((s_nasn[chn] - s_lasn[chn]) & SeqMsk) >= RWS-1)
      sndack(chn);

   return(rdatl);
}

/**/

/* : PROCEDURE FUNCTION (prsack)

Parse an Ack-packet.  If the packet is valid, flow control information is
updated accordingly.
*/

prsack(pkt)

char pkt[];     /* The ack-packet to be parsed */
{
int  asn;       /* Ack sequence number */
int  asn_valid; /* Valid Ack sequence number */
int  chn;       /* Channel of ack */
int  fields;    /* Fields of packet */

/* : If packet length incorrect, reject packet. */

   if (pkt[0] != MinPktLen)
   {
#if Debug
      if (dbgrejs)
      {  if (!dbgpkts)
            sdbgpkt("RcvPkt/", &pkt[1], pkt[0] & MASK_ALL);
         sdbgmsg("RejAck/length");
      }
#endif
      return;
   }

/* : Extract the acknowledgement sequence number and channel number. */

   fields = pkt[SOPLen+1] - AckOff;
   asn = fields & SeqMsk;
   chn = fields >> SeqFld;

/* : If the acknowledgement sequence number is invalid, reject packet. */

   if (r_asn[chn] <= s_psn[chn])
      asn_valid = (r_asn[chn] <= asn && asn <= s_psn[chn]);
   else
      asn_valid = (r_asn[chn] <= asn || asn <= s_psn[chn]);
   if (!asn_valid)
   {
#if Debug
      if (dbgrejs)
      {  if (!dbgpkts)
            sdbgpkt("RcvPkt/", &pkt[1], pkt[0] & MASK_ALL);
         sdbgmsg("RejAck/asn");
      }
#endif
      return;
   }

/* : Save the new acknowledgement sequence number. */

   r_asn[chn] = asn;
}

/**/

/* : PROCEDURE FUNCTION (prsbrk)

Parse a Break-packet.
*/

/* : NOTES

There are two types of break packets - one is the foreground break which serves
to interrupt a foreground activity (not possible on the PC) and the other is
the background break which provides a mechanism for disabling MOWSE on Multics
and to leave the communications open to non-MOWSE Multics
*/

prsbrk (pkt)

char pkt[];     /* The packet to be parsed */
{
char type;      /* Type field of packet */

/* : If a Disconnect then send a confirmation to Multics */

   if ((pkt[SOPLen+1] == DisCon + Request) && !ds_pending)
   {  ds_pending = ds_pending | RespDis;
      pending_timer[Dis_Timer_X] = 0;
      type = DisCon + Confirm;
      sndpkt (type,"");
   }

/* : If a Disconnect confirmation, then all done and shut off protocol modes */

   else if (pkt[SOPLen + 1] == DisCon + Confirm)
   {  pending_timer[Dis_Timer_X] = 0;
      disconnect_confirm(0);
   }

/* : If a Foreground break request then handle accordingly */

   else if (pkt[SOPLen + 1] == FGBrk + Request)
   {
   }

/* ; If a Foreground break confirm then handle accordingly */
   else if (pkt[SOPLen + 1] == FGBrk + Confirm)
   {  pending_timer[Break_Timer_X] = 0;
      br_pending = False;
      type = FGBrk + Confirm;
      sndpkt(type,"");
   }
}

/**/

/* PROCEDURE FUNCTION (prsdat)

Parse a Data-packet.  If the packet is valid, the data is stored in the receive
data queue.
*/

prsdat(pkt)

char pkt[];     /* The packet to be parsed */
{
char *data;     /* Accepted data buffer */
char *rdat;     /* Received data */
int  asn;       /* Ack sequence number */
int  asn_valid; /* Accept sequence number valid */
int  chn;       /* Channel */
int  datal;     /* Length of data */
int  fields;    /* Type field */
int  i;
int  psn;       /* Packet sequence number */

/* : Extract the acknowledgement sequence number, packet sequence number and
     channel number from the type char. */

   fields = pkt[SOPLen + 1] - DatOff;
   asn = fields & SeqMsk;
   psn = (fields >> SeqFld) & SeqMsk;
   chn = fields >> (SeqFld + SeqFld);

/* : If the acknowledgement sequence number is invalid, reject the packet. */

   if (r_asn[chn] <= s_psn[chn])
      asn_valid = (r_asn[chn] <= asn && asn <= s_psn[chn]);
   else
      asn_valid = (r_asn[chn] <= asn || asn <= s_psn[chn]);
   if (!asn_valid)
   {
#if Debug
      if (dbgrejs)
      {  if (!dbgpkts)
            sdbgpkt("RcvPkt/", &pkt[1], pkt[0] & MASK_ALL);
         sdbgmsg("RejDat/asn");
      }
#endif
      return;
   }

/* : Save the new acknowledgement sequence number. */

   r_asn[chn] = asn;

/* : If ds_pending then ignore all data */

   if (ds_pending)
      return;

/* : If the send sequence number is not the one we expect, send a Nak-packet,
     (unless one has already been sent) and ignore this packet. */

   if (psn != r_psn[chn])
   {  if (!r_ignoring[chn])
      {  sndnak(chn);
         r_ignoring[chn] = True;
      }
#if Debug
      if (dbgrejs)
      {  if (!dbgpkts)
            sdbgpkt("RcvPkt/", &pkt[1], pkt[0] & MASK_ALL);
         sdbgmsg("RejDat/psn");
      }
#endif
      return;
   }

/* : Accept the data. */

   data = &pkt[SOPLen + TypLen + 1];
   datal = (pkt[0] & MASK_ALL) - MinPktLen;
   rdat = &r_dat[chn][psn][1];
   rdat[-1] = datal;
   for (i = 0; i < datal; i++)
   {  rdat[i] = data[i];
   }
   r_ignoring[chn] = False;
   r_psn[chn] = (psn + 1) & SeqMsk;
}

/**/

/* : PROCEDURE FUNCTION (prsnak)

Parse a Nak-packet.  If the packet is valid, any data packets that have been
sent but are not acknowledged by this Nak-packet are resent.
*/

prsnak(pkt)

char pkt[];     /* The Nak-packet to be parsed */
{
int asn;        /* Ack sequence number */
int asn_valid;  /* Valid ack sequence number */
int chn;        /* Channel */
int fields;     /* Type field of packet */

/* : If packet length is incorrect, reject the packet. */

   if (pkt[0] != MinPktLen)
   {
#if Debug
      if (dbgrejs)
      {  if (!dbgpkts)
            sdbgpkt("RcvPkt/", &pkt[1], pkt[0] & MASK_ALL);
         sdbgmsg("RejNak/length");
      }
#endif
      return;
   }

/* : Extract the acknowledgement sequence number and the channel number from
     the type byte. */

   fields = pkt[SOPLen + 1] - NakOff;
   asn = fields & SeqMsk;
   chn = fields >> SeqFld;

/* : If the acknowledgement sequence number is invalid, reject the packet. */

   if (r_asn[chn] <= s_psn[chn])
      asn_valid = (r_asn[chn] <= asn && asn <= s_psn[chn]);
   else
      asn_valid = (r_asn[chn] <= asn || asn <= s_psn[chn]);
   if (!asn_valid)
   {
#if Debug
      if (dbgrejs)
      {  if (!dbgpkts)
            sdbgpkt("RcvPkt/", &pkt[1], pkt[0] & MASK_ALL);
         sdbgmsg("RejNak/asn");
      }
#endif
      return;
   }

/* : Save the new acknowledgement sequence number. */

   r_asn[chn] = asn;

/* : Resend any data in the send data queue. */

   resend(chn);
}

/**/

/* PROCEDURE FUNCTION (prsrst)

Parse a Reset-packet.  When a reset is complete, set the packetize flag to true
which indicates that protocol is set up completely.
*/

prsrst(pkt)

char pkt[];     /* The reset packet to be parsed */
{
char type;      /* Type field of a packet */

/* : If in process of disconnecting then ignore */

   if (ds_pending)
      return (0);

/* : If Multics requested reset: reset and send confirmation and pretend reset
     in packet queue */

   if (pkt[SOPLen+1] == RstOff + Request)
   {  rs_pending = rs_pending | RespRst;
      reset();
      r_pktin = 1;
      type = RstOff + Confirm;
      sndpkt(type, "");
   }

/* : Else if confirmation */

   else if (pkt[SOPLen + 1] == RstOff + Confirm)
   {  if (rs_pending & InitRst)
      {  pending_timer[Reset_Timer_X] = 0;
         type = RstOff + Confirm;
         sndpkt (type, "");
      }
      packetize_flag = True;
      rs_pending = 0;
   }
}

/**/

/* PROCEDURE FUNCTION (rcvchr)

To receive the next character detected by the interrupt handler for input from
the remote.  If the character is valid, it is added to the packet currently
being assembled.
*/

rcvchr(chr)

char chr;       /* The character received by the interrupt handler */
{
static int EndPkt = 1;
static int ExtChr = 2;
static int LngPkt = 3;
static int NoRoom = 4;

int  dbgmsg;    /* Accumulating debug message */
int  nextin;    /* Next packet in */
int  pktl;      /* Packet length */
int  test_ds;   /* Tests if ds_pending is set before processing data */
char *pkt;      /* Accumulating packet */

/* : If character is a null then ignore it (network created it) */

   if (!chr)
      return;

/* : Replace Null_Convert characters with a NULL character */

   if (chr == Null_Convert)
      chr = NULL;

   dbgmsg = 0;

/* : Assemble packet in next slot of received packet queue. */

   pkt = r_pkt[r_pktin];

/* : If the received char is the SOP char, start a new packet. */

   if (chr == r_SOP)
   {  r_esckey = '\000';
      pkt[0] = 1;
      pkt[1] = chr;
   }

/* : Else if we are not assembling a packet, discard the received char. */

   else if (pkt[0] == 0)
   {  dbgmsg = ExtChr;
   }

/* : Else if the received char is the EOP char, append it to the packet.
     If there is room in the received packet queue, make the packet visible (by
     updating the "in" pointer); otherwise flush the packet. */

   else if (chr == r_EOP)
   {  dbgmsg = EndPkt;
      pktl = ++pkt[0] & MASK_ALL;
      pkt[pktl] = chr;

      if (r_pktin < RQS)
         nextin = r_pktin + 1;
      else
         nextin = 0;

      if (nextin != r_pktout)
      {  r_pktin = nextin;
         r_pkt[r_pktin][0] = 0;
      }
      else
      {  dbgmsg = NoRoom;
         pkt[0] = 0;
      }
   }

/* : Else append the character (or what it stands for if it was preceded
     by an escape character) to the buffer, unless it is an escape
     character.  If this fills the packet (in which case there will be
     no room for the EOP character), flush the packet. */

   else
   {  if (r_esckey != '\000')
      {  chr = chr ^ r_esckey;
         r_esckey = '\000';
         r_ESC_count++;
      }
      else if (chr == r_ESC[0])
         r_esckey = '\100';
      else if (chr == r_ESC[1])
         r_esckey = '\200';
      else if (chr == r_ESC[2])
         r_esckey = '\300';

      if (r_esckey == '\000')
      {  pktl = ++pkt[0] & MASK_ALL;
         pkt[pktl] = chr;
         if (pktl >= MaxPktLen)
         {  dbgmsg = LngPkt;
            pkt[0] = 0;
         }
      }
   }

/* : Print any debugging messages. If printable, send as is, otherwise convert
     it to octal, preceed it with \ */
#if Debug
   if (dbgmsg != 0)
   {  if (dbgmsg == ExtChr)
      {  if (dbgxchr)
         {  if (chr >= ' ' && chr <= '~')
               sdbgchr(chr + REV_VIDEO);
            else
            {  sdbgchr('\\' + REV_VIDEO);
               sdbgchr(((chr>>6) & 3) + '0' + REV_VIDEO);
               sdbgchr(((chr>>3) & 7) + '0' + REV_VIDEO);
               sdbgchr((chr & 7) + '0' + REV_VIDEO);
            }
         }
      }
      else
      {  if (dbgpkts)
            sdbgpkt("RcvPkt/", &pkt[1], pktl);
         if (dbgrejs)
         {  if (dbgmsg == LngPkt)
            {  if (!dbgpkts)
                  sdbgpkt("RcvPkt/", &pkt[1], pktl);
               sdbgmsg("RejPkt/LngPkt");
            }
            else if (dbgmsg == NoRoom)
            {  if (!dbgpkts)
                  sdbgpkt("RcvPkt/", &pkt[1], pktl);
               sdbgmsg("RejPkt/NoRoom");
            }
         }
      }
   }
#endif

/* : If we were approving packets when we were interrupted to receive the
     character just processed, we want to simply return so that approving can
     continue.  If we were not approving packets and the received packet queue
     is not empty, then we want to initiate approving.
*/
   if (!apv_locked)
   {  apv_locked = (r_pktin != r_pktout);
      while (apv_locked)
      {  test_ds = ds_pending;
         apvpkt(r_pkt[r_pktout]);
         r_ESC_count = 0;
         if (r_pktout < RQS)
            r_pktout++;
         else
            r_pktout = 0;
         apv_locked = (r_pktin != r_pktout);

         if ((test_ds & ds_pending) & RespDis)
            disconnect_confirm(0);
      }
   }
}

/**/

/* : PROCEDURE FUNCTION (resend)

Resend all unacknowledged data for a channel.
*/

resend(chn)

int  chn;       /* Channel number */
{
int  psn;       /* Packet sequence number */
char type;      /* Packet type */

/* : Resend each packet */

   for (psn = r_asn[chn]; psn != s_psn[chn]; psn = (psn + 1) & SeqMsk)
   {  type = (((chn << SeqFld) + psn) << SeqFld) + s_nasn[chn] + DatOff;
      sndpkt(type, s_dat[chn][psn]);
      s_lasn[chn] = s_nasn[chn];
      s_timer[chn] = 0;
   }
}

/**/

/* PROCEDURE FUNCTION (reset)

To intialize the flow-control related variables of the protocol.
*/

reset()

{
int  chn;       /* Channel number */
int  i;

   apv_locked = False;
   ds_pending = 0;
   br_pending = 0;
   for (i = 0; i < 3; pending_timer[i++] = 0);

   for (i = 0; i <= RQS; i++)
   {  r_pkt[i][0] = 0;
   }
   r_pktin = 0;
   r_pktout = 0;

   for (chn = 0; chn < ChnCnt; chn++)
   {  for (i = 0; i < SeqCnt; i++)
      {  r_dat[chn][i][0] = 0;
      }
      r_ignoring[chn] = False;
      r_asn[chn] = 0;
      r_psn[chn] = 0;
      r_timer[chn] = 0;

      for (i = 0; i < SeqCnt; i++)
      {  s_dat[chn][i][0] = 0;
      }
      s_lasn[chn] = 0;
      s_nasn[chn] = 0;
      s_psn[chn] = 0;
      s_timer[chn] = 0;
   }
}

/**/

#if Debug

/* : PROCEDURE FUNCTION (sdbgmsg)

Send a debugging message.
*/

sdbgmsg(msg)

char msg[];     /* Message to be shown */
{
int  i;

/* : Send CR/LF and a reverse video '('. */

   sdbgchr(CR);
   sdbgchr(LF);
   sdbgchr('(' + REV_VIDEO);

/* : Send the message. */

   for (i = 0; msg[i] != '\000'; i++)
   {  sdbgchr(msg[i]);
   }

/* : Send a reverse-video ')' and CR/LF. */

   sdbgchr(')' + REV_VIDEO);
   sdbgchr(CR);
   sdbgchr(LF);
}
#endif

/**/

#if Debug

/* : PROCEDURE FUNCTION (sdbgpkt)

Send a debugging message that displays a packet.
*/

sdbgpkt(msg, pkt, pktl)

char msg[];     /* Message to be displayed */
char pkt[];     /* Debug packet */
int  pktl;      /* Length of packet */
{
char chr;       /* Temporary char space */
int  i;

/* : Send CR/LF and a reverse-video '('. */

   sdbgchr(CR);
   sdbgchr(LF);
   sdbgchr('(' + 128);

/* : Send the message describing the packet. */

   for (i = 0; msg[i] != '\0'; i++)
   {  sdbgchr(msg[i]);
   }

/* : Send the packet with nonprintable characters replaced by an octal
     escape sequence. */

   for (i = 0; i < pktl; i++)
   {  chr = pkt[i];
      if (chr >= ' ' && chr <= '~')
         sdbgchr(chr);
      else
      {  sdbgchr('`');
         sdbgchr(((chr>>6) & 3) + '0');
         sdbgchr(((chr>>3) & 7) + '0');
         sdbgchr((chr & 7) + '0');
      }
   }

/* : Send a reverse-video ')' and CR/LF. */

   sdbgchr(')' + 128);
   sdbgchr(CR);
   sdbgchr(LF);
}
#endif

/**/

/* PROCEDURE FUNCTION (sndack)

Send an Ack-packet.
*/

sndack(chn)

int  chn;       /* The channel to send the Ack along */
{
char type;      /* Type field */

   type = (chn << SeqFld) + s_nasn[chn] + AckOff;
   sndpkt(type, "");
   s_lasn[chn] = s_nasn[chn];
   r_timer[chn] = 0;
}

/**/

/* PROCEDURE FUNCTION (sndbrk)

Send a Break-packet to signal a break on the foreground channel.
*/

sndbrk()

{
char type;      /* A packet type field */

/* : Set up break processing protocol */

   br_pending = True;
   pending_timer[Break_Timer_X] = 0;

/* : Send the break message */

   type = FGBrk + Request;
   sndpkt (type, "");
}

/**/

/* PROCEDURE FUNCTION (snddat)

To queue and then send data to the remote.
*/

/* : RETURNS

   -1 => sum of lengths of strings to be sent exceeds 'MaxDatLen'.
    0 => data sent.
    1 => couldn't send data because send window was full.
    2 => couldn't send because reset is pending.

*/

int snddat(chn, datac, datap, datal)

int  chn,       /* Channel number */
     datac,     /* Count of number of strings to be sent */
     datal[];   /* Array of lengths of strings to be sent */
char *datap[];  /* Array of pointers to the strings to be sent */
{
static int TooLong = -1;
static int SentDat = 0;
static int WdwFull = 1;
static int RstPnd  = 2;

char *sdat;     /* Send data pointer */
char type;      /* Type field */
int  i;
int  j;
int  l;
int  spsn;      /* Send packet sequence number */

/* : If resetting or not talking yet, then return */

   if ((rs_pending) || (!packetize_flag))
      return RstPnd;

/* : Reject the data if the send data queue is full. */

   spsn = s_psn[chn];
   if (((spsn - r_asn[chn]) & SeqMsk) >= SWS)
      return WdwFull;

/* : Catenate the data to be sent in the next slot of the send data queue. */

   sdat = s_dat[chn][spsn];
   sdat[0] = 0;
   l = 0;
   for (i = 0; i < datac; i++)
   {  for (j = 0; j < datal[i]; j++)
      {  if (l < MaxDatLen)
            sdat[++l] = datap[i][j];
         else
            return TooLong;
      }
   }
   sdat[0] = l;

/* : Return if there is nothing to send. */

   if (l == 0)
      return SentDat;

/* : Make the catenated data visible by updating the packet sequence number. */

   s_psn[chn] = (spsn + 1) & SeqMsk;

/* : Send the data and reset resend timer. */

   type = (((chn << SeqFld) + spsn) << SeqFld) + s_nasn[chn] + DatOff;
   sndpkt(type, sdat);
   s_lasn[chn] = s_nasn[chn];
   r_timer[chn] = 0;
   s_timer[chn] = 0;
   return SentDat;
}

/**/

/* : PROCEDURE FUNCTION (snddis)

Initiate a disconnection from MOWSE on Multics.
*/

snddis()

{
char type;      /* Type field of message */

/* : If in not in packet/protocol mode then reject request */

   if (!packetize_flag || !packet_mode)
      return (WSNOTACT);

/* : If a disconnection is currently in progress, ignore it */

   if (ds_pending)
      return (WSDISPEN);

/* : If timeout has occurred, return timeout error */

   if (ds_timeout & TIME_OUT)
   {  ds_timeout = 0;
      return (TIME_OUT);
   }

/* : If got response, reply that Multics is still active */

   if (ds_timeout & DISCONNECT_OUT)
   {  ds_timeout = 0;
      return (DISCONNECT_OUT);
   }

/* : Initiate disconnection by sending Disconnect request to Multics */

   ds_pending |= InitDis;
   ds_timeout = 0;
   type = DisCon + Request;
   sndpkt (type, "");
   return (WSDISPEN);
}

/**/

/* PROCEDURE FUNCTION (sndnak)

Send a Nak-packet to the remote.
*/

sndnak(chn)

int  chn;       /* The channel on which to send the Nak-packet */
{
char type;      /* Type field of the packet */

   type = (chn << SeqFld) + /*r_psn*/s_nasn[chn] + NakOff;
   sndpkt(type, "");
   return (0);
}

/**/

/* PROCEDURE FUNCTION (sndpkt)

Send a packet to the remote.
*/

/* : NOTES

If MOWSE is not in packet mode state, then packets will not be sent as they
will go to the remote's command processor.

The packet to be sent is built in the local buffer 'pkt' and then sent to the
remote all at once.  The space required for this buffer could be saved if the
packet were sent to the remote a character at a time.  This was not done
because the time to execute a call to the routine that sends data to the remote
is greater than that to add a character to a buffer, and because to send the
packet in pieces would require that interrupts be inhibited for the duration of
the execution of 'sndpkt' in order to prevent it from being re-entered. 

Data outside the range ' ' through '_' for which the corresponding element of
's_escreq' is set is replaced in the packet via a two character escape sequence
consisting of an element of the array "s_ESC" followed by a printable ASCII
character between ' ' and '_'.  These two characters are chosen such that the
exclusive-or of the second with 64 times the ordinal in 's_ESC' of the first
yields the character they represent. 

The replacement of data characters via two character escape sequences has no
effect upon the checksum of the packet:  The checksum is calculated using the
original data characters rather than those actually sent in the data field of
the packet.  This allows the receiver of the packet to revert escape sequences
as soon as they are encountered.
*/

sndpkt(type, data)

char type;      /* Type field of message */
char data[];    /* Data of message */
{
static int EscKey[3]    = {1*64, 2*64, 3*64},
           GrpEscIdx[8] = {0, -1, -1, 0, 2, 1, 1, 2};

int  crc;                              /* CRC character */
int  chr;                              /* Character */
int  datal;                            /* Length of data */
int  escidx;                           /* Escape index */
int  i;
int  group;                            /* Group number of escape character */
int  pktl;                             /* Packet length */
char pkt[MinPktLen + 2*MaxDatLen];     /* Accumulating send packet */

/* : If not in packet mode (remote not MOWSE active), return */

   if (!packet_mode)
      return (0);

/* : If a disconnect is in progress and the type is not one of the disconnect
     packets, return */

   if (ds_pending && ((type != DisCon + Request) && (type != DisCon + Confirm)))
      return(0);

/* : Assemble the packet.  Insert escape sequences as required. */

   pkt[0] = s_SOP;
   pkt[1] = type;
   crc = crc_char (pkt[0], INIT_CRC);
   crc = crc_char (pkt[1], crc);
   pktl = 2;
   datal = data[0] & MASK_ALL;
   for (i = 1; i <= datal; i++)
   {  chr = data[i] & MASK_ALL;
      crc = crc_char ((char)chr, crc);
      group = chr >> 5;                /* Divide char by 32 to get group number */
      escidx = GrpEscIdx[group];
      if (escidx >= 0 && s_escreq[chr])
      {  pkt[pktl] = s_ESC[escidx];
         pktl++;
         chr ^= EscKey[escidx];
      }
      pkt[pktl] = chr;
      pktl++;
   }

/* : Insert the control information */

   pkt[pktl] = check_len (pktl + LenLen + ChkLen + SOPLen);
   crc = crc_char (pkt[pktl], crc);
   pktl++;
   pkt[pktl] = crc + MIN_ASCII;
   pktl++;
   pkt[pktl] = s_EOP;
   pktl++;

/* : Send the packet to the remote. */

   smdmstr(&pkt[0], pktl);

#if Debug
   if (dbgpkts)
   {  sdbgpkt("SndPkt/", &pkt[0], pktl);
   }
#endif
}

/**/

/* : PROCEDURE FUNCTION (sndrst)

Send a Reset-packet.
*/

sndrst()

{
char type;      /* Packet type field */

/* : If currently resetting, ignore */

   if (rs_pending)
      return (0);

/* : Send reset */

   rs_pending = rs_pending | InitRst;
   reset();
   type = RstOff + Request;
   sndpkt(type, "");
}




		    mowse.c                         08/23/88  0817.7rew 08/23/88  0815.0      216540



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-01-01,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
  2) change(86-01-20,ASmith), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Documentation and added call to getc_buff and allocated space for unions.
  3) change(86-05-07,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
     install(87-08-07,MR12.1-1072):
     Added call to init_cat, allocated cat tables.
  4) change(86-08-25,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Modified documentation.
  5) change(86-08-27,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Installed /M option.
  6) change(86-09-17,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Extracted option parsing into separate routine and installed start-up
     file support (/F).
  7) change(87-03-15,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Re-wrote argument processing, it was wrong before.
  8) change(87-03-24,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Added /E and /N options to allow access to escaping special characters
     and specifying that the connection will be via network.
  9) change(88-01-26,Flegel), approve(88-02-29,MCR7853),
     audit(88-03-10,Nakaska), install(88-03-15,MR12.2-1036):
     Added /H option to hold DTR high when connecting.
 10) change(88-06-17,Lee), approve(88-07-18,MCR7936), audit(88-08-10,Flegel),
     install(88-08-23,MR12.2-1091):
     Added support for Mark and Space parity.
                                                   END HISTORY COMMENTS */

/* :  PROCEDURE FUNCTION (MOWSE):

MOWSE command which loads MOWSE into PC memory.
*/

/* : NOTES:

The following is a list of command line options:

         /B - baud
         /C - communications port
         /D - data bits
         /E - escape character
         /F - start_up file
         /G - debug packets
         /H - hold DTR
         /I - user interrupt
         /L - autoload capability
         /M - turn on communications' error messages
         /N - Network connection
         /P - parity
         /S - stop bits
*/

#include <dos.h>
#include <stdio.h>
#include <fcntl.h>
#include <ws.h>
#include <mowsdefs.h>
#include <alloc.h>
#include <cat.h>
#include <ws_fgb.h>
#include <ws_auto.h>
#include <emulator.h>

#define BADARG       -1                /* Invalid parameter */
#define BADOPTION    -2                /* Invalid option */
#define OVERLOAD     -3                /* Too many autoload capabilities */
#define EXPECTING    -4                /* Argument expected */
#define BADCONTROL   -5                /* Option specifier ('/') expected */

#define OPTION_BUILT         001        /* Completed option */
#define PARAM_BUILT          002        /* Completed parameter */
#define OPTION_PENDING       004        /* Expecting option char */
#define PARAM_PENDING        010        /* Expecting one word of parameter */
#define READ_FILE            020        /* Start_up file specified */

#define DEFAULT_BAUD         B9600
#define DEFAULT_PARITY       EVEN_PAR
#define DEFAULT_STOP         STOP1
#define DEFAULT_DATAB        DATA7
#define DEFAULT_SOFTNO       97
#define DEFAULT_COM_PORT     0x3f8
#define DEFAULT_COM_NO       0
#define DEFAULT_MASK8259     0xef
#define DEFAULT_HARDINTRPT   0xc
#define DEFAULT_ERROR_MODE   0

#define WS_MEMORY_SIZE   2048 /* Size of MOWSE memory (4096 until MOWSE got too big) */

extern AUTO load_list[];      /* Autoload list of capabilities */
extern int load_list_pending; /* Autoload pending */
extern int _TOP;              /* TOP of stack as defined by C compiler */
extern int dbgpkts;           /* =1, to show level 2 packets */
extern int dbgrejs;           /* =1, to show rejected level 2 packets */
extern int dbgxchr;           /* =1, tp show extraneous received characters */
extern char s_escreq[256];    /* escape character flags */
extern char s_EOP;            /* Sender EOP character */
extern char r_EOP;            /* Receiver EOP character */
int        datab;             /* Data bit parameter */
int        _stack = 12288;    /* MOWSE needs a large runtime stack */
int        SOFTNO;            /* Software interrupt number for sub. library */
int        COM_PORT;          /* hardware address of comm port */
int        COM_NO;            /* number of comm port (COM1 or COM2)   */
char       MASK8259;          /* mask for setting enabling hardware interrupts */
int        HARDINTRPT;        /* hardware interrupt number */
int        packetize_flag;    /* Current packet mode */

local_cat       l_CAT [ NUMBER_OF_CAT_ENTRIES ]; /* Local CAT */
remote_cat      r_CAT [ NUMBER_OF_CAT_ENTRIES ]; /* Remote CAT */
int             NEW_INSTANCE_;

char            fg_memory[WS_MEMORY_SIZE];  /* Foreground linked list buffer */
struct allocstr fgastr,
                *fgaptr;

char            bg_memory[WS_MEMORY_SIZE];  /* Background linked list buffer */
struct allocstr bgastr,
                *bgaptr;

struct allocstr lcastr,
                *lcaptr;

struct fgbstr *lcbfptr;                /* first entry on local_cap queue */
struct fgbstr *lcblptr;                /* last message on local_cap queue */
struct fgbstr *fgbfptr;                /* first entry on foreground queue */
struct fgbstr *fgblptr;                /* last message on foreground queue */
struct fgbstr *bgbfptr;                /* first entry on background queue */
struct fgbstr *bgblptr;                /* last message on background queue */
struct fgbstr *sgbfptr;                /* first entry on status queue */
struct fgbstr *sgblptr;                /* last message on status queue */

int  bgcount;                          /* count of number of background messages */
int  error_mode;                       /* whether or not to print modem error messages */
char lc_memory[WS_MEMORY_SIZE];        /* memory for local cap  linked list buffer */

int  startup_flags = 0;                /* Flags indicating which options have been set */

main(argc,argv)
int argc;
char *argv[];
{
int          i;
int          baud;                     /* Communication line configuration */
int          parity;
int          stop;
int          comm_parameter;
int          flags;                   /* Flags for control information */
int          arg_count;               /* Number of parameters used in an option */
char         option;                  /* Command line option */
char         parameter[32];           /* Command line parameter */
char         start_file[32];
unsigned     highmem;                 /* Terminate and stay resident parameters */
union REGS   in_reg;                  /*    Register values of MOWSE */
struct SREGS segregs;                 /*    Segment register values of MOWSE */

/* : Initialzation */

   printf ("MOWSE version %d.%d ...", VERSION, SUBVERSION);

   fgaptr             = &fgastr;
   fgastr.memory_used = 0;
   fgastr.memory      = &fg_memory[0];
   fgastr.m_allocp    = NULL;
   fgastr.memory_size = WS_MEMORY_SIZE;
   fgbfptr            = NULL;
   fgblptr            = NULL;
   bgaptr             = &bgastr;
   bgastr.memory_used = 0;
   bgastr.memory      = &bg_memory[0];
   bgastr.m_allocp    = NULL;
   bgastr.memory_size = WS_MEMORY_SIZE;
   bgbfptr            = NULL;
   bgblptr            = NULL;
   bgcount            = 0;
   lcaptr             = &lcastr;
   lcastr.memory_used = 0;
   lcastr.memory      = &lc_memory[0];
   lcastr.m_allocp    = NULL;
   lcastr.memory_size = WS_MEMORY_SIZE;
   lcbfptr            = NULL;
   lcblptr            = NULL;
   sgbfptr            = NULL;
   sgblptr            = NULL;

/* : set default com port parameters. */

   baud               = DEFAULT_BAUD;
   parity             = DEFAULT_PARITY;
   stop               = DEFAULT_STOP;
   datab              = DEFAULT_DATAB;
   comm_parameter     = DEF_COMM;

   SOFTNO             = DEFAULT_SOFTNO;
   COM_PORT           = DEFAULT_COM_PORT;  /* hardware address of COM1 port */
   COM_NO             = DEFAULT_COM_NO;    /* set com1 port */
   MASK8259           = DEFAULT_MASK8259;  /* reset: IRQ4 */
   HARDINTRPT         = DEFAULT_HARDINTRPT;/* hardware (communications) interrupt  */
   error_mode         = DEFAULT_ERROR_MODE;

   flags              = 0;
   startup_flags      = 0;
   start_file[0]      = 0;

   load_list_pending  = 0;
   for (i = 0; i < AUTO_LIMIT; load_list[i++].flags = 0);

/* : Parse command line parameters */

   for (i = 1; i < argc;)
   {  if (argv[i][0] == '/')
      {  option = argv[i][1];
         if (argv[i][2])
            strcpy (parameter, &(argv[i][2]));
         else
            strcpy (parameter, argv[i+1]);

         arg_count = parse_options (option, parameter, &stop, &parity, &baud,
            &datab, start_file);
         if (arg_count < 0)
            exit (0);

         if (argv[i][2])
            i += 1;
         else
            i += (1 + arg_count);
      }
      else
      {  parse_error (BADCONTROL, argv[i][0], NULL);
         exit (0);
      }
   }

/* : If start_up file specified, parse through it */

   if (start_file[0])
      if (start_up_parser (start_file, &stop, &parity, &baud, &datab) < 0)
         exit (0);

/* : Initialize_mowse if MOWSE not already active
     - set communications port parameter
     - initialize the local and remote cat tables
     - start up MOWSE dumb terminal emulator
     - setup the memory location to be used to delimit code which
       is to remain resident
     - terminate and stay resident */

   /* set bits 8 to 10 for handling Mark and Space parity */
   if (parity == MARK_PAR || parity == SPAC_PAR) {
       comm_parameter = ((baud<<5)|(NO_PAR<<3)|(stop<<2)|(datab));
       comm_parameter |= parity << 8;
   }
   else
       comm_parameter = ((baud<<5)|(parity<<3)|(stop<<2)|(datab));

   if (initialize_mowse(comm_parameter) == 1)
   {  init_cat();
      printf ("\n");                                  /* We're done initializing */

#if EM_DEBUG
      em();
#endif
      printf ("\nResident portion of MOWSE installed on COM%d:\n", COM_NO + 1);

      segread(&segregs);
      highmem = _TOP + 16;

      in_reg.x.dx = (int) (highmem >> 4)+(segregs.ds-segregs.cs);
      in_reg.h.ah = 0x31;
      int86(33,&in_reg,0);
   }
   else
      printf (" already resident.\n");
}

/**/

/* : PROCEDURE FUNCTION (start_up_parser):

Parse through the start-up file specified.  The start-up file is interpretted
as follows:

        /X  parameter

where X is one of

        B,C,D,F,G,I,L,M,S

as defined for the parameter specifications for the command MOWSE.
*/

/* : RETURNS

      0 - all OK
    < 0 - an error occurred
*/

/* : NOTES

Capabilites that are to be autoloaded areshuffled off until MOWSE is active on
both Multics and the PC.

Command line options have precedence over start-up file specifications.  Thus
if for example /D is specified in the command line, then it will override any
mention of the option in the start up file.

If MOWSE is exitted normally BEFORE MOWSE is started up on Multics, all autoload
specifications will be lost.

/F options specified in the start_up file are treated as errors as recursive
start_up files are not acceptable.
*/

start_up_parser (p_file, p_stop, p_parity, p_baud, p_datab)

char p_file[];        /* NULL terminated string specifying startup file name */
int  *p_stop;         /* Stop bits */
int  *p_parity;       /* Parity */
int  *p_baud;         /* Baud rate */
int  *p_datab;        /* Data bits */
{
int  fd;              /* File Descriptor to start_up file */
int  i;
int  param_idx;       /* Position in parameter construction */
char buffer[257];     /* Input line from file */
char parameter[33];   /* Parmater being built */
int  n_chars;         /* Chars read from input file */
int  code;            /* Error code */
int  flags;           /* Current flag settings */
char option;          /* Option specified */
char junk[32];        /* Useless space */

/* : Open the file to read */
   if ((fd = open (p_file, O_RDONLY)) == -1)
   {  printf (" Error opening %s.\n", p_file);
      return (-1);
   }

/* : While not EOF
     - For each character extracted from the file
     -- If char = '/', done getting last parameter, process option, clear flags
     -- Else if char non-printable, done collection of parameter, process option
     -- Else (printable character), build option or parameter */

   flags = 0;
   while ((n_chars = read (fd, buffer, 256)) > 0)
   {  for (i = 0; i < n_chars; i++)
      {  if (buffer[i] == '/')
         {  if (flags & PARAM_PENDING)
            {  if (option == 'F' || option == 'f')
               {  printf (" Cannot load start_up files recursively.\n");
                  close (fd);
                  return (-1);
               }
               parameter[param_idx++] = 0;
               if ((code = parse_options (option, parameter, p_stop, p_parity, p_baud, p_datab, junk)) < 0)
               {  close (fd);
                  return (code);
               }
            }
            flags = OPTION_PENDING;
            option = 0;
            param_idx = 0;
            parameter[0] = 0;
         }

         else if (buffer[i] <= '\040' || buffer[i] >= '\177')
         {  if (flags & PARAM_PENDING && param_idx)
            {  flags = (flags ^ PARAM_PENDING) | PARAM_BUILT;
               if (option == 'F' || option == 'f')
               {  printf (" Cannot load start_up files recursively.\n");
                  close (fd);
                  return (-1);
               }
               parameter[param_idx++] = 0;
               if ((code = parse_options (option, parameter, p_stop, p_parity, p_baud, p_datab, junk)) < 0)
               {  close (fd);
                  return (code);
               }
            }
         }

         else
         {  if (flags & OPTION_PENDING)
            {  option = buffer[i];
               flags = (flags ^ OPTION_PENDING) | OPTION_BUILT | PARAM_PENDING;
            }
            else if (flags & PARAM_PENDING)
               parameter[param_idx++] = buffer[i];
         }
      }
   }

   close (fd);
   return (0);
}

/**/

/* : PROCEDURE FUNCTION (parse_options):

Parse the option and its parameter and handle accordingly.
*/

/* : RETURNS

     0         - OK
     BADARG    - Invalid parameter
     BADOPTION - Invalid option
     OVERLOAD  - Too many autoload capabilities
     EXPECTING - Argument expected
*/

/* : NOTES

If an error occurs, the error message is printed from parse_options and the
error code (above) is returned.
*/

parse_options (p_option, p_param, p_stop, p_parity, p_baud, p_datab, p_start)

char p_option;           /* Option */
char p_param[];          /* Parameter to option (may be 0 length) */
int  *p_stop;            /* Stop bits */
int  *p_parity;          /* Parity */
int  *p_baud;            /* Baud rate */
int  *p_datab;           /* Data bits */
char p_start[];          /* Start_up file name */
{
int  j;                  /* Temp */
int  i;
int  code;               /* Error code */
int  arg_count;          /* Number of arguments extracted */
int  index;              /* Escape character value */
int  convert_code;       /* Escape char conversion code */

   arg_count = 0;
   code = 0;

   switch (p_option)
   {  case 'B':                        /* BAUD */
      case 'b':

         arg_count = 1;
         if (startup_flags & OPTION_B)
            break;
         else if (!(p_param[0]) || (p_param[0] == '/'))
            code = EXPECTING;
         else switch (atoi(p_param))
         {  case 110:  *p_baud = B110;  break;
            case 150:  *p_baud = B150;  break;
            case 300:  *p_baud = B300;  break;
            case 600:  *p_baud = B600;  break;
            case 1200: *p_baud = B1200; break;
            case 2400: *p_baud = B2400; break;
            case 4800: *p_baud = B4800; break;
            case 9600: *p_baud = B9600; break;
            default:
               code = BADARG;
         }
         startup_flags |= OPTION_B;
         break;

      case 'C':                        /* COM PORT */
      case 'c':

         if (startup_flags & OPTION_C)
            break;

         arg_count = 1;
         if (!(p_param[0]) || (p_param[0] == '/'))
            code = EXPECTING;
         else switch (atoi(p_param))
         {  case 1:

               COM_PORT = DEFAULT_COM_PORT;    /* hardware address of COM1 port */
               COM_NO = DEFAULT_COM_NO;        /* set com1 port */
               MASK8259 = DEFAULT_MASK8259;    /* reset: IRQ4 */
               HARDINTRPT= DEFAULT_HARDINTRPT; /* hardware interrupt  */
               break;

            case 2:

               COM_PORT = 0x2f8;       /* hardware address of COM2 port */
               COM_NO = 1;             /* set com2 port */
               MASK8259 = (char) 0xf7; /* reset: IRQ3 */
               HARDINTRPT= 0xb;        /* hardware interrupt  */
               break;

            default:

               code =  BADARG;
         }
         startup_flags |= OPTION_C;
         break;

      case 'D':                        /* DATA BITS */
      case 'd':

         if (startup_flags & OPTION_D)
            break;

         arg_count = 1;
         if (!(p_param[0]) || (p_param[0] == '/'))
            code = EXPECTING;
         else switch (atoi(p_param))
         {  case 7:  *p_datab = DATA7; break;
            case 8:  *p_datab = DATA8; break;
            default: code = BADARG;
         }
         startup_flags |= OPTION_D;
         break;

      case 'E':                        /* Escape character */
      case 'e':

         arg_count = 1;
         if (!(p_param[0]) || (p_param[0] == '/'))
            code = EXPECTING;
         else
         {  convert_code = sscanf (p_param, "%o", &index);
            if (convert_code != 1)
               code = BADARG;
            else if ((index < 0) || (index > 255))
               code = BADARG;
            else
               s_escreq[index] = 1;
         }

         break;

      case 'F':                        /* START_UP FILE */
      case 'f':

         if (!(p_param[0]) || (p_param[0] == '/'))
            strcpy (p_start, "MOWSE.INI");
         else
         {  stccpy (p_start, p_param, 31);
            p_start[31] = 0;
            arg_count = 1;
         }
         break;

      case 'G':                        /* DEBUG PACKETS */
      case 'g':

         arg_count = 1;
         if (!(p_param[0]) || (p_param[0] == '/'))
            code = EXPECTING;
         else switch (p_param[0])
         {  case 'P':                  /* Show all packets */
            case 'p':

               if (startup_flags & OPTION_GP)
                  break;
               startup_flags |= OPTION_GP;
               dbgpkts = 1; 
               break;

            case 'R':                  /* Show rejected packets */
            case 'r':

               if (startup_flags & OPTION_GR)
                  break;
               startup_flags |= OPTION_GR;
               dbgpkts = 1; 
               break;

            case 'X':                  /* Show extra characters */
            case 'x':

               if (startup_flags & OPTION_GX)
                  break;
               startup_flags |= OPTION_GX;
               dbgpkts = 1; 
               break;

            default:  
               code = BADARG;
         }
         break;

      case 'H':                        /* HOLD DTR */
      case 'h':
         startup_flags |= OPTION_H;
         break;

      case 'I':                        /* USER MOWSE INTERRUPT */
      case 'i':

         if (startup_flags & OPTION_I)
            break;

         arg_count = 1;
         if (!(p_param[0]) || (p_param[0] == '/'))
            code = EXPECTING;
         else
         {  j = atoi(p_param);
            if ((j > 10) && (j < 256))
               SOFTNO = j;
            else
               code = BADARG;
         }
         startup_flags |= OPTION_I;
         break;

      case 'L':                        /* AUTOLOAD CAPABILITY */
      case 'l':

         arg_count = 1;
         if (!(p_param[0]) || (p_param[0] == '/'))
            code = EXPECTING;

         if (!code)
         {  for (i = 0; (i < AUTO_LIMIT) && (load_list[i].flags & AUTO_ON); i++);
            if (i == AUTO_LIMIT)
               code = OVERLOAD;
         }

         if (!code)
         {  strncpy (load_list[i].name, p_param, AUTO_LENGTH - 1);
            load_list_pending = AUTO_PENDING;
            load_list[i].name[AUTO_LENGTH] = 0;
            load_list[i].flags = AUTO_ON;
         }
         break;

      case 'M':                        /* MODEM ERROR MESSAGES */
      case 'm':

         error_mode = 1;
         break;

      case 'N':                        /* Network Connection */
      case 'n':

         arg_count = 0;
         s_EOP = CR;
         r_EOP = CR;
         s_escreq[CR] = 1;
         break;

      case 'P':                        /* PARITY */
      case 'p':

         if (startup_flags & OPTION_P)
            break;

         arg_count = 1;
         if (!(p_param[0]) || (p_param[0] == '/'))
            code = EXPECTING;
         else switch (p_param[0])
         {  case 'E':
            case 'e':

               *p_parity = EVEN_PAR;                /* even parity */
               break;

            case 'O':
            case 'o':

               *p_parity = ODD_PAR;                 /* odd parity */
               break;

            case 'M':
            case 'm':

               *p_parity = MARK_PAR;                /* mark parity */
               break;

            case 'S':
            case 's':
            
               *p_parity = SPAC_PAR;                /* space parity */
               break;

            case 'N': 
            case 'n':

               *p_parity = NO_PAR;                  /* no parity */
               *p_datab = DATA8; 
               break;

            default:  
               code = BADARG;
         }

         startup_flags |= OPTION_P;
         break;

      case 'S':                        /* STOP BITS */
      case 's':

         if (startup_flags & OPTION_S)
            break;

         arg_count = 1;
         if (!(p_param[0]) || (p_param[0] == '/'))
            code = EXPECTING;
         else switch (atoi(p_param))
         {  case 1:  *p_stop = STOP1; break;
            case 2:  *p_stop = STOP2; break;
            default: code = BADARG;
         }
         startup_flags |= OPTION_S;
         break;

      default:

         code =  BADOPTION;
   }

/* : If there was an error code, then it will cause an exit so return it */

   if (code) 
   {  parse_error (code, p_option, p_param);
      return (code);
   }

/* : Else it went OK and return the number of parameters used */

   return (arg_count);

}

/**/

/* : PROCEDURE FUNCTION (parse_error):

Display an appropriate error message for the code.
*/

parse_error (p_code, p_option, p_param)

int  p_code;
char p_option;
char p_param[];
{

   if (p_code == BADARG)
      printf (" Invalid parameter %s.\n", p_param);
   else if (p_code == BADOPTION)
      printf (" Invalid option /%c.\n", p_option);
   else if (p_code == OVERLOAD)
      printf (" Too many capabilities to autoload.\n");
   else if (p_code == EXPECTING)
      printf (" Argument expected.\n");
   else if (p_code == BADCONTROL)
      printf (" Invalid option delimiter: '%c'.\n", p_option);
}




		    mowse.mak                       08/07/87  1522.8rew 08/07/87  1246.1      115398



#  BEGIN MAKEFILE: MOWSE.MAK
#
#  B.WESTCOTT  JULY 29,1986
#  Modified Sept. 15 - R.L. - updated all dependent include files
#  Makefile for compose using MICROSOFT MAKE
#   MACROS
#
s=c:\mowse
h=c:\mowse
o=c:\mowse
#
#       MOWSE
#
autoload.obj : autoload.c ws.h ws_auto.h ws_dcls.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

buffer.obj  : buffer.asm mowsdefs.mac ws_buf.mac
        masm $*.asm,$*;

callmows.obj : callmows.c ws.h ws_error.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

capabil.obj : capabil.c ws.h cat.h ws_error.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

cretinst.obj: cretinst.c ws.h cat.h ws_dcls.h ws_error.h ws_func.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

conrqst.obj: conrqst.c ws.h wsmincap.h ws_mcb.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

conresp.obj: conresp.c ws.h wsmincap.h ws_mcb.h ws_error.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

curpos.obj: curpos.c emulator.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

dbgetkbl.obj:   dbgetkbl.c keydefs.h emulator.h ws.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

dbprocop.obj:   dbprocop.c keydefs.h emulator.h ws.h ws_dcls.h wsmincap.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

dbtoggle.obj:   dbtoggle.c ws_error.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

debug.obj: debug.c
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

destinst.obj: destinst.c cat.h ws_func.h ws_dcls.h ws_error.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

disrqst.obj: disrqst.c ws.h wsmincap.h ws_mcb.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

disresp.obj: disresp.c ws.h wsmincap.h ws_mcb.h ws_error.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

dtm_mows.obj: dtm_mows.c mowse.h cat.h ws_msg.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

emulator.obj: emulator.c ws.h ws_dcls.h wsmincap.h emulator.h keydefs.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

em_put.obj: em_put.c emulator.h keydefs.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

em_routs.obj: em_routs.c emulator.h keydefs.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

execap.obj: execap.c ws.h alloc.h ws_mcb.h ws_error.h ws_func.h ws_dcls.h wsmincap.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

execom.obj: execom.c ws.h ws_mcb.h ws_error.h ws_func.h ws_dcls.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

external.obj: external.c cat.h ws_msg.h wsmincap.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

findname.obj: findname.c cat.h ws_dcls.h ws_func.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

findnumb.obj: findnumb.c cat.h ws_dcls.h ws_func.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

freeprog.obj: freeprog.asm ws.mac cat.mac
        masm $*.asm,$*;

getbgmes.obj : getbgmes.c ws.h ws_dcls.h ws_func.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

getkbkey.obj : getkbkey.c emulator.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

getmcbv.obj : getmcbv.c ws_error.h  cat.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

getstat.obj : getstat.c ws.h ws_msg.h ws_error.h  ws_dcls.h ws_func.h wsmincap.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

gettdata.obj : gettdata.c ws.h ws_dcls.h ws_func.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

hard_int.obj: hard_int.asm mowsdefs.mac rs232err.mac wsmincap.mac ws_buf.mac util.mac
        masm $*.asm,$*;

initmows.obj: initmows.asm mowsdefs.mac xoscall.mac ws.mac ws_buf.mac
        masm $*.asm,$*;

internal.obj: internal.c ws_msg.h ws_error.h cat.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

i_con.obj:    i_con.c ws_error.h ws_msg.h ws_dcls.h wsmincap.h cat.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q


i_creins.obj: i_creins.c cat.h ws_dcls.h ws_stack.h ws_error.h ws_msg.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

i_desins.obj: i_desins.c cat.h ws_dcls.h ws_error.h ws_msg.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

i_execap.obj: i_execap.c ws.h ws_error.h ws_dcls.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

i_execom.obj: i_execom.c ws_error.h  cat.h ws_msg.h ws_dcls.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

i_fndcna.obj: i_fndcna.c cat.h ws_dcls.h ws_error.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

i_fndcnu.obj: i_fndcnu.c ws.h cat.h ws_dcls.h ws_error.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

i_getbgm.obj : i_getbgm.c alloc.h cat.h ws_dcls.h ws_error.h ws_msg.h ws_fgb.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

i_putbgm.obj: i_putbgm.c alloc.h cat.h ws_dcls.h ws_error.h ws_msg.h ws_fgb.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

i_reset.obj : i_reset.c ws.h ws_error.h ws_msg.h ws_dcls.h ws_fgb.h cat.h wsmincap.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

i_sendbg.obj: i_sendbg.c ws.h ws_error.h ws_msg.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

i_sleep.obj: i_sleep.c ws.h ws_error.h ws_msg.h ws_dcls.h ws_fgb.h cat.h wsmincap.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

i_suspnd.obj: i_suspnd.c ws.h wsmincap.h cat.h ws_dcls.h ws_msg.h ws_fgb.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

linebrk.obj : linebrk.asm mowsedefs.mac
        masm $*.asm,$*;

mio.obj : mio.c ws_error.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

mowse.obj   : mowse.c mowsdefs.h alloc.h cat.h ws_fgb.h emulator.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

narcint.obj : narcint.asm asmdefs.mac
        masm $*.asm,$*;

op_routs.obj    : op_routs.c keydefs.h emulator.h ws.h ws_dcls.h wsmincap.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

pack.obj    : pack.c ws.h cat.h ws_error.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

pe.obj      : pe.c ws.h ws_msg.h wsmincap.h ws_mcb.h ws_func.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

pe_entry.obj: pe_entry.asm
        masm $*.asm,$*;

prime.obj   : prime.asm
        masm $*.asm,$*;

putbgmes.obj: putbgmes.asm ws.mac ws_dcls.mac ws_mcb.mac ws_func.mac
        masm $*.asm,$*;

putstat.obj : putstat.c ws.h ws_dcls.h ws_func.h ws_error.h wsmincap.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

puttdata.obj: puttdata.c ws.h ws_dcls.h ws_func.h wsmincap.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

rcvdata.obj : rcvdata.c ws.h alloc.h cat.h ws_fgb.h ws_buf.h ws_msg.h wsmincap.h ws_error.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

rcvfgdat.obj : rcvfgdat.c ws.h alloc.h cat.h ws_fgb.h ws_buf.h ws_msg.h wsmincap.h ws_error.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

rcvmsg.obj : rcvmsg.c ws.h alloc.h cat.h ws_fgb.h ws_buf.h ws_msg.h wsmincap.h ws_error.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

rcvbyte.obj: rcvbyte.asm mowsdefs.mac rs232err.mac wsmincap.mac ws_buf.mac
        masm $*.asm,$*;

resetcap.obj: resetcap.c ws.h wsmincap.h ws_mcb.h ws_dcls.h ws_func.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

resume.obj : resume.c ws.h wsmincap.h ws_mcb.h ws_dcls.h ws_func.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

rs232out.obj: rs232out.asm mowsdefs.mac rs232err.mac ws_buf.mac
        masm $*.asm,$*;

send.obj    : send.asm mowsdefs.mac
        masm $*.asm,$*;

sendimsg.obj: sendimsg.c ws.h alloc.h ws_error.h ws_msg.h ws_fgb.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

sendqrep.obj: sendqrep.c ws.h ws_msg.h ws_func.h wsmincap.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

sendterm.obj: sendterm.asm mowsdefs.mac ws_buf.mac
        masm $*.asm,$*;

set_dta.obj : set_dta.asm
        masm $*.asm,$*;

setlock.obj : setlock.asm
     masm $*.asm,$*;

smdmstr.obj : smdmstr.asm mowsdefs.mac
        masm $*.asm,$*;

stackfix.obj: stackfix.asm util.mac mowsdefs.mac ws_stack.mac
        masm $*.asm,$*;

stayres.obj: stayres.c cat.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

suspend.obj: suspend.c ws.h wsmincap.h ws_mcb.h ws_dcls.h ws_func.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q
     
termbuff.obj: termbuff.asm mowsdefs.mac ws.mac ws_fgb.mac
        masm $*.asm,$*;

termcap.obj:  termcap.c ws.h wsmincap.h ws_mcb.h ws_error.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

termmows.obj: termmows.asm xoscall.mac mowsdefs.mac ws.mac ws_buf.mac
     masm $*.asm,$*;

user_int.obj: user_int.asm ws.mac ws_stack.mac ws_dcls.mac ws_error.mac wsmincap.mac
        masm $*.asm,$*;

wakeup.obj  : wakeup.c ws.h alloc.h ws_mcb.h cat.h ws_fgb.h ws_msg.h wsmincap.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

wsalloc.obj : wsalloc.c
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

wsexe.obj   : wsexe.c ws.h wsmincap.h ws_error.h ws_msg.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q

wsexecap.obj: wsexecap.asm ws.mac ws_msg.mac cat.mac
        masm $*.asm,$*;

wssleep.obj : wssleep.c ws.h wsmincap.h ws_mcb.h ws_dcls.h ws_func.h ws_error.h
     lc1 $*.c  -ic:\lc\  -d -n32
     lc2 $*.q



telib.lib: emulator.obj getkbkey.obj em_put.obj curpos.obj op_routs.obj dbprocop.obj \
           dbgetkbl.obj em_routs.obj
     plib86 bu telib.lib fi emulator.obj,getkbkey.obj,em_put.obj,curpos.obj
     ren telib.lib telib.old
     plib86 bu telib.lib fi op_routs.obj,dbprocop.obj,dbgetkbl.obj,em_routs.obj,telib.old

protolib.lib: hard_int.obj  narcint.obj mio.obj prime.obj smdmstr.obj \
              rs232out.obj buffer.obj initmows.obj linebrk.obj
     plib86 bu protolib.lib fi hard_int.obj,narcint.obj,mio.obj,prime.obj,linebrk.obj
        ren protolib.lib protolib.old
     plib86 bu protolib.lib fi smdmstr.obj,rs232out.obj,buffer.obj,initmows.obj,protolib.old

msintlib.lib: rcvdata.obj internal.obj wsexe.obj sendimsg.obj \
              set_dta.obj wsexecap.obj rcvbyte.obj rcvfgdat.obj \
              rcvmsg.obj wakeup.obj autoload.obj dtm_mows.obj \
              external.obj
     plib86 bu msintlib.lib fi rcvdata.obj,internal.obj,wsexe.obj,sendimsg.obj,set_dta.obj,rcvbyte.obj,wsexecap.obj
     ren msintlib.lib msintlib.old
     plib86 bu msintlib.lib fi rcvfgdat.obj,rcvmsg.obj,wakeup.obj,autoload.obj,dtm_mows.obj,msintlib.old,external.obj
     del msintlib.old

userlib.lib: send.obj user_int.obj termbuff.obj sendterm.obj i_execom.obj \
             i_fndcna.obj i_fndcnu.obj i_creins.obj i_desins.obj i_getbgm.obj \
             capabil.obj getmcbv.obj i_execap.obj i_reset.obj i_sleep.obj \
             i_sendbg.obj i_putbgm.obj i_suspnd.obj termmows.obj i_con.obj \
             dbtoggle.obj freeprog.obj
     plib86 bu userlib.lib fi send.obj,user_int.obj,termbuff.obj,sendterm.obj
        rename userlib.lib userlib.old
     plib86 bu userlib.lib fi i_fndcna.obj,i_fndcnu.obj,i_creins.obj,i_desins.obj,userlib.old 
        del userlib.old
        rename userlib.lib userlib.old
     plib86 bu userlib.lib fi capabil.obj,getmcbv.obj,i_execap.obj,i_reset.obj,userlib.old 
        del userlib.old
        rename userlib.lib userlib.old
     plib86 bu userlib.lib fi i_sleep.obj,i_execom.obj,i_getbgm.obj,dbtoggle.obj,userlib.old
        del userlib.old
        rename userlib.lib userlib.old
     plib86 bu userlib.lib fi i_suspnd,i_putbgm.obj,i_sendbg.obj,termmows.obj,userlib.old
        del userlib.old
        rename userlib.lib userlib.old
     plib86 bu userlib.lib fi i_con.obj,freeprog.obj,userlib.old


utillib.lib: debug.obj stackfix.obj setlock.obj
     plib86 bu utillib.lib fi debug.obj,stackfix.obj,setlock.obj

mowslib.lib: gettdata.obj execom.obj  callmows.obj puttdata.obj getbgmes.obj \
             cretinst.obj destinst.obj findname.obj findnumb.obj execap.obj \
             pe_entry.obj pe.obj conrqst.obj disrqst.obj disresp.obj  \
             getstat.obj putstat.obj resetcap.obj resume.obj wssleep.obj \
             sendqrep.obj putbgmes.obj suspend.obj pack.obj wsalloc.obj \
             conresp.obj stayres.obj termcap.obj
     plib86 bu mowslib.lib fi gettdata.obj,execom.obj,callmows.obj,puttdata.obj  
        ren mowslib.lib mowslib.old
     plib86 bu mowslib.lib fi cretinst.obj,destinst.obj,findname.obj,findnumb.obj,mowslib.old   
        del mowslib.old
        ren mowslib.lib mowslib.old
     plib86 bu mowslib.lib fi pe_entry.obj,pe.obj,conrqst.obj,disrqst.obj,mowslib.old   
        del mowslib.old
        ren mowslib.lib mowslib.old
     plib86 bu mowslib.lib fi getstat.obj,putstat.obj,resetcap.obj,resume.obj,mowslib.old  
        del mowslib.old
        ren mowslib.lib mowslib.old
     plib86 bu mowslib.lib fi sendqrep.obj,putbgmes.obj,pack.obj,wsalloc.obj,mowslib.old 
        del mowslib.old
        ren mowslib.lib mowslib.old
     plib86 bu mowslib.lib fi getbgmes.obj,execap.obj,disresp.obj,wssleep.obj,mowslib.old
        del mowslib.old
        ren mowslib.lib mowslib.old
     plib86 bu mowslib.lib fi conresp.obj,suspend.obj,stayres.obj,termcap.obj,mowslib.old

#
#   MOWSE
#
mowse.com: mowse.obj telib.lib protolib.lib msintlib.lib userlib.lib \
            utillib.lib mowslib.lib
     del *.old 
           link \lc\c\c mowse ,mowse,mowse,TELIB+PROTOLIB+MSINTLIB+USERLIB+UTILLIB+MOWSLIB+\lc\s\lc/map
           mapsym mowse
           exe2bin mowse mowse.com
           del mowse.exe

#   END MAKEFILE: MOWSE.MAK




		    narcint.asm                     08/07/87  1521.0rew 08/07/87  1438.1       63873



; ***********************************************************
; *                                                         *
; * Copyright, (C) Honeywell Bull Inc., 1987                *
; *                                                         *
; * Copyright, (C) Honeywell Information Systems Inc., 1986 *
; *                                                         *
; ***********************************************************

page 55,132

; HISTORY COMMENTS:
;  1) change(86-02-16,Westcott), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Created.
;  2) change(86-09-04,Flegel), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Installed mowse_timer to count seconds
;     rather than use timer_count to count ticks.
;                                                      END HISTORY COMMENTS

;/* : PROCEDURE FUNCTION (int1cep):
;
;This is the NARC interrupt handler.  It is designed to receive control when 
;ever any of the three interrupts defined below occurs. If the interrupts are
;not nested, and if the interrupt did not occur in DOS, then NARC is invoked 
;by a call to rcvdatas.
;
; Entries: int 1Ch  (from timer)
;          int 28h  (from console I/O wait routine)
;          int 13h  (from diskette services)
;*/

;/* : NOTES:
;
;The implementation is a duplicate of the one used by the Print spooler in 
;Dos 2.0.
;*/

include dos.mac
include asmdefs.mac

NON_EOI    = 20h
EOI_PORT   = 20h

page
;**************************************************************
;                                       MAIN
;**************************************************************
pseg

;--------- Public Declarations

public int13ep
public int1cep
public int28ep
public wstime

;--------- External Declarations

extrn   mowse_time:word                ; Current time in MOWSE
extrn   ticpersec:word                 ; Clock tics per second
extrn   calladvtmr:word                ; Time to call advtmr routine
extrn   advance_count:word             ; Time to advance count
extrn   time_count:dword               ; Number of tics since
extrn   INT13:word                     ; Interrupt vector
extrn   INT1C:word                     ; ...
extrn   INT28:word                     ; ...
extrn   IN_DOS:word                    ; Are we in DOS flag
extrn   IN_INT28:word                  ; Are we in INT28 flag
extrn   IN_NARC:word                   ; are we in MOWSE flag
extrn   IN_SOFT:word                   ; are we in soft interrupt flag

;--------- External Procedures

extrn   rcvdata:near
extrn   receive_byte:near
extrn   setup_stack:near
extrn   reset_stack:near
extrn   advtmr:near

int1cep proc near

; /* : increment advance_count, increment time_count */

        inc     CS:advance_count
        inc     word ptr CS:time_count+2
        jnz     shortt
        inc     word ptr CS:time_count

shortt:
        inc     CS:calladvtmr          ; Increment the protocol timer
        push    cx
        push    ax
        xor     cx,cx
        call    setup_stack
        push    bp

; /* : issue non-specific EOI to allow interrupts */

        mov     al,NON_EOI
        out     EOI_PORT,al

; /* : If 1 second has elapsed
;      - reset counter
;      - increment mowsetime
;      - set flag to call advtmr */

        push    ax
        mov     ax,CS:advance_count
        cmp     ax,CS:ticpersec
        pop     ax
        jb      check_dos
        inc     CS:mowse_time
        mov     CS:advance_count,0

; /* : if in DOS, return */

check_dos:
        push    ds
        push    si
        lds     si,dword ptr cs:[IN_DOS]
        cmp     byte ptr [si],0
        pop     si
        pop     ds
        jne     ret1c

; /* : If calladvtmr flag set then reset flag and call advtmr */

        push    ax
        mov     ax,CS:calladvtmr
        shl     ax,1                   ; Multiply the current timer by two
        cmp     ax,ticpersec           ; same as comparing time to 1/2 second
        pop     ax
        jl      dont_advance           ; if equal to 1 second, increment

        mov     CS:calladvtmr,0
        push    ax
        mov     bp,sp
        call    advtmr                 ; advance protocol timeout timer
        mov     sp,bp
        pop     ax

dont_advance:

; /* : Call rcvbyte to empty rs232 buffer */

        mov     bp,sp
        call    receive_byte
        mov     sp,bp

; /* : if in narc already, return */

        cmp     CS:IN_NARC,0
        jne     ret1c

; /* : if in software interrupt, return */

        cmp     CS:IN_SOFT,0
        jne     ret1c

; /* : Call rcvdata */

        inc     cs:IN_NARC             ; Notify that we are in MOWSE
        push    ax
        mov     bp, sp
        xor     ax,ax
        push    ax
        call    rcvdata                ; call narc routine
        mov     sp, bp
        pop     ax
        mov     CS:IN_NARC,0

ret1c:
        pop     bp
        call    reset_stack
        pop     ax
        pop     cx

; /* : return from interrupt */

        jmp     dword ptr cs:[INT1C]

; /* : int28ep - interrupt 28 handler (console i/o)
;      if in narc already, return */

int28ep:
        cmp     CS:IN_NARC,0
        jne     ret28

; /* : if in software interrupt, return */

        cmp     CS:IN_SOFT,0
        jne     ret28

; /* : if in software interrupt, return */

        cmp     CS:IN_INT28,0
        jne     ret28

; /* : set in_narc and in_int28 flags */

        inc     CS:IN_NARC
        inc     CS:IN_INT28
        sti

; /* : call rcvdata */

        push    cx
        push    ax
        xor     cx,cx
        call    setup_stack            ; Swap in MOWSE stack
        push    bp
        mov     bp, sp
        mov     ax,1                   ; set dosflag to indicate that we are in DOS
        push    ax
        call    rcvdata                ; Handle messages
        mov     sp, bp
        pop     bp
        cli
        call    reset_stack            ; Swap out MOWSE stack
        pop     ax
        pop     cx
        sti

; /* : return from int28 */

        mov     CS:IN_NARC,0
        mov     CS:IN_INT28,0

ret28:
        jmp     dword ptr cs:[INT28]

int1cep endp

; /* : int13ep - interrupt 13 handler (diskette services) */

int13ep proc far
        pushf

; /* : set in_narc flag */

        inc     cs:IN_NARC
        push    cs
        push    word ptr cs:INT13RET   ; push return address

; /* : simulate interrupt */

        push    word ptr cs:INT13+2    ; push real interrupt segment address
        push    word ptr cs:INT13      ; push real interrupt offset address
        ret                            ; simulate interrupt

; /* : decrement in_narc flag */

ret13:  pushf
        dec     cs:IN_NARC
        popf
        ret     2                      ; We'll let you guess what the 2 means

INT13RET dw     offset ret13           ; return address from interrupt

int13ep endp

;/* PROCEDURE FUNCTION (wstime):
;
;returns current value of mowse_time to caller.
;*/

wstime proc near
     mov   ax,word ptr CS:mowse_time
     ret
wstime endp
endps
        end




		    op_routs.c                      08/07/87  1519.9rew 08/07/87  1435.6       44955



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-09-26,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
     install(87-08-07,MR12.1-1072):
     Routines extracted from proc_op.c,
      now used by in proc_op.c and dbprocop.c
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (freeze)

loop until any keyboard character is hit
*/

#include <ctype.h>
#include <ws.h>
#include <ws_dcls.h>
#include <wsmincap.h>
#include <keydefs.h>
#include <emulator.h>

#if EM_DEBUG                           /* Do NOT compile if !EM_DEBUG */

extern int em_tab_size;
extern int bg_sender_in;
extern int bg_sender_out;
extern int bg_sender_buff[];
extern char *buff;

freeze()
{
int i;
int ch;

/* : if no key was pressed, loop for a while to give clock interrupts a 
     chance */

   while (!get_kb_key(&ch))
      for (i = 0; i < 100; i++);

}

/* : PROCEDURE FUNCTION (menu)

print a summary of the emulator functions
*/

menu()
{
int ch;

   printf ("----------------------------------------------------------\n");
   printf ("  * Background messages preceeded by ^\n");
   printf ("  * Preceed input with ^ to write to background\n\n");
   printf ("\n");
   printf ("F1 - Freeze display          F2 - Select display mode\n");
   printf ("F3 - Help menu               F4 - Toggle local edit\n");
   printf ("F5 - Toggle term data only   F6 - Show query status\n");
   printf ("F7 - Set tab size            F8 - Execute DOS command\n");
   printf ("F9 - send BREAK              F10 - Exit Emulator\n");
   printf ("\n");
   printf ("ALT F1 - Toggle Show Packets\n");
   printf ("ALT F2 - Toggle Diagnose Rejects\n");
   printf ("ALT F3 - Toggle Extra RCV Chars\n");
   printf ("----------------------------------------------------------\n");
}

/* : PROCEDURE FUNCTION (set_tab_size)

set a new tab size; if the tab size entered by the user is invalid, do not 
change existing tab size
*/

set_tab_size()
{
int size;

/* : prompt for a new tab size and read in user's response */

   printf("$$ Enter new tab size: ");
   gets(buff);

/* : check that only a signle number is entered; the size must be at least one 
     and less than the width of the screen */

   if (sscanf(buff,"%d%s",&size) != 1 || size < 1 || size > get_screen_width())
      printf("$$ -- Invalid tab size, tab size is now %d -- $$\n", em_tab_size);
   else {
      em_tab_size = size;
      printf("$$ New tab size = %d $$\n", em_tab_size);
   }
}

/* : PROCEDURE FUNCTION (execute_dos_cmd)

get and execute a command for the command interpreter 
*/

execute_dos_cmd()
{

/* : prompt and get user's command for command interpreter */

   printf ("$$ Enter DOS command: ");
   gets(buff);

/* : execute it and return to the emulator */

   system(buff);
   printf ("$$ Returning to normal emulation $$\n");
}

/* : PROCEDURE FUNCTION (send_query_status)

display the contents of the background query queue 
*/

sender_query_status()
{
int pending;
int sys;
int major;
int i;
int index;

/* : check to see if the queue is empty */

   if (bg_sender_in == bg_sender_out)
      printf ("$$ No background queries pending $$\n");

/* : get count of queries pending in the queue */

   else {
      if (bg_sender_in > bg_sender_out)
         pending = bg_sender_in - bg_sender_out;
      else
         pending = bg_sender_in - bg_sender_out + BG_SENDBUFF_SIZE;

/* : display the system id and major capability number of all query senders 
     in the queue */

      printf ("$$ %d queries pending:\n", pending);
      for (i = 0; i < pending; i++) {
         index = (bg_sender_out + i) % BG_SENDBUFF_SIZE;
         c_unpack(&sys,&major,bg_sender_buff[index]);
         printf ("  Query %2d>  system = %4d  major = %d\n", i, sys, major);
      }
      printf ("$$ Returning to normal emulation $$\n");
   }
}

/* : PROCEDURE FUNCTION (reply_to_query)

check the background query queue and if not empty, reply to first pending 
message in queue with message from user.
*/

reply_to_query()
{

/* : if background query queue is empty */  

   if (bg_sender_in == bg_sender_out)
      printf ("$$ No background queries pending $$\n");

/* : else background query queue not empty */

   else {
      printf ("$$ Enter reply message: ");
      gets(buff);
      sendqrep(buff,bg_sender_buff[bg_sender_out]);

/* : reply made, remove query sender from queue */

      bg_sender_out = (bg_sender_out+1) % BG_SENDBUFF_SIZE;
   }
}
#else
freeze ()
{}
menu ()
{}
set_tab_size ()
{}
execute_dos_cmd ()
{}
sender_query_status ()
{}
reply_to_query ()
{}
#endif




		    pack.c                          08/07/87  1519.9rew 08/07/87  1435.5       36387



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-05-05,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
     install(87-08-07,MR12.1-1072):
     Created.
  2) change(86-06-10,Westcott), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Removed from capabil.c
  3) change(86-11-14,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Check for WSMAJCAP as a capability number.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (c_pack):

Pack system_id and major capability number into one integer
*/

/* : RETURNS:

     0         - if pack successful
     WSINVNUM  - if major_number outside of the range MIN_CAPABILITY_NUMBER and
                 MAX_CAPABILITY_NUMBER
     WSINVSYS  - if system_id is outside of the range MIN_SYSTEM_ID and 
                 MAX_SYSTEM_ID
*/

/* : NOTES

Both system_id and major number are considered to be 8 bit unsigned integers. 
The system_id is moved to the high order half of major capability is moved 
to the low order half.
*/

#include <dos.h>
#include <ws.h>
#include <cat.h>
#include <ws_error.h>

#define LOW_8_BITS  0x00FF
#define BYTE_SHIFT  8

c_pack (system_id, major_number, major_capability)
int system_id;           /* system id */
int major_number;        /* Major capability number */
int *major_capability;   /* Resultant capability number (packed) */
{

/* : if major_number not between 32 and 64 inclusive then
     - set code to invalid major number */

   if (major_number < WSMAJCAP || major_number > MAX_CAPABILITY_NUMBER)
      return(WSINVNUM);

/* : if system id not between 32 and 64 and not WSLOCAL and WSREMOTE then
     - set code to invalid system id */

   if ((system_id != WSLOCAL) && (system_id != WSREMOTE) &&
       ((system_id < MIN_SYSTEM_ID) || (system_id > MAX_SYSTEM_ID)))
   {
      return(WSINVSYS);
   }

/* : return major capability number, where system id occupies high 8 bits, 
     major_number low 8 bits */

   *major_capability = (system_id << BYTE_SHIFT) | major_number;
   return(0);
}

/* : PROCEDURE FUNCTION (c_unpack):

Unpack system_id and major capability number from one integer into two 
separate integers.
*/

/* : RETURNS:

     0, if unpack successful
     WSINVNUM - if major_number outside of the range
                MIN_CAPABILITY_NUMBER and MAX_CAPABILITY_NUMBER
*/

/* : NOTES

Both system_id and major number are considered to be 8 bit unsigned integers. 
The high order half of major_capability is moved to the low order byte in
system_id, while the low order half of major_capability is moved to the low 
order half of major_number.
*/

c_unpack (system_id, major_number, major_capability)
int *system_id;        /* Pointer to system id (resultant) */
int *major_number;     /* Pointer to major number (resultant) */
int major_capability;  /* Capability number to be unpacked */
{

/* : - system id is high 8 bits */

   *system_id = (major_capability >> BYTE_SHIFT) & LOW_8_BITS;

/* : - major number is low 8 bits */

   *major_number = major_capability & LOW_8_BITS;

/* : - if major number unpacked is invalid, return error code */

   if (*major_number < WSMAJCAP || *major_number > MAX_CAPABILITY_NUMBER)
      return(WSINVNUM);

/* : if system id not between 32 and 64 and is not WSREMOTE and WSLOCAL then
     -  return invalid system id error code */

   if ((*system_id != WSLOCAL) && (*system_id != WSREMOTE) &&
       ((*system_id < MIN_SYSTEM_ID) || (*system_id > MAX_SYSTEM_ID)))
   {
      return(WSINVSYS);
   }

   return(0);
}




		    pe.c                            08/07/87  1519.8rew 08/07/87  1435.5      180954



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-07-01,Westcott), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
  2) change(86-11-15,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Reimplementation of reset,resume,suspend,
     terminate.
  3) change(86-11-27,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Empty buffers when a fail is returned.
                                                   END HISTORY COMMENTS */

/* :  PROCEDURE FUNCTION (pe)

pe (pre-entry) is the MOWSE routine which is forced into the application's
address space and called before the application is called.  It is responsible
for the following:

   1) packet assembly/disassembly
   2) specialized minor capability manipulations required to be done in the
      application's space
   3) call user application with data messages

*/

#include <stdio.h>
#include <ws.h>                        /* General constants */
#include <ws_msg.h>                    /* Message structures */
#include <wsmincap.h>                  /* Minor capability definitions */
#include <ws_mcb.h>                    /* MOWSE Control BLock def */
#include <ws_func.h>                   /* User interrupt MOWSE functions */
#include <ws_error.h>                  /* Error codes */

#define TRUE  1
#define FALSE 0

pe (p_mcb_ptr, p_minor_cap, p_bufseg, p_bufoff, p_buflen)

mcb  *p_mcb_ptr;                       /* Capability's MCB */
char p_minor_cap;                      /* Minor cap of message */
int  p_bufseg;                         /* Segment address of message */
int  p_bufoff;                         /* Offset of message within segment */
int  p_buflen;                         /* Length of message */
{
int  link_info_size;
int  msg_header_size;
int  sender_major;
int  code;
struct more_msg more_message;          /* Message types for passed message */
struct input_msg *message;

/* : - if there is no handler for the message, ignore it */

   if (p_mcb_ptr -> mcb_flag & MCB_NULL_ROUTINE)
      return (0);

/* : - copy message into user space. */

   msg_header_size = sizeof(more_message)-2;
   link_info_size = sizeof(struct linklst)-2;
   peek (p_bufseg,p_bufoff,&more_message, msg_header_size);
   message = (struct input_msg *) (&more_message);

/* : - switch on the minor capability */

   switch ((int) p_minor_cap)
   {
      case CONTINUE_MESSAGE:

         return (handle_continue (p_mcb_ptr, &more_message));

      case PARTIAL_MESSAGE:

         return (handle_partial (p_mcb_ptr, p_buflen, p_bufseg, p_bufoff, 
            msg_header_size, link_info_size, &more_message));

      case RESUME_APPLICATION:

         if (!(p_mcb_ptr -> mcb_flag & MCB_SUSPEND))
            return (WSNOSPND);
         p_mcb_ptr -> mcb_flag &= ~MCB_SUSPEND;
         code = forward (p_mcb_ptr, message -> minor, &(message -> msg_data[0]),
            p_buflen, message -> source_system, message -> source_major);
         return (code);

      case SUSPEND_APPLICATION:

         if (p_mcb_ptr -> mcb_flag & MCB_SUSPEND)
            return (WSSUSPND);
         code = forward (p_mcb_ptr, message -> minor, &(message -> msg_data[0]),
            p_buflen, message -> source_system, message -> source_major);
         p_mcb_ptr -> mcb_flag |= MCB_SUSPEND;
         return (code);

      case RESET_APPLICATION:

         return (handle_reset (p_mcb_ptr, message, p_buflen));

      case FAIL_CAPABILITY:
      case SYSTEM_ERROR:

         return (handle_fail (p_mcb_ptr, message, p_buflen));

      case TERMINATE_APPLICATION:

         code = forward (p_mcb_ptr, message -> minor, &(message -> msg_data[0]), 
            p_buflen, message -> source_system, message -> source_major);
         return (code);

      default:

         return (handle_default (p_mcb_ptr, p_buflen, p_bufseg, p_bufoff, p_minor_cap,
            msg_header_size, link_info_size, &more_message));
   }
}
/**/
/* : PROCEDURE FUNCTION (llpfree)

Free the space occupied by the link list pointed to by llp.  The space that
is to be freed is a list that is trailing behind the the llp node:
         -------------------
first ->|   |   |   |   |   |
         -------------------
          |
          V
         -------------------
  llp ->|   |   |   |   |   |        <= free this list into core
         -------------------
          |
          V
         -------------------
        |   |   |   |   |   |
         -------------------
*/

llpfree (core,first,llp)

struct allocstr *core;                 /* Where to free into */
struct linklst **first;                /* First node in list */
struct linklst *llp;                   /* Node to free */
{
struct linklst *llp1;                  /* Search node pointer */

/* : Find the predecessor to the node to be freed and adjust the pointers
     to go around the node to be freed */

   llp1 = *first;
   if (llp1 == llp)
      *first = llp1 -> nextbuf;
   else
   {  while (llp1 != NULL)
      {  if (llp1->nextbuf == llp)
         {  llp1->nextbuf = llp->nextbuf;
            break;
         }
         llp1 = llp1->nextbuf;
      }
   }

/* : Free all of the "sub-nodes" in the trailing list */

   while (llp != NULL)
   {  llp1 = llp->nextlink;
      wsfree(core,llp);
      llp = llp1;
   }
}
/**/
/* : PROCEDURE FUNCTION (forward)

Simply pass the message immediately to the application.  It shouldn't be
stored in the buffers as there is no need and the application needs immediate
knowledge.
*/

forward (p_mcb_ptr, p_minor, p_data, p_data_len, p_source_system, p_source_major)

mcb  *p_mcb_ptr;
char p_minor;
char *p_data;
int  p_data_len;
char p_source_system;
char p_source_major;
{
int major_sender;

   major_sender = (p_source_system << 8) | p_source_major;

/* : If suspended and not TERMINATE or RESUME, send FAIL_CAPABILITY to source */

   if ((p_mcb_ptr -> mcb_flag & MCB_SUSPEND) && (p_minor != TERMINATE_APPLICATION)
      && (p_minor != RESUME_APPLICATION) && (p_minor != SUSPEND_APPLICATION))
   {
      return (execap (major_sender, FAIL_CAPABILITY, NULL, 0, p_mcb_ptr));
   }

/* : Else forward to application */

   (*p_mcb_ptr -> application_entry)
      ((int)p_minor, major_sender, p_data, p_data_len,
      p_mcb_ptr -> data_block_ptr, p_mcb_ptr);

   return (0);
}
/**/
/* : PROCEDURE FUNCTION (handle_reset)

Perform the operations necessary to handle resetting the application.
*/

/* : NOTES

POTENTIAL BUG: reset clears out all of the applications input and output
   buffers.  If there are partial long messages being sent/received, this
   may cause problems in the assembly/dissasembly
*/

handle_reset (p_mcb_ptr, p_message, p_message_len)

mcb  *p_mcb_ptr;
struct input_msg *p_message;
int p_message_len;
{
struct linklst *msg_buffer;
struct linklst *next_buf;

/* : Clear out the applications input buffers */

   msg_buffer = p_mcb_ptr -> inbuff;
   while (msg_buffer != NULL)
   {  next_buf = msg_buffer -> nextbuf;
      llpfree (p_mcb_ptr -> inalloc, &(p_mcb_ptr -> inbuff), msg_buffer);
      msg_buffer = next_buf;
   }
   p_mcb_ptr -> inbuff = NULL;

/* : Clear out the applications output buffers */

   msg_buffer = p_mcb_ptr -> outbuff;
   while (msg_buffer != NULL)
   {  next_buf = msg_buffer -> nextbuf;
      llpfree (p_mcb_ptr -> outalloc, &(p_mcb_ptr -> outbuff), msg_buffer);
      msg_buffer = next_buf;
   }
   p_mcb_ptr -> outbuff = NULL;

/* : Pass the RESET_APPLICATION message to the capability */

   forward (p_mcb_ptr, p_message -> minor, &(p_message -> msg_data [0]), 
      p_message_len, p_message -> source_system, p_message -> source_major);
}
/**/
/* : PROCEDURE FUNCTION (handle_fail)

Perform the operations necessary to handle a fail capability,  this means
clearing out the applications output buffers.
*/

handle_fail (p_mcb_ptr, p_message, p_message_len)

mcb  *p_mcb_ptr;
struct input_msg *p_message;
int p_message_len;
{
struct linklst *msg_buffer;
struct linklst *next_buf;

/* : Clear out the applications output buffers */

   msg_buffer = p_mcb_ptr -> outbuff;
   while (msg_buffer != NULL)
   {  next_buf = msg_buffer -> nextbuf;
      llpfree (p_mcb_ptr -> outalloc, &(p_mcb_ptr -> outbuff), msg_buffer);
      msg_buffer = next_buf;
   }
   p_mcb_ptr -> outbuff = NULL;

/* : Pass the FAIL_CAPABILITY message to the capability */

   forward (p_mcb_ptr, p_message -> minor, &(p_message -> msg_data [0]), 
      p_message_len, p_message -> source_system, p_message -> source_major);
}
/**/
/* : PROCEDURE FUNCTION (handle_partial)

Perform the necessary functions when a partial message for the application
arrives.

     -- header_format = system|major|CONTINUE|source_system|source_minor|minor

*/

handle_partial (p_mcb_ptr, p_buflen, p_bufseg, p_bufoff, p_msg_hdr_size, p_link_info_size, p_more_message)

mcb  *p_mcb_ptr;                       /* Capability's MCB */
int  p_bufseg;                         /* Segment address of message */
int  p_bufoff;                         /* Offset of message within segment */
int  p_buflen;                         /* Length of message */
int  p_msg_hdr_size;
int  p_link_info_size;
struct more_msg *p_more_message;

{
int  found;
int  done;
int  buffer_size;
int  amount_to_copy;
int  major_sender;
int  i;
char *more_msg_header1;
char *more_msg_header2;
struct linklst *msg_buffer;
struct linklst *prev_msg_buffer;
struct linklst *new_msg_buffer;


   msg_buffer = p_mcb_ptr->inbuff;
   prev_msg_buffer = p_mcb_ptr->inbuff;

/* : Find if this belongs to a message currently being built */

   found = done = FALSE;
   while ((found == FALSE) && (done == FALSE))
   {  if (msg_buffer == NULL)
         done = TRUE;
      else
      {  more_msg_header1 = (char *) msg_buffer->lldata;
         more_msg_header2 = (char *) p_more_message;

         if (!strncmp(more_msg_header1,more_msg_header2,p_msg_hdr_size))
            found = done = TRUE;
         else
         {  prev_msg_buffer = msg_buffer;
            msg_buffer = msg_buffer->nextbuf;
         }
      }
   }

/* : If done & !found then this is a new long message and allocate space */

   if (found == FALSE)
   {  buffer_size = p_mcb_ptr->inbuff_length + p_link_info_size + p_msg_hdr_size;
      new_msg_buffer = (struct linklst *) wsalloc(p_mcb_ptr->inalloc, buffer_size);

/* : - if succeeded then copy the message in */

      if (new_msg_buffer != NULL)
      {  new_msg_buffer->linksize = buffer_size;
         amount_to_copy = min(buffer_size-p_link_info_size,p_buflen);
         peek(p_bufseg,p_bufoff,new_msg_buffer->lldata,amount_to_copy);
         new_msg_buffer->nextlink = NULL;
         new_msg_buffer->nextbuf = NULL;
         new_msg_buffer->linkused = amount_to_copy;

         if (prev_msg_buffer == p_mcb_ptr->inbuff)
            p_mcb_ptr->inbuff = new_msg_buffer;
         else 
            prev_msg_buffer->nextbuf = new_msg_buffer;
      }

/* : - else make a new message header for it for later */

      else
      {  buffer_size = p_msg_hdr_size+p_link_info_size+1;
         new_msg_buffer = (struct linklst *) wsalloc(p_mcb_ptr->inalloc,buffer_size);

         if (new_msg_buffer != NULL)
         {  for (i=0; i<p_msg_hdr_size; i++)
               new_msg_buffer->lldata[i] = *(((char *) p_more_message)+i);

            new_msg_buffer->nextlink = NULL;
            new_msg_buffer->nextbuf = NULL;
            new_msg_buffer->linkused = buffer_size;
            new_msg_buffer->linksize = buffer_size;

            if (prev_msg_buffer == p_mcb_ptr->inbuff)
               p_mcb_ptr->inbuff = new_msg_buffer;
            else 
               prev_msg_buffer->nextbuf = new_msg_buffer;
         }

/* : -- if can't do that then send FAIL_CAPABILITY to the source */

         else
         {  major_sender = p_more_message -> source_major;
            major_sender = (major_sender << 8) | p_more_message -> minor;
            return (execap(major_sender, FAIL_CAPABILITY, NULL, 0, p_mcb_ptr));
         }
      }
   }
            
/* : - If a buffer is found then add as much as possible to the buffer */

   if (found == TRUE)
   {  amount_to_copy = min((p_buflen-p_msg_hdr_size),(msg_buffer->linksize-msg_buffer->linkused-p_link_info_size));
      peek(p_bufseg,p_bufoff+p_msg_hdr_size,&(msg_buffer->lldata[msg_buffer->linkused]),
         amount_to_copy);
      msg_buffer->linkused += amount_to_copy;
   }

/* : - Send a <CONTINUE_MESSAGE> to the source of the message thus requesting
        more data from the capability sending the long message. */

   major_sender = p_more_message -> source_major;
   major_sender = (major_sender << 8) | p_more_message -> minor;
   return (execap (major_sender, CONTINUE_MESSAGE,&(p_more_message -> source_system),1,p_mcb_ptr));
}
/**/
/* : PROCEDURE FUNCTION (handle_continue)

Handle the continue message for the capability.  This means extracting another
portion of the currently long message from the capability's outbuff.

*/

handle_continue (p_mcb_ptr, p_more_message)

mcb  *p_mcb_ptr;                       /* Capability's MCB */
struct more_msg *p_more_message;

{
int  found;
int  done;
int  major_sender;
int  i;
int  code;
struct linklst *msg_buffer;
struct linklst *prev_msg_buffer;
struct more_msg *message;


   code = 0;
   msg_buffer = p_mcb_ptr->outbuff;
   prev_msg_buffer = p_mcb_ptr->outbuff;
   found = FALSE;
   done = FALSE;

/* : Look for a the message that is to be continued */

   while ((found == FALSE) && (done == FALSE))
   {  if (msg_buffer == NULL)
         done = TRUE;
      else
      {  message = (struct more_msg *) msg_buffer->lldata;
         if ((message->system == p_more_message -> source_system)
            && (message->major == p_more_message -> source_major)
            && (message->source_system == p_more_message -> minor))
         {
            found = TRUE;
            done = TRUE;
         }
         else if ((message->system == p_more_message -> source_system)
            && (message->major == p_more_message -> source_major)
            && (message->more_minor == p_more_message -> minor))
         {
            found = TRUE;
            done = TRUE;
         }
         else
         {  prev_msg_buffer = msg_buffer;
            msg_buffer = msg_buffer->nextbuf;
         }
      }
   }

/* : If found then get the next portion and send it to the destination */

   if (found)
   {  if (prev_msg_buffer == p_mcb_ptr->outbuff)      /* Head of list */
      {  p_mcb_ptr->outbuff = msg_buffer->nextlink;
         if (msg_buffer->nextlink != NULL)
            p_mcb_ptr->outbuff->nextlink->nextbuf = msg_buffer->nextbuf;
      }
      else                                            /* Elsewhere in list */
      {  prev_msg_buffer->nextbuf = msg_buffer->nextlink;
         if (msg_buffer->nextlink != NULL)
            msg_buffer->nextlink->nextbuf = msg_buffer->nextbuf;
      }

/* : - I$EXECAP knows what's going on with the messages, so call it */

      code = call_mowse_int(I$EXECAP,msg_buffer->lldata, msg_buffer->linkused);
      wsfree(p_mcb_ptr->outalloc,msg_buffer);

   }

/* : Otherwise we are trying to continue a message that does not exist so send
     a FAIL_CAPABILITY to the application (this one is sending it) */

   else
   {  code = forward (p_mcb_ptr, FAIL_CAPABILITY, NULL, 0, (char)WSIBMPC, 
         (char)WSMAJCAP);
   }

   return (code);
}
/**/
/* : PROCEDURE FUNCTION (handle_default)

Handle passing the message on to the application.
*/

handle_default (p_mcb_ptr, p_buflen, p_bufseg, p_bufoff, p_minor_cap, p_msg_hdr_size, p_link_info_size, p_more_message)

mcb  *p_mcb_ptr;                       /* Capability's MCB */
int  p_bufseg;                         /* Segment address of message */
int  p_bufoff;                         /* Offset of message within segment */
int  p_buflen;                         /* Length of message */
int  p_minor_cap;
int  p_msg_hdr_size;
int  p_link_info_size;
struct more_msg *p_more_message;
{
int  found;
int  done;
int  buffer_size;
int  amount_to_copy;
int  major_sender;
int  i;
int  all_copied;
int  start_of_message;
int  data_length;
char *more_msg_header1;
char *more_msg_header2;
struct input_msg *input_message;
struct linklst *msg_buffer;
struct linklst *prev_msg_buffer;
struct more_msg *message;

/* : Look for a buffer containing previous portion of this message */

   msg_buffer = p_mcb_ptr->inbuff;
   prev_msg_buffer = NULL;

   found = FALSE;
   done = FALSE;
   while ((found == FALSE) && (done == FALSE))
   {  if (msg_buffer == NULL)
         done = TRUE;
      else
      {  message = (struct more_msg *) msg_buffer->lldata;
         if ((message->system == p_more_message -> system)
            && (message->major == p_more_message -> major)
            && (message->source_system == p_more_message -> more_minor))
         {
            found = TRUE;
            done = TRUE;
         }
         else
         {  prev_msg_buffer = msg_buffer;
            msg_buffer = msg_buffer->nextbuf;
         }
      }
   }

/* : If one exists the copy as much of the current message into the buffer 
     located otherwise allocate a buffer and try to copy all of the message 
     into it. */
        
   if (found == TRUE)
   {  amount_to_copy = min((p_buflen-p_msg_hdr_size+1),(msg_buffer->linksize - msg_buffer->linkused-p_link_info_size));

      if (amount_to_copy == (p_buflen-p_msg_hdr_size+1))
      {  peek(p_bufseg,p_bufoff+p_msg_hdr_size-1,&(msg_buffer->lldata[msg_buffer->linkused]),
            amount_to_copy);
         msg_buffer->linkused += amount_to_copy;
         data_length = msg_buffer->linkused - p_msg_hdr_size;
         start_of_message = p_msg_hdr_size;
         all_copied = TRUE;
      }
      else
         all_copied = FALSE;
   }
   else
   {  buffer_size = p_buflen+p_link_info_size;
      msg_buffer = (struct linklst *) wsalloc(p_mcb_ptr->inalloc,buffer_size);

      if (msg_buffer != NULL)
      {  peek(p_bufseg,p_bufoff,msg_buffer->lldata,p_buflen);
         msg_buffer->nextlink = NULL;
         msg_buffer->nextbuf = NULL;
         msg_buffer->linkused = buffer_size;
         msg_buffer->linksize = buffer_size;
         data_length = p_buflen - (p_msg_hdr_size -1);
         start_of_message = p_msg_hdr_size -1;
         all_copied = TRUE;
      }
      else
         all_copied = FALSE;
   }

             
/* : If all of the current message was copied then call the application
     with the information in the buffer and the minor specified otherwise, 
     call the application with the buffer and the minor = BUFFER_OVERFLOW. */

   major_sender = p_more_message -> source_system;
   major_sender = (major_sender << 8) | p_more_message -> source_major;

   if (all_copied == TRUE)
   {  input_message = (struct input_msg *) msg_buffer->lldata;
      if (input_message->system != WSIBMPC)
         return(-1);

/* : - pass the message on to the application */

      forward (p_mcb_ptr, p_minor_cap, (&(msg_buffer -> lldata[start_of_message])),
         data_length, p_more_message -> source_system, p_more_message -> source_major);
   }
   else
   {  forward (p_mcb_ptr, WSOVRFLW, NULL, 0, (char)WSIBMPC, (char)WSMAJCAP);
   }
                  
/* : Free the buffer just sent to the application if necessary. */

   if ((found == TRUE) && (msg_buffer != NULL))
   {  if ((msg_buffer == p_mcb_ptr->inbuff) ||
         (prev_msg_buffer == p_mcb_ptr->inbuff))
      {
         p_mcb_ptr->inbuff = msg_buffer->nextbuf;
      }
      else
         prev_msg_buffer->nextbuf = msg_buffer->nextbuf;

      wsfree(p_mcb_ptr->inalloc,msg_buffer);
   }
   else
   {  if (msg_buffer != NULL)
         wsfree(p_mcb_ptr->inalloc,msg_buffer);
   }

   return(0);
}




		    pe_entry.asm                    08/07/87  1520.9rew 08/07/87  1438.1       22050



; ***********************************************************
; *                                                         *
; * Copyright, (C) Honeywell Bull Inc., 1987                *
; *                                                         *
; * Copyright, (C) Honeywell Information Systems Inc., 1986 *
; *                                                         *
; ***********************************************************

; HISTORY COMMENTS:
;  1) change(86-07-04,Westcott), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Created.
;                                                      END HISTORY COMMENTS

;/* : PROCEDURE FUNCTION (pe_antry)
;
;Provides a "far" entry point to be used by MOWSE for calling pe.c when an 
;application message is received. The use of this routine allows us to use
;the small memory model for the Lattice compiler.
;*/

include  dos.mac

;-------------- External procedures

extrn    pe:near

;-------------- Data segment

dseg

pe_str  struc
old_bp  dw      ?       ; save area for old bp
off_r1  dw      ?       ; return offset from stack call
seg_r1  dw      ?       ; return segment from stack call
off_r2  dw      ?       ; return offset from wsexecap
seg_r2  dw      ?       ; return segment from execap
mcb_ptr dw      ?       ; param for pe (mcb_ptr)
min_cap dw      ?       ; param for pe (minor_capability)
bufseg  dw      ?       ; param for pe (buffer segment address)
bufoff  dw      ?       ; param for pe (buffer offset address)
buflen  dw      ?       ; param for pe (buffer length)
pe_str  ends
endds

;*************************************************************************
;                                  MAIN
;*************************************************************************
pseg

public pe_entry

pe_entry proc far

        push    bp                     ; save BP
        mov     bp,sp                  ; Get parameter off stack
        push    buflen[bp]             ; ... bp -> pe_str.buf_lend (backwords addressing)
        push    bufoff[bp]             ; ... and put them onto stack individually
        push    bufseg[bp]
        push    min_cap[bp]
        push    mcb_ptr[bp]
        call    pe                     ; call pre_entry routine to application
        mov     sp,bp                  ; put sp back
        pop     bp                     ; restore original bp
        ret

pe_entry endp
endps
       end




		    prime.asm                       08/07/87  1520.9rew 08/07/87  1438.1       35784



; ***********************************************************
; *                                                         *
; * Copyright, (C) Honeywell Bull Inc., 1987                *
; *                                                         *
; * Copyright, (C) Honeywell Information Systems Inc., 1986 *
; *                                                         *
; ***********************************************************

; HISTORY COMMENTS:
;  1) change(86-01-01,McGinn), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Created
;                                                      END HISTORY COMMENTS

;/* PROCEDURE FUNCTION (prime_rs232_out)
;
; Send a BYTE string of specified length to the RS232 port.  This has the effect
; of forcing transmit holding register empty interrupts when the character has 
; been sent where the hard_int can send out the next character to be transmitted.
;*/

;/* : NOTES
;
;       mov  cx,length
;       mov  ES,DS
;       mov  ax,offset string
;       mov  si,ax
;       call prime_RS232_out
;
; Arguments:
;       cx    - length of byte string
;       ES    - Data segment of byte string pointer
;       si    - Address of byte string into the Data segment
;*/

include dos.mac

page
;******************************************************************************
;                        DATA
;******************************************************************************
dseg

;--------- External Declarations

extrn   send_buffer:byte
extrn   send_buffer_end:word
extrn   send_buffer_head:word
extrn   send_buffer_tail:word
extrn   send_buffer_char_count:word
extrn   send_buffer_flag:word

;--------- Public Declarations

public    prime_RS232_out

endds

page
;******************************************************************************
;                        MAIN
;******************************************************************************
pseg

;--------- External Procedures
extrn     RS232_out:near

prime_RS232_out proc near

;/* pc:: Send a character in the send_buffer to RS232 port */

        push ax                       ;save used registers
        push cx
        push si
        mov  si, send_buffer_head     ;get buffer position of character to send
        mov  cx, send_buffer_char_count
                                      ;get number of characters in buffer
        cmp  cx, 0                    ;if buffer empty, do nothing
        je   empty

;   /* pc:: Call RS232_out to send the character to the RS232 port */

        mov  al, byte ptr ds:[si]     ;get next character to send from
                                      ;byte string
        push si                       ;save used registers
        push cx
        call RS232_out                ;RS232_out(al)
        pop  cx                       ;restore registers used
        pop  si

        call incptr                   ;after sending character,
                                      ;set up for next character
        mov  send_buffer_head, si     ;update pointer to next character to send
        mov  send_buffer_char_count, cx
                                      ;update number of characters to send

;   /* pc:: After character has been sent, exit routine */

empty:
        pop  si                       ;restore registers and return
        pop  cx
        pop  ax
        ret

prime_RS232_out endp

;/* : PROCEDURE FUNCTION (incptr)
;
;Increment the buffer pointer for the transmit characters.
;*/

incptr  proc near
        dec  cx                    ;decrement count of characters in buffer
        inc  si                    ;increment pointer to next character to send
        cmp  si, offset send_buffer_end
                                   ;if not at end of buffer, return
        jne  IP100
        mov  si, offset send_buffer
                                   ;end of buffer, set pointer to buffer start
IP100:  ret

incptr  endp
        endps
        end




		    proc_op.c                       08/07/87  1519.8rew 08/07/87  1435.5       18099



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-08-22,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
     install(87-08-07,MR12.1-1072):
     Created.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (process_options)

Processes options in the emulator, depending on the key pressed.  The value 
of the terminate flag passed will always be FALSE unless the 'exit emulator' 
key was pressed.
*/

#include <ctype.h>
#include <ws.h>
#include <ws_dcls.h>
#include <wsmincap.h>
#include <keydefs.h>
#include <emulator.h>

extern char *print_mode_type[];
extern char *on_off_status[];
extern int packetize_flag;
extern int em_print_mode;
extern int em_tab_size;
extern int local_edit;
extern int fg_data_only;
extern int bg_sender_in;
extern int bg_sender_out;
extern int bg_sender_buff[];
extern int dbgpkts;
extern int dbgrejs;
extern int dbgxchr;
extern char *buff;

process_options(option,terminate_flag)

int option;
int *terminate_flag;
{

/* : process special options */

   switch(option) {

/* : sit in a tight loop until any key is pressed */

      case OP_FREEZE:
         freeze();
         break;

/* : pass a command to the command interpreter */

      case OP_EXEDOSCMD: 
         execute_dos_cmd();
         break;

/* : send a foreground break */

      case OP_BREAK:
         puttdata(FG_BREAK,0,0);
         break;

/* : set flag to exit the emulator */

      case OP_EXIT:
         *terminate_flag = FALSE;
         break;

      case OP_BG_REPLY:
         reply_to_query();
         break;
   }
}




		    putbgmes.asm                    08/07/87  1520.9rew 08/07/87  1438.1       48429



; ***********************************************************
; *                                                         *
; * Copyright, (C) Honeywell Bull Inc., 1987                *
; *                                                         *
; * Copyright, (C) Honeywell Information Systems Inc., 1986 *
; *                                                         *
; ***********************************************************

; HISTORY COMMENTS:
;  1) change(86-07-06,Westcott), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Created.
;                                                      END HISTORY COMMENTS

;/* : PROCEDURE FUNCTION (putbgmes)
;
;Sends a message from a background application to the foreground message 
;handler. These messages will be queued by MOWSE until they are retrieved 
;via a getbgmes call from a foreground program.
;*/

;/* : NOTES
;
;Syntax:
;    code = putbgmes(mcb_ptr,code,caller,control,arg1,..argN)
;    mcb *mcb_ptr;
;    int code;
;    char *caller;
;    char *control;
;
;Arguments:
;    mcb_ptr - the pointer to the application's MOWSE control block.
;    code    - determines the type of message if 0, the message will 
;              consist only of the contents of the control string if WSQUERY, 
;              the control string will be used to prompt the user for a 
;              response.
;    caller  - the name of the background machine that is making this call.
;    control - a "printf" control string
;    Arg1..ArgN
;            - printf arguments to be substituted into the control argument. 
;              These arguments are optional. They are only used if required 
;              by the control argument.
;
;Returns:
;    WSINVBUF, if the resulting message is longer than WSPAKSIZ
;*/

include dos.mac
include ws.mac
include ws_dcls.mac
include ws_mcb.mac
include ws_func.mac

;----------- WORKING STORAGE FOR PUTBGMES

dseg

sv_bp   dw      ?       ; caller's BP save space
sv_retn dw      ?       ; return address from call
sv_mcb  dw      ?       ; pointer to caller's mcb
sv_code dw      ?       ; code
work    putbgstr <0,0,0>
string  db      "%d",0  ; control string to sprintf for code expansion

endds

pseg
;----------- PUBLICS

public putbgmes

;----------- EXTERNALS

extrn  call_mowse_int:near
extrn  sprintf:near

;----------- DYNAMIC STORAGE FOR PUTBGMES

dyns    struc
old_bp  dw      ?       ; caller's BP save
retn    dw      ?       ; return address from call
mcb_ptr dw      ?       ; pointer to caller's mcb
code    dw      ?       ; code
caller  dw      ?       ; address of caller string
control dw      ?       ; address of control string
dyns    ends

putbgmes proc near
        push    bp
        mov     bp,sp

;/* : cleanup stack so that a call to sprintf can be made */

        pop     ax
        mov     sv_bp,ax
        pop     ax
        mov     sv_retn,ax
        pop     ax
        mov     sv_mcb,ax
        pop     ax
        mov     sv_code,ax

;/* : insert the caller's name at the beginning of the string */

        pop     si
        lea     di,work.pbgmsg
        xor     cx,cx

pl1:
        lodsb
        or      al,al
        jz      pl2    ; if end of caller's name
        stosb
        inc     cx
        jmp     pl1

pl2:
        mov     al,':'
        stosb
        mov     al,' '
        stosb
        add     cx,2
        mov     work.plength,cx

;/* : Copy in the code value if it is not 0 and not WSQUERY */

        mov     ax, sv_code
        cmp     ax, WSQUERY
        jne     no_query
        mov     work.ptype, ax
        jmp     no_code

no_query:
        mov     work.ptype, WSINFO     ; Info type
        or      ax, ax                 ; Is the code 0?
        je      no_code

        push    di                     ; save message position
        mov     bp, sp
        push    ax                     ; ax is code
        lea     si, string             ; string is control string
        push    si
        push    di                     ; di is current position in message
        call    sprintf
        mov     sp, bp
        add     work.plength, ax       ; save the length of the string
        pop     di
        add     di, ax                 ; increment position in message

        mov     al,'.'                 ; terminate the code with some chars
        stosb
        mov     al,' '
        stosb
        add     work.plength,2

;/* : since control string and arguments are already in the stack, all we 
;     have to do is push the address of the buffer and set the stack pointer. */

no_code:
        mov     bp,sp
        push    di
        call    sprintf
        mov     sp,bp

        add     work.plength,ax        ; save length of string

        mov     bx,sv_mcb
        mov     ah,system_id[bx]
        mov     al,major_capability[bx]
        mov     work.psender_major,ax

        mov     ax,work.plength        ; make sure message is less than WSPAKSIZ
        cmp     ax,WSPAKSIZ
        jle     no_overflow
        mov     work.plength,WSPAKSIZ

no_overflow:
        mov     bp,sp
        mov     cx,type work
        push    cx
        lea     bx,work
        push    bx
        mov     ax,I$PUTBGMES
        push    ax
        call    call_mowse_int
        mov     sp,bp
        mov     bp,sv_bp
        push    sv_retn
        ret

putbgmes endp
endps
        end





		    putstat.c                       08/07/87  1519.8rew 08/07/87  1435.5       17163



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-07-12,Westcott), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (putstat)

Sends a message to the foreground application that contains a null terminated 
character string that contains status information.
*/

#include <dos.h>
#include <stdio.h>
#include <ws.h>
#include <ws_dcls.h>
#include <ws_func.h>
#include <ws_error.h>
#include <wsmincap.h>

putstat (p_status_reply,p_mcb_ptr)

char *p_status_reply;                    /* Reply message */
mcb  *p_mcb_ptr;                         /* Caller's MCB */
{
int code;               /* return code */
int i;                  /* loop counter*/
int system;
int major;
int param_size;
struct putbg_struc msg; /* structure for message */

   if (p_mcb_ptr == NULL)
      return (WSINVMCB);

/* : copy status argument to mowse buffer */

   msg.length = stccpy (msg.bgmsg, p_status_reply, WSPAKSIZ);

/* : create caller's major capability number */

   system = (int)(p_mcb_ptr -> system_id);
   major = (int)(p_mcb_ptr -> major_capability);
   if (code = c_pack (system, major, &msg.sender_major))
      return (code);

/* : call user_interrupt to send the status */

   msg.type = STATUS_REPLY;
   param_size = msg.length + sizeof (struct putbg_struc) - WSPAKSIZ;
   return (call_mowse_int (I$PUTBGMES, &msg , param_size));
}




		    puttdata.c                      08/07/87  1519.8rew 08/07/87  1435.5       19512



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-04-26,Westcott), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
                                                   END HISTORY COMMENTS */
/* : PROCEDURE FUNCTION (puttdata)

Sends a data string to the Multics user i/o switch over the foreground channel.
*/

#include <dos.h>
#include <ws.h>
#include <ws_dcls.h>
#include <ws_func.h>
#include <wsmincap.h>

#define LOW_BYTE   0x00FF

puttdata (p_min_cap, p_buffer_ptr, p_buffer_len)

int  p_min_cap;                        /* Minor capability of foreground data */
char *p_buffer_ptr;                    /* Pointer to data to be sent */
int p_buffer_len;                      /* Length of data to send */
{
struct putt_struc ps;
int  error_code;
int  length;
int  i;
char *sp;


/* : if minor cap is FG_BREAK, then no data and call mowse */

   if (p_min_cap == FG_BREAK)
      return (call_mowse_int (I$FOREBREAK, 0, 0));

/* : If minor cap is 125-127, then submit a request to turn on the appropriate
     debug packet switch */

   if ((p_min_cap & LOW_BYTE) >= 125)
      return (call_mowse_int (8, &p_min_cap, 2));

/* : call user_interrupt to put data */

   ps.minor_cap = p_min_cap;

/* : while (string length > 0) send data in packet size chunks */

   while (p_buffer_len > 0)
   {  if (p_buffer_len > WSPAKSIZ) 
         length = WSPAKSIZ;
      else
         length = p_buffer_len;

      sp = &ps.putstr[0];
      for (i=0; i < length; i++)
      {  *sp++ = *p_buffer_ptr++;
      }

/* : - send  packet to mowse */

      ps.putstrl = length;
      error_code = call_mowse_int (I$PUTTDATA,&ps ,sizeof(ps));
      p_buffer_len -= length;
   }

   return(error_code);
}




		    rcvbyte.asm                     08/07/87  1520.9rew 08/07/87  1438.0       57420



; ***********************************************************
; *                                                         *
; * Copyright, (C) Honeywell Bull Inc., 1987                *
; *                                                         *
; * Copyright, (C) Honeywell Information Systems Inc., 1986 *
; *                                                         *
; ***********************************************************

page 55,132
; HISTORY COMMENTS:
;  1) change(86-07-26,Westcott), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Created.
;  2) change(86-08-27,Flegel), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Installed support for /M option in MOWSE.
;  3) change(86-08-29,Flegel), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Test and set installed to prevent recursive
;     calls to recevie_byte, thus preventing race condition.
;                                                      END HISTORY COMMENTS

;/* : PROCEDURE FUNCTION (rcvbyte)

;Transfer received data from the RS232 input circular buffer to the protocol
;analyzer (rcvchr.c) if MOWSE is running, and into fg_sav_buf if MOWSE is
;not running.

;This routine also detects hardware error and status flags embedded in the
;data stream in a two byte
;*/

;/* : NOTES

;format:
;      Byte 0 = 3, following byte contains line status      */
;      Byte 0 = 4, following byte contains modem status     */
;      Byte 0 = 5, following byte contains buffer status    */
;      Byte 0 = 6, following byte contains input data       */

;If an error or status message is detected, then a message will be written to
;the PC screen.

;This routine calls get_inbuff, which also detects whether the MOWSE protocol
;is running and sets the the packet_mode flag if it is.                          */
;*/

;/* : RETURNS

;number of characters transferred.
;*/

include dos.mac                 ;Lattice include file
include mowsdefs.mac
include rs232err.mac            ; Error definitions
include wsmincap.mac            ; Predefined mincaps
include ws_buf.mac              ; Circular buffer definitions

;**************************************************************
;                                       DATA
;**************************************************************
dseg

;--------- External Declarations

extrn packet_mode:word
extrn in_protocol:word
extrn fg_buf:word
extrn error_mode:word

;--------- Public Declarations
public  receive_byte

;--------- Local Memory Declarations
merr      db      "***** ERROR  Modem status :  "
merrval   db      0,0
rerr      db      "***** ERROR  Receive Error:  "
rerrval   db      0,0
berr      db      "***** ERROR Buffer overflow ",0

proc_lock db      0       ; procedure lock
endds

;**************************************************************
;                                       MAIN
;**************************************************************
pseg

;-------- External Procedures
extrn   get_inbuff:near
extrn   sstmsg:near
extrn   rcvchr:near
extrn   setlock:near

receive_byte proc near
        push    bp

; /* : If currently executing, return */
        mov     bp,sp
        mov     bx,offset proc_lock
        push    bx
        call    setlock
        mov     sp,bp
        test    ax,1
        je      rcv_ok                   ; if lock not set then OK
        jmp     rcv_active               ; else do not process

; /* : Pass characters in inbuff to protocol */

rcv_ok:
        test    packet_mode,1            ; if in packet mode
        jnz     rcv_loop                 ;    jump to packet mode handler
        push    ax                       ; else dump chars to fg buffer
        push    bx
        mov     bx,offset fg_buf
        mov     ax,bout[bx]
        sub     ax,bin[bx]
        ja      skip1                    ; if no wrap
        add     ax,bsize[bx]

skip1:
        cmp     ax,2
        pop     bx
        pop     ax
        jb      rcv_nodat               ; if fg_buf is full
        mov     byte ptr fg_buf+bminor,FG_TERMINAL_DATA
        jmp     rcv_loop

rcv_nodat:
        jmp     no_rcvdata

rcv_loop:
        call    get_inbuff
        jnc     rcv_nodat               ; if input buffer empty
        cmp     al,ESCAPE_STATUS
        ja      call_rcv                ; if valid character
        je      esc_rcv                 ; if escape character
        cmp     al,LINE_STATUS
        jb      call_rcv                ; if valid character
        je      lsrerr                  ; receive error
        cmp     al,INTERRUPT_STATUS
        je      inbuff_ovf              ; if buffer overflow occurred
        call    get_inbuff              ; get error character

;/* : display error message */

        mov     bx, offset merr
        mov     merrval,al
        jmp     display_err

lsrerr:
        call    get_inbuff              ; get error character
        mov     bx, offset rerr
        mov     rerrval,al

display_err:
        test    error_mode, 1           ; if in error mode, display modem error
        je      rcv_loop
        mov     bp,sp
        push    bx
        call    sstmsg
        mov     sp,bp
        jmp     rcv_loop

inbuff_ovf:
        mov     bx,offset berr
        jmp     display_err

esc_rcv:
        call    get_inbuff              ; get valid character

;/* : call rcvchr to pass character to PAD */

call_rcv:
        mov     bx, packet_mode
        cmp     bx, 1
        jne     receive_data
        mov     bp, sp
        push    ax
        call    rcvchr
        mov     sp, bp
        jmp     rcv_cont

;/* : Else move data to foreground save buffer */

receive_data:
        put_buf fg_buf
        push    bx
        mov     bx,offset fg_buf
        mov     ax,bout[bx]
        sub     ax,bin[bx]
        ja      skip2                   ; if no wrap
        add     ax,bsize[bx]

skip2:
        cmp     ax,2
        pop     bx
        jb      no_rcvdata              ; if fg_buf is full

rcv_cont:
        jmp     rcv_loop

no_rcvdata:
lock    mov     proc_lock,0             ; clear procedure lock

rcv_active:                             ; jump label around clearing of
        pop     bp                      ;    procedure lock
        ret

;/* : END receive_byte */
receive_byte endp

        endps
        end




		    rcvdata.c                       08/07/87  1519.8rew 08/07/87  1435.5       87516



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(85-12-22,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
  2) change(86-01-30,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     New parameter format.
  3) change(86-05-26,Westcott), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Suport for subchannels.
  4) change(86-08-27,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Extracted queue insertion sections and FG
     buffer manipulations.
  5) change(86-08-29,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Removed call to receive_byte.
  6) change(86-09-02,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Extracted section for wakeup.
  7) change(86-10-10,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Support for autoload.
  8) change(86-11-11,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Call to external_mowse before wsexecap.
  9) change(86-12-09,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Check on packetize_flag rather than packet_mode
     for autoload.
 10) change(86-12-11,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Guaruntee a reply is sent to the source of a
     REQUEST_DISCONNECT message if the destination does not exist.
 11) change(87-01-06,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Added guaruntee to send a status reply in the
     event that the specified capability does not exist for a status request.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (rcvdata):

Get a message from the Protocol Handler . If the message is from the foreground
channel, then insert it into the foreground buffer (terminal_buf). If the
message is from the background channel, then call message_parser to handle it.
*/

#include <dos.h>
#include <stdio.h>
#include <ws.h>
#include <alloc.h>
#include <cat.h>
#include <ws_fgb.h>
#include <ws_dcls.h>
#include <ws_buf.h>
#include <ws_msg.h>
#include <wsmincap.h>
#include <ws_error.h>
#include <ws_auto.h>

extern struct fgbstr *lcbfptr;         /* First entry in application global buffer */
extern struct fgbstr *lcblptr;         /* ... last */
extern struct bstruc fg_buf;           /* Foreground intermediate buffer */
extern struct allocstr *lcaptr;        /* Application global allocation area */

extern int bg_in_use;                  /* Background active flag */
extern int packetize_flag;             /* MOWSE protocol active flag */
extern int mowse_terminating;          /* True when Multics MOWSE shutting down */
extern int load_list_pending;          /* Whether there are autoloads to perform */

extern char bg_sav_buf[];             /* Intermediate background message buffer */
extern char mysystem;                 /* System id */

extern local_cat *sleepq;             /* Sleeping application list */
extern local_cat l_CAT[];             /* Local cat */

/**/

rcvdata (p_dosflag)
int  p_dosflag;                /* =1, if entry through int28 (DOS)  */
{
int loopflag;                  /* Determinas when we are done processing */
int size;                      /* Size calculation space */
int ecode;                     /* Error code */
int i;                         /* Counter */
int length;                    /* Length calculation space */
int majorcap;                  /* Major capability number */
int inpl;                      /* length of input message */

struct input_msg *ip;          /* pointer to input message header structure  */

struct fgbstr *bufp;           /* Temporary buffer pointer */
struct fgbstr *fgbp1;          /* Capability buffer pointer */

local_cat *catp;               /* pointer to a CAT entry */

char *p1;                      /* Temporary pointers */
char *f1;

char  *wsalloc();
int   rcvfgdat();


/* : Clear out input buffer */

   receive_byte();

/* : while (more data available from protocol) */

   loopflag = 1;
   while (loopflag) {
      loopflag = 0;

/* : - if room in foreground save buffer (empty) (buffer begins at bminor) */

      if (fg_buf.bin == fg_buf.bout) {
         length = getdat(FG,&fg_buf.bminor);
         if (length > 0) {
            loopflag = 1;
            fg_buf.bout = fg_buf.bfirst;
            fg_buf.bin = fg_buf.bfirst + length - 1;
         }
      }

/* : - if room in background save buffer */

      if (!bg_in_use)
      {  bg_in_use = getdat(BG,&bg_sav_buf);
         if (bg_in_use > 0)
         {  loopflag = 1;
            bufp = (struct fgbstr *)wsalloc (lcaptr,bg_in_use + 1 + sizeof(struct fgbstr));
            if (bufp != NULL)

/* : -- copy to local capability buffer */

            {  p1 = &bg_sav_buf[0];
               f1 = &bufp -> fgb_char[0];
               for (i = 0; i < bg_in_use; i++)
               {  *f1++ = *p1++;
               }
               *f1++ = '\0';             /* terminate all messages with NULL */
               bufp -> fgb_length = bg_in_use;
               bufp -> fgb_next = NULL;
               bg_in_use = 0;

/* : -- link to previous local capability buffers */

               rcvmsg (bufp, &lcbfptr, &lcblptr);
            }
         }
      }

/* : - if foreground data available */

      if (fg_buf.bin != fg_buf.bout)
         rcvfgdat (&fg_buf);

/* : - if mowse terminating on Multics, dtm_mowse */

      if (mowse_terminating && !p_dosflag)
      {  dtm_mowse ();
         mowse_terminating = 0;
      }

/* : - if sleep queue is not empty and dos was NOT interrupted
     -- call wakeup */

      if (sleepq != NULL && !p_dosflag)
         wakeup ();

/* : - if there are any autoloads pending then load them */

      if (!p_dosflag && load_list_pending && packetize_flag)
      {  load_list_pending = 0;
         autoload ();
      }

/* : - if background data available */

      if ((lcbfptr != 0) && (!p_dosflag) ) {
         bufp = lcbfptr;
         inpl = bufp -> fgb_length;
         ip = (struct input_msg *) &bufp -> fgb_char[0];

/* : -- if major_capability number = mowse major capability
     --- call internal to parse and deal with the message */

         if (ip -> major == WSMAJCAP) {
            internal_mowse(inpl,ip);
         }

/* : -- Else */

         else {
            majorcap = ((int) ip -> major) - MIN_CAPABILITY_NUMBER;

/* : --- if capability is not active (does not exist)
     ---- send error message back to sender(FAIL_CAPABILITY) */

            if ((majorcap < 0) || (majorcap > NUMBER_OF_CAT_ENTRIES))
               message_error (ip -> source_system, ip -> source_major, FAIL_CAPABILITY);
            else if (l_CAT[majorcap].mcb_ptr == NULL)
            {  if (ip -> minor == PARTIAL_MESSAGE)
                  message_error (ip -> source_major, ip -> msg_data[0], FAIL_CAPABILITY);
               else if (ip -> minor == REQUEST_DISCONNECT)
                  message_error (ip -> source_system, ip -> source_major, RESPONSE_DISCONNECT);
               else if (ip -> minor == GET_STATUS)
                  message_error (ip -> source_system, ip -> source_major, STATUS_REPLY);
               else
                  message_error (ip -> source_system, ip -> source_major, FAIL_CAPABILITY);
            }

/* : --- else pass message to the application */

            else {
               external_mowse (&l_CAT[majorcap],ip,inpl);
            }
         }
         loopflag = 1;
         lcbfptr = bufp -> fgb_next;
         if (lcbfptr == NULL)
            lcblptr = NULL;
         wsfree (lcaptr,bufp);
      }
   }
}

/**/

/* : PROCEDURE FUNCTION (message_error)

Send the appropriate error to the source.
*/

message_error (p_system, p_major, p_minor)

char p_system;                         /* Destination system of error */
char p_major;                          /* Destination major */
char p_minor;                          /* Minor to send */
{
struct input_msg exerep;               /* Message */
char   data;                           /* Message data */
struct putbg_struc status_msg;         /* Status reply message */

   exerep.system        = p_system;
   exerep.major         = p_major;
   exerep.minor         = p_minor;
   exerep.source_major  = WSMAJCAP;
   exerep.source_system = mysystem;

/* : If minor was RESPONSE_DISCONNECT, then it failed */

   if (p_minor == RESPONSE_DISCONNECT)
   {  data = WSREJECT;
      send_i_mess(&exerep.system, sizeof(exerep) - 1, &data, 1);
   }

/* : Else if it was GET_STATUS, send an error message back */

   else if (p_minor == STATUS_REPLY)
   {  status_msg.type = STATUS_REPLY;
      status_msg.sender_major = (mysystem << 8) | WSMAJCAP;
      strcpy (status_msg.bgmsg, "Capability does not exist.");
      status_msg.length = strlen (status_msg.bgmsg);

      i_putbgm (&status_msg);
   }

/* : Else pass on the minor capability provided */

   else
      send_i_mess(&exerep.system, sizeof(exerep) - 1,NULL,0);
}




		    rcvfgdat.c                      08/07/87  1519.8rew 08/07/87  1435.5       32427



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-08-27,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created from extraction of rcvdata.c
  2) change(86-12-10,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Placed status reply messages into Status buffer .
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (rcvfgdat):

Receive foreground data and dump it into the foreground terminal data queue
or into the background message queue accordingly.
*/

#include "dos.h"
#include "stdio.h"
#include "ws.h"
#include "alloc.h"
#include "cat.h"
#include "ws_fgb.h"
#include "ws_buf.h"
#include "ws_msg.h"
#include "wsmincap.h"
#include "ws_error.h"

extern struct fgbstr   *fgbfptr;       /* FG buffer first pointer */
extern struct fgbstr   *fgblptr;       /* FG buffer last pointer */
extern struct fgbstr   *bgbfptr;       /* BG buffer first pointer */
extern struct fgbstr   *bgblptr;       /* BG buffer last pointer */
extern struct fgbstr   *sgbfptr;       /* Status buffer first pointer */
extern struct fgbstr   *sgblptr;       /* Status buffer last pointer */
extern struct allocstr *fgaptr;        /* FG allocation buffer */
extern struct allocstr *bgaptr;        /* BG allocation buffer */
extern int             bgcount;        /* Number of messages in BG buffer */

rcvfgdat (p_fg_buff_ptr)
struct bstruc *p_fg_buff_ptr;
{
int i;
int length;
struct fgbstr *bufp;
char *p1;
char *f1;

/* EXTERNAL PROCEDURES */
int  rcvmsg();
char *wsalloc();


/* : If no foreground data, return */
   if (p_fg_buff_ptr -> bin == p_fg_buff_ptr -> bout)
      return (0);

/* : Allocate space for buffer */
   length = p_fg_buff_ptr -> bin - p_fg_buff_ptr -> bout;
   if (length < 0)
      length += p_fg_buff_ptr ->bsize;

   if (length >WSMINBUF)
      length = WSMINBUF;

   if ((p_fg_buff_ptr -> bminor == BG_MESSAGE)
      || (p_fg_buff_ptr -> bminor == BG_QUERY) 
      || (p_fg_buff_ptr -> bminor == STATUS_REPLY))
   {
      bufp = (struct fgbstr *) wsalloc (bgaptr,length + sizeof(struct fgbstr));
   }
   else
      bufp = (struct fgbstr *) wsalloc (fgaptr,length + sizeof(struct fgbstr));

/* : If allocation failed, lose the message and return */
   if (bufp == NULL)
      return (0);

/* : copy to foreground buffer */
   p1    = &bufp->fgb_minor;
   *p1++ = p_fg_buff_ptr -> bminor;
   f1    = p_fg_buff_ptr -> bout;

   for (i = 0; i < length; i++)
   {  *p1++ =  *f1++;
      if (f1 > p_fg_buff_ptr -> blast)
         f1 = p_fg_buff_ptr -> bfirst;
   }

   p_fg_buff_ptr -> bout = f1;
   bufp->fgb_length = length;
   bufp->fgb_next = NULL;

/* : Link to previous background message buffer */
   if ((p_fg_buff_ptr -> bminor == BG_MESSAGE)
      || (p_fg_buff_ptr -> bminor == BG_QUERY))
   {  if (bgbfptr == NULL)
         bgcount = 1;
      else
         bgcount++;
      rcvmsg (bufp, &bgbfptr, &bgblptr);
   }
   else if (p_fg_buff_ptr -> bminor == STATUS_REPLY)
      rcvmsg (bufp, &sgbfptr, &sgblptr);

/* : Else link to foreground message buffer */
   else
      rcvmsg (bufp, &fgbfptr, &fgblptr);
}




		    rcvmsg.c                        08/07/87  1519.8rew 08/07/87  1435.4       14913



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-08-27,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created from extraction of rcvdata.c
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (rcvmsg):

Place the specified message into the specified linked list.
*/

#include "dos.h"
#include "stdio.h"
#include "ws.h"
#include "alloc.h"
#include "cat.h"
#include "ws_fgb.h"
#include "ws_buf.h"
#include "ws_msg.h"
#include "wsmincap.h"
#include "ws_error.h"

/**/

rcvmsg (p_msg_ptr, p_first_ptr, p_last_ptr)
struct fgbstr *p_msg_ptr,           /* Message to be inserted */
              **p_first_ptr,        /* First element in list */
              **p_last_ptr;         /* Last element in list */
{
struct fgbstr    *temp_ptr;         /* Temp holding for pointer */

/* MAIN */

/* : If no data, return */
   if (p_msg_ptr == NULL)
      return (0);

/* : Link to previous background message buffers */
   if (*p_first_ptr == NULL)
   {  *p_first_ptr = p_msg_ptr;
      *p_last_ptr  = p_msg_ptr;
   }
   else
   {  temp_ptr = *p_last_ptr;
      temp_ptr -> fgb_next = p_msg_ptr;
      *p_last_ptr = p_msg_ptr;
   }
}




		    resetcap.c                      08/07/87  1519.8rew 08/07/87  1435.4       17676



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-07-13,Westcott), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
  2) change(86-11-11,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Source capability needs to be passed in the
     message.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (resetcap)

Sends a "RESET_APPLICATION" minor capability message to the addressed major 
capability. This message is used by the major capability as a signal to 
discard all un-processed buffers amd to reset all counters, etc.
*/

#include <stdio.h>
#include <ws.h>
#include <wsmincap.h>
#include <ws_mcb.h>
#include <ws_dcls.h>
#include <ws_func.h>
#include <ws_error.h>

resetcap (p_major_number, p_mcb_ptr)

int p_major_number;
mcb *p_mcb_ptr;
{
int code;                /* return code  */
int system;              /* Temp system id */
int major;               /* Temp major cap */
struct xcap_struc xcap;  /* parameter area for call to MOWSE */

   if (p_mcb_ptr == NULL)
      return (WSINVMCB);

/* : send message to application */

   if (code = c_unpack (&system, &major, p_major_number))
      return (code);

   xcap.system = (char)system;
   xcap.major = (char)major;
   xcap.minor = RESET_APPLICATION;
   xcap.source_system = p_mcb_ptr -> system_id;
   xcap.source_major  = p_mcb_ptr -> major_capability;

   return (call_mowse_int (I$RESET, &xcap, sizeof (xcap) - 1));
}




		    resume.c                        08/07/87  1519.8rew 08/07/87  1435.4       17064



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-07-13,Westcott), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (resume)

Sends a "RESUME_APPLICATION" minor capability message to the addressed major 
capability. This message is used by the major capability as a signal to begin 
processing messages again.
*/

#include <stdio.h>
#include <ws.h>
#include <wsmincap.h>
#include <ws_mcb.h>
#include <ws_dcls.h>
#include <ws_func.h>
#include <ws_error.h>

extern char local_system;

resume (p_major_number, p_mcb_ptr)

int p_major_number;
mcb *p_mcb_ptr;
{
int code;                              /* return code  */
int system;                            /* Temporary system id */
int major_cap;                         /* Temporary capability index */
struct xcap_struc xcap;                /* parameter area for call to MOWSE */

   if (p_mcb_ptr == NULL)
      return (WSINVMCB);

/* :  Send message to application via MOWSE */

   code = c_unpack (&system, &major_cap, p_major_number);
   if (code != 0) 
      return (code);

   xcap.system        = system;
   xcap.major         = major_cap;
   xcap.minor         = RESUME_APPLICATION;
   xcap.source_system = p_mcb_ptr -> system_id;
   xcap.source_major  = p_mcb_ptr -> major_capability;

   return (call_mowse_int (I$RESET, &xcap , sizeof (xcap) - 1));
}




		    rs232out.asm                    08/07/87  1520.9rew 08/07/87  1438.0       34416



; ***********************************************************
; *                                                         *
; * Copyright, (C) Honeywell Bull Inc., 1987                *
; *                                                         *
; * Copyright, (C) Honeywell Information Systems Inc., 1986 *
; *                                                         *
; ***********************************************************

PAGE 55,132

; HISTORY COMMENTS:
;  1) change(85-12-15,Flegel), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Created.
;                                                      END HISTORY COMMENTS

;/* : PROCEDURE FUNCTION (RS232_out):
;
;Send the byte in al to the RS232 port only when it is safe to do so.
;*/

;/* : ARGUMENTS
;
;     al - byte to be outputted to RS232 port
;*/

include dos.mac                 ;Lattice include file
include mowsdefs.mac            ;Constant values
include rs232err.mac            ; Hardware interrupt errors
include ws_buf.mac              ; circular buffer macros

;*******************************************************************
;                            DATA
;*******************************************************************
dseg

;-------- External declarations

extrn  COM_PORT:word

;-------- Public Declarations
public RS232_out

endds

page
;*******************************************************************
;                             MAIN
;*******************************************************************
pseg

;--------- External Procedures

extrn put_inbuff:near

RS232_out proc near

        push ax
        push bx
        push cx
        push dx

;/* : Set up RS232 */

        mov     bl,al                  ;Save char to bl temporarily
        mov     dx,MCR                 ;Modem control Register
        add     dx,COM_PORT
        mov     al,MCRREAD             ;Out2, DTR, RTS
        out     dx,al
        sub     cx,cx                  ;Initialize timeout count
        mov     dx,MSR                 ;Modem status Register
        add     dx,COM_PORT

;/* : Wait for CTS (Clear to send) */

RS150:  
        sub     cx,cx                  ;Another timeout count

TIME_LOOP:  
        in      al,dx
        test    al,MSRCTS              ;Clear to send?
        jnz     SEND_CLEAR             ;yes
        loop    TIME_LOOP              ;No, loop til timeout

;/* : Too long, exit */

        mov     ah,INTERRUPT_STATUS
        mov     al, ISCTSTO            ; record CTS timeout
        call    put_inbuff
        jmp     short RSXIT            ;And QUIT

;/* : Wait for THRE (Transmit Holding Register Empty) */

SEND_CLEAR:
        mov     dx,LSR                 ;Line Status register
        add     dx,COM_PORT
        sub     cx,cx                  ;Another time out

STATUS_TIMING:
        in      al,dx                  ;LSR status
        test    al,LSRTHRE             ;Transmit holding reg empty
        jnz     SEND_CHAR              ;Yes
        loop    STATUS_TIMING          ;No, loop til timeout

;/* : Too long, exit */

        mov     ah,INTERRUPT_STATUS
        mov     al,ISTHRETO
        call    put_inbuff             ;record error
        jmp     short RSXIT            ;And QUIT

;/* : Get line status , send char */

SEND_CHAR:
        mov     ah,al                  ;Get line status for return
        and     ah,MASK7               ;mask bit 7
        mov     al,bl                  ;restore char to al
        mov     dx,THR                 ;transmit holding register
        add     dx,COM_PORT
        out     dx,al                  ;Output it to RS232

RSXIT:  
        pop     dx                     ;Restore Registers
        pop     cx
        pop     bx
        pop     ax
        ret

RS232_out endp
        endps
        end




		    send.asm                        08/07/87  1520.8rew 08/07/87  1437.8       28071



; ***********************************************************
; *                                                         *
; * Copyright, (C) Honeywell Bull Inc., 1987                *
; *                                                         *
; * Copyright, (C) Honeywell Information Systems Inc., 1986 *
; *                                                         *
; ***********************************************************

; HISTORY COMMENTS:
;  1) change(86-01-01,McGinn), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Created.
;  2) change(86-04-13,Flegel), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Major/minor capability number in dh/dl.
;                                                      END HISTORY COMMENTS

;/* : PROCEDURE FUNCTION (send_message)
;
;Send the message to multics through protocol channels with major/minor 
;numbers prepended to the message.
;*/

;/* : NOTES
;
;Syntax:
;        mov  cx,length
;        mov  dh,major_cap
;        mov  dl,major_cap
;        mov  si,offset data_buff
;
;Arguments:
;        cx - length of data
;        dx - major/minor capability number
;        si - address of data
;
;
;Currently, messages greater than 1 packet length will lose the data after 
;one packetlength.
;*/

page 55,132
include dos.mac
include mowsdefs.mac

dseg

;---------- Public Declarations

public send_message
hal_buff        db 255
endds
page
;**************************************************************************
;                               MAIN
;**************************************************************************
pseg

;----------- Externals

extrn snddat:near

send_message proc near

        push ax
        push cx
        push dx
        push di
        push si

;/* : place major and minor into packet buffer */

        mov  ax,offset hal_buff
        mov  di,ax

        add  dh,ADD_CONTROL            ; Make sure major printable
        mov  ds:[di],dh
        inc  di
        add  dl,ADD_CONTROL            ; Make sure minor printable
        mov  ds:[di],dl
        inc  di

;/* : Copy message into sending packet buffer */

        push cx

copyloop:
        mov  ax, es:[si]               ; si is indexing source data
        mov  ds:[di], ax               ; di is indexing destination data
        inc  si
        inc  di
        loopne copyloop

        pop  cx
        add  cx,2                      ; add character count plus minr/major count

        mov  si, offset hal_buff       ; prepare to call into snddat
        mov  ax, 1
        mov  bp,sp
        push cx                        ; length
        push si                        ; Message address
        push ax                        ; channel

;/* : call snddat(channel, data, length) */

        call snddat                     ;Hal's routine to build packet &
                                        ;send it to multics
        mov  sp,bp

        pop  si
        pop  di
        pop  dx
        pop  cx
        pop  ax
        ret

send_message endp
        endps
        end




		    sendimsg.c                      08/07/87  1519.8rew 08/07/87  1435.4       45540



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-06-01,Westcott), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
  2) change(86-11-24,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Check to make sure that it is safe to send
     to the destination (is it suspended?).
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (sendimsg):

This module is used by internal mowse programs to send an internal mowse 
minor capability message to another application.
*/

#include <stdio.h>
#include <dos.h>
#include <ws.h>
#include <alloc.h>
#include <ws_error.h>
#include <ws_msg.h>
#include <ws_fgb.h>
#include <cat.h>
#include <wsmincap.h>

extern struct allocstr *lcaptr;
extern struct fgbstr   *lcbfptr,
                       *lcblptr;
extern char            mysystem;
extern local_cat       l_CAT[];        /* Local CAT */
extern remote_cat      r_CAT[];        /* Remote CAT */

send_i_mess (p_message,p_message_len,p_data,p_data_len)

struct input_msg  *p_message;          /* Message header */
int     p_message_len;                 /* length of header */
char    *p_data;                       /* Data in message */
int     p_data_len;                    /* Length of data in message */
{
char *flags;                           /* Flags of application */
char header[6];                        /* Header string */
char *data_ptrs[2];                    /* Message pieces */
int  data_lens[2];                     /* Message piece lengths */
int  major;                            /* Major capability index into CAT */
int  error;
int  total_len;                        /* Combined length of message */
int  i;
char *c1;                              /* Copy pointers */
char *c2;
struct fgbstr *bufp;                   /* Mesage buffer for local messages */
struct fgbstr *lcbp1;                  /* Temp pointer for local message insertion */

char *wsalloc();


/* : Get the flags of the destination application, at the same time, make
     sure the capability exists */

   major = (int) (p_message -> major) - MIN_CAPABILITY_NUMBER;
   if ((major < 0) || (major > NUMBER_OF_CAT_ENTRIES))
   {  if (p_message -> major != WSMAJCAP)
         return (WSINVNUM);
      flags = NULL;
   }
   else if (p_message -> system == mysystem)
   {  if (!l_CAT[major].mcb_ptr)
         return (WSINVNUM);
      flags = &(l_CAT[major].flags);
   }
   else
   {  if (!r_CAT[major].major_capability)
         return (WSINVNUM);
      flags = &(r_CAT[major].flags);
   }

/* : If something about the flags says that we shouldn't send, return suspended */

   if (flags)
   {  if ((*flags & (SUSPENDED_BIT | RESET_BIT))
         && (p_message -> minor != TERMINATE_APPLICATION)
         && (p_message -> minor != RESUME_APPLICATION)
         && (p_message -> minor != SUSPEND_APPLICATION)
         && (p_message -> minor != RESET_APPLICATION)
         && (p_message -> minor != FAIL_CAPABILITY))
      {
         return (WSSUSPND);
      }
   }

/* : if message is addressed to this system  */

   if (p_message -> system == mysystem) {
      total_len = p_message_len + p_data_len;
      bufp = (struct fgbstr *)wsalloc (lcaptr,total_len+sizeof(struct fgbstr));

/* : - copy to local capability buffer */

      if (bufp != NULL) {
         c1 = (char *) p_message;
         c2 = &bufp -> fgb_char[0];
         for (i = 0;i < p_message_len;i++) {
            *c2++ = *c1++;
         }
         c1 = p_data;
         for (i = 0;i < p_data_len;i++) {
            *c2++ = *c1++;
         }
         bufp -> fgb_length = total_len;

/* : - link to previous local capability buffers  */

         bufp -> fgb_next = NULL;
         if (lcbfptr == NULL) {        /* Head */
            lcbfptr = bufp;
            lcblptr = bufp;
         }
         else {                        /* Tail */
            lcbp1 = lcblptr;
            lcbp1 -> fgb_next = bufp;
            lcblptr = bufp;
         }
         return(0);
      }
      return(WSBUFOVR);
   }
/* : else message is addressed to remote system
     - set up structure for snddat */

   else {
      data_ptrs[0] = (char *) p_message;
      data_lens[0] = p_message_len;
      data_ptrs[1] = p_data;
      data_lens[1] = p_data_len;

/* : - while (message not sent because window full) try and send 2 messages */
   while (snddat (BG, 2 ,&data_ptrs,&data_lens) == 1);

/* : - return with error code
     -- = 0, if message sent
     -- = WSBUFOVR, if message too long */

   if (error == -1)
      return (WSBUFOVR);
   return(0);
   }
}




		    sendqrep.c                      08/07/87  1519.8rew 08/07/87  1435.4       17064



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-07-12,Westcott), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (sendqrep)

Send a user' response to a query message to the originator of the background 
query message. The reponse must be less than or equal to WSPAKSIZ characters 
in length.
*/

#include <dos.h>
#include <stdio.h>
#include <ws.h>
#include <ws_msg.h>
#include <ws_func.h>
#include <ws_mcb.h>
#include <wsmincap.h>
#include <ws_error.h>

#define HEADER_SIZE 5

sendqrep (p_reply_string, p_major_num)

char *p_reply_string;     /* Reply to be sent */
int p_major_num;          /* Destination of reply */
{
int code;                 /* return code */
int msg_len;              /* Length of reply string */
int system_id;            /* Temporary system id */
int major;                /* Temporary major */
struct packet_msg msg;    /* structure for message */

/* : copy reply string to mowse buffer */

   msg_len = stccpy (msg.msg_data, p_reply_string, WSPAKSIZ);

   c_unpack (&system_id, &major, p_major_num);
   msg.system = system_id;
   msg.major = major;
   msg.minor = QUERY_REPLY;
   msg.source_system = WSIBMPC;
   msg.source_major = WSMAJCAP;

/* : call user_interrupt to send data (don't send the null) */

   return (call_mowse_int (I$SENDBG, &msg , msg_len - 1 + HEADER_SIZE));
}




		    sendterm.asm                    08/07/87  1520.8rew 08/07/87  1438.0       30384



; ***********************************************************
; *                                                         *
; * Copyright, (C) Honeywell Bull Inc., 1987                *
; *                                                         *
; * Copyright, (C) Honeywell Information Systems Inc., 1986 *
; *                                                         *
; ***********************************************************

; HISTORY COMMENTS:
;  1) change(86-01-01,McGinn), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Created.
;  2) change(86-04-29,Westcott), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Support for circular buffers.
;                                                      END HISTORY COMMENTS

;/* : PROCEDURE FUNCTION (send_terminal_data)
;
;Send a BYTE string of specified length to the RS232 port while ignoring 
;protocol procedures.
;*/

;/* : NOTES
;
;Syntax:
;          mov  cx,length
;          mov  ES,DS
;          mov  ax,offset string
;          mov  si,ax
;          call send_terminal_data
;
;Arguments:
;          cx    - length of byte string
;          ES    - Data segment of byte string pointer
;          si    - Address of byte string into the Data segment
;
; Returns: ax = 0, if successful
;          ax = 1, if not successful (buffer full)
;*/

include dos.mac
include mowsdefs.mac
include ws_buf.mac
page
;******************************************************************************
;                                       DATA
;******************************************************************************
dseg

;--------- External Declarations
extrn   send_buffer:word
extrn   transmit_active:word

;--------- Public Declarations
public    send_terminal_data

endds

page
;******************************************************************************
;                                       MAIN
;******************************************************************************
pseg

;--------- External Procedures
extrn     RS232_OUT:near

send_terminal_data proc near

;/* : return if not enough room for message in send buffer

        len_buf send_buffer
        cmp     ax,cx                  ; ax = room left, cx = amount to send
        ja      next_out               ; if room
        mov     ax,1                   ; if no room in buffer
        ret                            ; if no room in send buffer

;/* : Stuff characters to send to RS232 port in a buffer */

next_out:
        mov     al, byte ptr es:[si]    ;get next character to send from
                                        ;byte string
        put_buf send_buffer             ;RS232_out(al)
        inc     si


        loopne  next_out                ;loop until character count = 0

;/* : If (transmit not active) call prime_RS232_out() */

        cmp     transmit_active,0
        jnz     noprime                 ;if transmit interrupt will pick up new data
        inc     transmit_active

;/* : Call RS232_out to send the character to the RS232 port */

        get_buf send_buffer
        jnc     noprime                 ; if send buffer empty
        call    RS232_out               ;RS232_out(al)

noprime:
        xor     ax,ax                   ;show send successful
        ret

send_terminal_data endp
        endps
        end




		    set_dta.asm                     08/07/87  1520.8rew 08/07/87  1438.0       44793



; ***********************************************************
; *                                                         *
; * Copyright, (C) Honeywell Bull Inc., 1987                *
; *                                                         *
; * Copyright, (C) Honeywell Information Systems Inc., 1986 *
; *                                                         *
; ***********************************************************

; HISTORY COMMENTS:
;  1) change(86-06-16,Westcott), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Created.
;                                                      END HISTORY COMMENTS

;/* : PROCEDURE FUNCTION (set_dta)
;
;This routine is used to provide a DTA address so that the called MOWSE 
;application does not use the foreground applications's DTA. It does this 
;by saving the old DTA address and then providing a new DTA address
;*/

;/* : NOTES
;
;Syntax:
;      call set_dta()
;*/

include dos.mac
dseg

;-------------- DATA

svdtaoff        dd      0       ; save address for old DTA offset address
trap22          dd      0       ; old int22 vector address
trap23          dd      0       ; old int23 vector address
trap24          dd      0       ; old int24 vector address
newdta          db      128 dup (0);  new dta
endds

;*******************************************************************
;                          MAIN
;*******************************************************************
pseg

;-------------- PUBLICS

public  set_dta
public  rst_dta
public  set_trap
public  rst_trap
public  wstrap23
public  wstrap24

set_dta proc    near
        push    bp
        push    es
        mov     ah,2Fh
        int     21h                    ; get old dta address into es:bx
        mov     word ptr svdtaoff+2,es ; save addresses
        mov     word ptr svdtaoff,bx
        mov     dx,offset newdta
        mov     ah,1Ah
        int     21h                    ; set new dta address
        pop     es
        pop     bp
        ret
set_dta endp

;/* : PROCEDURE FUNCTION (rst_dta)
;
;This routine is used to restore the DTA address previously saved by set_dta.
;*/

;/* : NOTES
;
;Syntax:
;     call rst_dta()
;*/

rst_dta proc    near
        push    bp
        push    ds
        lds     dx,svdtaoff            ; set ds:dx old dta address
        mov     ah,1aH
        int     21h
        pop     ds
        pop     bp
        ret
rst_dta endp

;/* : PROCEDURE FUNCTION (set_trap)
;
;This routine is used to set the trap vectors for DOS Interrupts 23,24,25 to 
;a MOWSE controlled routine.
;*/

;/* : NOTES
;
;Syntax:
;     call set_trap()
;*/

set_trap proc near
        push    bp
        push    es
        mov     al,23h
        mov     ah,35h
        int     21h                    ; get old trap vector
        mov     word ptr trap23+2,es
        mov     word ptr trap23,bx
        mov     dx, offset wstrap23
        mov     al,23h
        mov     ah,25h
        int     21h                    ; set new vector
        mov     al,24h
        mov     ah,35h
        int     21h                    ; get old trap vector
        mov     word ptr trap24+2,es
        mov     word ptr trap24,bx
        mov     dx, offset wstrap24
        mov     al,24h
        mov     ah,25h
        int     21h                    ; set new vector
        pop     es
        pop     bp
        ret
set_trap endp

;/* : PROCEDURE FUNCTION (rst_trap)
;
;This routine is used to restore the trap vectors for DOS Interrupts 23,24,25 
;to the previous values so that MOWSE knows when these interrupts occur.
;*/

;/* : NOTES
;
;Syntax:
;     call rst_trap()
;*/

rst_trap proc near
        push    bp
        push    ds
        lds     dx,trap23
        mov     al,23h
        mov     ah,25h
        int     21h                    ; restore interrupt 23 vector
        pop     ds
        push    ds
        lds     dx,trap24
        mov     al,24h
        mov     ah,25h
        int     21h                    ; restore interrupt 24 vector
        pop     ds
        pop     bp
        ret
rst_trap endp

;/* : PROCEDURE FUNCTION (wstrap23)
;
;This routine will get control whenever an Interrupt 23 occurs while MOWSE 
;is active.
;*/

;/* : NOTES
;Syntax:
;     wstrap23()
;*/

INTRAP23 dw 0

wstrap23  proc near
        sti
        cmp     cs:INTRAP23,0
        jne     notrap23
        inc     cs:INTRAP23
        or      al,al
        dec     cs:INTRAP23

notrap23:
        iret

wstrap23  endp

;/* : PROCEDURE FUNCTION (wstrap24)
;
;This routine will get control whenever an Interrupt 24 occurs while MOWSE 
;is active.
;*/

;/* : NOTES
;
;Syntax:
;     wstrap24()
;*/

INTRAP24 dw 0

wstrap24  proc near
        sti
        cmp     cs:INTRAP24,0
        jne     notrap24
        inc     cs:INTRAP24
        or      al,al
        dec     cs:INTRAP24

notrap24:
        xor     al,al                  ;tell DOS to ignore the trap
        iret

wstrap24  endp
endps
        end




		    setlock.asm                     08/07/87  1520.8rew 08/07/87  1438.0       21834



; ***********************************************************
; *                                                         *
; * Copyright, (C) Honeywell Bull Inc., 1987                *
; *                                                         *
; * Copyright, (C) Honeywell Information Systems Inc., 1986 *
; *                                                         *
; ***********************************************************

page 55,132
; HISTORY COMMENTS:
;  1) change(86-08-30,Flegel), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Created.
;                                                      END HISTORY COMMENTS

;/* : PROCEDURE FUNCTION (setlock)

;This procedure provides a means of setting locks in order to provide
;a means of setting locks on critical sections of instructions (code).
;The lock byte specified is exchanged with the value passed and the older
;value is returned in ax (typical return register both for 'C' routines and
;assembler.
;
;     char lockbyte;               lockbyte  db 0
;     setlock (&lockbyte);         mov    bx,offset lockbyte
;                                  push   bx
;                                  call   setlock
;
;Where lockbyte MUST be a static variable (not from the stack).
;
;Thus register ax is NOT preserved.
;*/

;/* : NOTES
;
;This implementation is simple as it allows only true/false settings on the
;lockbyte.
;*/

;/* : RETURNS

;ax = old value of lock byte.
;*/

include dos.mac                 ;Lattice include file

;**************************************************************
;                                       DATA
;**************************************************************
dseg

;--------- External Declarations

;--------- Public Declarations
public  setlock

;--------- Local Memory Declarations

endds

;**************************************************************
;                                       MAIN
;**************************************************************
pseg

;-------- External Procedures

setlock proc near
        push    bp
        mov     bp,sp

        push    bx
        mov     bx,[bp+4]       ; address of lock in bx

        xor     ax,ax
        mov     al,1            ; set test register
lock    xchg    [bx],al         ; exchange register with lock

        pop     bx
        pop     bp
        ret

setlock endp

        endps
        end




		    smdmstr.asm                     08/07/87  1520.8rew 08/07/87  1438.0       18972



; ***********************************************************
; *                                                         *
; * Copyright, (C) Honeywell Bull Inc., 1987                *
; *                                                         *
; * Copyright, (C) Honeywell Information Systems Inc., 1986 *
; *                                                         *
; ***********************************************************

; HISTORY COMMENTS:
;  1) change(86-04-29,Westcott), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Created.
;                                                      END HISTORY COMMENTS

;/* : PROCEDURE FUNCTION (smdmstr)
;
;Send a string of characters directly to the communications port.
;*/

;/* : NOTES
;
;Syntax:
;      call smdmstr (buffer, length)
;
;Arguments:
;      char *buffer;   pointer to string
;      int  length;    length of string
;*/

include dos.mac                 ;Lattice include file
include mowsdefs.mac

page
;**************************************************************
;                                       DATA
;**************************************************************
dseg

;--------- External Declarations

;--------- Local Memory Declarations

endds

page
;**************************************************************
;                                       MAIN
;**************************************************************
pseg

;-------- External Procedures
extrn   send_terminal_data:near

;--------- Public Declarations
public  smdmstr

smdmstr  proc near
        pop     ax                     ; bx = return address
        pop     si                     ; si = address of string
        pop     cx                     ; cx = length of string
        push    ax

send_loop:
        push    bp
        mov     bp,sp

;/* : call send_terminal_data() */

        call    send_terminal_data
        mov     sp,bp
        pop     bp
        or      ax,ax
        jnz     send_loop              ; if send buffer full try again
        ret
smdmstr endp

        endps
        end




		    stackfix.asm                    08/07/87  1520.8rew 08/07/87  1438.0       56448



; ***********************************************************
; *                                                         *
; * Copyright, (C) Honeywell Bull Inc., 1987                *
; *                                                         *
; * Copyright, (C) Honeywell Information Systems Inc., 1986 *
; *                                                         *
; ***********************************************************

; HISTORY COMMENTS:
;  1) change(86-01-09,Flegel), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Created.
;  2) change(86-05-14,Westcott), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Support local data.
;                                                      END HISTORY COMMENTS

;/* : PROCEDURE FUNCTION (setup_stack, reset_stack)
;
;setup_stack - Manipulate the stack such that the NARC uses its own stack 
;              segment (which is in the DS) and adjust the SP appropriately.
;              ALL relevant registers are preserved here.
;              Data addressability is established and ES will contain the old 
;              DS for addressing into the other data.
;reset_stack - Adjust the stack segment and stack pointer to be what they were 
;              BEFORE the LATEST interrupt occurred.
;              ALL preserved registers are restored here. 
;              Data addressability is restored.
;*/

;/* : NOTES
;
;Syntax:
;     extrn setup_stack:near,reset_stack:near
;     push cx
;     mov  cx, size_of_local_data
;     call setup_stack
;        ...
;     call reset_stack
;
;Arguments:
;     setup_stack: cx = size of local data area
;                  current stack contains return
;*/

PAGE 55,132

include dos.mac
include util.mac
include mowsdefs.mac
include ws_stack.mac


page
;**************************************************************
;                                       DATA
;**************************************************************
dseg

;-------- External Declarations
extrn   _BASE:word

;--------- Public Declarations
public  setup_stack
public  reset_stack
public  data_seg
public  stackseg
public  sp_base

endds

page
;**************************************************************
;                                       SETUP STACK
;**************************************************************
pseg

setup_stack proc near
        cli                            ;turn interrupts off for safety
        push    ax
        push    bx
        push    bp
        push    ds
        mov     ds,CS:data_seg         ;set up addressability to local data
        mov     ax,cs:sp_base
        mov     bx,ax
        sub     bx,cx
        sub     bx,ws_stack.wsparm - ws_stack.ipreg + 4
        inc     bx
        and     bl,0feh                ;ensure stack address is even
        push    bx
        sub     bx,FRAMESIZE           ;allow space for stack operations
        mov     cs:sp_base,bx          ;set stack frame
        cmp     bx,_BASE
        ja      no_change              ;lots of stack space left

;/* : Handle STACK OVERFLOW here */

        sti
        push    ax
        mov     al,20h
        out     20h,al
        pop     ax

;/* : save registers on new stack
;     save address of old stackframe in new stack frame   */

no_change:
        mov     [bx],ax

;/* : clean up old stack */

        pop     bx                     ;bx = base address of ws_stack
        pop     dsreg[bx]
        pop     bpreg[bx]
        pop     bxreg[bx]
        pop     axreg[bx]
        mov     cxreg[bx],cx
        pop     cx                     ; cx = return address from setup_stack
        mov     dxreg[bx],dx           ; save users registers
        mov     sireg[bx],si
        mov     direg[bx],di
        mov     spreg[bx],sp
        mov     esreg[bx],es
        mov     ssreg[bx],ss
        mov     bpsave[bx],bx

;/* : now set up new stack pointers */

        mov     ss,cs:stackseg
        mov     sp,bx

;/* :  set bp = address of local data area */

        mov     bp,bx
        push    ds
        pop     es                     ; for lattice c es=ds
        mov     ax,axreg[bp]
        mov     bx,bxreg[bp]

;/* : return */

        push    cx                     ;push return address
        mov     cx,cxreg[bp]
        sti                            ; turn interrupts back on
        ret

setup_stack endp

page
;**************************************************************
;                         RESET STACK
;**************************************************************

reset_stack proc near

        cli                            ; turn interrupts off for safety

;/* : save return address */

        pop     dx                     ;get the return address of the NARC
                                       ;   function which made the call

;/* : restore user's stack registers */

        mov     bx,bp                  ; bx = address of ws_stack

        mov     ax,ssreg[bx]           ; swap in users stack stuff
        mov     cx,spreg[bx]
        mov     ss,ax
        mov     sp,cx

;/* : restore registers */

        push    dx                     ;push return address
        push    bxreg[bx]
        push    dsreg[bx]
        mov     ax,axreg[bx]           ;swap in saved registers
        mov     cx,cxreg[bx]
        mov     dx,dxreg[bx]
        mov     si,sireg[bx]
        mov     di,direg[bx]
        mov     es,esreg[bx]
        mov     bp,bpreg[bx]

;/* : restore previous stack frame  */

        mov     bx,cs:sp_base
        mov     bx,[bx]                ; bx = address of previous stack frame
        mov     cs:sp_base,bx
        pop     ds
        pop     bx
        sti
        ret

reset_stack endp

page
;**************************************************************
;                       LOCAL DATA (must be in CS)
;**************************************************************
;  These are in the CS so that they are addressible by interrupt
;  handlers which do not know the DS yet

;---------- NARC segment and stack --------
data_seg        dw      ?               ;NARC DS
stackseg        dw      ?               ;NARC SS
sp_base         dw      ?               ;NARC sp

        endps
        end
;/* pc:: END */




		    stayres.c                       08/07/87  1519.7rew 08/07/87  1435.4       10377



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-06-06,Rohs), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
     install(87-08-07,MR12.1-1072):
     Created.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (stayres)

Load the calling application into resident memory.
*/

#include <dos.h>
#include <cat.h>

#define FUNCTION_NUMBER   0x31
#define STAYRES_FUNCTION  33

extern int _TSIZE;

stayres(mcbptr)

mcb *mcbptr;                           /* Caller's MCB */
{
struct SREGS segregs;
union  REGS  inreg;

/* : Generate DOS interrupt 0x31 */

   segread(&segregs);
   inreg.x.dx = _TSIZE;
   inreg.h.ah = FUNCTION_NUMBER;
   int86(STAYRES_FUNCTION,&inreg,0);
}




		    suspend.c                       08/07/87  1519.7rew 08/07/87  1435.4       18990



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */


/* HISTORY COMMENTS:
  1) change(86-09-27,ASmith), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (suspend)

Tells MOWSE to suspend the specified application.  The suspended application 
is notified by the dedicated minor capability SUSPEND_APPLICATION and will 
not be allowed to send or receive messages.
*/

/* : NOTES
       
A call to the mowse library routine 'resume' by some other application is
required to allow the application suspended to send and receive messages.
*/

#include <stdio.h>
#include <ws.h>
#include <wsmincap.h>
#include <ws_mcb.h>
#include <ws_dcls.h>
#include <ws_func.h>
#include <ws_error.h>

extern char local_system;

suspend (major_number, mcb_ptr)

int major_number;
mcb *mcb_ptr;
{
int code;                              /* return code */
int system;                            /* Temp system id */
int major;                             /* Temp major number */
struct xcap_struc suspend_message;     /* MOWSE parameters */

/* : Verify the validity of the caller */

   if (mcb_ptr == NULL)
      return (WSINVMCB);

   if (code = c_unpack (&system, &major, major_number))
      return (code);


/* : Send the message */

   suspend_message.system        = system;
   suspend_message.major         = major;
   suspend_message.minor         = SUSPEND_APPLICATION;
   suspend_message.source_system = mcb_ptr -> system_id;
   suspend_message.source_major  = mcb_ptr -> major_capability;
   return (call_mowse_int (I$SUSPEND, &suspend_message , sizeof (suspend_message)));
}





		    termbuff.asm                    08/07/87  1520.7rew 08/07/87  1438.0       56232



; ***********************************************************
; *                                                         *
; * Copyright, (C) Honeywell Bull Inc., 1987                *
; *                                                         *
; * Copyright, (C) Honeywell Information Systems Inc., 1986 *
; *                                                         *
; ***********************************************************

; HISTORY COMMENTS:
;  1) change(86-01-10,Flegel), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Created.
;  2) change(86-05-22,Westcott), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Support for gettdata structure.
;  3) change(86-09-05,Flegel), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Returns minor cap in AX.
;  4) change(86-12-15,Flegel), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Concatenation of consequetive FG_TERMINAL_DATA
;     messages.
;                                                      END HISTORY COMMENTS

page 55,132
;/* : PROCEDURE FUNCTION (terminal_buffer_check):
;
;Check the terminal buffer to see if anything is in it, if so, copy the 
;characters into the buffer supplied in ES:DI.
;*/

;/* : ARGUMENTS:
;
;        es:di - contains a pointer (byte) to where the
;                character string is be placed.
;        cx    - max. no. of characters wanted
;*/

;/* : RETURNS:
;
;        ax - minor capability number
;        cx - numbers of characters copied to buffer
;*/

include dos.mac
include mowsdefs.mac
include ws.mac
include ws_fgb.mac
include wsmincap.mac

page
;**************************************************************
;                                       DATA
;**************************************************************
dseg

;------------ External Declarations
extrn   fgbfptr:word
extrn   fgblptr:word
extrn   fgaptr:word

;------------ Public Declarations
public  terminal_buffer_check

endds

page
;**************************************************************
;                                       MAIN
;**************************************************************
pseg

;------------ External Declarations
extrn   wsfree:near

terminal_buffer_check proc near

        push    bx                         ;save registers to be used
        push    dx
        push    di
        xor     ax,ax                      ; ax = minor capability
        xor     dx,dx                      ; dx = copied data length

        cmp     cx,0                       ; cx = length of caller's buffer
        jbe     normal_return              ; if caller's buffer full, return

;/* : Look at each pending piece of foreground data
;     - Check terminal_buf status */

copy_buffer:
        mov     bx,fgbfptr                 ; bx = data buffer pointer
        cmp     bx,0
        je      normal_return              ; return if empty (no more)

        cmp     cx,fgb_length[bx]          ; cx = space left in caller's buffer
        jb      normal_return              ; if caller's buffer not big enough

;/* : Concatenate FG_TERMINAL_DATA pieces together */

        cmp     ax,0                       ; First piece extracted ?
        je      extract_portion            ; ... get portion

        cmp     ax,FG_TERMINAL_DATA        ; Not Concatenating ?
        jne     normal_return              ; ... return

        cmp     fgb_minor[bx],FG_TERMINAL_DATA  ; Concatenating next piece ?
        je      extract_portion                 ; ... get portion

        jmp     normal_return              ; Complete message so return

;/* : If (Something in terminal_buf) */

extract_portion:
        add     dx,fgb_length[bx]          ; increment copy count
        sub     cx,fgb_length[bx]          ; decrement space left length
        push    cx                         ; save space left length

        lea     si,fgb_char[bx]            ; load address of data
        mov     cx,fgb_length[bx]          ; cx = length of copy data

        mov     al,fgb_minor[bx]           ; minor capability in ax
        xor     ah,ah
        push    ax                         ; save on stack

        or      cx,cx                      ; Empty buffer ?
        jbe     nextbuf                    ; ... free empty buffer


;/* : copy to caller's buffer */

tbcloop:
        lodsb                              ; si -> source
        stosb                              ; di -> destination (always)
        loop    tbcloop                    ; si++, di++, cx-- ... automagic

nextbuf:
        pop     ax                         ; restore minor
        pop     cx                         ; restore space left

        mov     si,fgb_next[bx]            ; fgb_next = next foreground message
        mov     fgbfptr,si                 ; set fgbfptr (first) to next message

;/* : Free the message extracted */

        cmp     si,0                       ; If more buffers
        jne     free_msg
        mov     fgblptr,si                 ; set fgblptr (last) to NULL

free_msg:
        push    ax                         ; save minor
        push    cx                         ; save space left length
        push    dx                         ; save length
        push    di                         ; save destination buffer position

        push    bp
        mov     bp,sp
        push    bx                         ; bx = message to free
        push    fgaptr
        call    wsfree                     ; free the buffer just emptied
        mov     sp,bp
        pop     bp

        pop     di                         ; restore destination buffer position
        pop     dx                         ; restore length
        pop     cx                         ; restore space left length
        pop     ax                         ; restore minor

        jmp     copy_buffer                ; Get next portion

normal_return:
        mov     cx,dx                      ; cx = length of copied data
        pop     di
        pop     dx
        pop     bx
        ret

terminal_buffer_check endp                 ;End of termbuf_check procedure

        endps
        end





		    termcap.c                       08/07/87  1519.7rew 08/07/87  1435.4       13473



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-10-29,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (termcap)

Send a TERMINATE_APPLICATION minor cap to the specified capability.
*/

#include <stdio.h>
#include <ws.h>
#include <wsmincap.h>
#include <ws_mcb.h>
#include <ws_error.h>

#define BYTE_SHIFT 8

termcap (cap_num,mcb_ptr)

int cap_num;                           /* Capability to terminate */
mcb *mcb_ptr;                          /* MCB of caller */
{
int sysid;
int major;

/* : call execap to send message to application */

   sysid = ((cap_num & 0xff00) >> BYTE_SHIFT);
   major = (cap_num & 0xff);

   if (mcb_ptr == NULL)
      return (WSINVMCB);

   if ((sysid != WSMULTICS) && (sysid != WSIBMPC))
      return(WSINVSYS);

   if ((major < WSMAJCAP) && (major > MAX_CAPABILITY_NUMBER))
      return(WSINVNUM);

   return (execap (cap_num, TERMINATE_APPLICATION, NULL, 0, mcb_ptr));
}




		    termmows.asm                    08/07/87  1520.7rew 08/07/87  1437.9       47862



; ***********************************************************
; *                                                         *
; * Copyright, (C) Honeywell Bull Inc., 1987                *
; *                                                         *
; * Copyright, (C) Honeywell Information Systems Inc., 1986 *
; *                                                         *
; ***********************************************************

; HISTORY COMMENTS:
;  1) change(86-08-14,Westcott), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Created.
;  2) change(86-09-11,Flegel), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Resetting the MCR to not drop DTR.
;  3) change(86-09-11,Flegel), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Resetting the MCR to not drop RTS as well.
;  4) change(87-04-08,Flegel), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Erase the entire data area (security measures).
;                                                      END HISTORY COMMENTS

page 55,132
;/* : PROCEDURE FUNCTION (terminate_mowse):
;
;Remove MOWSE from the PC. This involves:
;     - disabling interrupts from rs232 hardware
;     - restoring interrupt vectors to pre-mowse values
;     - releasing memory used by mowse
;*/

include dos.mac          ;Lattice include file
include xoscall.mac      ;Bios and Dos Call macros
include mowsdefs.mac
include ws.mac
include ws_buf.mac

env_addr equ 2Ch         ; location of address of environment string on PSP

page
;*****************************************************************************
;                                       DATA
;*****************************************************************************
dseg

;------- External Declarations -----------------------------------------------

extrn   _PSP:word
extrn   MASK8259:byte
extrn   SOFTNO:word
extrn   COM_PORT:word
extrn   HARDINTRPT:word
extrn    _TOP:word
extrn    _STACK:word

;------- Public Declarations -------------------------------------------------

public  terminate_mowse

endds

page
;*****************************************************************************
;                               Program mainline
;*****************************************************************************
pseg

extrn INTHARD:near
extrn INTSOFT:near
extrn INT13:near
extrn INT1C:near
extrn INT28:near
extrn free_program:near

terminate_mowse proc near

        push    bp

;/* : disable hardware interrupt on 8259 interrupt controller */

        cli
        in      AL,IMR8259             ;Get current masks
        mov     cl,MASK8259
        not     cl
        or      al,cl                  ;Reset interrupt mask
        out     IMR8259,AL             ;And restore to Interrupt Mask
                                       ;Register

;/* : disable 8250 interrupts */

        mov     DX,LCR                  ;DX ==> LCR
        add     DX,COM_PORT
        in      AL,DX                   ;Reset DLAB for IER access
        and     AL,MASKLCR
        out     DX,AL
        mov     DX,IER                  ;Address IER
        add     DX,COM_PORT
        xor     ax,ax
        out     DX,AL                   ; disable all rs232 interrupts

;/* : disable DTR,RTS,OUT1,OUT2 on 8250 */

        mov     DX,MCR                  ;Address MCR
        add     DX,COM_PORT
        mov     al,MASKMCR              ;Disable OUT2, Leave DTR, RTS active low
        out     DX,AL
        sti

;/* : Restore interrupt vectors to pre-mowse values */

        push    ds
        mov     ax,HARDINTRPT
        push    cs                          ; Set up addressability into CS
        pop     ds
        mov     dx,word ptr INTHARD
        mov     ds,word ptr INTHARD+2
        mov     ah,25h
        int     21h
        pop     ds

        mov     ax,SOFTNO
        push    ds
        push    cs                          ; Set up addressability into CS
        pop     ds

;/* : restore sofware interrupt vector */

        mov     dx,word ptr INTSOFT
        mov     ds,word ptr INTSOFT+2
        mov     ah,25h
        int     21h

;/* : restore int 13 vector */

        mov     dx,word ptr INT13
        mov     ds,word ptr INT13+2
        mov     al,13h
        mov     ah,25h
        int     21h

;/* : restore int 1C vector */

        mov     dx,word ptr INT1C
        mov     ds,word ptr INT1C+2
        mov     al,1Ch
        mov     ah,25h
        int     21h

;/* : restore int 28 vector */

        mov     dx,word ptr INT28
        mov     ds,word ptr INT28+2
        mov     al,28h
        mov     ah,25h
        int     21h
        pop     ds

;/* : Erase all static data area */

        xor     al,al
        mov     cx,_TOP
        sub     cx,_STACK
        xor     si,si
        push    DS
        pop     ES

erase_data:
        mov     ES:[si],al
        inc     si
        loopne  erase_data

;/* : Free memory occupied by environment block */

        push    ES
        push    CS
        pop     ES                       ; ES = CS of program to free
        call    free_program             ; free program
        pop     ES

        pop     bp
        ret

terminate_mowse endp

endps
      end




		    user_int.asm                    08/07/87  1520.7rew 08/07/87  1437.8      141759



; ***********************************************************
; *                                                         *
; * Copyright, (C) Honeywell Bull Inc., 1987                *
; *                                                         *
; * Copyright, (C) Honeywell Information Systems Inc., 1986 *
; *                                                         *
; ***********************************************************

; HISTORY COMMENTS:
;  1) change(86-01-03,Flegel), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Created.
;  2) change(86-04-13,Flegel), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Extracted send_message module.
;  3) change(86-05-07,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
;     install(87-08-07,MR12.1-1072):
;     Added CREATE_INST, DESTROY_INST, FINDCAPNUM,
;     and FINDCAPNAME handlers.
;  4) change(86-05-21,Westcott), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Support parameter copying.
;  5) change(86-08-12,Flegel), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Installed FG_BREAK and DISCONNECT.
;  6) change(86-08-27,Flegel), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Modifications to DISCONNECT.
;  7) change(86-09-02,Flegel), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Installed checks for packet mode mincaps.
;     8) chnage(86-09-27,ASmith): Installed SUSPEND handler.
;  9) change(86-10-18,ASmith), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Installed connect by name handler.
; 10) change(87-02-10,Flegel), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Changed tests for MOWSE active to check
;     packetize_flag instead of packet_mode
;                                                      END HISTORY COMMENTS

page 55,132
        .xlist
; /* : PROCEDURE FUNCTION (user_interrupt_handler):
;
; This is the MOWSE user interrupt handler.  This deals with MOWSE requested 
; functions.
; */

; /* : NOTES:
;
; Syntax:
;         #include <dos.h>                mov ah,<MOWSE FUNCTION>
;         union REGS *inregs,outregs;     int USERINTRPT
;         inregs->h.al = <MOWSE FUNCTION>;
;         int86(USERINTRPT,in,out);
;
;  Input Arguments:
;         ah   - register determines MOWSE FUNCTION (input)
;         si   - address of parameter structure
;         cx   - length of parameter structure
;
; */
;
;/* : RETURNS:
;         ax - return code appropriate to command called
;
; If data is required to be passed back, it would be preferrable for the 
; generating interrupt to pass addresses as determined by the interrupt handler
; requested and to return only an error code in the AX register.
; */

; /* : NOTES
;
; Each case in this massive switch is primarily concerned with setting up
; the argument list to each of the handlers for that specific case.  This may
; include moving data into and out of parameter structures.
; */

include dos.mac
include ws.mac
include ws_stack.mac
include ws_dcls.mac
include ws_error.mac
include wsmincap.mac

page
;**************************************************************
;                                       MAIN
;**************************************************************
dseg

;          Public Declarations

public user_interrupt_handler

;          Data Declarations

endds

page
;**************************************************************
;                                       MAIN
;**************************************************************

PGROUP  GROUP   PROG
PROG    SEGMENT WORD PUBLIC 'PROG'
        ASSUME  CS:PGROUP

;--------- External Procedures -----------------------------------------------

extrn   packetize_flag:word
extrn   bgcount:word
extrn   IN_SOFT:word
extrn   setup_stack:near
extrn   reset_stack:near
extrn   send_terminal_data:near
extrn   terminal_buffer_check:near
extrn   snddat:near
extrn   i_execom:near
extrn   i_creins:near
extrn   i_desins:near
extrn   i_fndcnu:near
extrn   i_fndcna:near
extrn   i_execap:near
extrn   i_getbgm:near
extrn   i_putbgm:near
extrn   i_sendbg:near
extrn   i_reset:near
extrn   i_sleep:near
extrn   i_suspnd:near
extrn   i_connect:near
extrn   terminate_mowse:near
extrn   toggle_debug_switches:near
extrn   snddis:near
extrn   sndbrk:near
extrn   line_break:near

;------ publics --------------------------------------------------------------

public uisystem

user_interrupt_handler proc near

         jmp     arounds               ; provide a signiture for MOWSE

         even
uisystem db     0
         db     'MOWSE',0

; /* : call setup_stack () */

arounds:
        inc     CS:IN_SOFT
        call    setup_stack            ;Set up user interrupt stack frame
        push    bp

; /* : copy parameters from caller's address space into MOWSE address space */

        or      cx,cx
        jbe     nocopy                 ; if no parameter to copy
        push    ds
        pop     es
        mov     si,sireg[bp]
        lea     di,wsparm[bp]
        mov     ds,dsreg[bp]
        rep     movsb                  ; copy string into this address space
        push    es
        pop     ds

; /* : switch (user call type) */

nocopy:
        xor    cx,cx                   ; requested MOWSE function:
        mov    cl,ah                   ; switch (ah)
        sal    cx,1
        mov    di,cx
        cmp    di,MAXJMP               ; ensure request is valid
        jbe    do_jump                 ; if request not valid
        jmp    end_int

do_jump:
        mov    cx,CS:JMPTBL[di]
        jmp    cx

; /* : -- case SENDMESSAGE: not used */

SENDMESS:
        jmp    end_int

; /* : SENDTERM: Not used */

SENDTERM:
        jmp    end_int

; /* : -- case EXECUTCOM: */

EXECUTCOM:
        push    bp                     ; save bp
        lea     di,wsparm[bp]          ; di -> the parameter structure
        mov     bp,sp                  ; save SP so we can put it back after the C
        push    di                     ; put the parameter pointer on the stack (arg)
        call    i_execom               ; call the procedure
        mov     sp,bp                  ; restore the stack position
        pop     bp                     ; restore BP
        jmp     copy_back              ; copy resutls back into callers space

; /* : -- case 3: EXECAP */

EXECAP:
        push    bp
        lea     di,wsparm[bp]
        mov     cx,cxreg[bp]
        mov     bp,sp
        push    cx
        push    di
        call    i_execap
        mov     sp,bp
        pop     bp
        jmp     copy_back

; /* : -- case 4: CREATE_INSTANCE */

CREATE_INST:
        push    bp
        lea     di,wsparm[bp]
        mov     ax,bp
        mov     bp,sp
        push    di                     ; push address of copy of caller's mcb
        push    ax                     ; push address of stack
        call    i_creins
        mov     sp,bp
        pop     bp
        jmp     copy_back

; /* : -- case 5: DESTROY_INSTANCE */

DESTROY_INST:
        push    bp
        lea     di,wsparm[bp]
        mov     bp,sp
        push    di
        call    i_desins
        mov     sp,bp
        pop     bp
        jmp     copy_back

; /* : -- case 6: FINDCAPNAME */

FINDCAPNAME:
        push    bp
        lea     di,wsparm[bp]
        mov     bp,sp
        push    di
        call    i_fndcna
        mov     sp,bp
        pop     bp
        jmp     copy_back

; /* : -- case 7: FINDCAPNUM */

FINDCAPNUM:
        push    bp
        lea     di,wsparm[bp]
        mov     bp,sp
        push    di
        call    i_fndcnu
        mov     sp,bp
        pop     bp
        jmp     copy_back

; /* : -- case 8: Debug packet switches - undocumented */

L08:
        mov     ax,wsparm[bp]
        push    bp
        push    ax
        call    toggle_debug_switches
        pop     bp
        jmp     copy_back

; /* : -- case GETTDATA: Get data from terminal buffer */

GETTDATA:
        lea     bx,wsparm[bp]
        mov     cx,bgcount             ; see if background messages are pending
        mov     gbpflag[bx],cx

        mov     di,getlbp[bx]          ;di = address of caller's buffer
        mov     cx,getlbs[bx]          ;cx = size of caller's buffer
        push    es
        mov     es,dsreg[bp]
        push    bp                     ;check for foreground data
        call    terminal_buffer_check
        pop     bp
        pop     es

        cmp     cx,0                   ;if no data then check the mode flag
        jne     data_ready

        test    packetize_flag,1       ;if clear, then set minor cap to mowse_detached
        jne     set_attached           ;else set minor to mowse_attached
        mov     ax,MOWSE_DETACHED
        jmp     data_ready

set_attached:
        mov     ax,MOWSE_ATTACHED

data_ready:
        mov     gmincap[bx],ax
        mov     ax,cx                  ;return number of chars obtained to caller
        mov     cx,gettlen
        jmp     copy_back

; /* : -- case PUTTDATA   : Send data over foreground channel */

PUTDATA:
        lea     bx,wsparm[bp]
        test    packetize_flag,1
        jz      nopkt

; /* : --- if in packet mode create send packet structure for snddat */

        mov     ax,minor_cap[bx]
        lea     si,pkthdr[bp]
        mov     [si],al                ; insert minor cap in packet header
        mov     datap[bp],si           ; insert pointer to packet header
        mov     datal[bp],1            ; insert length of packet header
        lea     si,puttstr[bx]
        mov     datap+2[bp],si         ; insert pointer to data string
        mov     ax,putstrl[bx]
        mov     datal+2[bp],ax         ; insert length of data string
        mov     datac[bp],2            ; insert count of packet pieces
        mov     chan[bp],FG            ; insert channel id (foreground)
        lea     bx,chan[bp]

; /* : --- give the packet to the protocol to send */

        jmp     send_pkt               ; give data to protocol

; /* : -- else, just transmit the data */

nopkt:
        push    bp
        mov     cx,putstrl[bx]
        lea     si,puttstr[bx]
        mov     bp,sp
        call    send_terminal_data
        mov     sp,bp
        pop     bp
        jmp     end_int

; /* : -- case GETBGMES: */

GETBGMES:
        push    bp
        lea     di,wsparm[bp]
        mov     bp,sp
        push    di                     ; push address of parameter structure
        call    i_getbgm               ; get background message
        mov     sp,bp
        pop     bp
        jmp     copy_back

; /* : -- case PUTBGMES: */

PUTBGMES:
        push    bp
        lea     di,wsparm[bp]
        mov     bp,sp
        push    di                     ; push address of parameter structure
        call    i_putbgm               ; put background message
        mov     sp,bp
        pop     bp
        jmp     copy_back

; /* : -- case SENDBG: */

SENDBG:
        push    bp
        lea     di,wsparm[bp]
        mov     cx,cxreg[bp]
        mov     bp,sp
        push    cx                     ; push length of message
        push    di                     ; push address of message
        call    i_sendbg
        mov     sp,bp
        pop     bp
        jmp     copy_back

; /* : -- case L14: Nothing */

L14:
        mov     bx,wsparm[bp]
        mov     ax,[bx]
        jmp     end_int

; /* : -- case RESET: */

RESET:
        push    bp
        lea     di,wsparm[bp]
        mov     cx,cxreg[bp]
        mov     bp,sp
        push    cx                     ; push length of message
        push    di
        call    i_reset
        mov     sp,bp
        pop     bp
        jmp     copy_back

; /* : -- case SLEEP */

SLEEP:
        push    bp
        lea     di,wsparm[bp]
        mov     bp,sp
        push    di
        call    i_sleep
        mov     sp,bp
        pop     bp
        jmp     copy_back

SUSPEND:
        push    bp
        lea     di,wsparm[bp]
        mov     bp,sp
        push    di
        call    i_suspnd
        mov     sp,bp
        pop     bp
        jmp     copy_back

CONNECT:
        push    bp
        lea     di,wsparm[bp]
        mov     bp,sp
        push    di
        call    i_connect
        mov     sp,bp
        pop     bp
        jmp     copy_back

; /* : -- case DISCONNECT */

DISCONNECT:
        test    wsparm[bp],1           ; but if force is requested, continue
        jne     discon_ok

        test    packetize_flag,1       ; if in packet mode then fail
        je      discon_ok

        push    bp
        mov     bp,sp
        call    snddis                 ; establish disconnection attempt
        mov     sp,bp
        pop     bp
        jmp     copy_back

discon_ok:
        push    bp
        mov     bp,sp
        call    terminate_mowse        ; remove mowse from the PC
        mov     sp,bp
        pop     bp
        jmp     copy_back

; /* : -- case FOREBREAK: */

FOREBREAK:
        xor     ax,ax
        test    packetize_flag,1       ; Packet mode ?
        jne     soft_brk               ;  YES - Protocol break
        call    line_break             ;   NO - Line break
        jmp     copy_back

soft_brk:
        push    bp
        mov     bp,sp
        call    sndbrk                 ; call to send break to Multics
        mov     sp,bp
        pop     bp
        jmp     copy_back

; /* : send_pkt : give a packet structure to the mowse protocol for packetizing
;      and subsequent trasmission */

send_pkt:
        push    bp
        lea     si,datap[bp]
        lea     di,datal[bp]
        mov     ax,chan[bp]
        mov     cx,datac[bp]
        mov     bp,sp
        push    di
        push    si
        push    cx
        push    ax
        call    snddat                 ; send the packet to the protocol
        mov     sp,bp
        pop     bp
        cmp     ax,1
        je      send_pkt               ; if window full, try again
        mov     axreg[bp],ax           ; save return code
        jmp     end_int


; /* : COPY_BACK: copy parameter structure back to user's address space before
;      returning from interrupt. */

copy_back:
        mov     axreg[bp],ax           ; save return code
        mov     cx,cxreg[bp]
        or      cx,cx
        jbe     end_int                ; if no parameter to copy
        mov     di,sireg[bp]
        lea     si,wsparm[bp]
        mov     es,dsreg[bp]
        rep     movsb                  ; copy string into this address space

; /* : End of interrupt: call reset_stack(), return from interrupt */

end_int:
        pop     bp                     ; Put the stack to where it was
        call    reset_stack            ;   before the interrupt
        dec     CS:IN_SOFT
        iret

;          Switching Table

JMPTBL  dw      pgroup:SENDMESS
        dw      pgroup:SENDTERM
        dw      pgroup:EXECUTCOM
        dw      pgroup:EXECAP
        dw      pgroup:CREATE_INST
        dw      pgroup:DESTROY_INST
        dw      pgroup:FINDCAPNAME
        dw      pgroup:FINDCAPNUM
        dw      pgroup:L08
        dw      pgroup:GETTDATA
        dw      pgroup:PUTDATA
        dw      pgroup:GETBGMES
        dw      pgroup:PUTBGMES
        dw      pgroup:SENDBG
        dw      pgroup:L14
        dw      pgroup:RESET
        dw      pgroup:SLEEP
        dw      pgroup:DISCONNECT
        dw      pgroup:FOREBREAK
        dw      pgroup:SUSPEND
        dw      pgroup:CONNECT
JMP_END dw      0
MAXJMP  = JMP_END - JMPTBL

; /* : END user_interrupt_handler */
user_interrupt_handler endp

        endps
        end





		    wakeup.c                        08/07/87  1519.7rew 08/07/87  1435.4       32850



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-09-02,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created from extract of rcvdata.c
  2) change(86-11-11,Flegel), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Call to external_mowse before wsexecap.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (wakeup):

Detect whether or not an application is to be awoken because its sleep time has
expired.  If so, a message is generated to the sleeping application.
*/

/* : NOTES:

This procedure must ONLY be called if it is safe to execute a capability.
*/

#include <stdio.h>
#include <dos.h>
#include <ws.h>
#include <alloc.h>
#include <ws_mcb.h>
#include <cat.h>
#include <ws_fgb.h>
#include <ws_msg.h>
#include <wsmincap.h>

extern local_cat *sleepq;
extern local_cat l_CAT[];
extern char mysystem;
extern struct allocstr *lcaptr;

wakeup ()
{
struct null_msg  exerep;      /* Remote message indicating sleep awakeninig */
struct input_msg *msg_ptr;    /* pointer to input message header structure  */
struct fgbstr    *bufp;       /* allocation buffer */
local_cat        *catp;       /* pointer to CAT entry */
char             *p1;         /* Temporary pointers */
int              i;
char             major;       /* Major cap of awakening application */

/* EXTERNAL CALLS */
unsigned int wstime();
char  *wsalloc();


/* MAIN */

/* : While there are still things to check in the sleep queue */

   catp = sleepq;
   while (catp != NULL)

/* : - if timer not expired then return */

   {  if (catp -> sleep_time > wstime())
         return (0);

/* : -- calculate the major number from the relative offset of the
        current one to the start of the table */

      major = (char)((((int)catp - (int)l_CAT) / sizeof (local_cat)) + MIN_CAPABILITY_NUMBER);

/* : - Allocate message space, if cant then return */

      bufp = (struct fgbstr *) wsalloc (lcaptr,sizeof(struct fgbstr)+sizeof(struct input_msg)-1);
      if (bufp == NULL)
         return (0);

/* : - notify remote system that wakeup has occurred */

      exerep.system = WSMULTICS;
      exerep.major = WSMAJCAP;
      exerep.source_major = major;
      exerep.source_system = mysystem;
      exerep.minor = WS_RESET_SLEEP_FLAG;
      send_i_mess(&exerep, sizeof(struct null_msg) - 1, NULL, 0);

/* : - create message to wakeup application */

      bufp -> fgb_length = sizeof (struct input_msg);
      bufp -> fgb_next = NULL;

      msg_ptr = (struct input_msg *) &bufp -> fgb_char[0];
      msg_ptr -> system = mysystem;
      msg_ptr -> major = major;
      msg_ptr -> minor = WAKE_UP;
      msg_ptr -> source_system = mysystem;
      msg_ptr -> source_major = WSMAJCAP;

/* : - Adjust the queue for sleeping capabilities */

      catp -> flags &= ~SLEEPING_BIT;
      catp -> sleep_time = 0;
      sleepq = catp -> next_cat;
      catp -> next_cat = NULL;

/* : - Send the message to the application */

      external_mowse (catp, msg_ptr, sizeof(struct input_msg)-1);
      wsfree (lcaptr, bufp);

/* : - get next CAT entry from sleepq */

      catp = sleepq;
   }
   return (0);
}




		    wsalloc.c                       08/07/87  1519.7rew 08/07/87  1435.4       25128



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-06-06,Westcott), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION

The following routines are general purpose "memory management" routines used
to manage internal memory buffers.  They are direct copies from 
Kernigan & Ritchie.
*/

#include <stdio.h>
#include <alloc.h>

char *wsalloc (mptr,nbytes)

struct allocstr *mptr;
unsigned nbytes;
{
HEADER *morecore();
register HEADER *p, *q;
register int nunits;

   nunits = 1+(nbytes+sizeof(HEADER) -1)/sizeof (HEADER);
   if ((q = mptr->m_allocp) == NULL) {  /* no free list yet */
      mptr->m_base.s.ptr = mptr->m_allocp =q = &mptr->m_base;
      mptr->m_base.s.size = 0;
   }

   for (p=q->s.ptr; ;q=p, p=p->s.ptr) {
      if (p->s.size >= nunits) {  /* big enough */
         if (p->s.size == nunits)    /* exactly */
            q->s.ptr = p->s.ptr;
         else {  /* allocate tail end */
            p->s.size -= nunits;
            p += p->s.size;
            p->s.size = nunits;
         }
         mptr->m_allocp = q;
         return ((char *) (p+1));
      }
      if ( p == mptr->m_allocp)  /* wrapped around free list */
         if ((p = morecore (mptr,nunits)) == NULL)
            return (NULL);  /* none left */
   }
}

wsfree (mptr,ap)

struct allocstr *mptr;
char *ap;
{
register HEADER *p, *q;

   p = (HEADER *) ap -1;  /* point to header */
   for (q=mptr->m_allocp; !(p > q && p < q->s.ptr); q=q->s.ptr)
      if (q >= q->s.ptr && (p > q || p < q->s.ptr))
         break;   /* at one end or other */

   if (p+p->s.size == q->s.ptr) {  /* join to upper neighbor */
      p->s.size += q->s.ptr->s.size;
      p->s.ptr = q->s.ptr->s.ptr;
   }
   else
      p->s.ptr = q->s.ptr;
   if (q+q->s.size == p) {  /* join to lower neighbor */
      q->s.size += p->s.size;
      q->s.ptr = p->s.ptr;
   }
   else
      q->s.ptr = p;
   mptr->m_allocp = q;
}

HEADER *morecore (mptr,nu)

struct allocstr *mptr;
unsigned nu;
{
register HEADER *up;
char *cp;

   if (mptr->memory_used == 1) 
      return(NULL);
   cp = mptr->memory;
   mptr->memory_used = 1;
   up = (HEADER *)cp;
   up->s.size = mptr->memory_size / sizeof (HEADER);
   wsfree (mptr,(char *) (up+1));
   return (mptr->m_allocp);
}




		    wsexe.c                         08/07/87  1519.6rew 08/07/87  1435.4       22797



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-02-24,ASmith), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
  2) change(86-06-05,Westcott), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Support for execom structure.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (EXECUTE_COMMAND)

This Internal MOWSE software interrupt handler executes a command (included 
in a message) sent from some remote system.  Errors encountered in processing 
the command are sent back to a specified capability.
*/

/* : NOTES
*/

#include <stdio.h>
#include <ws.h>
#include <wsmincap.h>
#include <ws_error.h>
#include <ws_msg.h>

#define STATUS_SUCCESS 32
#define STATUS_FAILED 33

extern char mysystem;

EXECUTE_COMMAND(com_len,execmp)

int     com_len;                /* Length of message */
struct execom_msg *execmp;      /* Execute command message */
{
int error;
char *cmd;                      /* pointer to command string */
struct exerep_msg exerep;       /* reply message */
struct execom_msg *execmd;      /* pointer to execute command message */


/* : Try to execute command locally. */

   cmd = &execmp->command[0];
   com_len = com_len - sizeof(struct execom_msg) + 1;
   cmd[com_len] = '\0';         /* ensure command ends with zero byte */
   set_dta();                   /* use Mowse's DTA */
   set_trap();                  /* use MOWSE's trap rotuines */
   error = system(cmd);
   rst_trap();
   rst_dta();

/* : If execution failed then formulate message_1 to send to err_handler. */

   if (error)
      exerep.status = (char) STATUS_FAILED;
   else
      exerep.status = STATUS_SUCCESS;

/* : Send the reply to the source of the request */

   exerep.system = execmp->source_system;
   exerep.major = execmp->source_major;
   exerep.minor = EXECUTE_COMMAND_REPLY;
   exerep.source_major = WSMAJCAP;
   exerep.source_system = mysystem;
   exerep.cmd_id = execmp->cmd_id;

   send_i_mess(&exerep.system,sizeof(exerep),NULL,0);
}
/* : END */




		    wsexecap.asm                    08/07/87  1520.7rew 08/07/87  1437.8       35937



; ***********************************************************
; *                                                         *
; * Copyright, (C) Honeywell Bull Inc., 1987                *
; *                                                         *
; * Copyright, (C) Honeywell Information Systems Inc., 1986 *
; *                                                         *
; ***********************************************************

; HISTORY COMMENTS:
;  1) change(86-06-16,Westcott), approve(87-07-13,MCR7580),
;     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
;     Created
;                                                      END HISTORY COMMENTS

;/* : PROCEDURE FUNCTION (wsexecap)
;
;Pass a message received from a remote MOWSE, to an application by calling 
;it's entry point stored in the local CAT. The calling sequence for the 
;application is:
;
;        p_event(mcb_ptr,minor_cap,bufseg,bufoff,buflen)
;
;        where  mcb_ptr = pointer to application's mcb
;               minor_cap = minor capability number in the message
;               bufseg = segment address of the message
;               bufoff = offset address of the message
;               buflen = length of the message
;*/

;/* : NOTES
;
;Syntax: wsexecap(catptr,capmsgp,capmsgl)
;        struct local_cat *catptr;
;        struct execap_msg *capmsgp;
;        int capmsgl;
;
;Arguments:
;        *catptr  - pointer to cat entry for application
;        *capmsgp - pointer to the structure that contains the message
;        capmsgl  - length of the message
;*/

include dos.mac
include ws.mac
include ws_msg.mac
include cat.mac

;------------- DATA

dseg

capstr  struc
oldbp   dw      ?
retn    dw      ?
catptr  dw      ?
catmsgp dw      ?
catmsgl dw      ?
capstr  ends
endds

;*******************************************************************
;                           MAIN
;*******************************************************************
pseg

       public wsexecap
wsexecap proc near

        push    bp
        mov     bp,sp
        mov     bx,[bp].catptr

;/* : load relevant information into registers since we must switch
;     to user's address space in order to set up a call to p_event */

        mov     si,[bp].catmsgp
        mov     cx,[bp].catmsgl
        mov     al,[si].ep_minor
        xor     ah,ah
        mov     di,[bx].mcb_ptr

;/* : Switch to the user's stack. */

        mov     dx,ss
        mov     bp,sp
        cli
        mov     ss,ssreg[bx]
        mov     sp,spreg[bx]
        sti

;/* : The call to the user's application is accomplished by pushing a small
;     program into the user's stack that, when called, will do a far call
;     to the application. */

        push    dx
        push    bp
        push    es
        push    ds
        sub     sp,0ch
        mov     bp,sp
        lea     dx,[bp+4]
        mov     [bp],dx
        mov     [bp+2],ss
        mov     byte ptr [bp+05h],09ah
        mov     byte ptr [bp+0ah],0cbh
        mov     byte ptr [bp+04h],090h
        mov     dx,csreg[bx]
        mov     [bp+08h],dx
        mov     dx,ws_entry[bx]
        mov     [bp+06h],dx

;/* : Set user's DS and ES registers. */

        mov     dx,ds
        push    esreg[bx]
        push    dsreg[bx]
        pop     ds
        pop     es
        mov     bp,sp
        push    cx              ; push message length
        push    si              ; push message offset
        push    dx              ; push message segment
        push    ax              ; push minor capability number
        push    di              ; push mcb pointer

;/* : Call the user application */

        call    dword ptr [bp]     ; call user application
        mov     sp,bp
        add     sp,0ch
        pop     ds
        pop     es
        pop     bx
        pop     dx

;/* : restore mowse's segment registers and stack */

        cli
        mov     ss,dx
        mov     sp,bx
        sti
        pop     bp
        ret

wsexecap endp
endps
        end




		    wssleep.c                       08/07/87  1519.6rew 08/07/87  1435.4       17388



/* ***********************************************************
   *                                                         *
   * Copyright, (C) Honeywell Bull Inc., 1987                *
   *                                                         *
   * Copyright, (C) Honeywell Information Systems Inc., 1986 *
   *                                                         *
   *********************************************************** */

/* HISTORY COMMENTS:
  1) change(86-06-13,Westcott), approve(87-07-13,MCR7580),
     audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
     Created.
                                                   END HISTORY COMMENTS */

/* : PROCEDURE FUNCTION (wssleep):

Requests MOWSE to suspend the application for a fixed period of time. While 
the application is sleeping, all messages received from other applications 
(except MOWSE) will be ignored. Mowse will send a message to the remote 
system(s) to inform them that the application is sleeping.  The sleeping 
application will be awakened by the minor capability WAKE_UP when the time has 
expired.
*/

/* : RETURNS:

     0, if message sent
     WSINVNUM, if capability number is invalid
     WSNOSPND, if capability is not currently suspended
*/

#include <stdio.h>
#include <ws.h>
#include <wsmincap.h>
#include <ws_mcb.h>
#include <ws_dcls.h>
#include <ws_func.h>
#include <ws_error.h>

extern char local_system;

wssleep (time, mcb_ptr)
int time;
mcb *mcb_ptr;
{
struct sleep_struc sleep_data; /* structure to hold sleep request */

/* : Check that the sleep time is valid */
   if (time <= 0)
      return (WSINVTIM);

/* :  Send sleep request to MOWSE */
   sleep_data.time = time;
   sleep_data.source_system = mcb_ptr -> system_id;
   sleep_data.source_major  = mcb_ptr -> major_capability;
   sleep_data.minor = WS_SET_SLEEP_FLAG;

   return (call_mowse_int (I$SLEEP, &sleep_data , sizeof (sleep_data)));

/* : END */
}




		    bull_copyright_notice.txt       08/30/05  1008.4r   08/30/05  1007.3    00020025

                                          -----------------------------------------------------------


Historical Background

This edition of the Multics software materials and documentation is provided and donated
to Massachusetts Institute of Technology by Group Bull including Bull HN Information Systems Inc. 
as a contribution to computer science knowledge.  
This donation is made also to give evidence of the common contributions of Massachusetts Institute of Technology,
Bell Laboratories, General Electric, Honeywell Information Systems Inc., Honeywell Bull Inc., Groupe Bull
and Bull HN Information Systems Inc. to the development of this operating system. 
Multics development was initiated by Massachusetts Institute of Technology Project MAC (1963-1970),
renamed the MIT Laboratory for Computer Science and Artificial Intelligence in the mid 1970s, under the leadership
of Professor Fernando Jose Corbato.Users consider that Multics provided the best software architecture for 
managing computer hardware properly and for executing programs. Many subsequent operating systems
incorporated Multics principles.
Multics was distributed in 1975 to 2000 by Group Bull in Europe , and in the U.S. by Bull HN Information Systems Inc., 
as successor in interest by change in name only to Honeywell Bull Inc. and Honeywell Information Systems Inc. .

                                          -----------------------------------------------------------

Permission to use, copy, modify, and distribute these programs and their documentation for any purpose and without
fee is hereby granted,provided that the below copyright notice and historical background appear in all copies
and that both the copyright notice and historical background and this permission notice appear in supporting
documentation, and that the names of MIT, HIS, Bull or Bull HN not be used in advertising or publicity pertaining
to distribution of the programs without specific prior written permission.
    Copyright 1972 by Massachusetts Institute of Technology and Honeywell Information Systems Inc.
    Copyright 2006 by Bull HN Information Systems Inc.
    Copyright 2006 by Bull SAS
    All Rights Reserved
