home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / compsrcs / misc / volume06 / clock.msk < prev    next >
Encoding:
Internet Message Format  |  1991-08-27  |  12.9 KB

  1. From decwrl!ucbvax!pasteur!ames!lll-winken!uunet!allbery Mon May  8 18:34:01 PDT 1989
  2. Article 867 of comp.sources.misc:
  3. Path: decwrl!ucbvax!pasteur!ames!lll-winken!uunet!allbery
  4. From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  5. Newsgroups: comp.sources.misc
  6. Subject: v06i098: display time in MSKermit 2.32 mode line
  7. Message-ID: <54204@uunet.UU.NET>
  8. Date: 8 May 89 03:11:16 GMT
  9. Sender: allbery@uunet.UU.NET
  10. Reply-To: spolsky-joel@YALE.ARPA (Joel Spolsky)
  11. Lines: 358
  12. Approved: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  13.  
  14. Posting-number: Volume 6, Issue 98
  15. Submitted-by: spolsky-joel@YALE.ARPA (Joel Spolsky)
  16. Archive-name: clock.msk
  17.  
  18. Here's a short program I wrote. It's not of much use unless you have
  19. MS-Kermit 2.32 or some other PC-based VT100 terminal emulator with a
  20. writable mode line.
  21.  
  22. If you happen to be using IBM/PC Kermit in VT102 emulation mode to log
  23. onto a Unix machine, you might find this little program fun. When you
  24. run it on Unix, it displays a running time and date in the mode line
  25. (line 25, otherwise useless). If you have mail it tries to figure out
  26. who it's from and displays that on the modeline too. I find it to be
  27. really neat. There's just one C program and a man page; you should
  28. have no problem getting it to work on any generic Unix: I've tried it
  29. with SunOS 4.0 and Ultrix on Suns, VAXen, and Decstations.
  30.  
  31. It might be possible to modify this to work with other terminals that
  32. let you write in the mode line; if so please let me know.
  33.  
  34. +----------------+----------------------------------------------------------+
  35. |  Joel Spolsky  | bitnet: spolsky@yalecs.bitnet     uucp: ...!yale!spolsky |
  36. |                | internet: spolsky@cs.yale.edu     voicenet: 203-436-1483 |
  37. +----------------+----------------------------------------------------------+
  38.                                                       #include <disclaimer.h>
  39.  
  40.  
  41. #    This is a shell archive.
  42. #    Remove everything above and including the cut line.
  43. #    Then run the rest of the file through sh.
  44. #-----cut here-----cut here-----cut here-----cut here-----#
  45. #!/bin/sh
  46. # shar:    Shell Archiver
  47. #    Run the following text with /bin/sh to create:
  48. #    vt100clock.1
  49. #    vt100clock.c
  50. # This archive created: Sat May  6 02:06:35 1989
  51. echo shar: extracting vt100clock.1 '(1279 characters)'
  52. sed 's/^X//' << \SHAR_EOF > vt100clock.1
  53. X.TH VT100CLOCK 1 "5 May 1989"
  54. X.SH NAME
  55. Xvt100clock \- display clock & mail info on mode line of VT100 emulator
  56. X.SH SYNOPSIS
  57. X.B vt100clock
  58. X[
  59. X.B seconds
  60. X] 
  61. X.SH DESCRIPTION
  62. X.B vt100clock
  63. Xis meant for users who are logging onto Unix systems with PC's running
  64. Xthe kermit terminal emulator in VT102 emulation mode. It might work
  65. Xwith other terminal emulators; I haven't tried it.
  66. X.B vt100clock
  67. Xdisplays the date and time in the lower right hand corner of the
  68. Xscreen. This is updated every 30 seconds, unless you specify a
  69. Xdifferent number of seconds on the command line. In addition, if the
  70. Xuser has mail, it attempts to find the names of the senders and
  71. Xdisplay them on the mode line as well.
  72. X.B vt100clock
  73. Xruns in the background automatically. It will automatically die when
  74. Xyou log out (actually, when the shell from which you executed the
  75. Xcommand dies). 
  76. X.SH BUGS
  77. XThe method used to figure out who mail is from is not perfect and
  78. Xsometimes gets confused. Also, since vt100clock drops into the
  79. Xbackground automatically it is hard to kill it; you have to find its
  80. Xprocess id (ps aux | grep vt100clock) and kill that process. Usually
  81. Xit is sufficient to have it automatically die on logout. I have never
  82. Xseen this interfere with other screen-oriented programs although it
  83. Xmight do so.
  84. SHAR_EOF
  85. if test 1279 -ne "`wc -c vt100clock.1`"
  86. then
  87. echo shar: error transmitting vt100clock.1 '(should have been 1279 characters)'
  88. fi
  89. echo shar: extracting vt100clock.c '(8858 characters)'
  90. sed 's/^X//' << \SHAR_EOF > vt100clock.c
  91. X/** vt100clock for Unix and Kermit - version 1.00
  92. X ** 
  93. X ** (C) 1989 Joel Spolsky. All Rights Reserved. Permission is
  94. X ** granted for noncommercial use of this software. You may use,
  95. X ** distribute, or modify this software as long as you don't make
  96. X ** people pay you for it. I assume no responsibility if this
  97. X ** program doesn't work!!!
  98. X **
  99. X ** This program requires that you be logged on using a vt100 terminal
  100. X ** emulator with 25 lines, for example, Kermit 2.31 with the mode line
  101. X ** turned off. It's pretty generic; I have tested it on a Sun 3
  102. X ** under Sun-OS 4.0, a VAX running Ultrix, and a decstation 3100 also
  103. X ** running Ultrix. Standard "cc" and GNU "gcc" compile it with no
  104. X ** complaints on all the above systems.
  105. X **
  106. X ** It displays the time and date in the lower right hand corner.
  107. X ** Also, if you have mail, it tells you and tries to figure out who the
  108. X ** mail is from. The program runs quietly in the background
  109. X ** (you don't have to put it in the background with & - it drops
  110. X ** to the background automatically). It dies as soon as the shell that
  111. X ** spawned it dies, i.e., when you log out.
  112. X **
  113. X ** It accepts one optional argument which is the number of seconds
  114. X ** to sleep for between checks. This is currently 30 seconds by
  115. X ** default if no argument is specified.
  116. X **/
  117. X
  118. X/** 
  119. X ** Here are some #defines you might need to play with:
  120. X **/
  121. X
  122. X#define MAILFILE "/usr/spool/mail/%s"
  123. X/* Where mail spool files are kept in your system. The %s will be replaced
  124. X   with the user name. */
  125. X
  126. X#define SLEEPTIME 30
  127. X/* by default, how many seconds to sleep for between checks */
  128. X
  129. X
  130. X#define ESC 27
  131. X#define clearmodeline() printf("%c7%c[25;1H%c[2K%c8", ESC, ESC, ESC, ESC)
  132. X
  133. X#include <signal.h>        /* to handle keyboard interrupts */
  134. X#include <stdio.h>        
  135. X#include <sys/types.h>
  136. X#include <sys/stat.h>
  137. X#include <time.h>
  138. X
  139. Xint clean_and_exit();        /* clear mode line and exit */
  140. X
  141. Xmain(argc,argv)
  142. X     int argc;
  143. X     char **argv;
  144. X{
  145. X    char modeline[81];        /* whats on the modeline now */
  146. X    char newmodeline[1024];    /* what we want to be there - big in case
  147. X                   lots of mail. */
  148. X    int firstchange, lastchange;/* changes in modeline */
  149. X    struct tm *tm;        /* time structure */
  150. X    long timeval;        /* time in seconds locally */
  151. X    char *nowtext;        /* text of day, date, time */
  152. X    struct stat st;        /* for checking size of mailbox */
  153. X    char path[50];        /* path file name of mailbox */
  154. X    char iline[80];        /* input line from mail file */
  155. X    int old_size=0, new_size=0;    /* size of mailbox */
  156. X    int shellid; /* pid of user's shell. program will die if user logs off */
  157. X    FILE *mailfile;        /* mailbox */
  158. X    int i;            /* loops */
  159. X    int sleeptime=SLEEPTIME;    /* how long to sleep */
  160. X
  161. X
  162. X    /* Trap signals to abort: first clean bottom line, then die. */
  163. X    signal(SIGHUP,clean_and_exit);  /* handle hangup */
  164. X    signal(SIGINT,clean_and_exit);  /* ctrl-C handler */
  165. X    signal(SIGQUIT,clean_and_exit); /* ctrl-\ handler */
  166. X    signal(SIGTERM,clean_and_exit); /* if process is killed */
  167. X
  168. X    if (argc == 2) sleeptime = atoi(argv[1]);
  169. X
  170. X    /* When the parent dies, this will die. Since vt100clock is
  171. X       usually execl'ed from the users shell, this means that when
  172. X       the user logs out, vt100clock will die immediately instead
  173. X       of scribbling on the terminal of the next person that
  174. X       happens to log on to the same tty. */
  175. X
  176. X    shellid = getppid();
  177. X
  178. X    /* drop into the background */
  179. X    if (fork()) exit();
  180. X
  181. X    /* first thing - clear the mode line */
  182. X    clearmodeline();
  183. X    fflush(stdout);
  184. X
  185. X    /* for portability, I am not using memset. */
  186. X    for (i=0; i<80; i++) 
  187. X    newmodeline[i] = modeline[i] = ' ';
  188. X    newmodeline[80] = modeline[80] = 0;
  189. X
  190. X    /* remember where mail is kept */
  191. X    sprintf(path, MAILFILE, cuserid(NULL));
  192. X
  193. X    while(kill(shellid,0)==0) {       /* while still logged on */
  194. X
  195. X    /* check mail */
  196. X    old_size = new_size;
  197. X    if (!stat(sprintf(path, MAILFILE, cuserid(NULL)), &st))
  198. X        new_size = st.st_size;
  199. X    else 
  200. X        new_size = 0;
  201. X
  202. X    /* if mailbox grew or shrank, analyze who mail is from... */
  203. X    if (old_size != new_size) {
  204. X        newmodeline[0] = '\0';
  205. X        if (new_size > 0) {
  206. X        strcat (newmodeline,"Mail from: ");
  207. X        
  208. X        /* open mail file to see who mail is from */
  209. X        mailfile = fopen (path, "r");
  210. X
  211. X        /* read a line at a time... */
  212. X        while (fgets (iline,79,mailfile) != NULL) {
  213. X            /* check if line begins From: **/
  214. X            if (strncmp(iline, "From:", 5) == 0) {
  215. X            parse(iline); /* extract name */
  216. X            strcat (newmodeline, iline);
  217. X            }
  218. X            if (strlen(newmodeline) > 63) {
  219. X            newmodeline[60] =
  220. X                newmodeline[61] =
  221. X                newmodeline[62] = '.';
  222. X            newmodeline[63] = ' ';
  223. X            newmodeline[64] = 0; /* max length we can display */
  224. X            }
  225. X        }
  226. X        fclose (mailfile);
  227. X        }
  228. X    }
  229. X    /* find time */
  230. X    timeval = time(0);
  231. X    tm=localtime(&timeval);
  232. X    nowtext = asctime(tm);
  233. X    nowtext[16]=0;        /* get rid of seconds and year */
  234. X    /* put this time into newmodeline */
  235. X    /* add at least 64 blanks to newmodeline */
  236. X    for (i=0; i<4; i++)
  237. X        strcat(newmodeline,"                ");
  238. X    /* chop it... */
  239. X    newmodeline[64] = 0;
  240. X    strcat(newmodeline, nowtext);
  241. X
  242. X        /* Instead of printing the whole newmodeline, just see
  243. X       where it differs from the old modeline
  244. X       and print that much. */
  245. X    firstchange = 0; lastchange = 79;
  246. X    /* assume we'll have to update whole modeline */
  247. X
  248. X    while (newmodeline[firstchange] == modeline[firstchange] &&
  249. X           firstchange <= 80)
  250. X        firstchange++;
  251. X    if (firstchange!=81) /* changes */ {
  252. X        /* figure out last change */
  253. X        while (newmodeline[lastchange] == modeline[lastchange] &&
  254. X           lastchange >= firstchange)
  255. X        lastchange--;
  256. X        /* print line from firstchange to lastchange. */
  257. X        /* sorry this printf is such a mess. */
  258. X        printf("%c7%c[25;%dH%.*s%c8",ESC,ESC,
  259. X           firstchange+1,
  260. X           lastchange-firstchange+1,
  261. X           newmodeline+firstchange,ESC);
  262. X
  263. X        /* output must be flushed or else it will not necessarily be sent
  264. X           right away. */
  265. X        fflush(stdout);
  266. X    }
  267. X    strncpy(modeline,newmodeline,80);
  268. X
  269. X    sleep(sleeptime); /* redo this every sleeptime seconds... */
  270. X    }
  271. X    /* if we get this far, user logged off - take no more action. */
  272. X}
  273. X
  274. Xclean_and_exit()
  275. X{
  276. X    clearmodeline();
  277. X    fflush(stdout);
  278. X    exit(-1);
  279. X}
  280. X
  281. X/** parse: take a whole From: line and try to extract the person's name
  282. X ** otherwise settle for email address.
  283. X **
  284. X ** Cases this understands:
  285. X **
  286. X ** From: Email@address.here               Use Email address (all we know)
  287. X ** From: email@so.and.so (Joe User)       Extracts name from (parentheses)
  288. X ** From: Joe User <Email@address.here>    Just take the name before <email>
  289. X ** From: <email@address.here>             Take email address (all we know)
  290. X **
  291. X ** BUGS: From: lines that do not signify new messages will also be
  292. X ** reported as senders (this can happen if a message is quoted)
  293. X ** Officially we should be looking at "\nFrom " which really means
  294. X ** "new message" but that does not usually have the sender's real name.
  295. X ** There may be problems with some kinds of mailers that I don't
  296. X ** know about. This algorithm seems to usually work for arpanet,
  297. X ** uucp, and bitnet mail. 
  298. X **/
  299. X
  300. Xparse (iline)
  301. X     char *iline;
  302. X{
  303. X    int i,j,l;
  304. X
  305. X    /* Shift left to get rid of From: keyword and blanks */
  306. X    j=5;
  307. X    while (iline[j]==' ') j++;
  308. X    for (i=0; iline[j]; i++, j++)
  309. X    iline[i] = iline[j];
  310. X    iline[i]=0;
  311. X
  312. X    l=strlen(iline);
  313. X    
  314. X    /* scan for parentheses */
  315. X    for (i=0; i<l; i++) {
  316. X    if (iline[i] == '(') {
  317. X        for (j=0, i++; iline[i] != ')'; j++, i++)
  318. X        iline[j] = iline[i];
  319. X        iline[j] = 0;
  320. X    }
  321. X    /* if there is an email address <in angle brackets>
  322. X       AND there is something between the From: and the brackets,
  323. X       keep only that something. */
  324. X        if ((iline[i] == '<') && (i>7)) {
  325. X        iline[i] = 0;
  326. X    }
  327. X    }
  328. X
  329. X/* scan and replace newlines with 0s */
  330. X    for (i=0; i<l; i++)
  331. X    if (iline[i] == '\n') {
  332. X        iline[i] = 0;
  333. X        break;
  334. X    }
  335. X    strcat(iline," "); /* add a space, always. */
  336. X    return;
  337. X}
  338. X        
  339. X
  340. X/** A few words about this program:
  341. X ** It works by instructing the terminal to remember the cursor position,
  342. X ** then it jumps down to the 25th line and updates what needs to be
  343. X ** updated, then it instructs the terminal to restore the remembered
  344. X ** cursor position.
  345. X **
  346. X ** The byte stream this sends to the terminal is kept short, in hopes
  347. X ** that it will be sent atomically. I have observed no problems with
  348. X ** any programs, including emacs and other curses programs.
  349. X ** It is conceivable that some software (perhaps software that relies
  350. X ** upon the ability to save and restore cursor positions) will not
  351. X ** work correctly while vt100clock is running.
  352. X **
  353. X ** For more info, later versions, etc, please contact the author:
  354. X **
  355. X **                             Joel Spolsky
  356. X **                             spolsky@yalecs.bitnet
  357. X **                             spolsky@cs.yale.edu
  358. X **                             ...!yale!spolsky
  359. X **/
  360. X
  361. X
  362. X
  363. X
  364. X
  365. SHAR_EOF
  366. if test 8858 -ne "`wc -c vt100clock.c`"
  367. then
  368. echo shar: error transmitting vt100clock.c '(should have been 8858 characters)'
  369. fi
  370. #    End of shell archive
  371. exit 0
  372.  
  373.  
  374.