home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume12 / wclock / part01 next >
Encoding:
Text File  |  1990-05-14  |  30.7 KB  |  1,148 lines

  1. Newsgroups: comp.sources.misc
  2. organization: U of Arizona CS Dept, Tucson
  3. subject: v12i086: A Wall Clock
  4. from: robert@cs.arizona.edu (Robert J. Drabek)
  5. Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  6.  
  7. Posting-number: Volume 12, Issue 86
  8. Submitted-by: robert@cs.arizona.edu (Robert J. Drabek)
  9. Archive-name: wclock/part01
  10.  
  11. A Wall Clock
  12.  
  13. For those who use standard terminals instead of work stations, but still
  14. want a clock display and mail indicator, this program will help you out
  15. if your terminal includes a status line (aka the 25th line).  Also
  16. includes screen-saver and alarm options and you can select 24-hour
  17. or UTC displays.
  18.  
  19. It works under Unix (BSD) and VMS.
  20.  
  21. It knows about the status line for the following terminals:
  22.   AT&T 4425, TeleVideo 950, TeleVideo 955, Wyse-60, Wyse-75,
  23.   Zenith/Heath-19 & 29 (if in ANSI mode)
  24. But if your termcap (Unix) includes the "hs", "ts", and "fs"
  25. capabilities for some other terminal the program will use those
  26. automatically.
  27.  
  28. Run it in the background.  Some examples (under Unix):
  29.  
  30.      clock wyse60 &       # If your termcap doesn't include hs, ts, fs.
  31.      clock -i15 -s &      # If your termcap does include hs, ts, fs and
  32.                           #   you want seconds displayed every 15 seconds.
  33.  
  34. Unix users, as the clock program will tell you nicely when you have
  35. mail, you will want to run the "biff n" command to disable the mailer
  36. messing up your screen.
  37.  
  38. VMS users, you must specify the terminal type, and the mail and news
  39. indicators don't work.  If some interprising VMS hacker can show me how
  40. to add the "has_mail" function into the program, I would appreciate it.
  41.  
  42. --
  43. Robert J. Drabek                            robert@cs.Arizona.EDU
  44. Department of Computer Science              uunet!arizona!robert
  45. The University of Arizona                   602 621 4326
  46. Tucson, AZ  85721
  47.  
  48. /* - - - - - - - - - - - - - -  CUT HERE  - - - - - - - - - - - - - - - */
  49. #! /bin/sh
  50. # This is a shell archive.  Remove anything before this line, then unpack
  51. # it by saving it into a file and typing "sh file".  To overwrite existing
  52. # files, type "sh file -c".  You can also feed this as standard input via
  53. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  54. # will see the following message at the end:
  55. #        "End of shell archive."
  56. # Contents:  README Makefile clock.c
  57. # Wrapped by robert@megaron.cs.arizona.edu on Mon May 14 10:33:49 1990
  58. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  59. if test -f 'README' -a "${1}" != "-c" ; then 
  60.   echo shar: Will not clobber existing file \"'README'\"
  61. else
  62. echo shar: Extracting \"'README'\" \(1468 characters\)
  63. sed "s/^X//" >'README' <<'END_OF_FILE'
  64. A Wall Clock
  65. X
  66. XFor those who use standard terminals instead of work stations, but still
  67. want a clock display and mail indicator, this program will help you out
  68. if your terminal includes a status line (aka the 25th line).  Also
  69. includes screen-saver and alarm options.
  70. X
  71. It works under Unix (BSD) and VMS.
  72. X
  73. It knows about the status line for the following terminals:
  74. X  AT&T 4425, TeleVideo 950, TeleVideo 955, Wyse-60, Wyse-75,
  75. X  Zenith/Heath-19 & 29 (if in ANSI mode)
  76. But if your termcap (Unix) includes the "hs", "ts", and "fs"
  77. capabilities for some other terminal the program will use those
  78. automatically.
  79. X
  80. Run it in the background.  Some examples (under Unix):
  81. X
  82. X     clock wyse60 &       # If your termcap doesn't include hs, ts, fs.
  83. X     clock -i15 -s &      # If your termcap does include hs, ts, fs and
  84. X                          #   you want seconds displayed every 15 seconds.
  85. X
  86. Unix users, as the clock program will tell you nicely when you have
  87. mail, you will want to run the "biff n" command to disable the mailer
  88. messing up your screen.
  89. X
  90. VMS users, you must specify the terminal type and the mail and news
  91. indicators don't work.  If some interprising VMS hacker can show me how
  92. to add the "has_mail" function into the program, I would appreciate it.
  93. X
  94. X--
  95. Robert J. Drabek                            robert@cs.Arizona.EDU
  96. Department of Computer Science              uunet!arizona!robert
  97. The University of Arizona                   602 621 4326
  98. Tucson, AZ  85721
  99. END_OF_FILE
  100. if test 1468 -ne `wc -c <'README'`; then
  101.     echo shar: \"'README'\" unpacked with wrong size!
  102. fi
  103. # end of 'README'
  104. fi
  105. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  106.   echo shar: Will not clobber existing file \"'Makefile'\"
  107. else
  108. echo shar: Extracting \"'Makefile'\" \(901 characters\)
  109. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  110. X# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  111. X#
  112. X# Makefile for the clock program.
  113. X#
  114. X# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  115. X
  116. XEXECUTABLE = clock
  117. X
  118. DATE_STRING = "\"`date`\""
  119. MAILDIR = "\"/usr/spool/mail/\""
  120. X
  121. CFLAGS = -O -s -x -D__DATE__=$(DATE_STRING) -DMAILDIR=$(MAILDIR)
  122. X
  123. X$(EXECUTABLE) :    $(EXECUTABLE).c
  124. X    cc $(CFLAGS) $(EXECUTABLE).c -o $(EXECUTABLE) -ltermcap
  125. X
  126. X# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  127. X
  128. X# Install files in the correct directories.
  129. install : $(EXECUTABLE)
  130. X    -cp $(EXECUTABLE)    /usr/local
  131. X    -cp $(EXECUTABLE).1  /usr/man/manl/$(EXECUTABLE).l
  132. X    -cp $(EXECUTABLE).c  /usr/src/local
  133. X
  134. X# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  135. X
  136. lint :
  137. X    lint -D__DATE__="\"xxx\"" -DMAILDIR=$(MAILDIR) $(EXECUTABLE).c -ltermcap
  138. X
  139. X# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  140. END_OF_FILE
  141. if test 901 -ne `wc -c <'Makefile'`; then
  142.     echo shar: \"'Makefile'\" unpacked with wrong size!
  143. fi
  144. # end of 'Makefile'
  145. fi
  146. if test -f 'clock.c' -a "${1}" != "-c" ; then 
  147.   echo shar: Will not clobber existing file \"'clock.c'\"
  148. else
  149. echo shar: Extracting \"'clock.c'\" \(24384 characters\)
  150. sed "s/^X//" >'clock.c' <<'END_OF_FILE'
  151. X/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  152. X
  153. X   A wall clock for the special display area (status line) of your
  154. X   terminal.  Works under Unix (BSD 4.3) and VMS.
  155. X
  156. X   If no terminal is specified then, under Unix, the termcap will
  157. X   be examined, looking for the "hs", "ts", and "fs" capabilities.
  158. X
  159. X   Otherwise the last argument can specify one of
  160. X      att4425, tvi950, tvi955, wyse50, wyse60, wyse75, wyse75-bottom,
  161. X      z19 (if in ANSI mode), z29 (if in ANSI mode).
  162. X
  163. X   In addition to the time, under Unix a message will be displayed
  164. X   if mail is waiting.
  165. X
  166. X   "clock off" will kill all clock processes under Unix.
  167. X
  168. X   Options:
  169. X
  170. X     -aTIME
  171. X           Sets an alarm for the given time.
  172. X           The time must be of the form xx:xx plus possibly am,
  173. X           pm or UTC, depending upon the form of the clock indicator.
  174. X           Examples: -a10:24am   -a9:21pm   -a11:52UTC   -a17:20
  175. X     -b    The terminal's bell is rung on the hour.
  176. X     -bb   The terminal's bell is rung multiple times on the hour.
  177. X     -24   Display 24-hour time instead of am/pm.
  178. X     -s    The display includes the seconds.
  179. X     -ss#  Invokes the screen saver.  # is optional and is the number
  180. X             of minutes to screen saving.  (Unix only).
  181. X     -i#   Specifies the interval (in seconds) between display
  182. X             updates (default is 60 seconds).
  183. X     -m    Don't check for mail; used when the display interval
  184. X             is small and we want to conserve resources.
  185. X     -mb   Don't ring the silly bell when new mail arrives.
  186. X     -mboxPATH
  187. X           Use an alternate path name for the mail box file.
  188. X           Example: clock -mbox/usr/spool/secretmail/joan
  189. X     -n    Do check for news!  (Not the default.)  (Unix only).
  190. X     -u    Give UTC (aka Greenwich mean time)
  191. X     -v    Just prints the version number and compile date.
  192. X
  193. X   Robert J. Drabek
  194. X   The University of Arizona
  195. X  
  196. X   March 1986 with various modifications since.
  197. X
  198. X   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  199. X
  200. X   Unix compilation:
  201. X       cc -O -s -x -n clock.c -o clock -ltermcap \
  202. X          -D__DATE__='"June 10, 1989"' -DMAILDIR="/usr/spool/mail/"
  203. X                (where you substitute the correct date and spool directory)
  204. X                 or
  205. X       gcc -O -s -x -n clock.c -o clock -DMAILDIR="/usr/spool/mail/"
  206. X  
  207. X   VMS compilation:   cc/optim clock.c
  208. X                      link clock
  209. X  
  210. X   It should be run as a backround process, for example,
  211. X
  212. X     UNIX:  clock -bb wyse75 &
  213. X
  214. X     VMS:   First, define RUNCLOCK :== $MYDISK:[MYDIRS]CLOCK.EXE
  215. X                      and CLOCK :== SPAWN/NOWAIT/INPUT=NL: RUNCLOCK
  216. X            (where MYDISK and MYDIRS are appropriate for your machine)
  217. X            Then, use clock -bb wyse75
  218. X
  219. X   If you cannot modify termcap, clock can be modified to perform on
  220. X   other video terminals, provided they either incorporate the cursor-save
  221. X   function within their command repertoire or automatically return the
  222. X   cursor after writing to the special display area.  The modifications
  223. X   will entail adding new entries to the terminal_kinds enumerated type
  224. X   and the Terminal_Description table below.
  225. X
  226. X   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  227. X  
  228. X
  229. X#define VERSION "Version 4.1 (%s) Robert J. Drabek\n"
  230. X
  231. X
  232. X/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  233. X
  234. X#define EMPTY_NEWS_STR      "  "
  235. X#define NEW_NEWS_STR        " *"
  236. X#define ALARM_OFF_STR       "  "
  237. X#define ALARM_ON_STR        "! "
  238. X#define EMPTY_MAIL_STR      "          "
  239. X#define NEW_MAIL_STR        " NEW MAIL "
  240. X#define NEW_WYSE75_MAIL_STR "\016\017QNEW MAIL\016\017@"
  241. X#define OLD_MAIL_STR        "     Mail "
  242. X
  243. X/* If the above are changed, the Open_Window and Close_Window
  244. X   strings below will probably also need to be changed. */
  245. X
  246. X/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  247. X
  248. X   These tables store all terminal-specific data.
  249. X
  250. X   The enumerated type and the character array must be kept in
  251. X   correspondence.
  252. X
  253. X   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  254. X
  255. typedef enum {
  256. X  ATT4425      =  0,
  257. X  TVI950955    =  1,
  258. X  WYSE5060     =  2,
  259. X  WYSE75       =  3,
  260. X  WYSE75BOTTOM =  4,
  261. X  Z1929        =  5, /* with terminal set to ANSI mode */
  262. X  NO_TERM_DEF  = -1
  263. X} terminal_kinds;
  264. X
  265. X
  266. X/* The three strings for each terminal type are respectively
  267. X     Open window,
  268. X     Close window,
  269. X     Clear window,
  270. X     Clear screen.
  271. X*/
  272. X
  273. static char *Terminal_Description[][5] = {
  274. X
  275. X  /* ATT4425 */
  276. X  { "\0337\033[7m\033[25;9H",
  277. X    "\033[8m\0338",
  278. X    "\0337\033[25;1H                                                 \0338",
  279. X    "\033[;H\033[2J" },
  280. X
  281. X  /* TVI950955 */
  282. X  { "\033f         ",
  283. X    "\r",
  284. X    "\033f\r",
  285. X    "\033*" },
  286. X
  287. X  /* WYSE5060 */
  288. X  { "\033F      ",
  289. X    "\r",
  290. X    "\033F\r",
  291. X    "\032" },
  292. X
  293. X  /* WYSE75 : Wyse-75, upper-right corner */
  294. X  { "\033[>+? ",
  295. X    "?",
  296. X    "\033[>+? ?",
  297. X    "\033[;H\033[2J" },
  298. X
  299. X  /* WYSE75BOTTOM : Wyse-75, 25th line */
  300. X     /* ^N^OQ goes into reverse video, ^N^O@ leaves reverse video
  301. X        ?'s delimit string  */
  302. X  { "\033[>,?         \016\017Q ",
  303. X    "        \016\017@?",
  304. X    "\033[>,? ?",
  305. X    "\033[;H\033[2J" },
  306. X
  307. X  /* Z1929 */
  308. X     /* Time window is on the 25th line.  Terminal set to ANSI mode */
  309. X  { "\0337\033[25;9H\033[2K= = ",
  310. X    "      = =\0338",
  311. X    "\0337\033[>1h\033[25;1H\033[2K\033[>1l\0338",
  312. X    "\033[;H\033[2J" },
  313. X
  314. X};
  315. X
  316. X/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  317. X
  318. X
  319. X#include <signal.h>
  320. X#include <stdio.h>
  321. X#include <time.h>
  322. X
  323. X#ifdef  unix
  324. X#include <sgtty.h>
  325. X#include <sys/types.h>
  326. X#include <sys/stat.h>
  327. X#endif
  328. X#ifdef    vms
  329. X#include <unixio.h>
  330. X#endif
  331. X
  332. typedef char bool;
  333. X#define TRUE    1
  334. X#define FALSE   0
  335. X
  336. X#define BELL '\07'
  337. X#define EOS  '\0'
  338. X
  339. X#define OUTEARLY -2  /* two exceptions to be handled specially */
  340. X#define BYEBYE   -1
  341. X
  342. X#define streq(s1,s2) (strcmp(s1,s2)==0)
  343. X
  344. typedef enum { AM_PM, INTERNAT, UTC } suffix_type;
  345. X
  346. typedef enum { NO_CHIME, SINGLE_CHIME, MULTIPLE_CHIMES } chime_type;
  347. X
  348. X#ifdef unix
  349. X#define NEWS_FREQUENCY 5  /* How often we check for news. */
  350. X
  351. X/* This should be defined on the compile command line:
  352. X     MAILDIR  "/usr/spool/mail/"
  353. X*/
  354. typedef enum { NO_MAIL, NEW_MAIL, OLD_MAIL } mail_type;
  355. X#endif
  356. X
  357. X#define WHICH_FD 2
  358. X
  359. X#ifdef  unix
  360. extern FILE *popen();
  361. extern char *ttyname();
  362. X#define TERM_NAME ttyname(WHICH_FD)
  363. X#define QUIET  0
  364. X#endif
  365. X
  366. X#ifdef  vms
  367. X#define TERM_NAME "SYS$OUTPUT:"
  368. X#define QUIET  1
  369. X#endif
  370. X
  371. X/* Global variables */
  372. struct tm *Tp;
  373. long       Tloc;
  374. X
  375. struct tm *((*calc_time)());
  376. X
  377. int Update_Interval      = 60; /* seconds */
  378. X#ifdef    unix
  379. bool         Check_Mail     = TRUE;  /* whether or not to check the mail */
  380. bool         Ring_Mail_Bell = TRUE;  /* whether or not to ring the mail bell */
  381. bool         Check_News     = FALSE; /* whether or not to check the news */
  382. int          Screen_Save_Interval = 0; /* minutes */
  383. static char *P_CL = NULL;
  384. X#endif
  385. X
  386. terminal_kinds Terminal_Kind = NO_TERM_DEF;
  387. X
  388. char *Open_Window, *Close_Window, *Clear_Window;
  389. X
  390. chime_type  Chime          = NO_CHIME; /* ring the chimes every hour */
  391. bool        Alarm_On       = FALSE;
  392. char        Alarm_Time[26] = { EOS };
  393. suffix_type Display_Type   = AM_PM;
  394. char       *Time_Suffix    = "ERR";
  395. bool        Seconds_On     = FALSE;  /* display will include the seconds */
  396. XFILE       *Fp;
  397. X
  398. X#ifdef unix
  399. X#include <pwd.h>
  400. char        Mailfile[100];
  401. X#endif
  402. X
  403. X/* Forward function declarations for time. */
  404. extern int      (*signal())();
  405. extern struct tm *localtime();
  406. extern struct tm *gmtime();
  407. extern long       time();
  408. X
  409. X#ifdef  unix
  410. extern char *asctime();
  411. extern int   getppid();
  412. X#endif
  413. X
  414. X#ifdef  vms
  415. extern char *ctime();
  416. X#endif
  417. X
  418. X
  419. static void get_args();
  420. static bool set_strings();
  421. static bool term_cap();
  422. static void special_work();
  423. static void get_alarm();
  424. static void do_display();
  425. static void fix_hour();
  426. static void chimes();
  427. static int  die();
  428. static void usage();
  429. X
  430. X#ifdef unix
  431. static int       find();
  432. static void      stop();
  433. static bool      has_news();
  434. static mail_type has_mail();
  435. static void      init_mailfile();
  436. static long      find_idle();
  437. static void      clrscr();
  438. X#endif
  439. X
  440. X/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  441. X
  442. main(argc, argv)
  443. int   argc;
  444. char *argv[];
  445. X{
  446. X#ifdef  unix
  447. X  int orig_ppid, new_ppid;
  448. X  long idle_time;
  449. X#define MAXNAME 20
  450. X  static char tty[MAXNAME + 1];
  451. X#endif
  452. X
  453. X  if (!isatty(WHICH_FD))
  454. X    die(OUTEARLY);
  455. X
  456. X  if ((Fp = fopen(TERM_NAME, "w")) == NULL) {
  457. X    fprintf(stderr, "%s - cannot open %s\n", argv[0], TERM_NAME);
  458. X    die(OUTEARLY);
  459. X  }
  460. X
  461. X  get_args(argc, argv);
  462. X
  463. X#ifdef unix
  464. X  init_mailfile(argv[0]);
  465. X  strcpy(tty, ttyname(0));
  466. X#endif
  467. X
  468. X
  469. X  signal(SIGTERM, die);
  470. X  signal(SIGINT, die);
  471. X
  472. X#ifdef  unix
  473. X  orig_ppid = getppid(); /* Keep track of the current process, so after
  474. X                            you log out, the clock will know to die off. */
  475. X  if (orig_ppid == 1) die(OUTEARLY); /* For when people try to run this
  476. X                                     from vi or whatever. */
  477. X#endif
  478. X
  479. X  special_work();
  480. X
  481. X  Tloc = time((long *)0);
  482. X  Tp = (*calc_time)(&Tloc);
  483. X
  484. X  fix_hour(Tp->tm_hour);
  485. X  do_display();
  486. X
  487. X
  488. X  /* This is the main loop which displays the clock periodically. */
  489. X
  490. X  for (;;) {
  491. X
  492. X#ifdef  unix
  493. X    if ((new_ppid = getppid()) != orig_ppid) die(BYEBYE);
  494. X    if (new_ppid == 1) die(BYEBYE); /* For when people try to run this
  495. X                                       from vi or whatever. */
  496. X#endif
  497. X
  498. X    Tp = (*calc_time)(&Tloc);
  499. X    sleep( (unsigned) (Update_Interval - Tp->tm_sec % Update_Interval) );
  500. X
  501. X    Tloc = time((long *)0);
  502. X    Tp = (*calc_time)(&Tloc);
  503. X        
  504. X    fix_hour(Tp->tm_hour);
  505. X    do_display();
  506. X
  507. X    if (Chime != NO_CHIME && Tp->tm_min == 00 && Tp->tm_sec <= 3)
  508. X      chimes(Tp->tm_hour);
  509. X
  510. X#ifdef    unix
  511. X    if (Screen_Save_Interval != 0  && Tp->tm_min % 5 == 0 && Tp->tm_sec <= 3) {
  512. X      idle_time = find_idle(tty);
  513. X      if (idle_time >= Screen_Save_Interval)
  514. X        clrscr();
  515. X    }
  516. X#endif
  517. X
  518. X  }
  519. X
  520. X}  /* main */
  521. X
  522. X
  523. X/* get_args
  524. X     Read the arguments and set up the various globals appropriately.
  525. X*/
  526. static void get_args(argc, argv)
  527. int   argc;
  528. char *argv[];
  529. X{
  530. X  char *getenv();
  531. X  char *termdef;
  532. X  int  i;
  533. X
  534. X#ifdef    unix
  535. X  Mailfile[0] = EOS;
  536. X#endif
  537. X
  538. X  calc_time = localtime;
  539. X
  540. X  if ((termdef = getenv("TERM")) != NULL)
  541. X    if      (streq(termdef,   "att4425")
  542. X            || streq(termdef, "att"))
  543. X      Terminal_Kind = ATT4425;
  544. X    else if (streq(termdef,   "tvi950")
  545. X            || streq(termdef, "tvi955"))
  546. X      Terminal_Kind = TVI950955;
  547. X    else if (streq(termdef,   "wyse")
  548. X            || streq(termdef, "wyse75"))
  549. X      Terminal_Kind = WYSE75;
  550. X    else if (streq(termdef,   "wyse75-bottom"))
  551. X      Terminal_Kind = WYSE75BOTTOM;
  552. X    else if (streq(termdef,   "wyse50")
  553. X            || streq(termdef, "wyse60"))
  554. X      Terminal_Kind = WYSE5060;
  555. X    else if (streq(termdef,   "z19")
  556. X            || streq(termdef, "h19")
  557. X            || streq(termdef, "s19")
  558. X            || streq(termdef, "z29")
  559. X            || streq(termdef, "h29"))
  560. X      Terminal_Kind = Z1929;
  561. X
  562. X  for (i = 1; i < argc; i++)
  563. X
  564. X    if      (streq(argv[i],   "att4425")
  565. X            || streq(argv[i], "att"))
  566. X      Terminal_Kind = ATT4425;
  567. X    else if (streq(argv[i],   "tvi950")
  568. X            || streq(argv[i], "tvi955"))
  569. X      Terminal_Kind = TVI950955;
  570. X    else if (streq(argv[i],   "wyse")
  571. X            || streq(argv[i], "wyse75"))
  572. X      Terminal_Kind = WYSE75;
  573. X    else if (streq(argv[i],   "wyse75-bottom"))
  574. X      Terminal_Kind = WYSE75BOTTOM;
  575. X    else if (streq(argv[i],   "wyse50")
  576. X            || streq(argv[i], "wyse60"))
  577. X      Terminal_Kind = WYSE5060;
  578. X    else if (streq(argv[i],   "z19")
  579. X            || streq(argv[i], "h19")
  580. X            || streq(argv[i], "s19")
  581. X            || streq(argv[i], "z29")
  582. X            || streq(argv[i], "h29"))
  583. X      Terminal_Kind = Z1929;
  584. X#ifdef  unix
  585. X    else if (streq(argv[i], "off")) {
  586. X      stop(argv[0]);
  587. X      die(OUTEARLY);
  588. X      }
  589. X#endif
  590. X    else if (strncmp(argv[i], "-a", 2) == 0) {
  591. X      Alarm_On = TRUE;
  592. X      get_alarm(argv[i] + 2);
  593. X      }
  594. X    else if (streq(argv[i], "-b"))
  595. X      Chime = SINGLE_CHIME;
  596. X    else if (streq(argv[i], "-bb"))
  597. X      Chime = MULTIPLE_CHIMES;
  598. X    else if (strncmp(argv[i], "-i", 2) == 0) {
  599. X      Update_Interval = atoi(argv[i] + 2);
  600. X      if (Update_Interval < 1) Update_Interval = 60;
  601. X      }
  602. X#ifdef    unix
  603. X    else if (streq(argv[i], "-m"))
  604. X      Check_Mail = FALSE;
  605. X    else if (streq(argv[i], "-mb"))
  606. X      Ring_Mail_Bell = FALSE;
  607. X    else if (strncmp(argv[i], "-mbox", 5) == 0)
  608. X      strcpy(Mailfile, argv[i] + 5);
  609. X    else if (streq(argv[i], "-n"))
  610. X      Check_News = TRUE;
  611. X#endif
  612. X    else if (streq(argv[i], "-s"))
  613. X      Seconds_On = TRUE;
  614. X#ifdef    unix
  615. X    else if (strncmp(argv[i], "-ss", 3) == 0) {
  616. X      /* in minutes */
  617. X      Screen_Save_Interval = atoi(argv[i] + 3);
  618. X      if (Screen_Save_Interval < 1)
  619. X        Screen_Save_Interval = 60;
  620. X      else if (Screen_Save_Interval < 5)
  621. X        Screen_Save_Interval = 5;
  622. X      }
  623. X#endif
  624. X    else if (streq(argv[i], "-u")) {
  625. X      calc_time = gmtime;
  626. X      Display_Type = UTC;
  627. X      }
  628. X    else if (streq(argv[i], "-v")) {
  629. X      fprintf(stderr, VERSION, __DATE__);
  630. X      die(OUTEARLY);
  631. X      }
  632. X    else if (streq(argv[i], "-24"))
  633. X      Display_Type = INTERNAT;
  634. X    else
  635. X      usage(argv[0]);
  636. X
  637. X  if (!set_strings())
  638. X    usage(argv[0]);
  639. X
  640. X  if (Display_Type == INTERNAT && calc_time == gmtime)
  641. X    Display_Type = UTC;
  642. X
  643. X  switch (Display_Type) {
  644. X    case UTC      : Time_Suffix = "UTC"; break;
  645. X    case INTERNAT : Time_Suffix = "   "; break;
  646. X    default       : Time_Suffix = "ERR"; break; /* Something's broken
  647. X                                                   if this shows up. */
  648. X  }
  649. X
  650. X  /* Fix the alarm string. */
  651. X  if (Alarm_On && Display_Type == AM_PM && Alarm_Time[0] == '0')
  652. X    Alarm_Time[0] = ' ';
  653. X  if (strlen(Alarm_Time) == 5)
  654. X    strcat(Alarm_Time, "  ");
  655. X
  656. X}  /* get_args */
  657. X
  658. X
  659. X/* set_strings
  660. X     Set the terminal-control strings after we've read in the command-
  661. X     line arguments.  Unix versions may try to use termcap.  Return
  662. X     FALSE if the control strings cannot be set.
  663. X*/
  664. static bool set_strings()
  665. X{
  666. X
  667. X  if (Terminal_Kind != NO_TERM_DEF) {
  668. X    Open_Window  = Terminal_Description[(int)Terminal_Kind][0];
  669. X    Close_Window = Terminal_Description[(int)Terminal_Kind][1];
  670. X    Clear_Window = Terminal_Description[(int)Terminal_Kind][2];
  671. X#ifdef    unix
  672. X    P_CL         = Terminal_Description[(int)Terminal_Kind][3];
  673. X#endif
  674. X    return TRUE;
  675. X  }
  676. X
  677. X#if unix
  678. X  if (term_cap())
  679. X    return TRUE;
  680. X#endif
  681. X
  682. X  return FALSE;
  683. X
  684. X}  /* set_strings */
  685. X
  686. X
  687. X/* get_alarm
  688. X*/
  689. static void get_alarm(alarm)
  690. char *alarm;
  691. X{
  692. X  if (alarm[1] != ':')
  693. X    strcpy(Alarm_Time, alarm);
  694. X  else {
  695. X    Alarm_Time[0] = ' ';
  696. X    strcpy(Alarm_Time + 1, alarm);
  697. X  }
  698. X}  /* get_alarm */
  699. X
  700. X
  701. X/* special_work
  702. X     Do some special work for some particular terminals.
  703. X*/
  704. static void special_work()
  705. X{
  706. X
  707. X  switch(Terminal_Kind) {
  708. X    case Z1929 :
  709. X      /* open up the 25th line */
  710. X      fputs("\0337\033[>1h\0338", Fp); /* enable 25th line */
  711. X      fputs(Clear_Window, Fp); /* clear 25th line */
  712. X      fflush(Fp);
  713. X      break;
  714. X    default :
  715. X      break;
  716. X  }
  717. X
  718. X}  /* special_work */
  719. X
  720. X
  721. X/* do_display
  722. X     Display the time.
  723. X*/
  724. static void do_display()
  725. X{
  726. X  static char temp_time[26], out_string[150];
  727. X  static bool rang_bell = FALSE;
  728. X  static int  news_count = 0;
  729. X  int time_width;
  730. X  static char *mail_string = EMPTY_MAIL_STR;
  731. X  static char *news_string = EMPTY_NEWS_STR;
  732. X  static char *alarm_string = ALARM_OFF_STR;
  733. X
  734. X#ifdef unix
  735. X  /* News stuff */
  736. X  if (news_count == 0)
  737. X    news_string = has_news() ? NEW_NEWS_STR : EMPTY_NEWS_STR;
  738. X  news_count = (news_count + 1) % NEWS_FREQUENCY;
  739. X
  740. X  /* Mail stuff */
  741. X  switch (has_mail()) {
  742. X    case NO_MAIL  : mail_string = EMPTY_MAIL_STR;
  743. X                    rang_bell = FALSE;
  744. X                    break;
  745. X    case NEW_MAIL : if (Terminal_Kind == WYSE75)
  746. X                      mail_string = NEW_WYSE75_MAIL_STR;
  747. X                    else
  748. X                      mail_string = NEW_MAIL_STR;
  749. X                    if (Ring_Mail_Bell && !rang_bell) {
  750. X                      putc(BELL, Fp); fflush(Fp);
  751. X                      sleep(1);
  752. X                      putc(BELL, Fp);
  753. X                      rang_bell = TRUE;
  754. X                    }
  755. X                    break;
  756. X    case OLD_MAIL : mail_string = OLD_MAIL_STR;
  757. X                    rang_bell = FALSE;
  758. X                    break;
  759. X  }
  760. X
  761. X  strcpy(temp_time, asctime(Tp));
  762. X  if (Display_Type == AM_PM && temp_time[11] == '0') temp_time[11] = ' ';
  763. X#endif
  764. X
  765. X#ifdef  vms
  766. X  static char hr[3];
  767. X
  768. X  mail_string = EMPTY_MAIL_STR;
  769. X  strcpy(temp_time, ctime(&Tloc));
  770. X  if (Display_Type == AM_PM)
  771. X    sprintf(hr, "%2d", Tp->tm_hour);
  772. X  else
  773. X    sprintf(hr, "%02d", Tp->tm_hour);
  774. X  temp_time[11] = hr[0];
  775. X  temp_time[12] = hr[1];
  776. X#endif
  777. X
  778. X  if (Alarm_On &&
  779. X      strncmp(temp_time + 11, Alarm_Time, 5) == 0 &&
  780. X      strncmp(Time_Suffix, Alarm_Time + 5, 2) == 0) {
  781. X    putc(BELL, Fp); fflush(Fp);
  782. X    sleep(1);
  783. X    putc(BELL, Fp);
  784. X    Alarm_On = FALSE;
  785. X  }
  786. X
  787. X  alarm_string = Alarm_On ? ALARM_ON_STR : ALARM_OFF_STR;
  788. X
  789. X  time_width = Seconds_On ? 19 : 16;
  790. X  sprintf(out_string, "%s%s%s%s %*.*s %s%s",
  791. X                      Open_Window, news_string, alarm_string, mail_string,
  792. X                      time_width, time_width,
  793. X                      temp_time,
  794. X                      Time_Suffix,
  795. X                      Close_Window);
  796. X  fputs(out_string, Fp);
  797. X  fflush(Fp);
  798. X
  799. X}  /* do_display */
  800. X
  801. X
  802. X/* fix_hour
  803. X     Change 24-hour time to 12-hour time.
  804. X     Return AM or PM.
  805. X*/
  806. static void fix_hour(hour)
  807. int hour;
  808. X{
  809. X
  810. X  if (Display_Type == AM_PM)
  811. X    if (1 <= hour && hour <= 11)
  812. X      Time_Suffix = "am ";
  813. X    else if (13 <= hour && hour <= 23) {
  814. X      Tp->tm_hour -= 12;
  815. X      Time_Suffix = "pm ";
  816. X      }
  817. X    else if (hour == 0) {
  818. X      Tp->tm_hour = 12;
  819. X      Time_Suffix = "am ";
  820. X      }
  821. X    else if (hour == 12)
  822. X      Time_Suffix = "pm ";
  823. X    
  824. X}  /* fix_hour */
  825. X
  826. X
  827. X/* chimes
  828. X     Rings the bell the correct number of times.
  829. X*/
  830. static void chimes(hour)
  831. int hour;
  832. X{
  833. X  int i;
  834. X
  835. X  switch (Chime) {
  836. X    case NO_CHIME :
  837. X      break;
  838. X    case SINGLE_CHIME :
  839. X      putc(BELL, Fp);
  840. X      fflush(Fp);
  841. X      break;
  842. X    case MULTIPLE_CHIMES :
  843. X      for (i = 0; i < hour; i++) {
  844. X        putc(BELL, Fp);
  845. X        fflush(Fp);
  846. X        sleep(1);
  847. X      }
  848. X      break;
  849. X  }
  850. X  
  851. X}  /* chimes */
  852. X
  853. X
  854. X/* die
  855. X     Come here to die.
  856. X*/
  857. static int die(i)
  858. int i;
  859. X{
  860. X
  861. X  if (i == OUTEARLY) exit(QUIET);
  862. X
  863. X  if (i == BYEBYE || i == SIGTERM || i == SIGINT) {
  864. X    fputs(Clear_Window, Fp);
  865. X    fflush(Fp);
  866. X  }
  867. X  if (i == BYEBYE) exit(QUIET);
  868. X  if (i == SIGTERM || i == SIGINT) exit(i);
  869. X
  870. X  exit(i); /* probably won't ever happen */
  871. X
  872. X}  /* die */
  873. X
  874. X
  875. X/* usage
  876. X     Call when the program is envoked with the wrong arguments.
  877. X     Display a brief usage message and then die.
  878. X*/
  879. static void usage(pname)
  880. char *pname;
  881. X{
  882. X  int i;
  883. X  static char *msgs[] =
  884. X  {
  885. X#ifdef  unix
  886. X    "usage:  %s  [options]  [TERM]  &\n",
  887. X    "  where options is any combination of\n",
  888. X    "    -aTIME -b  -bb  -i#  -m  -mb  -mboxPATH  -n  -s  -ss#  -u  -24  -v\n",
  889. X    "  and where TERM is one of  att4425, tvi950, tvi955, wyse50, wyse60,\n",
  890. X    "                            wyse75, wyse75-bottom, z19, z29, off\n"
  891. X#endif
  892. X#ifdef  vms
  893. X    "\nusage:  %s  options  TERM\n",
  894. X    "  where options is any combination of\n",
  895. X    "    -aTIME -b  -bb  -i#  -s  -u  -24  -v\n",
  896. X    "  and where TERM is one of  att4425, tvi950, tvi955, wyse50, wyse60,\n",
  897. X    "                            wyse75, wyse75-bottom, z19, z29\n"
  898. X#endif
  899. X  };
  900. X
  901. X#ifdef  vms
  902. X  pname = "clock";
  903. X#endif
  904. X
  905. X  fprintf(stderr, msgs[0], pname);
  906. X  for (i = 1; i < sizeof msgs / sizeof msgs[0]; i++)
  907. X    fputs(msgs[i], stderr);
  908. X
  909. X  die(OUTEARLY);
  910. X
  911. X}  /* usage */
  912. X
  913. X/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  914. X
  915. X#ifdef  unix
  916. X/* find
  917. X     Find starting index of the first string within the second.
  918. X     Return -1 if not there.
  919. X*/
  920. static int find(t, s)
  921. char *t, *s;
  922. X{
  923. X  int i, n;
  924. X
  925. X  n = strlen(t);
  926. X  for (i = 0; s[i] != EOS; i++)
  927. X    if (strncmp(s+i, t, n) == 0)
  928. X      return i;
  929. X  return -1;
  930. X
  931. X}  /* find */
  932. X
  933. X
  934. X/* stop
  935. X     Stop all your processes called "clock".
  936. X*/
  937. static void stop(pname)
  938. char *pname;
  939. X{
  940. X  FILE *fin;
  941. X  static char buf[BUFSIZ];
  942. X  int pid;
  943. X
  944. X  if ((fin = popen("ps x", "r")) == NULL)
  945. X    usage(pname);
  946. X  fgets(buf, sizeof(buf), fin); /* skip over first line of ps output */
  947. X  while (fgets(buf, sizeof(buf), fin) != NULL)
  948. X    if (find(pname, buf) >= 0) {
  949. X      buf[strlen(buf) - 1] = EOS;
  950. X      sscanf(buf, "%d", &pid);
  951. X      if (pid != getpid()) kill(pid,  SIGTERM);
  952. X    }
  953. X
  954. X}  /* stop */
  955. X
  956. X
  957. X/* has_news - checks news */
  958. static bool has_news()
  959. X{
  960. X  FILE *news_fd;
  961. X#define TEMP_STR 15
  962. X  char temp[TEMP_STR + 1];
  963. X  bool n_flag;
  964. X
  965. X  if (!Check_News) return FALSE;
  966. X  if ((news_fd = popen("/usr/local/checknews", "r")) == NULL)
  967. X    return FALSE;
  968. X  n_flag = fgets(temp, TEMP_STR, news_fd) != NULL;
  969. X  pclose(news_fd);
  970. X  return n_flag;
  971. X} /* has_news */
  972. X
  973. X
  974. X/* has_mail
  975. X     Return a value based on the status of the mail file.
  976. X*/
  977. static mail_type has_mail()
  978. X{
  979. X  static struct stat buf;
  980. X
  981. X  if (!Check_Mail) return NO_MAIL;
  982. X  if (stat(Mailfile, &buf) == -1) return NO_MAIL;
  983. X  if (buf.st_atime > buf.st_mtime) return OLD_MAIL;
  984. X  return NEW_MAIL;
  985. X      
  986. X} /* has_mail */
  987. X
  988. X
  989. X/* init_mailfile
  990. X     Initialize Mailfile name.
  991. X*/
  992. static void init_mailfile(progname)
  993. char *progname;
  994. X{
  995. X  char *p, *getlogin();
  996. X  struct passwd *pw, *getpwuid();
  997. X
  998. X  if ((p = getlogin()) == NULL) {
  999. X    pw = getpwuid(getuid());
  1000. X    if (pw == NULL ) {
  1001. X      fprintf(stderr, "%s: Can't check mail!\n", progname);
  1002. X      Mailfile[0] = EOS;
  1003. X      Check_Mail = FALSE;
  1004. X      return;
  1005. X    }
  1006. X    p = (*pw).pw_name;
  1007. X  }
  1008. X
  1009. X  /* Mailfile may have been set in get_args. */
  1010. X  if (Mailfile[0] == EOS) {
  1011. X    strcpy(Mailfile, MAILDIR);
  1012. X    strcat(Mailfile, p);
  1013. X  }
  1014. X
  1015. X} /*init_mailfile */
  1016. X
  1017. X
  1018. X/* find_idle
  1019. X     Return the number of minutes the current tty has been idle.
  1020. X*/
  1021. static long find_idle(tty)
  1022. char *tty;
  1023. X{
  1024. X  struct stat ttystatus;
  1025. X  long current_time;
  1026. X
  1027. X  if (stat(tty, &ttystatus) < 0) {
  1028. X    fprintf(stderr, "finger: Can't stat %s\n", tty);
  1029. X    exit(1);
  1030. X  }
  1031. X  time(¤t_time);
  1032. X  return current_time < ttystatus.st_atime
  1033. X           ? 0L : (current_time - ttystatus.st_atime) / 60;
  1034. X                  /* change from seconds to minutes */
  1035. X
  1036. X}  /* find_idle */
  1037. X
  1038. X/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  1039. X/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  1040. X
  1041. extern char *getenv(), *tgetstr(), *tgoto();
  1042. static char *tget();
  1043. X
  1044. char clear_wn[80]; /* Clears the status line. */
  1045. X
  1046. X/* Buffer of original string from termcap gotten by using tgetent(). */
  1047. char TC_Buf[1024];
  1048. X/* Buffer of decoded strings gotten by using tgetstr(). */
  1049. char Decoded_Buf[200];
  1050. X
  1051. X
  1052. X/* term_cap
  1053. X     Attempt to read and decode the "hs", "ts", "fs", and "ds"
  1054. X     capabilities from the termcap data base.
  1055. X*/
  1056. static bool term_cap()
  1057. X{
  1058. X  char *cur_bp = Decoded_Buf;
  1059. X  char *tc_name;
  1060. X  char *P_CM;
  1061. X
  1062. X  /* Makes sure we have a valid termcap  */
  1063. X  switch (tgetent(TC_Buf, tc_name = getenv("TERM")) ) {
  1064. X    case -1:
  1065. X      fprintf(stderr, "Termcap file not accessible.\n");
  1066. X      die(OUTEARLY);
  1067. X    case 0:
  1068. X      fprintf(stderr, "Termcap entry not available for %s.\n", tc_name);
  1069. X      die(OUTEARLY);
  1070. X  }
  1071. X
  1072. X  P_CL = tgetstr("cl", &cur_bp);
  1073. X  if (P_CL == NULL)
  1074. X    Screen_Save_Interval = 0; /* can't clear the screen */
  1075. X
  1076. X  if (tgetflag("hs") == 0)
  1077. X    return FALSE;
  1078. X
  1079. X  P_CM = tgetstr("ts", &cur_bp);
  1080. X  if (P_CM == NULL)
  1081. X    return FALSE;
  1082. X  /* The "ts" capability can be specified with a parameter and so
  1083. X     we use tgoto put the number in correctly. */
  1084. X  Open_Window = tgoto(P_CM, 0, 0);
  1085. X
  1086. X  if (Open_Window == NULL || Open_Window[0] == EOS)
  1087. X    return FALSE;
  1088. X
  1089. X  Close_Window = tgetstr("fs", &cur_bp);
  1090. X  if (Close_Window == NULL)
  1091. X    return FALSE;
  1092. X
  1093. X  Clear_Window = tgetstr("ds", &cur_bp);
  1094. X  if (Clear_Window == NULL) {
  1095. X    strcpy(clear_wn, Open_Window);
  1096. X    strcat(clear_wn, Close_Window);
  1097. X    Clear_Window = clear_wn;
  1098. X  }
  1099. X
  1100. X  return TRUE;
  1101. X
  1102. X}  /* term_cap */
  1103. X
  1104. X
  1105. static int putone(ch)
  1106. char ch;
  1107. X{
  1108. X  (void) fwrite(&ch, sizeof(char), 1, stdout);
  1109. X}  /* putone */
  1110. X
  1111. X
  1112. X/* Print an error message, make certain the keyboard is in cooked
  1113. X   mode, and exit.
  1114. X*/
  1115. X
  1116. X/* clrscr
  1117. X*/
  1118. static void clrscr()
  1119. X{
  1120. X  static int count = 0;
  1121. X  int i;
  1122. X
  1123. X  tputs(P_CL, 1, putone);
  1124. X  for (i = 0; i < count; i++)
  1125. X    fputc(' ', stdout);
  1126. X  fputs("Press <RETURN>\n", stdout);
  1127. X  count = count < 60 ? count + 1 : 0;
  1128. X}  /* clrscr */
  1129. X
  1130. X#endif
  1131. X
  1132. X/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  1133. X/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  1134. END_OF_FILE
  1135. if test 24384 -ne `wc -c <'clock.c'`; then
  1136.     echo shar: \"'clock.c'\" unpacked with wrong size!
  1137. fi
  1138. # end of 'clock.c'
  1139. fi
  1140. echo shar: End of shell archive.
  1141. exit 0
  1142. -- 
  1143. Robert J. Drabek                            robert@cs.Arizona.EDU
  1144. Department of Computer Science              uunet!arizona!robert
  1145. The University of Arizona                   602 621 4326
  1146. Tucson, AZ  85721
  1147.  
  1148.