Newsgroups: comp.sources.misc From: A.Raman@massey.ac.nz ("Anand") Subject: v26i034: psimail - UNIX-VMS PSI Mailer, Part01/02 Message-ID: X-Md4-Signature: 2b074a87531e8fdf8a0f4985eb46f283 Date: Wed, 20 Nov 1991 23:49:53 GMT Approved: kent@sparky.imd.sterling.com Submitted-by: A.Raman@massey.ac.nz ("Anand") Posting-number: Volume 26, Issue 34 Archive-name: psimail/part01 Environment: UNIX This package contains the files necessary to make the two binaries: Sendpsimail and Recvpsimail. These programs enable a UNIX machine to communicate via email with Mail servers running PSI_MAILSHR. In most situations these are VAX/VMS machines. The medium of transfer is x.25 and the protocol used is MAIL-11. They have specific relevance to the Pyramid implementation of x.25 (1980) although a hack to port on other platforms should not be too difficult. I will be happy to assist in a port to Sunlink x.25 if necessary. Please see the README for more information. Cheers! venkataraman anand, November 1991 (A.Raman@massey.ac.nz) (6300006412::A.Raman) --------- #! /bin/sh # This is a shell archive. Remove anything before this line, then feed it # into a shell via "sh file" or similar. To overwrite existing files, # type "sh file -c". # The tool that generated this appeared in the comp.sources.unix newsgroup; # send mail to comp-sources-unix@uunet.uu.net if you want that tool. # Contents: psimail psimail/Makefile psimail/recvpsimail.c # psimail/sendpsimail.c # Wrapped by kent@sparky on Tue Nov 12 22:43:53 1991 PATH=/bin:/usr/bin:/usr/ucb ; export PATH echo If this archive is complete, you will see the following message: echo ' "shar: End of archive 1 (of 2)."' if test ! -d 'psimail' ; then echo shar: Creating directory \"'psimail'\" mkdir 'psimail' fi if test -f 'psimail/Makefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'psimail/Makefile'\" else echo shar: Extracting \"'psimail/Makefile'\" \(2867 characters\) sed "s/^X//" >'psimail/Makefile' <<'END_OF_FILE' X# X# Copyright (c) 1991 Computing Services, Massey University, X# Palmerston North, New Zealand X# All rights reserved. X# X# Redistribution and use in source and binary forms, with or without X# modification, are permitted provided that the following conditions X# are met: X# 1. Redistributions of source code must retain the above copyright X# notice, this list of conditions and the following disclaimer. X# 2. Redistributions in binary form must reproduce the above copyright X# notice, this list of conditions and the following disclaimer in the X# documentation and/or other materials provided with the distribution. X# 3. All advertising materials mentioning features or use of this software X# must display the following acknowledgement: X# This product includes software developed by the Systems Software X# Support Group, Computing Services, Massey University, X# Palmerston North, NZ. X# 4. The name of Massey University may not be used to endorse or promote X# products derived from this software without specific prior written X# permission. X# X# THIS SOFTWARE IS PROVIDED BY COMPUTING SERVICES, MASSEY UNIVERSITY X# `AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED X# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR X# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MASSEY UNIVERSITY BE X# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR X# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF X# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS X# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN X# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) X# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE X# POSSIBILITY OF SUCH DAMAGE. X# X# Makefile for recvpsimail and sendpsimail X# $ Log: Makefile,v $ X# Venkataraman Anand, May 91 X# XCC = /bin/cc XCFLAGS = $(DEFS) #-DDEBUG -gx XLDFLAGS = XLIBS = XOBJS = /usr/x25/src/x25lib.o debugmsg.o str.o XRMFLAGS = -f XDEST = /usr/local/etc XMAILER = /usr/local/mail/mailers/psi XDEFS = -DDEBUGDIR='"/tmp"' -DUSER2ALIAS XMAKEFILE = Makefile X Xall: recvpsimail sendpsimail X Xpsi: all $(MAKEFILE) X make install X Xrecvpsimail: recvpsimail.o $(OBJS) X $(CC) $(LDFLAGS) -o $@ recvpsimail.o $(OBJS) $(LIBS) X Xsendpsimail: sendpsimail.o $(OBJS) X $(CC) $(LDFLAGS) -o $@ sendpsimail.o $(OBJS) $(LIBS) X Xdebugmsg.o: debugmsg.c X $(CC) -c $(CFLAGS) debugmsg.c X Xclean: X rm $(RMFLAGS) recvpsimail sendpsimail *.o *~ #*# X X Xinstall: recvpsimail sendpsimail X install -m 755 recvpsimail $(DEST) X install -m 755 sendpsimail $(MAILER) X Xlint:; X lint recvpsimail.c debugmsg.c str.c X lint sendpsimail.c debugmsg.c str.c X X## Xdebugmsg.o: $(MAKEFILE) Xrecvpsimail.o: $(MAKEFILE) recvpsimail.c Xsendpsimail.o: $(MAKEFILE) sendpsimail.c END_OF_FILE if test 2867 -ne `wc -c <'psimail/Makefile'`; then echo shar: \"'psimail/Makefile'\" unpacked with wrong size! fi # end of 'psimail/Makefile' fi if test -f 'psimail/recvpsimail.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'psimail/recvpsimail.c'\" else echo shar: Extracting \"'psimail/recvpsimail.c'\" \(21428 characters\) sed "s/^X//" >'psimail/recvpsimail.c' <<'END_OF_FILE' X#ifndef lint X static char rcsid[] ="$Id: recvpsimail.c version 1.0"; X#endif X/* X * $Log: recvpsimail.c,v $ X * X * This program accepts an incoming x25 connection from a PSI mail site X * by being fired off by x25d. At this stage, its stdin and stdout are X * connected to the x25 line. While receiving the mail message from the X * PSI site in MAIL-11 Protocol, it replies appropriately to the remote X * site, at the same time, making a tcp connection to port 25 (sendmail) X * and passing on the message to the local IP mailing system. X * Venkataraman Anand, 13 apr 91 X */ X X/* X * Copyright (c) 1991 Computing Services, Massey University, X * Palmerston North, New Zealand X * All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * 3. All advertising materials mentioning features or use of this software X * must display the following acknowledgement: X * This product includes software developed by the Systems Software X * Support Group, Computing Services, Massey University, X * Palmerston North, NZ. X * 4. The name of Massey University may not be used to endorse or promote X * products derived from this software without specific prior written X * permission. X * X * THIS SOFTWARE IS PROVIDED BY COMPUTING SERVICES, MASSEY UNIVERSITY X * `AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED X * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR X * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MASSEY UNIVERSITY BE X * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR X * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF X * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS X * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN X * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) X * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE X * POSSIBILITY OF SUCH DAMAGE. X */ X X#define LOGFILE "/usr/spool/log/psimail.log" X X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X X#include X#include X X#include "/usr/x25/src/iocmd.h" X#include "/usr/x25/src/x25.h" X#include "/usr/x25/src/x25errno.h" X X#include "str.h" X Xextern int errno; X X#define isodd(n) ((n) % 2) X#define iseven(n) (!isodd(n)) X X#define MAILSERVER "localhost" X#define DOMAIN "massey.ac.nz" X#define SENDMAIL 25 X X#ifndef DEBUGDIR X# define DEBUGDIR "/tmp" /* Where to create debug files */ X#endif X X/* X * Bit masks used in negotiation: X * The Master mail reserves all even bits. X * On receipt, the slave mail can confirm by setting the next odd bit to 1 X * in its response. Master requests by sending a WILLsomething. Slave can X * confirm by responding with DOsamething. X */ X#define WILLMSGNOTIFY 1 X#define WILLBLKSEND 1 X#define WILLPFXSEND 4 X#define WILLCC 16 X#define DOMSGNOTIFY 2 X#define DOBLKSEND 2 X#define DOPFXSEND 8 X#define DOCC 32 X X#define MAXADDRS 1024 X X/* X * Globals X */ Xstruct { X char *addr; X u_char addrok; X} Addrv[MAXADDRS]; Xint Addrc = 0; Xint Sd = -1,Lun = -1;; Xchar *Prog = "recvpsimail"; Xchar *Sendernode = NULL, *Sender = NULL; Xchar Confirm[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; Xchar Success[] = { 1, 0, 0, 0 }; Xchar Failure[] = { 0, 0, 0, 0 }; Xchar Callaccpt[] = { 1, 0, 15 }; X#ifdef DEBUG Xint Fdd = -1; X#endif X X/* X * Flags related to the protocol X */ Xu_char Willblksend = 0, X Willcc = 0, X Willpfxsend = 0, X Willmsgnotify = 0; X X/* X * forward declarations X */ Xvoid main(); Xchar *savestring(); Xchar *malloc(); Xchar *getsendernode(); Xchar *normalize(); Xchar *makeccline(); Xtime_t time(); X X#ifndef DEBUG X# define debugmsg(Fdd, s) X# define xdebugmsg(Fdd, s,n) X#endif X Xvoid main(argc,argv) Xint argc; Xchar *argv[]; X{ X char *toline, *ccline, *subjline, *p; X char path[100], buf[BUFSIZ]; X int count,i; X int outlun; X X setbuf(stderr,(char *) NULL); X if (argc < 3) { X fprintf(stderr,"%s: Not enough arguments\n",Prog); X finish(1); X } X#ifdef DEBUG X if ((Fdd = opendebug(Prog)) < 0) { X syslog(LOG_ERR, "%s: Unable to open debug file", Prog); X exit(1); X } X#endif X outlun = atoi(argv[2]); X /* X * Open the lun X */ X Lun = x25open(path, 0, 0, X25_ADAPTER, outlun); X if (Lun < 0) { X fprintf(stderr,"%s\n",x25error()); X exit(1); X } X count = read(Lun,buf,1024); /* Call Request */ X debugmsg(Fdd, "* Received call request"); X xdebugmsg(Fdd, (u_char *) buf,count); X if (count < 0) { X syslog(LOG_ERR,"%s: read failed (Call accept): %m: %s",Prog, x25error()); X (void) close(Lun); X exit(1); X } X Sendernode = getsendernode((u_char *) buf, count); X if (Sendernode == NULL) { X syslog(LOG_ERR, "%s: Unable to resolve sender node", Prog); X (void) close(Lun); X exit(1); X } X debugmsg(Fdd, "* Got sender node"); X debugmsg(Fdd, Sendernode); X /* X * accept the call X */ X (void) write(Lun, (char *) Callaccpt, 3); X debugmsg(Fdd, "* Accepting call with:"); X xdebugmsg(Fdd, (u_char *) Callaccpt,3); X /* X * set data mode, so we don't have to form the packet each time X */ X if (ioctl(Lun, (int) IOX25DATA, (char *) &i) < 0) { X syslog(LOG_ERR, "%s: ioctl call failed: %m\n",Prog); X (void) close(Lun); X exit(i); X } X debugmsg(Fdd, "* LUN now set to DATA mode"); X Sd = sendmailsock(); X if (Sd < 0) { X syslog(LOG_ERR,"%s: Can't connect to Mailserver: %m",Prog); X finish(1); X } X debugmsg(Fdd, "* SMTP Entry Message"); X count = insd(buf); /* Read off G'day drivel */ X if (*buf > '3') { X buf[count] = '\0'; X syslog(LOG_ERR,"%s: Sendmail: %s",Prog,buf); X finish(1); X } X /* X * If we get a socket successfully, we must redirect fatal signals so X * we can clean up properly on exit X */ X signalstuff(); X /* X * If we receive the connect initiate, we call a procedure to complete X * the required transaction to confirm the incoming connection. X */ X debugmsg(Fdd, "* Trying to read connect initiate"); X count = read(Lun,buf,BUFSIZ); X if (count < 0) { X syslog(LOG_ERR,"%s: read failed on connect initiate: %s", X Prog, x25error()); X finish(1); X } X debugmsg(Fdd, "* Received connect initiate"); X xdebugmsg(Fdd, (u_char *) buf, count); X if (!conn_init((u_char *) buf,count)) { X syslog(LOG_ERR, "%s: Invalid connect initiate", Prog); X finish(1); X } X (void) sprintf(buf,"HELO cc-server1\n"); X outsd(buf); X count = insd(buf); X if (*buf > '3') { X buf[count] = '\0'; X syslog(LOG_ERR,"%s: Sendmail: %s",Prog,buf); X finish(1); X } X /* X * Once the connect initiate and confirm is through we receive the X * Sender name in one or more packets. X */ X count = read(Lun,buf,BUFSIZ); X if (count < 0) { X syslog(LOG_ERR,"%s: read failed in Sender name: %s", Prog, x25error()); X finish(1); X } X Sender = savestring(buf,count); X p = strchr(Sender, ' '); X if (p) { X *p = '\0'; X while (*p && (*p == ' ' || *p == '\t')) X ++p; X } X (void) sprintf(buf,"MAIL FROM: %s <%s::%s@PSI-GATEWAY.%s> \n", X p? p : "", Sendernode, Sender, DOMAIN); X outsd(buf); X count = insd(buf); X if (*buf > '3') { X buf[count] = '\0'; X syslog(LOG_ERR,"%s: Sendmail: %s",Prog,buf); X finish(1); X } X /* X * Then a list of addressees follows. Each addressee has to be confirmed X * with a 01 00 00 00. This we do if sendmail confirms the address for us. X * Else we send a 00 00 00 00 which indicates failure. Addressees are X * followed by an EOF packet of length 1 null content. X * These addresses will be gathered into a list Addrv[] by getaddressees() X */ X (void) getaddressees(); X if (Addrc == 0) { X syslog(LOG_ERR,"%s: Incoming mail request had no addressees",Prog); X finish(1); X } X#ifdef DEBUG X debugmsg(Fdd, sprintf(buf,"* %d addressee names received",Addrc)); X for (i = 0; i < Addrc; i++) X debugmsg(Fdd, sprintf(buf,"\t%s: %s",Addrv[i].addr, X Addrv[i].addrok? "OK" : "NOK")); X#endif X /* X * Now we get the "To:" line as typed in by the user at the remote end. X * At this stage, we are ready to start sending in the Data to the X * sendmail daemon. X */ X outsd("DATA\n"); X count = insd(buf); X if (*buf > '3') { X buf[count] = '\0'; X syslog(LOG_ERR,"%s: Sendmail: %s",Prog,buf); X finish(1); X } X debugmsg(Fdd, "* Reading `To:' line"); X count = read(Lun,buf,BUFSIZ); X if (count < 0) { X syslog(LOG_ERR,"%s: read failed in getting `To:' line: %s", X Prog, x25error()); X finish(1); X } X /* X * The To: line must be normalized to the local convention for address X * specification. Basically, we extract the username from each addressee, X * and append a domain to it if not already present. X */ X toline = normalize(buf,count); X outsd(toline); X /* X * The next line could either be the CC: line or the Subj: line X * depending on whether the master requested to send the CC line X * or not. If the master did not request to send a CC, then we X * form one ourselves from adressees not found in the `To' line. X */ X if (Willcc) { X debugmsg(Fdd, "* Reading `CC:' line"); X count = read(Lun,buf,BUFSIZ); X if (count < 0) { X syslog(LOG_ERR,"%s: read failed in getting `CC:' line: %s", X Prog, x25error()); X finish(1); X } X ccline = savestring(buf,count); X (void) sprintf(buf,"CC: %s%s",ccline,(buf[count-1] == '\n')? "":"\n"); X outsd(buf); X free(ccline); X } else { X ccline = makeccline(toline); X if (strlen(ccline) > 3) { /* CC line will atleast have CC: */ X debugmsg(Fdd, "* Constructed `CC:' line"); X outsd(ccline); X } X } X debugmsg(Fdd, "* Reading `Subject:' line"); X count = read(Lun,buf,BUFSIZ); X if (count < 0) { X syslog(LOG_ERR,"%s: read failed in getting `Subj:' line: %s", X Prog, x25error()); X finish(1); X } X subjline = savestring(buf,count); X (void) sprintf(buf,"Subject: %s%s",subjline, X (buf[count-1] == '\n')? "":"\n"); X outsd(buf); X free(subjline); X /* X * This is followed by the message text. This can either come X * in blocks of 512 bytes each or in lines. X */ X if (Willblksend) X getmsgblks(); X else X getmsglines(); X outsd(".\n"); /* Signifies end of mail to sendmail */ X count = insd(buf); X if (*buf > '3') { X buf[count] = '\0'; X syslog(LOG_ERR,"%s: Sendmail: %s",Prog,buf); X finish(1); X } X outsd("QUIT\n"); X count = insd(buf); X if (*buf > '3') { X buf[count] = '\0'; X syslog(LOG_ERR,"%s: Sendmail: %s",Prog,buf); X } X /* X * Now we send confirmation of receipt for each addressee to the master X * mail X */ X for (i = 0; i < Addrc; i++) { X debugmsg(Fdd, "* Sending Message confirmation"); X xdebugmsg(Fdd, (u_char *) Success,4); X (void) write(Lun,Success,4); X } X finish(0); X} X Xgetaddressees() X{ X int count; X char buf[BUFSIZ],*p; X X while ((count = read(Lun,buf,BUFSIZ)) > 0) { X if (count == 1 && buf[0] == 0) { /* EOF */ X debugmsg(Fdd, "* Received EOF"); X break; X } X /* X * If the address was typed as psi%XXXXXXX::"User@domain", we X * delete the double quotes. Sendmail will handle the @domain part X * for us. X */ X p = savestring(buf,count); X (void) strrmc(p, '"'); X if (Addrc >= MAXADDRS) { X syslog(LOG_ERR,"%s: %s: Too many addressees",Prog,p); X (void) write(Lun,Failure,4); X (void) sprintf(buf,"%s: Too many addresses",p); X (void) write(Lun,buf,strlen(buf)); X (void) write(Lun,"\0",1); X } X Addrv[Addrc].addr = p; X if (!Addrv[Addrc].addr) { X syslog(LOG_ERR,"%s: Memory allocation failed in getaddressees",Prog); X finish(1); X } X (void) sprintf(buf,"RCPT TO:%s\n",Addrv[Addrc].addr); X outsd(buf); X count = insd(buf); X if (count <= 0) { X syslog(LOG_ERR, "%s: Sendmail not responding to Recepient %s", X Addrv[Addrc].addr); X finish(1); X } X if (*buf > '3') { X p = savestring(buf,count); X syslog(LOG_ERR,"%s: Sendmail: %s",Prog,p); X (void) write(Lun,Failure,4); X debugmsg(Fdd, "* Sending Failure text record"); X (void) write(Lun,p,strlen(p)); X (void) write(Lun,"\0",1); /* EOF */ X free(p); X Addrv[Addrc].addrok = 0; X } else { X (void) write(Lun,Success,4); X Addrv[Addrc].addrok = 1; X } X ++Addrc; X } X return Addrc; X} X Xgetnextc() X{ X static u_char buf[512]; X static int i = 0, count = 0; X X if (i == count) { X count = read(Lun, (char *) buf, 512); X debugmsg(Fdd, "* Block begins"); X xdebugmsg(Fdd, buf, count); X debugmsg(Fdd, "* Block ends"); X if (count == 1 && !buf[0]) { X debugmsg(Fdd, "* Received EOF on block-mode message"); X return -1; X } else if (count <= 0) X return -1; /**/ X i = 0; X } X return ((int) buf[i++]); X} X Xgetmsgblks() X{ X int i, msb, lsb, linelen; X char temp[BUFSIZ], *t; X X debugmsg(Fdd, "* Receiving message in block-mode"); X while ((lsb = getnextc()) != -1 && (msb = getnextc()) != -1) { X linelen = lsb + 256 * msb; X debugmsg(Fdd, sprintf(temp, "* linelen = %d", linelen)); X t = temp; X for (i = 0; i < linelen && i < BUFSIZ - 1; i++) X *t++ = getnextc(); X *t = '\0'; X if (!strcmp(temp,".")) X outsd(".."); /* Hidden dot */ X else X outsd(temp); X if (isodd(linelen)) X (void) getnextc(); /* Discard the padding zero */ X } X} X Xgetmsglines() X{ X char buf[BUFSIZ]; X int count; X X debugmsg(Fdd, "* Receiving message in line-mode"); X while ((count = read(Lun, buf, BUFSIZ)) > 0) { X if (count == 1 && !buf[0]) { X debugmsg(Fdd, "* Received EOF on line-mode Message"); X return; X } X buf[count] = '\0'; X debugmsg(Fdd, buf); X outsd(buf); X } X} X Xconn_init(buf,count) Xu_char buf[]; Xint count; X{ X int i; X X if (count < 4) X return 0; X for (i = 0; i < 4; i++) X Confirm[i] = buf[i]; X Willmsgnotify = buf[4] & WILLMSGNOTIFY; X Willblksend = buf[8] & WILLBLKSEND; X Willpfxsend = buf[8] & WILLPFXSEND; X Willcc = buf[8] & WILLCC; X if (Willmsgnotify) X Confirm[4] |= DOMSGNOTIFY; X if (Willblksend) X Confirm[8] |= DOBLKSEND; X if (Willpfxsend) X Confirm[8] |= DOPFXSEND; X if (Willcc) X Confirm[8] |= DOCC; X Confirm[12] = 2; X Confirm[13] = 2; X debugmsg(Fdd, "* Sending connect confirm"); X xdebugmsg(Fdd, (u_char *) Confirm,16); X (void) write(Lun,Confirm,16); X return 1; X} X Xsendmailsock() X{ X int sock; X struct sockaddr_in server; X struct hostent *hostp; X X sock = socket(AF_INET,SOCK_STREAM,0); X if (sock < 0) X return sock; X hostp = gethostbyname(MAILSERVER); X if ((void *)hostp == NULL) { X syslog(LOG_ERR,"%s: Mailserver is undefined",Prog); X return -1; X } X bzero ((char *)&server,sizeof(server)); X bcopy (hostp->h_addr,(char *)&server.sin_addr,hostp ->h_length); X server.sin_family = hostp->h_addrtype; X server.sin_port = htons(SENDMAIL); X if (connect(sock,(struct sockaddr *)&server,sizeof(server)) < 0) X return -1; X return sock; X} X Xsignalstuff() /* Trap all fatal signals to cleanup */ X{ X int onint(),onterm(),onquit(); X X (void) signal(SIGINT,onint); X (void) signal(SIGTERM,onterm); X (void) signal(SIGQUIT,onquit); X} X Xonint() X{ X syslog(LOG_NOTICE,"%s: Killed by SIGINT",Prog); X finish(1); X} X Xonterm() X{ X syslog(LOG_NOTICE,"%s: Killed by SIGTERM",Prog); X finish(1); X} X Xonquit() X{ X syslog(LOG_NOTICE,"%s: Killed by SIGQUIT",Prog); X finish(1); X} X Xfinish(code) Xint code; X{ X static int fd = -1; X long now; X char buf[128]; X X if (fd > 0) { /* if someone kills us when we are finishing up */ X debugmsg(Fdd, "* Nested finish"); X return; X } X (void) sprintf(buf, "Exit status %d", code); X debugmsg(Fdd, buf); X if (code && Sd > 0) { X debugmsg(Fdd, "* Closed open socket on abort"); X (void) close(Sd); X } X if (code && Lun > 0) { X debugmsg(Fdd, "* Closed open Lun on abort"); X (void) close(Lun); X } X#ifdef DEBUG X if (Fdd > 0) X (void) close(Fdd); X#endif X fd = open(LOGFILE, O_WRONLY | O_APPEND); X if (fd < 0) X fd = open(LOGFILE, O_WRONLY | O_CREAT, 0666); X if (fd < 0) { X syslog(LOG_ERR,"%s: Cannot open logfile: %m", Prog); X exit(code); X } X if (flock(fd, LOCK_EX) < 0) X syslog(LOG_ERR, "%s: Cannot obtain lock on %s: %m", Prog, LOGFILE); X now = time((long *) 0); X (void) sprintf(buf,"exit %d: mail from %s at %s: %d rcpts %s", code, X Sender? Sender : "", X Sendernode? Sendernode : "", X Addrc, X ctime(&now)); X (void) strrmc(buf, '\n'); X (void) strcat (buf, "\n"); X (void) write(fd, buf, strlen(buf)); X (void) flock(fd, LOCK_UN); X (void) close(fd); X exit(code); X} X Xinsd(buf) Xchar *buf; X{ X int c; X X c = read(Sd,buf,BUFSIZ); X if (c < 0) { X syslog(LOG_ERR,"%s: socket read failed: %m",Prog); X finish(1); X } X buf[c] = '\0'; X debugmsg(Fdd, buf); X return c; X} X Xchar *savestring(s,size) Xchar *s; Xint size; X{ X char *p; X X p = malloc((unsigned) size+1); X if (p == NULL) { X syslog(LOG_ERR,"%s: Memory allocation error",Prog); X finish(1); X } X (void) strncpy(p,s,size); X p[size] = '\0'; X (void) strrmc(p,'\r'); X (void) strrmc(p,'\n'); X return p; X} X Xchar *normalize(buf,c) Xchar *buf; Xint c; X{ X static char toline[BUFSIZ+16]; X static int first = 1; X char *addr, *norm, *domain; X X /* X * +16 to BUFSIZ so we will have enough room to strcat some X * diagnostic message to temp even after it is almost filled up. X */ X (void) strcpy(toline,"To:"); X buf[c] = '\0'; X addr = strtok(buf," ,\t\r\n"); X while (addr != NULL) { X (void) strrmc(addr,'"'); /* Remove double quotes if any */ X norm = strrchr(addr,':'); /* Node name */ X if (norm == NULL) X norm = addr; X else X ++norm; X if (strlen(toline) + 1 + strlen(norm) >= BUFSIZ) { X syslog(LOG_ERR,"%s: Too many addressees in the `To:' line",Prog); X (void) strcat(toline,""); X return toline; X } X if (first) X first = 0; X else X (void) strcat(toline,", "); X /* X * Since this is a final mailer, there is no need for domains. X * So it gets stripped off here. X */ X domain = strchr(norm,'@'); /* Domain name */ X if (domain != NULL) X *domain = '\0'; X (void) strcat(toline,norm); X addr = strtok((char *) NULL, " ,\t\r\n"); X } X return toline; X} X Xchar *makeccline(toline) Xchar *toline; X{ X static char ccline[BUFSIZ]; X static int first = 1; X int i; X X (void) strcpy(ccline,"CC:"); X for (i = 0; i < Addrc; i++) X if (stristr(toline,Addrv[i].addr) == NULL) { X if (first) X first = 0; X else X (void) strcat(ccline,", "); X (void) strcat(ccline,Addrv[i].addr); X if (strchr(Addrv[i].addr,'@') == NULL) { X (void) strcat(ccline,"@"); X (void) strcat(ccline,DOMAIN); X } X } X return ccline; X} X Xchar *getsendernode(buf,count) Xu_char *buf; Xint count; X{ X static char callnumber[32]; X char *s = callnumber; X int srclen, dstlen, i; X X if (count < 4) X return (NULL); X /* X * The addresses are in BCD. Each byte contains two digits. If there X * are an odd number of digits in the two address, only the first nibble X * of last byte is of use to us and the second nibble can discarded. X * Ref: RED book CCITT X.25 recommendation (5.2.2.1.3) X * The idea is to get both the dest and src addresses, and take the X * last srclen digits of the address string to be the source address. X */ X dstlen = (int) (buf[3] & 0x0f); /* no. of digits in dest addr */ X srclen = (int) (buf[3] >> 4 & 0x0f); /* Samehow with source addr */ X#ifdef DEBUG X fprintf(stderr,"dstlen = %d, srclen = %d\n", dstlen, srclen); X#endif X if (srclen > 15) { X syslog(LOG_ERR, "%s: Incoming source address longer than 15", Prog); X finish(1); X } X /* X * The source address starts from Byte 4 X */ X for (i = 0; i < srclen+dstlen; i++) { X if (iseven(i)) /* Left digit */ X *s++ = '0' + (int) (buf[i/2 + 4] >>4 & 0x0f); X else /* Right digit */ X *s++ = '0' + (int) (buf[i/2 + 4] & 0x0f); X } X *s = '\0'; X debugmsg(Fdd, "Addressfield is:"); X debugmsg(Fdd, callnumber); X return callnumber + dstlen; X} X Xoutsd(s) Xchar *s; X{ X int len; X char temp [BUFSIZ+16]; X X len = strlen(s); X if (len && s[len-1] == '\n') X s[len-1] = '\0'; X if (len < BUFSIZ) X (void) sprintf(temp,"%s\r\n",s); X else { X syslog(LOG_ERR,"%s: Long line truncated",Prog); X (void) strncpy(temp,s,BUFSIZ); X (void) strcat(temp," \r\n"); X } X debugmsg(Fdd, temp); X if (write(Sd,temp,strlen(temp)) < 0) { X syslog(LOG_ERR,"%s: write to socket failed",Prog); X finish(1); X } X} END_OF_FILE if test 21428 -ne `wc -c <'psimail/recvpsimail.c'`; then echo shar: \"'psimail/recvpsimail.c'\" unpacked with wrong size! fi # end of 'psimail/recvpsimail.c' fi if test -f 'psimail/sendpsimail.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'psimail/sendpsimail.c'\" else echo shar: Extracting \"'psimail/sendpsimail.c'\" \(23825 characters\) sed "s/^X//" >'psimail/sendpsimail.c' <<'END_OF_FILE' X#ifndef lint X char *rcsid[] = "$Id: sendpsimail.c version 1.0"; X#endif X/* X * $Log: sendpsimail.c,v $ X * X * This program is called by sendmail on the mailserver and passed the mail X * message on stdin. The destination addresses are specified on the command X * line like so: 6300006412::ARaman@psi-gateway X * The following are the functions of this program: X * 1. Open an x25 connection to the destination machine X * 2. Accept the incoming mail on stdin from Sendmail. X * 3. Send it to the remote machine through MAIL-11 over x25 X * Venkataraman Anand, 2 may 91 X */ X X/* X * Copyright (c) 1991 Computing Services, Massey University, X * Palmerston North, New Zealand X * All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * 3. All advertising materials mentioning features or use of this software X * must display the following acknowledgement: X * This product includes software developed by the Systems Software X * Support Group, Computing Services, Massey University, X * Palmerston North, NZ. X * 4. The name of Massey University may not be used to endorse or promote X * products derived from this software without specific prior written X * permission. X * X * THIS SOFTWARE IS PROVIDED BY COMPUTING SERVICES, MASSEY UNIVERSITY X * `AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED X * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR X * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MASSEY UNIVERSITY BE X * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR X * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF X * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS X * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN X * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) X * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE X * POSSIBILITY OF SUCH DAMAGE. X */ X X#define LOGFILE "/usr/spool/log/psimail.log" X X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X X#include "/usr/x25/src/iocmd.h" X#include "/usr/x25/src/x25.h" X#include "/usr/x25/src/x25errno.h" X X#include "str.h" X X#define DOMAIN "massey.ac.nz" X X#define PACK_SIZE 256 X#define ERR_RET(e) return (x25errno = (e), -1) X X#define isodd(n) ((n) % 2) X#define iseven(n) (!isodd(n)) X X/* Local defines */ X#define CONTROLLER 0 X#define LINE 0 X X/* X * Bit masks used in negotiation: X * The Master mail reserves all even bits. X * On receipt, the slave mail can confirm by setting the next odd bit to 1 X * in its response. Master requests by sending a WILLsomething. Slave can X * confirm by responding with DOsamething. X */ X#define WILLMSGNOTIFY 1 X#define WILLBLKSEND 1 X#define WILLPFXSEND 4 X#define WILLCC 16 X#define DOMSGNOTIFY 2 X#define DOBLKSEND 2 X#define DOPFXSEND 8 X#define DOCC 32 X#define MSGBLKSIZ 512 X Xextern int errno, x25errno; X X/* X * Globals X */ Xchar *Prog = "sendpsimail"; Xstruct Namelist { X char *name; X int nameok; X struct Namelist *next; X}; Xstruct Node { X char x25addr[16]; X int couldconnect; X struct Namelist *nlist; X} Nodev[BUFSIZ]; Xint Nodec = 0; X Xstruct Msg { X u_char rec[MSGBLKSIZ]; X int size; X}; Xstruct Msg **Msgv; Xint Msgc = 0; X Xchar *Ouraddress = "12"; /* x25 subaddress */ Xchar Sender[BUFSIZ+1] = ""; Xchar *Toline, *Fromline, *Ccline, *Subjline; Xchar *Otherheader[BUFSIZ]; Xint Headerc = 0, Mustbuffer = 0; XFILE *Fpmail = NULL; Xint Lun = -1; X X#ifdef DEBUG X int Fdd = -1; X#else X# define debugmsg(fd,s) X# define xdebugmsg(fd,s,n) X#endif X Xu_char Mail_init[] = { 0xff, 0, 0, 0, 'V', '3', '.', '0', ' ', X 'M', 'A', 'I', 'L', '-', '1', '1' }; Xu_char Conn_init[] = { 3, 0, 0, 7, 0, 0, 0, 0, 1, 0, 0, 0, 2, 2, 0, 0 }; X X/* X * Flags relating to the protocol X */ Xu_char WillBlksend = 0, X WillCc = 0, X WillPfxSend = 0, X WillMsgNotify = 0; X X/* X * forward declarations X */ Xint main(), onpwr(), onint(), onterm(), onpipe(), onquit(), onprof(); Xchar *nextline(); Xchar *user2alias(); XFILE *popen(); Xchar *gets(), *calloc(), *realloc(); Xtime_t time(); X Xmain(argc,argv) Xint argc; Xchar *argv[]; X{ X char buf[BUFSIZ], field[128], fieldval[256], colon[8], *s; X int count, nfails = 0, i; X struct passwd *p; X struct Namelist *nl; X X#ifdef DEBUG X if ((Fdd = opendebug(Prog)) < 0) { X syslog(LOG_ERR, "%s: Unable to open debug file", Prog); X exit(EX_TEMPFAIL); X } X#endif X /* X * resolve default sendername from uid of caller, this will be reset X * later if and when we get a `From:' line in the message header. X */ X p = getpwuid(getuid()); X if (p == NULL) { X syslog(LOG_ERR, "%s: caller doesn't exist in passwd file", Prog); X finish(EX_OSERR); X } X (void) strcpy(Sender, user2alias(p->pw_name)); X debugmsg(Fdd, "* Resolved default sendername:"); X debugmsg(Fdd, Sender); X /* X * First, we parse the addresses passed on the command line and create X * a vector of destinations. X */ X if (makenodev(argc,argv) == 0) { X (void) sprintf(buf, "%s: No Destination nodes specified", Prog); X errlog(buf); X finish(EX_USAGE); X } X /* X * Collect the message upto the end of header. X * The end of header is marked by a single blank line X */ X while (gets(buf) != (char *) NULL) { X if (buf[0] == '\0') /* End of header */ X break; X if (sscanf(buf,"%*[ ] %[^ :] %[:] %[^\r\n]", X field, colon, fieldval) == 3) { X if (!stricmp(field, "TO")) { X if ((Toline = strsave(fieldval)) == NULL) X memerr(); X debugmsg(Fdd, "* Received To: line"); X debugmsg(Fdd, Toline); X } else if (!stricmp(field, "CC")) { X if ((Ccline = strsave(fieldval)) == NULL) X memerr(); X debugmsg(Fdd, "* Received CC: line"); X debugmsg(Fdd, Ccline); X } else if (!stricmp(field, "Subject")) { X if ((Subjline = strsave(fieldval)) == NULL) X memerr(); X debugmsg(Fdd, "* Received Subject: line"); X debugmsg(Fdd, Subjline); X } else if (!stricmp(field, "From")) { X if ((Fromline = strsave(fieldval)) == NULL) X memerr(); X debugmsg(Fdd, "* Received From: line"); X debugmsg(Fdd, Fromline); X } else { /* ignore all other header lines at present */ X debugmsg(Fdd, "* Received other header line"); X debugmsg(Fdd, buf); X } X } else { X debugmsg(Fdd, "* Received other header line"); X debugmsg(Fdd, buf); X } X } X /* X * If there was a Fromline, then we try to reset the sender name. X * The previous one was only a placeholder in case we didn't get sent X * a from line. In general From: addresses will be of the form X * User@DOMAIN, User@machine.DOMAIN or User@machine X * In either case, we are interested only in User because a user can have X * only one mailbox in the campus. X */ X if (Fromline != NULL && sscanf(Fromline, "%*[^<]<%[^>]>", buf) == 1) { X s = strchr(buf, '@'); X if (s != NULL) X *s = '\0'; X (void) strcpy(Sender, user2alias(buf)); X debugmsg(Fdd, "* Reset Sendername from Fromline:"); X debugmsg(Fdd, Sender); X } X /* X * Now if nodec == 1, we know there is only one x25 site to send the X * message to, so there is no need to buffer stdin. X */ X Mustbuffer = (Nodec > 1); X /* X * Now we trap all fatal signals so we can cleanup properly if X * someone kills us. If Lun != -1, then it is probably open and X * needs to be closed. X */ X (void) signal(SIGINT, onint); X (void) signal(SIGPWR, onpwr); X (void) signal(SIGTERM, onterm); X (void) signal(SIGPIPE, onpipe); X (void) signal(SIGQUIT, onquit); X (void) signal(SIGPROF, onprof); X /* X * We now open x25 connections to the specified destinations one by one X * and send the message to all addressees on the same node in the same X * transaction. X */ X for (i = 0; i < Nodec; i++) { X /* X * Connect initiate: X */ X Lun = getlun(Nodev[i].x25addr); X if (Lun < 0) { X Nodev[i].couldconnect = 0; X ++nfails; X continue; /* Go on to the next x25 destination */ X } X /* X * Mark that address as successful X */ X Nodev[i].couldconnect = 1; X /* X * Send sender's name X */ X debugmsg(Fdd, "* Sending sender name"); X outlun(Sender); X /* X * Now send the addressees one by one and receive confirmation for X * them X */ X for (nl = Nodev[i].nlist; nl != NULL; nl = nl->next) { X (void) sprintf(buf, "* Sending Addressee name %s", nl->name); X debugmsg(Fdd, buf); X outlun(nl->name); X count = read(Lun, buf, BUFSIZ); X if (count < 0) { X (void) sprintf(buf,"%s: Error reading Circuit to address %s: %s", X Prog,Nodev[i].x25addr, x25error()); X errlog(buf); X finish(EX_PROTOCOL); X } X if (!(buf[0] & 0x01)) { /* failure */ X nl->nameok = 0; X (void) sprintf(buf, "%s: Error sending to user %s at %s", Prog, X nl->name,Nodev[i].x25addr); X errlog(buf); X failmessage(); X } else X nl->nameok = 1; X } X sendeof(); X /* X * We now need to send the `To:' line and the subject line over X */ X if (Toline == NULL) { X debugmsg(Fdd, "* Constructing To: line"); X (void) sprintf(buf, "%s", Nodev[i].nlist->name); X for (nl = Nodev[i].nlist->next; nl != NULL; nl = nl->next) { X if (strlen(buf) >= BUFSIZ - 100) { X (void) strcat(buf, " "); X break; X } X (void) strcat(buf, " "); X (void) strcat(buf, nl->name); X } X if ((Toline = strsave(buf)) == NULL) X memerr(); X } X debugmsg(Fdd, "* Sending To: line"); X outlun(Toline); X if (WillCc && Ccline != NULL) { X debugmsg(Fdd, "Sending CC: line"); X outlun(Ccline); X } X debugmsg(Fdd, "* Sending Subject: line"); X if (Subjline != NULL) { X outlun(Subjline); X } else X outlun(" "); X debugmsg(Fdd, "* Sending message blocks"); X sendmessage(); X debugmsg(Fdd, "* Sending EOF"); X sendeof(); X /* X * Now we read the confirmation for message delivery to each one X * of the confirmed addressees X */ X for (nl = Nodev[i].nlist; nl != NULL; nl = nl->next) X if (nl->nameok) { X count = read(Lun, buf, BUFSIZ); X if (count < 0) { X (void) sprintf(buf, "%s: Can't read confirmation for %s: %s", X Prog, nl->name, x25error()); X errlog(buf); X } else if (!(buf[0] & 0x01)) { X (void) sprintf(buf, "%s: Failed to deliver to %s", X Prog, nl->name); X errlog(buf); X failmessage(); X } else { X (void) sprintf(buf, "* Confirmation for %s received", nl->name); X debugmsg(Fdd, buf); X } X } X (void) close(Lun); X Lun = -1; X } X if (!nfails) X finish(0); X /* X * If all connections failed, we exit with EX_TEMPFAIL, so sendmail X * will try again. If some connections succeeded, we exit EX_SOFTWARE X * so that sendmail can return the message to the sender. X */ X if (nfails == Nodec) X finish(EX_TEMPFAIL); X /* X * At this stage, we know that some connections, but not all, have failed. X */ X errlog("-- The mailer connected successfully to the following site(s):"); X for (i = 0; i < Nodec; i++) X if (Nodev[i].couldconnect) X errlog(Nodev[i].x25addr); X errlog("-- The mailer was not able to connect to the following site(s):"); X errlog(" Will retry for 3 more days"); X for (i = 0; i < Nodec; i++) X if (!Nodev[i].couldconnect) X errlog(Nodev[i].x25addr); X if (nfails) X finish(EX_SOFTWARE); X finish(0); X} X Xfailmessage() X{ X char buf[BUFSIZ]; X int count; X X errlog("Remote mailer said this:"); X while((count = read(Lun, buf, BUFSIZ)) > 0) { X if (count == 1 && buf[0] == '\0') X return; X buf[count] = '\0'; X errlog(buf); X } X} X X/* X * sendmessage() reads lines from stdin, makes 512 byte blocks from them X * and packs it off to the remote mailer. X */ Xsendmessage() X{ X static int firsttime = 1; X char buf[BUFSIZ], *s; X struct Msg m; X int len, i; X X if (firsttime) { X firsttime = 0; X m.size = 0; X while (nextline(buf) != NULL) { X /* X * Lines over 255 bytes will get truncated at 240 chars. X * Hey! cut out that sour face... We're doing better than the X * VMS implementation here. The VMS mailer will complain and die if X * you try mailing a long line. At least we send part of it across. X */ X if (strlen(buf) > 255) X (void) strcpy(buf+240, ""); X debugmsg(Fdd, "* Next line is:"); X debugmsg(Fdd, buf); X len = strlen(buf); X if (len + 3 >= MSGBLKSIZ) { X (void) strcpy(buf+MSGBLKSIZ-20, " "); X len = strlen(buf); X errlog("The following line was too long: it was truncated"); X errlog(buf); X } X s = buf; X nextchar(&m, (u_char) len % 256); X nextchar(&m, (u_char) len / 256); X while (*s) X nextchar(&m, (u_char) *s++); X if (isodd(len)) X nextchar(&m, 0); X } X xdebugmsg(Fdd, (u_char *) m.rec, m.size); X (void) write(Lun, (char *) m.rec, m.size); X if (Mustbuffer) X bufferit(&m); X else X m.size = 0; X } else { X /* X * We've already been through this once. So just write out the X * message we've been buffering X */ X for (i = 0; i < Msgc; i++) X (void) write(Lun, (char *) Msgv[i]->rec, Msgv[i]->size); X } X} X Xnextchar(mptr,c) Xstruct Msg *mptr; Xu_char c; X{ X mptr->rec[mptr->size++] = c; X if (mptr->size == MSGBLKSIZ) { X xdebugmsg(Fdd, (u_char *) mptr->rec, mptr->size); X (void) write(Lun, (char *) mptr->rec, mptr->size); X if (Mustbuffer) X bufferit(mptr); X mptr->size = 0; X } X} X Xbufferit(mptr) Xstruct Msg *mptr; X{ X static int firsttime = 1; X X if (firsttime) { X firsttime = 0; X Msgv = (struct Msg **) calloc((unsigned) BUFSIZ, sizeof(struct Msg *)); X if (Msgv == NULL) X memerr(); X } else if (Msgc % BUFSIZ == 0) { X Msgv = (struct Msg **) realloc((char *) Msgv, X (unsigned) (Msgc / BUFSIZ + 1) * BUFSIZ); X if (Msgv == NULL) X memerr(); X } X Msgv[Msgc] = (struct Msg *) calloc((unsigned) 1, sizeof(struct Msg)); X if (Msgv[Msgc] == NULL) X memerr(); X bcopy(mptr, Msgv[Msgc], sizeof (struct Msg)); X ++Msgc; X mptr->size = 0; X} X Xsendeof() X{ X (void) write(Lun,"\0",1); X} X Xmakenodev(argc,argv) Xint argc; Xchar *argv[]; X{ X int i, j; X char temp[512], *p; X char x25addr[128], username[128]; X struct Namelist *nl; X X bzero(Nodev, BUFSIZ * sizeof(struct Node)); X for (i = 1; i < argc; i++) { X p = strchr(argv[i],'%'); X if (p) X (void) strcpy(temp,p+1); X else X (void) strcpy(temp,argv[i]); X if (!strnicmp(temp, "pacnet.", 7)) X (void) strcpy(temp, temp+7); X if (sscanf(temp,"%[^:]::%s", x25addr, username) != 2) { X (void) sprintf(temp,"%s: Illegal address: %s", Prog, argv[i]); X errlog(temp); X continue; X } X p = strchr(username, '@'); /* Throw away domain */ X if (p != NULL) X *p = '\0'; X for (j = 0; j < Nodec; j++) { X if (strcmp(Nodev[j].x25addr, x25addr) == 0) X break; X } X if (j == Nodec) { /* No matches found */ X if (Nodec == BUFSIZ) { X (void) sprintf(temp, "%s: Too many destinations specified", Prog); X errlog(temp); X continue; X } X (void) strcpy(Nodev[Nodec].x25addr, x25addr); X Nodev[Nodec].nlist = (struct Namelist *) calloc((unsigned) 1, sizeof X (struct Namelist)); X if (Nodev[Nodec].nlist == NULL) X memerr(); X Nodev[Nodec].nlist->name = strsave(username); X if (Nodev[Nodec].nlist->name == NULL) X memerr(); X ++Nodec; X continue; X } X /* X * Get to the tail of the list, so we can add a new node X */ X for (nl = Nodev[j].nlist; nl->next != NULL; nl = nl->next) X ; /* EMPTY */ X nl->next = (struct Namelist *) calloc((unsigned) 1, X sizeof(struct Namelist)); X if (nl->next == NULL) X memerr(); X nl->next->name = strsave(username); X if (nl->next->name == NULL) X memerr(); X } X return Nodec; X} X X/* X * nextline() returns a pointer to the next line in the mail message. X * First, if a CC line was specified, but not sent because WillCc != 1, X * it returns the Ccline. Then it returns lines accumulated in Otherheader[]. X * After lines in Otherheader[] are exhausted, it gets lines from stdin and X * returns them. After those are finished too, it returns NULL X */ Xchar *nextline(buf) Xchar *buf; X{ X static int hcount = 0; X X if (!WillCc && Ccline != NULL) { X (void) sprintf(buf, "CC: %s", Ccline); X free (Ccline); X Ccline = NULL; X } else if (Headerc > 0 && hcount < Headerc) { X (void) strcpy(buf, Otherheader[hcount]); X free(Otherheader[hcount]); X Otherheader[hcount] = NULL; X ++hcount; X } else if (hcount == Headerc) { X (void) strcpy(buf, ""); X ++hcount; X } else if (gets(buf) == (char *) NULL) X return (NULL); X return buf; X} X Xmemerr() X{ X char temp[BUFSIZ]; X X (void) sprintf(temp, "%s: Internal error: Memory allocation failed",Prog); X errlog(temp); X finish(EX_SOFTWARE); X} X Xx25select(line, controller, adaptor, mode, number, data, datalen) Xint line, controller, adaptor, mode, datalen; Xchar number[]; Xunsigned char data[]; X{ X u_char packet[PACK_SIZE]; X int i, j, err, destlen, srclen; X unsigned char c; X char path[20], addrfield[32]; X X /* X * Build the outgoing call packet X */ X i = 0; X packet[i++] = 0; X packet[i++] = 0; X packet[i++] = CALL_REQUEST; X /* X * Check address length X */ X destlen = strlen(number); X srclen = strlen(Ouraddress); X if (destlen > 15) X ERR_RET(BAD_ADDRESS); X packet[i] = destlen; X packet[i] |= strlen(Ouraddress) << 4; X ++i; X /* X * Format the address field in BCD X */ X (void) sprintf(addrfield, "%s%s", number, Ouraddress); X for (j = 0; j < destlen + srclen; ++j) { X c = addrfield[j] - '0'; X if (c > 9) /* Non decimal number */ X ERR_RET(BAD_ADDRESS); X if (iseven(j)) /* Left BCD digit */ X packet[i++] = (c << 4); X else /* Right BCD digit */ X packet[i-1] += c; X } X packet[i++] = 0; X /* X * User data field X */ X for (j = 0; j < datalen; ++j) X packet[i++] = data[j]; X /* X * Open a free Lun X */ X if ((Lun = x25open(path, line, controller, adaptor, -1)) < 0) X ERR_RET(x25errno); X /* X * Write the outgoing call packet X */ X debugmsg(Fdd, "* Sending Call request"); X xdebugmsg(Fdd, packet, i); X if (write(Lun, (char *) packet, i) < 0) { X err = errno; X (void) close(Lun); X ERR_RET(err); X } X /* X * Wait for the call confirm packet X */ X if ((i = read(Lun, (char *) packet, PACK_SIZE)) < 3) { X err = (i < 0) ? errno : BAD_PACKET; X (void) close(Lun); X ERR_RET(err); X } X debugmsg(Fdd, "* Received Call accept/reject"); X xdebugmsg(Fdd, packet, i); X /* X * Exit if clear received X */ X if (packet[2] == CLEAR_INDICATION || packet[2] == CLEAR_CONFIRMATION) { X (void) close(Lun); X ERR_RET(CALL_CLEARED); X } X /* X * Exit if bad packet received X */ X if (packet[2] != CALL_ACCEPT) { X (void) close(Lun); X ERR_RET(BAD_PACKET); X } X /* X * Set mode (packet or data) X */ X if (mode == DATA_MODE) X if (ioctl(Lun, (int) IOX25DATA, (char *) &i) < 0) { X err = errno; X (void) close(Lun); X ERR_RET(err); X } X /* X * Return the Lun ready for transfer X */ X return (Lun); X} X X/* X * This forms a special call packet and sends its off to the X * specified x25 address. If that site is running PSI mail the call X * request packet will be accepted and we return successfully. X */ Xgetlun(addr) Xchar *addr; X{ X int Lun; X char buf[BUFSIZ]; X X debugmsg(Fdd, sprintf(buf, "* Trying to connect to %s", addr)); X Lun = x25select(LINE, CONTROLLER, X25_ADAPTER, DATA_MODE, X addr, Mail_init, sizeof(Mail_init)); X if (Lun < 0) X return Lun; X debugmsg(Fdd, "* Sending connect initiate"); X xdebugmsg(Fdd, (u_char *) Conn_init, sizeof(Conn_init)); X (void) write(Lun, (char *) Conn_init, sizeof(Conn_init)); X if (read(Lun, buf, BUFSIZ) < 0) { X (void) close(Lun); X Lun = -1; X return Lun; X } X debugmsg(Fdd, "* Received connect confirm"); X xdebugmsg(Fdd, (u_char *) buf, 16); X WillMsgNotify = buf[8] & DOMSGNOTIFY; X WillBlksend = buf[8] & DOBLKSEND; X WillPfxSend = buf[8] & DOPFXSEND; X WillCc = buf[8] & DOCC; X /* X * In our connect initiate packet, we request to send the message in X * Block mode. If the remote end says "no" to it we complain and die. X * This seems to be the accepted norm in PSI. If the slave disagrees X * with the master then the master dies. X */ X if (!WillBlksend) { X debugmsg(Fdd, "Slave wants lines; Master wants blocks"); X (void) close(Lun); X Lun = -1; X return Lun; X } X return Lun; X} X X/* X * outlun() strips of any trailing carriage control and send it X * down the line X */ Xoutlun(s) Xchar *s; X{ X char *p; X X debugmsg(Fdd, s); X p = strchr(s, '\r'); X if (p != NULL) X *p = '\0'; X p = strchr(s, '\n'); X if (p != NULL) X *p = '\0'; X (void) write(Lun, s, strlen(s)); X} X Xerrlog(s) Xchar *s; X{ X static int firsttime = 1; X char cmdline[BUFSIZ]; X X if (firsttime) { X firsttime = 0; X (void) sprintf(cmdline, "/usr/ucb/mail -s \"Mailer Error\" %s", Sender); X Fpmail = popen(cmdline, "w"); X if (Fpmail == NULL) { X syslog(LOG_ERR, "%s: Can't mail %s: %m", Prog, Sender); X finish(EX_SOFTWARE); X } X } X fprintf(Fpmail, "%s\n", s); X} X Xfinish(code) Xint code; X{ X static int fd = -1; X char buf[BUFSIZ]; X time_t now; X int i; X X if (fd > 0) { /* If someone kills us when we're finishing up */ X debugmsg(Fdd, "* (Nested finish)"); X return; X } X (void) sprintf(buf, "Exit status %d", code); X debugmsg(Fdd, buf); X if (Lun > 0) X (void) close(Lun); X if (Fpmail != NULL) X (void) fclose(Fpmail); X#ifdef DEBUG X if (Fdd > 0) X (void) close(Fdd); X#endif X fd = open(LOGFILE, O_WRONLY | O_APPEND); X if (fd < 0) X fd = open(LOGFILE, O_WRONLY | O_CREAT, 0666); X if (fd < 0) { X syslog(LOG_ERR,"%s: Cannot open logfile: %m", Prog); X exit(code); X } X if (flock(fd, LOCK_EX) < 0) X syslog(LOG_ERR, "%s: Cannot obtain lock on %s: %m", Prog, LOGFILE); X now = time((time_t *) 0); X for (i = 0; i < Nodec; i++) { X (void) sprintf(buf,"exit %d: mail from %s to %s: %s", code, X Sender[0]? Sender : "", X Nodev[i].x25addr, X ctime(&now)); X (void) strrmc(buf, '\n'); X (void) strcat(buf, "\n"); X (void) write(fd, buf, strlen(buf)); X } X (void) flock(fd, LOCK_UN); X (void) close(fd); X exit(code); X} X Xonint() X{ X syslog(LOG_NOTICE, "%s: Terminated by SIGINT", Prog); X finish(EX_SOFTWARE); X} Xonterm() X{ X syslog(LOG_NOTICE, "%s: Terminated by SIGTERM", Prog); X finish(EX_SOFTWARE); X} Xonpwr() X{ X syslog(LOG_NOTICE, "%s: Terminated by SIGPWR", Prog); X finish(EX_SOFTWARE); X} Xonquit() X{ X syslog(LOG_NOTICE, "%s: Terminated by SIGQUIT", Prog); X finish(EX_SOFTWARE); X} Xonpipe() X{ X syslog(LOG_NOTICE, "%s: Terminated by SIGPIPE", Prog); X finish(EX_SOFTWARE); X} Xonprof() X{ X#ifndef pyr X (void) signal(SIGPROF, onprof); X#endif X debugmsg(Fdd, "Caught SIGPROF"); X return; X} X X#ifdef USER2ALIAS Xchar *user2alias(u) Xchar *u; X{ X return u; X} X#endif END_OF_FILE if test 23825 -ne `wc -c <'psimail/sendpsimail.c'`; then echo shar: \"'psimail/sendpsimail.c'\" unpacked with wrong size! fi # end of 'psimail/sendpsimail.c' fi echo shar: End of archive 1 \(of 2\). cp /dev/null ark1isdone MISSING="" for I in 1 2 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked both archives. rm -f ark[1-9]isdone else echo You still must unpack the following archives: echo " " ${MISSING} fi exit 0 exit 0 # Just in case... -- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM Sterling Software, IMD UUCP: uunet!sparky!kent Phone: (402) 291-8300 FAX: (402) 291-4362 Please send comp.sources.misc-related mail to kent@uunet.uu.net.