1 /* ***********************************************************
  2    *                                                         *
  3    * Copyright, (C) Honeywell Bull Inc., 1987                *
  4    *                                                         *
  5    * Copyright, (C) Honeywell Information Systems Inc., 1986 *
  6    *                                                         *
  7    *********************************************************** */
  8 
  9 /* HISTORY COMMENTS:
 10   1) change(86-06-23,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
 11      install(87-08-07,MR12.1-1072):
 12      Created.
 13   2) change(86-07-25,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
 14      install(87-08-07,MR12.1-1072):
 15      Modifed command line args, saves to script file
 16   3) change(86-08-24,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
 17      install(87-08-07,MR12.1-1072):
 18      Added menus
 19   4) change(86-09-07,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
 20      install(87-08-07,MR12.1-1072):
 21      Added tab handling, local editing
 22   5) change(86-09-11,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
 23      install(87-08-07,MR12.1-1072):
 24      DOS commands, query status
 25   6) change(86-09-26,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
 26      install(87-08-07,MR12.1-1072):
 27      Split emulator into two versions, a debugging
 28      and a non-debugging version; change the define EM_DEBUG in emulator.h
 29      to 0 for non-debugging version, change to 1 for debugging version
 30                                                    END HISTORY COMMENTS */
 31 
 32 /* : PROCEDURE FUNCTION (emulator)
 33 
 34 Allows a user to interact through MOWSE foreground and background channels
 35 through a simple terminal interface.  This terminal emulator treats foreground
 36 data as would a normal emulator.  However, to distinguish background data from
 37 foreground data, all background data is preceeded by a carat (^).  Thus any
 38 background data going onto the screen will be preceeded by a carat.  Similarly,
 39 if keyboard input is preceed by a carat, then it will be sent to the background
 40 channel. No priority will be given to either channel, information that is
 41 displayed first will be displayed.  If there are several background queries,
 42 then background data from the keyboard will go to each background query in
 43 sequence.
 44 
 45 Unless otherwise specified, all function keys may be invoked in either
 46 packet or non-packet mode (i.e. after or before attaching to MOWSE).
 47 
 48 F1 - debugging mode only;
 49      Suspend processing of terminal data; when this key is pressed
 50      while foreground or background data is being received and displayed,
 51      the emulator will sit in a tight loop, resulting in temporary
 52      stoppage in the handling of terminal data.  Hitting any other key
 53      will resume processing.
 54 
 55 F2 - Debugging mode only. Toggle display mode; there are 3 modes:
 56         Printable ASCII only - only printable ascii characters except
 57             for the linefeed, carriage return and tab characters will
 58             be discarded.
 59         Non-printable octal - any non-printable ascii character except
 60             for linefeed, carriage return and tab characters will be
 61             displayed as a 3 digit octal value preceeded by a backslash.
 62             Any backslash character as terminal data will appear as
 63             a double backslash.
 64         Any character - displays all characters with character image in the
 65             character set of the machine
 66 
 67 F3 - debugging mode only. Help menu.
 68      Summary of what function keys do, how to handle background data
 69 
 70 F4 - debugging mode only. Toggle local editting flag;
 71      the flag is only used when in packet-mode.
 72      When local editting is enabled, pressing ESC or @ will kill and erase
 73      the current line of input; pressing BACKSPACE or # will erase the
 74      previous character and the \ key will serve to escape the @, #, ESC
 75      and \ keys.  With local editting disabled, key values are entered
 76      as straight data.
 77 
 78 F5 - Toggle between foreground terminal data only or any foreground data;
 79      debugging mode only;
 80      By default, foreground terminal data only is enabled.
 81 
 82 F6 - debugging mode, CTRL-]R - non-debugging mode;
 83      Show query status; when background queries are received by the
 84      emulator, they are displayed immediately but the senders' capability
 85      are saved in a queue until the user responds to these queries
 86      (by preceeding the input with the ^ character).  Thus, any data
 87      entered as a response to background queries will be sent to
 88      the earliest background query in the queue.  Once, a background
 89      message has been responded to, the capability is removed from the
 90      queue.  The F6 key will display the system id and the major
 91      capability of the sender of all unanswered background queries.
 92 
 93 F7 - debugging mode only;
 94      Set tab size; used to change or examine the tab size.  This tab
 95      value determines both the amount of padding to use for displaying
 96      and for the tab key (i.e. it is used in both packet and non-packet
 97      mode).
 98 
 99 F8 - debugging mode, CTRL-]C - non-debugging mode;
100      Execute DOS command; pass a command to the command interpreter on
101      the PC and resume normal terminal emulation upon completion.
102      Note that the F1 key will not work since the command interpreter
103      has control; however, ^S and ^Q will serve to suspend and resume
104      while control is not passed back to the emulator.
105 
106 F9 - debugging mode; CTRL-]B - non-debugging mode;
107      Send foreground break; a foreground break is sent through the
108      foreground channel.  This works only when MOWSE is attached on
109      the other side.
110 
111 F10 - debugging mode; CTRL-]Q - non-debugging mode;
112      Exit the terminal emulator.
113 
114 CTRL-]R - non-debugging mode only
115      Send a query reply
116 
117 CTRL-]0 - non-debugging mode only
118      Send a null over the foreground channel
119 
120 CTRL-]CTRL-] - non-debugging mode only
121      Send a CTRL-] over the foreground channel
122 
123 Local editing is always on for non-debugging version; the # functions
124 the same as backspace and the @ functions the same as the ESC key
125 which wipes out the line.  These may be escaped by the \ key.
126 
127 */
128 
129 #include <ws.h>
130 #include <ws_dcls.h>
131 #include <wsmincap.h>
132 #include <keydefs.h>
133 #include <emulator.h>
134 
135 #if EM_DEBUG                           /* Do NOT compile if !EM_DEBUG */
136 
137 char NULLBYTE;
138 char *print_mode_type[] = {            /* Message strings */
139    "PRINTABLE ASCII ONLY",
140    "OCTAL NON-PRINTABLE ASCII",
141    "ANY ASCII"
142 };
143 
144 char *on_off_status[] = {              /* Status message strings */
145    "OFF",
146    "ON"
147 };
148 
149 struct get_struc gettdatas;
150 char buff[KB_BUFFERSIZE];
151 char kb_stack[KB_STACKSIZE];
152 int  bg_sender_buff[BG_SENDBUFF_SIZE];
153 int bg_sender_in = 0;
154 int bg_sender_out = 0;
155 extern int packetize_flag;
156 int em_print_mode;
157 int em_tab_size;
158 int local_edit;
159 int fg_data_only;
160 
161 em()
162 {
163 
164 /* MISC */
165    int str_len;
166    int i;
167    int sender_major;
168    int message_type;
169    int bg_query_flag;
170    int j;
171    int err_code;
172    int option;
173    int do_te_loop = TRUE;
174    int delay_i;
175    int ch;
176    int sys;
177    int major;
178 
179 /* INITIALIZATION */
180    str_len = 0;
181    bg_query_flag = 0;
182 
183 /* : set default modes */
184 
185    local_edit = TRUE;
186    em_print_mode = ANY_CHAR;
187    fg_data_only = TRUE;
188    em_tab_size = KB_TABSIZE;
189 
190 /* : initialize the structure for getting terminal data */
191 
192    gettdatas.local_buffer_pointer = &buff[0];
193    gettdatas.local_buffer_size = sizeof(buff);
194 
195 /* : print out terminal emulator banner and instructions */
196 
197    printf("===== MOWSE Terminal Emulator\n");
198    printf("===== Hit F3 to display emulator functions.\n");
199 
200 /* : While (not asked to quit by user) */
201 
202    while (do_te_loop) {
203 
204 /* : - check terminal buffer for data character from the remote machine
205        and display it if it exists */
206 
207       str_len = gettdata(&gettdatas);
208       if (gettdatas.minor_capability == FG_TERMINAL_DATA || !fg_data_only)
209          em_print_buff(buff,str_len);
210 
211 /* : - loop for a while here to allow clock interrupt time to happen */
212 
213       for (delay_i = 0; delay_i < DELAY_INTERVAL; delay_i++);
214 
215 /* : - check for background messages
216      - if there is background data then */
217 
218       while (gettdatas.background_pending_flag > 0) {
219          err_code = getbgmes(buff, &message_type, &sender_major);
220 
221 /* : -- display the data preceeded by a carat (^) */
222 
223          if (message_type == WSINFO || message_type == WSQUERY) {
224             c_unpack(&sys, &major, sender_major);
225             printf("^[%2d:%2d]%s\n",sys,major,buff);
226          }
227 
228 /* : -- if it was a query message, save sender's major in the FIFO
229      --- check for queue overflow */
230 
231          if (message_type == WSQUERY) {
232             if (bg_sender_out == ((bg_sender_in+1) % BG_SENDBUFF_SIZE))
233                printf ("$$ query buffer overflow $$\n");
234             else {
235                bg_sender_buff[bg_sender_in] = sender_major;
236                bg_sender_in = (bg_sender_in + 1) % BG_SENDBUFF_SIZE;
237             }
238          }
239 
240 /* : -- decrement count of background messages left */
241 
242          gettdatas.background_pending_flag--;
243       }
244 
245 
246 /* : - check for input from the user
247      - if in packet-mode */
248 
249       if (packetize_flag) {
250 
251 /* : -- check for a line of input from user */
252 
253          str_len = db_get_kb_line(buff, kb_stack, &option);
254          if (str_len > 0) {
255 
256 /* : --- if input is not preceeded by ^, destined for foreground */
257 
258             if (buff[0] != '^')
259                puttdata(FG_TERMINAL_DATA,buff,str_len);
260 
261 /* : --- if user wants to send input with ^ as the first character over
262          foreground, he enters ^^ and the first one is stripped, rest is
263          sent to foreground */
264 
265             else if (str_len > 1 && buff[0] == '^' && buff[1] == '^')
266                puttdata(FG_TERMINAL_DATA,buff+1,str_len-1);
267 
268 /* : --- data is destined for background, get the sender major off stack and
269          send back the response */
270 
271             else if (bg_sender_in != bg_sender_out) {
272                buff[str_len] = '\0';
273                sendqrep (buff+1,bg_sender_buff[bg_sender_out]);
274                c_unpack(&sys,&major,bg_sender_buff[bg_sender_out]);
275                printf ("$$ Reply sent to [%d:%d]\n", sys, major);
276                bg_sender_out = (bg_sender_out + 1) % BG_SENDBUFF_SIZE;
277             }
278             else
279                printf ("$$ No queries pending $$\n");
280          }
281 
282 /* : -- check if special function key was pressed */
283 
284          else if (option >= 0)
285          db_process_options(option,&do_te_loop);
286       }
287 
288 /* : -- else in non-packet mode
289      --- check if a key was pressed
290      ---- check and handle any special function key
291      ---- otherwise send character over foreground channel */
292 
293       else {
294          if (get_kb_key(&ch)) {
295             if (ch > 255)
296                db_process_options(ch,&do_te_loop);
297             else
298                puttdata(FG_TERMINAL_DATA,&ch,1);
299          }
300       }
301    }
302 
303 /* : print message to indicate exit from terminal emulator */
304 
305    printf("\n==== MOWSE Terminal Emulator returning to DOS ====\n");
306 }
307 
308 #else
309 em ()
310 {}
311 #endif
312 ^Z