#! /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:  Imakefile Xwhom.ad xwhom.c
# Wrapped by jpaparel@cs on Mon Dec 23 12:01:33 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Imakefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Imakefile'\"
else
echo shar: Extracting \"'Imakefile'\" \(132 characters\)
sed "s/^X//" >'Imakefile' <<'END_OF_FILE'
SYS_LIBRARIES = $(XAWLIB) $(XTOOLLIB) $(XMULIB) $(XLIB)
LDOPTIONS = -O -s
OBJS = xwhom.o
SRCS = xwhom.c
ComplexProgramTarget(xwhom)
END_OF_FILE
if test 132 -ne `wc -c <'Imakefile'`; then
    echo shar: \"'Imakefile'\" unpacked with wrong size!
fi
# end of 'Imakefile'
fi
if test -f 'Xwhom.ad' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Xwhom.ad'\"
else
echo shar: Extracting \"'Xwhom.ad'\" \(429 characters\)
sed "s/^X//" >'Xwhom.ad' <<'END_OF_FILE'
X#ifdef COLOR
xwhom*vport*foreground:#6e4242
xwhom*vport*background:#af008f6e8ff5
xwhom*vport*borderColor:#fa00ce009d00
xwhom*name*foreground:#fa00ce009d00
xwhom*name*background:#6e4242
xwhom*host*foreground:#fa00ce009d00
xwhom*host*background:#6e4242
xwhom*shell*dialog*background:#bc8f8f
xwhom*shell*button*foreground:#fa00ce009d00
xwhom*shell*button*borderColor:#6e4242
X#endif
xwhom*name*font:variable
xwhom*host*font:variable
END_OF_FILE
if test 429 -ne `wc -c <'Xwhom.ad'`; then
    echo shar: \"'Xwhom.ad'\" unpacked with wrong size!
fi
# end of 'Xwhom.ad'
fi
if test -f 'xwhom.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xwhom.c'\"
else
echo shar: Extracting \"'xwhom.c'\" \(10791 characters\)
sed "s/^X//" >'xwhom.c' <<'END_OF_FILE'
X/* XWhom - written by Joseph Paparella    Dec 16, 1991
X * University of Massachusetts at Lowell
X *
X * XWhom is a simple X-hack I did one day because I didn't feel like
X * doing real work.  XWhom lists the users on the system in an Athena List
X * Widget.  If you have a .whom file in your home directory, the names in
X * your .whom file will replace the corresponding login names.  Click on the
X * desired user to get information about them and their processes.  XWhom
X * updates the list every 10 seconds.  Press 'Q' to quit.
X *
X * The .whom file contains aliases for login names.  The aliases may have
X * spaces, but will be truncated to 8 characters.  A sample .whom file:
X * login:   alias:
X *
X * root     The Man
X * uucp     mailman
X * jpaparel Joe
X *
X * The -w option just displays users in your .whom file.
X * The -u option lets you adjust the user list refresh interval.
X * The -c option lets you set the default number of columns.
X * The -s option disables scrollbars.
X *
X * Merge in the default resources by typing:  xrdb -merge Xwhom.ad
X * You can edit this file to put in your own default resources then add it
X * to your .Xdefaults file.
X *
X * Please report any problems, suggestions, bug fixes, etc. to me at:
X *   jpaparel@cs.ulowell.edu
X */
X
X#include <X11/Intrinsic.h>
X#include <X11/StringDefs.h>
X#include <X11/Shell.h>
X#include <X11/Xaw/Command.h>
X#include <X11/Xaw/Dialog.h>
X#include <X11/Xaw/Label.h>
X#include <X11/Xaw/List.h>
X#include <X11/Xaw/Paned.h>
X#include <X11/Xaw/Viewport.h>
X#include <sys/file.h>
X#include <stdio.h>
X#include <stdlib.h>
X#include <utmp.h>
X#include <pwd.h>
X
X#define STRSIZE 80
X#define MAXUSER 100
X#define MAXPALS 100
X#define FILEBUF 1024
X#define DATASIZ 512
X#define GECOSSZ 120
X
void QuitProc();
X
Display *dpy;
XXtAppContext app;
Widget topLevel, label, shell = NULL;
unsigned long interval = 10000;
Bool whomOnly = False;
Bool scrollBars = True;
int count = 0;
int columns = 3;
String items[MAXUSER] = {NULL};
struct utmp entry[MAXUSER];
static char buffer[FILEBUF];
X
String translationTable = "<Key>q:quit()";
XXtActionsRec actionsTable = {"quit", (XtActionProc)QuitProc};
X
String format = "\
User: %s\n\n\
Name: %s\n\n\
Host: %s\n\n\
Line: %s\n\n\
Login Time: %s\n\n\
Office: %s\n\n\
Home Phone: %s\n\n\
Office Phone: %s\n\n\
Directory: %s\n\n\
X%s\n\n\
X";
X
int pals;
struct PalTbl {
X  char logName[9];
X  char palName[9];
X} table[MAXPALS];
X
int palcmp(e1, e2)
register struct PalTbl *e1;
register struct PalTbl *e2;
X{
X  return strcmp(e1->palName, e2->palName);
X}
X
int utmpcmp(e1, e2)
register struct utmp *e1;
register struct utmp *e2;
X{
X  return strncmp(e1->ut_name, e2->ut_name, 8);
X}
X
String getps(index)
int index;
X{
X  char command[STRSIZE];
X  register FILE *fp;
X  register String p, e;
X  String filename = tmpnam(NULL);
X
X  sprintf(command, "ps -t%c%c > %s\n", entry[index].ut_line[3],
X		entry[index].ut_line[4], filename);
X
X  system(command);
X
X  if (!(fp = fopen(filename, "r")))
X    return NULL;
X
X  for (p = buffer, e = buffer + 8191; !feof(fp) && p <= e; p++)
X    *p = fgetc(fp);
X  *(--p) = 0;
X
X  fclose(fp);
X
X  unlink(filename);
X
X  return buffer;
X}
X
void setupInfo(string, index)
register String string;
register int index;
X{
X  register struct passwd *pwd;
X  register String p, q, s;
X  char user[9], host[17], line[9], timstr[9], gecos[GECOSSZ];
X  register struct PalTbl *pal;
X  struct PalTbl key;
X
X  memcpy(key.palName, entry[index].ut_name, 8);
X  key.palName[8] = 0;
X
X  qsort(table, pals, sizeof(struct PalTbl), palcmp);
X  if (pal = (struct PalTbl *)bsearch(&key, table, pals, sizeof(struct PalTbl),
X							  palcmp))
X    p = pal->logName;
X  else
X    p = entry[index].ut_name;
X
X  for (q = user, s = q + 8; *p && q < s; p++, q++)
X    *q = *p;
X  *q = 0;
X
X  for (p = entry[index].ut_host, q = host, s = q + 16; *p && q < s; p++, q++)
X    *q = *p;
X  *q = 0;
X
X  for (p = entry[index].ut_line, q = line, s = q + 8; *p && q < s; p++, q++)
X    *q = *p;
X  *q = 0;
X
X  strftime(timstr, 9, "%I:%M %p", localtime(&entry[index].ut_time));
X
X  pwd = getpwnam(user);
X  
X  q = gecos;
X  p = pwd->pw_gecos;
X  for (; *p && !(*p == ',' || *p == ':' || *p == '\n');)
X    *q++ = *p++;
X  *q = 0;
X
X  q = gecos + 30;
X  if (*p && *p != ':')
X    for (p++; *p && !(*p == ',' || *p == ':' || *p == '\n'); p++, q++)
X	 *q = *p;
X  *q = 0;
X    
X  q = gecos + 60;
X  if (*p && *p != ':')
X    for (p++; *p && !(*p == ',' || *p == ':' || *p == '\n'); p++, q++)
X	 *q = *p;
X  *q = 0;
X
X  q = gecos + 90;
X  if (*p && *p != ':')
X    for (p++; *p && !(*p == ',' || *p == ':' || *p == '\n'); p++, q++)
X	 *q = *p;
X  *q = 0;
X
X  sprintf(string, format, user, gecos, host, line, timstr,
X		gecos + 30, gecos + 90, gecos + 60, pwd->pw_dir, getps(index));
X}
X
void makeTable()
X{
X  register char c;
X  register int i;
X  register FILE *fp;
X  char filename[STRSIZE];
X
X  strcpy(filename, getenv("HOME"));
X  strcat(filename, "/.whom");
X  if (!(fp = fopen(filename, "r")))
X    return;
X
X  for (pals = 0; !feof(fp); pals++) {
X    fscanf(fp, "%s", table[pals].logName);
X
X    while (isspace(c = fgetc(fp)));
X    ungetc(c, fp);
X
X    for (i = 0; i < 8; i++)
X	 if ((c = fgetc(fp)) == '\n')
X	   break;
X	 else
X	   table[pals].palName[i] = c;
X
X    while (c != '\n' && !feof(fp))
X	 c = fgetc(fp);
X    ungetc(c, fp);
X
X    table[pals].palName[i] = 0;
X  }
X  pals--;
X
X  fclose(fp);
X}
X
void setList()
X{
X  register int fd;
X  register struct PalTbl *tmp;
X  register int i;
X  struct PalTbl key;
X
X  if (*items)
X    XtFree(*items);
X
X  if ((fd = open("/etc/utmp", O_RDONLY)) < 0) {
X    fprintf(stderr, "Can't open /etc/utmp.\n");
X    exit(1);
X  }
X
X  qsort(table, pals, sizeof(struct PalTbl), strcmp);
X
X  for (count = 0; read(fd, entry + count, sizeof(struct utmp)) > 0;)
X    if (*entry[count].ut_name)
X	 if (!whomOnly)
X	   count++;
X	 else {
X	   memcpy(key.logName, entry[count].ut_name, 8);
X	   key.logName[8] = 0;
X	   if (bsearch(&key, table, pals, sizeof(struct PalTbl), strcmp))
X		count++;
X	 }
X
X  close(fd);
X
X  *items = XtMalloc((count + 1) * 9);
X  items[count] = NULL;
X
X  for (i = 0; i < count; i++) {
X    items[i] = items[0] + i * 9;
X
X    memcpy(key.logName, entry[i].ut_name, 8);
X    key.logName[8] = 0;
X    if (tmp = (struct PalTbl *)bsearch(&key, table, pals,
X							    sizeof(struct PalTbl), strcmp))
X	 memcpy(entry[i].ut_name, tmp->palName, 8);
X    
X    memcpy(items[i], entry[i].ut_name, 8);
X    items[i][8] = 0;
X  }
X  qsort(entry, count, sizeof(struct utmp), utmpcmp);
X  qsort(*items, count, sizeof(char[9]), strcmp);
X}
X
void processUTmp(list, id)
Widget list;
XXtIntervalId *id;
X{
X  char string[STRSIZE];
X
X  if (!XtIsRealized(list)) {
X    XtAppAddTimeOut(app, 500, processUTmp, list);
X    return;
X  }
X
X  setList();
X
X  XawListChange(list, items, 0, 0, False);
X  
X  if (count > 1)
X    sprintf(string, "XWhom: %d users", count);
X  else
X    strcpy(string, "XWhom: 1 user");
X
X  XtVaSetValues(label, XtNlabel, string, NULL);
X  XtAppAddTimeOut(app, interval, processUTmp, list);
X}
X
void QuitProc(widget, event, params, num_params)
Widget widget;
XXEvent *event;
String *params;
Cardinal *num_params;
X{
X  if (*items)
X    XtFree(*items);
X
X  XtDestroyApplicationContext(app);
X  XtCloseDisplay(dpy);
X  exit(0);
X}
X
void OkCB(widget, client_data, call_data)
Widget widget;
caddr_t client_data;
caddr_t call_data;
X{
X  XtPopdown(shell);
X}
X
void ListSelectCB(widget, client_data, call_data)
Widget widget;
caddr_t client_data;
register XawListReturnStruct *call_data;
X{
X  Position x, y;
X  Dimension width, height;
X  char string[DATASIZ];
X  static Widget dialog;
X
X  call_data->list_index = (call_data->list_index >= count) ? count - 1 :
X    call_data->list_index;
X
X  setupInfo(string, call_data->list_index);
X
X  if (!shell) {
X    Widget button;
X
X    shell = XtCreatePopupShell("shell", transientShellWidgetClass, topLevel,
X						 NULL, 0);
X
X    dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, shell,
X							  XtNlabel, string, NULL);
X
X    button = XtVaCreateManagedWidget("button", commandWidgetClass, dialog,
X							  XtNlabel, "Ok", NULL);
X    XtAddCallback(button, XtNcallback, OkCB, NULL);
X  }
X
X  XtVaGetValues(topLevel, XtNwidth, &width, XtNheight, &height, NULL);
X  XtTranslateCoords(topLevel, (Position)(width >> 1), (Position)(height >> 1),
X				&x, &y);
X
X  XtVaGetValues(dialog, XtNwidth, &width, XtNheight, &height, NULL);
X  if (!width && !height) {
X    XtPopup(shell, XtGrabNone);
X    XtVaGetValues(dialog, XtNwidth, &width, XtNheight, &height, NULL);
X  }
X  x = (x + width > DisplayWidth(dpy, DefaultScreen(dpy))) ? x - width : x;
X  y = (y + height > DisplayHeight(dpy, DefaultScreen(dpy))) ? y - height : y;
X
X  XtVaSetValues(dialog, XtNlabel, string, NULL);
X  XtVaSetValues(shell, XtNx, x, XtNy, y, NULL);
X  XtPopup(shell, XtGrabNone);
X}
X
void main(argc, argv)
int argc;
char *argv[];
X{
X  char c;
X  char hostname[STRSIZE];
X  Widget pane, list, viewport;
X  XtTranslations translations;
X  extern char *optarg;
X
X  while ((c = getopt(argc, argv, "whsu:c:")) != EOF)
X    switch (c) {
X    case 'u':
X	 interval = atoi(optarg) * 1000;
X	 break;
X    case 'w':
X	 whomOnly = True;
X	 break;
X    case 'c':
X	 columns = atoi(optarg);
X	 break;
X    case 's':
X	 scrollBars = False;
X	 break;
X    case 'h':
X	 fprintf(stderr, "Help:");
X    default:
X	 fprintf(stderr, "\nusage: xwhom [-options...]\n\n");
X	 fprintf(stderr, "where options include:\n");
X	 fprintf(stderr, "\t-h\t\tThis help message\n");
X	 fprintf(stderr, "\t-w\t\tOnly display users in .whom file\n");
X	 fprintf(stderr, "\t-s\t\tDisable scrollbars.\n");
X	 fprintf(stderr, "\t-c columns\tSet the default number of columns\n");
X	 fprintf(stderr, "\t-u interval\tUpdate list every x seconds\n");
X	 exit(0);
X    }
X
X  XtToolkitInitialize();
X
X  app = XtCreateApplicationContext();
X
X  if (!(dpy = XtOpenDisplay(app, "", *argv, "XWhom", NULL, 0, &argc, argv)))
X    XtError("Can't open display.");
X
X  topLevel = XtAppCreateShell(*argv, "XWhom", applicationShellWidgetClass,
X						dpy, argv, argc);
X
X  translations = XtParseTranslationTable(translationTable);
X  XtAppAddActions(app, &actionsTable, 1);
X
X  pane = XtVaCreateManagedWidget("pane", panedWidgetClass, topLevel,
X						   XtNtranslations, translations, NULL);
X  
X  label = XtVaCreateManagedWidget("name", labelWidgetClass, pane, NULL);
X
X  strcpy(hostname, "Host: ");
X  gethostname(hostname + 6, STRSIZE);
X  XtVaCreateManagedWidget("host", labelWidgetClass, pane,
X					 XtNlabel, hostname, NULL);
X
X  viewport = XtVaCreateManagedWidget("vport", viewportWidgetClass, pane,
X							  XtNborderWidth, 1,
X							  XtNallowHoriz, scrollBars,
X							  XtNallowVert, scrollBars, NULL);
X  makeTable();
X  setList();
X  list = XtVaCreateManagedWidget("list", listWidgetClass, viewport, 
X						   XtNlist, items,
X						   XtNdefaultColumns, columns,
X						   XtNverticalList, True, NULL);
X  XtAddCallback(list, XtNcallback, ListSelectCB, NULL);
X
X  processUTmp(list, NULL);
X
X  XtRealizeWidget(topLevel);
X  XtAppMainLoop(app);
X}
END_OF_FILE
if test 10791 -ne `wc -c <'xwhom.c'`; then
    echo shar: \"'xwhom.c'\" unpacked with wrong size!
fi
# end of 'xwhom.c'
fi
echo shar: End of shell archive.
exit 0
