Relay-Version: version nyu B notes v1.6.1 1/11/90; site acf3.NYU.EDU From: SRGHCXP@grace.dsir.govt.nz Date: 20 Feb 91 08:46 EST Date-Received: 22 Feb 91 03:30 EST Subject: mirror part 1 of 2, multiple terminals to single session Message-ID: <8614@grace.dsir.govt.nz> Path: acf3!cmcl2!cmcl2!adm!hsdndev!wuarchive!usc!elroy.jpl.nasa.gov!ames!uhccux!waikato.ac.nz!comp.vuw.ac.nz!wnv!grace!srghcxp Newsgroups: comp.os.vms Organization: DSIR, Gracefield, New Zealand Lines: 430 $ ! Here follows a two part share file of a program called $ ! MIRROR which allows multiple terminals to connect to $ ! a single session. They can all see the same output and $ ! can all type input. It seems to work with most applications $ ! (including EDT etc) $ ! $ ! It is based on PHOTO and you need the TWDRIVER and PYDRIVER's $ ! $ ! Append the two halfs, removed mail headers, and @ $ ! Then @compile.com $ ! Then @mirror.com and answer YES on the first terminal. $ ! $ ! (only tested on VMS 5.3-1) $ ! $ ! Enjoy, Chris. $ ! $! ------------------ CUT HERE ----------------------- $ v='f$verify(f$trnlnm("SHARE_VERIFY"))' $! $! This archive created by VMS_SHARE Version 7.2-007 22-FEB-1990 $! On 20-FEB-1991 12:58:16.43 By user SRGHCXP $! $! This VMS_SHARE Written by: $! Andy Harper, Kings College London UK $! $! Acknowledgements to: $! James Gray - Original VMS_SHARE $! Michael Bednarek - Original Concept and implementation $! $!+ THIS PACKAGE DISTRIBUTED IN 2 PARTS, TO KEEP EACH PART $! BELOW 30 BLOCKS $! $! TO UNPACK THIS SHARE FILE, CONCATENATE ALL PARTS IN ORDER $! AND EXECUTE AS A COMMAND PROCEDURE ( @name ) $! $! THE FOLLOWING FILE(S) WILL BE CREATED AFTER UNPACKING: $! 1. COMPILE.COM;3 $! 2. LINK.COM;3 $! 3. MIRROR.C;84 $! 4. MIRROR.COM;7 $! 5. MIRRORSPY.C;18 $! $set="set" $set symbol/scope=(nolocal,noglobal) $f=f$parse("SHARE_TEMP","SYS$SCRATCH:.TMP_"+f$getjpi("","PID")) $e="write sys$error ""%UNPACK"", " $w="write sys$output ""%UNPACK"", " $ if f$trnlnm("SHARE_LOG") then $ w = "!" $ ve=f$getsyi("version") $ if ve-f$extract(0,1,ve) .ges. "4.4" then $ goto START $ e "-E-OLDVER, Must run at least VMS 4.4" $ v=f$verify(v) $ exit 44 $UNPACK: SUBROUTINE ! P1=filename, P2=checksum $ if f$search(P1) .eqs. "" then $ goto file_absent $ e "-W-EXISTS, File ''P1' exists. Skipped." $ delete 'f'* $ exit $file_absent: $ if f$parse(P1) .nes. "" then $ goto dirok $ dn=f$parse(P1,,,"DIRECTORY") $ w "-I-CREDIR, Creating directory ''dn'." $ create/dir 'dn' $ if $status then $ goto dirok $ e "-E-CREDIRFAIL, Unable to create ''dn'. File skipped." $ delete 'f'* $ exit $dirok: $ w "-I-PROCESS, Processing file ''P1'." $ if .not. f$verify() then $ define/user sys$output nl: $ EDIT/TPU/NOSEC/NODIS/COM=SYS$INPUT 'f'/OUT='P1' PROCEDURE Unpacker ON_ERROR ENDON_ERROR;SET(FACILITY_NAME,"UNPACK");SET( SUCCESS,OFF);SET(INFORMATIONAL,OFF);f:=GET_INFO(COMMAND_LINE,"file_name");b:= CREATE_BUFFER(f,f);p:=SPAN(" ")@r&LINE_END;POSITION(BEGINNING_OF(b)); LOOP EXITIF SEARCH(p,FORWARD)=0;POSITION(r);ERASE(r);ENDLOOP;POSITION( BEGINNING_OF(b));g:=0;LOOP EXITIF MARK(NONE)=END_OF(b);x:=ERASE_CHARACTER(1); IF g=0 THEN IF x="X" THEN MOVE_VERTICAL(1);ENDIF;IF x="V" THEN APPEND_LINE; MOVE_HORIZONTAL(-CURRENT_OFFSET);MOVE_VERTICAL(1);ENDIF;IF x="+" THEN g:=1; ERASE_LINE;ENDIF;ELSE IF x="-" THEN IF INDEX(CURRENT_LINE,"+-+-+-+-+-+-+-+")= 1 THEN g:=0;ENDIF;ENDIF;ERASE_LINE;ENDIF;ENDLOOP;t:="0123456789ABCDEF"; POSITION(BEGINNING_OF(b));LOOP r:=SEARCH("`",FORWARD);EXITIF r=0;POSITION(r); ERASE(r);x1:=INDEX(t,ERASE_CHARACTER(1))-1;x2:=INDEX(t,ERASE_CHARACTER(1))-1; COPY_TEXT(ASCII(16*x1+x2));ENDLOOP;WRITE_FILE(b,GET_INFO(COMMAND_LINE, "output_file"));ENDPROCEDURE;Unpacker;QUIT; $ delete/nolog 'f'* $ CHECKSUM 'P1' $ IF CHECKSUM$CHECKSUM .eqs. P2 THEN $ EXIT $ e "-E-CHKSMFAIL, Checksum of ''P1' failed." $ ENDSUBROUTINE $START: $ create 'f' X$ set verify X$ cc mirror X$ cc mirrorspy X$ define lnk$library sys$library:vaxcrtl X$ link mirror /notrace X$ link mirrorspy /notrace $ CALL UNPACK COMPILE.COM;3 2084253445 $ create 'f' X$ define lnk$library sys$library:vaxcrtl X$ link mirror /notrace $ CALL UNPACK LINK.COM;3 1751859181 $ create 'f' X/* MIRROR.C X *`20 X * `09MIRROR allows multiple terminals to connect to a single session. X * `09Only tested on VMS5.3-1 X * `09 X * `09Chief Munger:`09Chris Pugmire, DSIR Physical Sciences X * `09`09`09in%"srghcxp@grv.dsir.govt.nz" X *`20 X * `09You will need the CMU-TEK terminal drivers (tw and py) and`20 X *`09GRPNAM priv so the mailboxes can talk to each other X * `09(The tw/py drivers must match your version of vms!) X *`20 X *`09(alternatively see the code in MIRROR_START.COM which X *`09creates a logical name table which can be written to`20 X * `09without priv) X * X *`09The mirror spy program doesn't use PASTHRU mode so that`20 X * `09control y's will abort the program, this could easily be fixed. X * X * `09MIRROR is a munged version of photo, the photo copyright messages X * `09follow. 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 MIRROR X * Link: LINK/NOTRACE MIRROR,SYS$LIBRARY:CSHARE/OPT X * Place: SYS$SYSTEM: X * Install: INSTALL> ADD SYS$SYSTEM:MIRROR/PRIV=(PHY_IO,GRPNAM) 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`091986`09Created File. X XCharles Karney`09`091987`09Spawn child process to be name MIRROR_xxxxxx X XBob Sloane`09`091987`09Added the IO$M_ESCAPE modifier to the QIO to X`09`09`09`09read from the terminal and the problem went X`09`09`09`09away. I also fixed up my code in log_line so X`09`09`09`09that it will handle CR/LF and LF/CR pairs X`09`09`09`09spread across lines. X XChris Ho, USC`09`091988`09Fix privileges after DEC security patch v2. X XKevin Carosso, NRC`099-JUN-1988 X`09`09`09`09Modify for new PY/TW driver set. Change X`09`09`09`09the name of the pseudo-terminal from TZA X`09`09`09`09to TWA. Change SENSEMODE to $GETDVI to X`09`09`09`09get unit number in DEVDEPEND. If we X`09`09`09`09don't have PHY_IO, issue warning but X`09`09`09`09don't exit. For now, ignore SS$_DATAOVERUN X`09`09`09`09return on writes to the PY. We really should X`09`09`09`09watch the delivered char count in the IOSB X`09`09`09`09and 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 `5E\ */ X#define timchar 29 /* Time logging flag `5E`5D */ 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) `7C`7C ((a) == LF) `7C`7C (!(a)) Xunsigned int z_ef; X/*---------------------------------------------------------------*/ X X Xstruct CHARBLK `7Bunsigned char class, X ttype; X unsigned short pgwid; X unsigned ttchr : 24; X unsigned char pglen; X unsigned int xchar; X `7D; X Xstruct IOSBBLK `7Bunsigned short stats, X tmoff, X tmntr, X tmsiz; X `7D; X Xtypedef struct DVIBLK `7B X`09unsigned short`09len, code; X`09char`09* buffp; X`09long`09* lenp; X`09long`09terminate; X`09`7D DVIBLK; X Xlong py_chn, py_mb_chn, X tt_chn, tt_mb_chn, X pid,st,line_index=0; X Xchar finaltw`5Btwdevlen`5D, X line`5Blinesz`5D=0, time`5B24`5D, X py_mb`5Bmbsiz`5D, tt_mb`5Bmbsiz`5D, X ttline`5Blinesz`5D, twline`5Blinesz`5D, 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 Xquit() /* This is done upon exiting, by exit handler */ X`7B X int j; X X j= SYS$DELMBX(py_mb_chn); X if (bad(j)) X puts ("`5BSYS$DELMBX pseudo-mbx deletion failed`5D"); 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 ("`5BSYS$QIO /setmode/ failed`5D"); X puts ("\nEnd MIRROR session"); X`7D X/*---------------------------------------------------------------*/ X X Xlow_lib_spawn(pty_io,pid) /* Spawns subprocess to speaks to pseudo terminal V */ X char *pty_io; X int *pid; X`7B X long prv`5B2`5D, oprv`5B2`5D; X int my_pid, owner, item; X char procnm`5B16`5D, ownprc`5B16`5D; 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 MIRROR X */ X check (LIB$GETJPI (&JPI$_PRCNAM,0, 0, 0, &d_procnm) ); X check (LIB$GETJPI (&JPI$_OWNER, 0, 0, &owner) ); X sprintf (ownprc, "MIRROR_%04X", owner & 0xFFFF); X if (! strncmp (ownprc, procnm, 10) ) X`09`7B printf("MIRROR is in use\n"); return 2; `7D X X sprintf (procnm, "MIRROR_%04X", my_pid & 0xFFFF); X d_procnm.dsc$w_length = 10; X d_pty_io.dsc$w_length = strlen (pty_io); X X prv`5B0`5D = prv`5B1`5D = -1; X check (SYS$SETPRV (0, prv, 0, oprv) );`09/* disable image privs */ X check (LIB$GETJPI (&JPI$_PROCPRIV, 0, 0, prv) ); X prv`5B0`5D `7C= PRV$M_GRPNAM;`09`09`09 X SYS$SETPRV (1, prv, 0, 0) ;`09`09/* enable normal privs + GRPNAM */ X X st = LIB$SPAWN (0, &d_pty_io, &d_pty_io, &1, &d_procnm, pid); X if (st & SS$_NORMAL) X`09check (SYS$SETPRV (1, oprv, 0, 0) );`09/* enable image privs */ X return st; X`7D X/*---------------------------------------------------------------*/ X X Xasctim() /* Returns Time-stamp info */ X`7B X char buf`5B24`5D; X $DESCRIPTOR(d_asctim,&buf); X X check(SYS$ASCTIM(0,&d_asctim,0,0)); X buf`5B20`5D= 0; X sprintf(&time,"`5B%s`5D",&buf); X`7D X/*---------------------------------------------------------------*/ X Xtoggle(swtch) /* Set switches as desired */ X char swtch; X`7B X char buf`5B40`5D; X X if (swtch == logchar) `7B X`09exit(1); X `7D X else `7B 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 `7D X check(SYS$QIOW(0,tt_chn,IO$_WRITEVBLK,0,0,0,&buf,strlen(&buf),0,0,0,0)); X`7D X/*---------------------------------------------------------------*/ X X Xtw_srv() /* AST: on pseudo terminal. Deals with spurious hangups */ X`7B 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`7D X/*---------------------------------------------------------------*/ X X Xtt_srv() /* AST: Read on real terminal */ X`7B X int j; X X check(tiosb.stats); X /* Read everything typed right away */ X check(SYS$QIO(z_ef,tt_chn,IO$_READVBLK`7CIO$M_TIMED`7CIO$M_ESCAPE,&tiosb V,0,0, X &ttline,linesz,0,0,0,0)); X check(SYS$WAITFR(z_ef)); /* for some reason QIOW does not work V */ Xread_again: X j= tiosb.tmoff + tiosb.tmsiz; /* How many chars read */ X if ((ttline`5B0`5D == logchar) `7C`7C (ttline`5B0`5D == timchar)) /* f Vlags */ X toggle(ttline`5B0`5D); X /* write everything we read to pseudo-terminal */ X check(SYS$QIO(z_ef,py_chn,IO$_WRITEVBLK,&tiosb,0,0,&ttline,j,0,0,0,0)); X check(SYS$WAITFR(z_ef)); /* for some reason QIOW does not work V */ X if (tiosb.stats != SS$_DATAOVERUN) X`09check(tiosb.stats); X X check(SYS$QIO(z_ef,tt_chn,IO$_READVBLK`7CIO$M_TIMED`7CIO$M_ESCAPE,&tiosb V,0,0, X &ttline,linesz,0,0,0,0)); X check(SYS$WAITFR(z_ef)); /* for some reason QIOW does not work V */ X if (tiosb.stats!=SS$_TIMEOUT) goto read_again; X 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`7D 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`7B X int i; /* counter var */ X char ch; /* current character */ X X for ( i=0; i= 0 ) /* if starting a new line * V/ X `7C`7C line_index >= linesz-1 ) `7B /* or the buffer is f Vull */ X line_index = 0; /* start the new line */ X line`5Bline_index`5D = 0; /* make sure it has an V EOS */ X `7D X if ( (lastch == LF `7C`7C lastch < 0) && ch == CR ) /* CR starting l Vine? */ X continue; /* yes - ignore it */ X if ( lastch == CR && ch != LF ) `7B /* check for CR/LF pair * V/ X line`5Bline_index++`5D = CR; /* not CR/LF pair, file V it */ X line`5Bline_index`5D = 0; /* make line a C string V */ X `7D X if ( ch != LF && ch != CR ) `7B /* don't want these on fi Vle */ X line`5Bline_index++`5D = ch; /* add the character to V line */ X line`5Bline_index`5D = 0; /* and the EOS */ X `7D X lastch = ch; /* remember the last char * V/ X `7D X`7D X/*---------------------------------------------------------------*/ X Xget_tt_info() X`7B X $DESCRIPTOR(d_tt, "SYS$COMMAND"); X /* Get a channel & mailbox of terminal */ X check(LIB$ASN_WTH_MBX(&d_tt,&mbsiz,&maxsiz,&tt_chn,&tt_mb_chn)); X /* Get the terminal characteristics. */ X check(SYS$QIOW(0,tt_chn,IO$_SENSEMODE,0,0,0,&tt_chr,ttchrlen,0,0,0,0)); X tt_sav_chr= tt_chr; +-+-+-+-+-+-+-+- END OF PART 1 +-+-+-+-+-+-+-+-