From:	CSBVAX::MRGATE!RELAY-INFO-VAX@CRVAX.SRI.COM@SMTP 15-SEP-1988 03:42
To:	ARISIA::EVERHART
Subj:	Termlock v1.05 (part 2 of 3)


Received: From KL.SRI.COM by CRVAX.SRI.COM with TCP; Thu, 15 SEP 88 00:08:40 PDT
Received: from ucbvax.Berkeley.EDU by KL.SRI.COM with TCP; Wed, 14 Sep 88 23:58:50 PDT
Received: by ucbvax.Berkeley.EDU (5.59/1.31)
	id AA28302; Tue, 13 Sep 88 05:44:19 PDT
Received: from USENET by ucbvax.Berkeley.EDU with netnews
	for info-vax@kl.sri.com (info-vax@kl.sri.com)
	(contact usenet@ucbvax.Berkeley.EDU if you have questions)
Date: 8 Sep 88 23:40:19 GMT
From: mcmi!hdr!unocss!dent@uunet.uu.net  (Dave Caplinger)
Organization: U. of Nebraska at Omaha
Subject: Termlock v1.05 (part 2 of 3)
Message-Id: <402@unocss.UUCP>
Sender: info-vax-request@kl.sri.com
To: info-vax@kl.sri.com


+-+-+-+ Beginning of part 2 +-+-+-+
X        unsigned term_char      :24;    /* --> terminal characteristics */
X        unsigned page_length    :8;     /* --> page length goes in here */
X        unsigned extended       :32;    /* --> extended characteristics */
X        } charbuf;                      /* terminal characteristics buf */
X 
Xstruct  {
X        char    buffer[20];             /* the mailbox message info blk */
X        char    length;                 /* the current message's length */
X        char    filler;                 /* for some reason this is null */
X        char    message[100];           /* the messages sent to mailbox */
X        } mbx;
X 
Xstruct dsc {    long int len;           /* descriptors needed sometimes */
X                char     *addr;         /* using only a len and address */
X           };                           /* instead of the whole descrip */
X 
Xunion  pointer  {                       /* defines pointer type used in */
X                int  *intbuf;           /* in item lists of certain sys */
X                char *charbuf;          /* routines and stuff like that */
X                };
X 
Xstruct itmlst   {
X                unsigned short int bufferlength;
X                unsigned short int item_code;
X                union pointer  addr;
X                int  *retlength;
X                };                      /* used in some system services */
Xstruct itmlst trnlist[2];               /* Used in translating logicals */
X 
X$DESCRIPTOR(term, "SYS$OUTPUT");        /* device for in assign service */
X$DESCRIPTOR(mbx_name, "REPLY_MBX");     /* mailbox to send messages out */
X 
Xchar    *local_node = "SYS$NODE";       /* local node name (for DECNET) */
Xchar    *rscs_node  = "SYS$RSCS_NODE";  /* network node name (for JNET) */
Xchar    *jan_node   = "JAN_LOCAL_NODE"; /* new network name (JNET V3.2) */
X 
Xstruct  dsc$descriptor_s header_dsc =
X        { 20, DSC$K_DTYPE_T, DSC$K_CLASS_S, header.date };
X 
X/***********************************************************************/
X/* Set up an AST handler for any trapped messages that come our way... */
X/***********************************************************************/
X 
Xget_msg()
X{
Xint`009start = 0;
X
X        get_time();                             /* gets a time and date */
X`009while (!isalpha(mbx.message[start]) && (mbx.message[start] != '('))
X`009    mbx.message[start++] = ' ';
X        mbx.message[mbx.length] = 0;            /* null terminates msgs */
X
X        if (mbx.length != 0) {                  /* only continue if msg */
X           get_name(start);                     /* gets a name and node */
X
X`009   if ((!ignore) && ((send) || (file) || (phone))) {
X`009`009user_cnt++;
X`009`009reset_input();
X`009   } else if ((!ignore) && ((mail) || (job) || (reply))) {
X`009`009sys_cnt++;
X`009`009reset_input();
X`009   }
X
X`009   if (!ignore) {
X`009`009fprintf(fp,"%s\n", header.weekday);  /* print time log notes */
X`009`009fprintf(fp,"%s\n", mbx.message);     /* puts message to file */
X`009   }
X        }
X        status=sys$qio(3,msg_chan,IO$_READVBLK  /* - do read on mailbox */
X                ,0,get_msg,0,&mbx,120,0,0,0,0); /* - with an AST finish */
X}
X
X
Xchar *bad_signal(char *sigargs[], char *mechargs[5])
X{
X
X`009if ((errno) || (status != 1)) {
X`009`009printf("\n\n\nBoom!");
X`009`009printf("\n\007\007\007Error code:%d",errno);
X`009`009printf("\n\007Status code:%d",status);
X`009`009printf("\npid=%d\n",mypid);
X`009`009sys$delprc(&mypid,0);
X`009`009printf("error: process continuing\n");
X`009`009printf("procname=%s\n",myprocname);
X`009`009sys$delprc(0,&myprocname);
X`009`009printf("error: pass 2 failed; process continuing\n");
X`009`009exit(0);
X`009}
X}
X
X 
X/***********************************************************************/
X/* The main control loop... Set up message, initialize stuff, and wait */
X/***********************************************************************/
X 
Xmain(argc, argv)
Xint     argc;
Xchar    **argv;
X{
X`009char cmd[2];
X 
X`009lib$getjpi(JPI$_PID,&mypid);
X`009lib$getjpi(JPI$_USERNAME,0,&myprocname);
X`009cuserid(myself);
X
X`009lib$establish(bad_signal);
X
X`009printf("TERMLOCK activated; Please wait.\n");
X
X/* First, get the reply message to send and set up the command line... */
X 
X        if (argc > 2) 
V        { printf("FORMAT: TERMLOCK\n    or  TERMLOCK \"REPLY STRING\"\n" ); exi
Xt(); }
X 
X        if ((argc == 2) && (strlen(argv[1]) < 101))
X`009    strcpy(reply_string, argv[1]);
X`009else if (argc == 2) {
X`009    strncpy(reply_string, argv[1], 100);
X`009    reply_string[strlen(reply_string)] = '\0';
X`009}
X
X        initialize();                           /* open file, do screen */
X        password[0] = 0;
X        while (status) {                  /* while no errors here */
X                status = sys$qiow(2,tt_chan,97,0,0,0,&cmd,1,0,0,0,0);
X                switch (toupper(cmd[0])) {      /* input a character... */
X                        case 'Q': leave_reply();/* quits if it is a 'Q' */
X`009`009`009`009  break;
X`009`009`009case 'E': call_editor();/* call editor on log   */
X`009`009`009`009  break;
X                        case 'V': view_messages();/* view  messages-'V' */
X`009`009`009`009  break;
X                        case 'L': lock_term();  /* lock the term on 'L' */
X`009`009`009`009  break;
X                        case 'U': unlock_term();/* unlock term on a 'U' */
X`009`009`009`009  break;
X`009`009`009case 23 : draw_screen();/* redraw on control-w! */
X                 }                              /* otherwise ignores it */
X        }
X        lib$signal(status);                     /* report the error msg */
X}
X 
X/***********************************************************************/
X/* Close files, clear screen, tie up loose ends,  then exit this mess! */
X/***********************************************************************/
X 
Xleave_reply()
X{
X        if (unlock_term() != 0) return;         /* no leaving if locked */
X        uninitialize();                         /* kill everything here */
X`009reset_terminal();`009`009`009/* reset and close file */
X        sys$dassgn(tt_chan);                    /* deassign the channel */
X`009printf("%c[24;1H",esc);`009`009`009/* put cursor at bottom */
X        exit();
X}
X 
X/***********************************************************************/
X/* Close up our log file and remove all the mailbox stuff please.      */
X/***********************************************************************/
X 
Xuninitialize()
X{
X        sys$delprc(&pid,0);                     /* kills the subprocess */
X        sys$delmbx(mbx_chan);                   /* kill its mailbox too */
X        sys$delmbx(msg_chan);                   /* zap terminal mailbox */
X        sys$cantim(0,3);                        /* cancels update timer */
X}
X 
X/***********************************************************************/
X/* Reset the terminal characteristics, kill ast traps, kill timer, etc */
X/***********************************************************************/
X 
Xreset_terminal()
X{
X        sys$cancel(tt_chan);                    /* cancels terminal I/O */
X        charbuf.term_char = old_term_char;      /* restore the old term */
X        charbuf.extended = old_extended;        /* characteristics back */
X        sys$qiow(0,tt_chan,IO$_SETMODE,0,0,0,   /* so they can get msgs */
X                 &charbuf,12,0,0,0,0);          /* again to their term! */
X`009fclose(fp);
X`009lib$enable_ctrl(&old_ctrl);`009`009/* put back ctrl keys   */
X        sys$setast(0);                          /* disable the ast call */
X}
X 
X/***********************************************************************/
X/* Sets up the display, open log file, sets up the mailbox stuff, etc. */
X/***********************************************************************/
X 
Xinitialize()
X{
Xint      len;
Xunsigned no_ctrlt; 
X
X        open_file();                            /* open the file again */
X 
X/* Find out our local and rscs node names from translating logicals now */
X 
X        decnet_node = tranlog(local_node,0);    /* translate a logical */
X
X        len  = strlen(decnet_node)-2;           /* skip the "::" of it */
X        if (len <= 0) {                         /* make sure it exists */
X                printf("?Logical name SYS$NODE must be defined to use REPLY");
X                exit();                         /* if not then exit... */
X        }
X        bitnet_node = tranlog(rscs_node,0);     /* try translating this */
X        if (*bitnet_node == 0)`009`009`009/* if none then try new */
X           bitnet_node = tranlog(jan_node,0);   /* jnet version logical */
X        if (*bitnet_node == 0) 
X`009   strcpy(bitnet_node,decnet_node);     /* uses other if none.  */
X 
X/* Create mailbox thru which we send replys, create subprocess to do it */
X 
X        status = sys$crembx(0,&mbx_chan,0,0,240,0,&mbx_name);
X        if (status != 1) lib$signal(status);
X 
X        status = lib$spawn(0,&mbx_name,0,&1,0,&pid);
X        if (status != 1) lib$signal(status);
X 
X        status = lib$asn_wth_mbx(&term,&0,&0,&tt_chan,&msg_chan);
X        if (status != 1) lib$signal(status);
X
X/* Disable all error-related messages in the sub-process                */
X
X`009status = sys$qiow(0,mbx_chan,IO$_WRITEVBLK,0,0,0,
X`009`009&"set message/nofacility/noid/noseverity/notext",
X`009`00945,0,0,0,0);
X`009if (status != 1) lib$signal(status);
X
X/* Disable ^T,  save old mask so we can put it back.                    */
X
X`009lib$disable_ctrl(&no_ctrlt,&old_ctrl);
X
X/* Set up the terminal so that everything works and draw a neat display */
X 
X        setup_term();
X}
X 
X/***********************************************************************/
X/* Open the message log file in append mode, if an error, then exit... */
X/***********************************************************************/
X 
Xopen_file()
X{
Xchar    junk[128];
X 
X`009user_cnt = sys_cnt = old_cnt = 0;`009/* start with no msgs. */
X        fp=fopen("sys$login:termlock.log","r"); /* try opening my file */
X 
X        if (fp != NULL) {                       /* if it exists,  then */
X           old_cnt--;                           /* (otherwise one off) */
X           do { fgets(junk,128,fp);             /* gets line from file */
X                old_cnt++;                      /* increments counters */
X                }                               /* repeat loop til eof */
X           while (feof(fp) != 1);               /* count := msg's * 2  */
X        old_cnt = old_cnt / 2;                  /* gets the real count */
X        fclose(fp);                             /* close file up again */
X        }
X 
X        fp=fopen("sys$login:termlock.log","a+");/* open the file again */
X
X        if  (fp == NULL) {                      /* check for errors... */
X              printf("?Error opening file SYS$LOGIN:TERMLOCK.LOG");
X        }
X}
X 
X
X/* Called on ^Y AST - ring the bell to make some noise. */
Xdo_nothing()
X{
X`009printf("\007");
X`009return;
X}
X
X/***********************************************************************/
X/* Set up the terminal display,  and save/set terminal characteristics */
X/***********************************************************************/
X 
Xsetup_term()
X{
Xint     mask[1];
X 
X        status = sys$qiow(0,tt_chan,IO$_SENSEMODE,0,0,0,&charbuf,12,0,0,0,0);
X        if (status != 1) lib$signal(status);
X 
X        old_term_char = charbuf.term_char;      /* saves chars for exit */
X        old_extended = charbuf.extended;        /* saves extendeds too! */
X 
X        charbuf.term_char = charbuf.term_char   /* SET TERM/NOBROADCAST */
X                |TT$M_MBXDSABL|TT$M_NOBRDCST;   /* (also sets MBXDSABL) */
X        charbuf.extended = charbuf.extended     /* SET TERM/BRDCSTMBX   */
X                |TT2$M_BRDCSTMBX;               /* so we receive in mbx */
X 
X        status = sys$qiow(0,tt_chan,IO$_SETMODE,0,0,0,&charbuf,12,0,0,0,0);
X        if (status != 1) lib$signal(status);
X 
X/* Sets up an out of band ast trap for any control C or control Y chars */
X
X        mask[0] = 0; mask[1] = 33554440;        /* mask for ^C/^Y chars */
X        status = sys$qiow(4,tt_chan,            /* sets up the ast trap */
X                IO$_SETMODE|IO$M_OUTBAND,       /* for ^C/^Y characters */
X                0,0,0,do_nothing,mask,0,0,0,0); /* so no naughty exits! */
X        if (status != 1) lib$signal(status);    /* an error setting it? */
X
X/* Disable ^T so that malicious passersby can't fill our file.          */
X
X`009lib$disable_ctrl(&no_ctrlt);
X
X/* Fix a gap in the time/date/day header so that we have a neat display */
X 
X        strcpy(header.filler," ");              /* make display neat... */
X`009draw_screen();
X
X/* Queue an ast routine to read from the terminal's message mailbox... */
X 
X        sys$setast(1);                          /* enable ast delivery */
X
X/* This loads status, which is tested in the WHILE statement of main() */
X
X        status=sys$qio(3,msg_chan,IO$_READVBLK,0,get_msg,0,&mbx,120,0,0,0,0);
X}
X 
X
X/***********************************************************************/
X/*  Actually draw the screen display                                   */
X/***********************************************************************/
X
Xdraw_screen()
X{
Xprintf("%c[2J%c[H",esc,esc);
Xprintf("                Vax Automatic Message Reply Facility  v1.05\n");
Xprintf("      --------------------------------------------------------------");
Xprintf("\n");
Xprintf("       L to LOCK the terminal\n");
Xprintf("       U to UNLOCK the terminal\n");
Xprintf("       E to EDIT message file\n");
Xprintf("       V to VIEW message file\n");
Xprintf("       Q to QUIT this program\n\n\n");
Xprintf("      --------------------------------------------------------------");
Xprintf("\n");
Xreset_input();
X}
X 
X
X/***********************************************************************/
X/* get the time and date so we can log it to a file or screen display. */
X/***********************************************************************/
X 
Xget_time()
X{
Xint      i;                                     /* counter variables... */
Xunsigned int j[4];                              /* holds internal times */
X 
Xstatic     char day_list[] =
X"Monday,   Tuesday,  Wednesday,Thursday, Friday,   Saturday, Sunday,   ";
X 
X        lib$date_time(&header_dsc);             /* get the current time */
X 
X        sys$gettim(&j[0]);                      /* and an internal time */
X        lib$day_of_week(&j[0], &i);             /* gets day of the week */
X        i = (i - 1) * 10;                       /* calculate offset now */
X 
X        strncpy(header.weekday,&day_list[i],10);/* put in output buffer */
X}
X 
X/***********************************************************************/
X/* reset the cursor to command line, used after message or bad command */
X/***********************************************************************/
X 
Xreset_input()
X{
X           printf("%c[3;42H%d User messages received",esc,user_cnt);
-+-+-+-+-+ End of part 2 +-+-+-+-+-

