From: Greg Brockman Date: Tue, 23 Mar 2010 21:03:07 +0000 (-0400) Subject: Added source for zsend X-Git-Url: http://andersk.mit.edu/gitweb/zcommit.git/commitdiff_plain/a022372912592ef2bf5f1c1bddee391bcaa17b7d Added source for zsend --- diff --git a/bin/zsend b/bin/zsend deleted file mode 100755 index 7dde6b3..0000000 Binary files a/bin/zsend and /dev/null differ diff --git a/src/zsend-0.0.1/Makefile b/src/zsend-0.0.1/Makefile new file mode 100644 index 0000000..e3751b3 --- /dev/null +++ b/src/zsend-0.0.1/Makefile @@ -0,0 +1,50 @@ +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 + diff --git a/src/zsend-0.0.1/ZCkAuth.c b/src/zsend-0.0.1/ZCkAuth.c new file mode 100644 index 0000000..6b65387 --- /dev/null +++ b/src/zsend-0.0.1/ZCkAuth.c @@ -0,0 +1,75 @@ +/* Modifications for tzc by Darrell Kindred , 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 +#else +#include +#define ZAUTH_UNSET (-3) /* from internal.h */ +#include /* 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 +} diff --git a/src/zsend-0.0.1/debian/changelog b/src/zsend-0.0.1/debian/changelog new file mode 100644 index 0000000..0e910aa --- /dev/null +++ b/src/zsend-0.0.1/debian/changelog @@ -0,0 +1,6 @@ +zsend (0.0.1-1) stable; urgency=low + + * Initial Release. + + -- Aaron Solochek Sun, 09 Oct 2005 10:30:00 -0600 + diff --git a/src/zsend-0.0.1/debian/control b/src/zsend-0.0.1/debian/control new file mode 100644 index 0000000..4960cb8 --- /dev/null +++ b/src/zsend-0.0.1/debian/control @@ -0,0 +1,15 @@ +Source: zsend +Section: net +Priority: optional +Maintainer: Aaron Solochek +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. diff --git a/src/zsend-0.0.1/debian/copyright b/src/zsend-0.0.1/debian/copyright new file mode 100644 index 0000000..bce481d --- /dev/null +++ b/src/zsend-0.0.1/debian/copyright @@ -0,0 +1,29 @@ +This package was debianized by Aaron Solochek 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. + +*/ diff --git a/src/zsend-0.0.1/debian/dirs b/src/zsend-0.0.1/debian/dirs new file mode 100644 index 0000000..e772481 --- /dev/null +++ b/src/zsend-0.0.1/debian/dirs @@ -0,0 +1 @@ +usr/bin diff --git a/src/zsend-0.0.1/debian/rules b/src/zsend-0.0.1/debian/rules new file mode 100755 index 0000000..1d06031 --- /dev/null +++ b/src/zsend-0.0.1/debian/rules @@ -0,0 +1,90 @@ +#!/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 + + diff --git a/src/zsend-0.0.1/debian/zsend.files b/src/zsend-0.0.1/debian/zsend.files new file mode 100644 index 0000000..e772481 --- /dev/null +++ b/src/zsend-0.0.1/debian/zsend.files @@ -0,0 +1 @@ +usr/bin diff --git a/src/zsend-0.0.1/lread.c b/src/zsend-0.0.1/lread.c new file mode 100644 index 0000000..852c82e --- /dev/null +++ b/src/zsend-0.0.1/lread.c @@ -0,0 +1,703 @@ +/* + 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 + +#include "lread.h" +#include +#include /* 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 +( +) +" +\ + + + + */ + +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("#", 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 diff --git a/src/zsend-0.0.1/lread.h b/src/zsend-0.0.1/lread.h new file mode 100644 index 0000000..57daf67 --- /dev/null +++ b/src/zsend-0.0.1/lread.h @@ -0,0 +1,71 @@ +/* + 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 /* 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(); diff --git a/src/zsend-0.0.1/zsend.c b/src/zsend-0.0.1/zsend.c new file mode 100644 index 0000000..f3149d0 --- /dev/null +++ b/src/zsend-0.0.1/zsend.c @@ -0,0 +1,334 @@ +/* + 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 use instance \n"); + fprintf(stderr, " -c use class \n"); +#ifdef CMU_INTERREALM + fprintf(stderr, " -r use realm \n"); +#endif + fprintf(stderr, " -s use signature \n"); + fprintf(stderr, " -S use sender \n"); + fprintf(stderr, " -O use opcode \n"); + fprintf(stderr, " -m 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); +}