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
-------