-+-+-+-+-+-+-+-+ START OF PART 3 -+-+-+-+-+-+-+-+ X /* queue an asynchronous read to the PTY; this will handle all output, X * writing to both the log file and the TTY X */ X X status = SYS$QIO(py_efn,py_chan,IO$_READVBLK,&py_read_iosb,&py_ast,0,py_b Vuf, X`09`09 PY_BUF_MAX,0,0,0,0); X`09`09 `20 X if(!(status & SS$_NORMAL)) X `7B X kill_log(); X mess_d.dsc$a_pointer = "read on PY device (in log_session())"; X mess_d.dsc$w_length = (USHORT) strlen(mess_d.dsc$a_pointer); X LIB$STOP(JLG_CANT_QUEUE,1L,&mess_d); X `7D X X /* wait for the event flag to be set; this is important but I can't X * take credit for it; from the README file for PHOTO: X * X * PHOTO running on a multi-processor VAX (e.g. VAX 8800) with X * VAX/VMS Version 5.x runs into a problem due to SMP which allows the X * subprocess to get MUCH more CPU time then was previously possible X * without SMP. The subprocess generates hangups very rapidly and on a X * lightly loaded system it will generate a hangup between the time X * "enable_hangups" is turned on and when begin_session posts a X * QIOW(IO$_READVBLK) on py_chan. This causes PHOTO to exit as if the X * subprocess had logged out! X *`20 X * PHOTO has been fixed to issue a QIO instead of QIOW followed by X * WAITFR and "enable_hangups" is now turned on after the first QIO to X * py_chan in begin_session (used to be turned on in main). It has been X * tested on a VAX 8800 with VAX/VMS Version 5.0-2. X *`20 X * `09Michael Kimura`09`09Internet: mnk%draco@hac2arpa.hac.com X * `09Hughes Aircraft Co.`09BITnet: mnk@draco.hac.com X *`20 X * `09January 31, 1989 X */ X X status = SYS$WAITFR(py_efn); X X if(!(status & SS$_NORMAL)) X `7B X kill_log(); X LIB$STOP(status); X `7D X X flags.hangups = TRUE;`09`09/* enable hangups on the PTY`09 */ X X for(;;) X `7B X /* read from the TTY */ X X status = SYS$QIOW(tt_r_efn,tt_chan,IO$_READVBLK,&tt_read_iosb,0,0,tt_b Vuf, X`09`09`091,0,&term_block,0,0); X X if(!(status & SS$_NORMAL) `7C`7C !(tt_read_iosb.status & SS$_NORMAL)) X `7B X`09 kill_log(); X`09 mess_d.dsc$a_pointer = "read on TT device"; X`09 mess_d.dsc$w_length = (USHORT) strlen(mess_d.dsc$a_pointer); X`09 LIB$STOP(JLG_CANT_QUEUE,1L,&mess_d); X `7D X X /* Stall for 50 milli-seconds waiting for more data */ X X status = SYS$SETIMR(wait_efn,&bintim,0,0); X X if(!(status & SS$_NORMAL)) X `7B X`09 kill_log(); X`09 LIB$STOP(status); X `7D X X status = SYS$WAITFR(wait_efn); X X if(!(status & SS$_NORMAL)) X `7B X`09 kill_log(); X`09 LIB$STOP(status); X `7D X X /* get the rest of it */ X X status = SYS$QIOW(tt_r_efn,tt_chan,IO$_READVBLK`7CIO$M_TIMED,&tt_read_ Viosb, X`09`09`090,0,&tt_buf`5B1`5D,sizeof(tt_buf)-1,0,&term_block,0,0); X X if(!(status & SS$_NORMAL)) X`09 LIB$STOP(status); X X if(tt_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(tt_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) - 1); X`09 else X`09 write_tt(tt_chan,log_enable,(ULONG) sizeof(log_enable) - 1); X `20 X`09 write_py(py_chan,cr,(ULONG) tt_read_iosb.count + 1,&py_write_iosb); X`09 flags.logging = !flags.logging; X`09 flags.verify = FALSE; X`09 `7D X`09 else if(tt_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, X`09`09`09(ULONG) sizeof(stamp_disable) - 1); X`09 else X`09 write_tt(tt_chan,stamp_enable,(ULONG) sizeof(stamp_enable) - 1); X X`09 write_py(py_chan,cr,(ULONG) tt_read_iosb.count + 1,&py_write_iosb); X`09 flags.time_stamp = !flags.time_stamp; X`09 `7D X `7D X X /* write it to the PTY */ X X status = write_py(py_chan,tt_buf,(ULONG) tt_read_iosb.count + 1, X`09`09`09&py_write_iosb); X X if(!(status & SS$_NORMAL)) X `7B X kill_log(); X LIB$STOP(JLG_CANT_WRITE,1L,"to PY device"); X `7D X `7D X X return;`09`09`09`09/* should never get here`09 */ X X`7D`09/*** log_session ***/ X`0C X/*************************************************************************** V**** X**************************************************************************** V**** X X Function:`09ask_disposition X X Purpose:`09Ask the user what should be done with the log file and do X`09`09it. X X Formal Parameters: X X`09Name`09`09`09Description X`09----`09`09`09----------- X`09filename`09`09name of log file X`09stage_dir`09`09staging directory for log files X`09flags`09`09`09computed flags X`09args`09`09`09run-time arguments X X Global variables: X X`09Name`09`09`09Examine/Modify/Use/Read/Write X`09----`09`09`09----------------------------- X`09disp_failed`09`09`09 X 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`09status X X**************************************************************************** V**** X**************************************************************************** V***/ X Xstatic void ask_disposition(char *logfile,char *stage_dir,FLAG_DEF *flags, X`09`09`09 ARG_DEF *args) X X`7B`09/*** ask_disposition ***/ X`09`09`09`09`09/******** LOCAL VARIABLES ********/ X`09 ULONG`09 status,`09`09/* return code status holder`09 */ X`09`09 disable_mask;`09`09/* for disabling control-Y at DCL */ X`09 char`09 *save_ptr;`09`09/* saved logfile name`09`09 */ X`09 USHORT`09 done,`09`09`09/* loop control variable`09 */ X`09`09 length;`09`09/* length of read from my_gets`09 */ X`09 char`09 ch`5B10`5D;`09`09/* character read in`09`09 */ Xstatic $DESCRIPTOR(in_d,"SYS$INPUT");`09/* input channel descriptor`09 V */ X X X disable_mask = LIB$M_CLI_CTRLY;`09/* tell DCL to ignore control-Y`09 V */ X X status = LIB$DISABLE_CTRL(&disable_mask); X X if(!(status & SS$_NORMAL)) X `7B X delete(logfile); X LIB$SIGNAL(status); X `7D X/* X status = SYS$ASSIGN(&tt_d,&tt_chan,0,0); X X if(!(status & SS$_NORMAL)) X `7B X delete(logfile); X LIB$STOP(status); X `7D X*/ X X if(flags->verify) X my_puts("\n\nYour log file is VERIFIED."); X else X my_puts("\n\nYour log file is UNVERIFIED."); X X done = FALSE; X status = SUCCESS;`09`09`09/* just to be sure`09`09 */ X X do X `7B X if(args->print) X`09 ch`5B0`5D = 'P';`09`09`09/* user specified /PRINT`09 */ X else if(args->mail) X`09 ch`5B0`5D = 'M'; X else if(args->save) X`09 ch`5B0`5D = 'S'; X else X `7B X`09 my_puts("\n\nDo you want to:"); X`09 my_puts(" Print your log file? Enter p"); X`09 my_puts(" Save log to your area? Enter s"); X`09 my_puts(" Mail notification of log to someone? Enter m"); X`09 my_puts(" Delete your log file? Enter d\n"); X`09 status = my_gets(tt_chan,&ch," Your choice `5Bdefault is d`5D ? ", X`09`09`09 &length,sizeof(ch) - 1); X`09 squeeze_str(ch); X X`09 if(status == CANCEL) X`09 ch`5B0`5D = 'D';`09`09/* `5EC or `5EY`09`09`09 */ X`09 else if(ch`5B0`5D == CARRIAGE_RETURN `7C`7C ch`5B0`5D == '\0') X`09 ch`5B0`5D = 'D'; `09`09/* default is delete`09`09 */ X`09 else if((status == SUCCESS && ch`5B1`5D != '\0') `7C`7C status == FAILUR VE) X`09 ch`5B0`5D = '\0';`09`09/* more than one char; error`09 */ X`09 else X`09 ch`5B0`5D = _toupper(ch`5B0`5D); X `7D X X switch(ch`5B0`5D) X `7B X`09 case('P'): X X`09 /* user wants it printed off */ X X`09 status = print_log(logfile,tt_chan,flags->verify); X X`09 if(status == FAILURE) X`09 `7B X`09 my_puts("\n\7*ERROR* Cannot print log file"); X`09 args->print = FALSE;`09/* start over`09`09`09 */ X`09 disp_failed = TRUE;`09/* ensure user is prompted next time */ X`09 `7D X`09 else if(status == CANCEL) X`09 `7B X`09 /* user entered `5EC or `5EY; delete the log file and get out */ X X`09 delete(logfile); X`09 my_puts("\nLog file deleted.\n"); X`09 done = TRUE; X`09 `7D X else X`09 `7B X`09 done = TRUE;`09`09/* no need to delete log file here */ X`09 `7D X X`09 break; X X`09 case('S'): X X`09 status = save_log(logfile,tt_chan); X X`09 if(status == FAILURE) X`09 `7B X`09 my_puts("\n\7*ERROR* Cannot save log file"); X`09 args->save = FALSE;`09/* start over`09`09`09 */ X`09 disp_failed = TRUE;`09/* ensure user is prompted next time */ X`09 `7D X`09 else if(status == CANCEL) X`09 `7B X`09 /* user entered `5EC or `5EY; delete the log file and get out */ X X`09 delete(logfile); X`09 my_puts("\nLog file deleted.\n"); X`09 done = TRUE; X`09 `7D X`09 else X`09 `7B X`09 done = TRUE; X`09 delete(logfile); X`09 `7D X X`09 break; X X`09 case('D'): X X`09 /* we really don't care too much if delete() fails since X`09 * the batch job will kill it anyway; besides, it should never X`09 * fail X`09 */ X X`09 delete(logfile); X`09 my_puts("\nLog file deleted.\n"); X`09 done = TRUE; X X`09 break; X X`09 case('M'): X X`09 status = mail_log(logfile,stage_dir,tt_chan,flags->verify); X X`09 if(status == FAILURE) X`09 `7B X`09 my_puts("\n\7*ERROR* Cannot mail log file notification"); X`09 args->mail = FALSE; X`09 disp_failed = TRUE;`09/* ensure user is prompted next time */ X`09 `7D X`09 else if(status == CANCEL) X`09 `7B X`09 /* user entered `5EC or `5EY; delete the log file and get out */ X X`09 delete(logfile); X`09 my_puts("\nLog file deleted.\n"); X`09 done = TRUE; X`09 `7D X`09 else if(status == SUCCESS) X`09 `7B X`09 done = TRUE; X`09 delete(logfile); X`09 `7D X X`09 break; X X`09 default: X X`09 /* bad option specified; try again */ X X`09 my_puts("\n\7Invalid option. Try again."); X`09 break; X `7D X `7D X while(!done); X X status = LIB$ENABLE_CTRL(&disable_mask); X X if(!(status & SS$_NORMAL)) X LIB$STOP(status); X X return; X X`7D`09/*** ask_disposition ***/ X`0C X/*************************************************************************** V**** X**************************************************************************** V**** X X Function:`09get_file X X Purpose:`09Create a filename and open the log file. X X Formal Parameters: X X`09Name`09`09`09Description X`09----`09`09`09----------- X`09filename`09`09name of log file X`09log_dir`09`09`09directory where log files live X`09log_fab`09`09`09FAB for log file X`09log_rab`09`09`09RAB for log file X`09log_xabpro`09`09XABPRO for log file X`09args`09`09`09command-line arguments X`09flags`09`09`09program flags 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 system calls X X**************************************************************************** V**** X**************************************************************************** V***/ X Xstatic ULONG get_file(char *filename,char *log_dir,struct FAB *log_fab, X`09`09 struct RAB *log_rab,struct XABPRO *log_xabpro, X`09`09 ARG_DEF *args,FLAG_DEF *flags) X X`7B`09/*** get_file ***/ X`09`09`09`09`09/******** LOCAL VARIABLES ********/ X`09 ULONG`09 status;`09`09/* return code status holder`09 */ Xstatic`09 union`09 prvdef _align(longword) privs; X X X#ifdef PHOTO_MODE X X strcpy(filename,"JOBLOG.LOG"); X X#else X X /* turn on SYSPRV so we can write to the log file area */ X X privs.prv$v_sysprv = ON; X status = SYS$SETPRV(ON,&privs,FALSE,NULL); X X if(!(status & SS$_NORMAL)) X return(status); X X X strcpy(filename,"JOBXXXXXX");`09/* make our own log file name`09 */ X X if(mktemp(filename) == NULL) X `7B X my_puts("JOBLOG -- cannot create log file name\n"); X SYS$EXIT(); X `7D X X strcat(filename,".LOG"); X strcpy(flags->filename,filename);`09/* save filename for later`09 */ X strins(filename,log_dir,0);`09`09/* add secure directory name`09 */ X X#endif X X *log_fab = cc$rms_fab; X *log_rab = cc$rms_rab; X *log_xabpro = cc$rms_xabpro; X X /* if we were doing exact logging, we would have a test here for it and X * we would open the log file appropriately; since exact logging is such X * a pain in the a*s, we'll just assume everything is "unexact" (is that X * even a word?) X */ X X log_fab->fab$l_fna = filename;`09/* name of log file`09`09 */ X log_fab->fab$b_fns = (UCHAR) strlen(filename); X log_fab->fab$l_fop = FAB$M_SUP;`09/* supersede old version of log file * V/ X log_fab->fab$l_fop = FAB$M_MXV;`09/* supersede old version of log file * V/ X log_fab->fab$b_org = FAB$C_SEQ;`09/* sequential access`09`09 */ X log_fab->fab$b_rat = FAB$M_CR;`09/* CR attributes for records`09 */ X log_fab->fab$b_rfm = FAB$C_VAR;`09/* variable-length records`09 */ X log_fab->fab$b_shr = FAB$M_NIL;`09/* don't allow sharing`09`09 */ X log_fab->fab$l_xab = log_xabpro;`09/* for setting protection on close V */ X X log_rab->rab$l_fab = log_fab;`09/* FAB for log file`09`09 */ X log_rab->rab$b_rac = RAB$C_SEQ;`09/* sequential access`09`09 */ X log_rab->rab$l_rop = RAB$M_WBH; 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 V `7C 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$CREATE(log_fab); X X if(!(status & RMS$_NORMAL)) X return(status); X X status = SYS$CONNECT(log_rab); X X if(!(status & RMS$_NORMAL)) X `7B X kill_log(); X return(status); X `7D X X#ifndef PHOTO_MODE X X /* now that the file is open, turn SYSPRV off again to be safe */ X X status = SYS$SETPRV(OFF,&privs,FALSE,NULL); X X if(!(status & SS$_NORMAL)) X return(status); X X#endif X X return(RMS$_NORMAL); X X`7D`09/*** get_file ***/ X`0C X/*************************************************************************** V**** X**************************************************************************** V**** X X Function:`09welcome X X Purpose:`09Write the welcome message to the tty. X X Formal Parameters: X X`09Name`09`09`09Description X`09----`09`09`09----------- X`09args`09`09`09run-time arguments 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 system calls X X**************************************************************************** V**** X**************************************************************************** V***/ X Xstatic void welcome(ARG_DEF *args) X X`7B`09/*** welcome ***/ X`09`09`09`09`09/******** LOCAL VARIABLES ********/ X`09 USHORT`09 i = 0;`09`09/* array index`09`09`09 */ Xstatic`09 char`09 *text`5B`5D = `7B`09`09/* stuff to say upon entry to JOBL VOG */ X`7B" "`7D, X`7B"Welcome to JOBLOG! Please try not to use full-screen editors or other"` V7D, X`7B"screen-oriented programs as they tend not to be logged correctly."`7D, X`7B" "`7D, X`7B"Also, please don't use SET HOST as it causes problems with JOBLOG log"`7 VD, X`7B"files."`7D, X`7B" "`7D, X`7B"To exit JOBLOG, enter LOGOUT."`7D, X`7B" "`7D, X`7B""`7D`7D; `20 X X X#ifndef PHOTO_MODE X X if(!args->expert) X while(*text`5Bi`5D != '\0') X`09 my_puts(text`5Bi++`5D); X X#endif X X my_puts("\nJOBLOG started.\n");`09`09/* mandatory startup message`09 V */ X return; X X`7D`09/*** welcome ***/ X`0C X/*************************************************************************** V**** X**************************************************************************** V**** X X Function:`09copy_file X X Purpose:`09Make a copy of a file. X X Formal Parameters: X X`09Name`09`09`09Description X`09----`09`09`09----------- X`09source`09`09`09file to be copied X`09dest`09`09`09where copy is to go 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`09SUCCESS X`09FAILURE X X**************************************************************************** V**** X**************************************************************************** V***/ X Xstatic ULONG copy_file(char *source,char *dest) X X`7B`09/*** copy_file ***/ X`09`09`09`09`09/******** LOCAL VARIABLES ********/ X`09 ULONG`09 status,`09`09/* return code status holder`09 */ X`09`09 status2,`09`09/* some secondary return codes`09 */ X`09`09 status3, X`09`09 status4; X`09 char `09 in_buf`5BIN_BUF_MAX+1`5D;`09/* buffer for reading/writing`09 V */ Xstruct`09 FAB`09 in_fab,`09`09/* FAB's for input and output files */ X`09`09 out_fab; Xstruct`09 RAB`09 in_rab,`09`09/* RAB's for input and output files */ X`09`09 out_rab; X X X in_fab = cc$rms_fab; `09`09/* initialize all of the RMS blocks */ X in_rab = cc$rms_rab; X out_rab = cc$rms_rab; X X in_fab.fab$b_fac = FAB$M_BIO `7C`09/* block I/O for input file`09 */ X`09`09 FAB$M_GET; X `20 X in_fab.fab$l_fna = source; X in_fab.fab$b_fns = (UCHAR) strlen(source); X in_fab.fab$b_fac = FAB$M_BIO `7C FAB$M_GET; X X in_rab.rab$l_fab = &in_fab;`09`09/* pointer to input FAB`09`09 */ X in_rab.rab$b_rac = RAB$C_SEQ;`09/* sequential access for copy`09 */ X in_rab.rab$w_usz = IN_BUF_MAX;`09/* length of input buffer`09 */ X in_rab.rab$l_ubf = in_buf;`09`09/* pointer to buffer`09`09 */ X X out_rab.rab$l_fab = &out_fab;`09/* pointer to input FAB`09`09 */ X out_rab.rab$b_rac = RAB$C_SEQ;`09/* sequential access for copy`09 */ X out_rab.rab$w_usz = IN_BUF_MAX; `09/* length of output buffer`09 */ X out_rab.rab$l_rbf = in_buf; `09`09/* pointer to buffer`09`09 */ X X /* open the input file */ X X status = SYS$OPEN(&in_fab); X X if(!(status & RMS$_NORMAL)) X `7B X SYS$CLOSE(&in_fab); X return(FAILURE); X `7D X X /* connect the input file's RMS blocks */ X X status = SYS$CONNECT(&in_rab); X X if(!(status & RMS$_NORMAL)) X `7B X SYS$CLOSE(&in_fab); X return(FAILURE); X `7D X X out_fab = in_fab; `09`09`09/* copy the input file's FAB`09 */ X out_fab.fab$w_ifi = 0; `09`09/* reset this!`09`09`09 */ X out_fab.fab$b_fac = FAB$M_BIO `7C FAB$M_PUT; X X out_fab.fab$l_fna = dest; X out_fab.fab$b_fns = (UCHAR) strlen(dest); X X /* open the output file */ X X status = SYS$CREATE(&out_fab); X X if(!(status & RMS$_NORMAL)) X `7B X SYS$CLOSE(&out_fab); X SYS$CLOSE(&in_fab);`20 X return(FAILURE); X `7D X X /* connect the output file's RMS blocks */ X X status = SYS$CONNECT(&out_rab); X X if(!(status & RMS$_NORMAL)) X `7B X SYS$CLOSE(&out_fab); X SYS$CLOSE(&in_fab); X return(FAILURE); X `7D X X /* now copy the input file to the output file */ X X status = SYS$READ(&in_rab); X status2 = RMS$_NORMAL;`09`09/* have to lie to fool the loop`09 */ X X while((status == RMS$_NORMAL) && (status2 == RMS$_NORMAL)) X `7B X out_rab.rab$w_rsz = in_rab.rab$w_rsz; X status2 = SYS$WRITE(&out_rab); X status = SYS$READ(&in_rab); X `7D X X /* close both of the files */ X X status3 = SYS$CLOSE(&in_fab); X status4 = SYS$CLOSE(&out_fab); X X /* did the loop terminate properly? if not, delete the output file and X * scream at the user X */ X X if(status != RMS$_EOF `7C`7C status2 != RMS$_NORMAL `7C`7C status3 != RMS V$_NORMAL `7C`7C X status4 != RMS$_NORMAL) X return(FAILURE); X X return(SUCCESS); X X`7D`09/*** copy_file ***/ X`0C X/*************************************************************************** V**** X**************************************************************************** V**** X X Function:`09print_log X X Purpose:`09Print the log file (verified or nonverified) to the line X`09`09printer. The /DELETE qualifier is passed to the print job X`09`09so that the log file is deleted after printing. X X Formal Parameters: X X`09Name`09`09`09Description X`09----`09`09`09----------- X`09logfile`09`09`09name of log file X`09channel`09`09`09TTY channel X`09verify_flag`09`09TRUE = verified LPT copy X X Global variables: X X`09Name`09`09`09Examine/Modify/Use/Read/Write X`09----`09`09`09----------------------------- X`09disp_failed`09`09 X X X Return Codes: X X`09Code`09 `09`09Reason X`09----`09`09`09------ X`09SUCCESS X`09FAILURE X`09CANCEL X X**************************************************************************** V**** X**************************************************************************** V***/ X Xstatic ULONG print_log(char *logfile,USHORT channel,UCHAR verify_flag) X X`7B`09/*** print_log ***/ X `09`09`09`09`09/******** LOCAL VARIABLES ********/ X`09 ULONG`09 status;`09`09/* return code status holder`09 */ X`09 long`09 entry_num;`09`09/* entry number in queue`09 */ X`09 USHORT`09 length;`09`09/* length of status string`09 */ X`09 IOSB_DEF iosb;`09`09`09/* I/O status block`09`09 */ X`09 char`09 def_queue`5BQUEUE_MAX+1`5D, X`09`09 queue`5BQUEUE_MAX+1`5D,`09/* queue to use for call`09 */ X`09`09 prompt`5BBUFSIZ`5D, X`09`09 status_str`5BSTATUS_STR_MAX+1`5D; X`09 $DESCRIPTOR(print_d,"PRINT"); X`09 $DESCRIPTOR(table_d,"LNM$PROCESS"); X`09 $DESCRIPTOR(table2_d,"LNM$SYSTEM"); X`09 $DESCRIPTOR(queue_d,queue); X`09 $DESCRIPTOR(sys_print_d,"SYS$PRINT"); Xstatic`09 char`09 *account = "VERIFY", X`09`09 *account2 = "UNVERIFY", X`09`09 *job_name = "VERIFIED_JOBLOG", X`09`09 *job_name2 = "UNVERIFIED_JOBLOG", X`09`09 *verified = "Verified JOBLOG listing", X`09`09 *unverified = "Unverified JOBLOG listing"; Xstatic`09 ITM_LST items`5B`5D = `7B`09`09/* item list for stuff we want to V do */ X`7B0,SJC$_ACCOUNT_NAME,0L,0L`7D, X`7B0,SJC$_FILE_SPECIFICATION,0L,0L`7D, X`7B0,SJC$_DELETE_FILE,0L,0L`7D, X`7B0,SJC$_ENTRY_NUMBER_OUTPUT,0L,0L`7D, X`7B0,SJC$_JOB_NAME,0L,0L`7D, X`7B0,SJC$_JOB_STATUS_OUTPUT,0L,0L`7D, X`7B0,SJC$_NOTE,0L,0L`7D, X`7B0,SJC$_NOTIFY,0L,0L`7D, X`7B0,SJC$_QUEUE,0L,0L`7D, X`7B0,0,0L,0L`7D`7D, X`09`09 items2`5B`5D = `7B`09`09/* items obtained during translation */ X`7B0,LNM$_STRING,NULL,NULL`7D,`09`09/* things are filled in below`09 */ X`7B0,0,NULL,NULL`7D`7D; X X `20 X status = CLI$GET_VALUE(&print_d,&queue_d,&length); X X if(status == SS$_NORMAL && !disp_failed) X queue`5Blength`5D = '\0';`09`09/* use it`09`09`09 */ X else X `7B X /* get the current default print queue from SYS$PRINT */ X X items2`5B0`5D.buf_addr = def_queue; X items2`5B0`5D.ret_len = &length; X items2`5B0`5D.buf_len = sizeof(def_queue); X length = 0; X X /* check the user's process table first */ X X status = SYS$TRNLNM(0L,&table_d,&sys_print_d,0,&items2); X X if(status != SS$_NORMAL `7C`7C length == 0) X `7B X`09 status = SYS$TRNLNM(0L,&table2_d,&sys_print_d,0,&items2); X X`09 if(status != SS$_NORMAL `7C`7C length == 0) X`09 `7B X`09 my_puts("\n\7*ERROR* SYS$PRINT not defined.\n"); X`09 return(FAILURE); X`09 `7D X `7D X X my_puts(" "); X X def_queue`5Blength`5D = '\0';`09`09/* make it a string`09`09 */ X cat(prompt,"Which printer did you want to use `5Bdefault is ",def_queu Ve, X`09 "`5D? "); X X status = my_gets(channel,queue,prompt,&length,sizeof(queue) - 1); X X if(status == FAILURE) X`09 return(FAILURE); X else if(status == CANCEL) X`09 return(CANCEL); X X /* input is ok if we get here */ X X queue`5Blength`5D = '\0'; X str_pref_trim(queue); X str_post_trim(queue); X X if(queue`5B0`5D == '\0') X`09 strcpy(queue,def_queue);`09/* use the default`09`09 */ X `7D X X /* set up the item list so we can print */ X X items`5B1`5D.buf_len = strlen(logfile); X items`5B1`5D.buf_addr = logfile; X items`5B3`5D.buf_len = sizeof(long); X items`5B3`5D.buf_addr = &entry_num; X items`5B5`5D.buf_len = STATUS_STR_MAX; X items`5B5`5D.buf_addr = status_str; X items`5B5`5D.ret_len = &length; X items`5B8`5D.buf_len = strlen(queue); X items`5B8`5D.buf_addr = queue; X X if(verify_flag) X `7B X items`5B0`5D.buf_len = strlen(account); X items`5B0`5D.buf_addr = account; X items`5B4`5D.buf_len = strlen(job_name); X items`5B4`5D.buf_addr = job_name; X items`5B6`5D.buf_len = strlen(verified); X items`5B6`5D.buf_addr = verified; X `7D X else X `7B X items`5B0`5D.buf_len = strlen(account2); X items`5B0`5D.buf_addr = account2; X items`5B4`5D.buf_len = strlen(job_name2); X items`5B4`5D.buf_addr = job_name2; X items`5B6`5D.buf_len = strlen(unverified); X items`5B6`5D.buf_addr = unverified; X `7D X X /* now try to queue the log file to the printer */ X X status = SYS$SNDJBCW(0,SJC$_ENTER_FILE,0L,&items,&iosb,0L,0L); X X if(!(status & SS$_NORMAL)) X return(FAILURE); X X if(iosb.status != SS$_NORMAL) X `7B X LIB$SIGNAL(iosb.status); X return(FAILURE); X `7D X X /* report the status line to the user */ X X status_str`5Blength`5D = '\0';`09`09/* make status message a string`09 V */ X my_puts(" "); X my_puts(status_str); X X return(SUCCESS); X X`7D`09/*** print_log ***/ X`0C X/*************************************************************************** V**** X**************************************************************************** V**** X X Function:`09mail_log X X Purpose:`09Mail notification of a verified JOBLOG to the specified user X`09`09and copy the log file to JOBLOG staging area. The history X`09`09file must be updated also. X X Formal Parameters: X X`09Name`09`09`09Description X`09----`09`09`09----------- X`09logfile`09`09`09name of log file X`09stage_dir`09`09staging directory for log files X`09channel`09`09`09TTY channel X`09verify`09`09`09TRUE if JOBLOG still verified X X Global variables: X X`09Name`09`09`09Examine/Modify/Use/Read/Write X`09----`09`09`09----------------------------- X`09disp_failed`09`09`09 X X X Return Codes: X X`09Code`09 `09`09Reason X`09----`09`09`09------ X`09SUCCESS X`09FAILURE X`09NO_INPUT X X**************************************************************************** V**** X**************************************************************************** V***/ X Xstatic ULONG mail_log(char *logfile,char *stage_dir,USHORT channel,UCHAR ver Vify) X X`7B`09/*** mail_log ***/ X`09`09`09`09`09/******** LOCAL VARIABLES ********/ X`09 char`09 *username,`09`09/* name of user mailing the notice */ X`09`09 *verify_ptr,`09`09/* used for making mail message`09 */ X`09`09 *verify_ch;`09`09/* used for making filename`09 */ X`09 ULONG`09 status,`09`09/* return code status holder`09 */ X`09`09 status2;`09`09/* secondary return code holder`09 */ X`09 USHORT`09 length;`09`09/* length of string from LIB$GETJPI() */ X`09 time_t`09 time_val;`09`09/* value from time()`09`09 */ X`09 IOSB_DEF iosb;`09`09`09/* for QIO's`09`09`09 */ X`09 char`09 tempfile`5BNAM$C_MAXRSS+1`5D, X`09`09 filename`5BNAM$C_MAXRSS+1`5D, X`09`09 out_buf`5BBUFSIZ`5D,`09/* formatting and I/O buffer`09 */ X`09`09 account`5BACCOUNT_MAX+1`5D, X`09`09 recipient`5BUSERNAME_MAX+1`5D, X`09`09 command`5BCOMMAND_MAX+1`5D, X`09`09 prompt`5B`5D = X`09`09 `7B"Who do you want to mail the log file notification to? "`7D; Xstruct`09 tm`09 *time_ptr;`09`09/* pointer to localtime() structure */ Xstruct`09 FAB`09 out_fab;`09`09/* for creating mail message file */ Xstruct`09 RAB`09 out_rab; X$DESCRIPTOR(null_d,"NL:"); X$DESCRIPTOR(account_d,account); X$DESCRIPTOR(command_d,command); X$DESCRIPTOR(filename_d,filename); X$DESCRIPTOR(recipient_d,recipient); X$DESCRIPTOR(mail_d,"MAIL"); X$DESCRIPTOR(ctrstr_d, X`09 "!AD!AD_!AD_!AD.!AD_JOBLOG_!ZL!ZL_!ZL!ZL_!ZL!ZL_!ZL!ZL_!ZL!ZL_!ZL!ZL"); X X X status = CLI$GET_VALUE(&mail_d,&recipient_d,&length); X X if(status == SS$_NORMAL && !disp_failed) X `7B X /* save the /MAIL recipient */ X X recipient`5Blength`5D = '\0';`09`09/* make it a string`09`09 */ X `7D X else X `7B X /* /USER wasn't specified; prompt the user for it */ X X my_puts(" "); X status = my_gets(channel,recipient,prompt,&length,sizeof(recipient) - V 1); X X if(status == FAILURE) X`09 return(FAILURE); X else if(status == CANCEL) X`09 return(CANCEL); X X /* input is ok if we get here */ X X str_pref_trim(recipient); X str_post_trim(recipient); X X if(recipient`5B0`5D == '\0') X `7B X`09 my_puts("\n\07You must specify a username."); X`09 return(NO_INPUT); X `7D X X strlu(recipient);`09`09`09/* conver to all uppercase`09 */ X `7D X X /* see if we have a valid recipient */ X X if(valid_recip(recipient) == FALSE) X `7B X cat(out_buf,"\n\07You cannot send JOBLOG log files to ",recipient); X my_puts(out_buf); X return(FAILURE); X `7D X else X `7B X username = getenv("USER"); X X if(strcmp(recipient,username) == 0) X `7B X`09 my_puts("\n\07You cannot send JOBLOG log files to yourself!"); X`09 return(FAILURE); X `7D X `7D X X /* good recipient; get the account of the sender */ X X status = LIB$GETJPI(&JPI$_ACCOUNT,0L,NULL,0L,&account_d,0); X X if(!(status & SS$_NORMAL)) X return(FAILURE); X X /* strip off the trailing blanks in the account */ X X length = 0; X X while(length < ACCOUNT_MAX && account`5Blength`5D != ' ') X ++length; X X account`5Blength`5D = '\0';`09`09/* make it a string`09`09 */ X squeeze_str(account);`09`09/* squeeze out any internal blanks */ X X /* make a mail message for the recipient */ X X strcpy(tempfile,"JOBXXXXXX"); X mktemp(tempfile); X strcat(tempfile,".TMP"); X X out_rab = cc$rms_rab; X out_rab.rab$l_fab = &out_fab;`09/* pointer to input FAB`09`09 */ X out_rab.rab$b_rac = RAB$C_SEQ;`09/* sequential access for copy`09 */ X out_rab.rab$w_usz = sizeof(out_buf);`09/* length of output buffer`09 V */ X out_rab.rab$l_rbf = out_buf;`09`09/* pointer to buffer`09`09 */ X X out_fab = cc$rms_fab; X out_fab.fab$w_ifi = 0; `09`09/* reset this!`09`09`09 */ X out_fab.fab$b_fac = FAB$M_PUT; X X out_fab.fab$l_fna = tempfile; X out_fab.fab$b_fns = (UCHAR) strlen(tempfile); X X /* open the output file */ X X status = SYS$CREATE(&out_fab); X X if(status != RMS$_NORMAL) X `7B X SYS$CLOSE(&out_fab); X return(FAILURE); X `7D X X /* connect the output file's RMS blocks */ X X status = SYS$CONNECT(&out_rab); X X if(status != RMS$_NORMAL) X `7B X SYS$CLOSE(&out_fab); X return(FAILURE); X `7D X X if(verify) X verify_ptr = ""; X else X verify_ptr = "n UNVERIFIED"; X X cat(out_buf,"There is a",verify_ptr, X " JOBLOG log file from ",username," waiting to be retrieved."); X out_rab.rab$w_rsz = (USHORT) strlen(out_buf); X status = SYS$PUT(&out_rab); X X strcpy(out_buf,"To retrieve it, enter the command\n"); X out_rab.rab$w_rsz = (USHORT) strlen(out_buf); X status = SYS$PUT(&out_rab); X X cat(out_buf,"`09JOBLOG/RETRIEVE/USER=",username); X out_rab.rab$w_rsz = (USHORT) strlen(out_buf); X status = SYS$PUT(&out_rab); X X status = SYS$CLOSE(&out_fab); X X my_puts(" "); X cat(out_buf,"....sending mail to ",recipient,"...."); X my_puts(out_buf); X X /* create the command to be SPAWNed */ X X if(verify) X cat(command,"$MAIL/SUBJECT=\"JOBLOG pending from ",username,"\" ", X`09 tempfile," ",recipient); X else X cat(command, X`09 "$MAIL/SUBJECT=\"UNVERIFIED JOBLOG pending from ",username,"\" ", X`09 tempfile," ",recipient); X X command_d.dsc$w_length = (USHORT) strlen(command); X X /* now try to spawn the command to mail the notice */ X X status = LIB$SPAWN(&command_d,&null_d,&null_d,NULL,NULL,0L,&status2,0L,0L V, X`09`09 0L,0L,NULL,NULL); X X delete(tempfile);`09`09`09/* kill it before we forget`09 */ X X if(!(status & SS$_NORMAL)) X `7B X LIB$SIGNAL(JLG_NO_SPAWN); X return(FAILURE); X `7D X X /* create the filename that will be used when the log file is moved X * to the staging area X */ X X time_val = time(NULL);`20 X time_ptr = localtime(&time_val); X time_ptr->tm_mon += 1;`09`09/* because it is 0-11, not 1-12`09:-( */ X X /* create the filename that will be used when the log file is copied X * to the staging area X */ X X if(verify) X verify_ch = "V"; X else X verify_ch = "U"; X X status = SYS$FAO(&ctrstr_d,&length,&filename_d,(ULONG) strlen(stage_dir), X`09`09 stage_dir,(ULONG) strlen(username),username, X`09`09 (ULONG) strlen(recipient),recipient, X`09`09 (ULONG) strlen(account),account, X`09`09 strlen(verify_ch),verify_ch,time_ptr->tm_mon/10, X`09`09 time_ptr->tm_mon%10,time_ptr->tm_mday/10, X`09`09 time_ptr->tm_mday%10,time_ptr->tm_year/10, X`09`09 time_ptr->tm_year%10,time_ptr->tm_hour/10, X`09`09 time_ptr->tm_hour%10,time_ptr->tm_min/10, X`09`09 time_ptr->tm_min%10,time_ptr->tm_sec/10, X`09`09 time_ptr->tm_sec%10); X X /* copy the log file to the staging directory */ X X status = copy_file(logfile,filename); X X if(status != SUCCESS) X return(FAILURE); X X if(verify) X cat(out_buf,"\n\nNotification of VERIFIED JOBLOG sent to user ", X`09 recipient,"\n\n"); X else X cat(out_buf,"\n\nNotification of UNVERIFIED JOBLOG sent to user ", X`09 recipient,"\n\n"); X X my_puts(out_buf); X X return(SUCCESS); X X`7D`09/*** mail_log ***/ X`0C X/*************************************************************************** V**** X**************************************************************************** V**** X X Function:`09valid_recip X X Purpose:`09Determine if the user specified is allowed to received mailed X`09`09JOBLOG log files. X X Formal Parameters: X X`09Name`09`09`09Description X`09----`09`09`09----------- X`09recipient`09`09who is supposed to get the log file 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`09SUCCESS`09`09`09valid recipient X`09FAILURE`09`09`09invalid recipient X X**************************************************************************** V**** X**************************************************************************** V***/ X Xstatic USHORT valid_recip(char *recipient) X X`7B`09/*** valid_recip ***/ X`09`09`09`09`09/******** LOCAL VARIABLES ********/ +-+-+-+-+-+-+-+- END OF PART 3 +-+-+-+-+-+-+-+-