-+-+-+-+-+-+-+-+ START OF PART 2 -+-+-+-+-+-+-+-+ X args->exact = FALSE; X X if(CLI$PRESENT(&expert_d) == CLI$_PRESENT) X args->expert = TRUE; X else X args->expert = FALSE; X X if(CLI$PRESENT(&print_d) == CLI$_PRESENT) X args->print = TRUE; X else X args->print = FALSE; X X if(CLI$PRESENT(&retrieve_d) == CLI$_PRESENT) X args->retrieve = TRUE; X else X args->retrieve = FALSE; X`20 X if(CLI$PRESENT(&save_d) == CLI$_PRESENT) X args->save = TRUE; X else X args->save = FALSE; X`20 X if(CLI$PRESENT(&mail_d) == CLI$_PRESENT) X args->mail = TRUE; X else X args->mail = FALSE; X`20 X if(CLI$PRESENT(&skim_d) == CLI$_PRESENT) X args->skim = TRUE; X else X args->skim = FALSE; X X if(CLI$PRESENT(&delete_d) == CLI$_PRESENT) X args->delete = TRUE; X else X args->delete = FALSE; X X return; X X`7D`09/*** get_args ***/ X`0C X/*************************************************************************** V**** X**************************************************************************** V**** X X Function:`09quit X X Purpose:`09Exit handler used to clean up a few things. X X Formal Parameters: X X`09Name`09`09`09Description X`09----`09`09`09----------- X`09none X X Global variables: X X`09Name`09`09`09Examine/Modify/Use/Read/Write X`09----`09`09`09----------------------------- X`09tt_chan`09`09`09`09`09X X`09tt_mbx_chan`09`09`09`09X X`09tty_save_char`09`09`09`09X X`09log_fab`09`09`09`09`09X X`09logfile`09`09`09`09`09X X`09flags`09`09`09`09`09X X`09filename`09`09`09`09X X`09stage_dir`09`09`09`09X X`09args`09`09`09`09`09X X X Return Codes: X X`09Code`09`09`09Reason X`09---- `09`09`09------ X`09none X X Termination Codes: X X`09Code`09`09`09Reason X`09----`09`09`09------ X`09none X X**************************************************************************** V**** X**************************************************************************** V***/ X Xstatic void quit(void) X X`7B`09/*** quit ***/ X`09`09`09`09`09/******** LOCAL VARIABLES ********/ X`09 ULONG`09 status,`09`09/* return code status holder`09 */ X`09`09 length;`09`09/* length of device char. block`09 */ X `09 EXH_DEF exh2_blk = `7B0L,quit2,0,&status`7D; Xstatic`09 union`09 prvdef _align(longword) privs; X X X privs.prv$v_sysprv = ON;`09`09/* need SYSPRV to close the log file */ X X status = SYS$SETPRV(ON,&privs,FALSE,NULL); X X if(status != SS$_NORMAL) X `7B X LIB$SIGNAL(status); X return; X `7D X X /* set the protection to override any default the user might've set */ X X log_xabpro.xab$w_pro = ((XAB$M_NOREAD `7C XAB$M_NOWRITE `7C XAB$M_NOEXE ` V7C X`09`09`09 XAB$M_NODEL) << XAB$V_GRP) `7C ((XAB$M_NOREAD `7C X`09`09`09 XAB$M_NOWRITE `7C XAB$M_NOEXE `7C XAB$M_NODEL) X`09`09`09 << XAB$V_WLD); X X status = SYS$CLOSE(&log_fab);`09/* close the log file`09`09 */ X X if(status != RMS$_NORMAL) X `7B X delete(logfile); X LIB$STOP(status); X `7D X X /* declare ANOTHER exit handler to delete the log file in case the X * user decides to do something drastic like a disconnect X */ X X status = SYS$DCLEXH(&exh2_blk); X X if(status != SS$_NORMAL) X `7B X kill_log(); X LIB$STOP(JLG_NO_EXH); X `7D X X privs.prv$v_cmkrnl = ON; X X status = SYS$SETPRV(ON,&privs,FALSE,NULL); X X if(status != SS$_NORMAL) X `7B X LIB$SIGNAL(status); X return; X `7D X X /* clean up some things; start by cancelling I/O on all channels */ X X status = SYS$CANCEL(tt_mbx_chan); X X if(status != SS$_NORMAL) X LIB$SIGNAL(JLG_CANT_CANCEL_IO,1L,"TTY mailbox"); X X status = SYS$CANCEL(tt_chan); X X if(status != SS$_NORMAL) X LIB$SIGNAL(JLG_CANT_CANCEL_IO,1L,"TTY"); X X status = SYS$CANCEL(py_mbx_chan); X X if(status != SS$_NORMAL) X LIB$SIGNAL(JLG_CANT_CANCEL_IO,1L,"PTY mailbox"); X X status = SYS$CANCEL(py_chan); X X if(status != SS$_NORMAL) X LIB$SIGNAL(JLG_CANT_CANCEL_IO,1L,"PTY"); X X /* now delete and deassign some stuff */ X X status = SYS$DELMBX(py_mbx_chan);`09/* delete mailbox associated with PTY V */ X X if(status != SS$_NORMAL) X LIB$SIGNAL(JLG_CANT_DELETE,1L,"PTY mailbox"); X X status = SYS$DASSGN(py_mbx_chan); X X if(status != SS$_NORMAL) X LIB$SIGNAL(JLG_CANT_DASSGN,1L,"channel to PTY mailbox"); X X status = SYS$DASSGN(py_chan); X X if(status != SS$_NORMAL) X LIB$SIGNAL(JLG_CANT_DASSGN,1L,"channel to PTY"); X X status = SYS$DELMBX(tt_mbx_chan); X X if(status != SS$_NORMAL) X LIB$SIGNAL(JLG_CANT_DELETE,1L,"TTY mailbox"); X X status = SYS$DASSGN(tt_mbx_chan); X X if(status != SS$_NORMAL) X LIB$SIGNAL(JLG_CANT_DASSGN,1L,"channel to TTY mailbox"); X X /* set the terminal mode back to the way it was */ X `20 X length = (ULONG) sizeof(tty_save_char); X X status = SYS$QIOW(0,tt_chan,IO$_SETMODE,0,0,0,&tty_save_char,length,0,0,0 V, X`09`09 0); X X if(status != SS$_NORMAL) X LIB$SIGNAL(JLG_CANT_RESET); X X /* NOW we can deassign the TTY channel */ X X status = SYS$DASSGN(tt_chan); X X if(status != SS$_NORMAL) X LIB$SIGNAL(JLG_CANT_DASSGN,1L,"TTY channel"); X X /* ask user what should happen */ X X ask_disposition(logfile,stage_dir,&flags,&args); X X /* kill the secondary exit handler so that it doesn't kick in when we X * exit X */ X X status = SYS$CANEXH(&exh2_blk); X X if(status != SS$_NORMAL) X LIB$SIGNAL(JLG_NO_EXH); X X /* turn off SYSPRV and CMKRNL before exiting; since we specified them X * as temporary, they'll be disabled when the image exits anyway but X * let's be conscientious X */ X X status = SYS$SETPRV(OFF,&privs,FALSE,NULL); X X my_puts("\nExiting JOBLOG. Remember YOU ARE STILL LOGGED IN!!!\7\7\7\n") V; X X exit(); X X`7D`09/*** quit ***/ X`0C X/*************************************************************************** V**** X**************************************************************************** V**** X X Function:`09get_channels X X Purpose:`09Assign channels to both the TTY and the PTY (with mailboxes), X`09`09SETMODE the TTY and SETCHAR the PTY. X X Formal Parameters: X X`09Name`09`09`09Description X`09----`09`09`09----------- X`09none X X Global variables: X X`09Name`09`09`09Examine/Modify/Use/Read/Write X`09----`09`09`09----------------------------- X`09py_d`09`09`09`09`09X X`09tt_d`09`09`09`09`09X X`09tw_d`09`09`09`09 X`09X X`09tty_save_char`09`09`09 X X X Return Codes: X X`09Code`09`09`09Reason X`09----`09`09`09------ X`09none X X Termination Codes: X X`09Code`09`09`09Reason X`09----`09`09`09------ X`09status`09`09`09return code from various system calls X X**************************************************************************** V**** X**************************************************************************** V***/ X Xstatic void get_channels(short *tt_chan,short *py_chan,short *tt_mbx_chan, X`09`09`09 short *py_mbx_chan,long *max_msg,long *buf_quo) X `20 X`7B`09/*** get_channels ***/ X`09`09`09`09`09/******** LOCAL VARIABLES ********/ X`09 ULONG`09 status,`09`09/* return code status holder`09 */ X`09`09 length;`09`09/* length of tty_char block`09 */ X`09 short`09 tw_chan;`09`09/* channel for TWA device`09 */ X`09 IOSB_DEF iosb;`09`09`09/* I/O status block`09`09 */ X`09 SENS_DEF tty_char,`09`09/* TTY characteristics to set`09 */ X`09`09 twa_char;`09`09/* TWA characteristics to set`09 */ Xstatic`09 ULONG`09 py_num;`09`09/* device # of PTY control device */ Xstatic`09 USHORT`09 dvi_length;`09`09/* length of PY characteristics`09 V */ Xstatic`09 ITM_LST items`5B`5D = `7B`09`09/* for getting PTY characteristics V */ X`7B4,DVI$_DEVDEPEND,&py_num,&dvi_length`7D, X`7B0,0,0L,0L`7D`7D; Xstatic $DESCRIPTOR(format_d,"TWA!ZL:");`09/* for making device number`09 V */ X/* static`09 union `09 ttdef`09 _align(longword) tty_char; Xstatic`09 union `09 ttdef`09 _align(longword) twa_char; */ X X X /* get a channel & a mailbox for the user's TTY */ X X status = LIB$ASN_WTH_MBX(&tt_d,max_msg,buf_quo,tt_chan,tt_mbx_chan); X X if(status != SS$_NORMAL) X `7B X kill_log(); X LIB$STOP(status); X `7D X X /* now set the mode for the terminal */ X X length = sizeof(tty_char);`09`09/* get length of tty char. block */ X X status = SYS$QIOW(0,*tt_chan,IO$_SENSEMODE,&iosb,0,0,&tty_char,length,0,0 V, X`09`09 0,0); X `20 X if(status != SS$_NORMAL) X `7B X kill_log(); X LIB$STOP(status); X `7D X X /* copy the current TTY mode so it can be restored later */ X X tty_save_char = tty_char; X X /* now set up the characteristics we need to run */ X X/* X tty_char.tt$v_echo = FALSE; X*/ X tty_char.characts `7C= TT$M_NOECHO; X X /* set the TTY to HOSTSYNC and TTSYNC; if we don't, vt220's will hang X * because of flow control problems X */ X X/* X tty_char.characts `7C= TT$M_TTSYNC `7C TT$M_HOSTSYNC; X tty_char.tt$v_sync = TRUE; X tty_char.tt$v_hostsync = TRUE; X tty_char.tt$v_echo = TRUE; X*/ X tty_char.characts `7C= TT$M_TTSYNC; X tty_char.characts `7C= TT$M_HOSTSYNC; X tty_char.ext_char `7C= TT2$M_PASTHRU; X `20 X status = SYS$QIO(0,*tt_chan,IO$_SETMODE,&iosb,0,0,&tty_char,length,0,0, X`09`09 0,0); X X if(status != SS$_NORMAL) X `7B X kill_log(); X LIB$STOP(status); X `7D X X /* now get a channel and mailbox for the PTY */ X X status = LIB$ASN_WTH_MBX(&py_d,max_msg,buf_quo,py_chan,py_mbx_chan); X X if(status != SS$_NORMAL) X LIB$STOP(status); X X /* get the device-dependent characteristics */ X X status = SYS$GETDVI(0,*py_chan,0,&items,&iosb,0,0,0); X X if(status != SS$_NORMAL) X `7B X kill_log(); X LIB$STOP(status); X `7D X X /* get the device number of the PTY and use it to make the name of the X * associated control device so we can assign a channel to it X */ X X /* get the device number of the PTY and use it to make the name of the X * associated control device so we can assign a channel to it X */ X X status = SYS$FAO(&format_d,&length,&tw_d,py_num); X X if(status != SS$_NORMAL) X `7B X kill_log(); X LIB$STOP(status); X `7D X X tw_d.dsc$a_pointer`5Blength`5D = '\0';`09/* make it a string`09`09 * V/ X tw_d.dsc$w_length = length; X X status = SYS$ASSIGN(&tw_d,&tw_chan,0,0); X X if(status != SS$_NORMAL) X `7B X kill_log(); X LIB$STOP(status); X `7D X X /* set the characteristics of the TWA to be the same as the user's X * real terminal X */ X X twa_char = tty_save_char; X twa_char.ext_char `7C= TT2$M_HANGUP; X X status = SYS$QIO(0,tw_chan,IO$_SETCHAR,0,0,0,&twa_char,length,0,0,0,0); X X if(status != SS$_NORMAL `7C`7C status == SS$_NOPRIV) X `7B X kill_log(); X LIB$STOP(status); X `7D X X /* throw away the channel to the TWA because keeping it messes stuff up; X * we only wanted the mailbox X */ X X status = SYS$DASSGN(tw_chan); X X if(status != SS$_NORMAL) X `7B X kill_log(); X LIB$STOP(status); X `7D X X /* cancel I/O to the PYA device because we don't need it */ X X status = SYS$CANCEL(*py_chan); X X if(status != SS$_NORMAL) X `7B X kill_log(); X LIB$STOP(status); X `7D X X return; X X`7D`09/*** get_channels ***/ X`0C X/*************************************************************************** V**** X**************************************************************************** V**** X X Function:`09spawn X X Purpose:`09Spawn a subprocess to talk to the PTY. X X Formal Parameters: X X`09Name`09`09`09Description X`09----`09`09`09----------- X`09twname`09`09`09name of TW device X`09pid`09`09`09returns PID of subprocess X`09oldprivs`09`09default privileges of user X X Global variables: X X`09Name`09`09`09Examine/Modify/Use/Read/Write X`09----`09`09`09----------------------------- X`09none X X Return Codes: X X`09Code`09`09`09Reason X`09----`09`09`09------ X`09none X X Termination Codes: X X`09Code`09`09`09Reason X`09----`09`09`09------ X`09status`09`09`09return code from various system calls X X**************************************************************************** V**** X**************************************************************************** V***/ X `20 Xstatic void spawn(char *twname,ULONG *pid,union prvdef *oldprivs) X X`7B`09/*** spawn ***/ X`09`09`09`09`09/******** LOCAL VARIABLES ********/ X`09 ULONG`09 status,`09`09/* return code status holder`09 */ X`09`09 current_pid;`09`09/* PID of current process`09 */ X`09 short`09 length;`09`09/* length of process name`09 */ X`09 char`09 procname`5BPNAME_MAX+1`5D,/* current process name array`09 V */ X`09`09 newname`5BPNAME_MAX+1`5D;`09/* process name for JOBLOG subprocess */ X$DESCRIPTOR(procname_d,procname);`09/* for getting process name`09 */ X$DESCRIPTOR(newname_d,newname);`09`09/* for setting process name`09 */ X$DESCRIPTOR(pty_d,"");`09`09`09/* PTY name and number`09`09 */ X$DESCRIPTOR(prompt_d,"Joblog> ");`09/* DCL prompt when in JOBLOG`09 */ X$DESCRIPTOR(format_d,"JOBLOG_!XL"); Xstatic`09 union`09 prvdef _align(longword) privs; X X X current_pid = getpid();`09`09/* get PID for current process`09 */ X X /* make the process name that we are going to use */ X X status = SYS$FAO(&format_d,&length,&newname_d,current_pid & 0xFFFF); X X if(status != SS$_NORMAL) X `7B X kill_log(); X LIB$STOP(status); X `7D X X newname_d.dsc$w_length = length; X newname`5Blength`5D = '\0'; X pty_d.dsc$w_length = strlen(twname); X pty_d.dsc$a_pointer = twname; X `20 X /* put the current process back to it's default privileges so that we can X * give them to the subprocess; don't worry, we'll put the parent process X * back the way it was AFTER we create the subprocess; first we turn off X * all privileges X */ X X memset((void *) &privs,0xFF,sizeof(privs)); X X status = SYS$SETPRV(OFF,&privs,FALSE,oldprivs); X X if(status != SS$_NORMAL) X `7B X kill_log(); X LIB$STOP(status); X `7D X X /* get the default privileges so that we can propagate them to X * the subprocess X */ X X status = LIB$GETJPI(&JPI$_PROCPRIV,0,0,&privs); X X if(status != SS$_NORMAL) X `7B X kill_log(); X LIB$STOP(status); X `7D X X /* now enable the normal privs */ X X status = SYS$SETPRV(ON,&privs,FALSE,NULL); X X if(status != SS$_NORMAL) X `7B X kill_log(); X LIB$STOP(status); X `7D X X /* FINALLY! we spawn a subprocess to talk to the PTY and set the privs X * for it X */ X X status = LIB$SPAWN(0,&pty_d,&pty_d,&1L,&newname_d,pid,0,0,0,0,&prompt_d,0 V); X X if(status != SS$_NORMAL) X `7B X kill_log(); X LIB$STOP(status); X `7D X X /* set the privileges of the parent process back to what they are suppose Vd X * to be X */ X X status = SYS$SETPRV(ON,oldprivs,FALSE,NULL); `20 X X if(status != SS$_NORMAL) X `7B X kill_log(); X LIB$STOP(status); X `7D X X return; X X`7D`09/*** spawn ***/ X`0C X/*************************************************************************** V**** X**************************************************************************** V**** X X Function:`09queue_reads X X Purpose:`09Queue asynchronous read requests to both the PTY and the TTY. X X Formal Parameters: X X`09Name`09`09`09Description X`09----`09`09`09----------- X`09py_chan`09`09`09channel to PY device X`09py_mbx_chan `09`09channel to PY mailbox device X`09tt_mbx_chan `09`09channel to TT mailbox device X`09py_mbx_iosb`09`09I/O status block for PY mailbox X`09tt_mbx_iosb`09`09I/O status block for TT mailbox X`09py_mbx_buf`09`09buffer to receive messages for PTY control X`09`09`09`09device mailbox X`09tt_mbx_buf`09`09buffer to receive messages for TTY mailbox X`09max_msg`09`09`09maximum mailbox message size X X Global variables: X X`09Name`09`09`09Examine/Modify/Use/Read/Write X`09----`09`09`09----------------------------- X`09none X X Return Codes: X X`09Code`09`09`09Reason X`09----`09`09`09------ X`09none X X Termination Codes: X X`09Code`09`09`09Reason X`09----`09`09`09------ X`09status`09`09`09return code from SYS$QIO X X**************************************************************************** V**** X**************************************************************************** V***/ X `20 Xstatic void queue_reads(short py_chan,short py_mbx_chan,short tt_mbx_chan, X`09`09`09IOSB_DEF *py_mbx_iosb,IOSB_DEF *tt_mbx_iosb, X`09`09`09char *py_mbx_buf,char *tt_mbx_buf,FLAG_DEF *flags, X`09`09`09long max_msg) X X`7B`09/*** queue_reads ***/ X`09`09`09`09`09/******** LOCAL VARIABLES ********/ Xstatic`09 ULONG`09 status;`09`09/* return code status holder`09 */ X`09 IOSB_DEF iosb;`09`09`09/* for queuing SETMODE on PY`09 */ X X X /* queue an asynchronous read to the PTY control device mailbox; basicall Vy, X * this is done to detect hangups on the PTY X */ X X status = SYS$QIO(0,py_mbx_chan,IO$_READVBLK,py_mbx_iosb,py_mbx_ast,flags, X`09`09 py_mbx_buf,max_msg,0,0,0,0); X X if(status != SS$_NORMAL) X `7B X kill_log(); X LIB$STOP(JLG_CANT_QUEUE,1L,"AST QIO to PY mailbox"); X `7D X X /* queue an asynchronous read to the TTY mailbox; this will signal us X * that there is something on the real TTY to be read X */ X X status = SYS$QIO(0,tt_mbx_chan,IO$_READVBLK,tt_mbx_iosb,tt_mbx_ast,0, X`09`09 tt_mbx_buf,max_msg,0,0,0,0); X X if(status != SS$_NORMAL) X `7B X kill_log(); X LIB$STOP(JLG_CANT_QUEUE,"AST QIO to TT mailbox"); X `7D X X /* set up an AST to detect any change in the device characteristics so X * we can keep up with them; this is done primarily for the /EXACT X * qualifier because SMG applications like to change characteristics; X * to be implemented SOMEDAY (see get_args()) X */ X X/* X status = SYS$QIO(0,py_chan,IO$_SETMODE,&iosb,0,0,dev_chg_ast,0,0,3,0,0); X X if(status != SS$_NORMAL) X LIB$STOP(JLG_CANT_QUEUE,1L,"SETMODE QIO to PY device"); X*/ X X /* set up ASTs to detect XON/XOFF; same deal as above; see get_args() */ X X/* X status = SYS$QIO(0,py_chan,IO$_SETMODE,&iosb,0,0,xon_ast,0,0,1,0,0); X X if(status != SS$_NORMAL) X LIB$STOP(JLG_CANT_QUEUE,1L,"XON AST QIO to PY device"); X X status = SYS$QIO(0,py_chan,IO$_SETMODE,&iosb,0,0,xon_ast,0,0,2,0,0); X X if(status != SS$_NORMAL) X LIB$STOP(JLG_CANT_QUEUE,1L,"XOFF AST QIO to PY device"); X*/ X X return; X X`7D`09/*** queue_reads ***/ X`0C X/*************************************************************************** V**** X**************************************************************************** V**** X X Function:`09py_mbx_ast X X Purpose:`09AST routine for PTY control device mailbox X X Formal Parameters: X X`09Name`09`09`09Description X`09----`09`09`09----------- X`09flags`09`09`09global flags X X Global variables: X X`09Name`09`09`09Examine/Modify/Use/Read/Write X`09----`09`09`09----------------------------- X`09py_mbx_iosb`09`09 X`09`09X X`09py_mbx_buf`09`09`09`09X X`09py_mbx_chan`09`09`09`09X X`09max_msg`09`09`09`09`09X X`09flags`09`09`09 X X X Return Codes: X X`09Code`09`09`09Reason X`09----`09`09`09------ X`09none X X Termination Codes: X X`09Code`09`09`09Reason X`09----`09`09`09------ X`09status`09`09`09return code from SYS$QIO X`09py_mbx_iosb.status`09problems with AST delivery X X**************************************************************************** V**** X**************************************************************************** V***/ X Xstatic void py_mbx_ast(void) X X`7B`09/*** py_mbx_ast ***/ X`09`09`09`09`09/******** LOCAL VARIABLES ********/ Xstatic`09 ULONG`09 status;`09`09/* return code status holder`09 */ X X X if(py_mbx_iosb.status != SS$_NORMAL) X LIB$STOP(py_mbx_iosb.status); X X if(flags.hangups) X `7B X /* hangup on the terminal; let the exit handler do it's stuff */ X X exit(1); X `7D X else X `7B X status = SYS$QIO(0,py_mbx_chan,IO$_READVBLK,&py_mbx_iosb,py_mbx_ast, X`09`09 0,py_mbx_buf,max_msg,0,0,0,0); X X if(status != SS$_NORMAL) X `7B X`09 kill_log(); X`09 LIB$STOP(JLG_CANT_REQUEUE,1L,"AST to PY mailbox"); X `7D X `7D X X return;`09`09`09`09/* only get here if things are ok */ X X`7D`09/*** py_mbx_ast ***/ X`0C X/*************************************************************************** V**** X**************************************************************************** V**** X X Function:`09tt_mbx_ast X X Purpose:`09AST routine for TTY mailbox; this routine is called when X`09`09the mailbox AST is delivered to tell us that there is X`09`09data to read from the TTY. X X Formal Parameters: X X`09Name`09`09`09Description X`09----`09`09`09----------- X`09flags`09`09`09global flags X X Global variables: X X`09Name`09`09`09Examine/Modify/Use/Read/Write X`09----`09`09`09----------------------------- X`09tt_chan`09`09`09`09`09X X`09tt_mbx_chan`09`09`09`09X X`09tt_mbx_iosb`09`09 X`09`09X X`09tt_mbx_buf`09`09`09`09X X`09py_chan`09`09`09`09`09X X`09stamp_buf`09`09`09`09X X`09flags`09`09`09`09 X X X Return Codes: X X`09Code`09 `09`09Reason X`09----`09`09`09------ X`09none X X Termination Codes: X X`09Code`09`09`09Reason X`09----`09`09`09------ X`09status`09`09`09return code from SYS$QIO X`09tt_mbx_iosb.status`09problems with AST delivery X X**************************************************************************** V**** X**************************************************************************** V***/ X Xstatic void tt_mbx_ast(void) X X`7B`09/*** tt_mbx_ast ***/ X`09 `09`09`09`09/******** LOCAL VARIABLES ********/ Xstatic`09 ULONG`09 status;`09`09/* return code status holder`09 */ Xstatic`09 USHORT`09 length;`09`09/* number of characters read`09 */ Xstatic`09 IOSB_DEF tt_iosb;`09`09/* TTY I/O status block`09`09 */ Xstatic`09 char`09 tty_buf`5BTTY_BUF_MAX+1`5D, X`09`09 log_enable`5B`5D = `7B"Logging has been ENABLED\r\n"`7D, X`09`09 log_disable`5B`5D = `7B"Logging has been DISABLED\r\n"`7D, X`09`09 stamp_enable`5B`5D = `7B"Time stamping has been ENABLED\r\n"`7D, X`09`09 stamp_disable`5B`5D = `7B"Time stamping has been DISABLED\r\n"`7D; X X X /* make sure the TTY mailbox message came through ok */ X X if(tt_mbx_iosb.status != SS$_NORMAL) X `7B X kill_log(); X LIB$STOP(tt_mbx_iosb.status); X `7D X X /* read the data that was queued to the TTY */ X X status = SYS$QIOW(0,tt_chan,IO$_READVBLK`7CIO$M_TIMED`7CIO$M_ESCAPE,&tt_i Vosb,0,0, X`09`09 tty_buf,(ULONG) TTY_BUF_MAX,0,0,0,0); X X if(status != SS$_NORMAL) X `7B X kill_log(); X LIB$STOP(status); X `7D X X length = tt_iosb.count + tt_iosb.term_count; X X if(length > 0) X `7B X if(tty_buf`5B0`5D == CARRIAGE_RETURN && flags.time_stamp) X `7B X`09 flags.command = TRUE;`09`09/* this was a command`09`09 */ X`09 get_stamp(stamp_buf);`09`09/* create the time stamp for later */ X `7D X else X `7B X`09 /* check for toggle characters */ X X`09 if(tty_buf`5B0`5D == TOGGLE_LOG) X`09 `7B X`09 /* toggle the logging to the file */ X X`09 if(flags.logging) X`09 write_tt(tt_chan,log_disable,(ULONG) sizeof(log_disable)); X`09 else X`09 write_tt(tt_chan,log_enable,(ULONG) sizeof(log_enable)); X `20 X`09 flags.logging = !flags.logging; X`09 flags.verify = FALSE; X`09 `7D X`09 else if(tty_buf`5B0`5D == TOGGLE_STAMP) X`09 `7B X`09 /* toggle time-stamping */ X X`09 if(flags.time_stamp) X`09 write_tt(tt_chan,stamp_disable,(ULONG) sizeof(stamp_disable)); X`09 else X`09 write_tt(tt_chan,stamp_enable,(ULONG) sizeof(stamp_enable)); X X`09 flags.time_stamp = !flags.time_stamp; X`09 `7D X `7D X X /* write everything to the PTY control device */ X X status = write_py(py_chan,tty_buf,(ULONG) length); X X if(status != SS$_NORMAL) X `7B X`09 kill_log(); X`09 LIB$STOP(JLG_CANT_WRITE,1L,"to PY device"); X `7D X `7D X X /* repost read AST to the TTY */ X X status = SYS$QIO(0,tt_mbx_chan,IO$_READVBLK,&tt_mbx_iosb,tt_mbx_ast,0, X`09`09 tt_mbx_buf,max_msg,0,0,0,0); X X if(status != SS$_NORMAL) X `7B X kill_log(); X LIB$STOP(status); X `7D X X return; X X`7D`09/*** tt_mbx_ast ***/ X`0C X/*************************************************************************** V**** X**************************************************************************** V**** X X Function:`09dev_chg_ast X X Purpose:`09Called when the TW device characteristics are changed. Here X`09`09the TT characteristics are changed to match. X X Formal Parameters: X X`09Name`09`09`09Description X`09----`09`09`09----------- X`09none X X Global variables: X X`09Name`09`09`09Examine/Modify/Use/Read/Write X`09----`09`09`09----------------------------- X`09dev_chg_iosb`09`09`09`09X X`09py_chan`09`09`09`09`09X X`09tt_chan`09`09`09`09`09X X X Return Codes: X X`09Code`09 `09`09Reason X`09----`09`09`09------ X`09none X X Termination Codes: X X`09Code`09`09`09Reason X`09----`09`09`09------ X`09none X X**************************************************************************** V**** X**************************************************************************** V***/ X Xstatic void dev_chg_ast(void) X X`7B`09/*** dev_chg_ast ***/ X`09`09`09`09`09/******** LOCAL VARIABLES ********/ Xstatic`09 ULONG`09 status,`09`09/* return code status holder`09 */ X`09`09 length;`09`09/* length of characteristics block */ Xstatic`09 IOSB_DEF iosb;`09`09`09/* I/O status block`09`09 */ Xstatic`09 SENS_DEF dev_char;`09`09/* for getting PY dev characteristics */ X X X /* get the new device characteristics */ X X length = sizeof(dev_char); X status = SYS$QIOW(0,py_chan,IO$_SENSEMODE,&iosb,0,0,&dev_char,length,0,0, X`09`09 0,0); X `20 X if(status != SS$_NORMAL) X LIB$STOP(status); X X /* change the TTY to match */ X/* X status = SYS$QIOW(0,tt_chan,IO$_SETMODE,&iosb,0,0,&dev_char,length,0,0,0, V0); X X if(status != SS$_NORMAL) X LIB$STOP(status); X*/ X /* requeue the AST */ X X status = SYS$QIOW(0,py_chan,IO$_SETMODE,&iosb,0,0,dev_chg_ast,0,0,3,0,0); X X if(status != SS$_NORMAL) X LIB$STOP(JLG_CANT_QUEUE,1L,"SETMODE QIO to PY device"); X X return; X X`7D`09/*** dev_chg_ast ***/ X`0C X/*************************************************************************** V**** X**************************************************************************** V**** X X Function:`09xon_ast X X Purpose:`09Called when XON is detected on the PTY. X X Formal Parameters: X X`09Name`09`09`09Description X`09----`09`09`09----------- X`09none X X Global variables: X X`09Name`09`09`09Examine/Modify/Use/Read/Write X`09----`09`09`09----------------------------- X`09py_chan`09`09`09`09`09X X`09tt_chan`09`09`09`09`09X X X Return Codes: X X`09Code`09 `09`09Reason X`09----`09`09`09------ X`09none X X Termination Codes: X X`09Code`09`09`09Reason X`09----`09`09`09------ X`09none X X**************************************************************************** V**** X**************************************************************************** V***/ X Xstatic void xon_ast(ULONG param) X X`7B`09/*** xon_ast ***/ X`09`09`09`09`09/******** LOCAL VARIABLES ********/ Xstatic`09 ULONG`09 status;`09`09/* return code status holder`09 */ Xstatic`09 USHORT`09 xon_char;`09`09/* char to write to the TTY`09 */ Xstatic`09 IOSB_DEF iosb;`09`09`09/* I/O status block`09`09 */ X X X X /* write the XON char to the TTY */ X X xon_char = (USHORT) param >> 16;`09/* shift to get the character`09 V */ X/* `20 X status = SYS$QIOW(0,tt_chan,IO$_WRITEVBLK,&iosb,0,0,xon_char,2,0,0,0,0); X X if(status != SS$_NORMAL) X return(status); X*/ X /* requeue the AST */ X X status = SYS$QIOW(0,py_chan,IO$_SETMODE,&iosb,0,0,xon_ast,0,0,1,0,0); X X if(status != SS$_NORMAL) X LIB$STOP(JLG_CANT_REQUEUE,1L,"XON AST QIO to PY device"); X X return; X X`7D`09/*** xon_ast ***/ X`0C X/*************************************************************************** V**** X**************************************************************************** V**** X X Function:`09xoff_ast X X Purpose:`09Called when XOFF is detected on the PTY. X X Formal Parameters: X X`09Name`09`09`09Description X`09----`09`09`09----------- X`09param`09`09`09contains character from PTY X X Global variables: X X`09Name`09`09`09Examine/Modify/Use/Read/Write X`09----`09`09`09----------------------------- X`09py_chan`09`09`09`09`09X X`09tt_chan`09`09`09`09`09X X X Return Codes: X X`09Code`09 `09`09Reason X`09----`09`09`09------ X`09none X X Termination Codes: X X`09Code`09`09`09Reason X`09----`09`09`09------ X`09none X X**************************************************************************** V**** X**************************************************************************** V***/ X Xstatic void xoff_ast(ULONG param) X X`7B`09/*** xoff_ast ***/ X`09`09`09`09`09/******** LOCAL VARIABLES ********/ Xstatic`09 ULONG`09 status;`09`09/* return code status holder`09 */ Xstatic`09 USHORT`09 xoff_char;`09`09/* char to write to the TTY`09 */ Xstatic`09 IOSB_DEF iosb;`09`09`09/* I/O status block`09`09 */ X X X status = SYS$QIOW(0,py_chan,IO$_SETMODE,&iosb,0,0,xon_ast,0,0,2,0,0); X X if(status != SS$_NORMAL) X LIB$STOP(JLG_CANT_REQUEUE,1L,"XOFF AST QIO to PY device"); X X return; X X`7D`09/*** xoff_ast ***/ X`0C X/*************************************************************************** V**** X**************************************************************************** V**** X X Function:`09write_py X X Purpose:`09Write data from TTY to the PTY X X Formal Parameters: X X`09Name`09`09`09Description X`09----`09`09`09----------- X`09channel`09`09`09channel to write to X`09buffer`09`09`09buffer to write X`09length`09`09`09length of buffer to write`09 X X Global variables: X X`09Name`09`09`09Examine/Modify/Use/Read/Write X`09----`09`09`09----------------------------- X`09none X X Return Codes: X X`09Code`09 `09`09Reason X`09----`09`09`09------ X`09none X X Termination Codes: X X`09Code`09`09`09Reason X`09----`09`09`09------ X`09none X X**************************************************************************** V**** X**************************************************************************** V***/ X Xstatic ULONG write_py(short channel,char *buffer,ULONG length) X X`7B`09/*** write_py ***/ X`09`09`09`09`09/******** LOCAL VARIABLES ********/ Xstatic`09 ULONG`09 status;`09`09/* return code status holder`09 */ Xstatic`09 IOSB_DEF iosb;`09`09`09/* I/O status block for writing`09 */ X X X status = SYS$QIOW(0,channel,IO$_WRITEVBLK,&iosb,0,0,buffer,length,0,0,0,0 V); X X if(status != SS$_NORMAL && status != SS$_DATAOVERUN) X `7B X LIB$SIGNAL(status); X return(status); X `7D X X if(iosb.status != SS$_NORMAL && iosb.status != SS$_DATAOVERUN) X `7B X LIB$SIGNAL(iosb.status); X return(iosb.status); X `7D X X return(SS$_NORMAL); X X`7D`09/*** write_py ***/ X`0C X/*************************************************************************** V**** X**************************************************************************** V**** X X Function:`09write_tt X X Purpose:`09Write to the TTY X X Formal Parameters: X X`09Name`09`09`09Description X`09----`09`09`09----------- X`09channel`09`09`09channel to write to X`09buffer`09`09`09buffer to write X`09length`09`09`09length of buffer to write`09 X X Global variables: X X`09Name`09`09`09Examine/Modify/Use/Read/Write X`09----`09`09`09----------------------------- X`09none X X Return Codes: X X`09Code`09 `09`09Reason X`09----`09`09`09------ X`09status`09`09`09from SYS$QIO or IOSB of write to TTY X X Termination Codes: X X`09Code`09`09`09Reason X`09----`09`09`09------ X`09none X X**************************************************************************** V**** X**************************************************************************** V***/ X Xstatic ULONG write_tt(short channel,char *buffer,ULONG length) X X`7B`09/*** write_tt ***/ X`09`09`09`09`09/******** LOCAL VARIABLES ********/ Xstatic`09 ULONG`09 status;`09`09/* return code status holder`09 */ Xstatic`09 IOSB_DEF iosb;`09`09`09/* I/O status block`09`09 */ X X X status = SYS$QIOW(0,channel,IO$_WRITEVBLK,&iosb,0,0,buffer,length,0,0,0,0 V); X X if(status != SS$_NORMAL) X return(status); X X if(iosb.status != SS$_NORMAL) X return(iosb.status); X X /* make sure the right number of characters were written */ X X if((ULONG) iosb.count != length) X return(SS$_NOWRT);`09`09/* didn't write the right amount */ X X return(SS$_NORMAL); X X`7D`09/*** write_tt ***/ X`0C X/*************************************************************************** V**** X**************************************************************************** V**** X X Function:`09get_stamp X X Purpose:`09Create the time stamp string. X X Formal Parameters: X X`09Name`09`09`09Description X`09----`09`09`09----------- X`09stamp_buf`09`09where to put time stamp string X X Global variables: X X`09Name`09`09`09Examine/Modify/Use/Read/Write X`09----`09`09`09----------------------------- X`09none X X Return Codes: X X`09Code`09 `09`09Reason X`09----`09`09`09------ X`09stamp_buf`09`09pointer to where time stamp is X X Termination Codes: X X`09Code`09`09`09Reason X`09----`09`09`09------ X`09status`09`09`09return code from SYS$ASCTIM if it fails X X**************************************************************************** V**** X**************************************************************************** V***/ X Xstatic char *get_stamp(char *stamp_buf) X X`7B`09/*** get_stamp ***/ X`09`09`09`09`09/******** LOCAL VARIABLES ********/ Xstatic`09 ULONG`09 status;`09`09/* return code status holder`09 */ Xstatic`09 char`09 time_buf`5BTIME_MAX+1`5D;`09/* array for holding time str Ving */ Xstatic $DESCRIPTOR(time_d,time_buf);`09/* for getting time value`09 */ X X X status = SYS$ASCTIM(0,&time_d,0,0); X X if(status != SS$_NORMAL) X LIB$STOP(status); X X time_buf`5Btime_d.dsc$w_length`5D = '\0'; X cat(stamp_buf,"`5B",time_buf,"`5D"); X X return(stamp_buf);`09`09`09/* return pointer to time stamp str. */ X X`7D`09/*** get_stamp ***/ X`0C X/*************************************************************************** V**** X**************************************************************************** V**** X X Function:`09write_exact X X Purpose:`09Used for writing to the log file when the /EXACT qualifier X`09`09was specified. X X Formal Parameters: X X`09Name`09`09`09Description X`09----`09`09`09----------- X`09buf`09`09`09buffer to be written X`09flags`09`09`09run-time and computed flags X`09length`09`09`09length of buffer to be written X X Global variables: X X`09Name`09`09`09Examine/Modify/Use/Read/Write X`09----`09`09`09----------------------------- X`09stamp_buf`09`09`09`09X`09 X X X Return Codes: X X`09Code`09 `09`09Reason X`09----`09`09`09------ X`09none X X Termination Codes: X X`09Code`09`09`09Reason X`09----`09`09`09------ X`09none X X**************************************************************************** V**** +-+-+-+-+-+-+-+- END OF PART 2 +-+-+-+-+-+-+-+-