home *** CD-ROM | disk | FTP | other *** search
- From decwrl!ucbvax!pasteur!ames!lll-winken!uunet!allbery Mon May 8 18:34:01 PDT 1989
- Article 867 of comp.sources.misc:
- Path: decwrl!ucbvax!pasteur!ames!lll-winken!uunet!allbery
- From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
- Newsgroups: comp.sources.misc
- Subject: v06i098: display time in MSKermit 2.32 mode line
- Message-ID: <54204@uunet.UU.NET>
- Date: 8 May 89 03:11:16 GMT
- Sender: allbery@uunet.UU.NET
- Reply-To: spolsky-joel@YALE.ARPA (Joel Spolsky)
- Lines: 358
- Approved: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
-
- Posting-number: Volume 6, Issue 98
- Submitted-by: spolsky-joel@YALE.ARPA (Joel Spolsky)
- Archive-name: clock.msk
-
- Here's a short program I wrote. It's not of much use unless you have
- MS-Kermit 2.32 or some other PC-based VT100 terminal emulator with a
- writable mode line.
-
- If you happen to be using IBM/PC Kermit in VT102 emulation mode to log
- onto a Unix machine, you might find this little program fun. When you
- run it on Unix, it displays a running time and date in the mode line
- (line 25, otherwise useless). If you have mail it tries to figure out
- who it's from and displays that on the modeline too. I find it to be
- really neat. There's just one C program and a man page; you should
- have no problem getting it to work on any generic Unix: I've tried it
- with SunOS 4.0 and Ultrix on Suns, VAXen, and Decstations.
-
- It might be possible to modify this to work with other terminals that
- let you write in the mode line; if so please let me know.
-
- +----------------+----------------------------------------------------------+
- | Joel Spolsky | bitnet: spolsky@yalecs.bitnet uucp: ...!yale!spolsky |
- | | internet: spolsky@cs.yale.edu voicenet: 203-436-1483 |
- +----------------+----------------------------------------------------------+
- #include <disclaimer.h>
-
-
- # This is a shell archive.
- # Remove everything above and including the cut line.
- # Then run the rest of the file through sh.
- #-----cut here-----cut here-----cut here-----cut here-----#
- #!/bin/sh
- # shar: Shell Archiver
- # Run the following text with /bin/sh to create:
- # vt100clock.1
- # vt100clock.c
- # This archive created: Sat May 6 02:06:35 1989
- echo shar: extracting vt100clock.1 '(1279 characters)'
- sed 's/^X//' << \SHAR_EOF > vt100clock.1
- X.TH VT100CLOCK 1 "5 May 1989"
- X.SH NAME
- Xvt100clock \- display clock & mail info on mode line of VT100 emulator
- X.SH SYNOPSIS
- X.B vt100clock
- X[
- X.B seconds
- X]
- X.SH DESCRIPTION
- X.B vt100clock
- Xis meant for users who are logging onto Unix systems with PC's running
- Xthe kermit terminal emulator in VT102 emulation mode. It might work
- Xwith other terminal emulators; I haven't tried it.
- X.B vt100clock
- Xdisplays the date and time in the lower right hand corner of the
- Xscreen. This is updated every 30 seconds, unless you specify a
- Xdifferent number of seconds on the command line. In addition, if the
- Xuser has mail, it attempts to find the names of the senders and
- Xdisplay them on the mode line as well.
- X.B vt100clock
- Xruns in the background automatically. It will automatically die when
- Xyou log out (actually, when the shell from which you executed the
- Xcommand dies).
- X.SH BUGS
- XThe method used to figure out who mail is from is not perfect and
- Xsometimes gets confused. Also, since vt100clock drops into the
- Xbackground automatically it is hard to kill it; you have to find its
- Xprocess id (ps aux | grep vt100clock) and kill that process. Usually
- Xit is sufficient to have it automatically die on logout. I have never
- Xseen this interfere with other screen-oriented programs although it
- Xmight do so.
- SHAR_EOF
- if test 1279 -ne "`wc -c vt100clock.1`"
- then
- echo shar: error transmitting vt100clock.1 '(should have been 1279 characters)'
- fi
- echo shar: extracting vt100clock.c '(8858 characters)'
- sed 's/^X//' << \SHAR_EOF > vt100clock.c
- X/** vt100clock for Unix and Kermit - version 1.00
- X **
- X ** (C) 1989 Joel Spolsky. All Rights Reserved. Permission is
- X ** granted for noncommercial use of this software. You may use,
- X ** distribute, or modify this software as long as you don't make
- X ** people pay you for it. I assume no responsibility if this
- X ** program doesn't work!!!
- X **
- X ** This program requires that you be logged on using a vt100 terminal
- X ** emulator with 25 lines, for example, Kermit 2.31 with the mode line
- X ** turned off. It's pretty generic; I have tested it on a Sun 3
- X ** under Sun-OS 4.0, a VAX running Ultrix, and a decstation 3100 also
- X ** running Ultrix. Standard "cc" and GNU "gcc" compile it with no
- X ** complaints on all the above systems.
- X **
- X ** It displays the time and date in the lower right hand corner.
- X ** Also, if you have mail, it tells you and tries to figure out who the
- X ** mail is from. The program runs quietly in the background
- X ** (you don't have to put it in the background with & - it drops
- X ** to the background automatically). It dies as soon as the shell that
- X ** spawned it dies, i.e., when you log out.
- X **
- X ** It accepts one optional argument which is the number of seconds
- X ** to sleep for between checks. This is currently 30 seconds by
- X ** default if no argument is specified.
- X **/
- X
- X/**
- X ** Here are some #defines you might need to play with:
- X **/
- X
- X#define MAILFILE "/usr/spool/mail/%s"
- X/* Where mail spool files are kept in your system. The %s will be replaced
- X with the user name. */
- X
- X#define SLEEPTIME 30
- X/* by default, how many seconds to sleep for between checks */
- X
- X
- X#define ESC 27
- X#define clearmodeline() printf("%c7%c[25;1H%c[2K%c8", ESC, ESC, ESC, ESC)
- X
- X#include <signal.h> /* to handle keyboard interrupts */
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <time.h>
- X
- Xint clean_and_exit(); /* clear mode line and exit */
- X
- Xmain(argc,argv)
- X int argc;
- X char **argv;
- X{
- X char modeline[81]; /* whats on the modeline now */
- X char newmodeline[1024]; /* what we want to be there - big in case
- X lots of mail. */
- X int firstchange, lastchange;/* changes in modeline */
- X struct tm *tm; /* time structure */
- X long timeval; /* time in seconds locally */
- X char *nowtext; /* text of day, date, time */
- X struct stat st; /* for checking size of mailbox */
- X char path[50]; /* path file name of mailbox */
- X char iline[80]; /* input line from mail file */
- X int old_size=0, new_size=0; /* size of mailbox */
- X int shellid; /* pid of user's shell. program will die if user logs off */
- X FILE *mailfile; /* mailbox */
- X int i; /* loops */
- X int sleeptime=SLEEPTIME; /* how long to sleep */
- X
- X
- X /* Trap signals to abort: first clean bottom line, then die. */
- X signal(SIGHUP,clean_and_exit); /* handle hangup */
- X signal(SIGINT,clean_and_exit); /* ctrl-C handler */
- X signal(SIGQUIT,clean_and_exit); /* ctrl-\ handler */
- X signal(SIGTERM,clean_and_exit); /* if process is killed */
- X
- X if (argc == 2) sleeptime = atoi(argv[1]);
- X
- X /* When the parent dies, this will die. Since vt100clock is
- X usually execl'ed from the users shell, this means that when
- X the user logs out, vt100clock will die immediately instead
- X of scribbling on the terminal of the next person that
- X happens to log on to the same tty. */
- X
- X shellid = getppid();
- X
- X /* drop into the background */
- X if (fork()) exit();
- X
- X /* first thing - clear the mode line */
- X clearmodeline();
- X fflush(stdout);
- X
- X /* for portability, I am not using memset. */
- X for (i=0; i<80; i++)
- X newmodeline[i] = modeline[i] = ' ';
- X newmodeline[80] = modeline[80] = 0;
- X
- X /* remember where mail is kept */
- X sprintf(path, MAILFILE, cuserid(NULL));
- X
- X while(kill(shellid,0)==0) { /* while still logged on */
- X
- X /* check mail */
- X old_size = new_size;
- X if (!stat(sprintf(path, MAILFILE, cuserid(NULL)), &st))
- X new_size = st.st_size;
- X else
- X new_size = 0;
- X
- X /* if mailbox grew or shrank, analyze who mail is from... */
- X if (old_size != new_size) {
- X newmodeline[0] = '\0';
- X if (new_size > 0) {
- X strcat (newmodeline,"Mail from: ");
- X
- X /* open mail file to see who mail is from */
- X mailfile = fopen (path, "r");
- X
- X /* read a line at a time... */
- X while (fgets (iline,79,mailfile) != NULL) {
- X /* check if line begins From: **/
- X if (strncmp(iline, "From:", 5) == 0) {
- X parse(iline); /* extract name */
- X strcat (newmodeline, iline);
- X }
- X if (strlen(newmodeline) > 63) {
- X newmodeline[60] =
- X newmodeline[61] =
- X newmodeline[62] = '.';
- X newmodeline[63] = ' ';
- X newmodeline[64] = 0; /* max length we can display */
- X }
- X }
- X fclose (mailfile);
- X }
- X }
- X /* find time */
- X timeval = time(0);
- X tm=localtime(&timeval);
- X nowtext = asctime(tm);
- X nowtext[16]=0; /* get rid of seconds and year */
- X /* put this time into newmodeline */
- X /* add at least 64 blanks to newmodeline */
- X for (i=0; i<4; i++)
- X strcat(newmodeline," ");
- X /* chop it... */
- X newmodeline[64] = 0;
- X strcat(newmodeline, nowtext);
- X
- X /* Instead of printing the whole newmodeline, just see
- X where it differs from the old modeline
- X and print that much. */
- X firstchange = 0; lastchange = 79;
- X /* assume we'll have to update whole modeline */
- X
- X while (newmodeline[firstchange] == modeline[firstchange] &&
- X firstchange <= 80)
- X firstchange++;
- X if (firstchange!=81) /* changes */ {
- X /* figure out last change */
- X while (newmodeline[lastchange] == modeline[lastchange] &&
- X lastchange >= firstchange)
- X lastchange--;
- X /* print line from firstchange to lastchange. */
- X /* sorry this printf is such a mess. */
- X printf("%c7%c[25;%dH%.*s%c8",ESC,ESC,
- X firstchange+1,
- X lastchange-firstchange+1,
- X newmodeline+firstchange,ESC);
- X
- X /* output must be flushed or else it will not necessarily be sent
- X right away. */
- X fflush(stdout);
- X }
- X strncpy(modeline,newmodeline,80);
- X
- X sleep(sleeptime); /* redo this every sleeptime seconds... */
- X }
- X /* if we get this far, user logged off - take no more action. */
- X}
- X
- Xclean_and_exit()
- X{
- X clearmodeline();
- X fflush(stdout);
- X exit(-1);
- X}
- X
- X/** parse: take a whole From: line and try to extract the person's name
- X ** otherwise settle for email address.
- X **
- X ** Cases this understands:
- X **
- X ** From: Email@address.here Use Email address (all we know)
- X ** From: email@so.and.so (Joe User) Extracts name from (parentheses)
- X ** From: Joe User <Email@address.here> Just take the name before <email>
- X ** From: <email@address.here> Take email address (all we know)
- X **
- X ** BUGS: From: lines that do not signify new messages will also be
- X ** reported as senders (this can happen if a message is quoted)
- X ** Officially we should be looking at "\nFrom " which really means
- X ** "new message" but that does not usually have the sender's real name.
- X ** There may be problems with some kinds of mailers that I don't
- X ** know about. This algorithm seems to usually work for arpanet,
- X ** uucp, and bitnet mail.
- X **/
- X
- Xparse (iline)
- X char *iline;
- X{
- X int i,j,l;
- X
- X /* Shift left to get rid of From: keyword and blanks */
- X j=5;
- X while (iline[j]==' ') j++;
- X for (i=0; iline[j]; i++, j++)
- X iline[i] = iline[j];
- X iline[i]=0;
- X
- X l=strlen(iline);
- X
- X /* scan for parentheses */
- X for (i=0; i<l; i++) {
- X if (iline[i] == '(') {
- X for (j=0, i++; iline[i] != ')'; j++, i++)
- X iline[j] = iline[i];
- X iline[j] = 0;
- X }
- X /* if there is an email address <in angle brackets>
- X AND there is something between the From: and the brackets,
- X keep only that something. */
- X if ((iline[i] == '<') && (i>7)) {
- X iline[i] = 0;
- X }
- X }
- X
- X/* scan and replace newlines with 0s */
- X for (i=0; i<l; i++)
- X if (iline[i] == '\n') {
- X iline[i] = 0;
- X break;
- X }
- X strcat(iline," "); /* add a space, always. */
- X return;
- X}
- X
- X
- X/** A few words about this program:
- X ** It works by instructing the terminal to remember the cursor position,
- X ** then it jumps down to the 25th line and updates what needs to be
- X ** updated, then it instructs the terminal to restore the remembered
- X ** cursor position.
- X **
- X ** The byte stream this sends to the terminal is kept short, in hopes
- X ** that it will be sent atomically. I have observed no problems with
- X ** any programs, including emacs and other curses programs.
- X ** It is conceivable that some software (perhaps software that relies
- X ** upon the ability to save and restore cursor positions) will not
- X ** work correctly while vt100clock is running.
- X **
- X ** For more info, later versions, etc, please contact the author:
- X **
- X ** Joel Spolsky
- X ** spolsky@yalecs.bitnet
- X ** spolsky@cs.yale.edu
- X ** ...!yale!spolsky
- X **/
- X
- X
- X
- X
- X
- SHAR_EOF
- if test 8858 -ne "`wc -c vt100clock.c`"
- then
- echo shar: error transmitting vt100clock.c '(should have been 8858 characters)'
- fi
- # End of shell archive
- exit 0
-
-
-