allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (08/25/89)
Posting-number: Volume 8, Issue 16 Submitted-by: edf@ROCKY2.ROCKEFELLER.EDU (David MacKenzie) Archive-name: hint/part01 hint is an alternative to write(1) that sends a one-line message to one or more other users. The message appears along with the sender's user name and a beep (or, if possible, a ``visual bell'' such as flashing the screen) on the status line of the recipient's terminal, and disappears after 10 seconds. If the recipient's terminal does not have a status line, hints appear wherever the cursor happens to be when they are received. #! /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 archive 1 (of 2)." # Contents: README hint.1 clearhint.1 hall.1 MANIFEST main.c hint.h # hinttab.c hinttab.h stov.c stov.h str.c user.c hall.sh # Wrapped by dave@zedfdc on Thu Aug 24 19:49:21 1989 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'\" \(1576 characters\) sed "s/^X//" >'README' <<'END_OF_FILE' XInstallation notes for hint X XTo allow people to disable write and talk messages but still allow Xhints, hint does not use the mesg bit to determine write permission. XInstead, it uses the group-execute bit of the tty. However, because Xsetting this bit does not actually give write permission, hint must run Xsetuid to root. This ensures that running the hint program is the only Xinterface which can activate write permission for hints; that is Ximportant, because not only must the permission bit be set, but an Xentry in the file /usr/local/lib/hinttab must also be updated. X XA companion program, clearhint, is provided for systems where X"tput dsl" is not available to clear the status line. X XFor people with Wyse 50 terminals, the standard termcap files often don't Xhave the status line capabilities defined, and the Quick Reference Guide Xthat comes with the terminal isn't of much help either. For a status Xline on the bottom, use: X :hs:es:ds=\Ef\r:fs=\r:ts=\Ef:ws#78: X XFor a short status line on the top, use: X :hs:es:ds=\EF \r:fs=\r:ts=\EF:ws#46: X XFor a flash instead of a beep (this works for vi also): X :vb=\E`8\E`9: X XTerminfo users will need to adapt these. X XA brief history of hint is approximately as follows: X X-Originally written by Paul Borman, for the Heath/Zenith 29 terminal only. X-Rewritten by Mike Haertel, still for the H29 only. X-Simple terminal independence added by Walter Poxon and Jon Westbrock. X-Rewritten from scratch by David MacKenzie with an improved terminal X independence system and other enhancements. X XDavid MacKenzie <edf@rocky2.rockefeller.edu> END_OF_FILE if test 1576 -ne `wc -c <'README'`; then echo shar: \"'README'\" unpacked with wrong size! fi # end of 'README' fi if test -f 'hint.1' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'hint.1'\" else echo shar: Extracting \"'hint.1'\" \(4553 characters\) sed "s/^X//" >'hint.1' <<'END_OF_FILE' X.\" Copyright (C) 1989 David MacKenzie X.\" X.\" Permission is granted to make and distribute verbatim copies of this X.\" manual provided the copyright notice and this permission notice are X.\" preserved on all copies. X.\" X.\" Permission is granted to process this file through nroff or troff X.\" and print the results. X.\" X.\" Permission is granted to copy and distribute modified versions of X.\" this manual under the conditions for verbatim copying, provided that X.\" the entire resulting derived work is distributed under the terms of X.\" a permission notice identical to this one. X.\" X.\" Permission is granted to copy and distribute translations of this X.\" manual into another language, under the above conditions for X.\" modified versions. X.TH HINT 1L X.SH NAME Xhint \- send a one-line message to other users X.SH SYNOPSIS X\fBhint\fR [ \fB\-fp\fR ] [ \fB\-d sec\fR ] X\fBuser\fR|\fBtty\fR[\fB,user\fR|\fBtty\fR...] [ \fBmessage\fR ] X.br X\fBhint \-y\fR [ \fB\-bs\fR ] [ \fB\-T termtype\fR ] X.br X\fBhint \-n\fR X.br X\fBhint \-V\fR X.br X\fBhint\fR X.SH DESCRIPTION X.I hint Xsends a one-line message to one or more other users. The message Xappears along with the sender's user name and a beep (or, if possible, Xa ``visual bell'' such as flashing the screen) on the status line of Xthe recipient's terminal, and disappears after 10 seconds. If the Xrecipient's terminal does not have a status line, hints appear wherever Xthe cursor happens to be when they are received. X.PP XIf X.I hint Xis run with no arguments, it displays the user's current hint status, Xwhich is either X.B y Xor X.BR n , Xmeaning the user is allowing or refusing hints, respectively. The hint Xstatus is independent of the X.BR mesg (1) Xstatus. X.PP XIf one or more user names (e.g., \fIdave\fR) Xor terminal names (e.g., \fItty10\fR) Xare given (separated by commas but no spaces), any Xarguments after them are taken to be the message to send. If Xthe message is not given on the command line, X.I hint Xprompts for the message from the keyboard. X.PP X.I hint Xsends the message to all terminals where each given user Xis logged on and all terminals given directly. X.I hint Xskips users who are not logged in and hint X.B y Xand terminals that are not hint X.BR y , Xand sends the message to whatever users and terminals remain. X.SS OPTIONS X.PP XThe following options are used when setting the hint status: X.TP X.I \-y XAllow receipt of hints; no hint is sent. This option saves the codes Xfor accessing your terminal's status line, as read from the X.BR termcap (5) Xor X.BR terminfo (4) Xdatabase (whichever is available), Xinto an entry in the file /usr/local/lib/hinttab. X.TP X.I \-b XForce hints that you receive to beep even if a ``visual bell'' is available. XHas no effect if the X.I \-y Xoption is not also given. X.TP X.I \-s XForce hints that you receive to be silent; a ``visual bell'' will be used Xif available. If both X.I \-b Xand X.I \-s Xare given, neither a beep nor a ``visual bell'' will be used. XHas no effect if the X.I \-y Xoption is not also given. X.TP X.I \-T termtype XUse X.I termtype Xas the terminal type. XHas no effect if the X.I \-y Xoption is not also given. X.TP X.I \-n XRefuse receipt of hints; no hint is sent. X.PP XThe following options are used when sending a hint: X.TP X.I \-f XMake the hint last forever (until overwritten or cleared). This option Xoverrides any X.I \-d Xoption given. X.TP X.I \-p XMake the sender's name appear preceding the hint, enclosed in parentheses, Xrather than after the hint, following a dash. X.TP X.I \-d sec XChange the hint duration from 10 seconds to X.I sec Xseconds. X.I sec Xis not allowed to be less than 5 or greater than 60. X.PP XAdditional options: X.TP X.I \-V XDisplay the version number of the X.I hint Xprogram; no other action is taken. X.SS ENVIRONMENT X.PP XAll options except X.IR \-y , X.IR \-n , Xand X.I -V Xcan be given defaults by setting the X.B HINT Xenvironment variable. XFor example, to change the default duration Xof hints that you send from 10 seconds to 15 seconds, and always Xreceive silent hints, you could use: X.sp X.RS XFor the C shell: X.br Xsetenv HINT "-d15 -s" X.sp XFor the Bourne and Korn shells: X.br XHINT="-d15 -s"; export HINT X.RE X.SH FILES X/usr/local/lib/hinttab X.SH "SEE ALSO" X.BR clearhint (1L), X.BR hall (1L), X.BR mesg (1), X.BR write (1), X.BR terminfo (4), X.BR termcap (5) X.SH BUGS XIf a hint is sent to several terminals which have different length Xstatus lines, the message will be truncated on all of the terminals to Xthe length of the shortest status line, so that everyone gets the same hint. X.PP XThere is no network support. X.SH AUTHOR XDavid MacKenzie END_OF_FILE if test 4553 -ne `wc -c <'hint.1'`; then echo shar: \"'hint.1'\" unpacked with wrong size! fi # end of 'hint.1' fi if test -f 'clearhint.1' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'clearhint.1'\" else echo shar: Extracting \"'clearhint.1'\" \(1612 characters\) sed "s/^X//" >'clearhint.1' <<'END_OF_FILE' X.\" Copyright (C) 1989 David MacKenzie X.\" X.\" Permission is granted to make and distribute verbatim copies of this X.\" manual provided the copyright notice and this permission notice are X.\" preserved on all copies. X.\" X.\" Permission is granted to process this file through nroff or troff X.\" and print the results. X.\" X.\" Permission is granted to copy and distribute modified versions of X.\" this manual under the conditions for verbatim copying, provided that X.\" the entire resulting derived work is distributed under the terms of X.\" a permission notice identical to this one. X.\" X.\" Permission is granted to copy and distribute translations of this X.\" manual into another language, under the above conditions for X.\" modified versions. X.TH CLEARHINT 1L X.SH NAME Xclearhint \- erase terminal's status line X.SH SYNOPSIS X.B clearhint X[ X.B \-T terminal X] X.SH DESCRIPTION X.I clearhint Xerases the status Xline (usually a ``25th line'') of the user's terminal. If the terminal Xdoes not have a status line, X.I clearhint Xdoes nothing. The program Xis named for its main use, which is erasing messages sent by the X.BR hint (1L) Xprogram with the X.I \-f X(make the hint last forever) option given. X.PP X.I clearhint Xuses the X.BR termcap (5) Xor X.BR terminfo (4) Xdatabase (whichever is available) to determine how to move the cursor to the Xstatus line of each user's terminal. X.SS OPTIONS X.TP X.I \-T terminal XUse X.I terminal Xas the terminal type instead of the value given by the X.B TERM Xenvironment variable. X.SH "SEE ALSO" X.BR hall (1L), X.BR hint (1L), X.BR terminfo (4), X.BR termcap (5) X.SH AUTHOR XDavid MacKenzie END_OF_FILE if test 1612 -ne `wc -c <'clearhint.1'`; then echo shar: \"'clearhint.1'\" unpacked with wrong size! fi # end of 'clearhint.1' fi if test -f 'hall.1' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'hall.1'\" else echo shar: Extracting \"'hall.1'\" \(1161 characters\) sed "s/^X//" >'hall.1' <<'END_OF_FILE' X.\" Copyright (C) 1989 David MacKenzie X.\" X.\" Permission is granted to make and distribute verbatim copies of this X.\" manual provided the copyright notice and this permission notice are X.\" preserved on all copies. X.\" X.\" Permission is granted to process this file through nroff or troff X.\" and print the results. X.\" X.\" Permission is granted to copy and distribute modified versions of X.\" this manual under the conditions for verbatim copying, provided that X.\" the entire resulting derived work is distributed under the terms of X.\" a permission notice identical to this one. X.\" X.\" Permission is granted to copy and distribute translations of this X.\" manual into another language, under the above conditions for X.\" modified versions. X.TH HALL 1L X.SH NAME Xhall - hint all users logged on X.SH SYNOPSIS X.B hall X[ X.B message X] X.SH DESCRIPTION X.I hall Xsends a hint message to everyone who is logged on to the Xmachine where it is run and who is hint X.BR y . XIf no message is given on the command line, X.I hall Xprompts for one. X.SH FILES X.TP X/etc/utmp Xlist of who is logged on X.SH "SEE ALSO" X.BR clearhint (1L), X.BR hint (1L) X.SH AUTHOR XDavid MacKenzie END_OF_FILE if test 1161 -ne `wc -c <'hall.1'`; then echo shar: \"'hall.1'\" unpacked with wrong size! fi # end of 'hall.1' fi if test -f 'MANIFEST' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'MANIFEST'\" else echo shar: Extracting \"'MANIFEST'\" \(672 characters\) sed "s/^X//" >'MANIFEST' <<'END_OF_FILE' X File Name Archive # Description X----------------------------------------------------------- X README 1 X hint.1 1 X clearhint.1 1 X hall.1 1 X MANIFEST 1 This shipping list X main.c 1 X hint.h 1 X hinttab.c 1 X hinttab.h 1 X stov.c 1 X stov.h 1 X str.c 1 X tty.c 2 X user.c 1 X clearhint.c 2 X hall.sh 1 X Makefile 2 X COPYING 2 END_OF_FILE if test 672 -ne `wc -c <'MANIFEST'`; then echo shar: \"'MANIFEST'\" unpacked with wrong size! fi # end of 'MANIFEST' fi if test -f 'main.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'main.c'\" else echo shar: Extracting \"'main.c'\" \(10862 characters\) sed "s/^X//" >'main.c' <<'END_OF_FILE' X/* main.c -- argument parser and control loops X Copyright (C) 1989 David MacKenzie X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 1, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software X Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ X X/* hint - send a one-line message to other users X X Usage: hint [-fp] [-d sec] user|tty[,user|tty...] [message] X hint -y [-bs] [-T terminal] X hint -n X hint -V X hint X X Options: X -f make hint last forever, until overwritten X -p put sender's name at beginning of hint instead of end X -d duration in seconds (5 <= sec <= 60) before hint is erased (default 10) X X -y enable receipt of hints X -b don't use a visual bell (can still use audible bell) X -s don't use an audible bell (can still use visual bell) X -T specify terminal type, overriding $TERM X X -n disable receipt of hints X X -V display program version number X X With no arguments, displays the current hint status. X X David MacKenzie <edf@rocky2.rockefeller.edu> X Latest revision: 08/24/89 */ X X#define ALLOCATE /* Allocate global variables in hint.h. */ X X#include "hint.h" X X/* Hint status to set if 'y' or 'n'. */ Xstatic int new_stats; X X/* The hint message can be no longer than this. */ Xstatic int length_limit; X X/* Head of linked list of ttys to hint. */ Xstatic struct ttylist *tty_list; X Xint Xmain (argc, argv) X int argc; X char **argv; X{ X extern int optind; X struct ttylist *tp; /* A ttylist entry. */ X char temp_message[MAX_MESSAGE]; /* Hint read from tty. */ X int i; /* To reset `optind' between uses. */ X X program_name = argv[0] = basename (argv[0]); X new_stats = 0; X length_limit = MAX_MESSAGE - 1; X X if (argc == 1) X { X show_status (); X exit (0); X } X X if (chdir ("/dev") == -1) X pfatal ("Cannot change directory to /dev"); X X term = getenv ("TERM"); X /* Some implementations of getopt seem to start out with `optind' == 0, X while others start out with `optind' == 1. Whatever it starts out as, X we save it and then restore it. */ X i = optind; X parse_environment (); X optind = i; X parse_options (argc, argv, 1); X X if (new_stats) X { X if (argc < optind) X usage (); X set_status (new_stats); X exit (0); X } X X /* Check for user|tty[,user|tty...]. */ X if (optind < argc) X add_recipients (argv[optind++]); X if (tty_list == NULL) X { X fprintf (stderr, "%s: No ttys to hint\n", program_name); X exit (1); X } X endhtent (); X X length_limit -= 11; /* 8 for username + 3 for punctuation. */ X if (length_limit < 11) X length_limit = 11; /* Let's be reasonable. */ X X /* Check for message. */ X if (optind < argc) X for (; optind < argc; ++optind) X { X append_word (argv[optind]); X if (optind < argc - 1) X append_word (" "); X } X else X { X prompt (); X fgets (temp_message, MAX_MESSAGE, stdin); X append_word (temp_message); X } X X set_signals (); X /* Send the hint to all relevant ttys. */ X while (tp = next_tty ()) X sendhint (tp); X X if (forever) X exit (0); X switch (fork ()) X { X case -1: X pfatal ("Cannot fork"); X case 0: /* Child. */ X sleep (duration); X while (tp = next_tty ()) X erasehint (tp); X } X exit (0); X /* NOTREACHED */ X} X Xvoid Xparse_environment () X{ X char *enval; X struct args *argsp; X char *s; /* program_name + enval. */ X X enval = getenv (ENVAR); X if (enval && *enval) X { X s = xmalloc ((unsigned) (strlen (enval) + strlen (program_name) + 2)); X strcpy (s, program_name); X strcat (s, " "); X strcat (s, enval); X argsp = stov (s); X parse_options (argsp->argc, argsp->argv, 0); X free (s); X } X} X X/* If `cmdline' is nonzero, this function was called with command line X arguments; otherwise they were taken from the environment. */ X Xvoid Xparse_options (argc, argv, cmdline) X int argc; X char **argv; X int cmdline; X{ X extern int optind; X extern char *optarg; X int c; X X while ((c = getopt (argc, argv, "ynbfpsd:T:V")) != EOF) X { X switch (c) X { X case 'y': X case 'n': X if (cmdline) X new_stats = c; X else X ignored (c); X break; X case 'b': X use_vbell = 0; X break; X case 'f': X forever = 1; X break; X case 'p': X name_at_end = 0; X break; X case 's': X use_bell = 0; X break; X case 'd': X duration = atoi (optarg); X if (duration < MIN_SEC || duration > MAX_SEC) X { X fprintf (stderr, X "%s: %d: Duration out of range (%d-%d seconds)\n", X program_name, duration, MIN_SEC, MAX_SEC); X exit (1); X } X break; X case 'T': X term = optarg; X break; X case 'V': X if (cmdline) X { X fprintf (stderr, "hint, version 3.5\n"); X exit (0); X } X else X ignored (c); X break; X default: X if (cmdline) X usage (); X else X fprintf (stderr, "%s: Invalid option in environment ignored\n", X program_name); X break; X } X } X} X X/* Display a prompt that attempts to be as long as `length_limit'. */ X Xvoid Xprompt () X{ X static char *prompt_string = "[ Enter message (max. %d characters):"; X int prompt_length; X X printf (prompt_string, length_limit); X /* Set prompt_length to length of the prompt except for trailing spaces. */ X prompt_length = strlen (prompt_string) + 1; /* The 1 is the ']'. */ X if (length_limit > 99) X ++prompt_length; /* Adjust for the extra digit. */ X if (prompt_length > length_limit) X prompt_length = length_limit; X printf ("%*s]\n", length_limit - prompt_length, " "); X fflush (stdout); X} X X/* Print the program name, `s', and a system error message, and die. */ X Xvoid Xpfatal (s) X char *s; X{ X fprintf (stderr, "%s: ", program_name); X perror (s); X exit (1); X} X X/* Same but stay alive. */ X Xvoid Xpnonfatal (s) X char *s; X{ X fprintf (stderr, "%s: ", program_name); X perror (s); X} X Xvoid Xshow_status () X{ X char *tty; X X tty = ttyname (2); /* Stderr is least likely to be redirected. */ X if (tty == NULL) X pfatal ("Cannot get ttyname"); X printf ("is %c\n", hintable (tty) ? 'y' : 'n'); X} X X/* Set hint status. X `newstat' can be 'y' or 'n'. */ X Xvoid Xset_status (newstat) X char newstat; X{ X struct stat tty_stats; X char *tty; X X tty = ttyname (2); X if (tty == NULL) X pfatal ("Cannot get ttyname"); X if (stat (tty, &tty_stats) < 0) X pfatal (tty); X X if (newstat == 'y') X { X tty_stats.st_mode |= HINTBIT; X updatetab (tty); X } X else X tty_stats.st_mode &= ~HINTBIT; X if (chmod (tty, tty_stats.st_mode) < 0) X pfatal (tty); X} X X/* Return true if `tty' is hint y, false otherwise. */ X Xint Xhintable (tty) X char *tty; X{ X struct stat tty_stats; X X if (stat (tty, &tty_stats) < 0) X { X pnonfatal (tty); X return 0; /* Cannot stat; assume they're hint n. */ X } X return tty_stats.st_mode & HINTBIT; X} X X/* Return true if `name' is a tty device in /dev. */ X Xint Xistty (name) X char *name; X{ X struct stat stats; X char *path; X int i; X X path = xmalloc (strlen (name) + 3); X strcpy (path, "./"); X strcat (path, name); X i = stat (path, &stats); X free (path); X if (i == -1 || (stats.st_mode & S_IFMT) != S_IFCHR) X return 0; X else X return 1; X} X Xvoid Xadd_recipients (names) X char *names; X{ X char *name; X X for (name = strtok (names, ","); name; name = strtok ((char *) NULL, ",")) X if (istty (name)) X { X addtty ("user", name); X } X else X { X /* Add any ttys where user `name' is logged on to `tty_list'. */ X if (adduser (name) == 0) X fprintf (stderr, "%s: %s is not logged on\n", program_name, name); X } X} X X/* Add `user' at `tty' (which should have no leading path) to the list of X ttys to send the hint to. */ X Xvoid Xaddtty (user, tty) X char *user; X char *tty; X{ X struct ttylist *tp; X struct hinttab *ht; X char *ttypath; X X /* Make sure they haven't already been added. */ X for (tp = tty_list; tp; tp = tp->tt_next) X if (!strcmp (tp->tt_tty, tty)) X return; X X if (!hintable (tty)) X { X /* They're hint n. */ X fprintf (stderr, "%s: %s on %s is refusing hints\n", X program_name, user, tty); X return; X } X X sethtent (); /* Rewind hinttab file. */ X X ttypath = xmalloc ((unsigned) (strlen (tty) + 6)); X strcpy (ttypath, "/dev/"); X strcat (ttypath, tty); X ht = gethttty (ttypath); X free (ttypath); X X if (ht == NULL) X { X fprintf (stderr, "%s: No hinttab entry for %s\n", program_name, tty); X return; X } X X tp = (struct ttylist *) xmalloc (sizeof (struct ttylist)); X tp->tt_user = strdup (user); X tp->tt_tty = strdup (tty); X tp->tt_ht = *ht; X X tp->tt_next = tty_list; X tty_list = tp; X X /* Keep track of the shortest status line we'll be hinting. */ X if (length_limit > tp->tt_ht.h_ws) X length_limit = tp->tt_ht.h_ws; X} X X/* Return the next tty in the list. X Return NULL if the list is empty. */ X Xstruct ttylist * Xnext_tty () X{ X static struct ttylist *tp = NULL; X X tp = tp ? tp->tt_next : tty_list; X X return tp; X} X Xvoid Xset_signals () X{ X#ifdef SIGTTOU X signal (SIGTTOU, SIG_IGN); X#endif X /* If the sender logs out right after hinting, stick around to erase the X hint. */ X signal (SIGHUP, SIG_IGN); X signal (SIGINT, SIG_IGN); X} X X/* Concatenate `word' onto the end of the hint message, silently truncating X if it would overflow `length_limit', and removing any control X characters. */ X Xvoid Xappend_word (word) X char *word; X{ X static int message_length = 0;/* Length of message. */ X X for (; *word && message_length < length_limit; ++word) X if (isascii (*word) && isprint (*word)) X message[message_length++] = *word; X message[message_length] = 0; X} X X/* Return a malloc'd duplicate of string `s'. */ X Xchar * Xstrdup (s) X char *s; X{ X return strcpy (xmalloc ((unsigned) (strlen (s) + 1)), s); X} X X/* Return `name' with any leading path stripped off. */ X Xchar * Xbasename (name) X char *name; X{ X char *base; X X base = strrchr (name, '/'); X return base ? base + 1 : name; X} X Xvoid Xignored (c) X char c; X{ X fprintf (stderr, "%s: Option ignored in environment: -%c\n", program_name, c); X} X Xvoid Xusage () X{ X fprintf (stderr, X "Usage: %s [-fp] [-d sec] user|tty[,user|tty...] [message]\n", X program_name); X fprintf (stderr, " %s -y [-bs] [-T termtype]\n", program_name); X fprintf (stderr, " %s -n\n", program_name); X fprintf (stderr, " %s -V\n", program_name); X fprintf (stderr, " %s\n", program_name); X exit (1); X} END_OF_FILE if test 10862 -ne `wc -c <'main.c'`; then echo shar: \"'main.c'\" unpacked with wrong size! fi # end of 'main.c' fi if test -f 'hint.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'hint.h'\" else echo shar: Extracting \"'hint.h'\" \(3447 characters\) sed "s/^X//" >'hint.h' <<'END_OF_FILE' X/* hint.h -- constant, variable and function declarations X Copyright (C) 1989 David MacKenzie X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 1, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software X Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ X X#ifndef USG X#define strrchr rindex X#endif X X/* Enforced limits on hint duration. */ X#define MIN_SEC 5 X#define MAX_SEC 60 X X/* Maximum length of message (who has terminals wider than this?). */ X#define MAX_MESSAGE 400 X X/* Default status line width if not defined in termcap. */ X#define DEF_WS 78 X X/* The bit that determines hint y or n. */ X#define HINTBIT 00010 X X/* Environment variable to check for options. */ X#define ENVAR "HINT" X X#include <stdio.h> X#include <sys/types.h> X#include <sys/stat.h> X#include <ctype.h> X#include <pwd.h> X#include <fcntl.h> X#include <signal.h> X#ifdef USG X#include <termio.h> X#else X#include <sgtty.h> X#endif X X#include "stov.h" X#include "hinttab.h" X X/* List of ttys to send hint to. */ Xstruct ttylist X{ X char *tt_user; X char *tt_tty; /* Contains no leading path. */ X struct hinttab tt_ht; X struct ttylist *tt_next; X}; X X#ifdef ALLOCATE X#define EXTERN X#define INIT(x) = {x} X#else X#define EXTERN extern X#define INIT(x) X#endif X X/* Base of the name this program was run with. */ XEXTERN char *program_name; X X/* Terminal type. */ XEXTERN char *term; X X/* The hint to send. */ XEXTERN char message[MAX_MESSAGE]; X X/* If nonzero, put the name at the start of the hint. */ XEXTERN int name_at_end INIT (1); X X/* If nonzero, erase the hint. */ XEXTERN int forever INIT (0); X X/* If nonzero, try to use bell capability. */ XEXTERN int use_bell INIT (1); X X/* If nonzero, try to use visual bell capability. */ XEXTERN int use_vbell INIT (1); X X/* Seconds between sending the hint and erasing it. */ XEXTERN int duration INIT (10); X Xchar *getenv (); Xchar *getlogin (); Xchar *malloc (); Xchar *realloc (); Xchar *strcat (); Xchar *strcpy (); Xchar *strncat (); Xchar *strncpy (); Xchar *strrchr (); Xchar *strtok (); Xchar *tgetstr (); Xchar *tgoto (); Xchar *ttyname (); Xint strcspn (); Xint strspn (); Xoff_t lseek (); Xstruct passwd *getpwuid (); Xunsigned sleep (); Xvoid perror (); Xvoid exit (); Xvoid free (); X Xchar *basename (); Xchar *pwname (); Xchar *strdup (); Xchar *whoami (); Xchar *xmalloc (); Xchar *xrealloc (); Xint addmatch (); Xint adduser (); Xint buffer_char (); Xint hintable (); Xint istty (); Xstruct args *stov (); Xstruct hinttab *gethttty (); Xstruct ttylist *next_tty (); Xvoid add_recipients (); Xvoid addtty (); Xvoid append_word (); Xvoid buffer_string (); Xvoid endhtent (); Xvoid erasehint (); Xvoid flush_buffer (); Xvoid get_speed (); Xvoid ignored (); Xvoid init_buffer (); Xvoid parse_environment (); Xvoid parse_options (); Xvoid pfatal (); Xvoid pnonfatal (); Xvoid prompt (); Xvoid sendhint (); Xvoid set_signals (); Xvoid set_status (); Xvoid sethtapp (); Xvoid sethtent (); Xvoid setup_termcap (); Xvoid show_status (); Xvoid updatetab (); Xvoid usage (); Xvoid writehtent (); END_OF_FILE if test 3447 -ne `wc -c <'hint.h'`; then echo shar: \"'hint.h'\" unpacked with wrong size! fi # end of 'hint.h' fi if test -f 'hinttab.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'hinttab.c'\" else echo shar: Extracting \"'hinttab.c'\" \(2073 characters\) sed "s/^X//" >'hinttab.c' <<'END_OF_FILE' X/* hinttab.c -- functions for dealing with hinttab X Copyright (C) 1989 David MacKenzie X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 1, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software X Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ X X#include "hint.h" X Xstatic int fd = -1; Xstatic off_t offset; X X/* Open (rewind if already open) the hinttab for reading and writing. */ X Xvoid Xsethtent () X{ X if (fd == -1) X { X fd = open (HINTTAB, O_RDWR); X if (fd == -1) X pfatal (HINTTAB); X } X else X { X offset = 0; X if (lseek (fd, offset, 0) == -1) X pfatal (HINTTAB); X } X} X X/* Open the hinttab for appending. */ X Xvoid Xsethtapp () X{ X if (fd != -1) X close (fd); X fd = open (HINTTAB, O_WRONLY | O_APPEND); X if (fd == -1) X pfatal (HINTTAB); X offset = 0; X} X X/* Return a pointer to the hinttab entry matching `tty', or X NULL if none do. X The offset into hinttab will be left pointing to the start of the X matching entry. */ X Xstruct hinttab * Xgethttty (tty) X char *tty; X{ X static struct hinttab h; X X while (offset = lseek (fd, (off_t) 0, 1), X read (fd, &h, sizeof (h)) == sizeof (h)) X { X if (!strcmp (tty, h.h_tty)) X { X /* Seek back to the start of the record. */ X lseek (fd, offset, 0); X return &h; X } X } X return NULL; X} X X/* Update the current entry (the last one matched by gethttty). */ X Xvoid Xwritehtent (h) X struct hinttab *h; X{ X if (write (fd, h, sizeof (*h)) != sizeof (*h)) X pfatal (HINTTAB); X} X X/* Close the hinttab. */ X Xvoid Xendhtent () X{ X close (fd); X fd = -1; X} END_OF_FILE if test 2073 -ne `wc -c <'hinttab.c'`; then echo shar: \"'hinttab.c'\" unpacked with wrong size! fi # end of 'hinttab.c' fi if test -f 'hinttab.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'hinttab.h'\" else echo shar: Extracting \"'hinttab.h'\" \(1411 characters\) sed "s/^X//" >'hinttab.h' <<'END_OF_FILE' X/* hinttab.h -- declarations for accessing the hinttab file X Copyright (C) 1989 David MacKenzie X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 1, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software X Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ X X/* Maximum length of termcap strings. */ X#define TCSLEN 20 X X/* Structure of record in hinttab. X These are the strings returned by tgetstr. They will be run through X tputs when the hint is actually sent. X X Records are assigned in hinttab in first come, first served order. */ Xstruct hinttab X{ X char h_tty[15]; /* Full pathname. */ X char h_ts[TCSLEN]; /* Go to status line. */ X char h_fs[TCSLEN]; /* Go from status line. */ X char h_ds[TCSLEN]; /* Disable (clear) status line. */ X char h_bl[TCSLEN]; /* Bell or visible bell. */ X short h_ws; /* Width (columns) of status line. */ X}; X Xstruct hinttab *gethttty (); END_OF_FILE if test 1411 -ne `wc -c <'hinttab.h'`; then echo shar: \"'hinttab.h'\" unpacked with wrong size! fi # end of 'hinttab.h' fi if test -f 'stov.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'stov.c'\" else echo shar: Extracting \"'stov.c'\" \(2409 characters\) sed "s/^X//" >'stov.c' <<'END_OF_FILE' X/* stov.c -- convert string to vector X Copyright (C) 1989 David MacKenzie X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 1, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software X Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ X X#include "hint.h" X X/* Number of arguments between realloc's. */ X#define GRANULARITY 10 X X/* Make an argv-like vector (string array) from string `s' (such as an X environment variable). The last element of the vector is null. X Return a static structure with a malloc'd array of pointers into `s'. X Scatters nulls throughout `s'. */ X Xstruct args * Xstov (s) X char *s; X{ X static struct args args; X int argc; X char **argv; X X argc = 0; X argv = (char **) xmalloc ((unsigned) (sizeof (char *) * GRANULARITY)); X X for (s = strtok (s, " \t\n\r"); s; s = strtok ((char *) NULL, " \t\n\r")) X { X if (argc > 0 && argc % GRANULARITY == 0) X argv = (char **) xrealloc ((char *) argv, X (unsigned) (sizeof (char *) * (argc + GRANULARITY))); X argv[argc++] = s; X } X argv = (char **) xrealloc ((char *) argv, X (unsigned) (sizeof (char *) * (argc + 1))); X argv[argc] = NULL; X args.argc = argc; X args.argv = argv; X return &args; X} X Xstatic void Xmemory_out () X{ X fprintf (stderr, "%s: Virtual memory exhausted\n", program_name); X exit (1); X} X X/* Allocate `n' bytes of memory dynamically, with error checking. */ X Xchar * Xxmalloc (n) X unsigned n; X{ X char *p; X X p = malloc (n); X if (p == 0) X memory_out (); X return p; X} X X/* Change the size of an allocated block of memory `p' to `n' bytes, X with error checking. X If `p' is NULL, run xmalloc. X If `n' is 0, run free and return NULL. */ X Xchar * Xxrealloc (p, n) X char *p; X unsigned n; X{ X if (p == 0) X return xmalloc (n); X if (n == 0) X { X free (p); X return 0; X } X p = realloc (p, n); X if (p == 0) X memory_out (); X return p; X} END_OF_FILE if test 2409 -ne `wc -c <'stov.c'`; then echo shar: \"'stov.c'\" unpacked with wrong size! fi # end of 'stov.c' fi if test -f 'stov.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'stov.h'\" else echo shar: Extracting \"'stov.h'\" \(880 characters\) sed "s/^X//" >'stov.h' <<'END_OF_FILE' X/* stov.h -- declarations for using stov function X Copyright (C) 1989 David MacKenzie X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 1, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software X Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ X X/* Structure for return value of stov. */ Xstruct args X{ X int argc; X char **argv; X}; X Xstruct args *stov (); END_OF_FILE if test 880 -ne `wc -c <'stov.h'`; then echo shar: \"'stov.h'\" unpacked with wrong size! fi # end of 'stov.h' fi if test -f 'str.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'str.c'\" else echo shar: Extracting \"'str.c'\" \(2222 characters\) sed "s/^X//" >'str.c' <<'END_OF_FILE' X/* str.c -- string functions missing from BSD X Copyright (C) 1989 David MacKenzie X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 1, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software X Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ X X#define NULL 0 X Xchar *index (); X X/* Return the length of the span of characters at the start of `string' X that are members of `class'. */ X Xint Xstrspn (string, class) X char *string; X char *class; X{ X int count; X X for (count = 0; string[count]; ++count) X if (!index (class, string[count])) X break; X return count; X} X X/* Return the length of the span of characters at the start of `string' X that are non-members of `class'. */ X Xint Xstrcspn (string, class) X char *string; X char *class; X{ X int count; X X for (count = 0; string[count]; ++count) X if (index (class, string[count])) X break; X return count; X} X X/* Return the next token in `string', delimited by one or more members of X the set `separators'. If `string' is NULL, use the same string as in the X last call. */ X Xchar * Xstrtok (string, separators) X char *string; X char *separators; X{ X static char *pos = NULL; /* Current location in the string. */ X int token_length; X X if (string) X pos = string; X pos += strspn (pos, separators); /* Skip initial separators. */ X token_length = strcspn (pos, separators); /* Find token length. */ X if (token_length == 0) X return NULL; /* No more tokens; pos is on a 0. */ X separators = pos; /* Re-use separators to save start of token. */ X pos += token_length; /* Move onto the 0. */ X if (*pos) /* If not the last token, */ X *pos++ = 0; /* null terminate the token. */ X return separators; X} END_OF_FILE if test 2222 -ne `wc -c <'str.c'`; then echo shar: \"'str.c'\" unpacked with wrong size! fi # end of 'str.c' fi if test -f 'user.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'user.c'\" else echo shar: Extracting \"'user.c'\" \(1906 characters\) sed "s/^X//" >'user.c' <<'END_OF_FILE' X/* user.c -- functions dealing with logins X Copyright (C) 1989 David MacKenzie X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 1, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software X Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ X X#include "hint.h" X#include <utmp.h> X X/* Add all ttys where `user' is logged on to the list of ttys to hint. X Return the number of times `user' is logged on. */ X Xint Xadduser (user) X char *user; X{ X struct utmp ut; X int nfound; /* Number of times `user' is logged on. */ X int fd; X X fd = open ("/etc/utmp", O_RDONLY); X if (fd == -1) X pfatal ("/etc/utmp"); X X nfound = 0; X while (read (fd, &ut, sizeof (struct utmp)) > 0) X nfound += addmatch (user, &ut); X X close (fd); X return nfound; X} X X/* If the name field in `utp' matches `user' and the tty is hint y, X add the `utp' tty field to the list of ttys to hint and return 1; X else, X return 0. */ X Xint Xaddmatch (user, utp) X char *user; X struct utmp *utp; X{ X char temp_line[30]; /* 30 is random number > max. ut_line size. */ X X /* Make sure it's a valid entry. */ X if (*utp->ut_name == 0) X return 0; X X if (!strncmp (user, utp->ut_name, sizeof (utp->ut_name))) X { X strncpy (temp_line, utp->ut_line, sizeof (utp->ut_line)); X temp_line[sizeof (utp->ut_line)] = 0; X addtty (user, temp_line); X return 1; X } X else X return 0; X} END_OF_FILE if test 1906 -ne `wc -c <'user.c'`; then echo shar: \"'user.c'\" unpacked with wrong size! fi # end of 'user.c' fi if test -f 'hall.sh' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'hall.sh'\" else echo shar: Extracting \"'hall.sh'\" \(1009 characters\) sed "s/^X//" >'hall.sh' <<'END_OF_FILE' X#!/bin/sh X# hall -- hint all users logged in X# Copyright (C) 1989 David MacKenzie X# X# This program is free software; you can redistribute it and/or modify X# it under the terms of the GNU General Public License as published by X# the Free Software Foundation; either version 1, or (at your option) X# any later version. X# X# This program is distributed in the hope that it will be useful, X# but WITHOUT ANY WARRANTY; without even the implied warranty of X# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X# GNU General Public License for more details. X# X# You should have received a copy of the GNU General Public License X# along with this program; if not, write to the Free Software X# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. X X# Usage: hall [message] X# David MacKenzie X# Latest revision: 08/23/89 X Xecho 'Making list of everyone logged on . . .' Xusers=`who|awk '{ if (NR > 1) printf ","; printf "%s", $1 }'` Xif [ $# -eq 0 ] Xthen X hint $users Xelse X hint $users "$@" Xfi END_OF_FILE if test 1009 -ne `wc -c <'hall.sh'`; then echo shar: \"'hall.sh'\" unpacked with wrong size! fi chmod +x 'hall.sh' # end of 'hall.sh' fi echo shar: End of archive 1 \(of 2\). cp /dev/null ark1isdone MISSING="" for I in 1 2 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked both archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0