$ ! 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 +-+-+-+-+-+-+-+- -+-+-+-+-+-+-+-+ START OF PART 2 -+-+-+-+-+-+-+-+ X tt_chr.ttchr`7C= TT$M_NOECHO; /* term will be Noecho */ X tt_chr.ttchr&= `7ETT$M_HOSTSYNC & `7ETT$M_TTSYNC; /* it will have `5ES V */ X tt_chr.xchar`7C= TT2$M_PASTHRU; /* it will be PASTRHU */ X check(SYS$QIOW(0,tt_chn,IO$_SETMODE,0,0,0,&tt_chr,ttchrlen,0,0,0,0)); X`7D X/*---------------------------------------------------------------*/ Xfix_a_tw() /* Set up a Pseudo term */ X`7B X int efn=1, dev_depend, tw_chn; X struct CHARBLK tw_chr; X struct IOSBBLK iosb; X struct DVIBLK dvi_stuff = `7B4, DVI$_DEVDEPEND, &dev_depend, 0, 0`7D; X X X $DESCRIPTOR(d_pynam,"PYA0:"); /* Template. */ X $DESCRIPTOR(d_finaltw, &finaltw); X /* Assign a mailbox to PYA */ X check(LIB$ASN_WTH_MBX(&d_pynam,&mbsiz,&maxsiz,&py_chn,&py_mb_chn)); X/* X * Use $GETDVI to get the device dependent characteristics, which X * contains the associated terminal device's unit number. X */ X check(SYS$GETDVI(0,py_chn,0,&dvi_stuff,&iosb,0,0,0)); X check(iosb.stats); X sprintf(&finaltw,"TWA%d:",dev_depend); X tw_chr= tt_sav_chr; X tw_chr.xchar`7C= TT2$M_HANGUP; X d_finaltw.dsc$w_length= strlen(&finaltw); X check(SYS$ASSIGN(&d_finaltw,&tw_chn,0,0)); /* Get a channel on this TWA V */ X /* Make it look like user's real terminal */ X st = SYS$QIOW(0,tw_chn,IO$_SETCHAR,0,0,0,&tw_chr,ttchrlen,0,0,0,0); X if (st == SS$_NOPRIV) X`09printf ("WARNING -- PHY_IO privilege required to propagate terminal chara Vcteristics!\n"); X else X`09check(st); X check(SYS$DASSGN(tw_chn)); /* We don't need it. only the mailbox */ X /* in fact keeping it kills us. */ X`7D X/*---------------------------------------------------------------*/ X X Xpost_reads() /* This sets up ASTs */ X`7B X /* Read AST on Pseudo-term */ X check(SYS$QIO(0,py_mb_chn,IO$_READVBLK,&miosb,&tw_srv,0, X &py_mb,mbsiz,0,0,0,0)); X /* 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 Xmain(how_many,rscan) X int how_many; X char *rscan`5B`5D; X`7B X int exit_handler`5B4`5D= `7B0,quit,0,&st`7D; X char filnam`5B40`5D; X X check(LIB$GET_EF(&z_ef)); X check(SYS$DCLEXH(&exit_handler)); /* Define Exit handler (quit) */ X get_tt_info(); /* Get terminal channel & info */ X fix_a_tw(); /* Set a pseudo terminal by TT info * V/ X check(SYS$CANCEL(py_chn)); /* Don't need this Half of pseudo-ter V */ X check(low_lib_spawn(&finaltw,&pid)); /* Spawn a subprocess. */ X post_reads(); X enable_hangups= 1; X puts ("Begining Mirror session. Use `5E\\ to abort process"); X begin_session(); X`7D Xother_terminal(char *s,int j) X`7B X`09static buff`5B1000`5D; X`09strncpy(buff,s,j); X`09buff`5Bj`5D=0; X`09printf("%s",s); X X X`7D X X/*---------------------------------------------------------------*/ Xstruct IOSBBLK r_iosb,c_iosb,t_iosb,w_iosb`5B40`5D,ppiosb; X#define bsize 512 Xchar r_buff`5Bbsize`5D,c_buff`5Bbsize`5D; Xlong w_chan`5B40`5D,r_chan,c_chan; Xunsigned int efmask,r_ef,x_ef,t_ef,c_ef,p_ef,w_ef; Xint nw; Xbegin_session() X`7B X int j; X X open_mailboxes(); X pre_read_cont(); X pre_read_mail();`20 X pre_read_psuedo(); X for(;;) `7B /* Read/write forever loop */ X`09waitforflag(); X`09if (r_iosb.stats!=0) `7B send_psuedo(); pre_read_mail(); `7D X`09if (c_iosb.stats!=0) `7B new_slave(); pre_read_cont(); `7D X`09if (piosb.stats!=0) `7B send_screen(); send_mail(); pre_read_psuedo(); `7 VD X `7D X`7D Xopen_mailboxes() X`7B X`09char ss`5B22`5D; X`09$DESCRIPTOR(w_name, "MIRROR_WRITE"); /* reversed on purpose */ X`09$DESCRIPTOR(r_name, "MIRROR_READ"); X`09$DESCRIPTOR(c_name, "MIRROR_CONTROL"); X X`09check(SYS$CREMBX(0,&c_chan,0,0,0,0,&c_name)); X`09check(SYS$CREMBX(0,&r_chan,0,0,0,0,&w_name)); X X`09check(LIB$GET_EF(&x_ef)); X`09check(LIB$GET_EF(&w_ef)); X`09check(LIB$GET_EF(&r_ef)); X`09check(LIB$GET_EF(&p_ef)); X`09check(LIB$GET_EF(&c_ef)); X`09efmask = (1<<(r_ef-32)) + (1<<(p_ef-32)) + (1<<(c_ef-32)); X`7D Xpre_read_psuedo() X`7B X piosb.stats = 0; X check(SYS$QIO(p_ef,py_chn,IO$_READVBLK,&piosb,0,0, X &twline,90,0,0,0,0)); X`7D Xpre_read_cont() X`7B X c_iosb.stats = 0; X check(SYS$QIO(c_ef,c_chan,IO$_READLBLK,&c_iosb,0,0, X &c_buff,90,0,0,0,0)); X`7D Xpre_read_mail() X`7B X r_iosb.stats = 0; `20 X check(SYS$QIO(r_ef,r_chan,IO$_READLBLK,&r_iosb,0,0, X &r_buff,90,0,0,0,0)); X`7D Xget_rest() X`7B X`09int j,i; X`09j = piosb.tmoff + piosb.tmsiz; /* How much stuff did we read? */ X `09piosb.stats = 0; X `09check(SYS$QIO(x_ef,py_chn,IO$_READLBLK`7CIO$M_NOW,&piosb,0,0, X &twline+j,80,0,0,0,0)); X check(SYS$WAITFR(x_ef)); X`09check(piosb.stats); X`09piosb.tmoff = j + piosb.tmoff + piosb.tmsiz; `20 X`09piosb.tmsiz = 0; X`7D Xsend_mail() X`7B X`09int j,i; X j = piosb.tmoff + piosb.tmsiz; /* How much stuff did we read? */ X`09for (i=1;i<=nw;i++) `7B`09 X`09check(SYS$QIO(w_ef,w_chan`5Bi`5D,IO$_WRITELBLK,&w_iosb`5Bi`5D,0,0,&twline V,j,0,0,0,0)); X check(SYS$WAITFR(w_ef)); /* for some reason QIOW does not V work */ X`09check(w_iosb`5Bi`5D.stats); X`09`7D X`7D Xsend_screen() X`7B X`09int j; X j= piosb.tmoff + piosb.tmsiz; /* How much stuff did we read? */ X check(SYS$QIO(x_ef,tt_chn,IO$_WRITEVBLK,&t_iosb,0,0,&twline,j,0,0,0, V0)); X check(SYS$WAITFR(x_ef)); /* for some reason QIOW does not V work */ X`09check(t_iosb.stats); X`7D Xnew_slave() X`7B X`09int j; X`09char pid`5B20`5D; X`09static char nams`5B40`5D="MIRROR_00000000"; X`09$DESCRIPTOR(newname, nams); /* reversed on purpose */ X`09j = c_iosb.tmoff; /* + r_iosb.tmsiz;*/ X `09strncpy(nams,c_buff,j); X`09newname.dsc$w_length = j; X`09nams`5B15`5D = 0; X`09printf("Connecting to `7B%s`7D \n",nams); X`09nw++; X`09check(SYS$CREMBX(0,&w_chan`5Bnw`5D,0,0,0,0,&newname)); X`7D Xsend_psuedo() X`7B X`09int j; X`09j = r_iosb.tmoff; /* + r_iosb.tmsiz;*/ X`09r_buff`5Bj`5D = 0; X `09check(SYS$QIO(x_ef,py_chn,IO$_WRITEVBLK,&ppiosb,0,0,&r_buff,j,0,0,0,0 V)); X`09check(SYS$WAITFR(x_ef)); /* for some reason QIOW does not work V */ X `09check(ppiosb.stats); X`7D Xwaitforflag() X`7B X`09check(SYS$WFLOR(33,efmask)); X`09if (c_iosb.stats!=0) `7Bcheck(c_iosb.stats); check(SYS$CLREF(c_ef));`7D X`09if (r_iosb.stats!=0) `7Bcheck(r_iosb.stats); check(SYS$CLREF(r_ef));`7D X`09if (piosb.stats!=0) `7Bcheck(piosb.stats); check(SYS$CLREF(p_ef));`7D X`7D $ CALL UNPACK MIRROR.C;84 510870095 $ create 'f' X$ ! @ this procedure to run mirror. e.g. @USERDISK:`5BMIRROR`5DMIRROR.COM X$ ! Then answer YES on the the first terminal and NO on all others X$ ! Processes should be in the same group, or use the alternate`20 X$ ! logical name table as described at the bottom of this file. X$`20 X$ ! These lines find out where mirror is installed`20 X$ `09root = f$environment("procedure") X$ `09rootdev = f$parse(root,,,"device","syntax_only")`20 X$ `09rootdir = f$parse(root,,,"directory","syntax_only")`20 X$ `09root = rootdev+rootdir X$ X$ ! The process or image requires GRPNAM priv to use this. X$ `09define /table=lnm$process_directory lnm$temporary_mailbox lnm$group X$ ! *** This alternative logical name table doesn't require GRPNAM to be`20 X$ ! used but needs to be setup by someone with priv to start with. X$ ! define /table=lnm$process_directory lnm$temporary_mailbox lnm_mirror X$ `09inquire p1 "Is this the master (first) process" X$ `09if p1 then run 'root'mirror X$ `09if .not.(p1) then run 'root'mirrorspy X$`20 X$`20 X$ ! *** This command defines a logical name table which doesn't require grpn Vam`20 X$ ! (done in system startups) X$ ! create /name /parent=lnm$system_directory lnm_mirror /prot=w:rwed $ CALL UNPACK MIRROR.COM;7 1698851750 $ create 'f' 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 X#define bad(j) !((j) & 1) X#define check(a) if (bad(st = (a))) LIB$SIGNAL(st) X/*---------------------------------------------------------------*/ Xstruct IOSBBLK `7Bunsigned short stats, X tmoff, X tmntr, X tmsiz; X `7D; Xstruct IOSBBLK t_iosb,r_iosb,w_iosb,p_iosb,c_iosb; X#define bsize 512 Xchar t_buff`5Bbsize`5D; Xchar r_buff`5Bbsize`5D; Xchar c_buff`5Bbsize`5D; Xlong w_chan,t_chan,r_chan,tt_mb_chn,c_chan; Xunsigned efmask,st,r_ef,t_ef; X/*---------------------------------------------------------------*/ Xmain() X`7B X`09open_mailboxes(); X`09open_terminal(); X`09pre_read_term(); X`09pre_read_mail(); X`09for (;;) `7B X`09`09waitforflag(); X`09`09if (r_iosb.stats!=0) `7B print_term(); pre_read_mail(); `7D X`09`09if (t_iosb.stats!=0) `7B send_mail(); pre_read_term(); `7D X`09`7D X`7D X/*---------------------------------------------------------------*/ Xopen_terminal() X`7B X`09static $DESCRIPTOR(tt_desc,"tt"); X`09check(SYS$ASSIGN(&tt_desc,&t_chan,0,0)); X`7D Xopen_mailboxes() X`7B X`09char ss`5B22`5D; X`09static char nams`5B80`5D="MIRROR_00000000"; X X`09$DESCRIPTOR(r_name, nams); X`09$DESCRIPTOR(w_name, "MIRROR_WRITE"); X`09$DESCRIPTOR(c_name, "MIRROR_CONTROL"); X X`09sprintf(nams,"MIRROR_%X",getpid()); X`09r_name.dsc$w_length = strlen(nams); X X`09check(SYS$CREMBX(0,&c_chan,0,0,0,0,&c_name)); X`09check(SYS$CREMBX(0,&w_chan,0,0,0,0,&w_name)); X`09check(SYS$CREMBX(0,&r_chan,0,0,0,0,&r_name)); X X`09check(LIB$GET_EF(&r_ef)); X X`09strcpy(c_buff,nams); X`09check(SYS$QIO(r_ef,c_chan,IO$_WRITELBLK,&c_iosb,0,0,&c_buff,strlen(c_buff V),0,0,0,0)); X check(SYS$WAITFR(r_ef)); /* for some reason QIOW does not V work */ X`09check(c_iosb.stats); X`09printf("Now connected to Mirror process \n\n"); X`09check(LIB$GET_EF(&t_ef)); X`09efmask = (1<<(r_ef-32)) + (1<<(t_ef-32)); X`7D Xpre_read_term() X`7B X int read_mask; X t_iosb.stats = 0; X read_mask = IO$_READLBLK `7C IO$M_NOFILTR `7C IO$M_NOECHO; X check(SYS$QIO(t_ef,t_chan,read_mask,&t_iosb,0,0, X &t_buff,1,0,0,0,0)); X`7D Xpre_read_mail() X`7B X r_iosb.stats = 0; X check(SYS$QIO(r_ef,r_chan,IO$_READLBLK,&r_iosb,0,0, X &r_buff,140,0,0,0,0)); X`7D Xwaitforflag() X`7B X`09check(SYS$WFLOR(33,efmask)); X`09if (r_iosb.stats!=0) `7Bcheck(r_iosb.stats); check(SYS$CLREF(r_ef));`7D X`09if (t_iosb.stats!=0) `7Bcheck(t_iosb.stats); check(SYS$CLREF(t_ef));`7D X`7D Xprint_term() X`7B X`09char s`5B90`5D; X`09int j; X`09j = r_iosb.tmoff; /* + r_iosb.tmsiz;*/ X`09check(SYS$QIOW(0,t_chan,IO$_WRITELBLK,&p_iosb,0,0,&r_buff,j,0,0,0,0)); X`09check(p_iosb.stats); X`7D Xsend_mail() X`7B X`09int j; X`09j = t_iosb.tmoff + t_iosb.tmsiz; X`09check(SYS$QIOW(0,w_chan,IO$_WRITELBLK,&w_iosb,0,0,&t_buff,j,0,0,0,0)); X`09check(w_iosb.stats); X`7D X/* Xwaitforflag() X`7B X`09int ef; X`09check(SYS$WFLOR(1,efmask)); X`09check(SYS$READEF(1,&ef)); X`09printf("got flags %d \n",ef); X`09if (ef && (1<<(r_ef-32))) got_mail = true; X`09if (ef && (1<<(t_ef-32))) got_term = true; X`7D`09`09`09`09 X*/ Xgetpid() X`7B X`09int pid=0; X`09check(LIB$GETJPI(&JPI$_PID,&pid,0,0,0,0)); X`09return pid; X`7D $ CALL UNPACK MIRRORSPY.C;18 789806856 $ v=f$verify(v) $ EXIT