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,®,&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,®,&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 }