adding zephyr-im master branch

This commit is contained in:
2022-07-25 09:01:27 -06:00
parent 61f5ed8f01
commit ee1236fa5c
311 changed files with 62265 additions and 0 deletions

13
clients/Makefile.in Normal file
View File

@ -0,0 +1,13 @@
SHELL = /bin/sh
SUBDIRS=zaway zctl zleave zlocate znol \
zshutdown_notify zstat zwrite
all:
for i in ${SUBDIRS}; do (cd $$i; ${MAKE} $@) || exit 1; done
check install clean:
for i in ${SUBDIRS}; do (cd $$i; ${MAKE} $@) || exit 1; done
.PHONY: all check install clean

56
clients/zaway/Makefile.in Normal file
View File

@ -0,0 +1,56 @@
SHELL=@SHELL@
prefix=@prefix@
exec_prefix=@exec_prefix@
datadir=@datadir@
sysconfdir=@sysconfdir@
sbindir=@sbindir@
lsbindir=@lsbindir@
datarootdir=@datarootdir@
top_builddir=../..
includedir=@includedir@
mandir=@mandir@
libdir=@libdir@
bindir=@bindir@
srcdir=@srcdir@
top_srcdir=@top_srcdir@
BUILDTOP=../..
VPATH=@srcdir@
LIBTOOL=@LIBTOOL@
CC=@CC@
INSTALL=@INSTALL@
LIBZEPHYR=${BUILDTOP}/lib/libzephyr.la
CPPFLAGS=@CPPFLAGS@
CFLAGS=@CFLAGS@
ALL_CFLAGS=${CFLAGS} -I${top_srcdir}/h -I${BUILDTOP}/h ${CPPFLAGS}
LDFLAGS=@LDFLAGS@
LIBS=${LIBZEPHYR} @LIBS@ -lcom_err
OBJS= zaway.o
all: zaway
zaway: ${OBJS} ${LIBZEPHYR}
${LIBTOOL} --mode=link ${CC} ${LDFLAGS} -o $@ ${OBJS} ${LIBS}
.c.o:
${CC} -c ${ALL_CFLAGS} $<
check:
install: zaway
${LIBTOOL} --mode=install ${INSTALL} -m 755 zaway ${DESTDIR}${bindir}
${INSTALL} -m 644 ${srcdir}/zaway.1 ${DESTDIR}${mandir}/man1
clean:
${LIBTOOL} --mode=clean rm -f zaway
rm -f ${OBJS}
${OBJS}: ${top_srcdir}/h/sysdep.h ${BUILDTOP}/h/config.h
${OBJS}: ${BUILDTOP}/h/zephyr/zephyr.h ${BUILDTOP}/h/zephyr/zephyr_err.h
.PHONY: all check install clean

120
clients/zaway/zaway.1 Normal file
View File

@ -0,0 +1,120 @@
.\" $Id$
.\"
.\" Copyright 1987,1988 by the Massachusetts Institute of Technology
.\" All rights reserved. The file /usr/include/zephyr/mit-copyright.h
.\" specifies the terms and conditions for redistribution.
.\"
.\" @(#)zaway.1 6.1 (MIT) 7/9/87
.\"
.TH ZAWAY 1 "July 1, 1988" "MIT Project Athena"
.ds ]W MIT Project Athena
.SH NAME
zaway \- tell other people via Zephyr that you aren't around
.SH SYNOPSIS
.B zaway
[
.I OPTIONS
]
[
.I FILE
]
.SH DESCRIPTION
.I zaway
provides a way for you to automatically send replies when other people
contact you using
.I zwrite(1). zaway
subscribes itself to class "MESSAGE", instance "*", so that it can
monitor your incoming messages. It does not affect the operation of any
other client receiving messages.
.I zaway
is typically run when you are leaving your terminal or display
temporarily.
.I zaway
usually never exits; when you return to your terminal you should type
the interrupt character (usually ^C) in order to make
.I zaway
exit.
.SS OPTIONS
.TP
.I "\-m STRING"
Use STRING as the body of the auto-reply message. Any message file
(specified on the command line or the default) is ignored.
.TP
.I "\-w"
Watch the invoking user's location status. If the user is locatable
anywhere, no auto-replies will be sent.
.TP
.I "\-h"
Displays a short usage message and exits.
.PP
.I zaway
uses a message file (which defaults
to $HOME/.away) to describe what reponses should be sent to which
senders. The general format of this file
is:
.PP
.nf
>name
>name
message
>name
message
.fi
.PP
Any number of user names may be specified preceding the message to send
to those senders. If a user name appears more than once, the message will
be a concatenation of each of the appropriate messages. There are
two special names: "*" indicates that the following message should be
sent to all senders and "%" indicates that the following message should
only be sent if the user name has not matched yet.
.PP
If no file is specified,
and no default file can be found, the following message is returned:
.sp
.in +5
I'm sorry, but I am currently away from the terminal and am
not able to receive your message.
.in -5
.sp
If a user name does not match any of those listed in the file, and no
"*" or "%" field is specified, no return message is sent. All
messages are preceded by a signature "Automated reply:". To avoid
loops, messages are not sent in response to messages beginning with an
"Automated reply:" signature or sent by the same Kerberos principal as
the user running
.I zaway.
.SH SAMPLE FILE
.nf
>eichin
>tony
Hi there guys! I'm in the other room right now.
I'll be back in 5 minutes or so.
>jruser
Sorry, but I'm gone for the day...
>%
Hello...I'm not sure who you are. I'll be back soon,
though.
>*
This message comes to you compliments of zaway!
.fi
The final "compliments" message will be included in all messages,
whereas the "I'm not sure" message will only be included in messages that
are not from "eichin", "tony", or "jruser".
.SH FILES
$HOME/.away
.SH SEE ALSO
zephyr(1), zwgc(1), zwrite(1), zhm(8), zephyrd(8)
.br
Project Athena Technical Plan Section E.4.1, `Zephyr Notification
Service'
.SH AUTHOR
.PP
Robert S. French (MIT-Project Athena)
.SH RESTRICTIONS
Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.
All Rights Reserved.
.br
.I zephyr(1)
specifies the terms and conditions for redistribution.

270
clients/zaway/zaway.c Normal file
View File

@ -0,0 +1,270 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains code for the "zaway" command.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987, 1993 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#include <sysdep.h>
#include <zephyr/mit-copyright.h>
#include <zephyr/zephyr.h>
#include <pwd.h>
#ifndef lint
static const char rcsid_zaway_c[] = "$Id$";
#endif
#define MESSAGE_CLASS "MESSAGE"
#define DEFAULT_MSG "I'm sorry, but I am currently away from the terminal and am\nnot able to receive your message.\n"
#define RESPONSE_OPCODE ""
static char *find_message(ZNotice_t *, FILE *);
RETSIGTYPE cleanup(int);
u_short port;
static void
usage(char *name)
{
printf("Usage: %s [OPTIONS] [FILE]\n"
"\n"
" -m STRING use STRING as the body of the reply message\n"
" -w watch your location and only reply if you aren't locatable\n"
" -h display this help and exit\n",
name);
}
int
main(int argc,
char *argv[])
{
FILE *fp;
ZNotice_t notice;
ZSubscription_t sub;
register int retval;
struct passwd *pw;
register char *ptr;
char awayfile[BUFSIZ],*msg[2],*envptr;
int optchar, watch_location;
char *cmdline_msg;
int nlocs;
char *charset = NULL;
unsigned short zcharset;
#ifdef _POSIX_VERSION
struct sigaction sa;
#endif
if ((retval = ZInitialize()) != ZERR_NONE) {
com_err(argv[0],retval,"while initializing");
exit(1);
}
port = 0;
if ((retval = ZOpenPort(&port)) != ZERR_NONE) {
com_err(argv[0],retval,"while opening port");
exit(1);
}
sub.zsub_class = MESSAGE_CLASS;
sub.zsub_classinst = "*";
sub.zsub_recipient = ZGetSender();
cmdline_msg = 0;
watch_location = 0;
while ((optchar = getopt(argc, argv, "m:whx:")) != EOF) {
switch (optchar) {
case 'm':
cmdline_msg = optarg;
break;
case 'w':
watch_location = 1;
break;
case 'h':
usage(argv[0]);
return 0;
case 'x':
charset = optarg;
break;
case '?':
fprintf(stderr,
"Unrecognized option '-%c'.\n"
"Try '%s -h' for more information.\n",
optopt, argv[0]);
return 1;
}
}
zcharset = ZGetCharset(charset);
if (argc > optind)
(void) strcpy(awayfile,argv[optind]);
else {
envptr = getenv("HOME");
if (envptr)
(void) sprintf(awayfile,"%s/.away",envptr);
else {
if (!(pw = getpwuid((int) getuid()))) {
fprintf(stderr,"Who are you?\n");
exit(1);
}
(void) sprintf(awayfile,"%s/.away",pw->pw_dir);
}
}
fp = fopen(awayfile,"r");
if (!fp && argc > optind) {
fprintf(stderr,"File %s not found!\n",awayfile);
exit(1);
}
#ifdef _POSIX_VERSION
(void) sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = cleanup;
(void) sigaction(SIGINT, &sa, (struct sigaction *)0);
(void) sigaction(SIGTERM, &sa, (struct sigaction *)0);
(void) sigaction(SIGHUP, &sa, (struct sigaction *)0);
#else
(void) signal(SIGINT, cleanup);
(void) signal(SIGTERM, cleanup);
(void) signal(SIGHUP, cleanup);
#endif
if ((retval = ZSubscribeToSansDefaults(&sub,1,port)) != ZERR_NONE) {
com_err(argv[0],retval,"while subscribing");
exit(1);
}
for (;;) {
if ((retval = ZReceiveNotice(&notice, (struct sockaddr_in *)0)) != ZERR_NONE) {
if (retval != ETIMEDOUT)
com_err(argv[0],retval,"while receiving notice");
continue;
}
if (strcmp(notice.z_sender,ZGetSender()) == 0 ||
strcmp(notice.z_opcode,"PING") == 0 ||
strcmp(notice.z_opcode,"AUTO") == 0 ||
strcmp(notice.z_message,"Automated reply:") == 0) {
ZFreeNotice(&notice);
continue;
}
if (watch_location) {
if ((retval = ZLocateUser(ZGetSender(), &nlocs, ZNOAUTH))
!= ZERR_NONE) {
com_err(argv[0],retval,"while locating self");
continue;
}
if (nlocs != 0) {
/* User is logged in. Don't send an autoreply. */
continue;
}
ZFlushLocations();
}
if (cmdline_msg) {
ptr = strdup(cmdline_msg);
if (!ptr) {
com_err(argv[0],ENOMEM,"while getting cmdline message");
exit(1);
}
}
else if (fp) {
if (!(ptr = find_message(&notice,fp))) {
ZFreeNotice(&notice);
continue;
}
}
else {
ptr = malloc(sizeof(DEFAULT_MSG)+1);
if (!ptr) {
com_err(argv[0],ENOMEM,"while getting default message");
exit(1);
}
(void) strcpy(ptr,DEFAULT_MSG);
}
notice.z_recipient = notice.z_sender;
notice.z_sender = 0;
notice.z_default_format = "";
notice.z_opcode = RESPONSE_OPCODE;
notice.z_charset = zcharset;
msg[0] = "Automated reply:";
msg[1] = ptr;
notice.z_message_len = strlen(notice.z_message)+1;
if ((retval = ZSendList(&notice,msg,2,ZNOAUTH)) != ZERR_NONE) {
com_err(argv[0],retval,"while sending notice");
}
free(ptr);
ZFreeNotice(&notice);
}
}
char *
find_message(ZNotice_t *notice,
FILE *fp)
{
char *ptr,*ptr2;
char bfr[BUFSIZ],sender[BUFSIZ];
int gotone,lastwasnt;
rewind(fp);
(void) strcpy(sender,notice->z_sender);
ptr2 = strchr(sender,'@');
if (ptr2)
*ptr2 = '\0';
ptr = 0;
gotone = 0;
lastwasnt = 0;
while (fgets(bfr,sizeof bfr,fp) != (char *)0) {
if (*bfr == '>') {
if (lastwasnt)
gotone = 0;
bfr[strlen(bfr)-1] = '\0';
ptr2 = strchr(bfr,'@');
if (ptr2)
*ptr2 = '\0';
if (!strcmp(bfr+1,sender) ||
!strcmp(bfr+1,"*") ||
(!strcmp(bfr+1,"%") && !ptr))
gotone = 1;
lastwasnt = 0;
}
else {
if (gotone) {
if (!ptr) {
ptr = malloc((unsigned)(strlen(bfr)+1));
*ptr = '\0';
}
else
ptr = realloc(ptr,(unsigned)(strlen(bfr)+strlen(ptr)+1));
(void) strcat(ptr,bfr);
}
lastwasnt = 1;
}
}
return (ptr);
}
RETSIGTYPE
cleanup(int ignored)
{
ZCancelSubscriptions(port);
exit(1);
}

71
clients/zctl/Makefile.in Normal file
View File

@ -0,0 +1,71 @@
SHELL=@SHELL@
prefix=@prefix@
exec_prefix=@exec_prefix@
datadir=@datadir@
sysconfdir=@sysconfdir@
sbindir=@sbindir@
lsbindir=@lsbindir@
datarootdir=@datarootdir@
includedir=@includedir@
mandir=@mandir@
libdir=@libdir@
bindir=@bindir@
top_builddir=../..
srcdir=@srcdir@
top_srcdir=@top_srcdir@
BUILDTOP=../..
VPATH=@srcdir@
LIBTOOL=@LIBTOOL@
CC=@CC@
INSTALL=@INSTALL@
editman = sed \
-e 's|@datadir[@]|${datadir}|g' \
-e 's|@sysconfdir[@]|${sysconfdir}|g' \
-e 's|@sbindir[@]|${sbindir}|g' \
-e 's|@lsbindir[@]|${lsbindir}|g'
LIBZEPHYR=${BUILDTOP}/lib/libzephyr.la
CPPFLAGS=@CPPFLAGS@
CFLAGS=@CFLAGS@
ALL_CFLAGS=${CFLAGS} -I${top_srcdir}/h -I${BUILDTOP}/h @X_CFLAGS@ ${CPPFLAGS}
LDFLAGS=@LDFLAGS@
LIBS=${LIBZEPHYR} @SS_LIBS@ @LIBS@ -lcom_err
SS_OBJS=zctl_cmds.o
OBJS= zctl.o @SS_OBJS@
all: zctl zctl.1
zctl: ${OBJS} ${LIBZEPHYR}
${LIBTOOL} --mode=link ${CC} ${LDFLAGS} -o $@ ${OBJS} ${LIBS}
zctl_cmds.c: zctl_cmds.ct
mk_cmds ${srcdir}/zctl_cmds.ct
.c.o:
${CC} -c ${ALL_CFLAGS} $<
zctl.1: ${srcdir}/zctl.1.in Makefile
${editman} ${srcdir}/$@.in > $@.tmp
mv $@.tmp $@
check:
install: zctl zctl.1
${LIBTOOL} --mode=install ${INSTALL} -m 755 zctl ${DESTDIR}${bindir}
${INSTALL} -m 644 zctl.1 ${DESTDIR}${mandir}/man1
clean:
${LIBTOOL} --mode=clean rm -f zctl
rm -f ${OBJS} zctl_cmds.c
rm -f zctl.1
${OBJS}: ${top_srcdir}/h/sysdep.h ${BUILDTOP}/h/config.h
${OBJS}: ${BUILDTOP}/h/zephyr/zephyr.h ${BUILDTOP}/h/zephyr/zephyr_err.h
.PHONY: all check install clean

319
clients/zctl/zctl.1.in Normal file
View File

@ -0,0 +1,319 @@
.\" $Id$
.\"
.\" Copyright 1987,1988 by the Massachusetts Institute of Technology
.\" All rights reserved. The file /usr/include/zephyr/mit-copyright.h
.\" specifies the terms and conditions for redistribution.
.\"
.\"
.TH ZCTL 1 "July 1, 1988" "MIT Project Athena"
.ds ]W MIT Project Athena
.SH NAME
zctl \- zephyr control program
.SH SYNOPSIS
.B zctl
[
.I options
]
.SH DESCRIPTION
.I Zctl
is a general purpose control program for the
.I Zephyr(1)
Notification Service. It allows the user to subscribe to specific
notice types, to save the subscriptions in a file (default
$HOME/.zephyr.subs), to change his location information, and to send
control messages to the HostManager,
.I zhm(8),
and the WindowGram client,
.I zwgc(1).
.PP
The commands may be typed on the command line, or may be entered
interactively by just typing
.I zctl
and then typing commands to the prompt.
.br
.B NOTE:
For all commands accepting an optional \fIrecipient\fR argument, the
\fIrecipient\fR defaults to your Kerberos principal. You may also
subscribe to recipient ``\fI*\fR''. If you specify a recipient, it is
silently converted to ``\fI*\fR''.
.br
The commands are as follows:
.TP 15
.B add \fIclass instance\fR [ \fIrecipient\fR ]
Subscribe to \fIclass, instance, recipient\fR, and add this triplet to
the subscriptions file.
.TP
.B add_unsubscription \fIclass instance\fR [ \fIrecipient\fR ]
Unsubscribe to \fIclass, instance, recipient\fR, and add this triplet
to the subscriptions file as an un-subscription.
For an explanation of un-subscriptions, see below.
.TP
.B cancel
Cancel all subscriptions.
.TP
.B defaults
Retrieve the default subscription list from the Zephyr server.
.TP
.B delete \fIclass instance\fR [ \fIrecipient\fR ]
Unsubscribe to \fIclass, instance, recipient\fR, and remove this triplet
from the subscriptions file.
.TP
.B delete_unsubscription \fIclass instance\fR [ \fIrecipient\fR ]
Unsubscribe to \fIclass, instance, recipient\fR, and remove this triplet
from the subscriptions file as an un-subscription.
.TP
.B file \fR[ \fIfile\fR ]
Set default subscriptions file to \fIfile\fR. If \fIfile\fR isn't specified,
show what the current subscriptions file is.
.TP
.B flush_locs \fR[ \fIuser\fR ]
Tell the Zephyr servers to flush all location information associated with
\fIuser\fR, or with the user running the command if none is given. This
should only be used to remove any incorrect data that may have been left
after a system crash. Note that only Operations staff may flush location
information associated with another user.
.TP
.B flush_subs \fR[ \fIrecipient\fR ]
Tell the Zephyr servers to flush all of \fIrecipient\fR's subscriptions,
This differs from the cancel command in that it affects subscriptions for
all of \fIrecipient\fR's clients. Note that only Operations staff may flush
the subscriptions of another user.
.TP
.B hide
Hide your location as maintained by the Zephyr server. This does not
affect the value of the exposure variable (see below, under
.B set).
.TP
.B hm_flush
Tell the HostManager,
.I zhm(8),
to ask the server to flush all state associated with the current host.
.TP
.B list \fR[ \fIfile\fR ]
List contents of current subscriptions file or
.I file.
Any macros in the file (see below) are displayed verbatim and not expanded.
.TP
.B list_requests
List all available commands. May be abbreviated by '?'.
.TP
.B load \fR[ \fIfile\fR ]
Subscribe to all subscription triplets and unsubscribe to all
un-subscription triplets in current subscriptions file or \fIfile\fR.
.TP
.B new_server
Tell the HostManager,
.I zhm(8),
to find a new Zephyr server.
.TP
.B quit
Exit from \fIzctl.
.TP
.B retrieve
Retrieve all current subscriptions from the Zephyr server. These include
subscriptions that might have been made by other programs, such as
.I znol(1).
.TP
.B save \fR[ \fIfile\fR ]
Save all current subscriptions (as returned by the Zephyr server)
into current subscriptions file or \fIfile\fR. The
file will be replaced.
.TP
.B set \fIvar\fR [ \fIvalue\fR ]
Set the value of Zephyr variable \fIvar\fR to \fIvalue\fR, or null if
no \fIvalue\fR is specified. The variable \fBexposure\fR has special
significance, and can only be set to the values none, opstaff, realm-visible,
realm-announced, net-visible, and net-announced. Setting this variable
immediately updates the information in the Zephyr servers (see below for
an explanation of the exposure levels). In addition,
setting this variable to none automatically performs the equivalent of a
.B wg_shutdown
command, and setting it to one of the other values automatically
performs the equivalent of a
.B wg_startup
command.
.br
The variable \fBresolved_addresses\fR determines whether zwgc will,
for an IP address indicating the origin of a message, attempt to look
up the hostname corresponding to that IP address. The value none
indicates that hostnames will never be found, and that the zwgc
fromhost variable will thus always contain an IP address (in
dotted-decimal form). The value all indicates that there will always
be an attempt to look up a hostname. Note that in this case, if you
have any subscriptions with recipient ``\fI*\fR'', these subscriptions
may be revealed to other Zephyr users who operate their own DNS name
servers. Any other value is interpreted as a regular expression;
hostname lookup attempts will occur only if the IP address matches
this regular expression.
.br
Any variable settings you make will be stored in \fI$HOME/.zephyr.vars\fR
.TP
.B show \fIvar\fR [ \fIvar\fR \ ... ]
Show the value of the specified Zephyr variables. If a variable is not
defined in the user's own variables file, the system variables file
(\fI@sysconfdir@/zephyr/zephyr.vars\fR) is searched for a default value.
.TP
.B subscribe \fIclass instance\fR [ \fIrecipient\fR ]
Subscribe to \fIclass, instance, recipient\fR, but don't add this triplet to
the subscriptions file.
.TP
.B unhide
Make your location as maintained by the Zephyr server visible. This does not
affect the value of the exposure variable.
.TP
.B unload \fR[ \fIfile\fR ]
Unsubscribe to all subscription triplets in current subscriptions file
or \fIfile\fR. Un-subscriptions in the file are ignored.
.TP
.B unset \fIvar\fR [ \fIvar\fR \ ... ]
Delete the definitions of the specified Zephyr variables.
.TP
.B unsubscribe \fIclass instance\fR [ \fIrecipient\fR ]
Unsubscribe to \fIclass, instance, recipient\fR, but don't remove this triplet
from the subscriptions file.
.TP
.B wg_exit
Tell the WindowGram client,
.I zwgc(1),
to exit.
.TP
.B wg_read
Tell the WindowGram client,
.I zwgc(1),
to reread its description file.
.TP
.B wg_shutdown
Tell the WindowGram client to shutdown; this causes it to ignore all
notices until a wg_startup command is issued.
.TP
.B wg_startup
Tell the WindowGram client to start accepting notices again; useful
after a wg_shutdown command has been issued.
.SH MACROS and SUBSCRIPTION FILES
There are three macros,
.I %host%, %canon%, \fRand\fI %me%. %host%
is converted to the current hostname, \fI%canon%\fR is converted to the
official hostname as returned by
.I gethostbyname(3),
and \fI%me%\fR is converted to your Kerberos principal. These macros can be
used in your \fI$HOME/.zephyr.subs\fR file or as arguments to commands
to specify the
.I class
or
.I instance
fields. A sample \fI$HOME/.zephyr.subs\fR file might contain the following:
.PP
.nf
message,urgent,%me%
syslog,%host%,*
mail,pop,%me%
.fi
.PP
.I Zctl
reads the environment variable \fBWGFILE\fR, to find the name of the
file where the windowgram port resides. If \fBWGFILE\fR is not set,
the file name defaults to /tmp/wg.\fIuid\fR, where \fIuid\fR is the
user's UNIX uid.
.SH UN-SUBSCRIPTIONS
The zephyr server,
.I zephyrd(8),
maintains default subscriptions which are automatically added to all
users' subscriptions at the time of their first subscription during a
login session. If you wish to automatically remove some of these
default subscriptions, you use
.B un-subscriptions.
When you
.B load
a subscription file containing
un-subscriptions, the un-subscriptions are automatically sent to the
server as if you had used the
.B unsubscribe
command.
.SH EXPOSURE LEVELS
The different exposure levels affect the operation of zephyr and its
interaction with the user, as follows:
.TP 10
.I none
This completely disables Zephyr for the user. The user is not
registered with Zephyr. No user location information is
retained by Zephyr. No login or logout announcements will be
sent. No subscriptions will be entered for the user, and no notices
will be displayed by
.I zwgc(1).
.TP
.I opstaff
The user is registered with Zephyr. No login or logout
announcements will be sent, and location information will only be
visible to Operations staff. Default subscriptions and any additional
personal subscriptions will be entered for the user.
.TP
.I realm-visible
The user is registered with Zephyr. User location information is retained by
Zephyr and made available only to users within the user's
Kerberos realm. No login or logout announcements will be sent. This
is the system default. Default subscriptions and any additional
personal subscriptions will be entered for the user.
.TP
.I realm-announced
The user is registered with Zephyr. User location information is retained by
Zephyr and made available only to users authenticated within the user's
Kerberos realm. Login and logout announcements will be sent, but only to
users within the user's Kerberos realm who have explicitly requested
such via subscriptions. Default subscriptions and any additional
personal subscriptions will be entered for the user.
.TP
.I net-visible
The user is registered with Zephyr. User location information is
retained by Zephyr and made available to any authenticated user who
requests such. Login and logout announcements will be sent only to users
within the user's Kerberos realm who have explicitly requested such via
subscriptions. Default subscriptions and any additional personal
subscriptions will be entered for the user.
.TP
.I net-announced
The user is registered with Zephyr. User location information is retained by
Zephyr and made available to any authenticated user who requests such. Login
and logout announcements will be sent to any user has requested such.
Default subscriptions and any additional personal
subscriptions will be entered for the user.
.SH EXAMPLES
.TP 25
.B zctl
Runs \fIzctl\fR in interactive mode.
.TP
.B zctl load
Load subscriptions and un-subscriptions from \fI$HOME/.zephyr.subs\fR file.
.TP
.B zctl sub message personal
Subscribe to personal messages, but don't add this to the
subscriptions file.
.TP
.B zctl save
Save all current subscriptions to the default subscriptions file.
.TP
.B zctl set exposure none
Set your exposure level to `none', effectively turning off Zephyr.
.SH SEE ALSO
zephyr(1), zwgc(1), zhm(8), zephyrd(8)
gethostbyname(3)
.br
Project Athena Technical Plan Section E.4.1, `Zephyr Notification
Service'
.SH FILES
/tmp/wg.*
.br
$HOME/.zephyr.subs
.br
$ZEPHYR_VARS or $HOME/.zephyr.vars
.br
@sysconfdir@/zephyr/zephyr.vars
.SH AUTHOR
.PP
Robert S. French (MIT-Project Athena)
.sp
.SH RESTRICTIONS
Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.
All Rights Reserved.
.br
.I zephyr(1)
specifies the terms and conditions for redistribution.

1391
clients/zctl/zctl.c Normal file

File diff suppressed because it is too large Load Diff

101
clients/zctl/zctl_cmds.ct Normal file
View File

@ -0,0 +1,101 @@
# $Id$
#
command_table zctl_cmds;
request set_file, "Set default subscriptions file.",
file;
request cancel_subs, "Cancel all subscriptions.",
cancel;
request load_subs, "Subscribe to a subscriptions file.",
load, ld;
request load_subs, "Unsubscribe to a subscriptions file.",
unload, unld;
request load_subs, "List a subscriptions file.",
list, ls;
request subscribe, "Subscribe to a class/class instance.",
subscribe, sub;
request subscribe, "Unsubscribe to a class/class instance.",
unsubscribe, unsub;
request sub_file, "Subscribe and add to subscriptions file.",
add;
request sub_file, "Unsubscribe and add to subscriptions file\n as un-subscription.",
add_unsubscription, add_un;
request sub_file, "Unsubscribe and delete subscription from\n subscriptions file.",
delete, del, dl;
request sub_file, "Delete un-subscription from subscriptions file.",
delete_unsubscription, del_un;
request current, "Retrieve current subscriptions.",
retrieve, ret;
request current, "Retrieve system-wide default subscriptions.",
defaults, defs;
request current, "Save current subscriptions (replacing existing file).",
save;
request show_var, "Show a variable's value.",
show;
request set_var, "Set a variable's value.",
set;
request unset_var, "Delete a variable's value.",
unset;
request wgc_control, "Get the WindowGram to reread its description file.",
wg_read;
request wgc_control, "Tell the WindowGram not to react to incoming notices.",
wg_shutdown;
request wgc_control, "Tell the WindowGram to react to incoming notices.",
wg_startup;
request wgc_control, "Tell the WindowGram to exit completely.",
wg_exit;
request hm_control, "Tell the server to flush information about this host.",
hm_flush;
request hm_control, "Tell the HostManager to find a new server.",
new_server;
request flush_locations, "Flush all location information.",
flush_locs;
request flush_subscr, "Flush all subscription information.",
flush_subs;
request do_hide, "Hide your location.",
hide;
request do_hide, "Show (un-hide) your location.",
unhide;
request ss_list_requests, "List available commands.",
list_requests, lr, "?";
request ss_quit, "Quit.",
quit, exit, q;
#ifdef CMU_ZCTL_PUNT
request do_punt, "Ignore specified messages.",
punt;
request do_punt, "Stop ignoring specified messages.",
unpunt;
request list_punts, "List current messages to ignore.",
list_punts, lp;
#endif
end;

View File

@ -0,0 +1,56 @@
SHELL=@SHELL@
prefix=@prefix@
exec_prefix=@exec_prefix@
datadir=@datadir@
sysconfdir=@sysconfdir@
sbindir=@sbindir@
lsbindir=@lsbindir@
datarootdir=@datarootdir@
includedir=@includedir@
mandir=@mandir@
libdir=@libdir@
bindir=@bindir@
top_builddir=../..
srcdir=@srcdir@
top_srcdir=@top_srcdir@
BUILDTOP=../..
VPATH=@srcdir@
LIBTOOL=@LIBTOOL@
CC=@CC@
INSTALL=@INSTALL@
LIBZEPHYR=${BUILDTOP}/lib/libzephyr.la
CPPFLAGS=@CPPFLAGS@
CFLAGS=@CFLAGS@
ALL_CFLAGS=${CFLAGS} -I${top_srcdir}/h -I${BUILDTOP}/h ${CPPFLAGS}
LDFLAGS=@LDFLAGS@
LIBS=${LIBZEPHYR} @LIBS@ -lcom_err
OBJS= zleave.o
all: zleave
zleave: ${OBJS} ${LIBZEPHYR}
${LIBTOOL} --mode=link ${CC} ${LDFLAGS} -o $@ ${OBJS} ${LIBS}
.c.o:
${CC} -c ${ALL_CFLAGS} $<
check:
install: zleave
${LIBTOOL} --mode=install ${INSTALL} -m 755 zleave ${DESTDIR}${bindir}
${INSTALL} -m 644 ${srcdir}/zleave.1 ${DESTDIR}${mandir}/man1
clean:
${LIBTOOL} --mode=clean rm -f zleave
rm -f ${OBJS}
${OBJS}: ${top_srcdir}/h/sysdep.h ${BUILDTOP}/h/config.h
${OBJS}: ${BUILDTOP}/h/zephyr/zephyr.h ${BUILDTOP}/h/zephyr/zephyr_err.h
.PHONY: all check install clean

107
clients/zleave/zleave.1 Normal file
View File

@ -0,0 +1,107 @@
.\" $Id$
.\"
.\" Copyright (c) 1980 Regents of the University of California.
.\" All rights reserved. The Berkeley software License Agreement
.\" specifies the terms and conditions for redistribution.
.\"
.\"
.TH ZLEAVE 1 "July 1, 1988" "MIT Project Athena"
.ds ]W MIT Project Athena
.SH NAME
zleave \- notify you via Zephyr when you have to leave
.SH SYNOPSIS
.B zleave
[
.RI [+] hhmm
[
.I -m "Reminder Message"
] ]
.br
.B zleave
.I can\fR[\fIcel\fR]
.SH DESCRIPTION
.I Zleave
waits until the specified time, then reminds you that you
have to leave, using the \fIZephyr(1)\fR Notification Service.
You are reminded 5 minutes and 1 minute before the actual
time, at the time, and every minute thereafter.
When you log off,
.I zleave
exits just before it would have sent the next message.
.PP
The time of day is in the form hhmm where hh is a time in
hours (on a 12 or 24 hour clock).
All times are converted to a 12 hour clock, and assumed to
be in the next 12 hours.
.PP
If the time is preceded by `+', the alarm will go off in hours and minutes
from the current time.
.PP
If no argument is given,
.I zleave
prompts with "When do you
have to leave?". A reply of newline causes
.I zleave
to exit,
otherwise the reply is assumed to be a time.
This form is suitable for inclusion in a
.I .login
or
.I .profile.
.PP
The
.I cancel
option cancels the currently running \fIzleave\fR. If another
.I zleave
is running, it is automatically killed when a new time to leave is
set. The process id is stored in the file /tmp/zleave.\fIuid\fR, where
\fIuid\fR is the user's UNIX uid.
.PP
If the
.I -m
argument is specified, the next argument
is appended to the standard message
(a sentence describing how much time remains until the appointed hour)
sent at appropriate times.
If you want to append a multiple-word message, you normally must quote it with
double quotes (") (This is necessary for users of
.IR csh (1)
and
.IR sh (1).)
.PP
.I Zleave
automatically subscribes you to Zephyr class "MESSAGE",
instance "LEAVE". You do not have to add anything to your
default subscriptions file (see
.IR zctl (1)).
The reminder message is displayed by the WindowGram client (usually
.IR zwgc (1)).
.PP
If Zephyr is unavailable,
.I zleave
acts essentially like
.IR leave (1).
.PP
Zleave ignores SIGINT, SIGQUIT, and SIGTERM.
To get rid of it you should either log off or use the
.I cancel
option.
.SH FILES
/tmp/zleave.\fIuid\fR
/tmp/wg.*
.SH SEE ALSO
calendar(1), zephyr(1), leave(1), zwgc(1), zctl(1), csh(1), sh(1)
.br
Project Athena Technical Plan Section E.4.1, `Zephyr Notification
Service'
.SH RESTRICTIONS
Copyright (c) 1980, Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms are permitted
provided that this notice is preserved and that due credit is given
to the University of California at Berkeley. The name of the University
may not be used to endorse or promote products derived from this
software without specific written prior permission. This software
is provided ``as is'' without express or implied warranty.
.sp
Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.

424
clients/zleave/zleave.c Normal file
View File

@ -0,0 +1,424 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains code for the "zleave" command.
*
* Created by: David Jedlinsky
*
* $Id$
*
* Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#include <sysdep.h>
#include <zephyr/mit-copyright.h>
#include <zephyr/zephyr.h>
#ifndef lint
static const char rcsid_zlocate_c[] = "$Id$";
#endif /* lint */
/*
* Copyright (c) 1980 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and that due credit is given
* to the University of California at Berkeley. The name of the University
* may not be used to endorse or promote products derived from this
* software without specific written prior permission. This software
* is provided ``as is'' without express or implied warranty.
*/
#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1980 Regents of the University of California.\n\
All rights reserved.\n";
#endif /* not lint */
#define MESSAGE_CLASS "MESSAGE"
#define INSTANCE "LEAVE"
/*
* zleave [[+]hhmm [ -m "Reminder Message" ]]
* or
* zleave can[cel]
*
* Reminds you when you have to leave.
* Leave prompts for input and goes away if you hit return.
* Messages are sent through Zephyr. Subscriptions are handled automagically.
* It nags you like a mother hen.
*/
char origlogin[20];
char tempfile[40];
char *whenleave;
char *reminder_message = NULL;
char buff[100];
int use_zephyr=1, oldpid;
void usage(void);
void doalarm(long);
void bother(long, char *);
void delay(long);
int gethm(char *, int *, int*);
int
main(int argc,
char **argv)
{
time_t now;
long when, diff;
int hours, minutes;
char *cp;
FILE *fp;
struct tm *nv;
int port, c;
ZSubscription_t sub;
if (ZInitialize() != ZERR_NONE) {
fprintf(stderr,"No Zephyr! Will write directly to terminal.\n");
use_zephyr = 0;
}
(void) sprintf(tempfile, "/tmp/zleave.%d", (int) getuid());
if (use_zephyr) {
if ((port = ZGetWGPort()) == -1) {
fprintf(stderr,
"Can't find WindowGram subscription port.\n");
fprintf(stderr,"Will write directly to terminal.\n");
use_zephyr = 0;
} else {
sub.zsub_class = MESSAGE_CLASS;
sub.zsub_classinst = INSTANCE;
sub.zsub_recipient = ZGetSender();
if (ZSubscribeToSansDefaults(&sub,1,(u_short)port)
!= ZERR_NONE) {
fprintf(stderr,
"Subscription error! Writing to your terminal...\n");
use_zephyr = 0;
}
}
}
if (!use_zephyr) {
if ((cp = getlogin()) == NULL) {
fputs("leave: You are not logged in.\n", stderr);
exit(1);
}
(void) strcpy(origlogin, cp);
}
c = 1;
while ((c<argc) && (! reminder_message))
if (!strcmp(argv[c++],"-m")) {
if (argv[c])
reminder_message = argv[c];
else
usage();
}
if (!reminder_message)
reminder_message = "";
if (argc < 2) {
printf("When do you have to leave? ");
(void) fflush(stdout);
buff[read(0, buff, sizeof buff)] = 0;
cp = buff;
} else
cp = argv[1];
if (*cp == '\n')
exit(0);
if (*cp == '+') {
cp++;
if (!gethm(cp, &hours, &minutes))
usage();
if (minutes < 0 || minutes > 59)
usage();
diff = 60*hours+minutes;
doalarm(diff);
exit(0);
}
if (!strcmp(cp, "cancel") || !strcmp(cp, "can")) {
if (!(fp = fopen(tempfile,"r"))) {
printf("No zleave is currently running.\n");
exit(0);
}
if (fscanf(fp, "%d", &oldpid) != 1) {
printf("The zleave pid file is corrupted.\n");
(void) fclose(fp);
exit(0);
}
(void) fclose(fp);
if (kill(oldpid,9))
printf("No zleave is currently running.\n");
(void) unlink(tempfile);
exit(0);
}
if (!gethm(cp, &hours, &minutes))
usage();
if (hours > 12)
hours -= 12;
if (hours == 12)
hours = 0;
if (hours < 0 || hours > 12 || minutes < 0 || minutes > 59)
usage();
(void) time(&now);
nv = localtime(&now);
when = 60*hours+minutes;
if (nv->tm_hour > 12)
nv->tm_hour -= 12; /* do am/pm bit */
now = 60 * nv->tm_hour + nv->tm_min;
diff = when - now;
while (diff < 0)
diff += 12*60;
if (diff > 11*60) {
fprintf(stderr, "That time has already passed!\n");
exit(1);
}
doalarm(diff);
exit(0);
}
void
usage(void)
{
fprintf(stderr, "usage: zleave [[+]hhmm [-m \"Reminder Message\"]]\n\
\tor: zleave can[cel]\n");
exit(1);
}
int
gethm(char *cp,
int *hp,
int *mp)
{
char c;
int tod;
tod = 0;
while ((c = *cp++) != '\0') {
if (!isdigit(c))
return(0);
tod = tod * 10 + (c - '0');
}
*hp = tod / 100;
*mp = tod % 100;
return(1);
}
void
doalarm(long nmins)
{
time_t daytime;
char *msg1, *msg2, *msg3, *msg4;
register int i;
long slp1, slp2, slp3, slp4;
long seconds, gseconds;
FILE *fp;
#ifdef _POSIX_VERSION
struct sigaction sa;
#endif
seconds = 60 * nmins;
if (seconds <= 0)
seconds = 1;
gseconds = seconds;
msg1 = "You have to leave in 5 minutes";
if (seconds <= 60*5) {
slp1 = 0;
} else {
slp1 = seconds - 60*5;
seconds = 60*5;
}
msg2 = "Just one more minute!";
if (seconds <= 60) {
slp2 = 0;
} else {
slp2 = seconds - 60;
seconds = 60;
}
msg3 = "Time to leave!";
slp3 = seconds;
msg4 = "You're going to be late!";
slp4 = 60L;
(void) time(&daytime);
daytime += gseconds;
whenleave = ctime(&daytime);
fp = fopen(tempfile,"r");
if (fp) {
if (fscanf(fp, "%d", &oldpid) == 1)
if (!kill(oldpid,9))
printf("Old zleave process killed.\n");
(void) fclose(fp);
}
printf("Alarm set for %s", whenleave);
/* Subscribe to MESSAGE.LEAVE here */
switch(fork()) {
case -1:
perror("fork");
exit(-1);
break;
case 0:
break;
default:
exit(0);
break;
}
if (!(fp = fopen(tempfile, "w")))
fprintf(stderr, "Cannot open pid file.\n");
else {
fprintf(fp, "%d\n", getpid());
if (fclose(fp) == EOF)
(void) perror("fclose on pid file");
}
#ifdef _POSIX_VERSION
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = SIG_IGN;
sigaction(SIGINT, &sa, (struct sigaction *)0);
sigaction(SIGQUIT, &sa, (struct sigaction *)0);
sigaction(SIGTERM, &sa, (struct sigaction *)0);
sigaction(SIGTTOU, &sa, (struct sigaction *)0);
#else
(void) signal(SIGINT, SIG_IGN);
(void) signal(SIGQUIT, SIG_IGN);
(void) signal(SIGTERM, SIG_IGN);
(void) signal(SIGTTOU, SIG_IGN);
#endif
if (slp1)
bother(slp1, msg1);
if (slp2)
bother(slp2, msg2);
bother(slp3, msg3);
for (i = 0; i < 10; i++)
bother(slp4, msg4);
bother(0L, "That was the last time I'll tell you. Bye.");
(void) unlink(tempfile);
exit(0);
}
void
bother(long slp,
char *msg)
{
ZNotice_t notice;
ZNotice_t retnotice;
int retval;
char *real_message;
delay(slp);
if (use_zephyr) {
real_message = (char *) malloc(strlen(msg) +
strlen(reminder_message) + 3);
if (real_message == NULL) {
fprintf (stderr, "zleave: out of memory\n");
exit (1);
}
sprintf(real_message,"%c%s\n%s",'\0',msg,reminder_message);
(void) memset((char *)&notice, 0, sizeof(notice));
notice.z_kind = ACKED;
notice.z_port = 0;
notice.z_charset = ZCHARSET_UNKNOWN;
notice.z_class = MESSAGE_CLASS;
notice.z_class_inst = INSTANCE;
notice.z_recipient = ZGetSender();
notice.z_opcode = "";
notice.z_sender = (char *) 0;
notice.z_default_format = "\n$2";
notice.z_message = real_message;
/* +3: initial null, newline, final null */
notice.z_message_len = strlen(msg)+strlen(reminder_message)+3;
if (ZSendNotice(&notice, ZAUTH) != ZERR_NONE) {
printf("\7\7\7%s\n%s", msg, reminder_message);
use_zephyr = 0;
} else
if ((retval = ZIfNotice(&retnotice, (struct sockaddr_in *) 0,
ZCompareUIDPred,
(char *)&notice.z_uid)) != ZERR_NONE) {
fprintf(stderr,
"zleave: %s while waiting for acknowledgement\n",
error_message(retval));
use_zephyr = 0;
} else
if (retnotice.z_kind == SERVNAK) {
fprintf(stderr,
"zleave: authorization failure while sending\n");
use_zephyr = 0;
} else
if (retnotice.z_kind != SERVACK || !retnotice.z_message_len) {
fprintf(stderr, "zleave: Detected server failure while receiving acknowledgement\n");
use_zephyr = 0;
} else
if (strcmp(retnotice.z_message, ZSRVACK_SENT)) {
/* it wasn't sent */
exit(0);
}
if (!use_zephyr)
exit(1);
ZFreeNotice(&retnotice);
free(real_message);
} else
#ifdef __STDC__
printf("\a\a\a%s\n%s", msg, reminder_message);
#else
printf("\7\7\7%s\n%s", msg, reminder_message);
#endif
}
/*
* delay is like sleep but does it in 100 sec pieces and
* knows what zero means.
*/
void
delay(long secs)
{
long n;
register char *l;
while (secs > 0) {
n = 100;
if (secs < n)
n = secs;
secs -= n;
if (n > 0)
sleep((unsigned) n);
if (!use_zephyr) {
l = getlogin();
if (l == NULL)
exit(0);
if (strcmp(origlogin, l) != 0)
exit(0);
}
}
}
#ifndef HAVE_GETLOGIN
char *getlogin() {
#include <utmp.h>
static struct utmp ubuf;
int ufd;
ufd = open("/etc/utmp",0);
seek(ufd, ttyn(0)*sizeof(ubuf), 0);
read(ufd, &ubuf, sizeof(ubuf));
ubuf.ut_name[sizeof(ubuf.ut_name)] = 0;
return(&ubuf.ut_name);
}
#endif

View File

@ -0,0 +1,56 @@
SHELL=@SHELL@
prefix=@prefix@
exec_prefix=@exec_prefix@
datadir=@datadir@
sysconfdir=@sysconfdir@
sbindir=@sbindir@
lsbindir=@lsbindir@
datarootdir=@datarootdir@
includedir=@includedir@
mandir=@mandir@
libdir=@libdir@
bindir=@bindir@
top_builddir=../..
srcdir=@srcdir@
top_srcdir=@top_srcdir@
BUILDTOP=../..
VPATH=@srcdir@
LIBTOOL=@LIBTOOL@
CC=@CC@
INSTALL=@INSTALL@
LIBZEPHYR=${BUILDTOP}/lib/libzephyr.la
CPPFLAGS=@CPPFLAGS@
CFLAGS=@CFLAGS@
ALL_CFLAGS=${CFLAGS} -I${top_srcdir}/h -I${BUILDTOP}/h ${CPPFLAGS}
LDFLAGS=@LDFLAGS@
LIBS=${LIBZEPHYR} @LIBS@ -lcom_err
OBJS= zlocate.o
all: zlocate
zlocate: ${OBJS} ${LIBZEPHYR}
${LIBTOOL} --mode=link ${CC} ${LDFLAGS} -o $@ ${OBJS} ${LIBS}
.c.o:
${CC} -c ${ALL_CFLAGS} $<
check:
install: zlocate
${LIBTOOL} --mode=install ${INSTALL} -m 755 zlocate ${DESTDIR}${bindir}
${INSTALL} -m 644 ${srcdir}/zlocate.1 ${DESTDIR}${mandir}/man1
clean:
${LIBTOOL} --mode=clean rm -f zlocate
rm -f ${OBJS}
${OBJS}: ${top_srcdir}/h/sysdep.h ${BUILDTOP}/h/config.h
${OBJS}: ${BUILDTOP}/h/zephyr/zephyr.h ${BUILDTOP}/h/zephyr/zephyr_err.h
.PHONY: all check install clean

76
clients/zlocate/zlocate.1 Normal file
View File

@ -0,0 +1,76 @@
.\" $Id$
.\"
.\" Copyright 1987,1988 by the Massachusetts Institute of Technology
.\" All rights reserved. The file /usr/include/zephyr/mit-copyright.h
.\" specifies the terms and conditions for redistribution.
.\"
.\"
.TH ZLOCATE 1 "April 17, 1990" "MIT Project Athena"
.ds ]W MIT Project Athena
.SH NAME
zlocate \- find a user using Zephyr
.SH SYNOPSIS
.B zlocate
[
.B -a
|
.B -d
] [
.B -1
] [
.B -p
] user ...
.SH DESCRIPTION
.I Zlocate
uses the
.I Zephyr(1)
Notification Service to find where a user is currently logged in. If
the user is not logged in, or has set his location information such that
you do not have access to see it,
.I zlocate
prints "Hidden or not logged-in". Otherwise, each machine that the
user is currently logged into is printed, along with the time of
login and location. The location is usually the X window system display
name of the user's display, but may be the terminal name if he is not
using X or for some other reason is only using the terminal interface to
.I zwgc(1).
By default, all zlocate requests are authenticated using
.IR Kerberos .
If you do not have Kerberos tickets, or for some other reason do not
want to authenticate, the
.B -d
option will turn off authentication. The
.B -a
option is the default, authentication on.
When locating multiple users,
.I zlocate
will display the user name on a line by itself, followed by the locations for that user. To display the user name on the same line as the output, use the
.B -1
option (the numeral one).
To look up multiple users in parallel asynchronously, use the
.B -p
option.
.SH DIAGNOSTICS
.I zlocate
exits with status zero (0) if at least one user was found, and one (1)
if no users were found.
.SH SEE ALSO
zctl(1), zephyr(1), znol(1), zwgc(1), zhm(8), zephyrd(8), X(1)
.br
Project Athena Technical Plan Section E.4.1, `Zephyr Notification
Service'
.SH AUTHORS
.PP
Robert S. French (MIT-Project Athena)
.br
Marc Horowitz (MIT-Project Athena)
.SH RESTRICTIONS
Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.
All Rights Reserved.
.br
.I zephyr(1)
specifies the terms and conditions for redistribution.

182
clients/zlocate/zlocate.c Normal file
View File

@ -0,0 +1,182 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains code for the "zlocate" command.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#include <sysdep.h>
#include <zephyr/zephyr.h>
#include <sys/socket.h>
#if !defined(lint) && !defined(SABER)
static const char rcsid_zlocate_c[] = "$Id$";
#endif
int numusers=0, numleft=0, parallel=0, oneline=0;
char *whoami;
static RETSIGTYPE
timeout(int sig)
{
fprintf (stderr, "%s: no response from server\n", whoami);
exit(1);
}
static void
usage(void)
{
printf("Usage: %s [ -a | -d ] [ -p ] [ -1 ] user ... \n",whoami);
exit(1);
}
static void
print_locs(char *user,
int nlocs)
{
int one = 1, retval;
ZLocations_t locations;
if ((!oneline) && (numusers>1))
printf("\t%s:\n",user);
if ((!oneline) && (nlocs == 0))
printf("Hidden or not logged-in\n");
for (;nlocs;nlocs--) {
if ((retval = ZGetLocations(&locations,&one)) != ZERR_NONE) {
com_err(whoami,retval,"while getting location");
exit(1);
}
if (oneline) {
printf("%s:\t%s\t%s\t%s\n",user,locations.host,locations.tty,
locations.time);
} else {
printf("%-42s %-7s %s\n",locations.host, locations.tty, locations.time);
}
}
if ((!oneline) && (numusers > 1) && (numleft > 0))
printf("\n");
}
/*ARGSUSED*/
int
main(int argc,
char *argv[])
{
char user[BUFSIZ],*whichuser;
ZAsyncLocateData_t ald;
int retval,i,numlocs,numfound,loc,auth,rlen;
ZNotice_t notice;
#ifdef _POSIX_VERSION
struct sigaction sa;
#endif
whoami = argv[0];
auth = -1;
argv++;
argc--;
for (i=0; i < argc; i++)
if (argv[i][0] == '-')
switch (argv[i][1]) {
case 'a':
if (auth != -1) usage();
auth = 1;
break;
case 'd':
if (auth != -1) usage();
auth = 0;
break;
case 'p':
parallel = 1;
break;
case '1':
oneline = 1;
break;
default:
usage();
break;
}
else
numusers++;
if (numusers == 0)
usage();
if (auth == -1) auth = 1;
if ((retval = ZInitialize()) != ZERR_NONE) {
com_err(whoami,retval,"while initializing");
exit(1);
}
numleft = numusers;
numfound = 0;
rlen = strlen(ZGetRealm());
i = 0;
for (loc = 0; loc < argc; loc++) {
if (argv[loc][0] == '-') continue;
(void) strncpy(user,argv[loc],sizeof(user) - rlen - 2);
user[sizeof(user) - rlen - 2] = '\0';
if (!strchr(user,'@')) {
(void) strcat(user,"@");
(void) strcat(user,ZGetRealm());
}
if (parallel) {
if ((retval = ZRequestLocations(user, &ald, i ? UNSAFE : UNACKED,
auth?ZAUTH:ZNOAUTH)) != ZERR_NONE) {
com_err(whoami,retval,"requesting location of %s",user);
exit(1);
}
i = 1;
} else {
if ((retval = ZLocateUser(user,&numlocs,auth?ZAUTH:ZNOAUTH)) != ZERR_NONE) {
com_err(whoami,retval,"while locating user %s",user);
exit(1);
}
print_locs(user,numlocs);
numfound += numlocs;
}
}
if (parallel) {
#ifdef _POSIX_VERSION
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = timeout;
sigaction(SIGALRM, &sa, (struct sigaction *)0);
#else
signal (SIGALRM, timeout);
#endif
while (numleft-- > 0) {
alarm(SRV_TIMEOUT);
if ((retval = ZReceiveNotice(&notice, NULL)) != ZERR_NONE) {
com_err(whoami,retval,"while searching notice queue");
continue;
}
if ((retval = ZParseLocations(&notice, (ZAsyncLocateData_t *)NULL,
&numlocs, &whichuser)) != ZERR_NONE) {
com_err(whoami,retval,"while parsing locations");
continue;
}
if (numlocs >= 0) {
print_locs(whichuser,numlocs);
free(whichuser);
numfound += numlocs;
}
ZFreeNotice(&notice);
}
}
return((numfound > 0) ? 0 : 1);
}

56
clients/znol/Makefile.in Normal file
View File

@ -0,0 +1,56 @@
SHELL=@SHELL@
prefix=@prefix@
exec_prefix=@exec_prefix@
datadir=@datadir@
sysconfdir=@sysconfdir@
sbindir=@sbindir@
lsbindir=@lsbindir@
datarootdir=@datarootdir@
includedir=@includedir@
mandir=@mandir@
libdir=@libdir@
bindir=@bindir@
top_builddir=../..
srcdir=@srcdir@
top_srcdir=@top_srcdir@
BUILDTOP=../..
VPATH=@srcdir@
LIBTOOL=@LIBTOOL@
CC=@CC@
INSTALL=@INSTALL@
LIBZEPHYR=${BUILDTOP}/lib/libzephyr.la
CPPFLAGS=@CPPFLAGS@
CFLAGS=@CFLAGS@
ALL_CFLAGS=${CFLAGS} -I${top_srcdir}/h -I${BUILDTOP}/h ${CPPFLAGS}
LDFLAGS=@LDFLAGS@
LIBS=${LIBZEPHYR} @LIBS@ -lcom_err
OBJS= znol.o
all: znol
znol: ${OBJS} ${LIBZEPHYR}
${LIBTOOL} --mode=link ${CC} ${LDFLAGS} -o $@ ${OBJS} ${LIBS}
.c.o:
${CC} -c ${ALL_CFLAGS} $<
check:
install: znol
${LIBTOOL} --mode=install ${INSTALL} -m 755 znol ${DESTDIR}${bindir}
${INSTALL} -m 644 ${srcdir}/znol.1 ${DESTDIR}${mandir}/man1
clean:
${LIBTOOL} --mode=clean rm -f znol
rm -f ${OBJS}
${OBJS}: ${top_srcdir}/h/sysdep.h ${BUILDTOP}/h/config.h
${OBJS}: ${BUILDTOP}/h/zephyr/zephyr.h ${BUILDTOP}/h/zephyr/zephyr_err.h
.PHONY: all check install clean

109
clients/znol/znol.1 Normal file
View File

@ -0,0 +1,109 @@
.\" $Id$
.\"
.\" Copyright 1987,1988 by the Massachusetts Institute of Technology
.\" All rights reserved. The file /usr/include/zephyr/mit-copyright.h
.\" specifies the terms and conditions for redistribution.
.\"
.\" @(#)znol.1 6.1 (MIT) 7/9/87
.\"
.TH ZNOL 1 "July 1, 1988" "MIT Project Athena"
.ds ]W MIT Project Athena
.SH NAME
znol \- notify via Zephyr upon login or logout of interesting people
.SH SYNOPSIS
.B znol
[
.BI on|off
] [
.BI \-f \ file
] [
.BI \-u \ username
] [
.BI \-l
] [
.BI \-q
]
.SH DESCRIPTION
.I Znol
provides a way for you to be notified when "interesting" people log in
or out. It uses the
.I Zephyr(1)
Notification Service, which causes a message to appear on your screen
for every person specified in a namelist (which defaults to
$HOME/.anyone). The namelist should have one login name per line. Any
line starting with `#' is considered a comment and ignored.
Anyone in the namelist who is logged in when
.I znol
is executed is printed to stdout. The control arguments are as
follows:
.TP 12
.B on|off
Turns notification on or off.
.TP
.B \-f
The namelist file is taken to be
.I file.
If
.I file
is "-", then the standard input is used instead of a file. If
.I file
does not exist, an error message is printed, and
.I znol
exits.
This option may not be used in conjunction with the
.B \-u
option.
.TP
.B \-l
Causes
.I znol
to just list the people in the namelist who are currently logged in,
without subscribing to the login messages. This option may not be used
in conjunction with the
.BI \-q
option.
.TP
.B \-q
Disables printing who is currently logged in when subscribing. This
option may not be used in conjunction with the
.BI \-l
option.
.TP
.B \-u
Instead of reading a file to specify the "interesting" users, the next
argument is used as the only "interesting" user. This option may not be
used in conjunction with the
.B \-f
option.
.SH EXAMPLES
.nf
.in +.5in
znol
.in -.5in
.fi
reads the standard namelist file, prints the locations of any users
named therein which can be found on the system, and enters subscriptions
for notices about those users.
.nf
.in +.5in
znol \-l \-u foo
.in -.5in
.fi
prints the location (if visible) of the user 'foo'.
.SH FILES
$HOME/.anyone
.SH SEE ALSO
anyone(SIPB), nol(SIPB), zctl(1), zephyr(1), zwgc(1), zhm(8), zephyrd(8)
.br
Project Athena Technical Plan Section E.4.1, `Zephyr Notification
Service'
.SH AUTHOR
.PP
Robert S. French (MIT-Project Athena)
.sp
.SH RESTRICTIONS
Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.
All Rights Reserved.
.br
.I zephyr(1)
specifies the terms and conditions for redistribution.

256
clients/znol/znol.c Normal file
View File

@ -0,0 +1,256 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains code for the "znol" command.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#include <sysdep.h>
#include <zephyr/zephyr.h>
#include <pwd.h>
#ifndef lint
static const char rcsid_znol_c[] = "$Id$";
#endif
#define SUBSATONCE 7
#define ON 1
#define OFF 0
int
main(int argc, char *argv[])
{
register char *cp;
char *realm;
ZSubscription_t subs[SUBSATONCE];
ZLocations_t locations;
FILE *fp = NULL;
struct passwd *pwd;
char anyonename[BUFSIZ],name[BUFSIZ],cleanname[BUFSIZ],*envptr;
char *comment_ptr;
int onoff = ON,quiet = 0,justlist = 0,useronly = 0, filenamed = 0;
int retval,arg,ind,one,numlocs,i;
int wgport = 0;
if ((retval = ZInitialize()) != ZERR_NONE) {
com_err(argv[0],retval,"initializing");
exit (1);
}
for (arg=1;arg<argc;arg++) {
if (!strcmp(argv[arg],"on")) {
onoff = ON;
continue;
}
if (!strcmp(argv[arg],"off")) {
onoff = OFF;
continue;
}
if (argv[arg][0] == '-') {
char opt = argv[arg][1];
if (opt == 0 || argv[arg][2] != 0)
goto usage;
switch (argv[arg][1]) {
case 'q':
quiet = 1;
break;
case 'l':
justlist = 1;
break;
case 'f':
if (arg == argc-1) {
fprintf(stderr,"No file name specified\n");
goto usage;
}
(void) strcpy(anyonename,argv[++arg]);
filenamed = 1;
break;
case 'u':
if (arg == argc-1) {
fprintf(stderr,"No username specified\n");
goto usage;
}
(void) strcpy(cleanname,argv[++arg]);
useronly = 1;
break;
default:
goto usage;
}
continue;
}
usage:
fprintf(stderr,"Usage: %s [on|off] [-q | -l] [-f file | -u username]\n", argv[0]);
exit (1);
}
if (quiet && justlist) {
fprintf(stderr,"-q and -l cannot both be used\n");
goto usage;
}
if (useronly && filenamed) {
fprintf(stderr,"-u and -f cannot both be used\n");
goto usage;
}
if (!justlist)
if ((wgport = ZGetWGPort()) == -1) {
com_err(argv[0],errno,"while getting WindowGram port");
exit(1);
}
if (!useronly) {
/* If no filename specified, get the default */
if (!filenamed) {
envptr = getenv("HOME");
if (envptr)
(void) strcpy(anyonename,envptr);
else {
if (!(pwd = getpwuid((int) getuid()))) {
fprintf(stderr,"You are not listed in the password file.\n");
exit (1);
}
(void) strcpy(anyonename,pwd->pw_dir);
}
(void) strcat(anyonename,"/.anyone");
}
/* if the filename is "-", read stdin */
if (strcmp(anyonename,"-") == 0) {
fp = stdin;
} else if (!(fp = fopen(anyonename,"r"))) {
fprintf(stderr,"Can't open %s for input\n",anyonename);
exit (1);
}
}
ind = 0;
for (;;) {
if (!useronly) {
if (!fgets(cleanname,sizeof cleanname,fp))
break;
if (cleanname[0] == '#' || cleanname[0] == '\0' ||
cleanname[0] == '\n')
continue; /* ignore comment and empty lines */
comment_ptr = strchr(cleanname, '#');
if (comment_ptr)
*comment_ptr = '\0'; /* Ignore from # onwards */
/* Get rid of old-style nol entries, just in case */
cp = cleanname + strlen(cleanname) - 1;
*cp = '\0';
while(*--cp == ' ')
*cp = '\0';
if (*cleanname == '@' || !*cleanname)
continue;
} else if (ind)
break; /* only do the one name */
subs[ind].zsub_class = LOGIN_CLASS;
(void) strcpy(name,cleanname);
if (!strchr(name,'@')) {
cp = name + strlen(name);
*cp++ = '@';
(void) strcpy(cp,ZGetRealm());
}
cp = strchr(name,'@');
if (cp[0] && strcmp(cp+1,ZGetRealm())) {
realm = cp + 1;
*cp = '\0';
if ((subs[ind].zsub_classinst =
malloc((unsigned)(strlen(name) + strlen(realm) + 2)))
== NULL)
{
fprintf (stderr, "znol: out of memory");
exit (1);
}
(void) sprintf(subs[ind].zsub_classinst, "%s@%s", name,
realm);
(void) strcpy(name, subs[ind].zsub_classinst);
if ((subs[ind].zsub_recipient =
malloc((unsigned)(strlen(realm)+2))) == NULL) {
fprintf (stderr, "znol: out of memory");
exit (1);
}
(void) sprintf(subs[ind++].zsub_recipient, "@%s", realm);
} else {
if ((subs[ind].zsub_classinst =
malloc((unsigned)(strlen(name)+1))) == NULL)
{
fprintf (stderr, "znol: out of memory");
exit (1);
}
(void) strcpy(subs[ind].zsub_classinst, name);
subs[ind++].zsub_recipient = "";
}
if (!quiet && onoff == ON) {
if ((retval = ZLocateUser(name,&numlocs,ZAUTH))
!= ZERR_NONE) {
com_err(argv[0],retval,"locating user");
exit(1);
}
one = 1;
if (numlocs) {
for (i=0;i<numlocs;i++) {
if ((retval =
ZGetLocations(&locations,&one))
!= ZERR_NONE) {
com_err(argv[0],retval,
"getting location");
continue;
}
if (one != 1) {
printf("%s: internal failure while getting location\n",argv[0]);
exit(1);
}
printf("%s: %s\t%s\t%s\n",cleanname,
locations.host,
locations.tty,
locations.time);
}
}
}
if (ind == SUBSATONCE) {
if (!justlist)
if ((retval = (onoff==ON)?
ZSubscribeToSansDefaults(subs,ind,
(u_short)wgport):
ZUnsubscribeTo(subs,ind,(u_short)wgport)) !=
ZERR_NONE) {
com_err(argv[0],retval,(onoff==ON)?
"subscribing":
"unsubscribing");
exit(1);
}
for (ind=0;ind<SUBSATONCE;ind++)
{
if (subs[ind].zsub_recipient[0] != '\0')
free(subs[ind].zsub_recipient);
free(subs[ind].zsub_classinst);
}
ind = 0;
}
}
if (ind && !justlist)
if ((retval = (onoff==ON)?
ZSubscribeToSansDefaults(subs,ind,(u_short)wgport):
ZUnsubscribeTo(subs,ind,(u_short)wgport)) !=
ZERR_NONE) {
com_err(argv[0],retval,(onoff==ON)?
"subscribing":
"unsubscribing");
exit(1);
}
if (!useronly)
(void) fclose(fp); /* file is open read-only,
ignore errs */
exit(0);
}

View File

@ -0,0 +1,57 @@
SHELL=@SHELL@
prefix=@prefix@
exec_prefix=@exec_prefix@
datadir=@datadir@
sysconfdir=@sysconfdir@
sbindir=@sbindir@
lsbindir=@lsbindir@
datarootdir=@datarootdir@
includedir=@includedir@
mandir=@mandir@
libdir=@libdir@
bindir=@bindir@
top_builddir=../..
srcdir=@srcdir@
top_srcdir=@top_srcdir@
BUILDTOP=../..
VPATH=@srcdir@
LIBTOOL=@LIBTOOL@
CC=@CC@
INSTALL=@INSTALL@
LIBZEPHYR=${BUILDTOP}/lib/libzephyr.la
CPPFLAGS=@CPPFLAGS@
CFLAGS=@CFLAGS@
ALL_CFLAGS=${CFLAGS} -I${top_srcdir}/h -I${BUILDTOP}/h ${CPPFLAGS}
LDFLAGS=@LDFLAGS@
LIBS=${LIBZEPHYR} @LIBS@ -lcom_err
OBJS= zshutdown_notify.o
all: zshutdown_notify
zshutdown_notify: ${OBJS} ${LIBZEPHYR}
${LIBTOOL} --mode=link ${CC} ${LDFLAGS} -o $@ ${OBJS} ${LIBS}
.c.o:
${CC} -c ${ALL_CFLAGS} $<
check:
install: zshutdown_notify
${LIBTOOL} --mode=install ${INSTALL} -m 755 zshutdown_notify \
${DESTDIR}${lsbindir}
${INSTALL} -m 644 ${srcdir}/zshutdown_notify.8 ${DESTDIR}${mandir}/man8
clean:
${LIBTOOL} --mode=clean rm -f zshutdown_notify
rm -f ${OBJS}
${OBJS}: ${top_srcdir}/h/sysdep.h ${BUILDTOP}/h/config.h
${OBJS}: ${BUILDTOP}/h/zephyr/zephyr.h ${BUILDTOP}/h/zephyr/zephyr_err.h
.PHONY: all check install clean

View File

@ -0,0 +1,43 @@
.\" $Id$
.\"
.\" Copyright 1988 by the Massachusetts Institute of Technology
.\" All rights reserved. The file /usr/include/zephyr/mit-copyright.h
.\" specifies the terms and conditions for redistribution.
.\"
.TH ZSHUTDOWN_NOTIFY 8 "July 8, 1988" "MIT Project Athena"
.ds ]W MIT Project Athena
.SH NAME
zshutdown_notify \- notify users of impending shutdown via Zephyr
.SH SYNOPSIS
.B zshutdown_notify
.SH DESCRIPTION
.I zshutdown_notify
reads the standard input until EOF is reached, and then sends a Zephyr
notice with the official hostname, the collected input, and a warning
message as the message body of the notice.
The notice is sent to class FILSRV, instance
.I <hostname>,
recipient "*", where <hostname> is the official hostname of the sending host.
.PP
Any users who are using resources on the sending host are expected to
subscribe to these messages so they will be warned of any impending
shutdowns.
.PP
.I zshutdown_notify
is usually invoked from within
.I /etc/shutdown.
.SH SEE ALSO
attach(1), zephyr(1), zwgc(1), shutdown(8), zhm(8), zephyrd(8)
.br
Project Athena Technical Plan Section E.4.1, `Zephyr Notification
Service'
.SH AUTHOR
.PP
C. Anthony Della Fera (Digital Equipment Corporation-Project Athena)
.sp
.SH RESTRICTIONS
Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.
All Rights Reserved.
.br
.I zephyr(1)
specifies the terms and conditions for redistribution.

View File

@ -0,0 +1,143 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains code for "zshutdown_notify", a utility called by
* shutdown(8) to do Zephyr notification on shutdown.
*
* Created by: C. Anthony Della Fera
*
* $Id$
*
* Copyright (c) 1987, 1993 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#include <sysdep.h>
#include <zephyr/mit-copyright.h>
#include <zephyr/zephyr.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/nameser.h>
#ifndef lint
static const char rcsid_zshutdown_notify_c[] =
"$Id$";
#endif
#define N_KIND UNSAFE
#define N_CLASS "FILSRV"
#define N_OPCODE "SHUTDOWN"
#define N_DEF_FORMAT "From $sender:\n@bold(Shutdown message from $1 at $time)\n@center(System going down, message is:)\n\n$2\n\n@center(@bold($3))"
#define N_FIELD_CNT 3
#ifdef HAVE_KRB4
#define SVC_NAME "rcmd"
#endif
/*
* Standard warning strings appended as extra fields to
* the message body.
*/
static char warning[] = "Please detach any filesystems you may have\nattached from this host by typing detach -host %s";
/*ARGSUSED*/
int
main(int argc,
char *argv[])
{
ZNotice_t notice;
struct hostent *hp;
int retval;
char hostname[NS_MAXDNAME];
char msgbuff[BUFSIZ], message[Z_MAXPKTLEN], *ptr;
char scratch[BUFSIZ];
char *msg[N_FIELD_CNT];
#ifdef HAVE_KRB4
char tkt_filename[MAXPATHLEN];
char rlm[REALM_SZ];
char hn2[NS_MAXDNAME];
char *cp;
#endif
if (gethostname(hostname, sizeof(hostname)) < 0) {
com_err(argv[0], errno, "while finding hostname");
exit(1);
}
if ((hp = gethostbyname(hostname)) != NULL)
(void) strcpy(hostname, hp->h_name);
msg[0] = hostname;
msg[1] = message;
sprintf(scratch, warning, hostname);
msg[2] = scratch;
#ifdef HAVE_KRB4
(void) sprintf(tkt_filename, "/tmp/tkt_zshut_%d", getpid());
krb_set_tkt_string(tkt_filename);
cp = krb_get_phost(hostname);
if (cp)
(void) strcpy(hn2, cp);
else {
fprintf(stderr, "%s: can't figure out canonical hostname\n",argv[0]);
exit(1);
}
retval = krb_get_lrealm(rlm, 1);
if (retval) {
fprintf(stderr, "%s: can't get local realm: %s\n",
argv[0], krb_get_err_text(retval));
exit(1);
}
retval = krb_get_svc_in_tkt(SVC_NAME, hn2, rlm,
SERVER_SERVICE, SERVER_INSTANCE, 1,
(char *)KEYFILE);
if (retval) {
fprintf(stderr, "%s: can't get tickets: %s\n",
argv[0], krb_get_err_text(retval));
exit(1);
}
#endif
if ((retval = ZInitialize()) != ZERR_NONE) {
com_err(argv[0], retval, "while initializing");
exit(1);
}
ptr = message;
for (;;) {
if (!fgets(msgbuff, sizeof(msgbuff), stdin))
break;
if ((strlen(msgbuff) + (ptr - message)) > Z_MAXPKTLEN){
break;
}
(void) strcpy(ptr, msgbuff);
ptr += strlen(ptr);
}
(void) memset((char *)&notice, 0, sizeof(notice));
notice.z_kind = N_KIND;
notice.z_port = 0;
notice.z_charset = ZCHARSET_UNKNOWN;
notice.z_class = N_CLASS;
notice.z_class_inst = hostname;
notice.z_opcode = N_OPCODE;
notice.z_sender = 0;
notice.z_message_len = 0;
notice.z_recipient = "";
notice.z_default_format = N_DEF_FORMAT;
retval = ZSendList(&notice, msg, N_FIELD_CNT, ZAUTH);
#ifdef HAVE_KRB4
(void) dest_tkt();
#endif
if (retval != ZERR_NONE) {
com_err(argv[0], retval, "while sending notice");
exit(1);
}
return 0;
}

56
clients/zstat/Makefile.in Normal file
View File

@ -0,0 +1,56 @@
SHELL=@SHELL@
prefix=@prefix@
exec_prefix=@exec_prefix@
datadir=@datadir@
sysconfdir=@sysconfdir@
sbindir=@sbindir@
lsbindir=@lsbindir@
datarootdir=@datarootdir@
includedir=@includedir@
mandir=@mandir@
libdir=@libdir@
bindir=@bindir@
top_builddir=../..
srcdir=@srcdir@
top_srcdir=@top_srcdir@
BUILDTOP=../..
VPATH=@srcdir@
LIBTOOL=@LIBTOOL@
CC=@CC@
INSTALL=@INSTALL@
LIBZEPHYR=${BUILDTOP}/lib/libzephyr.la
CPPFLAGS=@CPPFLAGS@
CFLAGS=@CFLAGS@
ALL_CFLAGS=${CFLAGS} -I${top_srcdir}/h -I${BUILDTOP}/h ${CPPFLAGS}
LDFLAGS=@LDFLAGS@
LIBS=${LIBZEPHYR} @LIBS@ -lcom_err
OBJS= zstat.o
all: zstat
zstat: ${OBJS} ${LIBZEPHYR}
${LIBTOOL} --mode=link ${CC} ${LDFLAGS} -o $@ ${OBJS} ${LIBS}
.c.o:
${CC} -c ${ALL_CFLAGS} $<
check:
install: zstat
${LIBTOOL} --mode=install ${INSTALL} -m 755 zstat ${DESTDIR}${bindir}
${INSTALL} -m 644 ${srcdir}/zstat.8 ${DESTDIR}${mandir}/man8
clean:
${LIBTOOL} --mode=clean rm -f zstat
rm -f ${OBJS}
${OBJS}: zserver.h ${top_srcdir}/h/sysdep.h ${BUILDTOP}/h/config.h
${OBJS}: ${BUILDTOP}/h/zephyr/zephyr.h ${BUILDTOP}/h/zephyr/zephyr_err.h
.PHONY: all check install clean

26
clients/zstat/zserver.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef __ZSERVER_H__
#define __ZSERVER_H__
/* This file is part of the Project Athena Zephyr Notification System.
* It contains declarations for use in the server.
*
* Created by: John T. Kohl
*
* $Id$
*
* Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#define ADMIN_HELLO "HELLO" /* Opcode: hello, are you there */
#define ADMIN_IMHERE "IHEARDYOU" /* Opcode: yes, I am here */
#define ADMIN_SHUTDOWN "GOODBYE" /* Opcode: I am shutting down */
#define ADMIN_BDUMP "DUMP_AVAIL" /* Opcode: I will give you a dump */
#define ADMIN_DONE "DUMP_DONE" /* Opcode: brain dump for this server
is complete */
#define ADMIN_NEWCLT "NEXT_CLIENT" /* Opcode: this is a new client */
#define ADMIN_LOST_CLT "LOST_CLIENT" /* Opcode: client not ack'ing */
#define ADMIN_KILL_CLT "KILL_CLIENT" /* Opcode: client is dead, remove */
#define ADMIN_STATUS "STATUS" /* Opcode: please send status */
#endif /* !__ZSERVER_H__ */

51
clients/zstat/zstat.8 Normal file
View File

@ -0,0 +1,51 @@
.\" $Id$
.\"
.\" Copyright 1987,1988 by the Massachusetts Institute of Technology
.\" All rights reserved. The file /usr/include/zephyr/mit-copyright.h
.\" specifies the terms and conditions for redistribution.
.\"
.\"
.TH ZSTAT 8 "July 1, 1988" "MIT Project Athena"
.ds ]W MIT Project Athena
.SH NAME
zstat \- display Zephyr statistics
.SH SYNOPSIS
.B zstat
[
.BI -h
] [
.BI -s
] [
.BI host \ ...
]
.SH DESCRIPTION
.I Zstat
is used to display statistics reported by a HostManager,
.I zhm(8),
or a Zephyr Server
.I zephyrd(8),
or both.
.TP 12
.B \-h
is used to indicate that only HostManager statistics should be displayed.
.TP
.B \-s
is used to indicate that only server statistics should be displayed.
.TP
If no hosts are specified, the current host is assumed.
When both HostManager and server statistics are displayed,
statistics from the current server for each host are displayed.
.SH SEE ALSO
zephyr(1), zhm(8), zephyrd(8)
.br
Project Athena Technical Plan Section E.4.1, `Zephyr Notification
Service'
.SH AUTHOR
.PP
David C. Jedlinsky (MIT-Project Athena)
.SH RESTRICTIONS
Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.
All Rights Reserved.
.br
.I zephyr(1)
specifies the terms and conditions for redistribution.

312
clients/zstat/zstat.c Normal file
View File

@ -0,0 +1,312 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains the zstat program.
*
* Created by: David C. Jedlinsky
*
* $Id$
*
* Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
/* There should be library interfaces for the operations in zstat; for now,
* however, zstat is more or less internal to the Zephyr system. */
#include <internal.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include "zserver.h"
#if !defined(lint) && !defined(SABER)
static const char rcsid_zstat_c[] = "$Id$";
#endif
const char *hm_head[] = {
"Current server =",
"Items in queue:",
"Client packets received:",
"Server packets received:",
"Server changes:",
"Version:",
"Looking for a new server:",
"Time running:",
"Size:",
"Machine type:"
};
#define HM_SIZE (sizeof(hm_head) / sizeof (char *))
const char *srv_head[] = {
"Current server version =",
"Packets handled:",
"Uptime:",
"Server states:",
};
#define SRV_SIZE (sizeof(srv_head) / sizeof (char *))
int outoftime = 0;
int serveronly = 0,hmonly = 0;
u_short srv_port;
void usage(char *);
void do_stat(char *);
int srv_stat(char *);
int hm_stat(char *, char *);
static RETSIGTYPE
timeout(int ignored)
{
outoftime = 1;
}
int
main(int argc,
char *argv[])
{
Code_t ret;
char hostname[NS_MAXDNAME];
int optchar;
struct servent *sp;
if ((ret = ZInitialize()) != ZERR_NONE) {
com_err("zstat", ret, "initializing");
exit(-1);
}
if ((ret = ZOpenPort((u_short *)0)) != ZERR_NONE) {
com_err("zstat", ret, "opening port");
exit(-1);
}
while ((optchar = getopt(argc, argv, "sh")) != EOF) {
switch(optchar) {
case 's':
serveronly++;
break;
case 'h':
hmonly++;
break;
case '?':
default:
usage(argv[0]);
exit(1);
}
}
if (serveronly && hmonly) {
fprintf(stderr,"Only one of -s and -h may be specified\n");
exit(1);
}
sp = getservbyname(SERVER_SVCNAME,"udp");
srv_port = (sp) ? sp->s_port : SERVER_SVC_FALLBACK;
if (optind == argc) {
do_stat("127.0.0.1");
exit(0);
}
for (;optind<argc;optind++)
do_stat(argv[optind]);
exit(0);
}
void
do_stat(char *host)
{
char srv_host[NS_MAXDNAME];
if (serveronly) {
(void) srv_stat(host);
return;
}
if (hm_stat(host,srv_host))
return;
if (!hmonly)
(void) srv_stat(srv_host);
}
int
hm_stat(char *host,
char *server)
{
struct in_addr inaddr;
Code_t code;
char *line[20],*mp;
unsigned int i,nf;
struct hostent *hp;
time_t runtime;
struct tm *tim;
ZNotice_t notice;
if ((inaddr.s_addr = inet_addr(host)) == (unsigned)(-1)) {
if ((hp = gethostbyname(host)) == NULL) {
fprintf(stderr,"Unknown host: %s\n",host);
exit(-1);
}
(void) memcpy((char *) &inaddr, hp->h_addr, hp->h_length);
printf("Hostmanager stats: %s\n", hp->h_name);
} else {
printf("Hostmanager stats: %s\n", host);
}
if ((code = ZhmStat(&inaddr, &notice)) != ZERR_NONE) {
com_err("zstat", code, "getting hostmanager status");
exit(-1);
}
mp = notice.z_message;
for (nf=0;mp<notice.z_message+notice.z_message_len;nf++) {
line[nf] = mp;
mp += strlen(mp)+1;
}
(void) strcpy(server,line[0]);
printf("HostManager protocol version = %s\n",notice.z_version);
for (i=0; (i < nf) && (i < HM_SIZE); i++) {
if (!strncmp("Time",hm_head[i],4)) {
runtime = atol(line[i]);
tim = gmtime(&runtime);
printf("%s %d days, %02d:%02d:%02d\n", hm_head[i],
tim->tm_yday,
tim->tm_hour,
tim->tm_min,
tim->tm_sec);
}
else
printf("%s %s\n",hm_head[i],line[i]);
}
printf("\n");
ZFreeNotice(&notice);
return(0);
}
int
srv_stat(char *host)
{
char *line[20],*mp;
int sock,i,nf,ret;
struct hostent *hp;
struct sockaddr_in sin;
ZNotice_t notice;
time_t runtime;
struct tm *tim;
#ifdef _POSIX_VERSION
struct sigaction sa;
#endif
(void) memset((char *) &sin, 0, sizeof(struct sockaddr_in));
sin.sin_port = srv_port;
if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket:");
exit(-1);
}
sin.sin_family = AF_INET;
if ((sin.sin_addr.s_addr = inet_addr(host)) == (unsigned)(-1)) {
if ((hp = gethostbyname(host)) == NULL) {
fprintf(stderr,"Unknown host: %s\n",host);
exit(-1);
}
(void) memcpy((char *) &sin.sin_addr, hp->h_addr, hp->h_length);
printf("Server stats: %s\n", hp->h_name);
} else {
printf("Server stats: %s\n", host);
}
(void) memset((char *)&notice, 0, sizeof(notice));
notice.z_kind = UNSAFE;
notice.z_port = 0;
notice.z_charset = ZCHARSET_UNKNOWN;
notice.z_class = ZEPHYR_ADMIN_CLASS;
notice.z_class_inst = "";
notice.z_opcode = ADMIN_STATUS;
notice.z_sender = "";
notice.z_recipient = "";
notice.z_default_format = "";
notice.z_message_len = 0;
if ((ret = ZSetDestAddr(&sin)) != ZERR_NONE) {
com_err("zstat", ret, "setting destination");
exit(-1);
}
if ((ret = ZSendNotice(&notice, ZNOAUTH)) != ZERR_NONE) {
com_err("zstat", ret, "sending notice");
exit(-1);
}
#ifdef _POSIX_VERSION
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = timeout;
(void) sigaction(SIGALRM, &sa, (struct sigaction *)0);
#else
(void) signal(SIGALRM,timeout);
#endif
outoftime = 0;
(void) alarm(10);
if (((ret = ZReceiveNotice(&notice, (struct sockaddr_in *) 0))
!= ZERR_NONE) &&
ret != EINTR) {
com_err("zstat", ret, "receiving notice");
return (1);
}
(void) alarm(0);
if (outoftime) {
fprintf(stderr,"No response after 10 seconds.\n");
return (1);
}
mp = notice.z_message;
for (nf=0;mp<notice.z_message+notice.z_message_len;nf++) {
line[nf] = mp;
mp += strlen(mp)+1;
}
printf("Server protocol version = %s\n",notice.z_version);
for (i=0; i < nf; i++) {
if (i < 2)
printf("%s %s\n",srv_head[i],line[i]);
else if (i == 2) { /* uptime field */
runtime = atol(line[i]);
tim = gmtime(&runtime);
printf("%s %d days, %02d:%02d:%02d\n",
srv_head[i],
tim->tm_yday,
tim->tm_hour,
tim->tm_min,
tim->tm_sec);
} else if (i == 3) {
printf("%s\n",srv_head[i]);
printf("%s\n",line[i]);
} else printf("%s\n",line[i]);
}
printf("\n");
(void) close(sock);
ZFreeNotice(&notice);
return(0);
}
void
usage(char *s)
{
fprintf(stderr,"usage: %s [-s] [-h] [host ...]\n",s);
exit(1);
}

View File

@ -0,0 +1,56 @@
SHELL=@SHELL@
prefix=@prefix@
exec_prefix=@exec_prefix@
datadir=@datadir@
sysconfdir=@sysconfdir@
sbindir=@sbindir@
lsbindir=@lsbindir@
datarootdir=@datarootdir@
includedir=@includedir@
mandir=@mandir@
libdir=@libdir@
bindir=@bindir@
top_builddir=../..
srcdir=@srcdir@
top_srcdir=@top_srcdir@
BUILDTOP=../..
VPATH=@srcdir@
LIBTOOL=@LIBTOOL@
CC=@CC@
INSTALL=@INSTALL@
LIBZEPHYR=${BUILDTOP}/lib/libzephyr.la
CPPFLAGS=@CPPFLAGS@
CFLAGS=@CFLAGS@
ALL_CFLAGS=${CFLAGS} -I${top_srcdir}/h -I${BUILDTOP}/h ${CPPFLAGS}
LDFLAGS=@LDFLAGS@
LIBS=${LIBZEPHYR} @LIBS@ -lcom_err
OBJS= zwrite.o
all: zwrite
zwrite: ${OBJS} ${LIBZEPHYR}
${LIBTOOL} --mode=link ${CC} ${LDFLAGS} -o $@ ${OBJS} ${LIBS}
.c.o:
${CC} -c ${ALL_CFLAGS} $<
check:
install: zwrite
${LIBTOOL} --mode=install ${INSTALL} -m 755 zwrite ${DESTDIR}${bindir}
${INSTALL} -m 644 ${srcdir}/zwrite.1 ${DESTDIR}${mandir}/man1
clean:
${LIBTOOL} --mode=clean rm -f zwrite
rm -f ${OBJS}
${OBJS}: ${top_srcdir}/h/sysdep.h ${BUILDTOP}/h/config.h
${OBJS}: ${BUILDTOP}/h/zephyr/zephyr.h ${BUILDTOP}/h/zephyr/zephyr_err.h
.PHONY: all check install clean

290
clients/zwrite/zwrite.1 Normal file
View File

@ -0,0 +1,290 @@
.\" $Id$
.\"
.\" Copyright 1987,1988 by the Massachusetts Institute of Technology
.\" All rights reserved. The file /usr/include/zephyr/mit-copyright.h
.\" specifies the terms and conditions for redistribution.
.\"
.\"
.TH ZWRITE 1 "October 26, 1989" "MIT Project Athena"
.ds ]W MIT Project Athena
.SH NAME
zwrite \- write to another user via Zephyr
.SH SYNOPSIS
.B zwrite
[
.BI \-a
] [
.BI \-d
] [
.BI \-v
] [
.BI \-q
] [
.BI \-t
] [
.BI \-u
] [
.BI \-o
] [
.BI \-n
] [
.BI \-l
] [
.BI \-C
] [
.BI \-U
] [
.BI \-O
opcode ] [
.BI \-s
signature ] [
.BI \-c
class ] [
.BI \-i
instance ] [
.BI \-r
realm ] [
.BI \-f
arg ] [
.BI \-S
sender ] [
.BI user \ ...
] [
.BI \-m
.BI message
]
.SH DESCRIPTION
.I Zwrite
sends a message from you to another user through the
.I zephyr(1)
notification service. The user must have subscribed to messages of
the appropriate class and instance using the
.I zctl(1)
program.
.PP
.I Zwrite
understands the following options.
.TP 12
.B \-a
Causes
.I zwrite
to send the message authenticated, using
.I Kerberos
to perform the authentication. This is the default.
.TP
.B \-d
Causes
.I zwrite
to send the message unauthenticated.
.TP
.B \-v
Causes
.I zwrite
to print what type of message it is sending, and whether or not it was
successful.
.TP
.B \-q
Forces
.I zwrite
to suppress information about whether or not the message was sent.
.TP
.B \-t
Prevents
.I zwrite
from expanding tabs in the message into appropriate spaces. Normally
.I zwrite
will expand any tabs it finds into the appropriate number of spaces to
maintain separation based on 8-character tab stops.
.TP
.B \-l
Causes
.I zwrite
to ignore `.' on a line by itself in the input and only end a typed
message when the user types the end-of-file character (usually
control-D). When the input is not a terminal, this is the default action.
.TP
.B \-u
Sends an urgent message. This changes the
.I zephyr
instance of the message to ``URGENT''.
.TP
.B \-o
Causes
.I zwrite
to ignore the Zephyr variables
.IR zwrite-class ,
.IR zwrite-inst ,
and
.I zwrite-opcode
when picking a default class, instance, and opcode.
.TP
.B \-n
prevents
.I zwrite
from sending a PING message to verify the recipient is subscribing to
messages. By default,
.I zwrite
will send a notice to the destination class, instance, and recipient,
with opcode ``PING'' before sending the message. If the PING is sent,
and the server response indicates there are no recipients subscribed to
your message,
.I zwrite
exits without sending a message.
When the
.B \-n
option is used, no PING is sent.
.TP
.B \-C
prepends a "CC:" line to the body of the message indicating the
recipients of the message. This is strictly a convenience: the
presence of a "CC:" line at the top of a zephyr body does not
necessarily indicate that this option was used, or that the message
really was sent to the listed users, and its lack doesn't indicate
that the message was not sent to multiple users.
.TP
.B \-U
Send an unacked message.
.I zwrite
will not wait for acknowledgement that the message was sent, nor will
it issue a PING before sending.
.TP
.B \-s \fIsignature\fR
sets the signature to be included in the message. This overrides both
the user's name (as found in the password file) and any
setting of the Zephyr variable
.IR zwrite-signature .
.I signature
must
be a single argument, hence when using a shell it should be quoted with
double quotes. A
.I signature
argument of "" leaves the signature in
the message empty.
.TP
.B \-c \fIclass\fR
Allows a user to specify a different class for the message. This allows
a message to be sent to a large group of people with some degree of
security. See
.I zephyr(1)
and
.I zephyrd(8)
for a description of how to restrict access to classes. When this option
is specified, the message is sent to recipient "*" unless an additional
list of recipients is specified.
.br
This argument may not be used in conjunction with the \-f option.
.TP
.B \-i \fIinstance\fR
Allows a user to specify a different instance than the default.
When this option is used, the message is sent to recipient "*" unless an
additional list of recipients is specified. This allows a message to be
sent to a large group of people (e.g. a development group) just by having
the members subscribe to messages of class "MESSAGE", the specified instance,
and recipient "*".
.br
This argument may not be used in conjunction with the \-f option.
.TP
.B \-r \fIrealm\fR
Allows a user to specify a different realm for the message, if the
server supports interrealm Zephyr.
.TP
.B \-S \fIsender\fR
Specify a sender. The message will be sent unauthenticated.
.TP
.B \-F \fIformat\fR
Allows a user to specify a different default format for the message.
.TP
.B \-O \fIopcode\fR
Allows a user to specify a different opcode for the message.
Some Zephyr notice display programs may use the opcode to decide how
to display a notice.
.TP
.B \-f \fIarg\fR
Allows a user to specify an argument to be interpreted as a filesystem
specification. The class is set to
.BR FILSRV .
he instance is set
to
.I arg
as modified:
If
.I arg
contains no colons (`:'), it is assumed to
be a host name, and it is converted into an official host name via
.I gethostbyname(3).
If
.I arg
contains a colon, the portion preceding the colon is
treated as a host name, and the colon and any trailing characters are
appended to the offical host name returned by
.I gethostbyname.
If the name fails to resolve into an official host name, the instance is
set to
.I arg
unmodified.
.br
This option may not be used in conjunction with the \-c or \-i option.
.TP
.B \-m
.I Zwrite
sends the remaining arguments on the command line as the message.
.PP
If the
.I \-m
option is not specified, the user is prompted for the message to be
sent. The message may be terminated by typing ^D or ``.'' on a line
by itself.
.PP
The default class for messages is ``MESSAGE'', the default instance
is ``PERSONAL'', andthe default opcode is ``'' (an empty string).
These defaults can be overridden by setting the Zephyr
variables
.IR zwrite-class ,
.IR zwrite-inst ,
and
.IR zwrite-opcode ,
respectively.
Command-line options can override the defaults.
.PP
If the class is ``MESSAGE'' and the instance is either ``PERSONAL'' or
``URGENT'', a recipient must be specified. These comparisons are
case-sensitive.
.PP
Unless the
.B \-s
option is used, the contents of the Zephyr variable
.I zwrite-signature
are used to augment the user's username in the
message. If
.I zwrite-signature
is not set and the
.B \-s
option is not specified, the user's full name (as specified in the
password file) is used instead.
.SH BUGS
Tab expansion should really be done by the receiver of the message.
.br
The \-u option is provided for compatibility with old versions of
.I zwrite
and is not necessarily useful for sending messages to users who do not
have old subscription files.
.SH SEE ALSO
kerberosintro(1), zctl(1), zephyr(1), zwgc(1), zhm(8), zephyrd(8),
gethostbyname(3)
.br
Project Athena Technical Plan Section E.4.1, `Zephyr Notification
Service'
.SH FILES
/etc/passwd
.br
$ZEPHYR_VARS or $HOME/.zephyr.vars
.SH AUTHOR
.PP
.br
Robert S. French (MIT-Project Athena)
.SH RESTRICTIONS
Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.
All Rights Reserved.
.br
.I zephyr(1)
specifies the terms and conditions for redistribution.

568
clients/zwrite/zwrite.c Normal file
View File

@ -0,0 +1,568 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains code for the "zwrite" command.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#include <sysdep.h>
#include <zephyr/mit-copyright.h>
#include <zephyr/zephyr.h>
#include <netdb.h>
#include <pwd.h>
#ifndef lint
static const char rcsid_zwrite_c[] = "$Id$";
#endif /* lint */
#define DEFAULT_CLASS "MESSAGE"
#define DEFAULT_INSTANCE "PERSONAL"
#define URGENT_INSTANCE "URGENT"
#define DEFAULT_OPCODE ""
#define FILSRV_CLASS "FILSRV"
#define MAXRECIPS 100
int nrecips, msgarg, verbose, quiet, nodot, cc;
char *whoami, *inst, *class, *opcode, *realm, *recips[MAXRECIPS], *sender = 0;
Z_AuthProc auth;
ZNotice_Kind_t kind = ACKED;
void un_tabify(char **, int *);
char *fix_filsrv_inst(char *);
void usage(char *);
void send_off(ZNotice_t *, int);
int
main(int argc, char *argv[])
{
int retval, arg, nocheck, nchars, msgsize, filsys, tabexpand;
char *message, *signature = NULL, *format = NULL;
static char bfr[BUFSIZ], classbfr[BUFSIZ], instbfr[BUFSIZ], sigbfr[BUFSIZ];
static char opbfr[BUFSIZ];
static ZNotice_t notice;
char *charset = NULL;
whoami = argv[0];
if ((retval = ZInitialize()) != ZERR_NONE) {
com_err(whoami, retval, "while initializing");
exit(1);
}
if (argc < 2)
usage(whoami);
auth = ZAUTH;
verbose = quiet = msgarg = nrecips = nocheck = filsys = nodot = 0;
tabexpand = 1;
class = ZGetVariable("zwrite-class");
if (class) {
(void) strcpy(classbfr, class);
class = classbfr;
}
else
class = DEFAULT_CLASS;
inst = ZGetVariable("zwrite-inst");
if (inst) {
(void) strcpy(instbfr, inst);
inst = instbfr;
}
else
inst = DEFAULT_INSTANCE;
opcode = ZGetVariable("zwrite-opcode");
if (opcode)
opcode = strcpy(opbfr, opcode);
else
opcode = DEFAULT_OPCODE;
signature = ZGetVariable("zwrite-signature");
if (signature) {
(void) strcpy(sigbfr, signature);
signature = sigbfr;
}
arg = 1;
for (;arg<argc && !msgarg; arg++) {
if (*argv[arg] != '-') {
recips[nrecips++] = argv[arg];
continue;
}
if (strlen(argv[arg]) > 2)
usage(whoami);
switch (argv[arg][1]) {
case 'a': /* Backwards compatibility */
auth = ZAUTH;
break;
case 'o':
class = DEFAULT_CLASS;
inst = DEFAULT_INSTANCE;
opcode = DEFAULT_OPCODE;
break;
case 'd':
auth = ZNOAUTH;
break;
case 'v':
verbose = 1;
break;
case 'q':
quiet = 1;
break;
case 'n':
nocheck = 1;
break;
case 't':
tabexpand = 0;
break;
case 'u':
inst = URGENT_INSTANCE;
break;
case 'O':
if (arg == argc-1)
usage(whoami);
arg++;
opcode = argv[arg];
break;
case 'i':
if (arg == argc-1 || filsys == 1)
usage(whoami);
arg++;
inst = argv[arg];
filsys = -1;
break;
case 'c':
if (arg == argc-1 || filsys == 1)
usage(whoami);
arg++;
class = argv[arg];
filsys = -1;
break;
case 'f':
if (arg == argc-1 || filsys == -1)
usage(whoami);
arg++;
class = FILSRV_CLASS;
inst = fix_filsrv_inst(argv[arg]);
filsys = 1;
nocheck = 1; /* implied -n (no ping) */
break;
case 's':
if (arg == argc-1)
usage(whoami);
arg++;
signature = argv[arg];
break;
case 'm':
if (arg == argc-1)
usage(whoami);
nocheck = 1; /* implied -n (no ping) */
msgarg = arg+1;
break;
case 'l': /* literal */
nodot = 1;
break;
case 'F':
if (arg == argc-1)
usage(whoami);
arg++;
format = argv[arg];
break;
case 'r':
if (arg == argc-1)
usage(whoami);
arg++;
realm = argv[arg];
break;
case 'C':
cc = 1;
break;
case 'x':
if (arg == argc-1)
usage(whoami);
arg++;
charset = argv[arg];
break;
case 'S':
if (arg == argc-1)
usage(whoami);
arg++;
sender = argv[arg];
auth = ZNOAUTH;
break;
case 'U':
kind = UNACKED;
nocheck = 1; /* implied -n (no ping) */
break;
default:
usage(whoami);
}
}
if (!nrecips && !(strcmp(class, DEFAULT_CLASS) ||
(strcmp(inst, DEFAULT_INSTANCE) &&
strcmp(inst, URGENT_INSTANCE)))) {
/* must specify recipient if using default class and
(default instance or urgent instance) */
fprintf(stderr, "No recipients specified.\n");
usage(whoami);
}
if (!signature) {
/* try to find name in the password file */
register struct passwd *pwd;
register char *cp = sigbfr;
register char *cp2, *pp;
pwd = getpwuid(getuid());
if (pwd) {
cp2 = pwd->pw_gecos;
for (; *cp2 && *cp2 != ',' ; cp2++) {
if (*cp2 == '&') {
pp = pwd->pw_name;
*cp++ = islower(*pp) ? toupper(*pp) : *pp;
pp++;
while (*pp)
*cp++ = *pp++;
} else
*cp++ = *cp2;
}
signature = sigbfr;
}
}
memset(&notice, 0, sizeof(ZNotice_t));
notice.z_kind = kind;
notice.z_port = 0;
notice.z_class = class;
notice.z_class_inst = inst;
notice.z_opcode = "PING";
notice.z_sender = sender;
notice.z_message_len = 0;
notice.z_recipient = "";
notice.z_charset = ZGetCharset(charset);
if (format)
notice.z_default_format = format;
else
notice.z_default_format = "http://zephyr.1ts.org/wiki/df";
if (!nocheck && nrecips)
send_off(&notice, 0);
if (!msgarg && isatty(0)) {
if (nodot)
printf("Type your message now. End with the end-of-file character.\n");
else
printf("Type your message now. End with control-D or a dot on a line by itself.\n");
}
message = NULL;
msgsize = 0;
if (signature) {
message = malloc((unsigned)(strlen(signature)+2));
(void) strcpy(message, signature);
msgsize = strlen(message);
message[msgsize++] = '\0';
} else {
message = malloc(1);
message[msgsize++] = '\0';
}
if (cc && nrecips > 1) {
int size = msgsize;
for (arg=0;arg<nrecips;arg++)
size += (strlen(recips[arg]) + 2);
size += 6; /* for the newlines and "cc: " */
message = realloc(message, (unsigned) size);
(void) strcpy(message+msgsize, "CC: ");
msgsize += 4;
for (arg=0;arg<nrecips;arg++) {
(void) strcpy(message+msgsize, recips[arg]);
msgsize += strlen(recips[arg]);
if (arg != nrecips-1) {
message[msgsize] = ' ';
msgsize++;
}
}
message[msgsize] = '\n';
msgsize += 1;
}
if (msgarg) {
int size = msgsize;
for (arg=msgarg;arg<argc;arg++)
size += (strlen(argv[arg]) + 1);
size++; /* for the newline */
message = realloc(message, (unsigned) size);
for (arg=msgarg;arg<argc;arg++) {
(void) strcpy(message+msgsize, argv[arg]);
msgsize += strlen(argv[arg]);
if (arg != argc-1) {
message[msgsize] = ' ';
msgsize++;
}
}
message[msgsize] = '\n';
msgsize += 1;
} else {
if (isatty(0)) {
for (;;) {
unsigned int l;
if (!fgets(bfr, sizeof bfr, stdin))
break;
if (!nodot && bfr[0] == '.' &&
(bfr[1] == '\n' || bfr[1] == '\0'))
break;
l = strlen(bfr);
message = realloc(message, msgsize+l+1);
(void) strcpy(message+msgsize, bfr);
msgsize += l;
}
if (ferror(stdin)) /* drop the message */
exit(1);
message = realloc(message, (unsigned)(msgsize+1));
}
else { /* Use read so you can send binary messages... */
while ((nchars = read(fileno(stdin), bfr, sizeof bfr))) {
if (nchars == -1) {
fprintf(stderr, "Read error from stdin! Can't continue!\n");
exit(1);
}
message = realloc(message, (unsigned)(msgsize+nchars));
(void) memcpy(message+msgsize, bfr, nchars);
msgsize += nchars;
}
/* end of msg */
message = realloc(message, (unsigned)(msgsize+1));
}
}
notice.z_opcode = opcode;
if (tabexpand)
un_tabify(&message, &msgsize);
notice.z_message = message;
notice.z_message_len = msgsize;
send_off(&notice, 1);
exit(0);
}
void
send_off(ZNotice_t *notice, int real)
{
int i, success, retval;
char realm_recip[BUFSIZ], dest[3 * BUFSIZ];
ZNotice_t retnotice;
success = 0;
for (i=0;i<nrecips || i==0;i++) {
if (realm) {
sprintf(realm_recip, "%s@%s", (nrecips) ? recips[i] : "", realm);
notice->z_recipient = realm_recip;
} else {
notice->z_recipient = (nrecips) ? recips[i] : "";
}
if (nrecips)
strcpy(dest, recips[i]);
else if (!strcmp(class, DEFAULT_CLASS))
sprintf(dest, "instance \"%s\"", inst);
else if (!strcmp(inst, DEFAULT_INSTANCE))
sprintf(dest, "class \"%s\"", class);
else
sprintf(dest, "class \"%s\", instance \"%s\"", class, inst);
if (verbose && real)
printf("Sending %smessage, class %s, instance %s, to %s\n",
auth?"authenticated ":"",
class, inst,
nrecips?notice->z_recipient:"everyone");
if ((retval = ZSendNotice(notice, auth)) != ZERR_NONE) {
com_err(whoami, retval, "while sending notice to %s", dest);
break;
}
if (kind == UNACKED)
continue;
if (real && !quiet) {
if (verbose)
printf("Queued... ");
else
printf("Message queued for %s... ", dest);
fflush(stdout);
}
if ((retval = ZIfNotice(&retnotice, (struct sockaddr_in *) 0,
ZCompareUIDPred,
(char *)&notice->z_uid)) != ZERR_NONE) {
com_err(whoami, retval, "while waiting for acknowledgement for %s",
dest);
continue;
}
if (retnotice.z_kind == SERVNAK) {
if (!quiet) {
printf("Received authorization failure while sending to %s\n",
dest);
}
ZFreeNotice(&retnotice);
break; /* if auth fails, punt */
}
if (retnotice.z_kind != SERVACK || !retnotice.z_message_len) {
if (!quiet) {
printf("Detected server failure while receiving acknowledgement for %s\n",
dest);
}
ZFreeNotice(&retnotice);
continue;
}
if (!strcmp(retnotice.z_message, ZSRVACK_SENT)) {
success = 1;
if (real && !quiet)
printf("sent\n");
} else if (!strcmp(retnotice.z_message, ZSRVACK_NOTSENT)) {
if (verbose && real && !quiet) {
if (strcmp(class, DEFAULT_CLASS)) {
fprintf(stderr, "Not logged in or not subscribing to class %s, instance %s\n",
class, inst);
} else {
fprintf(stderr,
"Not logged in or not subscribing to messages\n");
}
}
else if (!quiet) {
if (!nrecips) {
fprintf(stderr,
"No one subscribing to class %s, instance %s\n",
class, inst);
} else {
if (strcmp(class, DEFAULT_CLASS)) {
fprintf(stderr, "%s: Not logged in or not subscribing to class %s, instance %s\n",
notice->z_recipient, class, inst);
} else {
fprintf(stderr, "%s: Not logged in or not subscribing to messages\n",
notice->z_recipient);
}
}
}
}
else
printf("Internal failure - illegal message field in server response\n");
ZFreeNotice(&retnotice);
}
if (!success)
exit(1);
}
void
usage(char *s)
{
fprintf(stderr,
"Usage: %s [-a] [-o] [-d] [-v] [-q] [-n] [-t] [-u] [-l]\n\
\t[-c class] [-i inst] [-O opcode] [-f fsname] [-s signature] [-C]\n\
\t[user ...] [-F format] [-r realm] [-x charset] [-m message]\n", s);
fprintf(stderr,"\t-f and -c are mutually exclusive\n\
\t-f and -i are mutually exclusive\n\
\trecipients must be specified unless -c or -f specifies a class\n\
\tother than the default class or -i or -f specifies an instance\n\
\tother than the default or urgent instance\n");
exit(1);
}
/*
if the -f option is specified, this routine is called to canonicalize
an instance of the form hostname[:pack]. It turns the hostname into the
name returned by gethostbyname(hostname)
*/
char *
fix_filsrv_inst(char *str)
{
static char fsinst[BUFSIZ];
char *ptr;
struct hostent *hp;
ptr = strchr(str,':');
if (ptr)
*ptr = '\0';
hp = gethostbyname(str);
if (!hp) {
if (ptr)
*ptr = ':';
return(str);
}
(void) strcpy(fsinst, hp->h_name);
if (ptr) {
(void) strcat(fsinst, ":");
ptr++;
(void) strcat(fsinst, ptr);
}
return(fsinst);
}
/* convert tabs in the buffer into appropriate # of spaces.
slightly tricky since the buffer can have NUL's in it. */
#ifndef TABSTOP
#define TABSTOP 8 /* #chars between tabstops */
#endif /* ! TABSTOP */
void
un_tabify(char **bufp,
int *sizep)
{
register char *cp, *cp2;
char *cp3;
register int i;
register int column; /* column of next character */
register int size = *sizep;
for (cp = *bufp, i = 0; size; size--, cp++)
if (*cp == '\t')
i++; /* count tabs in buffer */
if (!i)
return; /* no tabs == no work */
/* To avoid allocation churning, allocate enough extra space to convert
every tab into TABSTOP spaces */
/* only add (TABSTOP-1)x because we re-use the cell holding the
tab itself */
cp = malloc((unsigned)(*sizep + (i * (TABSTOP-1))));
if (!cp) /* XXX */
return; /* punt expanding if memory fails */
cp3 = cp;
/* Copy buffer, converting tabs to spaces as we go */
for (cp2 = *bufp, column = 1, size = *sizep; size; cp2++, size--) {
switch (*cp2) {
case '\n':
case '\0':
/* newline or null: reset column */
column = 1;
*cp++ = *cp2; /* copy the newline */
break;
default:
/* copy the character */
*cp = *cp2;
cp++;
column++;
break;
case '\t':
/* it's a tab, compute how many spaces to expand into. */
i = TABSTOP - ((column - 1) % TABSTOP);
for (; i > 0; i--) {
*cp++ = ' '; /* fill in the spaces */
column++;
(*sizep)++; /* increment the size */
}
(*sizep)--; /* remove one (we replaced the tab) */
break;
}
}
free(*bufp); /* free the old buf */
*bufp = cp3;
return;
}