adding zephyr-im master branch
This commit is contained in:
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