adding zephyr-im master branch
This commit is contained in:
13
clients/Makefile.in
Normal file
13
clients/Makefile.in
Normal 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
56
clients/zaway/Makefile.in
Normal 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
120
clients/zaway/zaway.1
Normal 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
270
clients/zaway/zaway.c
Normal 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(¬ice, (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(¬ice);
|
||||
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(¬ice,fp))) {
|
||||
ZFreeNotice(¬ice);
|
||||
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(¬ice,msg,2,ZNOAUTH)) != ZERR_NONE) {
|
||||
com_err(argv[0],retval,"while sending notice");
|
||||
}
|
||||
free(ptr);
|
||||
ZFreeNotice(¬ice);
|
||||
}
|
||||
}
|
||||
|
||||
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
71
clients/zctl/Makefile.in
Normal 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
319
clients/zctl/zctl.1.in
Normal 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
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
101
clients/zctl/zctl_cmds.ct
Normal 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;
|
56
clients/zleave/Makefile.in
Normal file
56
clients/zleave/Makefile.in
Normal 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
107
clients/zleave/zleave.1
Normal 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
424
clients/zleave/zleave.c
Normal 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 *)¬ice, 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(¬ice, 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 *)¬ice.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
|
56
clients/zlocate/Makefile.in
Normal file
56
clients/zlocate/Makefile.in
Normal 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
76
clients/zlocate/zlocate.1
Normal 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
182
clients/zlocate/zlocate.c
Normal 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(¬ice, NULL)) != ZERR_NONE) {
|
||||
com_err(whoami,retval,"while searching notice queue");
|
||||
continue;
|
||||
}
|
||||
if ((retval = ZParseLocations(¬ice, (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(¬ice);
|
||||
}
|
||||
}
|
||||
return((numfound > 0) ? 0 : 1);
|
||||
}
|
56
clients/znol/Makefile.in
Normal file
56
clients/znol/Makefile.in
Normal 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
109
clients/znol/znol.1
Normal 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
256
clients/znol/znol.c
Normal 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);
|
||||
}
|
57
clients/zshutdown_notify/Makefile.in
Normal file
57
clients/zshutdown_notify/Makefile.in
Normal 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
|
||||
|
43
clients/zshutdown_notify/zshutdown_notify.8
Normal file
43
clients/zshutdown_notify/zshutdown_notify.8
Normal 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.
|
143
clients/zshutdown_notify/zshutdown_notify.c
Normal file
143
clients/zshutdown_notify/zshutdown_notify.c
Normal 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 *)¬ice, 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(¬ice, 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
56
clients/zstat/Makefile.in
Normal 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
26
clients/zstat/zserver.h
Normal 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
51
clients/zstat/zstat.8
Normal 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
312
clients/zstat/zstat.c
Normal 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, ¬ice)) != 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(¬ice);
|
||||
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 *)¬ice, 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(¬ice, 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(¬ice, (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(¬ice);
|
||||
return(0);
|
||||
}
|
||||
|
||||
void
|
||||
usage(char *s)
|
||||
{
|
||||
fprintf(stderr,"usage: %s [-s] [-h] [host ...]\n",s);
|
||||
exit(1);
|
||||
}
|
56
clients/zwrite/Makefile.in
Normal file
56
clients/zwrite/Makefile.in
Normal 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
290
clients/zwrite/zwrite.1
Normal 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
568
clients/zwrite/zwrite.c
Normal 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(¬ice, 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(¬ice, 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(¬ice, 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 *)¬ice->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;
|
||||
}
|
Reference in New Issue
Block a user