1 /* ********************************************
  2    *                                          *
  3    * Copyright, (C) Honeywell Bull Inc., 1988 *
  4    *                                          *
  5    ******************************************** */
  6 
  7 /* HISTORY COMMENTS:
  8   1) change(88-03-02,Lee), approve(88-05-16,MCR7897), audit(88-09-19,Flegel),
  9      install(88-10-12,MR12.2-1160):
 10      Created routines for buffering.
 11   2) change(88-05-31,Lee), approve(88-05-16,MCR7897), audit(88-09-19,Flegel),
 12      install(88-10-12,MR12.2-1160):
 13      Added support for file and line printer auditing.
 14   3) change(88-07-25,Lee), approve(88-05-16,MCR7897), audit(88-09-19,Flegel),
 15      install(88-10-12,MR12.2-1160):
 16      Documentation additions only. Added header comments to all routines.
 17   4) change(88-08-09,Lee), approve(88-05-16,MCR7897), audit(88-09-19,Flegel),
 18      install(88-10-12,MR12.2-1160):
 19      Fix references to include files; "wstdefs.h" was split into
 20      "wstdefs.h" and "wsttype.h" to avoid declaration clash; also,
 21      various constants defined to descriptive names.
 22   5) change(89-01-18,Lee), approve(89-01-02,MCR8043), audit(89-03-14,Flegel),
 23      install(89-04-24,MR12.3-1033):
 24      Separated input and output parameters to int86() to avoid confusion
 25      when parameters are used.
 26                                                    END HISTORY COMMENTS */
 27 
 28 #include <stdio.h>
 29 #include <fcntl.h>
 30 #include <dos.h>
 31 #include <ctype.h>
 32 #include "wstdefs.h"
 33 #include "wstglob.h"
 34 
 35 
 36 /* used globally but only by these routines */
 37 
 38 static char wst_f_aud_buff[F_AUDIT_BUFF_SIZE];
 39 static int  wst_f_aud_dex = 0;
 40 static int  wst_f_aud_fd = -1;
 41 
 42 static char wst_p_aud_buff[P_AUDIT_BUFF_SIZE];
 43 static int wst_p_aud_dex;
 44 
 45 
 46 /*^L
 47 **********************************************************************
 48 
 49   Routine:            F_AUD_INIT
 50 
 51   Function:
 52       This routine intializes any global file audit variables used.
 53 
 54   Parameters:         NONE
 55 
 56   Returns:            NONE
 57 
 58 **********************************************************************/
 59 
 60 f_aud_init()
 61 {
 62      /* file audit buffer index set to beginning */
 63      wst_f_aud_dex = 0;
 64 
 65      /* initialize file descriptor for audit file */
 66      wst_f_aud_fd = -1;
 67 
 68 }
 69 
 70 
 71 
 72 /*^L
 73 **********************************************************************
 74 
 75   Routine:            F_AUD_OPEN
 76 
 77   Function:
 78       This routine opens the audit file and sets up the file audit
 79   buffer.
 80 
 81   Parameters:         NONE
 82 
 83   Returns:            -1 if unsuccessful in opening the audit file
 84                       0 if no errors
 85 
 86 **********************************************************************/
 87 
 88 f_aud_open()
 89 {
 90     wst_f_aud_fd = open(audit_file_name,O_CREAT|O_WRONLY|O_APPEND);
 91 
 92     /* check for successful open or create */
 93     if (wst_f_aud_fd < 0)
 94         return(-1);
 95 
 96     /* initialize buffer index to beginning of buffer */
 97     wst_f_aud_dex = 0;
 98 
 99     return(0);
100 }
101 
102 
103 
104 /*^L
105 **********************************************************************
106 
107   Routine:            F_AUD_CLOSE
108 
109   Function:
110       This routine flushes the contents of the audit buffer to file
111   and closes the audit file.
112 
113   Parameters:         NONE
114 
115   Returns:            NONE
116 
117 **********************************************************************/
118 
119 f_aud_close()
120 {
121     f_aud_flush();
122     close(wst_f_aud_fd);
123 }
124 
125 
126 
127 /*^L
128 **********************************************************************
129 
130   Routine:            BEGIN_FILE_AUDIT
131 
132   Function:
133       This routine is called to initiate a file audit session. If set
134   up and opening of the audit file and audit file buffer is
135   successful, an audit header containing the current date and time is
136   written to the audit buffer. If set up or opening of audit file is
137   unsuccessful, an error message is displayed and control passes back
138   to the call when a key is entered.
139 
140   Parameters:         NONE
141 
142   Returns:            -1 if unsuccessful
143                       0 if successful
144 
145 **********************************************************************/
146 
147 begin_file_audit()
148 {
149     char message[81];    /* local message buffer */
150 
151     /* if opening of audit file is unsuccessful */
152     if (f_aud_open() < 0) {
153 
154         /* display an error message and wait for any key */
155         sprintf(message,"Cannot open audit file: %s  <any key>-resume",
156             audit_file_name);
157         status_err_msg(message);
158 
159         return(-1);
160     }
161 
162     /* open is successful, log an audit trace begin message containing */
163     /*   the current date and time   */
164 
165     f_audit_msg("======= BEGIN WSTERM AUDIT TRACE: ",34);
166     get_date_time_str(message);
167     f_audit_msg(message,strlen(message));
168     f_audit_msg(" =======\n",9);
169 
170     return(0);
171 }
172 
173 
174 
175 /*^L
176 **********************************************************************
177 
178   Routine:            END_FILE_AUDIT
179 
180   Function:
181       This routine is called to terminate a file audit session. The
182   routine logs a terminating audit message containing the current
183   date and time, flushes the audit buffer and closes the audit file.
184 
185   Parameters:         NONE
186 
187   Returns:            NONE
188 
189 **********************************************************************/
190 
191 end_file_audit()
192 {
193     char str[MAX_DATE_TIME_STR_LENGTH];     /* local message buffer */
194 
195     /* log audit trace end message containing current date and time */
196     f_audit_msg("======= END WSTERM AUDIT TRACE: ",32);
197     get_date_time_str(str);
198     f_audit_msg(str,strlen(str));
199     f_audit_msg(" =======\n",9);
200 
201     /* close the audit file */
202     f_aud_close();
203 }
204 
205 
206 
207 /*^L
208 **********************************************************************
209 
210   Routine:            F_AUDIT_MSG
211 
212   Function:
213       This routine writes data to the audit file buffer which gets
214   flushed when full or when file audit is terminated.
215 
216   Parameters:
217      (input)          buff - pointer to the buffer containing the
218                           audit data
219      (input)          bytes - specifies the number of bytes of audit
220                           data to write
221 
222   Returns:            NONE
223 
224 **********************************************************************/
225 
226 f_audit_msg(buff,bytes)
227 char *buff;   /* data buffer */
228 int  bytes;   /* number of data bytes */
229 {
230     /* fill file buffer with data until no more data or file buffer full */
231     while (bytes > 0 && wst_f_aud_dex < F_AUDIT_BUFF_SIZE) {
232         wst_f_aud_buff[wst_f_aud_dex++] = *buff++;
233         bytes--;
234     }
235 
236     /* if no more data, done */
237     if (wst_f_aud_dex < F_AUDIT_BUFF_SIZE)
238         return;
239 
240     /* else buffer was full, flush it */
241     write(wst_f_aud_fd,wst_f_aud_buff,F_AUDIT_BUFF_SIZE);
242 
243     /* reset the file buffer index to start of buffer */
244     wst_f_aud_dex = 0;
245 
246     /* will rest of data fit into buffer? */
247     if (bytes < F_AUDIT_BUFF_SIZE) {
248 
249         /* yes, fill the buffer with rest of data */
250         while (bytes > 0) {
251             wst_f_aud_buff[wst_f_aud_dex++] = *buff++;
252             bytes--;
253         }
254     }
255     /* no, quicker to just flush all data straight to file */
256     else
257         write(wst_f_aud_fd,buff,bytes);
258 }
259 
260 
261 
262 /*^L
263 **********************************************************************
264 
265   Routine:            F_AUD_FLUSH
266 
267   Function:
268       This routine flushes the contents of the audit buffer to the
269   audit file.
270 
271   Parameters:         NONE
272 
273   Returns:            NONE
274 
275   Note 1 - The caller must ensure that the audit file is opened
276       before calling this routine as no checks are made before
277       writing to file.
278 **********************************************************************/
279 
280 f_aud_flush()
281 {
282     /* if data exists in file buffer */
283     if (wst_f_aud_fd > 0) {
284 
285         /* write it out */
286         write(wst_f_aud_fd,wst_f_aud_buff,wst_f_aud_dex);
287 
288         /* reset the buffer index to start of buffer */
289         wst_f_aud_dex = 0;
290     }
291 }
292 
293 
294 
295 /*^L
296 **********************************************************************
297 
298   Routine:            GET_DATE_TIME_STR
299 
300   Function:
301       This routine formats a string containing the current date and
302   time and passes the string back to the caller.
303 
304   Parameters:
305      (output)         str - pointer to the string to which the
306                           formatted date and date is to be passed
307                           backed
308 
309   Returns:            NONE
310 
311   Note 1 - The date and time are obtained from DOS and are meaningful
312       only if the date and time are correctly set before WSTERM is
313       invoked.
314 **********************************************************************/
315 
316 get_date_time_str(str)
317 char *str;
318 {
319     union REGS in, date, time;
320 
321     /* call DOS routine to get the date */
322     in.h.ah = DOS_GET_DATE;
323     intdos(&in,&date);
324 
325     /* call DOS routine to get the time */
326     in.h.ah = DOS_GET_TIME;
327     intdos(&in,&time);
328 
329     /* format the date and time into the user-specified string */
330     sprintf(str,"%s %d, %04d - %02d:%02d.%02d",
331         month_tab[date.h.dh-1],
332         date.h.dl,
333         date.x.cx,
334         time.h.ch,
335         time.h.cl,
336         time.h.dh);
337 }
338 
339 
340 
341 /*^L
342 **********************************************************************
343 
344   Routine:            BEGIN_PRINTER_AUDIT
345 
346   Function:
347       This routine initiates a printer audit session by checking that
348   the printer is ready and then printing a printer audit message
349   containing the current date and time.
350 
351   Parameters:         NONE
352 
353   Returns:            -1 if printer error occurred
354                       0 if otherwise successful
355 
356   Note 1 - If an error occurs, an error message is displayed on the
357       status line and the routine returns when a key is pressed.
358 **********************************************************************/
359 
360 begin_printer_audit()
361 {
362     char message[SCREEN_COLS+1];        /* local message buffer */
363     char *err_msg;        /* pointer to error messages displayed */
364 
365     /* check and handle printer not ready */
366     if (check_printer_status(&err_msg) < 0) {
367 
368         sprintf(message,"Printer error - %s <any key>-resume", err_msg);
369         status_err_msg(message);
370 
371         return(-1);
372     }
373 
374     /* printer is ready, display trace begin message containing date & time */
375     p_audit_msg("======= BEGIN WSTERM AUDIT TRACE: ",34,NULL);
376     get_date_time_str(message);
377     p_audit_msg(message,strlen(message),NULL);
378     p_audit_msg(" =======\n",9,NUL);
379 
380     return(0);
381 }
382 
383 
384 
385 /*^L
386 **********************************************************************
387 
388   Routine:            END_PRINTER_AUDIT
389 
390   Function:
391       This routine terminates a printer audit session by printing a
392   terminating message containing the current date and time.
393 
394   Parameters:         NONE
395 
396   Returns:            0 always
397 
398 **********************************************************************/
399 
400 end_printer_audit()
401 {
402     char str[MAX_DATE_TIME_STR_LENGTH];    /* local message buffer */
403 
404     /* printer a trace end message containing the date and time */
405     p_audit_msg("======= END WSTERM AUDIT TRACE: ",32,NULL);
406     get_date_time_str(str);
407     p_audit_msg(str,strlen(str),NULL);
408     p_audit_msg(" =======\n",9,NULL);
409     return(0);
410 }
411 
412 
413 
414 /*^L
415 **********************************************************************
416 
417   Routine:            P_AUD_INIT
418 
419   Function:
420       This routine initializes any global variables used for printer
421   auditing
422 
423   Parameters:         NONE
424 
425   Returns:            NONE
426 
427 **********************************************************************/
428 
429 p_aud_init()
430 {
431     wst_p_aud_dex = 0;
432 }
433 
434 
435 
436 /*^L
437 **********************************************************************
438 
439   Routine:            P_AUDIT_MSG
440 
441   Function:
442       This routine writes printer audit data to the printer buffer.
443   The buffer is flushed (by sending to the printer) when the end of a
444   line is detected or when the buffer is full.
445 
446   Parameters:
447      (input)          str - pointer to the buffer containg the
448                           printer audit data
449      (input)          len - specifies how many bytes of printer audit
450                           data to write to the printer audit buffer
451      (input)          stat_line - specifies the status line contents to
452                           restore, after the status line area has
453                           been overwritten with an error message;
454                           if NULL, the foreground status line is used
455 
456   Returns:            NONE
457 
458 **********************************************************************/
459 
460 p_audit_msg(str,len,stat_line)
461 char *str;
462 int len;
463 char *stat_line;
464 {
465     /* buffer the data in the printer audit buffer, flushing the buffer
466        whenever a linefeed is received or when the buffer becomes full
467     */
468     while (len > 0) {
469         if ((wst_p_aud_buff[wst_p_aud_dex++] = *str++) == '\n' ||
470             wst_p_aud_dex >= P_AUDIT_BUFF_SIZE)
471             p_aud_flush(stat_line);
472         len--;
473     }
474 }
475 
476 
477 
478 /*^L
479 **********************************************************************
480 
481   Routine:            P_AUD_FLUSH
482 
483   Function:
484       This routine flushes the audit buffer by sending each buffered
485   character to the printer port. The routine handles the case where a
486   printer error occurs in the middle of sending the buffer by keeping
487   track of where the printer occurred and preserving the unprinted
488   characters.
489 
490   Parameters:
491      (input)          stat_line - specifies the status line contents to
492                           restore, after the status line area has
493                           been overwritten with an error message;
494                           if NULL, the foreground status line is used
495 
496   Returns:            NONE
497 
498 **********************************************************************/
499 
500 p_aud_flush(stat_line)
501 char *stat_line;
502 {
503     int code;
504     int i;
505     char prt_err_msg[SCREEN_COLS+1];
506     char *err_type;
507     char *prev_err;
508 
509     /* print each character in buffer until no more characters */
510     /*   or until error occurs in printing */
511     i = ZERO_INDEX_VALUE;
512     while (i < wst_p_aud_dex) {
513         code = lpchar(wst_p_aud_buff[i]);
514         if (code) {
515             prev_err = NULL;
516             while (code) {
517                 code = check_printer_status(&err_type);
518                 if (code && prev_err != err_type) {
519                     sprintf(prt_err_msg,"Printer error (%s), fix printer",err_type);
520                     status_line(prt_err_msg);
521                     prev_err = err_type;
522                 }
523             }
524             if (stat_line == NULL)
525                 update_status();
526             else
527                 status_line(stat_line);
528         }
529         else
530             i++;
531     }
532     wst_p_aud_dex = ZERO_INDEX_VALUE;
533 }
534 
535 
536 
537 /*^L
538 **********************************************************************
539 
540   Routine:            LPCHAR
541 
542   Function:
543       This routine sends a single character to the printer port.
544 
545   Parameters:
546      (input)          ch - specifies what character to send to the
547                           printer port
548 
549   Returns:            TRUE if timeout occurred, indicating a printer
550                           error
551                       FALSE if not error
552 
553 **********************************************************************/
554 
555 lpchar(ch)
556 int ch;
557 {
558     union REGS reg, outreg;
559 
560     /* call BIOS to send character to printer port */
561     reg.h.ah = BIOS_PRT_PRINT;     /* select print function */
562     reg.x.dx = wst_printer_card;
563     reg.h.al = ch;
564     int86(BIOS_PRT,&reg,&outreg);
565 
566     /* timeout */
567     return(outreg.h.ah & 01);
568 }
569 
570 
571 
572 /*^L
573 **********************************************************************
574 
575   Routine:            SET_PRINTER_TIMEOUT
576 
577   Function:
578       This routine is used to set the duration of the wait period
579   before timeout occurs for a printer error. This is accomplished by
580   modifying timeout variables kept in the BIOS segment.
581 
582   Parameters:
583      (input)          timeout_val - specifies the timeout duration
584 
585   Returns:            NONE
586 
587 **********************************************************************/
588 
589 set_printer_timeout(timeout_val)
590 int timeout_val;
591 {
592     char val;
593 
594     val = timeout_val;
595     poke(BIOS_SEGMENT,PRT_TIMEOUT_BASE+wst_printer_card,&val,1);
596 }
597 
598 
599 
600 /*^L
601 **********************************************************************
602 
603   Routine:            SAVE_PRINTER_TIMEOUT
604 
605   Function:
606       This routine saves the default duration of the wait period
607   before timeout occurs for a printer error. This is accomplished by
608   reading and saving the timeout variable kept in the BIOS segment.
609 
610   Parameters:
611      (input)          timeout_val - specifies the timeout duration
612 
613   Returns:            NONE
614 
615 **********************************************************************/
616 
617 save_printer_timeout()
618 {
619     char val;
620 
621     /* save timeout value for printer card used */
622     peek(BIOS_SEGMENT,PRT_TIMEOUT_BASE+wst_printer_card,&val,1);
623     wst_prt_timeout = val;
624 }
625 
626 
627 /*^L
628 **********************************************************************
629 
630   Routine:            CHECK_PRINTER_STATUS
631 
632   Function:
633       This checks the printer status. If the printer is not ready, an
634   error message is passed back to try to specify the error.
635 
636   Parameters:
637      (output)         err_msg_ptr - address of a character pointer
638                           for passing back the address of a error
639                           message string if the printer is not ready;
640                           address passed back is NULL if printer is
641                           ready
642 
643   Returns:            0 if printer is ready
644                       -1 otherwise
645 
646 **********************************************************************/
647 
648 check_printer_status(err_msg_ptr)
649 char **err_msg_ptr;
650 {
651     union REGS reg, outreg;
652     char *error_msg;
653 
654     /* get printer status from BIOS */
655     reg.h.ah = BIOS_PRT_STATUS;
656     reg.x.dx = wst_printer_card;
657 
658     int86(BIOS_PRT,&reg,&outreg);
659 
660     /* check printer ready */
661     if (outreg.h.ah == PRT_READY_MODE) {
662         if (*err_msg_ptr != NULL)
663             *err_msg_ptr = NULL;
664         return(0);
665     }
666 
667     /* check printer error */
668     else {
669 
670         /* pass back error string if non-NULL address specified */
671         if (err_msg_ptr != NULL) {
672             switch(outreg.h.ah) {
673                 case PRT_OFF_LINE_MODE:
674                     *err_msg_ptr = print_error_list[PEL_OFF_LINE];
675                     break;
676                 case PRT_NO_PAPER_MODE:
677                     *err_msg_ptr = print_error_list[PEL_NO_PAPER];
678                     break;
679                 default:
680                     *err_msg_ptr = print_error_list[PEL_NOT_READY];
681              }
682         }
683     }
684 
685     /* indicate printer error occurred */
686     return(-1);
687 }