[comp.os.vms] USC PHOTO for new PTYs 1/2

KVC@BUSTER.NRC.COM (Kevin Carosso) (06/22/88)

...................... Cut between dotted lines and save. .....................
$!.............................................................................
$! VAX/VMS archive file created by VMS_SHARE V06.00 26-May-1988.
$!
$! VMS_SHARE was written by James Gray (Gray:OSBUSouth@Xerox.COM) from
$! VMS_SHAR by Michael Bednarek (U3369429@ucsvc.dn.mu.oz.au).
$!
$! To unpack, simply save, concatinate all parts into one file and
$! execute (@) that file.
$!
$! This archive was created by user KVC
$! on 14-OCT-1864 22:00:33.11.
$!
$! ATTENTION: To keep each article below 31 blocks (15872 bytes), this
$!            program has been transmitted in 2 parts.  You should
$!            concatenate ALL parts to ONE file and execute (@) that file.
$!
$! It contains the following 6 files:
$!        000_README.TXT
$!        PHOTO.C
$!        PHOTO.CLD
$!        PHOTO.HLP
$!        PHOTO.README
$!        PHOTOMSG.MSG
$!
$!==============================================================================
$ SET SYMBOL/SCOPE=( NOLOCAL, NOGLOBAL )
$ VERSION = F$GETSYI( "VERSION" )
$ IF VERSION .GES "V4.4" THEN GOTO VERSION_OK
$ WRITE SYS$OUTPUT "You are running VMS ''VERSION'; ", -
    "VMS_SHARE V06.00 26-May-1988 requires VMS V4.4 or higher."
$ EXIT 44 
$VERSION_OK:
$ GOTO START
$
$UNPACK_FILE:
$ WRITE SYS$OUTPUT "Creating ''FILE_IS'"
$ DEFINE/USER_MODE SYS$OUTPUT NL:
$ EDIT/TPU/COMMAND=SYS$INPUT/NODISPLAY/OUTPUT='FILE_IS'/NOSECTION -
    VMS_SHARE_DUMMY.DUMMY
b_part := CREATE_BUFFER( "{Part}", GET_INFO( COMMAND_LINE, "file_name" ) )
; s_file_spec := GET_INFO( COMMAND_LINE, "output_file" ); SET( OUTPUT_FILE
, b_part, s_file_spec ); b_errors := CREATE_BUFFER( "{Errors}" ); i_errors := 0
; pat_beg_1 := ANCHOR & "-+-+-+ Beginning"; pat_beg_2 := LINE_BEGIN 
& "+-+-+-+ Beginning"; pat_end := ANCHOR & "+-+-+-+-+ End"; POSITION
( BEGINNING_OF( b_part ) ); i_append_line := 0; LOOP EXITIF MARK( NONE 
) = END_OF( b_part ); s_x := ERASE_CHARACTER( 1 ); IF s_x = "+" THEN r_skip 
:= SEARCH( pat_beg_1, FORWARD, EXACT ); IF r_skip <> 0 THEN s_x := ""
; MOVE_HORIZONTAL( -CURRENT_OFFSET ); ERASE_LINE; ENDIF; ENDIF
; IF s_x = "-" THEN r_skip := SEARCH( pat_end, FORWARD, EXACT ); IF r_skip <
> 0 THEN s_x := ""; MOVE_HORIZONTAL( -CURRENT_OFFSET ); m_skip := MARK( NONE )
; r_skip := SEARCH( pat_beg_2, FORWARD, EXACT ); IF r_skip <> 0 THEN POSITION
( END_OF( r_skip ) ); MOVE_HORIZONTAL( -CURRENT_OFFSET ); MOVE_VERTICAL( 1 )
; MOVE_HORIZONTAL( -1 ); ELSE POSITION( END_OF( b_part ) ); ENDIF; ERASE
( CREATE_RANGE( m_skip, MARK( NONE ), NONE ) ); ENDIF; ENDIF
; IF s_x = "V" THEN s_x := ""; IF i_append_line <> 0 THEN APPEND_LINE
; MOVE_HORIZONTAL( -CURRENT_OFFSET ); ENDIF; i_append_line := 1; MOVE_VERTICAL
( 1 ); ENDIF; IF s_x = "X" THEN s_x := ""; IF i_append_line <
> 0 THEN APPEND_LINE; MOVE_HORIZONTAL( -CURRENT_OFFSET ); ENDIF; i_append_line 
:= 0; MOVE_VERTICAL( 1 ); ENDIF; IF s_x <> "" THEN i_errors := i_errors + 1
; s_text := CURRENT_LINE; POSITION( b_errors ); COPY_TEXT
( "The following line could not be unpacked properly:" ); SPLIT_LINE; COPY_TEXT
( s_x ); COPY_TEXT( s_text ); POSITION( b_part ); MOVE_VERTICAL( 1 ); ENDIF
; ENDLOOP; POSITION( BEGINNING_OF( b_part ) ); LOOP r_x := SEARCH( "`", FORWARD
, EXACT ); EXITIF r_x = 0; POSITION( r_x ); ERASE_CHARACTER( 1 )
; IF CURRENT_CHARACTER = "`" THEN MOVE_HORIZONTAL( 1 ); ELSE COPY_TEXT( ASCII
( INT( ERASE_CHARACTER( 3 ) ) ) ); ENDIF; ENDLOOP; IF i_errors = 0 THEN SET
( NO_WRITE, b_errors, ON ); ELSE POSITION( BEGINNING_OF( b_errors ) )
; COPY_TEXT( FAO( "The following !UL errors were detected while unpacking !AS"
, i_errors, s_file_spec ) ); SPLIT_LINE; SET( OUTPUT_FILE, b_errors
, "SYS$COMMAND" ); ENDIF; EXIT; 
$ DELETE VMS_SHARE_DUMMY.DUMMY;*
$ CHECKSUM 'FILE_IS
$ WRITE SYS$OUTPUT " CHECKSUM ", -
  F$ELEMENT( CHECKSUM_IS .EQ. CHECKSUM$CHECKSUM, ",", "failed!,passed." )
$ RETURN
$
$START:
$ FILE_IS = "000_README.TXT"
$ CHECKSUM_IS = 1953524851
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
XThis is a version of PHOTO modified to work with the new version
Xof the PY/TW drivers.  It has been tested under both VMS V5.0 and
XVMS V4.7.   This could use some work to clean it up and use the
Xnew features of the drivers.
X
XNote that PHY_IO privilege is required to properly propagate the
Xterminal characteristics, and PHOTO should therefore be installed
Xwith PHY_IO.  If PHOTO is not installed and the user does not have
XPHY_IO, a warning message will be issued and the pseudo-terminal
Xwill not have the same characteristics as the user's real terminal.
XPHOTO will still produce a session log, however.
X
X`009/Kevin Carosso                     kvc@nrc.com
X`009 Network Research Co.              kvc@ymir.bitnet
X
X`009June 9, 1988
$ GOSUB UNPACK_FILE
$ FILE_IS = "PHOTO.C"
$ CHECKSUM_IS = 1030740917
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
X/* PHOTO.C
X *
X * Copyright 1986, University of Southern California
X * Author - Asbed Bedrossian
X * This program may be copied or distributed for any non-commercial
X * purpose, as long as this notice remains intact.
X *
X * This program is used to log a terminal session.
X *
X * Compile: CC PHOTO
X *          MESSAGE PHOTOMSG
X * Link:    LINK/NOTRACE PHOTO,PHOTOMSG,SYS$LIBRARY:CSHARE/OPT
X * Place:   SYS$SYSTEM:
X * Install: INSTALL> ADD SYS$SYSTEM:PHOTO/PRIV=PHY_IO
X *
X * For proper execution, You will need to install CMU's PseudoTerminal (PTY)
X * driver on your system. You need PYDRIVER.EXE and TWDRIVER.EXE.
X * These drivers can be installed with the following SYSGEN commands:
X *   SYSGEN> RELOAD SYS$SYSTEM:TWDRIVER
X *   SYSGEN> CONNECT TWA0 /NOADAPTER
X *   SYSGEN> RELOAD SYS$SYSTEM:PYDRIVER
X *   SYSGEN> CONNECT PYA0 /NOADAPTER
X *
X */
X
X/*
XHistory:
X
XAsbed Bedrossian`0091986`009Created File.
X
XCharles Karney`009`0091987`009Spawn child process to be name Photo_xxxxxx
X
XBob Sloane`009`0091987`009Added the IO$M_ESCAPE modifier to the QIO to
X`009`009`009`009read from the terminal and the problem went
X`009`009`009`009away.  I also fixed up my code in log_line so
X`009`009`009`009that it will handle CR/LF and LF/CR pairs
X`009`009`009`009spread across lines.
X
XChris Ho, USC`009`0091988`009Fix privileges after DEC security patch v2.
X
XKevin Carosso, NRC`0099-JUN-1988
X`009`009`009`009Modify for new PY/TW driver set.  Change
X`009`009`009`009the name of the pseudo-terminal from TZA
X`009`009`009`009to TWA.  Change SENSEMODE to $GETDVI to
X`009`009`009`009get unit number in DEVDEPEND.  If we
X`009`009`009`009don't have PHY_IO, issue warning but
X`009`009`009`009don't exit.  For now, ignore SS$_DATAOVERUN
X`009`009`009`009return on writes to the PY.  We really should
X`009`009`009`009watch the delivered char count in the IOSB
X`009`009`009`009and wait for an XON AST.
X*/
X
X#include DESCRIP
X#include FAB
X#include IODEF
X#include RAB
X#include TTDEF
X#include TT2DEF
X#include stdio
X#include JPIDEF
X#include SSDEF
X#include PRCDEF
X#include PRVDEF
X#include DVIDEF
X
X#define  CR             13
X#define  LF             10
X#define  logchar        28           /* Logging on/off flag ^\ */
X#define  timchar        29           /* Time logging flag ^] */
X#define  ttchrlen       12
X#define  twdevlen       15
X#define  mbsiz          40
X#define  maxsiz         80
X#define  linesz        512
X
X#define  bad(j)      !((j) & 1)
X#define  check(a)    if (bad(st = (a))) LIB$SIGNAL(st)
X#define  garbage(a)  ((a) == CR) || ((a) == LF) || (!(a))
X
X
X
X
X
X
X
X
X
Xglobalvalue PHOTO_INUSE;
X
Xstruct CHARBLK {unsigned char     class,
X                                  ttype;
X                unsigned short    pgwid;
X                unsigned          ttchr    :  24;
X                unsigned char     pglen;
X                unsigned int      xchar;
X               };
X
Xstruct IOSBBLK {unsigned short stats,
X                               tmoff,
X                               tmntr,
X                               tmsiz;
X               };
X
Xtypedef struct DVIBLK {
X`009unsigned short`009len, code;
X`009char`009* buffp;
X`009long`009* lenp;
X`009long`009terminate;
X`009} DVIBLK;
X
Xlong py_chn, py_mb_chn,
X     tt_chn, tt_mb_chn,
X     pid,st,line_index=0;
X
Xchar finaltw[twdevlen],
X     line[linesz]=0, time[24],
X     py_mb[mbsiz], tt_mb[mbsiz],
X     ttline[linesz],   twline[linesz],
X     tim= 0, com= 0, log= 1, enable_hangups= 0;
X
Xstruct CHARBLK tt_chr, tt_sav_chr;
Xstruct IOSBBLK tiosb, piosb, miosb;
Xstruct FAB     zfab;
Xstruct RAB     zrab;
X
X
X
X
X
X
X
X
X
Xquit()                   /* This is done upon exiting, by exit handler */
X{
X    int j;
X
X    j= SYS$DELMBX(py_mb_chn);
X    if (bad(j))
X        puts ("[SYS$DELMBX pseudo-mbx deletion failed]");
X    j= SYS$QIOW(0,tt_chn,IO$_SETMODE,0,0,0,&tt_sav_chr,ttchrlen,0,0,0,0);
X    if (bad(j))
X        puts ("[SYS$QIO /setmode/ failed]");
X    puts ("\nEnd PHOTO session");
X}
X
X
X
X
X
X
X
X
X
Xlow_lib_spawn(pty_io,pid)  /* Spawns subprocess to speaks to pseudo terminal */
X    char *pty_io;
X    int  *pid;
X{
X    long prv[2], oprv[2];
X    int my_pid, owner, item;
X    char procnm[16], ownprc[16];
X
X    $DESCRIPTOR(d_procnm, procnm);
X    $DESCRIPTOR(d_pty_io, pty_io);  /* PTY name + number */
X
X    my_pid = getpid ();
X/*
X *      check to see if we are already in PHOTO
X */
X    check (LIB$GETJPI (&JPI$_PRCNAM,0, 0, 0, &d_procnm) );
X    check (LIB$GETJPI (&JPI$_OWNER, 0, 0, &owner) );
X    sprintf (ownprc, "PHOTO_%04X", owner & 0xFFFF);
X    if (! strncmp (ownprc, procnm, 10) )
X`009return PHOTO_INUSE;
X
X    sprintf (procnm, "PHOTO_%04X", my_pid & 0xFFFF);
X    d_procnm.dsc$w_length = 10;
X    d_pty_io.dsc$w_length = strlen (pty_io);
X
X    prv[0] = prv[1] = -1;
X    check (SYS$SETPRV (0, prv, 0, oprv) );`009/* disable image privs */
X    check (LIB$GETJPI (&JPI$_PROCPRIV, 0, 0, prv) );
X    check (SYS$SETPRV (1, prv, 0, 0) );`009`009/* enable normal privs */
X
X    st = LIB$SPAWN (0, &d_pty_io, &d_pty_io, &1, &d_procnm, pid);
X    if (st & SS$_NORMAL)
X`009check (SYS$SETPRV (1, oprv, 0, 0) );`009/* enable image privs */
X    return st;
X}
X
X
X
X
X
X
X
X
X
Xasctim()                   /* Returns Time-stamp info */
X{
X    char buf[24];
X    $DESCRIPTOR(d_asctim,&buf);
X
X    check(SYS$ASCTIM(0,&d_asctim,0,0));
X    buf[20]= 0;
X    sprintf(&time,"[%s]",&buf);
X}
X
X
X
X
X
X
X
X
X
Xtoggle(swtch)                   /* Set switches as desired */
X    char swtch;
X{
X    char buf[40];
X
X    if (swtch == logchar) {
X        log= !log;
X        if (log)
X            sprintf(&buf,"Logging has been ENABLED\r\n");
X        else
X            sprintf(&buf,"Logging has been DISABLED\r\n");
X    }
X    else {
X        tim= !tim;
X        if (tim)
X            sprintf(&buf,"Time stamping has been ENABLED\r\n");
X        else
X            sprintf(&buf,"Time stamping has been DISABLED\r\n");
X    }
X    check(SYS$QIOW(0,tt_chn,IO$_WRITEVBLK,0,0,0,&buf,strlen(&buf),0,0,0,0));
X}
X
X
X
X
X
X
X
X
X
Xtw_srv()       /* AST: on pseudo terminal. Deals with spurious hangups */
X{
X    check(miosb.stats);
X    if (enable_hangups)
X        exit(1);
X    else
X        check(SYS$QIO(0,py_mb_chn,IO$_READVBLK,&miosb,&tw_srv,0,
X                               &py_mb,mbsiz,0,0,0,0));
X}
X
X
X
X
X
X
X
X
X
Xtt_srv()                   /* AST: Read on real terminal */
X{
X    int j;
X
X    check(tiosb.stats);
X                       /* Read everything typed right away */
X    check(SYS$QIOW(0,tt_chn,IO$_READVBLK|IO$M_TIMED|IO$M_ESCAPE,&tiosb,0,0,
X                               &ttline,linesz,0,0,0,0));
X    j= tiosb.tmoff + tiosb.tmsiz;           /* How many chars read */
X    com= ttline[0]==CR;
X    if (com) {
X        if (tim) asctim();               /* Time stampi info */
X    }
X    else
X        if ((ttline[0] == logchar) || (ttline[0] == timchar))   /* flags */
X            toggle(ttline[0]);
X               /* write everything we read to pseudo-terminal */
X    check(SYS$QIOW(0,py_chn,IO$_WRITEVBLK,&tiosb,0,0,&ttline,j,0,0,0,0));
X    if (tiosb.stats != SS$_DATAOVERUN)
X`009check(tiosb.stats);
X                       /* re-post read AST on real term */
X    check(SYS$QIO(0,tt_mb_chn,IO$_READVBLK,&tiosb,&tt_srv,0,
X                               &tt_mb,mbsiz,0,0,0,0));
X}
X
X
X
X
X
X
X
X
X
Xint lastch = -1;                /* holds last character processed for
X                                   CR/LF or LF/CR processing. <0 means
X                                   this is the first line to avoid a null
X                                   line at the start of the file */
Xlog_line(num)                   /* This logs the input into a file */
X    int num;
X{
X    int i;                                       /* counter var */
X    char ch;                                     /* current character */
X
V    for ( i=0; i<num; ++i ) {                    /* go through the whole line *
X/
X        ch = twline[i];                          /* get the current char */
X        if ( (ch == LF && lastch >= 0 )          /* if starting a new line */
X              || line_index >= linesz-1 ) {      /* or the buffer is full */
X            zrab.rab$l_rbf= &line;               /* set up to write line */
X            zrab.rab$w_rsz= line_index;
X            check(SYS$PUT(&zrab,0,0));           /* write line into file */
X            if ((com) && (tim)) {                /* are we Time-stamping? */
X                zrab.rab$l_rbf= &time;
X                zrab.rab$w_rsz= strlen(&time);
X                check(SYS$PUT(&zrab,0,0));       /* Time-stamp in file */
X            }
X            line_index = 0;                      /* start the new line */
X            line[line_index] = 0;                /* make sure it has an EOS */
X        }
X        if ( (lastch == LF || lastch < 0) && ch == CR ) /* CR starting line? */
X            continue;                            /* yes - ignore it */
X        if ( lastch == CR && ch != LF ) {        /* check for CR/LF pair */
X            line[line_index++] = CR;             /* not CR/LF pair, file it */
X            line[line_index] = 0;                /* make line a C string */
X        }
X        if ( ch != LF && ch != CR ) {            /* don't want these on file */
V            line[line_index++] = ch;             /* add the character to line *
X/
X            line[line_index] = 0;                /* and the EOS */
X        }
X        lastch = ch;                             /* remember the last char */
X    }
X}
X
X
X
X
X
X
X
X
X
Xget_file(filspec)               /* Sets up a file RAB and FAB */
X    char *filspec;
X{
X    zfab= cc$rms_fab;
X    zrab= cc$rms_rab;
X    zfab.fab$b_fac= FAB$M_GET+FAB$M_PUT;
X    zfab.fab$l_fna= filspec;
X    zfab.fab$b_fns= strlen(filspec);
X    zfab.fab$b_org= FAB$C_SEQ;
X    zfab.fab$b_rat= FAB$M_CR;
X    zfab.fab$b_rfm= FAB$C_VAR;
X    zfab.fab$b_shr= FAB$M_SHRPUT | FAB$M_SHRGET | FAB$M_UPI;
X    check(SYS$CREATE(&zfab,0,0));
X    zrab.rab$l_fab= &zfab;
X    zrab.rab$w_isi= 0;
X    zrab.rab$l_rop= RAB$M_EOF;
X    check(SYS$CONNECT(&zrab, 0, 0));
X    zrab.rab$b_rac= RAB$C_SEQ;
-+-+-+-+-+ End of part 1 +-+-+-+-+-