--- /dev/null
+SHELL = /bin/sh
+
+prefix=/usr
+exec_prefix=${prefix}
+datadir=${prefix}/share
+sysconfdir=${prefix}/etc
+sbindir=${exec_prefix}/sbin
+lsbindir=${sbindir}
+mandir=${prefix}/share/man
+
+includedir=${prefix}/include
+libdir=${exec_prefix}/lib
+bindir=${exec_prefix}/bin
+
+srcdir=
+top_srcdir=
+BUILDTOP=
+CC=gcc -m32
+INSTALL=/usr/bin/install -c
+
+IRFLAGS=-DINTERREALM
+CPPFLAGS=-I/usr/athena/include
+CFLAGS=-g -O2
+ALL_CFLAGS=${CFLAGS} ${IRFLAGS} ${CPPFLAGS}
+LDFLAGS=-L${BUILDTOP}/lib
+#LIBS=-lreadline -L/usr/athena/lib -Wl,-R /usr/athena/lib -lzephyr -lkrb4 -lkrb5 -lcrypto -lcrypt -lresolv -lcom_err -ldl
+LIBS=-lreadline -L/usr/athena/lib -lzephyr -lkrb4 -lkrb5 -lcrypto -lcrypt -lresolv -lcom_err -ldl
+
+OBJS= ZCkAuth.o lread.o
+
+all: zsend
+
+zsend.o: zsend.c
+
+zsend: zsend.o lread.o lread.h ZCkAuth.o
+ ${CC} ${LDFLAGS} -o $@ ZCkAuth.o lread.o zsend.o ${LIBS}
+
+.c.o:
+ ${CC} -c ${ALL_CFLAGS} $<
+
+check:
+
+install: zsend
+ ${INSTALL} -m 755 -s zsend ../../bin
+
+clean:
+ rm -f *.o zsend
+
+.PHONY: all check install clean
+
--- /dev/null
+/* Modifications for tzc by Darrell Kindred <dkindred@cmu.edu>, April 1997:
+ * - cache the kerberos credentials, so we can continue to check auth
+ * even if the user re-kinits.
+ */
+
+/* This file is part of the Project Athena Zephyr Notification System.
+ * It contains source for the ZCheckAuthentication function.
+ *
+ * Created by: Robert French
+ *
+ * /mit/zephyr/src/CVS/zephyr/lib/zephyr/ZCkAuth.c,v
+ * ghudson
+ *
+ * Copyright (c) 1987,1991 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, see the file
+ * "mit-copyright.h".
+ */
+/* /mit/zephyr/src/CVS/zephyr/lib/zephyr/ZCkAuth.c,v 1.21 1995/06/30 22:03:53 ghudson Exp */
+
+
+#if 0
+#include <internal.h>
+#else
+#include <zephyr/zephyr.h>
+#define ZAUTH_UNSET (-3) /* from internal.h */
+#include <stdio.h> /* for NULL */
+#endif
+
+/* Check authentication of the notice.
+ If it looks authentic but fails the Kerberos check, return -1.
+ If it looks authentic and passes the Kerberos check, return 1.
+ If it doesn't look authentic, return 0
+
+ When not using Kerberos, return true if the notice claims to be authentic.
+ Only used by clients; the server uses its own routine.
+ */
+Code_t ZCheckAuthentication(notice, from)
+ ZNotice_t *notice;
+ struct sockaddr_in *from;
+{
+#ifdef ZEPHYR_USES_KERBEROS
+ int result;
+ ZChecksum_t our_checksum;
+ static CREDENTIALS cred;
+ static int got_cred = 0;
+
+ /* If the value is already known, return it. */
+ if (notice->z_checked_auth != ZAUTH_UNSET)
+ return (notice->z_checked_auth);
+
+ if (!notice->z_auth)
+ return (ZAUTH_NO);
+
+ if (!got_cred &&
+ (result = krb_get_cred(SERVER_SERVICE, SERVER_INSTANCE,
+ __Zephyr_realm, &cred)) != 0)
+ return (ZAUTH_NO);
+
+ got_cred = 1;
+
+#ifdef NOENCRYPTION
+ our_checksum = 0;
+#else /* NOENCRYPTION */
+ our_checksum = des_quad_cksum(notice->z_packet, NULL,
+ notice->z_default_format+
+ strlen(notice->z_default_format)+1-
+ notice->z_packet, 0, cred.session);
+#endif /* NOENCRYPTION */
+ /* if mismatched checksum, then the packet was corrupted */
+ return ((our_checksum == notice->z_checksum) ? ZAUTH_YES : ZAUTH_FAILED);
+
+#else /* ZEPHYR_USES_KERBEROS */
+ return (notice->z_auth ? ZAUTH_YES : ZAUTH_NO);
+#endif
+}
--- /dev/null
+zsend (0.0.1-1) stable; urgency=low
+
+ * Initial Release.
+
+ -- Aaron Solochek <aarons@aberrant.org> Sun, 09 Oct 2005 10:30:00 -0600
+
--- /dev/null
+Source: zsend
+Section: net
+Priority: optional
+Maintainer: Aaron Solochek <aarons@aberrant.org>
+Build-Depends: debhelper, bison, libzephyr-dev, libreadline-dev
+Standards-Version: 3.1.1
+
+Package: zsend
+Section: net
+Architecture: any
+Depends: zephyr-clients, ${shlibs:Depends}
+Description: zsend is a stripped zwrite ideal for use in scripts
+ .
+ This package contains the zsend binary for use in zephyr notification
+ scripts.
--- /dev/null
+This package was debianized by Aaron Solochek <aarons@aberrant.org> on
+Mon, 4 Dec 2000 05:28:22 -0500.
+
+Copyright:
+
+/*
+
+Copyright 1987,1988,1995 by the Massachusetts Institute of Technology
+
+All rights reserved.
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of the Massachusetts
+Institute of Technology (M.I.T.) not be used in advertising or publicity
+pertaining to distribution of the software without specific, written
+prior permission.
+
+M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+*/
--- /dev/null
+#!/usr/bin/make -f
+# Sample debian/rules that uses debhelper.
+# GNU copyright 1997 by Joey Hess.
+#
+# This version is for a hypothetical package that builds an
+# architecture-dependant package, as well as an architecture-independent
+# package.
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+# This is the debhelper compatability version to use.
+export DH_COMPAT=3
+
+# This has to be exported to make some magic below work.
+export DH_OPTIONS
+SONAME=3
+
+configure: configure-stamp
+configure-stamp:
+ dh_testdir
+
+ # Add here commands to configure the package.
+ -mkdir build-tree
+ cp *.c build-tree/
+ cp *.h build-tree/
+ cp Makefile build-tree/
+
+build: configure-stamp build-stamp
+build-stamp:
+ dh_testdir
+
+ # Add here commands to compile the package.
+ $(MAKE) -C `pwd`/build-tree
+ touch build-stamp
+
+clean:
+ dh_testdir
+ dh_testroot
+ -rm -f build-stamp configure-stamp
+
+ # Add here commands to clean up after the build process.
+ -rm -rf build-tree debian/tmp
+
+ dh_clean
+
+install: DH_OPTIONS=
+install: build
+ dh_testdir
+ dh_testroot
+ dh_clean -k
+ -rm -rf debian/tmp
+ dh_installdirs
+ mkdir -p debian/tmp/usr/bin/
+
+ # Add here commands to install the package into debian/tmp.
+ cd build-tree&&$(MAKE) DESTDIR=`pwd`/../debian/tmp install
+
+
+# Build architecture-independent files here.
+# Pass -i to all debhelper commands in this target to reduce clutter.
+binary-indep: build install
+
+
+# Build architecture-dependent files here.
+# Pass -a to all debhelper commands in this target to reduce clutter.
+binary-arch: build install
+ dh_testdir
+ dh_testroot
+ set -e; \
+ dh_movefiles -pzsend
+ dh_movefiles --sourcedir=debian/tmp -pzsend
+ dh_installdebconf
+ dh_installdocs
+ dh_installchangelogs
+ dh_strip
+ dh_compress
+ dh_fixperms
+ dh_makeshlibs
+ dh_shlibdeps
+ dh_installdeb
+ dh_gencontrol
+ dh_md5sums
+ dh_builddeb
+
+binary: binary-indep binary-arch
+
+.PHONY: build clean binary-indep binary-arch binary install configure
+
+
--- /dev/null
+/*
+ lread.c: simple sexp-like data structures in C.
+ useful for communication between emacs and C client programs
+
+ Copyright (C) 1992 Nick Thompson (nix@cs.cmu.edu)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ TODO
+
+ add tag checking on CAR, CDR, etc?
+ */
+
+#include <setjmp.h>
+
+#include "lread.h"
+#include <stdio.h>
+#include <string.h> /* for strlen() */
+
+Value *
+vmake_cons(Value *car, Value *cdr)
+{
+ Value *v = ALLOC_VALUE();
+ v->tag = cons;
+ VCAR(v) = car;
+ VCDR(v) = cdr;
+ return v;
+}
+
+Value *
+vmake_symbol(int length, char *data)
+{
+ Value *v = ALLOC_VALUE();
+ v->tag = symbol;
+ VSLENGTH(v) = length;
+ VSDATA(v) = data;
+ return v;
+}
+
+Value *
+vmake_symbol_c(char *s)
+{
+ Value *v = ALLOC_VALUE();
+ v->tag = symbol;
+ VSLENGTH(v) = strlen(s);
+ VSDATA(v) = s;
+ return v;
+}
+
+Value *
+vmake_string(int length, char *data)
+{
+ Value *v = ALLOC_VALUE();
+ v->tag = string;
+ VSLENGTH(v) = length;
+ VSDATA(v) = data;
+ return v;
+}
+
+Value *
+vmake_string_c(char *s)
+{
+ Value *v = ALLOC_VALUE();
+ v->tag = string;
+ VSLENGTH(v) = strlen(s);
+ VSDATA(v) = s;
+ return v;
+}
+
+char *
+vextract_string_c(Value *v)
+{
+ char *s = (char *) malloc(VSLENGTH(v) + 1);
+ memcpy(s, VSDATA(v), VSLENGTH(v));
+ s[VSLENGTH(v)] = '\0';
+ return s;
+}
+
+Value *
+vmake_integer(int n)
+{
+ Value *v = ALLOC_VALUE();
+ v->tag = integer;
+ VINTEGER(v) = n;
+ return v;
+}
+
+Value *
+vmake_var(enum Vtag tag, void **value)
+{
+ Value *v = ALLOC_VALUE();
+ v->tag = var;
+ VVTAG(v) = tag;
+ VVDATA(v) = value;
+ return v;
+}
+
+int
+vlength(Value *l)
+{
+ int i;
+ for (i=0; VTAG(l) == cons; i++, l = VCDR(l))
+ ;
+ return i;
+}
+
+typedef struct {
+ jmp_buf abort; /* nonlocal exit for abort */
+
+ char *input_string; /* input string */
+ int buflen; /* amount left in input string */
+ char *buf; /* pointer into input */
+
+ int strbuflen; /* length of scratch buffer */
+ char *strbuf; /* scratch buffer for building strings */
+} Globals;
+
+Value *read_value(Globals *g);
+Value *read_list(Globals *g);
+
+#define PEEK_CHAR(g) (*(g)->buf)
+#define NEXT_CHAR(g) ((g)->buflen > 0 ? \
+ (void) ((g)->buf++,((g)->buflen--)) : \
+ (void) (ABORT(g, 23)))
+#define ABORT(g, code) longjmp((g)->abort, (code))
+
+/* A pox on languages without coroutines. */
+/* I don't feel like putting the entire state of the parser in data
+ * structures that I can save and restore myself, so if EOF is
+ * encountered while parsing the parser will have to start from
+ * scratch when it gets more data */
+
+void
+expand_strbuf(Globals *g)
+{
+ if (g->strbuflen == 0) {
+ g->strbuflen = 128;
+ g->strbuf = (char *) malloc(g->strbuflen);
+ }
+ else {
+ int newbuflen = 3 * g->strbuflen / 2;
+ char *newbuf = (char *) malloc(newbuflen);
+ memcpy(newbuf, g->strbuf, g->strbuflen);
+ free(g->strbuf);
+ g->strbuf = newbuf;
+ g->strbuflen = newbuflen;
+ }
+}
+
+int parse(int slen, char *s, Value **v)
+{
+ Globals g;
+ int jmpret;
+
+ if (0 == (jmpret = setjmp(g.abort))) { /* successful parse */
+ g.input_string = s;
+ g.buflen = slen;
+ g.buf = g.input_string;
+ g.strbuflen = 0;
+ g.strbuf = NULL;
+ expand_strbuf(&g);
+ *v = read_value(&g);
+ return g.buf - g.input_string;
+ }
+ else { /* return from nonlocal abort */
+ free(g.strbuf);
+ *v = NULL;
+ return 0;
+ }
+}
+
+int
+read_escape(Globals *g, char *c)
+{
+ int valid = 1;
+ int nc = PEEK_CHAR(g);
+
+ switch (nc) {
+ case '\n':
+ valid = 0;
+ NEXT_CHAR(g);
+ break;
+ case 'n':
+ *c = '\n';
+ NEXT_CHAR(g);
+ break;
+ case 't':
+ *c = '\t';
+ NEXT_CHAR(g);
+ break;
+ default:
+ if (nc >= '0' && nc <= '7') {
+ int digits;
+ /* handle octal \nnn notation */
+ *c = 0;
+ for (digits = 0; digits < 3; digits++) {
+ if (nc < '0' || nc > '7')
+ break;
+ *c = (*c * 8) + (nc - '0');
+ NEXT_CHAR(g);
+ nc = PEEK_CHAR(g);
+ }
+ } else {
+ /* backslash followed by some random char, like \q.
+ * (some of these are actually valid, but I don't think prin1 will
+ * produce them, so it's not too critical). */
+ *c = nc;
+ NEXT_CHAR(g);
+ }
+ break;
+ }
+ return valid;
+}
+
+Value *
+read_string(Globals *g)
+{
+ int strpos = 0;
+ Value *v;
+ char c;
+
+#define ADD_CHAR(c) \
+ if (strpos >= g->strbuflen) \
+ expand_strbuf(g); \
+ g->strbuf[strpos++] = (c)
+
+ while (1) {
+ switch (PEEK_CHAR(g)) {
+ case '\"':
+ NEXT_CHAR(g);
+ v = ALLOC_VALUE();
+ v->tag = string;
+ v->value.s.length = strpos;
+ v->value.s.string = (char *) malloc(v->value.s.length);
+ memcpy(v->value.s.string, g->strbuf, v->value.s.length);
+ return v;
+ break;
+ case '\\':
+ NEXT_CHAR(g);
+ if (read_escape(g, &c))
+ ADD_CHAR(c);
+ break;
+ default:
+ ADD_CHAR(PEEK_CHAR(g));
+ NEXT_CHAR(g);
+ break;
+ }
+ }
+}
+
+/* characters
+(
+)
+"
+\
+<white>
+<character>
+<number>
+ */
+
+Value *
+read_num_or_symbol(Globals *g)
+{
+ Value *v;
+ int strpos = 0;
+ int i;
+ int is_integer;
+
+#define ADD_CHAR(c) \
+ if (strpos >= g->strbuflen) \
+ expand_strbuf(g); \
+ g->strbuf[strpos++] = (c)
+
+ while (g->buflen > 0) {
+ switch (PEEK_CHAR(g)) {
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\0':
+ case '\"':
+ case '(':
+ case ')':
+ case '.':
+ goto done;
+ break;
+ case '\\':
+ NEXT_CHAR(g);
+ ADD_CHAR(PEEK_CHAR(g));
+ NEXT_CHAR(g);
+ break;
+ default:
+ ADD_CHAR(PEEK_CHAR(g));
+ NEXT_CHAR(g);
+ break;
+ }
+ }
+ ABORT(g, 23);
+
+ done:
+ /* is this a number or a symbol? */
+ /* assume integer to start */
+ is_integer = 1;
+
+ /* assume no empty strings? */
+
+ /* if the first character is '+' or '-' and that's not the only */
+ /* character it can still be an integer */
+ i = 0;
+ if (strpos > 0) {
+ if (g->strbuf[0] == '-' || g->strbuf[0] == '+') {
+ if (strpos > 1) {
+ i = 1;
+ } else {
+ is_integer = 0;
+ }
+ }
+ }
+
+ while (is_integer && i < strpos) {
+ if (g->strbuf[i] < '0' || g->strbuf[i] > '9')
+ is_integer = 0;
+ i++;
+ }
+
+ if (is_integer) {
+ /* it's an integer */
+ v = ALLOC_VALUE();
+ v->tag = integer;
+ ADD_CHAR('\0');
+ v->value.integer.i = atoi(g->strbuf);
+ }
+ else {
+ /* it's a symbol */
+ if (3 == strpos &&
+ !memcmp(g->strbuf, "nil", 3)) {
+ v = NULL;
+ } else {
+ v = ALLOC_VALUE();
+ v->tag = symbol;
+ v->value.s.length = strpos;
+ v->value.s.string = (char *) malloc(v->value.s.length);
+ memcpy(v->value.s.string, g->strbuf, v->value.s.length);
+ }
+ }
+ return v;
+}
+
+Value *
+read_value(Globals *g)
+{
+ while (g->buflen > 0) {
+ switch (PEEK_CHAR(g)) {
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\0':
+ NEXT_CHAR(g);
+ break;
+ case '\"': /* begin string */
+ NEXT_CHAR(g);
+ return read_string(g);
+ break;
+ case '(':
+ NEXT_CHAR(g);
+ return read_list(g);
+ break;
+ case ')':
+ case '.':
+ return NULL;
+ break;
+ default:
+ return read_num_or_symbol(g);
+ break;
+ }
+ }
+ ABORT(g, 23);
+}
+
+Value *
+read_list(Globals *g)
+{
+ Value *list;
+ Value **tail;
+ Value *v;
+
+ tail = &list;
+ while (g->buflen > 0) {
+ if (NULL == (v = read_value(g))) {
+ switch (PEEK_CHAR(g)) {
+
+ case ')':
+ if (tail != NULL) { /* if no last cdr yet, use nil */
+ *tail = NULL;
+ }
+ NEXT_CHAR(g);
+ return list;
+ break;
+
+ case '.': /* set last cdr explicitly */
+ NEXT_CHAR(g);
+ *tail = read_value(g);
+ if (*tail == NULL) {
+ /* badly formed input ??? */
+ ABORT(g, 13);
+ }
+ tail = NULL;
+ break;
+
+ default:
+ /* badly formed input ??? */
+ ABORT(g, 13);
+ break;
+ }
+ }
+ else { /* read a value, add it to the list */
+ if (NULL == tail) {
+ /* two values after a . in a list. very bad! ??? */
+ ABORT(g, 13);
+ }
+ *tail = ALLOC_VALUE();
+ (*tail)->tag = cons;
+ (*tail)->value.cons.car = v;
+ tail = &(*tail)->value.cons.cdr;
+ }
+ }
+ ABORT(g, 23); /* added this -dkindred */
+}
+
+void free_value(Value *v)
+{
+ switch(VTAG(v)) {
+ case cons:
+ free_value(v->value.cons.car);
+ free_value(v->value.cons.cdr);
+ break;
+ case string:
+ case symbol:
+ free(v->value.s.string);
+ break;
+ default:
+ break;
+ }
+ free(v);
+}
+
+void prin(FILE *f, Value *v);
+
+void
+prinlis(FILE *f, Value *v, int first)
+{
+ switch(VTAG(v)) {
+ case cons: /* continue printing list */
+ if (! first)
+ putc(' ', f);
+ prin(f, v->value.cons.car);
+ prinlis(f, v->value.cons.cdr, 0);
+ break;
+ case nil: /* last elt in list */
+ putc(')', f);
+ break;
+ default: /* dotted pair */
+ putc(' ', f);
+ putc('.', f);
+ putc(' ', f);
+ prin(f, v);
+ putc(')', f);
+ break;
+ }
+}
+
+void
+prin(FILE *f, Value *v)
+{
+ switch (VTAG(v)) {
+ case nil:
+ fputs("\'()", f);
+ break;
+ case cons:
+ putc('(', f);
+ prinlis(f, v, 1);
+ break;
+ case string:
+ /* ??? do quoting of '"' ??? */
+ putc('\"', f);
+ fwrite(v->value.s.string, 1, v->value.s.length, f);
+ putc('\"', f);
+ break;
+ case symbol:
+ /* ??? do quoting of all whitespace and special chars ??? */
+ fwrite(v->value.s.string, 1, v->value.s.length, f);
+ break;
+ case integer:
+ fprintf(f, "%ld", v->value.integer.i);
+ break;
+ default:
+ fputs("#<huh?>", f);
+ break;
+ }
+}
+
+#define CHECK_TAG(v, t) if (VTAG(v) != (t)) return 0
+
+int
+eqv(Value *v1, Value *v2)
+{
+
+ switch (v1->tag) {
+/*
+ case any:
+ return 1;
+ break;
+ */
+ case nil:
+ CHECK_TAG(v2, nil);
+ return 1;
+ break;
+ case cons:
+ CHECK_TAG(v2, cons);
+ return (eqv(VCAR(v1), VCAR(v2)) &&
+ eqv(VCDR(v1), VCDR(v2)));
+ break;
+ case string:
+ CHECK_TAG(v2, string);
+ return (VSLENGTH(v1) == VSLENGTH(v2) &&
+ 0 == memcmp(VSDATA(v1), VSDATA(v2), VSLENGTH(v1)));
+ break;
+ case symbol:
+ CHECK_TAG(v2, symbol);
+ return (VSLENGTH(v1) == VSLENGTH(v2) &&
+ 0 == memcmp(VSDATA(v1), VSDATA(v2), VSLENGTH(v1)));
+ break;
+ case integer:
+ CHECK_TAG(v2, integer);
+ return (VINTEGER(v1) == VINTEGER(v2));
+ break;
+ case var:
+ if (VVTAG(v1) != any)
+ CHECK_TAG(v2, VVTAG(v1));
+ return 1;
+ break;
+ default:
+ fprintf(stderr,"eqv(): bad tag: %d\n",(int)(v1->tag));
+ /* die? */
+ return 0;
+ break;
+ }
+}
+
+Value *
+assqv(Value *key, Value *assoc)
+{
+ Value *pair;
+
+ /* cdr on through */
+ while (VTAG(assoc) == cons) {
+ pair = VCAR(assoc);
+ if (VTAG(pair) == cons && eqv(VCAR(pair), key)) {
+ return pair;
+ }
+ assoc = VCDR(assoc);
+ }
+ return NULL;
+}
+
+int
+destructure(Value *pattern, Value *match)
+{
+ switch (VTAG(pattern)) {
+ case any:
+ return 1;
+ break;
+ case nil:
+ CHECK_TAG(match, nil);
+ return 1;
+ break;
+ case cons:
+ CHECK_TAG(match, cons);
+ return (destructure(VCAR(pattern), VCAR(match)) &&
+ destructure(VCDR(pattern), VCDR(match)));
+ break;
+ case string:
+ CHECK_TAG(match, string);
+ return (VSLENGTH(pattern) == VSLENGTH(match) &&
+ 0 == memcmp(VSDATA(pattern), VSDATA(match), VSLENGTH(pattern)));
+ break;
+ case symbol:
+ CHECK_TAG(match, symbol);
+ return (VSLENGTH(pattern) == VSLENGTH(match) &&
+ 0 == memcmp(VSDATA(pattern), VSDATA(match), VSLENGTH(pattern)));
+ break;
+ case integer:
+ CHECK_TAG(match, integer);
+ return (VINTEGER(pattern) == VINTEGER(match));
+ break;
+ case var:
+ if (VVTAG(pattern) != any)
+ CHECK_TAG(match, VVTAG(pattern));
+ if (VVDATA(pattern) != NULL)
+ *VVDATA(pattern) = (void *) match;
+ return 1;
+ break;
+ default:
+ fprintf(stderr,"destructure(): bad tag: %d\n",(int)VTAG(pattern));
+ /* die? */
+ return 0;
+ break;
+ }
+}
+
+#ifdef TEST
+
+read_and_parse()
+{
+#define BUFLEN 512
+ char buf[BUFLEN]; /* this will have to be dynamically expanded */
+ int bufpos = 0;
+ int ret;
+ Value *v = NULL;
+ Value *match_data;
+ Value *pattern = vmake_cons(vmake_symbol_c("integer"),
+ vmake_var(integer, (void **) &match_data));
+
+ while (1) {
+ ret = read(0, buf + bufpos, BUFLEN - bufpos);
+ if (ret < 0) {
+ perror("read");
+ exit(1);
+ }
+ else {
+ bufpos += ret;
+
+ do {
+ if (v != NULL) {
+ free_value(v);
+ v = NULL;
+ }
+ ret = parse(bufpos, buf, &v);
+ if (ret > 0) {
+ memmove(buf, buf + ret, bufpos - ret);
+ bufpos -= ret;
+ printf("parsed: ");
+ prin(stdout, v);
+ fputc('\n', stdout);
+
+ if (destructure(pattern, v)) {
+ printf("match_data = ");
+ prin(stdout, match_data);
+ fputc('\n', stdout);
+ }
+ else {
+ printf("destructure failed\n");
+ }
+
+ free_value(v);
+ }
+ else
+ printf("EOF\n");
+ } while (ret > 0);
+ }
+ }
+}
+
+main(int argc, char *argv[])
+{
+ read_and_parse();
+#if 0
+ Value *v;
+ v = ALLOC_VALUE();
+
+ v->tag = cons;
+ v->value.cons.car = ALLOC_VALUE();
+ v->value.cons.car->tag = symbol;
+ v->value.cons.car->value.s.length = 6;
+ v->value.cons.car->value.s.string = "symbol";
+
+ v->value.cons.cdr = ALLOC_VALUE();
+ v->value.cons.cdr->tag = cons;
+
+ v->value.cons.cdr->value.cons.car = ALLOC_VALUE();
+ v->value.cons.cdr->value.cons.car->tag = string;
+ v->value.cons.cdr->value.cons.car->value.s.length = 6;
+ v->value.cons.cdr->value.cons.car->value.s.string = "string";
+
+ v->value.cons.cdr->value.cons.cdr = ALLOC_VALUE();
+ v->value.cons.cdr->value.cons.cdr->tag = integer;
+ v->value.cons.cdr->value.cons.cdr->value.integer.i = 23;
+ prin(stdout, v);
+ fputc('\n', stdout);
+#endif
+}
+#endif
--- /dev/null
+/*
+ lread.h Header file for elisp reader and destructurer
+ Copyright (C) 1992 Nick Thompson (nix@cs.cmu.edu)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ This code is useful for communicating with emacs, particularly in
+ subprocesses which are started by emacs. It allows you to do structured
+ ipc by passing printed s-expressions between emacs and the subprocess -
+ strings are parsed into a union "Value" by this code and there is also a
+ fairly convenient way to extract data.
+
+ */
+
+#include <stdlib.h> /* for malloc() */
+
+enum Vtag { any, nil, cons, string, symbol, integer, var };
+
+typedef struct Value Value;
+struct Value {
+ enum Vtag tag;
+ union {
+ /* tag nil has no data */
+ struct { Value *car, *cdr; } cons;
+ struct { int length; char *string; } s; /* tag string or symbol */
+ struct { long i; } integer;
+ struct { enum Vtag tag; void **value; } var;
+ } value;
+};
+
+#define ALLOC_VALUE() ((Value *) malloc(sizeof(Value)))
+
+#define VTAG(v) (v?((v)->tag):nil)
+
+extern Value *vmake_cons(Value *car, Value *cdr);
+#define VCAR(v) ((v)->value.cons.car)
+#define VCDR(v) ((v)->value.cons.cdr)
+
+extern Value *vmake_symbol(int length, char *data);
+extern Value *vmake_symbol_c(char *s);
+extern Value *vmake_string(int length, char *data);
+extern Value *vmake_string_c(char *s);
+extern char *vextract_string_c(Value *v);
+#define VSLENGTH(v) ((v)->value.s.length)
+#define VSDATA(v) ((v)->value.s.string)
+
+extern Value *vmake_integer(int n);
+#define VINTEGER(v) ((v)->value.integer.i)
+
+extern Value *vmake_var(enum Vtag tag, void **value);
+#define VVTAG(v) ((v)->value.var.tag)
+#define VVDATA(v) ((v)->value.var.value)
+
+extern Value *assqv(Value *key, Value *assoc);
+extern int vlength(Value *l);
+
+extern int eqv();
+extern int parse();
+extern void free_value();
--- /dev/null
+/*
+ zsend.c simple zephyr sender
+ Copyright (C) 1994 Darrell Kindred
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <strings.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <ctype.h>
+#include <zephyr/zephyr.h>
+#include <zephyr/zephyr_err.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/file.h>
+#include <signal.h>
+#include <string.h>
+#include <time.h>
+
+#define DEFAULT_CLASS "MESSAGE"
+#define DEFAULT_INSTANCE "PERSONAL"
+#define URGENT_INSTANCE "URGENT"
+#define DEFAULT_OPCODE ""
+#define FILSRV_CLASS "FILSRV"
+#ifdef CMU_INTERREALM
+#define DEFAULT_REALM "ANDREW.CMU.EDU"
+#endif
+
+extern Code_t ZCancelSubscriptions(), ZUnsetLocation(), ZClosePort(),
+ //ZRetrieveSubscriptions(),
+ ZGetSubscriptions(), ZSubscribeTo(),
+ ZSendNotice(), ZInitialize(), ZOpenPort(), ZPending(),
+ ZCompareUID(), ZReceiveNotice(), ZCheckAuthentication(),
+ ZFreeNotice(), ZSetLocation();
+#ifdef CMU_INTERREALM
+extern char *ZExpandRealm();
+#endif
+
+typedef struct PendingReply PendingReply;
+struct PendingReply {
+ char *instance;
+ char *recipient;
+ ZUnique_Id_t uid;
+ PendingReply *next;
+};
+
+struct Globals {
+ const char *program;
+ int argc;
+ const char **argv;
+
+ u_short port;
+ int zfd;
+
+ int debug;
+
+ /* linked list of messages sent which are waiting for replies */
+ PendingReply *pending_replies;
+
+};
+
+struct Globals global_storage, *globals = &global_storage;
+
+void usage(const char *progname) {
+ fprintf(stderr, "usage: %s [options] [recipients]\n", progname);
+ fprintf(stderr, " options:\n");
+ fprintf(stderr, " -i <inst> use instance <inst>\n");
+ fprintf(stderr, " -c <class> use class <class>\n");
+#ifdef CMU_INTERREALM
+ fprintf(stderr, " -r <realm> use realm <realm>\n");
+#endif
+ fprintf(stderr, " -s <sig> use signature <sig>\n");
+ fprintf(stderr, " -S <sender> use sender <sender>\n");
+ fprintf(stderr, " -O <opcode> use opcode <opcode>\n");
+ fprintf(stderr, " -m <msg> send msg instead of reading stdin (must be last arg)\n");
+ fprintf(stderr, " -d print debugging information\n");
+}
+
+void exit_tzc() {
+ ZClosePort();
+ exit(0);
+}
+
+Code_t check(Code_t e, char *s) {
+ if (e) {
+ printf(";;; return code %d\n",(int) e);
+ fflush(stdout);
+ com_err(__FILE__, e, s);
+ exit(1);
+ }
+ return e;
+}
+
+Code_t warn(Code_t e, char *s) {
+ if (e)
+ com_err(__FILE__, e, s);
+ return e;
+}
+
+char *auth_string(int n) {
+ switch (n) {
+ case ZAUTH_YES : return "yes";
+ case ZAUTH_FAILED : return "failed";
+ case ZAUTH_NO : return "no";
+ default : return "bad-auth-value";
+ }
+}
+
+char *kind_string(int n) {
+ switch (n) {
+ case UNSAFE: return "unsafe";
+ case UNACKED: return "unacked";
+ case ACKED: return "acked";
+ case HMACK: return "hmack";
+ case HMCTL: return "hmctl";
+ case SERVACK: return "servack";
+ case SERVNAK: return "servnak";
+ case CLIENTACK: return "clientack";
+ case STAT: return "stat";
+ default: return "bad-kind-value";
+ }
+}
+
+/* warning: this uses ctime which returns a pointer to a static buffer
+ * which is overwritten with each call. */
+char *time_str(time_t time_num)
+{
+ char *now_name;
+ now_name = ctime(&time_num);
+ now_name[24] = '\0'; /* dump newline at end */
+ return(now_name);
+}
+
+/* return time in the format "14:15:03" */
+/* uses ctime, which returns a ptr to a static buffer */
+char *debug_time_str(time_t time_num)
+{
+ char *now_name;
+ now_name = ctime(&time_num);
+ now_name[19] = '\0'; /* strip year */
+ return now_name+11; /* strip date */
+}
+
+void
+setup()
+{
+ check(ZInitialize(), "ZInitialize");
+ globals->port = 0;
+ check(ZOpenPort(&globals->port), "ZOpenPort");
+
+ globals->pending_replies = NULL;
+}
+
+int get_message(char **msg, char *sig) {
+ /* XXX fix this to be dynamic */
+ static char buf[65535];
+ int c, len;
+ char *p;
+ strcpy(buf, sig);
+ len = strlen(sig)+1;
+ p = &(buf[len]);
+ while ((c=getchar()) != EOF) {
+ *p++ = c;
+ len++;
+ }
+ len++;
+ *p = '\0';
+ *msg = buf;
+ return len;
+}
+
+int get_message_arg(char **msg, char *msgptr, char *sig) {
+ /* XXX fix this to be dynamic */
+ static char buf[65535];
+ int c, len;
+ int i = 0;
+ char *p;
+ strcpy(buf, sig);
+ len = strlen(sig)+1;
+ strcpy(&buf[len], msgptr);
+ len += strlen(msgptr)+1;
+ *msg = buf;
+ return len;
+}
+
+int main(int argc, const char *argv[]) {
+ const char *program;
+ const char **recipient;
+ char *msg;
+ int broadcast, msglen;
+ int n_recips = 0;
+ int (*auth)();
+ int use_zctl = 0, sw;
+ int havemsg = 0;
+ int haverealm = 0;
+ extern char *optarg;
+ extern int optind;
+ char location[BUFSIZ];
+ ZNotice_t notice;
+ int retval;
+ char *sender=NULL, *signature="", *instance=DEFAULT_INSTANCE,
+ *class=DEFAULT_CLASS, *opcode=DEFAULT_OPCODE, *msgptr="";
+#ifdef CMU_INTERREALM
+ char *realm=DEFAULT_REALM;
+ char rlmrecip[BUFSIZ];
+ char *cp;
+#endif
+
+ program = strrchr(argv[0], '/');
+ if (program == NULL)
+ program = argv[0];
+ else
+ program++;
+
+ while ((sw = getopt(argc, argv, "di:s:c:S:m:O:r:")) != EOF)
+ switch (sw) {
+ case 'O':
+ opcode = optarg;
+ break;
+ case 'i':
+ instance = optarg;
+ break;
+ case 'c':
+ class = optarg;
+ break;
+ case 's':
+ signature = optarg;
+ break;
+ case 'S':
+ sender = optarg;
+ break;
+ case 'd':
+ /* debug = 1; */
+ break;
+#ifdef CMU_INTERREALM
+ case 'r':
+ realm = optarg;
+ haverealm = 1;
+ break;
+#endif
+ case 'm':
+ msgptr = optarg;
+ havemsg = 1;
+ break;
+ case '?':
+ default:
+ usage(program);
+ exit(1);
+ }
+
+ broadcast = (optind == argc);
+
+ if (broadcast && !(strcmp(class, DEFAULT_CLASS) ||
+ (strcmp(instance, DEFAULT_INSTANCE) &&
+ strcmp(instance, URGENT_INSTANCE)))) {
+ /* must specify recipient if using default class and
+ (default instance or urgent instance) */
+ fprintf(stderr, "No recipients specified.\n");
+ usage(program);
+ exit(1);
+ }
+
+ if(havemsg)
+ msglen = get_message_arg(&msg, msgptr, signature);
+ else
+ msglen = get_message(&msg, signature);
+
+ setup();
+
+ for ( ; broadcast || optind < argc; optind++) {
+ bzero((char *) ¬ice, sizeof(notice));
+
+ notice.z_kind = UNACKED;
+ notice.z_port = 0;
+ notice.z_class = class;
+ notice.z_opcode = opcode;
+ notice.z_sender = sender;
+ notice.z_class_inst = instance;
+#ifdef CMU_INTERREALM
+ if (!broadcast && (cp = strchr(argv[optind], '@'))) {
+ (void) strcpy(rlmrecip, argv[optind]);
+ cp = strchr(rlmrecip, '@');
+ if (cp) {
+ cp++;
+ (void) strcpy(cp, (char *) ZExpandRealm(cp));
+ }
+ notice.z_recipient = rlmrecip;
+ } else if(haverealm) {
+ rlmrecip[0] = '@';
+ (void) strcpy(&rlmrecip[1], (char *) ZExpandRealm(realm));
+ notice.z_recipient = rlmrecip;
+ } else
+#endif
+ notice.z_recipient = (char *) (broadcast ? "" : argv[optind]);
+ notice.z_message = msg;
+ notice.z_message_len = msglen;
+ notice.z_default_format = "@bold(UNAUTHENTIC) Class $class, Instance $instance:\n$message";
+ auth = ZNOAUTH;
+ if (auth == ZAUTH) {
+ notice.z_default_format = "Class $class, Instance $instance:\nTo: @bold($recipient)\n$message";
+ }
+ if ((retval = ZSendNotice(¬ice, auth)) != ZERR_NONE) {
+#if 1
+ char bfr[BUFSIZ];
+ (void) sprintf(bfr, "while sending notice to %s",
+ notice.z_recipient);
+ com_err(__FILE__, retval, bfr);
+#endif
+ fprintf(stderr, "error %d from ZSendNotice while sending to %s\n",
+ retval, notice.z_recipient);
+ exit(1);
+ }
+ if (broadcast)
+ break;
+ }
+ exit(0);
+}