From:	CSBVAX::CSBVAX::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX" 18-MAR-1989 23:03
To:	MRGATE::"ARISIA::EVERHART"
Subj:	Termlock v1.16, part 3 of 5


Received: From KL.SRI.COM by CRVAX.SRI.COM with TCP; Tue, 14 MAR 89 09:00:47 PDT
Received: from ucbvax.Berkeley.EDU by KL.SRI.COM with TCP; Tue, 14 Mar 89 08:58:55 PST
Received: by ucbvax.Berkeley.EDU (5.61/1.36)
	id AA05067; Tue, 14 Mar 89 08:39:59 -0800
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: 9 Mar 89 05:15:34 GMT
From: ssbell!mcmi!amperif!unocss!dent@uunet.uu.net  (Dave Caplinger)
Organization: U. of Nebraska at Omaha
Subject: Termlock v1.16, part 3 of 5
Message-Id: <704@unocss.UUCP>
Sender: info-vax-request@kl.sri.com
To: info-vax@kl.sri.com


+-+-+-+ Beginning of part 3 +-+-+-+
X`009unsigned cond_address   :32;
X`009`125 exit_handler_block;
X
Xunsigned long exit_status;
X`032
X$DESCRIPTOR(term, "SYS$OUTPUT");        /* device for in assign service */
X$DESCRIPTOR(mbx_name, "TERMLOCK_MBX");     /* mailbox to send messages out */
X`032
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`032
Xstruct  dsc$descriptor_s header_dsc =
X        `123 20, DSC$K_DTYPE_T, DSC$K_CLASS_S, header.date `125;
X`032
X/***********************************************************************/
X/* Set up an AST handler for any trapped messages that come our way... */
X/***********************************************************************/
X`032
Xget_msg()
X`123
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) `123                  /* only continue if msg */
X           get_name(start);                     /* gets a name and node */
X
V`009   if ((!ignore) && ((send) `124`124 (file) `124`124 (phone) `124`124 (cm
Xd))) `123
X`009`009user_cnt++;
X`009`009reset_input();
V`009   `125 else if ((!ignore) && ((mail) `124`124 (job) `124`124 (reply))) `
X123
X`009`009sys_cnt++;
X`009`009reset_input();
X`009   `125
X
X`009   if (!ignore) `123
X`009`009fprintf(fp,"%s\n", date_string);     /* print time log notes */
X`009`009fprintf(fp,"%s\n", mbx.message);     /* puts message to file */
X`009   `125
X        `125
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`125
X
X/*
X *   logout the process (in case of a fatal error)...
X *   Note:  Also called in case a SYS$FORCEX from someone forces an exit.
X */
Xlogout()
X`123
X`009unsigned int id;
X
X`009uninitialize();`009`009`009/* Straight from leave_reply() */
X`009reset_terminal();
X`009sys$dassgn(tt_chan);
X
X`009cgoto(24,1);`009`009`009/* drop cursor to bottom */
X
X`009id = getpid();`009`009`009/* Get the process ID and kill it. */
X`009sys$delprc(&id, 0);
X`125
X
X/*
X *   generic signal handler for lib$signal(status)
X */
Xchar *bad_signal(char *sigargs[], char *mechargs[5])
X`123
X
X`009if ((errno) `124`124 (status != 1)) `123
X`009`009printf("\n\n\nBoom!\n");
X`009`009printf("Error code:%d\n",errno);
X`009`009printf("Status code:%d",status);
X
X`009`009logout();
X`009`125
X`125
X
X`032
X/***********************************************************************/
X/* The main control loop... Set up message, initialize stuff, and wait */
X/***********************************************************************/
X`032
Xmain(argc, argv)
Xint     argc;
Xchar    **argv;
X`123
X`009char cmd[2];
X`009char *junk;
X`009char *user_logfile = "TERMLOCK$LOGFILE";
X`009char *sys_timeout  = "TERMLOCK$SYSTEM_TIMEOUT";
X`009char *user_timeout = "TERMLOCK$TIMEOUT";
X`032
X`009printf("TERMLOCK %s activated; Please wait.\n",VERSION);
X
X`009junk = tranlog(user_logfile,1);
X`009if (*junk != 0) `123
X`009  strcpy(LOGFILE, junk);
X`009  printf("Using %s as the logfile...\n",LOGFILE);
X`009`125 else
X`009  LOGFILE[0] = '\0';
X
X
X`009START_TIME = TIME_OUT = 0;
X
X`009junk = tranlog(user_timeout,1);      /* check user-defined timeout */
X`009if (*junk != 0) `123
X`009  if (strlen(junk) > 5) junk[5] = '\0';
X`009  TIME_OUT = atoi(junk);
X`009  if (TIME_OUT < 0) TIME_OUT = 0;
X`009  if (TIME_OUT != 0) printf(
X            "TERMLOCK will log out this process in %d minutes.\n\n"
X            ,TIME_OUT);
X`009`125
X
X`009junk = tranlog(sys_timeout,0);     /* override with system timeout */
X`009if (*junk != 0) `123
X`009  if (strlen(junk) > 5) junk[5] = '\0';
X`009  if (TIME_OUT < 0) TIME_OUT = 0;
X`009  if ((TIME_OUT == 0) `124`124 (TIME_OUT >= atoi(*junk)))
X`009    TIME_OUT = atoi(junk);
X  `009  if (TIME_OUT != 0) printf(
V      "TERMLOCK will log out this process in %d minutes by system default.\n\
Xn"
X            ,TIME_OUT);
X`009`125
X
X        if (TIME_OUT != 0) `123
X`009  TIME_OUT = 2 * TIME_OUT;         /* (using 30-second intervals)  */
X`009`125
X
X`009cuserid(myself);
X`009lib$establish(bad_signal);
X
X`009exit_handler_block.forward_link = 0;
X`009exit_handler_block.address = logout;
X`009exit_handler_block.arg_count = 0;
X`009exit_handler_block.cond_address = &exit_status;
X
X`009status = sys$dclexh(&exit_handler_block);
X`009if (status != 1) lib$signal(status);
X
X/* First, get the reply message to send and set up the command line... */
X`032
X        if (argc > 2) `123
V             printf("FORMAT: TERMLOCK\n    or  TERMLOCK \"REPLY STRING\"\n" )
X;
X`009     nice_exit();
X`009`125
X
X        if ((argc == 2) && (strlen(argv[1]) < 101))
X`009    strcpy(reply_string, argv[1]);
X`009else if (argc == 2) `123
X`009    strncpy(reply_string, argv[1], 100);
X`009    reply_string[strlen(reply_string)] = '\0';
X`009`125
X
X        initialize();                           /* open file, do screen */
X        password[0] = 0;
X        while (status) `123                  /* 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])) `123      /* 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                 `125                              /* otherwise ignores it */
X        `125
X        lib$signal(status);                     /* report the error msg */
X`125
X`032
X/***********************************************************************/
X/* Close files, clear screen, tie up loose ends,  then exit this mess! */
X/***********************************************************************/
X`032
Xleave_reply()
X`123
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
X`009cgoto(24,1);`009`009`009`009/* put cursor at bottom */
X
X`009nice_exit();
X`125
X
Xnice_exit()
X`123
X`009/* Since this is a normal exit, we have to delete our
X`009    previously defined exit-handler... */
X
X`009status = sys$canexh(&exit_handler_block);
X`009if (status != 1) lib$signal(status);
X
X        exit();         /* normal exit back to DCL... */
X`125
X`032
X/***********************************************************************/
X/* Close up our log file and remove all the mailbox stuff please.      */
X/***********************************************************************/
X`032
Xuninitialize()
X`123
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`125
X`032
X/***********************************************************************/
X/* Reset the terminal characteristics, kill ast traps, kill timer, etc */
X/***********************************************************************/
X`032
Xreset_terminal()
X`123
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`125
X`032
X/***********************************************************************/
X/* Sets up the display, open log file, sets up the mailbox stuff, etc. */
X/***********************************************************************/
X`032
Xinitialize()
X`123
Xint      len;
Xunsigned no_ctrlt;`032
X
X        open_file();                            /* open the file again */
X`032
X/* Find out our local and rscs node names from translating logicals now */
X`032
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) `123                         /* make sure it exists */
X            printf("?Logical name SYS$NODE must be defined to use TERMLOCK");
X            nice_exit();                        /* if not then exit... */
X        `125
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)`032
X`009   strcpy(bitnet_node,decnet_node);     /* uses other if none.  */
X`032
X/* Create mailbox thru which we send replys, create subprocess to do it */
X`032
X        status = sys$crembx(0,&mbx_chan,0,0,240,0,&mbx_name);
X        if (status != 1) lib$signal(status);
X`032
X        status = lib$spawn(0,&mbx_name,0,&1,0,&pid);
X        if (status != 1) lib$signal(status);
X`032
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 `094T,  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`032
X        setup_term();
X`125
X`032
X/***********************************************************************/
X/* Open the message log file in append mode, if an error, then exit... */
X/***********************************************************************/
X`032
Xopen_file()
X`123
Xchar    junk[128];
X`032
X`009user_cnt = sys_cnt = old_cnt = 0;`009/* start with no msgs. */
X        fp=fopen((LOGFILE[0]) ? LOGFILE : "SYS$LOGIN:TERMLOCK.LOG",
X`009`009"r","rat=cr","rfm=var");       /* try opening my file */
X`032
X        if (fp != NULL) `123                       /* if it exists,  then */
X           old_cnt--;                           /* (otherwise one off) */
X           do `123 fgets(junk,128,fp);             /* gets line from file */
X                old_cnt++;                      /* increments counters */
X                `125                               /* 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        `125
X`032
X        fp=fopen((LOGFILE[0]) ? LOGFILE : "SYS$LOGIN:TERMLOCK.LOG",
X`009`009"a+","rat=cr","rfm=var");      /* open the file again */
X
X        if  (fp == NULL) `123                      /* check for errors... */
X              printf("?Error opening %s log file...",LOGFILE);
X`009      nice_exit();
X        `125
X`125
X`032
X
X/* Called on `094Y AST - ring the bell to make some noise. */
Xbeep()
X`123
X`009printf("\007");
X`009return;
X`125
X
X/***********************************************************************/
X/* Set up the terminal display,  and save/set terminal characteristics */
X/***********************************************************************/
X`032
Xsetup_term()
X`123
Xint     mask[1];
X`032
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`032
X        old_term_char = charbuf.term_char;      /* saves chars for exit */
X        old_extended = charbuf.extended;        /* saves extendeds too! */
X`032
X        charbuf.term_char = charbuf.term_char   /* SET TERM/NOBROADCAST */
V     `124TT$M_PASSALL`124TT$M_MBXDSABL`124TT$M_NOBRDCST; /* (also sets MBXDSA
XBL  */
X        charbuf.extended = charbuf.extended     /* SET TERM/BRDCSTMBX   */
X                             `124 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`032
X/* Sets up an out of band ast trap for any control C or control Y chars */
X
V        mask[0] = 0; mask[1] = 33554440;        /* mask for `094C/`094Y chars
X */
X        status = sys$qiow(4,tt_chan,            /* sets up the ast trap */
V                IO$_SETMODE`124IO$M_OUTBAND,       /* for `094C/`094Y charact
Xers */
X                0,0,0,beep,mask,0,0,0,0);       /* so no naughty exits! */
X        if (status != 1) lib$signal(status);    /* an error setting it? */
X
X/* Disable `094T so that malicious passersby can't fill our file.          */
X
X`009lib$disable_ctrl(&no_ctrlt);
X
X`009strcpy(header.filler, " ");
X`009draw_screen();
X
X/* Queue an ast routine to read from the terminal's message mailbox... */
X`032
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`125
X`032
X
X/***********************************************************************/
X/* get the time and date so we can log it to a file or screen display. */
X/***********************************************************************/
X`032
Xget_time()
X`123
Xint      i;                                     /* counter variables... */
Xunsigned int j[4];                              /* holds internal times */
X`032
Xstatic     char day_list[] =
X"Monday,   Tuesday,  Wednesday,Thursday, Friday,   Saturday, Sunday,   ";
X`032
X        lib$date_time(&header_dsc);             /* get the current time */
X`032
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
-+-+-+-+-+ End of part 3 +-+-+-+-+-

