ASBED@ACRUX.USC.EDU (Liquid Len) (06/23/87)
I've had a PHOTO program that does session logging that will avoid your having to go through SET HOST/LOG. It is written in C, and uses KVC's (or, alternately, CMU's) PseudoTerminal driver. I have embellished the program with a couple of features which turn on and off during a part of the session, another which turns on and off time-stamping, and it accepts a filename for logfile (optional. default is PHOTO.LOG) I have documentation which can go right into your help library. If you are interested, write me, and I will mail it out to you. I have not made a shar of this. All you'd need is to compile and link the source (C) and insert the help in your preferred help library. ---------------- Asbed Bedrossian, University Computing Services, U of Southern California ARPA: asbed@oberon.usc.edu BITNET: asbed@uscvaxq UUCP: {sdcrdcf, cit-vax}!oberon!asbed PHONE: (213) 743-4266 -------
ASBED@acrux.usc.EDU (Liquid Len) (06/29/87)
Surely, I did not expect such a deluge of requests for this facility. It's been collecting dust among other sources for years now... Anyway, I've had trouble contacting some of the requestors. And then I am starting to fall behind due to the volume of requests. So I have put PHOTO.C, PHOTO.CLD and PHOTO.HLP in ~ftp/pub on oberon.usc.edu, thus making it available via anonymous ftp. Instructions are in PHOTO.README. (filenames are not uppercased) Enjoy. _________________________________________________________________________ Asbed Bedrossian, University Computing Services, U of Southern California ARPA: asbed@oberon.usc.edu BITNET: asbed@uscvaxq UUCP: {sdcrdcf, cit-vax}!oberon!asbed PHONE: (213) 743-4266 -------
ASBED@ACRUX.USC.EDU (Liquid Len) (07/09/87)
Ok Ok! You asked for it... Cut where it says cut here, and put it in a COM file and execute it. It works for me, so obviously it'll work for you too. :-) It yields PHOTO.C, PHOTO.CLD, PHOTO.HLP. Then it formats the HLP file into PHOTO.HLB which you can insert into your local/system help library. Then It compiles and links(/notrace) the source file, so you can put it in your system directory and install it (with priv PHY_IO) The CLD file can go into your favorite DCLtables. All instructions are at the top of the source file. Best-o-luck. Let me know if you have problems. _________________________________________________________________________ Asbed Bedrossian, University Computing Services, U of Southern California ARPA: asbed@oberon.usc.edu BITNET: asbed@uscvaxq UUCP: {sdcrdcf, cit-vax}!oberon!asbed PHONE: (213) 743-4266 $!============================= Cut Here =============================== $ $ Create Photo.C $ Deck /* PHOTO.C * * Copywrite 1986, University of Southern California * Author - Asbed Bedrossian * This program may be copied or distributed for any non-commercial * purpose, as long as this notice remains intact. * * This program is used to log a terminal session. * * Compile: CC PHOTO * Link: LINK/NOTRACE PHOTO * Place: SYS$SYSTEM: * Install: INSTALL> ADD SYS$SYSTEM:PHOTO/PRIV=PHY_IO * * For proper execution, You will need to install KVC's PseudoTerminal * driver on your system. You need PYDRIVER.EXE and PTDRIVER.EXE. * (Available through anonymous FTP from somewhere) * These drivers can be installed with the following SYSGEN commands: * SYSGEN> RELOAD SYS$SYSTEM:PTDRIVER * SYSGEN> CONNECT TPA0/NOADAPTER/DRIVER=PTDRIVER * SYSGEN> RELOAD SYS$SYSTEM:PYDRIVER * SYSGEN> CONNECT PYA0/NOADAPTER/DRIVER=PYDRIVER * * Note: that really is TPA0 and not PTA0. I didn't mistype it. The * change took effect ever since DEC came up with a PTA0:. * */ #include DESCRIP #include FAB #include IODEF #include RAB #include TTDEF #include TT2DEF #include stdio #define CR 13 #define LF 10 #define logchar 28 /* Logging on/off flag ^\ */ #define timchar 29 /* Time logging flag ^] */ #define ttchrlen 12 #define tpdevlen 15 #define mbsiz 40 #define maxsiz 80 #define linesz 512 #define bad(j) !(j & 1) #define check(a) st=a; if (bad(st)) LIB$SIGNAL(st) #define garbage(a) (a == CR) || (a == LF) || (!a) struct CHARBLK {unsigned char class, ttype; unsigned short pgwid; unsigned ttchr : 24; unsigned char pglen; unsigned int xchar; }; struct IOSBBLK {unsigned short stats, tmoff, tmntr, tmsiz; }; long py_chn, py_mb_chn, tt_chn, tt_mb_chn, pid, st; char finaltp[tpdevlen], line[linesz], time[24], py_mb[mbsiz], tt_mb[mbsiz], ttline[linesz], tpline[linesz], tim= 0, com= 0, log= 1, enable_hangups= 0; struct CHARBLK tt_chr, tt_sav_chr; struct IOSBBLK tiosb, piosb, miosb; struct FAB zfab; struct RAB zrab; quit() /* This is done upon exiting, by exit handler */ {int j; j= SYS$DELMBX(py_mb_chn); if (bad(j)) printf("[SYS$DELMBX pseudo-mbx deletion failed]\n"); j= SYS$QIOW(0,tt_chn,IO$_SETMODE,0,0,0,&tt_sav_chr,ttchrlen,0,0,0,0); if (bad(j)) printf("[SYS$QIO /setmode/ failed]\n"); printf("\nEnd PHOTO session\n"); } low_lib_spawn(pty_io,pid) /* Spawns subprocess to speaks to pseudo terminal */ char *pty_io; int *pid; {int flg= 1; $DESCRIPTOR(d_pty_io, pty_io); /* PTY name + number */ d_pty_io.dsc$w_length= strlen(pty_io); st= LIB$SPAWN(0,&d_pty_io,&d_pty_io,&flg,0,pid,0,0,0,0,0,0); return(st); } asctim() /* Returns Time-stamp info */ {char buf[24]; $DESCRIPTOR(d_asctim,&buf); check(SYS$ASCTIM(0,&d_asctim,0,0)); buf[20]= 0; sprintf(&time,"[%s]",&buf); } toggle(swtch) /* Set switches as desired */ char swtch; {char buf[40]; if (swtch == logchar) { log= !log; if (log) sprintf(&buf,"Logging has been ENABLED\r\n"); else sprintf(&buf,"Logging has been DISABLED\r\n"); } else { tim= !tim; if (tim) sprintf(&buf,"Time stamping has been ENABLED\r\n"); else sprintf(&buf,"Time stamping has been DISABLED\r\n"); } check(SYS$QIOW(0,tt_chn,IO$_WRITEVBLK,0,0,0,&buf,strlen(&buf),0,0,0,0)); } tp_srv() /* AST: on pseudo terminal. Deals with spurious hangups */ { check(miosb.stats); if (enable_hangups) exit(1); else check(SYS$QIO(0,py_mb_chn,IO$_READVBLK,&miosb,&tp_srv,0,&py_mb,mbsiz,0,0,0,0)); } tt_srv() /* AST: Read on real terminal */ {int j; check(tiosb.stats); /* Read everything typed right away */ check(SYS$QIOW(0,tt_chn,IO$_READVBLK|IO$M_TIMED,&tiosb,0,0,&ttline,linesz,0,0,0,0)); j= tiosb.tmoff + tiosb.tmsiz; /* How many chars read */ com= ttline[0] == CR; if (com) { if (tim) asctim(); /* Time stampi info */ } else if ((ttline[0] == logchar) || (ttline[0] == timchar)) /* flags */ toggle(ttline[0]); /* write everything we read to pseudo-terminal */ check(SYS$QIOW(0,py_chn,IO$_WRITEVBLK,&tiosb,0,0,&ttline,j,0,0,0,0)); check(tiosb.stats); /* re-post read AST on real term */ check(SYS$QIO(0,tt_mb_chn,IO$_READVBLK,&tiosb,&tt_srv,0,&tt_mb,mbsiz,0,0,0,0)); } char *clean_up(num) int *num; {int j= 0, k; char *rad; rad= &tpline; k= *num; while ((garbage(tpline[j])) && (k)) /* Kill beginning of line CR&LFs */ { rad++; k--; j++; } j= *num - 1; while ((garbage(tpline[j])) && (k)) /* Kill end of line CR&LFs */ { tpline[j--]= 0; k--; } *num= k; return(rad); } log_line(num) /* This logs the input into a file */ int num; {char *rad, eol; eol= garbage(tpline[num-1]); rad= clean_up(&num); /* strip line of extraneous CRLFs */ strncat(&line,rad,num); if (eol) { num= strlen(&line); line[num]= 0; zrab.rab$l_rbf= &line; zrab.rab$w_rsz= num; check(SYS$PUT(&zrab,0,0)); /* write line into file */ line[0]= 0; if ((com) && (tim)) /* are we Time-stamping? */ { zrab.rab$l_rbf= &time; zrab.rab$w_rsz= strlen(&time); check(SYS$PUT(&zrab,0,0)); /* if yes: write Time-stamp in file */ } } } get_file(filspec) /* Sets up a file RAB and FAB */ char *filspec; { zfab= cc$rms_fab; zrab= cc$rms_rab; zfab.fab$b_fac= FAB$M_GET+FAB$M_PUT; zfab.fab$l_fna= filspec; zfab.fab$b_fns= strlen(filspec); zfab.fab$b_org= FAB$C_SEQ; zfab.fab$b_rat= FAB$M_CR; zfab.fab$b_rfm= FAB$C_VAR; zfab.fab$b_shr= FAB$M_SHRPUT | FAB$M_SHRGET | FAB$M_UPI; check(SYS$CREATE(&zfab,0,0)); zrab.rab$l_fab= &zfab; zrab.rab$w_isi= 0; zrab.rab$l_rop= RAB$M_EOF; check(SYS$CONNECT(&zrab, 0, 0)); zrab.rab$b_rac= RAB$C_SEQ; zrab.rab$l_rop= RAB$M_WBH; } get_tt_info() { $DESCRIPTOR(d_tt, "SYS$COMMAND"); /* Get a channel & mailbox of terminal */ check(LIB$ASN_WTH_MBX(&d_tt,&mbsiz,&maxsiz,&tt_chn,&tt_mb_chn)); /* Get the terminal characteristics. */ check(SYS$QIOW(0,tt_chn,IO$_SENSEMODE,0,0,0,&tt_chr,ttchrlen,0,0,0,0)); tt_sav_chr= tt_chr; tt_chr.ttchr|= TT$M_NOECHO; /* term will be Noecho */ tt_chr.ttchr&= ~TT$M_HOSTSYNC & ~TT$M_TTSYNC; /* it will have ^S */ tt_chr.xchar|= TT2$M_PASTHRU; /* it will be PASTRHU */ check(SYS$QIOW(0,tt_chn,IO$_SETMODE,0,0,0,&tt_chr,ttchrlen,0,0,0,0)); } fix_a_tp() /* Set up a Pseudo term */ {int efn=1, f1[3], tp_chn; struct IOSBBLK iosb; $DESCRIPTOR(d_pynam,"PYA0:"); /* Template. */ $DESCRIPTOR(d_finaltp, &finaltp); /* Assign a mailbox to PYA */ check(LIB$ASN_WTH_MBX(&d_pynam,&mbsiz,&maxsiz,&py_chn,&py_mb_chn)); /* this gives us a TPA number through SENSEMODE */ check(SYS$QIOW(0,py_chn,IO$_SENSEMODE,&iosb,0,0,&f1,ttchrlen,0,0,0,0)); sprintf(&finaltp,"TPA%d:",iosb.tmntr); /* see? */ d_finaltp.dsc$w_length= strlen(&finaltp); check(SYS$ASSIGN(&d_finaltp,&tp_chn,0,0)); /* Get a channel on this TPA */ /* Make it look like a terminal */ check(SYS$QIOW(0,tp_chn,IO$_SETCHAR,0,0,0,&tt_sav_chr,ttchrlen,0,0,0,0)); check(SYS$DASSGN(tp_chn)); /* We don't need it. only the mailbox */ /* in fact keeping it kills us. */ } post_reads() /* This sets up ASTs */ { /* Read AST on Pseudo-term */ check(SYS$QIO(0,py_mb_chn,IO$_READVBLK,&miosb,&tp_srv,0,&py_mb,mbsiz,0,0,0,0)); /* Read AST on real term */ check(SYS$QIO(0,tt_mb_chn,IO$_READVBLK,&tiosb,&tt_srv,0,&tt_mb,mbsiz,0,0,0,0)); } begin_session() {int j; for(;;) /* Read/write forever loop */ { /* Read the pseudo-term dry */ check(SYS$QIOW(0,py_chn,IO$_READVBLK,&piosb,0,0,&tpline,linesz,0,0,0,0)); check(piosb.stats); /* everything fine? */ j= piosb.tmoff + piosb.tmsiz; /* How much stuff did we read? */ /* Write the stuff to the terminal */ check(SYS$QIO(1,tt_chn,IO$_WRITEVBLK,&tiosb,0,0,&tpline,j,0,0,0,0)); check(SYS$WAITFR(1)); /* for some reason QIOW does not work */ if (log) { log_line(j); /* If we're looging, log it. */ if ((tim) && (com)) { sprintf(&time,"%s\r\n",&time); /* Time stamp */ check(SYS$QIOW(0,tt_chn,IO$_WRITEVBLK,0,0,0,&time,strlen(&time),0,0,0,0)); com= 0; } } } } main(how_many,rscan) int how_many; char *rscan[]; {int exit_handler[4]= {0,quit,0,&st}; char filnam[40]; check(SYS$DCLEXH(&exit_handler)); /* Define Exit handler (quit) */ if (how_many > 1) strcpy(&filnam,rscan[1]); else strcpy(&filnam,"Photo.Log"); /* default log file if none specified */ get_file(filnam); /* Open the file */ get_tt_info(); /* Get terminal channel & info */ fix_a_tp(); /* Set a pseudo terminal by TT info */ check(SYS$CANCEL(py_chn)); /* Don't need this Half of pseudo-ter */ check(low_lib_spawn(&finaltp,&pid)); /* Spawn a subprocess. */ post_reads(); enable_hangups= 1; printf("Begin PHOTO session\n"); begin_session(); } $EOD $ $ Create Photo.Cld define verb PHOTO image sys$system:photo parameter p1 value(type=$rest_of_line) $ $ Create Photo.Hlp 1 Photo !******************************************************** !* * !* * !* Photo * !* * !* * !******************************************************** Photo copies all of the Input/Output (IO) that appears on the terminal to a file. It is useful for turning in homework assignments, which do most of their IO to the terminal. Format: $ PHOTO [FILENAME.EXT] This starts recording, and creates a file called FILENAME.EXT in the user's current directory. If a filename is not specified, the default filename is PHOTO.LOG, in the user's current directory. To end PHOTO, either LOGOUT or POP. 2 Author Photo was written by Asbed Bedrossian. The program uses the PTDRIVER PYDRIVER combination to trap terminal IO on a pseudoterminal. The PT/PY package is the latest update from Kevin Carosso (@Hughes) on the old PTYDRIVER. 2 Usage Photo is a predefined command. The character ^\ toggles logging to the photo file. The character ^] toggles Time stamping. Time stamping will appear as the date and time in square brackets after every command the user types on the terminal. $ $ Library/Create/Help Photo.Hlb Photo.Hlp $ Cc Photo $ Link/Notrace Photo $ Exit -------