[comp.windows.news] faces - part 2 - REPOST.

richb@sunchat.UUCP (Rich Burridge) (12/14/88)

I've had several requests for a report of part 2 of faces, the visual
(mail/printer) monitor. So here it is.

    Rich.

------CUT HERE------CUT HERE------
#! /bin/sh
# this is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh to create the files:
#	get.c
#	main.c
#	mon.c
#	news.c
#	rec.c
#	sunview.c
# This archive created: Wed Dec 14 07:48:34 EST 1988
#
#
export PATH; PATH=/bin:$PATH
#
if [ -f get.c ]
then
echo shar: will not over-write existing file get.c
else
echo shar: extracting 'get.c',    10551 characters
cat > get.c <<'Funky_Stuff'
/*LINTLIBRARY*/
#ifndef lint
static char sccsid[] = "@(#)get.c 1.2 88/12/09" ;
#endif
	
/*  Extraction routines used by faces.
 *
 *  Copyright (c) Rich Burridge - Sun Microsystems Australia.
 *                                All rights reserved.
 *
 *  Permission is given to distribute these sources, as long as the
 *  copyright messages are not removed, and no monies are exchanged. 
 *
 *  No responsibility is taken for any errors on inaccuracies inherent
 *  either to the comments or the code of this program, but if reported
 *  to me, then an attempt will be made to fix them.
 */

#include "faces.h"
#include "extern.h"
#include "patchlevel.h"


get_blit_ikon(name, buf)      /* Load blit ikon file. */
char *name ;
unsigned short buf[256] ;
{
  FILE *fin ;
  char *ptr ;
  int i, j, temp ;

  if ((fin = fopen(name, "r")) == NULL) return(-1) ;
  for (i = 0; i < BLITHEIGHT; i++)
    {
      FGETS(nextline, MAXLINE, fin) ;
      ptr = nextline ;
      for (j = 0; j < 3; j++)
        {
          while (*ptr == ' ' || *ptr == '\t') ptr++ ;
          SSCANF(ptr,"0x%X",&temp) ;
          buf[i*4+j] = (short) temp ;
          ptr = index(ptr,',') ;
          ptr++ ;         
        }                 
      buf[i*4+3] = 0 ;    
    }
  for (i = BLITHEIGHT; i < ICONHEIGHT; i++)
    for (j = 0; j < 4; j++) buf[i*4+j] = 0 ;
  FCLOSE(fin) ;
  return(0) ;
}


char *
get_field(ftype,line)      /* Get field option from given line. */
enum field_type ftype ;
char *line ;
{
  char *ptr1, *ptr2 ;
  char str1[5],str2[MAXLINE],str3[4],str4[4],str5[3],str6[9],str7[5] ;

  SSCANF(line,"%s %s %s %s %s %s %s",
               str1,str2,str3,str4,str5,str6,str7) ;
  switch ((int) ftype)
    {
      case HOSTNAME  : if ((ptr2 = rindex(str2,'!')) != NULL)
                         {
                           ptr1 = str2 ;
                           *ptr2 = '\0' ;
                           while (ptr2 != ptr1)
                             {
                               *ptr2-- ;
                               if (*ptr2 == '!') return(ptr2+1) ;
                             }
                           return(ptr2) ;
                         }
                       else if ((ptr2 = index(str2,'@')) != NULL)
                         return(ptr2+1) ;
                       else return(NULL) ;
 
      case TIMESTAMP : str6[5] = '\0' ;
                       return(str6) ;
 
      case USERNAME  : if ((ptr2 = rindex(str2,'!')) != NULL)
                         return(ptr2+1) ;
                       else if ((ptr2 = index(str2,'@')) != NULL)
                         {
                           ptr1 = str2 ;
                           *ptr2 = '\0' ;
                           while (ptr2 != ptr1)
                             {
                               *ptr2-- ;
                               if (*ptr2 == '@') return(ptr2+1) ;
                             }
                           return(ptr2) ;
                         }
                       else return(str2) ;
    }
/*NOTREACHED*/
}


get_icon(dirname, buf)            /* Read in ikon or .icon file. */
char *dirname ;
unsigned short buf[256] ;
{

/*  Attempts to open the correct face file.
 *  If the face file is face.ps, then another record is added to the list
 *  of NeWS .ps files to animate at a later time.
 *  If this is 48x48x1 or sun.icon, and the open is successful, then the
 *  face image is read into buf.
 *  -1 is returned on failure.
 */

  char *ptr ;

  ptr = rindex(dirname,'/') ;     /* Find last slash in iconname. */
  if (EQUAL(ptr+1,"face.ps"))
    if (get_news_icon(dirname) == 0) return NEWSTYPE ;
  if (EQUAL(ptr+1,"sun.icon"))
    if (get_sun_icon(dirname, buf) == 0) return SUNTYPE ;
  if (EQUAL(ptr+1,"48x48x1"))
    if (get_blit_ikon(dirname, buf) == 0) return BLITTYPE ;
  return -1 ;
}


get_news_icon(name)    /* Create record for news.ps file. */
char *name ;
{
  FILE *fin ;

  if (gtype != NEWS) return -1 ;
  if ((fin = fopen(name, "r")) == NULL) return -1 ;
  FCLOSE(fin) ;
  add_ps_rec(row, column, name) ;
  return 0 ;
}


get_options(argc,argv)    /* Read and process command line options. */
int argc ;
char *argv[] ;
{
  char next[MAXLINE] ;    /* The next command line parameter. */

  INC ;
  while (argc > 0)
    {
      if (argv[0][0] == '-')
        switch (argv[0][1])
          {
            case 'P' : mtype = MONPRINTER ;  /* Monitor printer queue. */
                       INC ;
                       getparam(printer, argv, "-P needs printer name") ;
                       break ;
            case 'a' : mtype = MONALL ;      /* Monitor all of the spoolfile. */
                       break ;
            case 'b' : INC ;                 /* Alternate background pattern. */
                       getparam(bgicon, argv, "-b needs background icon") ;
                       break ;
            case 'f' : INC ;                 /* New directory for face icons. */
                       getparam(facedir, argv, "-f needs face directory") ;
                       SPRINTF(machfile, "%s/machine.tab", facedir) ;
                       SPRINTF(peopfile, "%s/people.tab", facedir) ;
                       break ;
            case 'i' : invert = 1 ;          /* Reverse video. */
                       break ;
            case 'n' : dontshowno = 1 ;      /* Don't show number of messages. */
                       break ;
            case 'p' : INC ;                 /* No. of seconds between checks. */
                       getparam(next, argv, "-p needs period time") ;
                       period = atoi(next) ; /* No. of seconds between checks. */
                       break ;
            case 's' : INC ;                 /* Alternative spoolfile. */
                       getparam(spoolfile, argv, "-s needs spool directory") ;
                       break ;
            case 't' : dontshowtime = 1 ;    /* Do not show timestamps. */
                       break ;
            case 'u' : dontshowuser = 1 ;    /* Do not show usernames. */
                       break ;
            case 'v' : FPRINTF(stderr, "%s version 1.3.%1d\n", progname, PATCHLEVEL) ;
                       exit(1) ;

/*  SunView windowing arguments. -Wp, -WP and -Wi are used in the NeWS
 *  implementation to initially position the window and icon.
 */

            case 'W' : switch (argv[0][2])
                         {
                           case 'H' : break ;   /* -WH, no sub-args follow */
                           case 'i' : iconic = 1 ;
                                      break ;   /* -Wi, start as an icon. */
                           case 'g' :           /* -Wg, set default color. */
                           case 'n' : break ;   /* -Wn, no label at all */
                           case 'h' :           /* -Wh, height */
                           case 'I' :           /* -WI "icon filename" */
                           case 'l' :           /* -Wl "some window label" */
                           case 'L' :           /* -Wl "some icon label" */
                           case 't' :           /* Font filename */
                           case 'T' :           /* Icon font filename */
                           case 'w' : INC ;     /* Width, in columns. */
                                      break ;
                           case 'p' : INC ;     /* -Wp xnum ynum */
                                      getparam(next, argv,
                                               "-Wp needs x coordinate") ;
                                      wx = atoi(next) ;
                                      INC ;
                                      getparam(next, argv,
                                               "-Wp needs y coordinate") ;
                                      wy = atoi(next) ;
                                      break ;
                           case 'P' : INC ;      /* -WP xnum ynum */
                                      getparam(next, argv,
                                               "-WP needs x coordinate") ;
                                      ix = atoi(next) ;
                                      INC ;
                                      getparam(next, argv,
                                               "-WP needs y coordinate") ;
                                      iy = atoi(next) ;
                                      break ;
                           case 's' : INC ; INC ;  /* -Ws xnum ynum */
                                      break ;
                           case 'b' :              /* -Wb r g b (bg color spec) */
                           case 'f' : INC ; INC ; INC ;  /* Same, fg color */
                                      break ;
                           default :  FPRINTF(stderr,"%s: -W%c unknown argument\n",
                                                      progname, argv[0][2]) ;
                                      break ;
                         }
                       break ;
            default  : FPRINTF(stderr, "Usage: %s [-P printer] ", progname) ;
                       FPRINTF(stderr, "[-Wi] [-Wp x y] [-WP x y] ") ;
                       FPRINTF(stderr, "[-b background] [-f facedir] [-i] [-n] ") ;
                       FPRINTF(stderr, "[-p period] [-s spoolfile] [-u] [-t] [-v]\n") ;
                       exit(1) ;
          }
      INC ;
    }
}


char *
getname()       /* Get users name from passwd entry. */
{
  char *getlogin(), *username ;
  struct passwd *getpwuid(), *pwent ;

  if (!(username = getlogin()))
    {
      pwent = getpwuid(getuid()) ;
      username = pwent->pw_name ;
      endpwent() ;                   /* Close the passwd file */
    }
  return username ;
}


getparam(s, argv, errmes)
char *s, *argv[], *errmes ;
{
  if (*argv != NULL && argv[0][0] != '-') STRCPY(s, *argv) ;
  else
    {
      FPRINTF(stderr,"%s: %s as next argument.\n", progname, errmes) ;
      exit(1) ;
    }
}


get_sun_icon(name, buf)     /* Load Sun icon file. */
char *name ;
unsigned short buf[256] ;
{
  FILE *fin ;
  char *ptr ;
  int i, j, temp ;

  if ((fin = fopen(name, "r")) == NULL) return -1 ;
  FGETS(nextline, MAXLINE, fin) ;        /* Load Sun icon file. */
  FGETS(nextline, MAXLINE, fin) ;
  for (i = 0; i < 32; i++)
    {
      FGETS(nextline, MAXLINE, fin) ;
      ptr = nextline ;
      for (j = 0; j < 8; j++)
        {
          while (*ptr == ' ' || *ptr == '\t') ptr++ ;
          SSCANF(ptr,"0x%X",&temp) ;
          buf[i*8+j] = (short) temp ;
          ptr = index(ptr, ',') ;
          ptr++ ;
        }
    }    
  FCLOSE(fin) ;
  return(0) ;
}
Funky_Stuff
len=`wc -c < get.c`
if [ $len !=    10551 ] ; then
echo error: get.c was $len bytes long, should have been    10551
fi
fi # end of overwriting check
if [ -f main.c ]
then
echo shar: will not over-write existing file main.c
else
echo shar: extracting 'main.c',    10551 characters
cat > main.c <<'Funky_Stuff'
#ifndef lint
static char sccsid[] = "@(#)main.c 1.2 88/12/11" ;
#endif

/*  Icon face server for monitoring mail and print jobs.
 *  This program is based on the AT&T v8 mail face server,
 *  vismon, but is not derived from vismon source.
 * 
 *  Copyright (c) Rich Burridge - Sun Microsystems Australia.
 *                                All rights reserved.
 *
 *  Permission is given to distribute these sources, as long as the
 *  copyright messages are not removed, and no monies are exchanged. 
 * 
 *  No responsibility is taken for any errors on inaccuracies inherent
 *  either to the comments or the code of this program, but if reported
 *  to me, then an attempt will be made to fix them.
 */

#include "faces.h"

char *get_field(), *getname() ;
int do_check() ;
struct recinfo *rec_exists() ;

struct comminfo *communities = NULL ;  /* Community alias/username chain. */
struct comminfo *clast = NULL ;     /* End of chain of community records. */
struct machinfo *machines = NULL ;  /* Known machine/communities. */
struct machinfo *mlast = NULL ;     /* End of chain of machine records. */
struct psinfo *psrecs = NULL ;      /* List of news.ps animation files. */
struct psinfo *plast = NULL ;       /* End of chain of NeWS animation files. */
struct recinfo *recs = NULL ;       /* Mail messages being monitored. */
struct recinfo *last = NULL ;       /* End of the chain of mail records. */
struct stat buf ;                   /* Buffer for file existence stat call. */
long lastsize ;                     /* Last known size of the mail folder. */

enum gr_type gtype ;     /* Indicates what graphics system is being used. */
enum mon_type mtype ;    /* Type of monitoring operation to do. */

char bgicon[MAXLINE] ;           /* Alternate background pattern. */
char community[MAXLINE] ;        /* Community name ("real" host name). */
char facedir[MAXLINE] ;          /* Directory containing face images. */
char fname[MAXTYPES][MAXLINE] ;  /* Array of various face name types. */
char iconname[MAXLINE] ;    /* Name of the icon file for this person. */
char machfile[MAXLINE] ;    /* Name of the machine/community file. */
char nextline[MAXLINE] ;    /* Next line from users mail spool file. */
char peopfile[MAXLINE] ;    /* Name of the people/username file. */
char printer[MAXLINE] ;     /* Printer name to monitor. */
char progname[MAXLINE] ;    /* Name of this program. */
char spoolfile[MAXLINE] ;   /* Full pathname of users current mail. */
char *username ;            /* This users name. */

int beeps ;         /* Number of beeps for arrival of new mail. */
int column ;        /* Column number for next icon. */
int dontshowno ;    /* Indicates if number of messages should be displayed. */
int dontshowtime ;  /* Indicates if timestamp for new mail should be shown. */
int dontshowuser ;  /* Indicates if username for new mail should be shown. */
int facetype ;      /* Type of face file found. */
int firsttime ;     /* Zeroised after first mail/printer check. */
int flashes ;       /* Number of flashes for arrival of new mail. */
int height ;        /* Height in pixels of faces display. */
int iconic ;        /* Start as an icon if set. */
int invert ;        /* Set if to use reverse video. */
int ix ;            /* Initial X position of the icon. */
int iy ;            /* Initial Y position of the icon. */
int newmail ;       /* Set if there is new mail this time around. */
int noicons ;       /* Number of faces this time around. */
int period ;        /* Period in seconds for new mail check. */
int row ;           /* Row number for next icon. */
int width ;         /* Width in pixels of faces display. */
int wx ;            /* Initial X position of the window. */
int wy ;            /* Initial Y position of the window. */


main(argc,argv)
int argc ;
char *argv[] ;
{
  STRCPY(progname,argv[0]) ;    /* Save this programs name. */
  initialise() ;                /* Set default values for various options. */
  get_options(argc,argv) ;      /* Read and process command line options. */
  read_mailrc() ;               /* Get number of flashes and beeps. */
  read_machines() ;             /* Setup up the machine/community chain. */
  read_aliases() ;              /* Setup the hostname alias subchains. */
  if (init_ws_type())           /* Determine window system type. */
    {
      FPRINTF(stderr,"Error initialising window system.\n") ;
      exit(1) ;
    }
  make_icon() ;                 /* Create default faces icon. */
  make_frame(argc,argv) ;       /* Create faces window/icon. */
  do_check() ;                  /* Generate initial faces display. */
  start_tool() ;                /* Start up and display the faces icon. */
}


a_to_u(community, user, realname)    /* Turn possible alias into username. */
char *community, *user, *realname ;
{
  struct comminfo *ctemp ;
  struct peopinfo *ptemp ;

  STRCPY(realname, user) ;      /* In case alias not found. */
  ctemp = communities ;         /* Point to chain of communities. */
  while (ctemp != NULL)
    if (EQUAL(ctemp->community, community))
      {
        ptemp = ctemp->people ;
        while (ptemp != NULL)
          if (EQUAL(ptemp->alias, user))
            {
              STRCPY(realname, ptemp->username) ;
              return ;
            }
          else ptemp = ptemp->next ;
        return ;
      }
    else ctemp = ctemp->next ;
}


initialise()
{
  lastsize = 0 ;              /* Initial size of spoolfile. */
  firsttime = 1 ;             /* No checks made yet. */
  iconic = 0 ;                /* Initially an open window. */
  STRCPY(fname[BLITTYPE], "48x48x1") ;
  STRCPY(fname[SUNTYPE], "sun.icon") ;
  STRCPY(fname[NEWSTYPE], "face.ps") ;
  wx = wy = ix = iy = 0 ;

#ifdef FBMONTYPE
  mtype = FBMONTYPE ;         /* Type of monitoring to do. */
#else
  mtype = MONNEW ;            /* Just monitor new mail by default. */
#endif FBMONTYPE

#ifdef BACKGROUND
  STRCPY(bgicon, BACKGROUND) ;          /* Alternate background pattern. */
#else
  STRCPY(bgicon, "") ;                  /* Default is to use root gray. */
#endif BACKGROUND

#ifdef FACEDIR
  STRCPY(facedir,FACEDIR) ;  /* Different directory for face icons. */
#else
  STRCPY(facedir,"/usr/local/faces") ;  /* Directory for face icons. */
#endif FACEDIR

  SPRINTF(machfile, "%s/machine.tab", facedir) ;
  SPRINTF(peopfile, "%s/people.tab", facedir) ;

#ifdef INVERT
  invert = INVERT ;          /* Set indicates reverse video. */
#else
  invert = 0 ;               /* Default is normal video. */
#endif INVERT

#ifdef PERIOD
  period = PERIOD ;          /* Period for new mail/print check. */
#else
  period = 60 ;              /* Default time in seconds for new check. */
#endif PERIOD

#ifdef DONTSHOWNO
  dontshowno = DONTSHOWNO ;  /* If nonzero, do not show number of messages. */
#else
  dontshowno = 0 ;           /* Show number of messages for this face. */
#endif DONTSHOWNO

#ifdef SPOOLFILE
  STRCPY(spoolfile,SPOOLFILE) ;   /* Alternative spoolfile to monitor. */
#else
  username = getname() ;     /* Get users name from passwd entry. */
  SPRINTF(spoolfile,"/usr/spool/mail/%s",username) ;
#endif SPOOLFILE

#ifdef DONTSHOWTIME
  dontshowtime = DONTSHOWTIME ;    /* If nonzero, do not show timestamp. */
#else
  dontshowtime = 0 ;         /* Show time stamp for new mail for this face. */
#endif DONTSHOWTIME

#ifdef DONTSHOWUSER
  dontshowuser = DONTSHOWUSER ;    /* If nonzero, do not show username. */
#else
  dontshowuser = 0 ;         /* Show username on the face icons. */
#endif DONTSHOWUSER
}


h_to_c(host, community)        /* Turn hostname into community name. */
char *host, *community ;
{
  struct machinfo *temp ;      /* Pointer to next machine record. */
 
  temp = machines ;            /* Point to list of machine/communitys. */
  if (host[0] == '\0') GETHOSTNAME(community, MAXLINE) ;
  else STRCPY(community, host) ;   /* Copied in case machine name not found. */
  while (temp != NULL)
    {
      if (EQUAL(temp->machine, community))
        {
          STRCPY(community, temp->community) ;
          return ;
        }
      temp = temp->next ;      /* Point to next record. */
    }
}


make_iconname(community, user)    /* Construct the icon name. */
char *community, *user ;
{

/*  Sets up community and user based on the first successful
 *  open from the following list of files:
 *
 *  $(FACEDIR)/community/user/[face.ps, sun.icon, 48x48x1]
 *  $(FACEDIR)/misc./user/[face.ps, sun.icon, 48x48x1]
 *  $(FACEDIR)/community/unknown/[face.ps, sun.icon, 48x48x1]
 *  $(FACEDIR)/misc./unknown/[face.ps, sun.icon, 48x48x1]
 *
 *  If none of these are found, the "blank face" is returned.
 */

  int i ;

  for (i = 0; i < MAXTYPES; i++)
    {
      SPRINTF(iconname, "%s/%s/%s/%s", facedir, community, user, fname[i]) ;
      if (stat(iconname, &buf) != -1) return ;
    }
 
  for (i = 0; i < MAXTYPES; i++)
    {
      SPRINTF(iconname, "%s/misc./%s/%s", facedir, user, fname[i]) ;
      if (stat(iconname, &buf) != -1)
        {
          STRCPY(community, "misc.") ;
          return ;
        }
    }
 
  for (i = 0; i < MAXTYPES; i++)
    {
      SPRINTF(iconname, "%s/%s/unknown/%s", facedir, community, fname[i]) ;
      if (stat(iconname, &buf) != -1)
        {
          STRCPY(user, "unknown") ;
          return ;
        }
    }

  for (i = 0; i < MAXTYPES; i++)
    {
      SPRINTF(iconname, "%s/misc./unknown/%s", facedir, fname[i]) ;
      if (stat(iconname, &buf) != -1)
        {
          STRCPY(community, "misc.") ;
          STRCPY(user, "unknown") ;
          return ;
        }
    }

/* The "blank face" should be used, so community and user are nulled. */

  community[0] = user[0] = '\0' ;
}


read_mailrc()                /* Get number of flashes and beeps. */
{
  char mrcname[MAXLINE] ;    /* Full pathname of the .mailrc file. */
  char *ptr ;
  FILE *fd ;

  beeps = 0 ;     /* Defaults if .mailrc file not found. */
  flashes = 0 ;
  if (getenv("HOME"))
    {
      SPRINTF(mrcname, "%s/.mailrc", getenv("HOME")) ;
      if ((fd = fopen(mrcname, "r")) == NULL) return ;
      while (fgets(nextline, MAXLINE, fd) != NULL)
        if (EQUAL(nextline, "set"))
          {
            ptr = index(nextline, ' ') ;
            if (EQUAL(ptr+1, "flash"))
              {
                ptr = index(nextline, '=') ;
                SSCANF(ptr+1, "%d", &flashes) ;
              }
            else if (EQUAL(ptr+1, "bell"))
              {
                ptr = index(nextline, '=') ;
                SSCANF(ptr+1, "%d", &beeps) ;
              }
          }
    }
  FCLOSE(fd) ;
}
Funky_Stuff
len=`wc -c < main.c`
if [ $len !=    10551 ] ; then
echo error: main.c was $len bytes long, should have been    10551
fi
fi # end of overwriting check
if [ -f mon.c ]
then
echo shar: will not over-write existing file mon.c
else
echo shar: extracting 'mon.c',     8937 characters
cat > mon.c <<'Funky_Stuff'
/*LINTLIBRARY*/
#ifndef lint
static char sccsid[] = "@(#)mon.c 1.4 88/12/11" ;
#endif

/*  Monitoring routines used by the faces program.
 * 
 *  Copyright (c) Rich Burridge - Sun Microsystems Australia.
 *                                All rights reserved.
 *
 *  Permission is given to distribute these sources, as long as the
 *  copyright messages are not removed, and no monies are exchanged. 
 * 
 *  No responsibility is taken for any errors on inaccuracies inherent
 *  either to the comments or the code of this program, but if reported
 *  to me, then an attempt will be made to fix them.
 */

#include "faces.h"
#include "extern.h"

adjust()          /* Adjust the row and column position. */
{
  struct psinfo *this ;

  if (mtype != MONNEW)
    {
      if (++column == NO_PER_ROW)
        {
          column = 0 ;
          row++ ;
        }
      return ;
    }
  if (psrecs != NULL)           /* Adjust animation positions for MONNEW */
    {
      this = psrecs ;           /* Point to beginning of chain. */
      while (this != NULL)
        {
          this->column++ ;      /* Adjust column position. */
          if (facetype == NEWSTYPE && this->next == NULL)
            this->column-- ;    /* Reset for brand new animate record. */
          this = this->next ;
        }
    }
}


do_check()        /* Perform another check of the appropriate type. */
{
  switch ((int) mtype)
    {
      case MONALL     : do_mail(MONALL) ;  /* Monitor all of the mail file. */
                        break ;
      case MONNEW     : do_mail(MONNEW) ;  /* Monitor new mail only. */
                        break ;
      case MONPRINTER : do_printer() ;     /* Monitor the print queue. */
                        break ;
    }
  firsttime = 0 ;
}


do_mail(mtype)              /* Monitor a mail file for new or all mail. */
enum mon_type mtype ;
{        
  char host[MAXLINE] ;      /* Pointer to host name from the "From" line. */
  char *ptr ;               /* Pointer to extract field. */
  char realname[MAXLINE] ;  /* Real username for this user. */
  char ts[MAXLINE] ;        /* Pointer to time stamp from the "From" line. */
  char user[MAXLINE] ;      /* Pointer to user name from the "From" line. */
  FILE *fp ;                /* File descriptor for users mail spool file. */
  struct recinfo *crec ;    /* Pointer to current mail record for updating. */

  column = row = 0 ;        /* Start in top left corner of pixrect. */
  newmail = 0 ;             /* Assume no new mail. */
  noicons = 0 ;

  if (mtype == MONNEW) make_pixrect(NO_PER_ROW) ;
  if (stat(spoolfile,&buf) == -1)
    {
      lastsize = 0 ;
      if (mtype == MONNEW) show_display() ;   /* Show new mail. */
      else make_display() ;     /* Output icons and tidyup chain of records. */
      return ;
    }
  if (buf.st_size > lastsize) newmail = 1 ;   /* New mail found. */
  if (mtype == MONNEW)
    if (buf.st_size <= lastsize)   /* Is the size of mail folder bigger? */
      {
        lastsize = buf.st_size ;   /* No: save new size and exit. */
        show_display() ;
        return ;
      }

  if ((fp = fopen(spoolfile,"r")) == NULL)     /* Open spoolfile. */
    {
      if (mtype == MONNEW) show_display() ;   /* Show new mail. */
      else make_display() ;     /* Output icons and tidyup chain of records. */
      return ;
    }
  if (mtype == MONNEW) FSEEK(fp, lastsize, 0) ;
  lastsize = buf.st_size ;
  while (fgets(nextline,MAXLINE,fp) != NULL)
    if (EQUAL(nextline,"From "))
      {
        host[0] = user[0] = ts[0] = '\0' ;

        if ((ptr = get_field(HOSTNAME,nextline)) != NULL)
          STRCPY(host, ptr) ;
        if ((ptr = get_field(USERNAME,nextline)) != NULL)
          STRCPY(user, ptr) ;
        if ((ptr = get_field(TIMESTAMP,nextline)) != NULL)
          STRCPY(ts, ptr) ;

        h_to_c(host, community) ;    /* Turn hostname into community name. */
        a_to_u(community, user, realname) ;
        make_iconname(community, realname) ;
        if (mtype == MONNEW)
          {
            add_face(BOTH, ORDINARY, iconname) ;
            if (!dontshowtime) text(ICON, LEFT, ts) ;
            if (!dontshowuser) text(WINDOW, LEFT, realname) ;
            adjust() ;
          }
        else
          {
            if ((crec = rec_exists(community, realname)) != NULL)
              {
                STRCPY(crec->ts, ts) ;
                if (!crec->total) noicons++ ;
                crec->total++ ;
              }
            else add_record(community, realname, ts, 0) ;
          }
      }
  FCLOSE(fp) ;
  if (mtype == MONNEW) show_display() ;   /* Show new mail. */
  else make_display() ;     /* Output icons and tidyup chain of records. */
}


do_printer()                 /* Monitor printer queue. */
{
  struct recinfo *this, *next ;
  FILE *fp ;                 /* File descriptor for users mail spool file. */
  char command[MAXLINE] ;    /* Lpq system call for this printer. */
  char owner[MAXLINE] ;      /* Owner of job in the print queue. */
  char tempname[MAXLINE] ;   /* Temporary unique filename. */
  int size ;                 /* Size of this print job in bytes. */

  noicons = 0 ;
  SPRINTF(tempname,"/tmp/faces%04d",getpid()) ;
  SPRINTF(command,"lpq -P %s > %s",printer,tempname) ;
  if (system(command))
    {
      FPRINTF(stderr,"%s: system call for printer %s stats failed.\n",
              progname,printer) ;
      return ;
    }
  if ((fp = fopen(tempname,"r")) == NULL)     /* Open spoolfile. */
    {
      FPRINTF(stderr,"%s: couldn't open printer stats in %s.\n",
              progname,tempname) ;
      return ;
    }
  column = row = 0 ;          /* Start in top left corner of pixrect. */
  FGETS(nextline,MAXLINE,fp) ;
  if (EQUAL(nextline,"no entries"))
    {
      make_pixrect(1) ;               /* Just the "no print" icon. */
      add_face(BOTH, NOPRINT, "") ;   /* Set to "no print" icon. */
    }
  else if (EQUAL(nextline,"Printer Error: may need attention!"))
    {
      make_pixrect(1) ;               /* Just the "no paper" icon. */
      add_face(BOTH, NOPAPER, "") ;   /* Set to "no paper" icon. */
      text(BOTH, LEFT, printer) ;     /* Output printer name. */
    }
  else
    {
      FGETS(nextline,MAXLINE,fp) ;    /* Skip the next line. */
      while (fgets(nextline,MAXLINE,fp) != NULL)
        {
          SSCANF(&nextline[7], "%s", owner) ;
          SSCANF(&nextline[60], "%d", &size) ;
          h_to_c("", community) ;
          make_iconname(community, owner) ;
          add_record("",owner,"",size) ;
        }
      make_pixrect(noicons) ;
      this = recs ;
      while (this != NULL)
        {
          next = this->next ;
          add_face(WINDOW, ORDINARY, this->iconname) ;
          SPRINTF(nextline, "%1d", this->size) ;
          if (!dontshowuser)
            text(WINDOW, LEFT, this->username) ;  /* Owner. */
          text(WINDOW, RIGHT, nextline) ;         /* Size. */
          if (this == recs)
            {
              add_face(ICON, ORDINARY, this->iconname) ;
              SPRINTF(nextline, "%1d %s", noicons, (noicons == 1 ? "job" : "jobs")) ;
              text(ICON, RIGHT, nextline) ;   /* Number of jobs. */
            }
          adjust() ;    /* Adjust column and row. */
          remove_record(this) ;
          this = next ;
        }
      recs = last = NULL ;
    }
  FCLOSE(fp) ;
  UNLINK(tempname) ;
  show_display() ;
}


make_pixrect(count)   /* Make window pixrect the correct size. */
int count ;
{
  int c, r ;          /* Size in columns and rows of window display. */

  r = ((count-1) / NO_PER_ROW) + 1 ;   /* Number of rows of faces. */
  c = NO_PER_ROW ;                     /* Full width display. */
  if (count <= 10)
    {
      r = 1 ;         /* One row. */
      c = count ;     /* Of 'count' columns. */
    }

  height = r * ICONHEIGHT ;    /* Height of the icon display. */
  width = c * ICONWIDTH ;      /* Width of the icon display. */
  create_pixrects(width, height) ;
}


make_display()              /* Output icons and tidyup chain of records. */
{
  int count ;               /* Name of faces in icon display. */
  struct recinfo *this, *next ;

  count = noicons ;         /* Number of faces to display. */
  if (!count) count = 1 ;   /* Always one "no mail" icon. */
  make_pixrect(count) ;

  if (!noicons) add_face(BOTH, NOMAIL, "") ;
  else
    {
      this = recs ;
      while (this != NULL)
        {
          next = this->next ;
          add_face(BOTH, ORDINARY, this->iconname) ;
          if (!dontshowno)
            {
              SPRINTF(nextline, "%1d", this->total) ;
              text(ICON, RIGHT, nextline) ;
            }
          if (!dontshowtime) text(ICON, LEFT, this->ts) ;
          if (!dontshowuser) text(WINDOW, LEFT, this->username) ;
          adjust() ;
          remove_record(this) ;
          this = next ;
        }
      recs = last = NULL ;
    }
  show_display() ;         /* Display the latest set of faces. */
}
Funky_Stuff
len=`wc -c < mon.c`
if [ $len !=     8937 ] ; then
echo error: mon.c was $len bytes long, should have been     8937
fi
fi # end of overwriting check
if [ -f news.c ]
then
echo shar: will not over-write existing file news.c
else
echo shar: extracting 'news.c',    10648 characters
cat > news.c <<'Funky_Stuff'
/*LINTLIBRARY*/
#ifndef lint
static char sccsid[] = "@(#)news.c 1.3 88/12/11" ;
#endif

/*  NeWS dependent graphics routines used by faces,
 *  the visual mail and print job monitor.
 * 
 *  Copyright (c) Rich Burridge - Sun Microsystems Australia.
 *                                All rights reserved.
 *
 *  Permission is given to distribute these sources, as long as the
 *  copyright messages are not removed, and no monies are exchanged. 
 * 
 *  No responsibility is taken for any errors on inaccuracies inherent
 *  either to the comments or the code of this program, but if reported
 *  to me, then an attempt will be made to fix them.
 */

#include "faces.h"
#include "extern.h"
#include <sundev/kbd.h>
#include <sundev/kbio.h>

#ifdef SUNOS3.x
int fullmask ;               /* Full mask of file descriptors to check on. */
int readmask ;               /* Readmask used in select call. */
#else
fd_set fullmask ;            /* Full mask of file descriptors to check on. */
fd_set readmask ;            /* Readmask used in select call. */
#endif SUNOS3.x

int kbdfd ;                  /* File descriptor for the keyboard. */
int psfd ;                   /* NeWS connection file descriptor. */
unsigned short ibuf[256] ;   /* Ikon/icon image buffer. */

extern FILE *PostScript ;
extern FILE *PostScriptInput ;


add_face(display, itype, name)     /* Add this icon to the display. */
enum disp_type display ;
enum icon_type itype ;
char *name ;
{
  char face[MAXLINE] ;        /* Canvas containing face (Source). */

  switch ((int) itype)
    {
      case NOMAIL   : STRCPY(face, "NomailIcon") ;
                      break ;
      case NOPAPER  : STRCPY(face, "NopaperIcon") ;
                      break ;
      case NOPRINT  : STRCPY(face, "NoprintIcon") ;
                      break ;
      case ORDINARY : if ((facetype = get_icon(name, ibuf)) != -1) 
                        switch (facetype)
                          {
                            case BLITTYPE :
                            case SUNTYPE  : load_icon("Curface") ;
                                            STRCPY(face, "CurfaceIcon") ;
                            case NEWSTYPE : break ;
                          }
                      else STRCPY(face, "NofaceIcon") ;
                      break ;
    }

  if (display == ICON)
    if (mtype == MONPRINTER) adjust_image("MPR", face, 0, 0) ;
    else adjust_image("MPR", face, row, column) ;
  else if (display == WINDOW) adjust_image("PR", face, row, column) ;
  else
    {
      adjust_image("MPR", face, row, column) ;
      adjust_image("PR", face, row, column) ;
    }
  FFLUSH(PostScript) ;
}


adjust_image(dest, face, row, column)
char *dest, *face ;
int row, column ;
{
  switch ((int) mtype)
    {
      case MONNEW     : FPRINTF(PostScript, "%d 0 %d %d %s ShiftImage\n",
                                ICONWIDTH, (NO_PER_ROW-1)*ICONWIDTH, ICONHEIGHT,
                                dest) ;
                        if (facetype == NEWSTYPE)
                          {
                            FPRINTF(PostScript, "%d %d %d %d %s ClearBox\n",
                                    column*ICONWIDTH, row*ICONHEIGHT,
                                    ICONWIDTH, ICONHEIGHT, dest) ;
                            return ;
                          }
      case MONALL     :
      case MONPRINTER : FPRINTF(PostScript,"%s %d %d %d %d %s MoveImage\n",
                                face, ICONWIDTH, ICONHEIGHT,
                                column*ICONWIDTH, row*ICONHEIGHT, dest) ;
    }
}


beep_flash(beeps, flashes)    /* Perform visual feedback. */
int beeps, flashes ;
{
  int i, x ;

  if (beeps)
    for (i = 0; i < beeps; i++)
      {
        x = KBD_CMD_BELL ;
        IOCTL(kbdfd, KIOCCMD, &x) ;
        usleep(250000) ;
        x = KBD_CMD_NOBELL ;
        IOCTL(kbdfd, KIOCCMD, &x) ;
        usleep(250000) ;
      }
}


create_pixrects(width, height)        /* Create pixrects for the face images. */
{
  int h, i, j, w ;

  if (mtype == MONNEW && !firsttime) return ;
  FPRINTF(PostScript,"%d %d PR DoPixrects\n", width, height) ;
  h = height ;
  w = width ;
  if (mtype == MONPRINTER)
    {
      h = ICONHEIGHT ;
      w = ICONWIDTH ;
    }
  FPRINTF(PostScript,"%d %d MPR DoPixrects\n", w, h) ;
  if (strlen(bgicon))
    {
      for (i = 0; i < (height / 64); i++)
        for (j = 0; j < (width / 64); j++)
          {
            FPRINTF(PostScript,"BackgroundIcon %d %d %d %d PR MoveImage\n",
                                  ICONWIDTH, ICONHEIGHT, j, i) ;
            FPRINTF(PostScript,"BackgroundIcon %d %d %d %d MPR MoveImage\n",
                                  ICONWIDTH, ICONHEIGHT, j, i) ;
          }
    }
  else FPRINTF(PostScript,"SetBackground\n") ;
}


do_news_ps(psrecs)     /* Display chain of NeWS animations. */
struct psinfo *psrecs ;
{
  struct psinfo *next, *this ;

  this = psrecs ;      /* Point to beginning of NeWS records. */
  while (this != NULL)
    {
      next = this->next ;
      if ((mtype != MONNEW) || (this->column < NO_PER_ROW))
        {
          FPRINTF(PostScript, "(%s) %d %d %d %d ExecFile\n",
                  this->name, ICONWIDTH, ICONHEIGHT,
                  this->column*ICONWIDTH, this->row*ICONHEIGHT) ;
          FFLUSH(PostScript) ;
        }
      this = next ;
    }
}


init_ws_type()
{
  if (ps_open_PostScript() < 0) return -1 ;
  if (send_ps_file(NEWSFILE) == -1)
    {
      FPRINTF(stderr,"%s: cannot open %s\n", progname, NEWSFILE) ;
      FCLOSE(PostScript) ;
      return(-1) ;
    }
  FFLUSH(PostScript) ;
  if (ferror(PostScript))
    {
      FCLOSE(PostScript) ;
      return(-1) ;
    }
  if (invert) FPRINTF(PostScript, "/Invert false def\n") ;
  else FPRINTF(PostScript, "/Invert true def\n") ;
  gtype = NEWS ;
  return(0) ;
}


load_icon(name)
char *name ;
{
  int i, j ;

  FPRINTF(PostScript,"/%sIcon 64 64 1 { } { <\n", name) ;
  for (i = 0; i < 32; i++)
    {
      for (j = 0; j < 8; j++) FPRINTF(PostScript,"%.4X ", ibuf[i*8+j]) ;
      FPRINTF(PostScript,"\n") ;
    }
  FPRINTF(PostScript,"> } buildimage def\n") ;
}


/*ARGSUSED*/
make_frame(argc,argv)
int argc ;
char *argv[] ;
{
  if ((kbdfd = open("/dev/kbd", 0)) == -1)
    {
      FPRINTF(stderr,"%s: can't open keyboard.\n", progname) ;
      exit(1) ;
    }

  psfd = fileno(PostScriptInput) ;

#ifdef SUNOS3.x
  fullmask = 1 << psfd ;
#else
  FD_ZERO(&fullmask) ;
  FD_SET(psfd, &fullmask) ;
#endif SUNOS3.x

  if (strlen(bgicon))
    if (get_sun_icon(bgicon, ibuf) == 0) load_icon("Background") ;

  FPRINTF(PostScript,"%d %d %d %d %d %d %d MakeFrame\n",
          wx, wy, NO_PER_ROW*ICONWIDTH+10, ICONHEIGHT*10+10,
          ix, iy, iconic) ;
  FPRINTF(PostScript,"InitFont\n") ;
  width = NO_PER_ROW * ICONWIDTH ;
  height = ICONHEIGHT ;
}


make_icon()
{
  if (get_sun_icon("noface.icon", ibuf) == 0) load_icon("Noface") ;
  if (get_sun_icon("nomail.icon", ibuf) == 0) load_icon("Nomail") ;
  if (get_sun_icon("nopaper.icon", ibuf) == 0) load_icon("Nopaper") ;
  if (get_sun_icon("noprint.icon", ibuf) == 0) load_icon("Noprint") ;
}


send_ps_file(fname)
char *fname ;
{
  FILE *stream ;
  int c ;

  if ((stream = fopen(fname,"r")) == NULL) return -1 ;
  while ((c = getc(stream)) != EOF) PUTC(c,PostScript) ;
  FCLOSE(stream) ;
  return 0 ;
}


show_display()        /* Show the latest set of mail icon faces. */
{
  if (mtype != MONPRINTER)
    FPRINTF(PostScript,"%d %d %d %d ShowDisplay\n",
                        width, height, width, height) ;
  else FPRINTF(PostScript,"%d %d %d %d ShowDisplay\n",
                        width, height, ICONWIDTH, ICONHEIGHT) ;

  if (newmail) beep_flash(beeps, flashes) ;
  if (psrecs != NULL) do_news_ps(psrecs) ;
  FFLUSH(PostScript) ;
}


start_tool()
{
  int type ;                     /* Value from NeWS server. */
  struct psinfo *next, *this ;   /* For removing current chain of records. */
  struct timeval tval ;

  tval.tv_usec = 0 ;
  tval.tv_sec = period ;

  for (;;)
    {
      readmask = fullmask ;
#ifdef SUNOS3.x
      SELECT(32, &readmask, 0, 0, &tval) ;
      if (readmask && (1 << psfd))
#else
      SELECT(FD_SETSIZE, &readmask, (fd_set *) 0, (fd_set *) 0, &tval) ;
      if (FD_ISSET(psfd, &readmask))
#endif SUNOS3.x
        {
          if (pscanf(PostScriptInput, "%d", &type) == EOF) exit(1) ;
          switch (type)
            {
              case DIED     : exit(0) ;
              case PAINTED  : if (psrecs != NULL) do_news_ps(psrecs) ;
            }
        }
      else
        {
          this = psrecs ;     /* Point to beginning of NeWS records. */
          if (mtype != MONNEW)
            {
              while (this != NULL)
                {
                  next = this->next ;
                  if (this->name != NULL) free(this->name) ;
                  free((char *) this) ;   /* Remove this record. */
                  this = next ;
                }
              psrecs = plast = NULL ;
            }
          do_check() ;        /* Check the mail/printer again. */
        }
    }
}


text(display,just,str)
enum disp_type display ;
enum just_type just ;
char *str ;
{
  int i, len ;
  int c, r ;             /* Column and row position for this face. */
  int x, y ;             /* Position of start of this text string. */
  char line[MAXLINE] ;   /* PostScript text string to be builtup. */
  char tpr ;             /* Indicator for destination offscreen canvas. */

  c = column ;
  r = row ;
  switch ((int) display)
    {
      case BOTH   : text(ICON, just, str) ;
                    text(WINDOW, just, str) ;
                    return ;
      case ICON   : tpr = 'M' ;       /* MPR canvas. */
                    if (mtype != MONALL) c = r = 0 ;
                    break ;
      case WINDOW : tpr = ' ' ;       /*  PR canvas. */
    }

  len = strlen(str) ;         /* Character length of text. */
  if (len > 10)
    {
      len = 10 ;
      str[10] = '\0' ;   /* Maximum of 10 characters. */
    }

  line[0] = '\0' ;
  for (i = 0; i < len; i++)
    switch (str[i])
      {
        case '\\' : STRCAT(line,"\\\\") ;
                    break ;
        case '('  : STRCAT(line,"\\(") ;
                    break ;
        case ')'  : STRCAT(line,"\\)") ;
                    break ;
        default   : STRNCAT(line,&str[i],1) ;
      }

  switch ((int) just)
    {
      case LEFT  : x = c*ICONWIDTH+2 ;
                   y = r*ICONHEIGHT+2 ;
                   break ;
      case RIGHT : x = (c+1)*ICONWIDTH-(len*6)-2 ;
                   y = r*ICONHEIGHT+2 ;
    }
  FPRINTF(PostScript,"%d %d %d %d %cPR ClearBox\n", x, y, len*6+2, 10, tpr) ;
  FPRINTF(PostScript,"(%s) %d %d %cPR MakeText\n", line, x, y, tpr) ;
}
Funky_Stuff
len=`wc -c < news.c`
if [ $len !=    10648 ] ; then
echo error: news.c was $len bytes long, should have been    10648
fi
fi # end of overwriting check
if [ -f rec.c ]
then
echo shar: will not over-write existing file rec.c
else
echo shar: extracting 'rec.c',     6808 characters
cat > rec.c <<'Funky_Stuff'
/*LINTLIBRARY*/
#ifndef lint
static char sccsid[] = "@(#)rec.c 1.2 88/12/09" ;
#endif

/*  Record handling routines used by the faces program.
 * 
 *  Copyright (c) Rich Burridge - Sun Microsystems Australia.
 *                                All rights reserved.
 *
 *  Permission is given to distribute these sources, as long as the
 *  copyright messages are not removed, and no monies are exchanged. 
 * 
 *  No responsibility is taken for any errors on inaccuracies inherent
 *  either to the comments or the code of this program, but if reported
 *  to me, then an attempt will be made to fix them.
 */

#include "faces.h"
#include "extern.h"

char *
Malloc(n)
int n ;
{
  char *val ;

  if ((val = malloc((unsigned) n)) == NULL)
    FPRINTF(stderr,"%s: Out of memory.\n",progname) ;
  return val ;
}


add_alias(crec, username, alias)  /* Add new alias to hostnames' list. */
struct comminfo *crec ;
char *username, *alias ;
{
  struct peopinfo *cptemp, *ptemp ;

  ptemp = (struct peopinfo *) Malloc(sizeof(struct peopinfo)) ;
  ptemp->alias = (char *) Malloc(strlen(alias)) ;
  STRCPY(ptemp->alias, alias) ;
  ptemp->username = (char *) Malloc(strlen(username)) ;
  STRCPY(ptemp->username, username) ;
  ptemp->next = NULL ;

  if (crec->people == NULL) crec->people = ptemp ;
  else
    {
      cptemp = crec->people ;
      while (cptemp != NULL)
        if (cptemp->next == NULL)
          {
            cptemp->next = ptemp ;
            return ;
          }
        else cptemp = cptemp->next ;
    }
}


add_machine(machine, community)    /* Add new machine to list. */
char *machine, *community ;
{
  struct machinfo *temp ;

  temp = (struct machinfo *) Malloc(sizeof(struct machinfo)) ;
  temp->machine = (char *) Malloc(strlen(machine)) ;
  STRCPY(temp->machine, machine) ;
  temp->community = (char *) Malloc(strlen(community)) ;
  STRCPY(temp->community, community) ;
  temp->next = NULL ;

  if (machines == NULL) machines = mlast = temp ;   /* Start chain. */
  else if (mlast != NULL)
    {
      mlast->next = temp ;     /* Add record to existing chain. */
      mlast = temp ;           /* Point to end of chain. */
    }
}


add_ps_rec(row, column, name)  /* Add record for later animation. */
int row, column ;
char *name ;
{
  struct psinfo *temp ;

  temp = (struct psinfo *) Malloc(sizeof(struct psinfo)) ;
  temp->name = (char *) Malloc(strlen(name)) ;
  STRCPY(temp->name, name) ;
  temp->row = row ;
  temp->column = column ;
  temp->next = NULL ;

  if (psrecs == NULL) psrecs = plast = temp ;    /* Start chain. */
  else if (plast != NULL)
    {
      plast->next = temp ;     /* Add record to existing chain. */
      plast = temp ;
    }
}


add_record(community, username, timestamp, size)
char *community, *username, *timestamp ;
int size ;
{
  struct recinfo *temp ;

  temp = (struct recinfo *) Malloc(sizeof(struct recinfo)) ;
  temp->community = (char *) Malloc(strlen(community)) ;
  STRCPY(temp->community, community) ;
  temp->username = (char *) Malloc(strlen(username)) ;
  STRCPY(temp->username, username) ;
  temp->iconname = (char *) Malloc(strlen(iconname)) ;
  STRCPY(temp->iconname, iconname) ;
  STRCPY(temp->ts, timestamp) ;
  temp->size = size ;
  temp->total = 1 ;
  temp->next = NULL ;
  noicons++ ;
  if (recs == NULL) recs = last = temp ;        /* Start chain. */
  else
    {
      last->next = temp ;  /* Add record to existing chain. */
      last = temp ;        /* Point to the end of the chain. */
    }
}


check_comm(hostname, username, alias)  /* Check community list. */
char *hostname, *username, *alias ;
{
  struct comminfo *ctemp ;
 
  ctemp = communities ;      /* Try and find machine record for hostname. */
  while (ctemp != NULL)
    if (EQUAL(ctemp->community, hostname))
      {  
        add_alias(ctemp, username, alias) ;
        return ;
      }  
    else ctemp = ctemp->next ;
 
  ctemp = (struct comminfo *) Malloc(sizeof(struct comminfo)) ;
  ctemp->community = (char *) Malloc(strlen(hostname)) ;
  STRCPY(ctemp->community, hostname) ; 
  ctemp->people = NULL ; 
  ctemp->next = NULL ; 
 
  if (communities == NULL) communities = clast = ctemp ;  /* Start chain. */ 
  else 
    { 
      clast->next = ctemp ;   /* Add record to existing chain. */
      clast = ctemp ;         /* Point to end of chain. */
    }
  add_alias(ctemp, username, alias) ;
}


read_aliases()     /* Setup the hostname aliases subchains. */
{
  char alias[MAXLINE] ;      /* Alias for this community/username. */
  char hostname[MAXLINE] ;   /* This records' hostname. */
  char username[MAXLINE] ;   /* This records real username. */
  char *ptr1, *ptr2 ;
  FILE *fd ;

  if ((fd = fopen(peopfile, "r")) == NULL)   /* Open people file. */
    {
      FPRINTF(stderr,"%s: cannot open %s\n", progname, peopfile) ;
      return ;
    }
  while (fgets(nextline, MAXLINE, fd) != NULL)
    {
      ptr1 = index(nextline, '/') ;
      STRNCPY(hostname, nextline, (int) (ptr1-nextline)) ;
      hostname[(int) (ptr1-nextline)] = '\0' ;
      ptr2 = index(nextline, '=') ;
      STRNCPY(alias, ptr1+1, (int) (ptr2-ptr1-1)) ;
      alias[(int) (ptr2-ptr1-1)] = '\0' ;
      STRNCPY(username, ptr2+1, strlen(ptr2)-2) ;
      username[strlen(ptr2)-2] = '\0' ;
      check_comm(hostname, username, alias) ;
    }
  FCLOSE(fd) ;
}


read_machines()       /* Setup the chain of machine/community records. */
{
  char community[MAXLINE] ;   /* This records' community. */
  char machine[MAXLINE] ;     /* This records' machine name. */
  char *ptr ;
  FILE *fd ;

  if ((fd = fopen(machfile, "r")) == NULL)   /* Open machine file. */
    {
      FPRINTF(stderr,"%s: cannot open %s\n", progname, machfile) ;
      return ;
    }
  while (fgets(nextline, MAXLINE, fd) != NULL)
    {
      ptr = index(nextline, '=') ;
      STRNCPY(machine, nextline, (int) (ptr-nextline)) ;
      machine[(int) (ptr-nextline)] = '\0' ;
      STRNCPY(community, ptr+1, strlen(ptr)-2) ;
      community[strlen(ptr)-2] = '\0' ;
      add_machine(machine, community) ;
    }
  FCLOSE(fd) ;
}


struct recinfo *
rec_exists(community,username)    /* Check if record exists for mail item. */
char *community, *username ;
{
  struct recinfo *temp ;     /* Pointer to mail records used for chaining. */

  temp = recs ;
  while (temp != NULL)
    {
      if (EQUAL(temp->username, username) &&
          EQUAL(temp->community, community))
        return(temp) ;       /* Record found. */
      temp = temp->next ;    /* Point to next record. */
    }
  return(NULL) ;
}


remove_record(thisrec)        /* Remove this record from the chain. */
struct recinfo *thisrec ;
{
  if (thisrec->community != NULL) free(thisrec->community) ;
  if (thisrec->username != NULL) free(thisrec->username) ;
  if (thisrec->iconname != NULL) free(thisrec->iconname) ;
  free((char *) thisrec) ;
}
Funky_Stuff
len=`wc -c < rec.c`
if [ $len !=     6808 ] ; then
echo error: rec.c was $len bytes long, should have been     6808
fi
fi # end of overwriting check
if [ -f sunview.c ]
then
echo shar: will not over-write existing file sunview.c
else
echo shar: extracting 'sunview.c',     9881 characters
cat > sunview.c <<'Funky_Stuff'
/*LINTLIBRARY*/
#ifndef lint
static char sccsid[] = "@(#)sunview.c 1.1 88/12/04" ;
#endif

/*  SunView dependent graphics routines used by faces,
 *  the visual mail and print job monitor.
 * 
 *  Copyright (c) Rich Burridge - Sun Microsystems Australia.
 *                                All rights reserved.
 *
 *  Permission is given to distribute these sources, as long as the
 *  copyright messages are not removed, and no monies are exchanged. 
 * 
 *  No responsibility is taken for any errors or inaccuracies inherent
 *  either to the comments or the code of this program, but if reported
 *  to me, then an attempt will be made to fix them.
 */

#include "faces.h"
#include "extern.h"
#include <stdio.h>
#include <suntool/sunview.h>
#include <suntool/canvas.h>

#define  ICON_SET                (void) icon_set
#define  NOTIFY_SET_ITIMER_FUNC  (void) notify_set_itimer_func
#define  PR_DESTROY              (void) pr_destroy
#define  PR_REPLROP              (void) pr_replrop
#define  PR_ROP                  (void) pr_rop

#ifdef SUNOS3.x
#define  PR_TTEXT                (void) pf_ttext
#else
#define  PR_TTEXT                (void) pr_ttext
#endif SUNOS3.x

#define  PW_ROP                  (void) pw_rop
#define  WIN_BELL                (void) win_bell
#define  WINDOW_SET              (void) window_set

#define  SMALLFONT    "/usr/lib/fonts/fixedwidthfonts/screen.r.7"
#define  ITIMER_NULL  ((struct itimerval *) 0)

int repaint_proc() ;

Canvas canvas ;
Frame frame ;
Icon faces_icon ;
Pixfont *sfont ;              /* Small font for timestamp and count. */
Pixrect *mpr, *pr ;           /* Pointers to current pixrects. */
Pixrect *old_mpr, *old_pr ;   /* Pointers to previous pixrects. */
Pixrect *background ;         /* Pointer to background pattern or gray. */
Pixwin *fpw, *pw ;
Rect *temprect ;
int ffd ;                     /* File descriptor of faces frame. */

short gray_image[] = { 0x8000, 0x8000, 0x2000, 0x2000 } ;
mpr_static(gray_pr, 4, 4, 1, gray_image) ;

short noface_image[] = {
#include "noface.icon"
} ;
mpr_static(noface_pr, 64, 64, 1, noface_image) ;

short nomail_image[] = {
#include "nomail.icon"
} ;
mpr_static(nomail_pr, 64, 64, 1, nomail_image) ;

short nopaper_image[] = {
#include "nopaper.icon"
} ;
mpr_static(nopaper_pr, 64, 64, 1, nopaper_image) ;

short noprint_image[] = {
#include "noprint.icon"
} ;
mpr_static(noprint_pr, 64, 64, 1, noprint_image) ;


add_face(display, itype, name)
enum disp_type display ;
enum icon_type itype ;
char *name ;
{
  Pixrect *face_pr ;
  unsigned short buf[256] ;  /* Ikon/icon image. */
  unsigned short *ptr ;
  int freeit ;               /* Set if we should destroy this pixrect. */
  int i ;

  freeit = 0 ;
  switch ((int) itype)
    {
      case NOMAIL   : face_pr = &nomail_pr ;
                      break ;
      case NOPAPER  : face_pr = &nopaper_pr ;
                      break ;
      case NOPRINT  : face_pr = &noprint_pr ;
                      break ;
      case ORDINARY : if (get_icon(name, buf) == -1) face_pr = &noface_pr ;
                      else
                        {
                          face_pr = mem_create(64, 64, 1) ;
                          ptr = (unsigned short *)
                                ((struct mpr_data *) face_pr->pr_data)->md_image ;
                          for (i = 0; i < 256; i++) ptr[i] = buf[i] ;
                          freeit = 1 ;
                        }
                      break ;
    }
  if (display == ICON)
    if (mtype == MONPRINTER) adjust_image(mpr, face_pr, 0, 0) ;
    else adjust_image(mpr, face_pr, row, column) ;
  else if (display == WINDOW) adjust_image(pr, face_pr, row, column) ;
  else
    {
      adjust_image(mpr, face_pr, row, column) ;
      adjust_image(pr, face_pr, row, column) ;
    }
  if (freeit) PR_DESTROY(face_pr) ;
}


adjust_image(fpr, face_pr, row, column)    /* Place new face in memory pixrect. */
Pixrect *fpr, *face_pr ;
int row, column ;
{
  switch ((int) mtype)
    {
      case MONNEW     : PR_ROP(fpr, 64, 0, 640-64, 64, PIX_SRC, fpr, 0, 0) ;
      case MONALL     :
      case MONPRINTER : PR_ROP(fpr, column*ICONWIDTH, row*ICONHEIGHT,
                               ICONWIDTH, ICONHEIGHT, PIX_SRC, face_pr, 0, 0) ;
    }
}


Notify_value
check_mail()
{
  do_check() ;
}


beep_flash(beeps, flashes)    /* Perform visual feedback. */
int beeps, flashes ;
{
  static struct timeval btime = { 0, 250000 } ;   /* Beep timer. */
  int bfd ;        /* File descriptor for faces window, or -1. */
  Pixwin *bpw ;    /* Pixwin pointer for faces window, or 0. */

  if (beeps || flashes)
    do
      {
        bfd = beeps > 0 ? ffd : -1 ;
        bpw = flashes > 0 ? fpw : (Pixwin *) 0 ;
        WIN_BELL(bfd, btime, bpw) ;
        SELECT(0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &btime) ;
        beeps-- ;
        flashes-- ;
      } 
    while (beeps > 0) ;
}


create_pixrects(width, height)   /* Create pixrects for the face images. */
int width, height ;
{
  old_pr = pr ;
  pr = mem_create(width, height, 1) ;
  PR_REPLROP(pr, 0, 0, width, height, PIX_SRC, background, 0, 0) ;
  faces_icon = (Icon) window_get(frame, FRAME_ICON) ;
  old_mpr = (Pixrect *) icon_get(faces_icon, ICON_IMAGE) ;
  if (mtype == MONPRINTER) mpr = mem_create(ICONWIDTH, ICONHEIGHT, 1) ;
  else
    {
      mpr = mem_create(width, height, 1) ;
      PR_REPLROP(mpr, 0, 0, width, height, PIX_SRC, background, 0, 0) ;
    }
  if (mtype == MONNEW && old_pr != NULL)
    PR_ROP(pr, 0, 0, width, height, PIX_SRC, old_pr, 0, 0) ;
  if (mtype == MONNEW && old_mpr != NULL)
    PR_ROP(mpr, 0, 0, width, height, PIX_SRC, old_mpr, 0, 0) ;
}


init_ws_type()
{
  gtype = SUNVIEW ;
  return 0 ;
}


make_frame(argc,argv)
int argc ;
char *argv[] ;
{
  unsigned short buf[256] ;  /* For background pattern. */
  unsigned short *ptr ;
  int i ;

  if (strlen(bgicon))
    {
      if (get_sun_icon(bgicon, buf) == 0) background = &gray_pr ;
      background = mem_create(64, 64, 1) ;
      ptr = (unsigned short *)
            ((struct mpr_data *) background->pr_data)->md_image ;
      for (i = 0; i < 256; i++) ptr[i] = buf[i] ;
    }
  else background = &gray_pr ;

  frame = window_create((Window) 0, FRAME,
                        FRAME_ICON, faces_icon,
                        FRAME_SHOW_LABEL, FALSE,
                        FRAME_SUBWINDOWS_ADJUSTABLE, FALSE,
                        FRAME_NO_CONFIRM, TRUE,
                        WIN_WIDTH, NO_PER_ROW * ICONWIDTH + 10,
                        WIN_HEIGHT, ICONHEIGHT * 10 + 10,
                        FRAME_ARGS, argc,argv,
                        0) ;
  fpw = (Pixwin *) window_get(frame, WIN_PIXWIN) ;
  ffd = (int) window_get(frame, WIN_FD) ;

  canvas = window_create(frame, CANVAS,
                         CANVAS_REPAINT_PROC, repaint_proc,
                         CANVAS_RETAINED, TRUE,
                         0) ;
  pw = canvas_pixwin(canvas) ;
  sfont = pf_open(SMALLFONT) ;
  width = NO_PER_ROW * ICONWIDTH ;
  height = ICONHEIGHT ;
}


make_icon()
{
  if (mtype == MONPRINTER)
    faces_icon = icon_create(ICON_IMAGE, &noprint_pr, 0) ;
  else faces_icon = icon_create(ICON_IMAGE, &nomail_pr, 0) ;
}


/*ARGSUSED*/
repaint_proc(canvas, pw, repaint_area)
Canvas canvas ;
Pixwin *pw ;
Rectlist *repaint_area ;
{
  PW_ROP(pw, 0, 0, width, height, PIX_SRC, pr, 0, 0) ;
}


show_display()    /* Show the latest set of mail icon faces. */
{
  if (invert)     /* Invert the memory pixrects before displaying. */
    {
      PR_ROP(pr, 0, 0, width, height, PIX_NOT(PIX_DST), pr, 0, 0) ;
      PR_ROP(mpr, 0, 0, width, height, PIX_NOT(PIX_DST), pr, 0, 0) ;
    }

  if (mtype != MONPRINTER)
    {
      temprect = (Rect *) icon_get(faces_icon, ICON_IMAGE_RECT) ;
      temprect->r_height = height ;
      temprect->r_width = width ;
      ICON_SET(faces_icon, ICON_HEIGHT, height,
                           ICON_WIDTH, width,
                           ICON_IMAGE_RECT, temprect,
                           ICON_IMAGE, mpr,
                           0) ;
    }
  else ICON_SET(faces_icon, ICON_IMAGE, mpr, 0) ;
  WINDOW_SET(frame, FRAME_ICON, faces_icon, 0) ;

  temprect = (Rect *) window_get(frame, FRAME_OPEN_RECT) ;
  temprect->r_height = height+10 ;
  temprect->r_width = width+10 ;
  WINDOW_SET(frame, FRAME_OPEN_RECT, temprect, 0) ;
  PW_ROP(pw, 0, 0, width, height, PIX_SRC, pr, 0, 0) ;

  if (newmail) beep_flash(beeps, flashes) ;
  if (old_pr) PR_DESTROY(old_pr) ;
  if (old_mpr) PR_DESTROY(old_mpr) ;
}


start_tool()
{
  struct itimerval tval ;

  tval.it_interval.tv_usec = 0 ;
  tval.it_interval.tv_sec = period ;
  tval.it_value.tv_usec = 0 ;
  tval.it_value.tv_sec = period ;
  NOTIFY_SET_ITIMER_FUNC(frame, check_mail,
                         ITIMER_REAL, &tval, ITIMER_NULL) ;
  window_main_loop(frame) ;
}


text(display, just, str)
enum disp_type display ;
enum just_type just ;
char *str ;
{
  int len ;
  int c, r ;         /* Column and row position for this face. */
  int x, y ;         /* Position of start of this text string. */
  Pixrect *tpr ;

  c = column ;
  r = row ;
  switch ((int) display)
    {
      case BOTH   : text(ICON, just, str) ;
                    text(WINDOW, just, str) ;
                    return ;
      case ICON   : tpr = mpr ;
                    if (mtype != MONALL) c = r = 0 ;
                    break ;
      case WINDOW : tpr = pr ;
    }

  len = strlen(str) ;              /* Character length of text. */
  if (len > 10)
    {
      len = 10 ;
      str[10] = '\0' ;   /* Maximum of 10 characters. */
    }
  switch ((int) just)
    {
      case LEFT  : x = c*ICONWIDTH+2 ;
                   y = (r+1)*ICONHEIGHT-2 ;
                   break ;
      case RIGHT : x = (c+1)*ICONWIDTH-(len*6)-2 ;
                   y = (r+1)*ICONHEIGHT-2 ;
    }
  PR_ROP(tpr, x, y-9, len*6+2, 10, PIX_CLR, (Pixrect *) NULL, 0, 0) ;
  PR_TTEXT(tpr, x, y, PIX_SRC ^ PIX_NOT(PIX_DST), sfont, str) ;
}
Funky_Stuff
len=`wc -c < sunview.c`
if [ $len !=     9881 ] ; then
echo error: sunview.c was $len bytes long, should have been     9881
fi
fi # end of overwriting check