From decwrl!wyse!mips!zaphod.mps.ohio-state.edu!usc!cs.utexas.edu!uunet!allbery Wed May 16 10:16:32 PDT 1990
Article 1579 of comp.sources.misc:
Path: decwrl!wyse!mips!zaphod.mps.ohio-state.edu!usc!cs.utexas.edu!uunet!allbery
From: robert@cs.arizona.edu (Robert J. Drabek)
Newsgroups: comp.sources.misc
Subject: v12i086: A Wall Clock
Message-ID: <88876@uunet.UU.NET>
Date: 14 May 90 23:06:57 GMT
Sender: allbery@uunet.UU.NET
Organization: U of Arizona CS Dept, Tucson
Lines: 1140
Approved: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)

Posting-number: Volume 12, Issue 86
Submitted-by: robert@cs.arizona.edu (Robert J. Drabek)
Archive-name: wclock/part01

A Wall Clock

For those who use standard terminals instead of work stations, but still
want a clock display and mail indicator, this program will help you out
if your terminal includes a status line (aka the 25th line).  Also
includes screen-saver and alarm options and you can select 24-hour
or UTC displays.

It works under Unix (BSD) and VMS.

It knows about the status line for the following terminals:
  AT&T 4425, TeleVideo 950, TeleVideo 955, Wyse-60, Wyse-75,
  Zenith/Heath-19 & 29 (if in ANSI mode)
But if your termcap (Unix) includes the "hs", "ts", and "fs"
capabilities for some other terminal the program will use those
automatically.

Run it in the background.  Some examples (under Unix):

     clock wyse60 &       # If your termcap doesn't include hs, ts, fs.
     clock -i15 -s &      # If your termcap does include hs, ts, fs and
                          #   you want seconds displayed every 15 seconds.

Unix users, as the clock program will tell you nicely when you have
mail, you will want to run the "biff n" command to disable the mailer
messing up your screen.

VMS users, you must specify the terminal type, and the mail and news
indicators don't work.  If some interprising VMS hacker can show me how
to add the "has_mail" function into the program, I would appreciate it.

--
Robert J. Drabek                            robert@cs.Arizona.EDU
Department of Computer Science              uunet!arizona!robert
The University of Arizona                   602 621 4326
Tucson, AZ  85721

/* - - - - - - - - - - - - - -  CUT HERE  - - - - - - - - - - - - - - - */
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  README Makefile clock.c
# Wrapped by robert@megaron.cs.arizona.edu on Mon May 14 10:33:49 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(1468 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
A Wall Clock
X
XFor those who use standard terminals instead of work stations, but still
want a clock display and mail indicator, this program will help you out
if your terminal includes a status line (aka the 25th line).  Also
includes screen-saver and alarm options.
X
It works under Unix (BSD) and VMS.
X
It knows about the status line for the following terminals:
X  AT&T 4425, TeleVideo 950, TeleVideo 955, Wyse-60, Wyse-75,
X  Zenith/Heath-19 & 29 (if in ANSI mode)
But if your termcap (Unix) includes the "hs", "ts", and "fs"
capabilities for some other terminal the program will use those
automatically.
X
Run it in the background.  Some examples (under Unix):
X
X     clock wyse60 &       # If your termcap doesn't include hs, ts, fs.
X     clock -i15 -s &      # If your termcap does include hs, ts, fs and
X                          #   you want seconds displayed every 15 seconds.
X
Unix users, as the clock program will tell you nicely when you have
mail, you will want to run the "biff n" command to disable the mailer
messing up your screen.
X
VMS users, you must specify the terminal type and the mail and news
indicators don't work.  If some interprising VMS hacker can show me how
to add the "has_mail" function into the program, I would appreciate it.
X
X--
Robert J. Drabek                            robert@cs.Arizona.EDU
Department of Computer Science              uunet!arizona!robert
The University of Arizona                   602 621 4326
Tucson, AZ  85721
END_OF_FILE
if test 1468 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(901 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
X#
X# Makefile for the clock program.
X#
X# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
X
XEXECUTABLE = clock
X
DATE_STRING = "\"`date`\""
MAILDIR = "\"/usr/spool/mail/\""
X
CFLAGS = -O -s -x -D__DATE__=$(DATE_STRING) -DMAILDIR=$(MAILDIR)
X
X$(EXECUTABLE) :	$(EXECUTABLE).c
X	cc $(CFLAGS) $(EXECUTABLE).c -o $(EXECUTABLE) -ltermcap
X
X# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
X
X# Install files in the correct directories.
install : $(EXECUTABLE)
X	-cp $(EXECUTABLE)    /usr/local
X	-cp $(EXECUTABLE).1  /usr/man/manl/$(EXECUTABLE).l
X	-cp $(EXECUTABLE).c  /usr/src/local
X
X# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
X
lint :
X	lint -D__DATE__="\"xxx\"" -DMAILDIR=$(MAILDIR) $(EXECUTABLE).c -ltermcap
X
X# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
END_OF_FILE
if test 901 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'clock.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'clock.c'\"
else
echo shar: Extracting \"'clock.c'\" \(24384 characters\)
sed "s/^X//" >'clock.c' <<'END_OF_FILE'
X/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
X
X   A wall clock for the special display area (status line) of your
X   terminal.  Works under Unix (BSD 4.3) and VMS.
X
X   If no terminal is specified then, under Unix, the termcap will
X   be examined, looking for the "hs", "ts", and "fs" capabilities.
X
X   Otherwise the last argument can specify one of
X      att4425, tvi950, tvi955, wyse50, wyse60, wyse75, wyse75-bottom,
X      z19 (if in ANSI mode), z29 (if in ANSI mode).
X
X   In addition to the time, under Unix a message will be displayed
X   if mail is waiting.
X
X   "clock off" will kill all clock processes under Unix.
X
X   Options:
X
X     -aTIME
X           Sets an alarm for the given time.
X           The time must be of the form xx:xx plus possibly am,
X           pm or UTC, depending upon the form of the clock indicator.
X           Examples: -a10:24am   -a9:21pm   -a11:52UTC   -a17:20
X     -b    The terminal's bell is rung on the hour.
X     -bb   The terminal's bell is rung multiple times on the hour.
X     -24   Display 24-hour time instead of am/pm.
X     -s    The display includes the seconds.
X     -ss#  Invokes the screen saver.  # is optional and is the number
X             of minutes to screen saving.  (Unix only).
X     -i#   Specifies the interval (in seconds) between display
X             updates (default is 60 seconds).
X     -m    Don't check for mail; used when the display interval
X             is small and we want to conserve resources.
X     -mb   Don't ring the silly bell when new mail arrives.
X     -mboxPATH
X           Use an alternate path name for the mail box file.
X           Example: clock -mbox/usr/spool/secretmail/joan
X     -n    Do check for news!  (Not the default.)  (Unix only).
X     -u    Give UTC (aka Greenwich mean time)
X     -v    Just prints the version number and compile date.
X
X   Robert J. Drabek
X   The University of Arizona
X  
X   March 1986 with various modifications since.
X
X   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
X
X   Unix compilation:
X       cc -O -s -x -n clock.c -o clock -ltermcap \
X          -D__DATE__='"June 10, 1989"' -DMAILDIR="/usr/spool/mail/"
X                (where you substitute the correct date and spool directory)
X                 or
X       gcc -O -s -x -n clock.c -o clock -DMAILDIR="/usr/spool/mail/"
X  
X   VMS compilation:   cc/optim clock.c
X                      link clock
X  
X   It should be run as a backround process, for example,
X
X     UNIX:  clock -bb wyse75 &
X
X     VMS:   First, define RUNCLOCK :== $MYDISK:[MYDIRS]CLOCK.EXE
X                      and CLOCK :== SPAWN/NOWAIT/INPUT=NL: RUNCLOCK
X            (where MYDISK and MYDIRS are appropriate for your machine)
X            Then, use clock -bb wyse75
X
X   If you cannot modify termcap, clock can be modified to perform on
X   other video terminals, provided they either incorporate the cursor-save
X   function within their command repertoire or automatically return the
X   cursor after writing to the special display area.  The modifications
X   will entail adding new entries to the terminal_kinds enumerated type
X   and the Terminal_Description table below.
X
X   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
X  
X
X#define VERSION "Version 4.1 (%s) Robert J. Drabek\n"
X
X
X/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
X
X#define EMPTY_NEWS_STR      "  "
X#define NEW_NEWS_STR        " *"
X#define ALARM_OFF_STR       "  "
X#define ALARM_ON_STR        "! "
X#define EMPTY_MAIL_STR      "          "
X#define NEW_MAIL_STR        " NEW MAIL "
X#define NEW_WYSE75_MAIL_STR "\016\017QNEW MAIL\016\017@"
X#define OLD_MAIL_STR        "     Mail "
X
X/* If the above are changed, the Open_Window and Close_Window
X   strings below will probably also need to be changed. */
X
X/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
X
X   These tables store all terminal-specific data.
X
X   The enumerated type and the character array must be kept in
X   correspondence.
X
X   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
X
typedef enum {
X  ATT4425      =  0,
X  TVI950955    =  1,
X  WYSE5060     =  2,
X  WYSE75       =  3,
X  WYSE75BOTTOM =  4,
X  Z1929        =  5, /* with terminal set to ANSI mode */
X  NO_TERM_DEF  = -1
X} terminal_kinds;
X
X
X/* The three strings for each terminal type are respectively
X     Open window,
X     Close window,
X     Clear window,
X     Clear screen.
X*/
X
static char *Terminal_Description[][5] = {
X
X  /* ATT4425 */
X  { "\0337\033[7m\033[25;9H",
X    "\033[8m\0338",
X    "\0337\033[25;1H                                                 \0338",
X    "\033[;H\033[2J" },
X
X  /* TVI950955 */
X  { "\033f         ",
X    "\r",
X    "\033f\r",
X    "\033*" },
X
X  /* WYSE5060 */
X  { "\033F      ",
X    "\r",
X    "\033F\r",
X    "\032" },
X
X  /* WYSE75 : Wyse-75, upper-right corner */
X  { "\033[>+? ",
X    "?",
X    "\033[>+? ?",
X    "\033[;H\033[2J" },
X
X  /* WYSE75BOTTOM : Wyse-75, 25th line */
X     /* ^N^OQ goes into reverse video, ^N^O@ leaves reverse video
X        ?'s delimit string  */
X  { "\033[>,?         \016\017Q ",
X    "        \016\017@?",
X    "\033[>,? ?",
X    "\033[;H\033[2J" },
X
X  /* Z1929 */
X     /* Time window is on the 25th line.  Terminal set to ANSI mode */
X  { "\0337\033[25;9H\033[2K= = ",
X    "      = =\0338",
X    "\0337\033[>1h\033[25;1H\033[2K\033[>1l\0338",
X    "\033[;H\033[2J" },
X
X};
X
X/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
X
X
X#include <signal.h>
X#include <stdio.h>
X#include <time.h>
X
X#ifdef  unix
X#include <sgtty.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#endif
X#ifdef	vms
X#include <unixio.h>
X#endif
X
typedef char bool;
X#define TRUE    1
X#define FALSE   0
X
X#define BELL '\07'
X#define EOS  '\0'
X
X#define OUTEARLY -2  /* two exceptions to be handled specially */
X#define BYEBYE   -1
X
X#define streq(s1,s2) (strcmp(s1,s2)==0)
X
typedef enum { AM_PM, INTERNAT, UTC } suffix_type;
X
typedef enum { NO_CHIME, SINGLE_CHIME, MULTIPLE_CHIMES } chime_type;
X
X#ifdef unix
X#define NEWS_FREQUENCY 5  /* How often we check for news. */
X
X/* This should be defined on the compile command line:
X     MAILDIR  "/usr/spool/mail/"
X*/
typedef enum { NO_MAIL, NEW_MAIL, OLD_MAIL } mail_type;
X#endif
X
X#define WHICH_FD 2
X
X#ifdef  unix
extern FILE *popen();
extern char *ttyname();
X#define TERM_NAME ttyname(WHICH_FD)
X#define QUIET  0
X#endif
X
X#ifdef  vms
X#define TERM_NAME "SYS$OUTPUT:"
X#define QUIET  1
X#endif
X
X/* Global variables */
struct tm *Tp;
long       Tloc;
X
struct tm *((*calc_time)());
X
int Update_Interval      = 60; /* seconds */
X#ifdef	unix
bool         Check_Mail     = TRUE;  /* whether or not to check the mail */
bool         Ring_Mail_Bell = TRUE;  /* whether or not to ring the mail bell */
bool         Check_News     = FALSE; /* whether or not to check the news */
int          Screen_Save_Interval = 0; /* minutes */
static char *P_CL = NULL;
X#endif
X
terminal_kinds Terminal_Kind = NO_TERM_DEF;
X
char *Open_Window, *Close_Window, *Clear_Window;
X
chime_type  Chime          = NO_CHIME; /* ring the chimes every hour */
bool        Alarm_On       = FALSE;
char        Alarm_Time[26] = { EOS };
suffix_type Display_Type   = AM_PM;
char       *Time_Suffix    = "ERR";
bool        Seconds_On     = FALSE;  /* display will include the seconds */
XFILE       *Fp;
X
X#ifdef unix
X#include <pwd.h>
char        Mailfile[100];
X#endif
X
X/* Forward function declarations for time. */
extern int      (*signal())();
extern struct tm *localtime();
extern struct tm *gmtime();
extern long       time();
X
X#ifdef  unix
extern char *asctime();
extern int   getppid();
X#endif
X
X#ifdef  vms
extern char *ctime();
X#endif
X
X
static void get_args();
static bool set_strings();
static bool term_cap();
static void special_work();
static void get_alarm();
static void do_display();
static void fix_hour();
static void chimes();
static int  die();
static void usage();
X
X#ifdef unix
static int       find();
static void      stop();
static bool      has_news();
static mail_type has_mail();
static void      init_mailfile();
static long      find_idle();
static void      clrscr();
X#endif
X
X/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
X
main(argc, argv)
int   argc;
char *argv[];
X{
X#ifdef  unix
X  int orig_ppid, new_ppid;
X  long idle_time;
X#define MAXNAME 20
X  static char tty[MAXNAME + 1];
X#endif
X
X  if (!isatty(WHICH_FD))
X    die(OUTEARLY);
X
X  if ((Fp = fopen(TERM_NAME, "w")) == NULL) {
X    fprintf(stderr, "%s - cannot open %s\n", argv[0], TERM_NAME);
X    die(OUTEARLY);
X  }
X
X  get_args(argc, argv);
X
X#ifdef unix
X  init_mailfile(argv[0]);
X  strcpy(tty, ttyname(0));
X#endif
X
X
X  signal(SIGTERM, die);
X  signal(SIGINT, die);
X
X#ifdef  unix
X  orig_ppid = getppid(); /* Keep track of the current process, so after
X                            you log out, the clock will know to die off. */
X  if (orig_ppid == 1) die(OUTEARLY); /* For when people try to run this
X                                     from vi or whatever. */
X#endif
X
X  special_work();
X
X  Tloc = time((long *)0);
X  Tp = (*calc_time)(&Tloc);
X
X  fix_hour(Tp->tm_hour);
X  do_display();
X
X
X  /* This is the main loop which displays the clock periodically. */
X
X  for (;;) {
X
X#ifdef  unix
X    if ((new_ppid = getppid()) != orig_ppid) die(BYEBYE);
X    if (new_ppid == 1) die(BYEBYE); /* For when people try to run this
X                                       from vi or whatever. */
X#endif
X
X    Tp = (*calc_time)(&Tloc);
X    sleep( (unsigned) (Update_Interval - Tp->tm_sec % Update_Interval) );
X
X    Tloc = time((long *)0);
X    Tp = (*calc_time)(&Tloc);
X        
X    fix_hour(Tp->tm_hour);
X    do_display();
X
X    if (Chime != NO_CHIME && Tp->tm_min == 00 && Tp->tm_sec <= 3)
X      chimes(Tp->tm_hour);
X
X#ifdef	unix
X    if (Screen_Save_Interval != 0  && Tp->tm_min % 5 == 0 && Tp->tm_sec <= 3) {
X      idle_time = find_idle(tty);
X      if (idle_time >= Screen_Save_Interval)
X        clrscr();
X    }
X#endif
X
X  }
X
X}  /* main */
X
X
X/* get_args
X     Read the arguments and set up the various globals appropriately.
X*/
static void get_args(argc, argv)
int   argc;
char *argv[];
X{
X  char *getenv();
X  char *termdef;
X  int  i;
X
X#ifdef	unix
X  Mailfile[0] = EOS;
X#endif
X
X  calc_time = localtime;
X
X  if ((termdef = getenv("TERM")) != NULL)
X    if      (streq(termdef,   "att4425")
X            || streq(termdef, "att"))
X      Terminal_Kind = ATT4425;
X    else if (streq(termdef,   "tvi950")
X            || streq(termdef, "tvi955"))
X      Terminal_Kind = TVI950955;
X    else if (streq(termdef,   "wyse")
X            || streq(termdef, "wyse75"))
X      Terminal_Kind = WYSE75;
X    else if (streq(termdef,   "wyse75-bottom"))
X      Terminal_Kind = WYSE75BOTTOM;
X    else if (streq(termdef,   "wyse50")
X            || streq(termdef, "wyse60"))
X      Terminal_Kind = WYSE5060;
X    else if (streq(termdef,   "z19")
X            || streq(termdef, "h19")
X            || streq(termdef, "s19")
X            || streq(termdef, "z29")
X            || streq(termdef, "h29"))
X      Terminal_Kind = Z1929;
X
X  for (i = 1; i < argc; i++)
X
X    if      (streq(argv[i],   "att4425")
X            || streq(argv[i], "att"))
X      Terminal_Kind = ATT4425;
X    else if (streq(argv[i],   "tvi950")
X            || streq(argv[i], "tvi955"))
X      Terminal_Kind = TVI950955;
X    else if (streq(argv[i],   "wyse")
X            || streq(argv[i], "wyse75"))
X      Terminal_Kind = WYSE75;
X    else if (streq(argv[i],   "wyse75-bottom"))
X      Terminal_Kind = WYSE75BOTTOM;
X    else if (streq(argv[i],   "wyse50")
X            || streq(argv[i], "wyse60"))
X      Terminal_Kind = WYSE5060;
X    else if (streq(argv[i],   "z19")
X            || streq(argv[i], "h19")
X            || streq(argv[i], "s19")
X            || streq(argv[i], "z29")
X            || streq(argv[i], "h29"))
X      Terminal_Kind = Z1929;
X#ifdef  unix
X    else if (streq(argv[i], "off")) {
X      stop(argv[0]);
X      die(OUTEARLY);
X      }
X#endif
X    else if (strncmp(argv[i], "-a", 2) == 0) {
X      Alarm_On = TRUE;
X      get_alarm(argv[i] + 2);
X      }
X    else if (streq(argv[i], "-b"))
X      Chime = SINGLE_CHIME;
X    else if (streq(argv[i], "-bb"))
X      Chime = MULTIPLE_CHIMES;
X    else if (strncmp(argv[i], "-i", 2) == 0) {
X      Update_Interval = atoi(argv[i] + 2);
X      if (Update_Interval < 1) Update_Interval = 60;
X      }
X#ifdef	unix
X    else if (streq(argv[i], "-m"))
X      Check_Mail = FALSE;
X    else if (streq(argv[i], "-mb"))
X      Ring_Mail_Bell = FALSE;
X    else if (strncmp(argv[i], "-mbox", 5) == 0)
X      strcpy(Mailfile, argv[i] + 5);
X    else if (streq(argv[i], "-n"))
X      Check_News = TRUE;
X#endif
X    else if (streq(argv[i], "-s"))
X      Seconds_On = TRUE;
X#ifdef	unix
X    else if (strncmp(argv[i], "-ss", 3) == 0) {
X      /* in minutes */
X      Screen_Save_Interval = atoi(argv[i] + 3);
X      if (Screen_Save_Interval < 1)
X        Screen_Save_Interval = 60;
X      else if (Screen_Save_Interval < 5)
X        Screen_Save_Interval = 5;
X      }
X#endif
X    else if (streq(argv[i], "-u")) {
X      calc_time = gmtime;
X      Display_Type = UTC;
X      }
X    else if (streq(argv[i], "-v")) {
X      fprintf(stderr, VERSION, __DATE__);
X      die(OUTEARLY);
X      }
X    else if (streq(argv[i], "-24"))
X      Display_Type = INTERNAT;
X    else
X      usage(argv[0]);
X
X  if (!set_strings())
X    usage(argv[0]);
X
X  if (Display_Type == INTERNAT && calc_time == gmtime)
X    Display_Type = UTC;
X
X  switch (Display_Type) {
X    case UTC      : Time_Suffix = "UTC"; break;
X    case INTERNAT : Time_Suffix = "   "; break;
X    default       : Time_Suffix = "ERR"; break; /* Something's broken
X                                                   if this shows up. */
X  }
X
X  /* Fix the alarm string. */
X  if (Alarm_On && Display_Type == AM_PM && Alarm_Time[0] == '0')
X    Alarm_Time[0] = ' ';
X  if (strlen(Alarm_Time) == 5)
X    strcat(Alarm_Time, "  ");
X
X}  /* get_args */
X
X
X/* set_strings
X     Set the terminal-control strings after we've read in the command-
X     line arguments.  Unix versions may try to use termcap.  Return
X     FALSE if the control strings cannot be set.
X*/
static bool set_strings()
X{
X
X  if (Terminal_Kind != NO_TERM_DEF) {
X    Open_Window  = Terminal_Description[(int)Terminal_Kind][0];
X    Close_Window = Terminal_Description[(int)Terminal_Kind][1];
X    Clear_Window = Terminal_Description[(int)Terminal_Kind][2];
X#ifdef	unix
X    P_CL         = Terminal_Description[(int)Terminal_Kind][3];
X#endif
X    return TRUE;
X  }
X
X#if unix
X  if (term_cap())
X    return TRUE;
X#endif
X
X  return FALSE;
X
X}  /* set_strings */
X
X
X/* get_alarm
X*/
static void get_alarm(alarm)
char *alarm;
X{
X  if (alarm[1] != ':')
X    strcpy(Alarm_Time, alarm);
X  else {
X    Alarm_Time[0] = ' ';
X    strcpy(Alarm_Time + 1, alarm);
X  }
X}  /* get_alarm */
X
X
X/* special_work
X     Do some special work for some particular terminals.
X*/
static void special_work()
X{
X
X  switch(Terminal_Kind) {
X    case Z1929 :
X      /* open up the 25th line */
X      fputs("\0337\033[>1h\0338", Fp); /* enable 25th line */
X      fputs(Clear_Window, Fp); /* clear 25th line */
X      fflush(Fp);
X      break;
X    default :
X      break;
X  }
X
X}  /* special_work */
X
X
X/* do_display
X     Display the time.
X*/
static void do_display()
X{
X  static char temp_time[26], out_string[150];
X  static bool rang_bell = FALSE;
X  static int  news_count = 0;
X  int time_width;
X  static char *mail_string = EMPTY_MAIL_STR;
X  static char *news_string = EMPTY_NEWS_STR;
X  static char *alarm_string = ALARM_OFF_STR;
X
X#ifdef unix
X  /* News stuff */
X  if (news_count == 0)
X    news_string = has_news() ? NEW_NEWS_STR : EMPTY_NEWS_STR;
X  news_count = (news_count + 1) % NEWS_FREQUENCY;
X
X  /* Mail stuff */
X  switch (has_mail()) {
X    case NO_MAIL  : mail_string = EMPTY_MAIL_STR;
X                    rang_bell = FALSE;
X                    break;
X    case NEW_MAIL : if (Terminal_Kind == WYSE75)
X                      mail_string = NEW_WYSE75_MAIL_STR;
X                    else
X                      mail_string = NEW_MAIL_STR;
X                    if (Ring_Mail_Bell && !rang_bell) {
X                      putc(BELL, Fp); fflush(Fp);
X                      sleep(1);
X                      putc(BELL, Fp);
X                      rang_bell = TRUE;
X                    }
X                    break;
X    case OLD_MAIL : mail_string = OLD_MAIL_STR;
X                    rang_bell = FALSE;
X                    break;
X  }
X
X  strcpy(temp_time, asctime(Tp));
X  if (Display_Type == AM_PM && temp_time[11] == '0') temp_time[11] = ' ';
X#endif
X
X#ifdef  vms
X  static char hr[3];
X
X  mail_string = EMPTY_MAIL_STR;
X  strcpy(temp_time, ctime(&Tloc));
X  if (Display_Type == AM_PM)
X    sprintf(hr, "%2d", Tp->tm_hour);
X  else
X    sprintf(hr, "%02d", Tp->tm_hour);
X  temp_time[11] = hr[0];
X  temp_time[12] = hr[1];
X#endif
X
X  if (Alarm_On &&
X      strncmp(temp_time + 11, Alarm_Time, 5) == 0 &&
X      strncmp(Time_Suffix, Alarm_Time + 5, 2) == 0) {
X    putc(BELL, Fp); fflush(Fp);
X    sleep(1);
X    putc(BELL, Fp);
X    Alarm_On = FALSE;
X  }
X
X  alarm_string = Alarm_On ? ALARM_ON_STR : ALARM_OFF_STR;
X
X  time_width = Seconds_On ? 19 : 16;
X  sprintf(out_string, "%s%s%s%s %*.*s %s%s",
X                      Open_Window, news_string, alarm_string, mail_string,
X                      time_width, time_width,
X                      temp_time,
X                      Time_Suffix,
X                      Close_Window);
X  fputs(out_string, Fp);
X  fflush(Fp);
X
X}  /* do_display */
X
X
X/* fix_hour
X     Change 24-hour time to 12-hour time.
X     Return AM or PM.
X*/
static void fix_hour(hour)
int hour;
X{
X
X  if (Display_Type == AM_PM)
X    if (1 <= hour && hour <= 11)
X      Time_Suffix = "am ";
X    else if (13 <= hour && hour <= 23) {
X      Tp->tm_hour -= 12;
X      Time_Suffix = "pm ";
X      }
X    else if (hour == 0) {
X      Tp->tm_hour = 12;
X      Time_Suffix = "am ";
X      }
X    else if (hour == 12)
X      Time_Suffix = "pm ";
X    
X}  /* fix_hour */
X
X
X/* chimes
X     Rings the bell the correct number of times.
X*/
static void chimes(hour)
int hour;
X{
X  int i;
X
X  switch (Chime) {
X    case NO_CHIME :
X      break;
X    case SINGLE_CHIME :
X      putc(BELL, Fp);
X      fflush(Fp);
X      break;
X    case MULTIPLE_CHIMES :
X      for (i = 0; i < hour; i++) {
X        putc(BELL, Fp);
X        fflush(Fp);
X        sleep(1);
X      }
X      break;
X  }
X  
X}  /* chimes */
X
X
X/* die
X     Come here to die.
X*/
static int die(i)
int i;
X{
X
X  if (i == OUTEARLY) exit(QUIET);
X
X  if (i == BYEBYE || i == SIGTERM || i == SIGINT) {
X    fputs(Clear_Window, Fp);
X    fflush(Fp);
X  }
X  if (i == BYEBYE) exit(QUIET);
X  if (i == SIGTERM || i == SIGINT) exit(i);
X
X  exit(i); /* probably won't ever happen */
X
X}  /* die */
X
X
X/* usage
X     Call when the program is envoked with the wrong arguments.
X     Display a brief usage message and then die.
X*/
static void usage(pname)
char *pname;
X{
X  int i;
X  static char *msgs[] =
X  {
X#ifdef  unix
X    "usage:  %s  [options]  [TERM]  &\n",
X    "  where options is any combination of\n",
X    "    -aTIME -b  -bb  -i#  -m  -mb  -mboxPATH  -n  -s  -ss#  -u  -24  -v\n",
X    "  and where TERM is one of  att4425, tvi950, tvi955, wyse50, wyse60,\n",
X    "                            wyse75, wyse75-bottom, z19, z29, off\n"
X#endif
X#ifdef  vms
X    "\nusage:  %s  options  TERM\n",
X    "  where options is any combination of\n",
X    "    -aTIME -b  -bb  -i#  -s  -u  -24  -v\n",
X    "  and where TERM is one of  att4425, tvi950, tvi955, wyse50, wyse60,\n",
X    "                            wyse75, wyse75-bottom, z19, z29\n"
X#endif
X  };
X
X#ifdef  vms
X  pname = "clock";
X#endif
X
X  fprintf(stderr, msgs[0], pname);
X  for (i = 1; i < sizeof msgs / sizeof msgs[0]; i++)
X    fputs(msgs[i], stderr);
X
X  die(OUTEARLY);
X
X}  /* usage */
X
X/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
X
X#ifdef  unix
X/* find
X     Find starting index of the first string within the second.
X     Return -1 if not there.
X*/
static int find(t, s)
char *t, *s;
X{
X  int i, n;
X
X  n = strlen(t);
X  for (i = 0; s[i] != EOS; i++)
X    if (strncmp(s+i, t, n) == 0)
X      return i;
X  return -1;
X
X}  /* find */
X
X
X/* stop
X     Stop all your processes called "clock".
X*/
static void stop(pname)
char *pname;
X{
X  FILE *fin;
X  static char buf[BUFSIZ];
X  int pid;
X
X  if ((fin = popen("ps x", "r")) == NULL)
X    usage(pname);
X  fgets(buf, sizeof(buf), fin); /* skip over first line of ps output */
X  while (fgets(buf, sizeof(buf), fin) != NULL)
X    if (find(pname, buf) >= 0) {
X      buf[strlen(buf) - 1] = EOS;
X      sscanf(buf, "%d", &pid);
X      if (pid != getpid()) kill(pid,  SIGTERM);
X    }
X
X}  /* stop */
X
X
X/* has_news - checks news */
static bool has_news()
X{
X  FILE *news_fd;
X#define TEMP_STR 15
X  char temp[TEMP_STR + 1];
X  bool n_flag;
X
X  if (!Check_News) return FALSE;
X  if ((news_fd = popen("/usr/local/checknews", "r")) == NULL)
X    return FALSE;
X  n_flag = fgets(temp, TEMP_STR, news_fd) != NULL;
X  pclose(news_fd);
X  return n_flag;
X} /* has_news */
X
X
X/* has_mail
X     Return a value based on the status of the mail file.
X*/
static mail_type has_mail()
X{
X  static struct stat buf;
X
X  if (!Check_Mail) return NO_MAIL;
X  if (stat(Mailfile, &buf) == -1) return NO_MAIL;
X  if (buf.st_atime > buf.st_mtime) return OLD_MAIL;
X  return NEW_MAIL;
X      
X} /* has_mail */
X
X
X/* init_mailfile
X     Initialize Mailfile name.
X*/
static void init_mailfile(progname)
char *progname;
X{
X  char *p, *getlogin();
X  struct passwd *pw, *getpwuid();
X
X  if ((p = getlogin()) == NULL) {
X    pw = getpwuid(getuid());
X    if (pw == NULL ) {
X      fprintf(stderr, "%s: Can't check mail!\n", progname);
X      Mailfile[0] = EOS;
X      Check_Mail = FALSE;
X      return;
X    }
X    p = (*pw).pw_name;
X  }
X
X  /* Mailfile may have been set in get_args. */
X  if (Mailfile[0] == EOS) {
X    strcpy(Mailfile, MAILDIR);
X    strcat(Mailfile, p);
X  }
X
X} /*init_mailfile */
X
X
X/* find_idle
X     Return the number of minutes the current tty has been idle.
X*/
static long find_idle(tty)
char *tty;
X{
X  struct stat ttystatus;
X  long current_time;
X
X  if (stat(tty, &ttystatus) < 0) {
X    fprintf(stderr, "finger: Can't stat %s\n", tty);
X    exit(1);
X  }
X  time(&current_time);
X  return current_time < ttystatus.st_atime
X           ? 0L : (current_time - ttystatus.st_atime) / 60;
X                  /* change from seconds to minutes */
X
X}  /* find_idle */
X
X/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
X/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
X
extern char *getenv(), *tgetstr(), *tgoto();
static char *tget();
X
char clear_wn[80]; /* Clears the status line. */
X
X/* Buffer of original string from termcap gotten by using tgetent(). */
char TC_Buf[1024];
X/* Buffer of decoded strings gotten by using tgetstr(). */
char Decoded_Buf[200];
X
X
X/* term_cap
X     Attempt to read and decode the "hs", "ts", "fs", and "ds"
X     capabilities from the termcap data base.
X*/
static bool term_cap()
X{
X  char *cur_bp = Decoded_Buf;
X  char *tc_name;
X  char *P_CM;
X
X  /* Makes sure we have a valid termcap  */
X  switch (tgetent(TC_Buf, tc_name = getenv("TERM")) ) {
X    case -1:
X      fprintf(stderr, "Termcap file not accessible.\n");
X      die(OUTEARLY);
X    case 0:
X      fprintf(stderr, "Termcap entry not available for %s.\n", tc_name);
X      die(OUTEARLY);
X  }
X
X  P_CL = tgetstr("cl", &cur_bp);
X  if (P_CL == NULL)
X    Screen_Save_Interval = 0; /* can't clear the screen */
X
X  if (tgetflag("hs") == 0)
X    return FALSE;
X
X  P_CM = tgetstr("ts", &cur_bp);
X  if (P_CM == NULL)
X    return FALSE;
X  /* The "ts" capability can be specified with a parameter and so
X     we use tgoto put the number in correctly. */
X  Open_Window = tgoto(P_CM, 0, 0);
X
X  if (Open_Window == NULL || Open_Window[0] == EOS)
X    return FALSE;
X
X  Close_Window = tgetstr("fs", &cur_bp);
X  if (Close_Window == NULL)
X    return FALSE;
X
X  Clear_Window = tgetstr("ds", &cur_bp);
X  if (Clear_Window == NULL) {
X    strcpy(clear_wn, Open_Window);
X    strcat(clear_wn, Close_Window);
X    Clear_Window = clear_wn;
X  }
X
X  return TRUE;
X
X}  /* term_cap */
X
X
static int putone(ch)
char ch;
X{
X  (void) fwrite(&ch, sizeof(char), 1, stdout);
X}  /* putone */
X
X
X/* Print an error message, make certain the keyboard is in cooked
X   mode, and exit.
X*/
X
X/* clrscr
X*/
static void clrscr()
X{
X  static int count = 0;
X  int i;
X
X  tputs(P_CL, 1, putone);
X  for (i = 0; i < count; i++)
X    fputc(' ', stdout);
X  fputs("Press <RETURN>\n", stdout);
X  count = count < 60 ? count + 1 : 0;
X}  /* clrscr */
X
X#endif
X
X/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
X/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
END_OF_FILE
if test 24384 -ne `wc -c <'clock.c'`; then
    echo shar: \"'clock.c'\" unpacked with wrong size!
fi
# end of 'clock.c'
fi
echo shar: End of shell archive.
exit 0
-- 
Robert J. Drabek                            robert@cs.Arizona.EDU
Department of Computer Science              uunet!arizona!robert
The University of Arizona                   602 621 4326
Tucson, AZ  85721


