home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume6 / clock.msk < prev    next >
Text File  |  1989-05-07  |  13KB  |  366 lines

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