home *** CD-ROM | disk | FTP | other *** search
- Subject: v18i004: Fido/Usenet gateway, Part03/05
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: Heikki Suonsivu <hsu@santra.hut.fi>
- Posting-number: Volume 18, Issue 4
- Archive-name: fnet/part03
-
- #!/bin/sh
- # this is part 3 of a multipart archive
- # do not concatenate these parts, unpack them in order with /bin/sh
- # file fpack.c continued
- #
- CurArch=3
- if test ! -r s2_seq_.tmp
- then echo "Please unpack part 1 first!"
- exit 1; fi
- ( read Scheck
- if test "$Scheck" != $CurArch
- then echo "Please unpack part $Scheck next!"
- exit 1;
- else exit 0; fi
- ) < s2_seq_.tmp || exit 1
- echo "x - Continuing file fpack.c"
- sed 's/^X//' << 'SHAR_EOF' >> fpack.c
- X mail is public and default is private).
- X
- X All letters having arguments have only on space after them, and all
- X rest of the line is considered to be that argument. */
- X
- Xbool
- Xwrite_hdr(source, packet)
- X FILE *source, *packet;
- X{
- X char buffer[BUFSIZ];
- X char from[36], to[36], subject[72], date[20];
- X Node msg_node;
- X int attr = 0;
- X struct stat stbuf;
- X
- X msg_node.zone = msg_node.net = msg_node.node = msg_node.point = -1;
- X
- X /* clean up from, to and subject */
- X *from = 0;
- X *to = 0;
- X *subject = 0;
- X *date = 0;
- X
- X while (fgets(buffer, BUFSIZ, source) && *buffer != '\n')
- X {
- X buffer[strlen(buffer) - 1] = 0; /* strip newline */
- X switch (*buffer)
- X {
- X case 'N':
- X if (parsefnetaddress(buffer, &msg_node))
- X {
- X log("Invalid destination: %s", buffer);
- X return False;
- X }
- X break;
- X case 'F':
- X (void) strncpy(from, buffer + 2, 35);
- X from[35] = 0;
- X break;
- X case 'T':
- X (void) strncpy(to, buffer + 2, 35);
- X to[35] = 0;
- X break;
- X case 'S':
- X (void) strncpy(subject, buffer + 2, 71);
- X subject[71] = 0;
- X break;
- X case 'D':
- X (void) strncpy(date, buffer + 2, 19);
- X date[19] = 0;
- X break;
- X case 'P':
- X attr |= ATTR_PRIVATE;
- X break;
- X }
- X }
- X
- X /* check if net/node was missing */
- X if (msg_node.net == -1 || msg_node.node == -1)
- X {
- X log("Message with no destination");
- X return False;
- X }
- X
- X /* we must have also receiver */
- X if (!*to)
- X {
- X log("Missing receiver in mail header");
- X return False;
- X }
- X
- X /* if from is missing, we'll improvise...*/
- X if (!*from)
- X {
- X log("Missing from is header");
- X (void) strcpy(from, "Usenet");
- X }
- X
- X /* if subject is missing, let's put there something */
- X if (!*subject)
- X {
- X log("Missing subject in header");
- X (void) strcpy(subject, "Mail from Usenet");
- X }
- X
- X /* if date is missing, put there current date */
- X if (!*date)
- X {
- X log("Missing date in header");
- X (void) strcpy(date, fido_date(time((long *) 0)));
- X }
- X
- X /* save all header values */
- X (void) write_int(packet, MSGTYPE); /* save msg type */
- X (void) write_int(packet, MY_NODE); /* save our node */
- X (void) write_int(packet, msg_node.node); /* save messages node */
- X (void) write_int(packet, MY_NET); /* save our net */
- X (void) write_int(packet, msg_node.net); /* save messages net */
- X (void) write_int(packet, attr); /* save attributes */
- X (void) write_int(packet, 0); /* cost, not used by us */
- X put_string(packet, date); /* save time of mail */
- X put_string(packet, to); /* save receiver */
- X put_string(packet, from); /* save sender */
- X put_string(packet, subject); /* save subject */
- X
- X /* get status of mailfile and log this message */
- X if (fstat(fileno(source), &stbuf) == -1)
- X log("Unable to get stat of msg");
- X
- X log("Msg from %s to %s at %s packetized (%ld chars)", from, to,
- X ascnode(msg_node), stbuf.st_size - ftell(source));
- X
- X /* done with this header */
- X return True;
- X}
- X
- X/* Write packet header for new packet.
- X
- X Tue Oct 11 04:01:49 1988
- X Changed fwrite to write-ints and so on, as there is too many problems
- X with int and specially long alignment on different architectures. This
- X should be more portable!
- X (two extra bytes added for long alignment caused confmail to find
- X message type to be 0 and so it just forgot about that packet thinking
- X that it was in the end!)
- X */
- X
- Xbool
- Xwrite_pkthdr(packet)
- X FILE *packet;
- X{
- X Packet header;
- X int count;
- X struct tm *tm;
- X time_t clock = time((long *) 0);
- X
- X tm = localtime(&clock);
- X
- X /* create packet structure */
- X header.orig_node = int16(MY_NODE);
- X header.dest_node = int16(node.node);
- X header.orig_net = int16(MY_NET);
- X header.dest_net = int16(node.net);
- X
- X /* save time for header (why all these fields?) */
- X header.year = int16(tm->tm_year + 1900);
- X header.month = int16(tm->tm_mon);
- X header.day = int16(tm->tm_mday);
- X header.hour = int16(tm->tm_hour + 1);
- X header.minute = int16(tm->tm_min);
- X header.second = int16(tm->tm_sec);
- X
- X header.rate = int16(MAXBAUD);
- X header.ver = int16(HDRVER);
- X header.product = 0;
- X header.x1 = 0;
- X#ifdef FIDO_V11w
- X for (count = 0; count < 16; count++) header.fill[count] = 0;
- X#else
- X for (count = 0; count < 8; count++) header.pwd_kludge[count] = 0;
- X header.orig_zone = int16(MY_ZONE);
- X header.dest_zone = int16(node.zone);
- X for (count = 0; count < 16; count++) header.B_fill2[count] = 0;
- X header.B_fill3 = 0;
- X#endif
- X /* write header to file */
- X FPUTINT16(header.orig_node, packet);
- X FPUTINT16(header.dest_node, packet);
- X FPUTINT16(header.year, packet);
- X FPUTINT16(header.month, packet);
- X FPUTINT16(header.day, packet);
- X FPUTINT16(header.hour, packet);
- X FPUTINT16(header.minute, packet);
- X FPUTINT16(header.second, packet);
- X FPUTINT16(header.rate, packet);
- X FPUTINT16(header.ver, packet);
- X FPUTINT16(header.orig_net, packet);
- X FPUTINT16(header.dest_net, packet);
- X putc(header.product, packet);
- X putc(header.x1, packet);
- X for (count = 0; count < 8; count++) putc(header.pwd_kludge[count], packet);
- X FPUTINT16(header.orig_zone, packet);
- X FPUTINT16(header.dest_zone, packet);
- X for (count = 0; count < 16; count++) putc(header.B_fill2[count], packet);
- X for (count = 0; count < 4; count++)
- X putc(header.B_fill3 << (8 * count), packet); /* pc long = 4 bytes! */
- X
- X if (ferr(packet))
- X {
- X log("$Write error on packet header");
- X return False;
- X }
- X
- X debug(1, "New packet created");
- X
- X return True;
- X}
- X
- X/*ARGSUSED*/
- Xint
- Xmain(argc, argv, envp)
- X int argc;
- X char **argv, **envp;
- X{
- X DIR *dp;
- X struct dirent *dir;
- X FILE *msg, *packet;
- X char packet_name[16];
- X int c;
- X Node np;
- X char *error;
- X
- X /* get options */
- X while ((c = getopt(argc, argv, "vf:")) != EOF)
- X switch (c)
- X {
- X case 'f':
- X if (parsefnetaddress(optarg, &np)) exit(1);
- X node = np;
- X break;
- X case 'v':
- X verbose++;
- X break;
- X default:
- X (void) fprintf(stderr, "Usage: %s [-v] -f fidonet_address\n", *argv);
- X exit(1);
- X }
- X
- X /* make sure that we got net/node */
- X if (node.net == -1 || node.node == -1)
- X {
- X log("Missing fidonet node in command line");
- X exit(1);
- X }
- X
- X /* try to update nodelist-index */
- X if (error = update_index())
- X {
- X if (*error == '$')
- X log("$Cannot update nodelist-index: %s", error + 1);
- X else
- X log("Cannot update nodelist-index: %s", error);
- X exit(EX_OSERR);
- X }
- X
- X /* goto spool directory, everything exiting happens there... */
- X if (chdir(SPOOL) == -1)
- X {
- X log("$Can not chdir to %s", SPOOL);
- X exit(1);
- X }
- X
- X /* create packet name */
- X sprintpacketname(packet_name, node);
- X
- X if (access(sprintfs("out/%s", packet_name), 0) == 0) {
- X debug(1, "Packet out/%s exists, append to it", packet_name);
- X if ((packet = fopen(sprintfs("out/%s", packet_name), "r+")) == NULL)
- X {
- X log("$Can not open out/%s for update", packet_name);
- X exit(1);
- X }
- X (void) fseek(packet, -2l, 2);
- X }
- X else {
- X debug(1, "New packet out/%s", packet_name);
- X if ((packet = fopen(sprintfs("out/%s", packet_name), "w")) == NULL)
- X {
- X log("$Can not open packet out/%s for writing", packet_name);
- X exit(1);
- X }
- X
- X /* protect packet from users...*/
- X (void) chmod(sprintfs("out/%s", packet_name), 0600);
- X
- X /* write packet-header, if it fails, exit */
- X if (!write_pkthdr(packet))
- X {
- X (void) unlink(sprintfs("out/%s", packet_name));
- X exit(1);
- X }
- X }
- X
- X /* lock packet, wait if it's alredy locked */
- X while (lock(fileno(packet)) == -1 && errno == EAGAIN)
- X (void) sleep((unsigned) 1);
- X
- X /* open spool directory */
- X if (dp = opendir("."))
- X {
- X while (dir = readdir(dp))
- X {
- X /* check that file is for us */
- X if (*dir->d_name == 'M' && dir->d_name[1] == '.')
- X {
- X if (msg = fopen(dir->d_name, "r"))
- X {
- X debug(1, "Adding mailfile %s", dir->d_name);
- X
- X /* save header */
- X if (write_hdr(msg, packet))
- X {
- X /* copy mail text, replace newlines with <cr> <lf> */
- X while ((c = getc(msg)) && c != EOF)
- X {
- X if (c == '\n')
- X (void) putc('\r', packet);
- X (void) putc(c, packet);
- X }
- X /* null-terminate msg text */
- X (void) putc(0, packet);
- X }
- X (void) fclose(msg);
- X if (unlink(dir->d_name) == -1)
- X log("$Unable to unlink %s", dir->d_name);
- X }
- X else
- X log("$Can not open mail %s for reading", dir->d_name);
- X }
- X }
- X (void) closedir(dp);
- X }
- X else
- X {
- X log("$Can not open spool directory %s", SPOOL);
- X exit(1);
- X }
- X
- X /* msg type 0 indicates end of packet */
- X (void) write_int(packet, 0);
- X
- X (void) fclose(packet);
- X
- X exit(0);
- X /* NOTREACHED */
- X}
- X
- X
- SHAR_EOF
- echo "File fpack.c is complete"
- chmod 0644 fpack.c || echo "restore of fpack.c fails"
- echo "x - extracting funpack.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > funpack.c &&
- X#ifndef lint
- Xstatic char *sccsid = "@(#)%M% %I% Teemu Torma %H%";
- X#endif
- X
- X/* Unpaketize fido-mail packets and send mail to reciver or send it to
- X news-server.
- X
- X @(#)Copyright (c) 1987 by Teemu Torma
- X
- X Permission is given to distribute this program and alter this code as
- X needed to adapt it to forign systems provided that this header is
- X included and that the original author's name is preserved. */
- X
- X#include <stdio.h>
- X#include <ctype.h>
- X#include <string.h>
- X#include <sys/types.h>
- X#include <varargs.h>
- X#include <time.h>
- X#include <dirent.h>
- X#include "hsu.h"
- X#include "config.h"
- X#include "fnet.h"
- X#include "fpack.h"
- X#include "nodelist.h"
- X#include "sysexits.h"
- X#include "fnews.h"
- X
- X#define MAXARGS (32) /* maximum number of arguments */
- X
- Xextern time_t time();
- Xextern char *tzname[];
- Xextern int getopt();
- Xextern int optind;
- Xextern char *optarg;
- Xextern void exit(), perror(), free();
- Xextern char *malloc();
- Xextern time_t dateconv();
- Xextern void swab();
- X
- Xint verbose = INIT_VERBOSE;
- Xint newsmode = FALSE;
- Xint acceptprivate = FALSE;
- Xint trashprivate = FALSE;
- X
- X#ifdef SCCS
- Xchar *version = "%I%";
- X#else
- Xchar *version = PROGRAMNAME;
- X#endif
- X
- X/* Test if string is totally numeric. */
- X
- Xbool
- Xnumeric(s)
- X register char *s;
- X{
- X while (*s)
- X if (!isdigit(*s++))
- X return False;
- X return True;
- X}
- X
- X/* Return msdos interger as machine integer */
- X
- Xint
- Xint16(msint)
- X INT16 msint;
- X{
- X static INT16 value;
- X
- X#ifdef SWAB_BYTES
- X swab((char *) &msint, (char *) &value, 2);
- X#else
- X value = msint;
- X#endif
- X return (int) value;
- X}
- X
- Xstatic FILE *badtemp = NULL;
- X
- X/*VARARGS2*/
- Xtprintf(fp, fmt, va_alist)
- X FILE *fp;
- X char *fmt;
- X{
- X char buffer[BUFSIZ];
- X va_list pvar;
- X
- X va_start(pvar);
- X vsprintf(buffer, fmt, pvar);
- X fputs(buffer, fp);
- X if (badtemp) fputs(buffer, badtemp);
- X va_end(pvar);
- X}
- X
- Xtputs(buffer, fp)
- X char *buffer;
- X FILE *fp;
- X{
- X fputs(buffer, fp);
- X if (badtemp) fputs(buffer, badtemp);
- X}
- X
- X#define tputc(c, fp) putc(c, fp); if (badtemp) putc(c, badtemp);
- X
- X/* Replacement for fgets(3S) to understand cr's generated by Fido
- X and 'soft' cr's generated by SEAdog. It return EOF if text is over,
- X ie. 0 is got from file.
- X
- X Sat Oct 1 10:15:46 1988
- X Must notice cr without linefeed, as confmail seems to send
- X strange ids without lf.
- X
- X Mon Oct 3 01:51:01 1988
- X Notice * Origin header and extract node from it. Useless time consumer
- X when looking for mail.
- X */
- X
- Xstatic char *
- Xffgets(buffer, maxlen, fp)
- X char *buffer;
- X int maxlen;
- X FILE *fp;
- X{
- X register int c, ch, index;
- X register char *cp;
- X char buf[BUFSIZ];
- X static char wordsave[BUFSIZ];
- X /* TRUE if last line was origin line without valid node */
- X static int last_line_was_origin = FALSE;
- X /* TRUE if last character caused line wrap */
- X static int last_char_wrapped = FALSE;
- X Node node;
- X
- X /* There might be wrapped word lying around */
- X if (*wordsave)
- X {
- X strcpy(buffer, wordsave);
- X strsclean(buffer);
- X debug(20, "Picked up word '%s'", buffer);
- X *wordsave = 0;
- X }
- X else
- X *buffer = 0;
- X
- X cp = buffer + strlen(buffer);
- X
- X while (--maxlen > 0 && (c = getc(fp)) != EOF && c)
- X {
- X /* Hard carriage return */
- X
- X if (c == '\r')
- X c = '\n';
- X else if (c == '\n' || c == 0x8d || c == '\215')
- X {
- X /* Forget about these ! */
- X continue;
- X }
- X else
- X if (c == '\001')
- X {
- X /* Kludge. Stupid idea to put control chars to messages,
- X but thats the way it is, replace with something which
- X doesn't make programs expecting ascii mad */
- X strncpy(cp, "FSC-Control:", 12);
- X cp += 12;
- X c = ' ';
- X }
- X
- X /* If last character caused line wrap, and we now got another
- X linefeed, skip this linefeed to avoid unneeded empty lines. */
- X
- X if (last_char_wrapped)
- X {
- X if (c == '\n')
- X {
- X last_char_wrapped = FALSE;
- X continue;
- X }
- X
- X if (isspace(c) && strempty(buffer)) continue;
- X }
- X
- X *cp++ = c;
- X
- X if (c == '\n')
- X break;
- X
- X *cp = 0;
- X
- X /* Try to wrap if line is too long and it is not a seen-by, origin
- X or path line. */
- X if (strlen(buffer) >= MAX_LINELEN - 1 &&
- X strncmp(" * Origin:", buffer, 10) &&
- X strncmp("SEEN-BY:", buffer, 8) &&
- X strncmp("FSC-Control:", buffer, 12)) /* - 1 for \n */
- X {
- X last_char_wrapped = TRUE;
- X
- X /* Search for place to cut */
- X for (index = strlen(buffer) - 1; index >= 0; index--)
- X {
- X c = buffer[index];
- X if (index <= MAX_LINELEN / 3)
- X {
- X /* Too long, cut. */
- X *cp++ = c = '\n';
- X goto collected;
- X }
- X
- X /* Note: [\]{|}@` are not considered punctuation because
- X they are used in some countries for national characters. */
- X if (isspace(c) || (ispunct(c) && !strchr("[\\]{|}@`", c)))
- X {
- X /* Wrap here! */
- X cp = buffer + index + 1; /* Punctuation left on this line */
- X strcpy(wordsave, cp);
- X debug(20, "saving word '%s'", wordsave);
- X *cp++ = c = '\n';
- X goto collected;
- X }
- X }
- X }
- X
- X last_char_wrapped = FALSE;
- X }
- X
- X collected:
- X
- X /* if we got nul, put it back if occurred in the middle of line */
- X if (!c && cp != buffer)
- X (void) ungetc(0, fp);
- X
- X *cp = 0; /* Cut it here */
- X
- X /* This is really nasty part: Try to work out reply-to path from
- X origin for those people who don't have node in nodelist.
- X This should handle both situations where origin line is split by
- X some stupid mailer, or because origin line was too long (sysops,
- X please don't use long system identifiers, it causes lots of trouble!).
- X It checks that line doesn't start with SEEN-BY: or FSC-Control as
- X those things generally follow origin lines. */
- X
- X if (!strncmp(" * Origin:", buffer, 10) || last_line_was_origin) {
- X char *left, *right;
- X
- X if (last_line_was_origin)
- X {
- X last_line_was_origin = FALSE;
- X /* If its seen-by or control, it probably isn't continuation! */
- X if (!strncmp("SEEN-BY:", buffer, 8) ||
- X !strncmp("FSC-Control:", buffer, 12))
- X goto out;
- X }
- X else
- X last_line_was_origin = TRUE;
- X
- X strcpy(buf, buffer);
- X right = buf;
- X
- X for (;;)
- X {
- X if ((left = strchr(right, '(')) && (right = strchr(left + 1, ')')))
- X {
- X *right = 0;
- X if (parsefnetaddress(++left, &node))
- X {
- X debug(1, "Could not parse %s", left);
- X }
- X else
- X {
- X memcpy( (char *) &originnode, (char *) &node, sizeof(Node));
- X debug(1, "Parsed %s to %d:%d/%d.%d", left, originnode.zone,
- X originnode.net, originnode.node, originnode.point);
- X }
- X left = ++right;
- X }
- X else
- X break;
- X }
- X }
- X
- X out:
- X return ((!c || c == EOF) && cp == buffer) ? (char *) 0 : buffer;
- X}
- X
- X/* Execute sender of fido-message. Argument will be program name, anrgument
- X for that and pid to return. If command is not empty, use it instead
- X of given program and build parameter table. */
- X
- Xstatic char command[64];
- X
- XFILE *
- Xopen_sender(program, args, pid)
- X char *program, **args;
- X int *pid;
- X{
- X FILE *fp;
- X int fd[2], count = 0;
- X char *p, *realargs[MAXARGS];
- X char *cmd, *realprogram;
- X
- X cmd = alloca(strlen(command) + 1);
- X strcpy(cmd, command);
- X
- X if (*cmd)
- X {
- X while (p = strtok(cmd, SEPARATORS))
- X {
- X realargs[count++] = p;
- X cmd = NULL; /* For strtok */
- X }
- X
- X realargs[count++] = NULL;
- X realprogram = *realargs;
- X
- X if (realprogram)
- X {
- X program = realprogram;
- X args = realargs;
- X }
- X }
- X
- X if (pipe(fd) == -1)
- X {
- X perror("funpack: pipe");
- X return (FILE *) 0;
- X }
- X
- X switch (*pid = fork())
- X {
- X case -1:
- X perror("funpack: fork failed");
- X return (FILE *) 0;
- X case 0:
- X (void) close(0);
- X if (dup(fd[0]) == 0)
- X {
- X (void) close(fd[0]);
- X (void) close(fd[1]);
- X if (args)
- X (void) execvp(program, args);
- X else
- X (void) execlp(program, basename(program), (char *) 0);
- X perror(program);
- X }
- X else
- X perror("funpack: dup");
- X exit(EX_OSERR);
- X default:
- X (void) close(fd[0]);
- X if ((fp = fdopen(fd[1], "w")) == NULL)
- X {
- X perror("funpack: fdopen");
- X return (FILE *) 0;
- X }
- X }
- X return fp;
- X}
- X
- Xstatic Packet header;
- X
- Xread_header(fp)
- X FILE *fp;
- X{
- X FGETINT16(header.orig_node, fp);
- X FGETINT16(header.dest_node, fp);
- X FGETINT16(header.year, fp);
- X FGETINT16(header.month, fp);
- X FGETINT16(header.day, fp);
- X FGETINT16(header.hour, fp);
- X FGETINT16(header.minute, fp);
- X FGETINT16(header.second, fp);
- X FGETINT16(header.rate, fp);
- X FGETINT16(header.ver, fp);
- X FGETINT16(header.orig_net, fp);
- X FGETINT16(header.dest_net, fp);
- X header.product = getc(fp);
- X header.x1 = getc(fp);
- X FREAD(header.pwd_kludge, 8, 1, fp);
- X FGETINT16(header.orig_zone, fp);
- X if (header.orig_zone == 0) header.orig_zone = int16(MY_ZONE);
- X FGETINT16(header.dest_zone, fp);
- X if (header.dest_zone == 0) header.dest_zone = int16(MY_ZONE);
- X FREAD(header.B_fill2, 16, 1, fp);
- X FREAD( (char *) &header.B_fill3, 4, 1, fp);
- X return ferr(fp);
- X}
- X
- X/* Return int from file. Int in file is supposed to be 16 bit ms-dos
- X integer. */
- X
- Xint
- Xread_int(fp)
- X FILE *fp;
- X{
- X static INT16 value;
- X
- X if (fread((char *) &value, 2, 1, fp) != 1)
- X {
- X if (ferr(fp))
- X log("Cannot read file, errno %d : %s", errno, sys_errlist[errno]);
- X
- X value = 0;
- X }
- X
- X debug(8, "< %02x(%ld)", int16(value), ftell(fp));
- X return int16(value);
- X}
- X
- X/* Read null-terminated string from file. Ensure that buffer is also
- X null-terminated. Remove possible \n:s from end, they are generated by
- X some buggy mailers. */
- X
- Xvoid
- Xget_string(buffer, fp, nbytes)
- X char *buffer;
- X FILE *fp;
- X int nbytes;
- X{
- X register int n;
- X char *p;
- X
- X debug(8, "get string start %ld", ftell(fp));
- X
- X for (n = 0, *buffer = 0; n < nbytes; n++)
- X if ((buffer[n] = getc(fp)) == 0)
- X break;
- X else
- X debug(8, "<%d %c>", buffer[n], buffer[n]);
- X
- X /* If still more chars in buffer, skip them until null char found */
- X if (n >= nbytes)
- X {
- X debug(8, "Skipping rest");
- X while(getc(fp));
- X }
- X
- X buffer[nbytes] = 0;
- X
- X /* Remove \n from end if its there, its a bug */
- X if (p = strchr(buffer, '\n')) *p = 0;
- X
- X debug(8, "Getstring at %ld %s", ftell(fp), buffer);
- X}
- X
- X#define NGFLAG_ACCEPT_PRIVATE 0
- X#define NGFLAG_COMMAND 1
- X#define NGFLAG_TRASH_PRIVATE 2
- X
- Xstatic char distribution[64];
- Xstatic char *ngflags[] = { "accept-private", "command", "trash-private", "" };
- X
- X/* Like strtok but returns empty string instead of null if no more thigns
- X found */
- X
- Xchar *estrtok(s, sep)
- X char *s, *sep;
- X{
- X char *p;
- X
- X if (p = strtok(s, sep)) return p;
- X return "";
- X}
- X
- Xchar *
- Xget_ng(config, echo, distrib)
- X FILE *config;
- X char *echo, *distrib;
- X{
- X static char conv[BUFLEN];
- X char *gr, *flag;
- X
- X debug(2, "Checking echolist '%s'", echo);
- X
- X *command = 0;
- X section(SECT_AREA_NG, config);
- X trashprivate = FALSE;
- X acceptprivate = FALSE;
- X while (getcl(conv, BUFLEN, config))
- X {
- X debug(3, "Config line '%s'", conv);
- X
- X gr = estrtok(conv, SEPARATORS);
- X if (!strcmp(gr, echo))
- X {
- X /* Matched, take distribution and return newsgroup */
- X
- X gr = estrtok(NULL, SEPARATORS);
- X strcpy(distrib, estrtok(NULL, SEPARATORS));
- X while (flag = strtok(NULL, SEPARATORS))
- X switch(listscan(ngflags, flag))
- X {
- X case NGFLAG_ACCEPT_PRIVATE:
- X acceptprivate = TRUE;
- X break;
- X
- X case NGFLAG_COMMAND:
- X /* Fails if fnews.cf has DEL char in it, but thats
- X mostly a philosophical question. */
- X strcpy(command, estrtok(NULL, "\377"));
- X break;
- X
- X case NGFLAG_TRASH_PRIVATE:
- X trashprivate = TRUE;
- X break;
- X
- X case -1:
- X default:
- X log("Bad flag '%s' for newsgroup %s", flag, gr);
- X break;
- X }
- X
- X debug(3, "Match, return newsgroup '%s', distribution %s",
- X gr, distrib);
- X return gr;
- X }
- X }
- X log("No newsgroup for '%s' found, return junk, distribution local", echo);
- X strcpy(distrib, "local");
- X return "junk";
- X}
- X
- X/* Check if message is news-message (currenlty: if first line begins
- X with AREA:). If area is found, we'll return name for that area,
- X otherwise NULL. */
- X
- Xchar *
- Xnews_msg(fp)
- X FILE *fp;
- X{
- X FILE *config;
- X long offset = ftell(fp);
- X char *cp;
- X static char area[64];
- X
- X if (ffgets(area, 64, fp) && !strncmp(area, "AREA:", 5))
- X {
- X /* this is echomail-message */
- X area[strlen(area) - 1] = 0;
- X
- X /* strip possible spaces */
- X for (cp = area + 5; *cp && isspace(*cp); cp++);
- X
- X if ((config = pfopen(LIBDIR, "fnews.cf", "r")) == NULL)
- X {
- X log("$Unable to open config file");
- X exit(1);
- X }
- X
- X strcpy(cp, get_ng(config, cp, distribution));
- X fclose(config);
- X
- X /* return converted area-name */
- X return cp;
- X }
- X else
- X {
- X /* this is not echomail message, seek back */
- X (void) fseek(fp, offset, 0);
- X return (char *) 0;
- X }
- X /* NOTREACHED */
- X}
- X
- X/* Return date of message. Date will be read and converted to one
- X long-interger as normal Unix-time will be.
- X
- X Both SEAdog and Fido date formats are understood.
- X SEAgod: Mon 1 Jan 86 02:34
- X Fido: 01 Jan 86 02:34:56 */
- X
- Xtime_t
- Xlgetdate(packet)
- X FILE *packet;
- X{
- X char buffer[20];
- X int c;
- X time_t timevar;
- X int n;
- X
- X /* read date from packet */
- X for (n = 0; n < 20; n++)
- X if ((buffer[n] = getc(packet)) == NULL) break;
- X
- X /* Some message-packers do mistakes! Date should be 20 bytes but
- X they start name directly after null terminating 18-char date
- X used in some systems. Check if following char is null or not,
- X and if not, put it back there as it probably is first char in
- X recipent name. This seems to be problem in OMMM, but I'm not
- X sure yet.
- X
- X Wed Nov 16 21:11:34 1988 Seems that the bug is in fsc001, as
- X I constantly keep receiving messages which 19 byte date?
- X */
- X
- X#ifdef FSC_IS_REALLY_CORRECT
- X for (n++; n < 20; n++)
- X if (c = getc(packet))
- X {
- X ungetc(c, packet);
- X }
- X#endif
- X
- X buffer[19] = 0;
- X debug(8, "Getdate %s at %ld", buffer, ftell(packet));
- X
- X /* try to get date */
- X timevar = getdate(buffer, (struct timeb *) NULL);
- X return timevar;
- X}
- X
- X/* Remove 'of net/node' from name. Number will be saved
- X for later use and used as reply-to address, as I think most users use
- X it as their home system or if they are sysops, as their node. */
- X
- Xsearch_node(from, node)
- X char *from;
- X Node *node;
- X{
- X char *s, *p, *of;
- X Node tempnode;
- X
- X s = alloca(strlen(from) + 1);
- X strcpy(s, from);
- X
- X p = strtok(s, WHITESPACE);
- X while (p)
- X {
- X if (!stricmp(p, "of"))
- X {
- X of = p;
- X /* Skip possible multiple 'of's */
- X for (; (p = strtok(NULL, WHITESPACE)) && !stricmp(p, "of"););
- X /* Of and something else follows, try to parse */
- X if (p)
- X {
- X if (!parsefnetaddress(p, &tempnode))
- X {
- X if (node) *node = tempnode;
- X /* Of net/node should be the last string */
- X if ((p = strtok(NULL, WHITESPACE)) == NULL)
- X {
- X /* Remove 'of ...' from name */
- X *(from + (int) (of - s)) = 0;
- X strclean(from);
- X return; /* Found it */
- X }
- X else
- X continue; /* Something follows, try again */
- X }
- X }
- X else
- X return; /* no more stuff */
- X }
- X p = strtok(NULL, WHITESPACE);
- X }
- X return;
- X}
- X
- X/* Remove userids from names, like "James Smith (SMITH)" will become
- X "James Smith". Simple algorithm now, but its enough. Scandinvian
- X chars are translated to a and o, and other special chars are
- X removed. */
- X
- Xremove_id(name)
- X char *name;
- X{
- X char *p, *cp;
- X
- X if (p = strchr(name, '(')) {
- X while (*p != ')' && *p)
- X for (cp = p; *cp = *(cp + 1); cp++); /* Remove one char */
- X
- X if (*p == ')')
- X for (cp = p; *cp = *(cp + 1); cp++); /* Remove last ) */
- X }
- X
- X /* Remove blanks from the end */
- X while (strlen(name) && isspace(name[strlen(name) - 1]))
- X name[strlen(name) - 1] = 0;
- X (void) ascii_convert(name);
- X fine_convert(name);
- X stripbad(name);
- X}
- X
- X/* Search alias name which matches with fidonet name, return NULL
- X if no alias specified. */
- X
- Xchar *get_alias(name)
- X char *name;
- X{
- X char buffer[BUFSIZ];
- X char *cp;
- X FILE *fp;
- X static char unixname[BUFSIZ], fidoname[BUFSIZ];
- X
- X if (fp = fopen(ALIAS, "r"))
- X {
- X while (fgets(buffer, BUFSIZ, fp))
- X {
- X buffer[strlen(buffer) - 1] = 0;
- X if (*buffer != '#')
- X {
- X if ((cp = strchr(buffer, ' ')) ?
- X cp : (cp = strchr(buffer, '\t')))
- X {
- X *cp = 0; /* Break unixname out */
- X strcpy(unixname, buffer); /* And save it */
- X debug(8, "Unix name %s", unixname);
- X }
- X else
- X {
- X /* No space or tab found, probably bad line */
- X debug(1, "Bad alias line %s", buffer);
- X continue;
- X }
- X
- X /* Search for name start, there may be space between */
- X cp++;
- X while (*cp && isspace(*cp)) cp++;
- X if (!*cp)
- X {
- X debug(1, "Bad alias line %s", buffer);
- X continue;
- X }
- X
- X strcpy(fidoname, cp); /* Save fidonet name */
- X debug(8, "Fidoname %s", fidoname);
- X
- X if (!stricmp(fidoname, name))
- X {
- X fclose(fp);
- X
- X /* There may be node specs after name, null them out */
- X if (cp = strchr(unixname, ',')) *cp = 0;
- X
- X debug(8, "Fidoname %s matched with %s, return %s",
- X fidoname, name, unixname);
- X return unixname;
- X }
- X }
- X }
- X }
- X
- X fclose(fp);
- X return NULL;
- X}
- X
- X/* Save bad article from file given to bad directory */
- X
- Xsavebad(fp)
- X FILE *fp;
- X{
- X char *fname, buffer[BUFSIZ];
- X FILE *badfile;
- X
- X log("Saving bad article/mail to %s",
- X fname = sprintfs("%s/bad%ld", BADARTICLES, sequencer(BADSEQ)));
- X if (badfile = fopen(fname, "w+"))
- X {
- X rewind(fp);
- X while (fgets(buffer, BUFSIZ, fp))
- X fputs(buffer, badfile);
- X }
- X else
- X {
- X log("$Could not open bad article file");
- X return -1;
- X }
- X fclose(badfile);
- X return 0;
- X}
- X
- X/* Unpack packet and all files in it. Packet's header will be stripped
- X off. For each message check if it is news-msg (First line begins
- X with AREA:). If it is, send it to news-sender sfnews, otherwise
- X send it to rmail. Address is given in to-field, or if it wont
- X fit to it, in the first line of message. In later case to-field
- X must be "Usenet". */
- X
- Xvoid
- Xunpack(packet, packetnode)
- X FILE *packet;
- X Node packetnode;
- X{
- X int count, attributes, messagetype;
- X char to[36], from[36], realto[40], realfrom[40], subject[72];
- X char badname[BUFSIZ];
- X char *args[MAXARGS];
- X char buffer[BUFSIZ], *cp, *p;
- X FILE *sender, *newssender;
- X int n, pid, stat_loc, c;
- X Node *entry, mynode, orignode, destnode, fromnode;
- X char hostname[10];
- X time_t msg_date;
- X char *area;
- X
- X /* get node-entry fo packet-sender */
- X if (node_entry(packetnode) == NULL)
- X {
- X log("Unknown packet sender: %s", ascnode(packetnode));
- X return;
- X }
- X
- X mynode.zone = MY_ZONE;
- X mynode.net = MY_NET;
- X mynode.node = MY_NODE;
- X mynode.point = MY_POINT;
- X
- X if ((entry = node_entry(mynode)) == NULL)
- X {
- X log("Unable to find this net/node from nodelist");
- X return;
- X }
- X
- X /* get our uucp-nodename */
- X if (gethostname(hostname, 10) == -1)
- X {
- X log("$Unable to get hostname");
- X return;
- X }
- X
- X while ((messagetype = read_int(packet)) == MSGTYPE)
- X {
- X *args = NULL;
- X originnode.zone = -1;
- X fromnode.zone = -1;
- X orignode.zone = packetnode.zone; /* Orignode zone and point are not */
- X orignode.point = packetnode.point; /* included in messages. */
- X destnode.zone = packetnode.zone;
- X destnode.point = packetnode.point;
- X
- X /* get nodes information about message */
- X orignode.node = read_int(packet);
- X destnode.node = read_int(packet);
- X
- X /* get nodes from message */
- X orignode.net = read_int(packet);
- X destnode.net = read_int(packet);
- X
- X debug(2, "Original net/node = %s", ascnode(orignode));
- X debug(2, "Destination net/node = %s", ascnode(destnode));
- X
- X /* we're not interested about attributes currenty */
- X attributes = read_int(packet);
- X
- X /* through away cost */
- X (void) read_int(packet);
- X
- X /* get date */
- X msg_date = lgetdate(packet);
- X
- X /* get receiver of message */
- X get_string(to, packet, 35);
- X search_node(to, (Node *) NULL);
- X remove_id(to);
- X debug(2, "Msg is to '%s'", to);
- X
- X /* get sender of message */
- X get_string(from, packet, 35);
- X search_node(from, &fromnode);
- X remove_id(from);
- X debug(2, "Msg is from '%s'", from);
- X
- X /* get subject */
- X get_string(subject, packet, 71);
- X
- X /* Remove trailing blanks */
- X for (count = strlen(subject) - 1; count >= 0 && isspace(subject[count]);
- X count--) subject[count] = 0;
- X
- X /* News expects some kind of subject and ignores the message
- X without one? */
- X if (!*subject) strcpy(subject, "No subject");
- X
- X debug(2, "Subject is '%s'", subject);
- X
- X /* check that message is to this node */
- X if (!samenode(destnode, mynode))
- X {
- X log("Msg from %s to %s at %s: wrong node address",
- X from, to, ascnode(destnode));
- X goto error;
- X }
- X
- X /* check if this is news-message. Private messages will not
- X be forwarded to readnews, they go to mail, if received is
- X known, otherwise they will be thrown away. Exception are
- X conferences which are marked accept-private. */
- X newsmode = FALSE;
- X if ((area = news_msg(packet)) &&
- X (acceptprivate || !(attributes & ATTR_PRIVATE)))
- X {
- X /* This is news-artcile. Open sendfidonews and give area name as
- X argument to it. Input of sfnews will be just like input
- X of mail. */
- X
- X debug(1, "Message is news-article");
- X newsmode = TRUE;
- X
- X /* create args for sender */
- X *args = strsave(RNEWS);
- X#ifdef NEEDED
- X args[1] = strsave(area);
- X args[2] = NULL;
- X#else
- X args[1] = NULL;
- X#endif
- X /* open sender */
- X if (!(sender = tmpfile()))
- X {
- X log("Can not create temp file, errno %d: %s",
- X errno, sys_errlist[errno]);
- X goto error;
- X }
- X
- X if ((newssender = open_sender(*args, args, &pid)) == NULL)
- X {
- X log("Can not execute %s", *args);
- X goto error;
- X }
- X
- X badtemp = NULL; /* tmp file for news messages will be
- X created later. */
- X }
- X else
- X {
- X debug(1, "Message is for mail");
- X if (area)
- X {
- X debug(1, "Private message for area %s", area);
- X if (trashprivate) goto error;
- X }
- X
- X /* If message receiver is Usenet, then receiver of mail will
- X be at first-line of message separated by commands/spaces.
- X If receiver is not usenet, mail will be sent to normal
- X receiver, but in this case all charactes will be converted
- X to lower case (Fido changes them, you know). */
- X
- X if (!strcmp(to, "Usenet"))
- X {
- X if (ffgets(buffer, BUFSIZ, packet) == NULL)
- X {
- X log("Missing receiver in msg from %s at %s", from,
- X ascnode(orignode));
- X goto error;
- X }
- X buffer[strlen(buffer) - 1] = 0;
- X }
- X else
- X {
- X debug(8, "Searching alias for %s", to);
- X if (p = get_alias(to))
- X {
- X (void) strcpy(buffer, p);
- X debug(8, "Got alias %s", buffer);
- X }
- X else
- X {
- X if (area)
- X {
- X log("Skipping private echo for %s", to);
- X goto error; /* If private echo message, skip */
- X }
- X (void) strcpy(buffer, to);
- X debug(8, "No alias, using %s", buffer);
- X }
- X
- X for (n = 0; buffer[n]; n++)
- X buffer[n] = tolower(buffer[n]);
- X }
- X
- X *args = strsave(basename(RMAIL));
- X for (n = 1, cp = strtok(buffer, ", \t"); cp && n < MAXARGS;
- X cp = strtok((char *) 0, ", \t"), n++)
- X args[n] = strsave(cp);
- X args[n] = NULL;
- X
- X for (n = 1; args[n]; n++)
- X log("Sending mail from %s at %s to %s", from, ascnode(orignode),
- X args[n]);
- X
- X /* open rmail for sending message */
- X if ((sender = open_sender(RMAIL, args, &pid)) == NULL)
- X {
- X log("Can not execute %s", RMAIL);
- X goto error;
- X }
- X
- X if (badtemp)
- X fclose(badtemp);
- X
- X if ((badtemp =
- X fopen(strcpy(badname, mktemp("/tmp/funpXXXXXX")), "w+"))
- X == NULL)
- X {
- X log("$Cannot open tmp file %s", badname);
- X goto error;
- X }
- X
- X area = NULL;
- X
- X }
- X
- X /* Save real names for further use. Blanks included, */
- X if (strchr(from, ' '))
- X {
- X strcpy(realfrom, " (");
- X strcat(realfrom, from);
- X strcat(realfrom, ")");
- X }
- X else
- X *realfrom = 0;
- X
- X if (strchr(to, ' '))
- X {
- X strcpy(realto, " (");
- X strcat(realto, to);
- X strcat(realto, ")");
- X }
- X else
- X *realto = 0;
- X
- X /* change all spaces in name to _'s */
- X for (n = 0; from[n]; n++)
- X if (from[n] == ' ') from[n] = '_';
- X /* Same for to field */
- X for (n = 0; to[n]; n++)
- X if (to[n] == ' ') to[n] = '_';
- X
- X /* set From_ line */
- X (void) tprintf(sender, "From %d!%s %s remote from %d\n", orignode.node,
- X from, date("%a %h %d %T 19%y", (long *) 0), orignode.net);
- X
- X /* Now generate valid RFC 822 header for mail. Some fields may
- X be different, in all places there may be comments between (
- X and )-charactes. */
- X
- X /* This is imporant for news articles, as without this inews
- X tries to post it back. This is a bit complicated, as we cannot
- X put fidonet path here? Hmm... why not, I have to check this out! */
- X (void) tprintf(sender, "Path: %s!%s\n", RECEIVE_PATH, from);
- X
- X /* print Received: field */
- X (void) tprintf(sender, "Received: by %s (funpack%s/%s)\n",
- X internode(*entry), version, entry->name);
- X (void) tprintf(sender, "\tid AA%05d; %s\n",
- X getpid(), date("%a, %d %h %y %T %o (%z)", (long *) 0));
- X
- X /* print Date: field */
- X (void) tprintf(sender, "Date: %s\n", date("%a, %d %h %y %T %o",
- X &msg_date));
- X
- X /* print From: field */
- X (void) tprintf(sender, "From: %s@%s%s\n", from, internode(orignode),
- X realfrom);
- X
- X /* print Subject: field */
- X (void) tprintf(sender, "Subject: %s\n", subject);
- X
- X /* print Message-Id: field */
- X (void) tprintf(sender, "Message-Id: <%s.AA%ld@%s>\n",
- X date("%y%m%q%H%M", (long *) 0), sequencer(IDSEQUENCE),
- X internode(*entry));
- X
- X if (area)
- X {
- X (void) tprintf(sender, "Newsgroups: %s\n", area);
- X if (strlen(distribution))
- X (void) tprintf(sender, "Distribution: %s\n", distribution);
- X
- X /* print Reply-To: field */
- X /* Note: This is not accurate yet, as * Origin can change
- X address to other node */
- X (void) tprintf(sender, "Reply-To: %s@%s%s\n",
- X from, internode(destnode), realfrom);
- X }
- X else
- X {
- X /* print To: field */
- X (void) tprintf(sender, "To: ");
- X for (n = 1; args[n]; n++)
- X {
- X (void) tprintf(sender, "%s", args[n]);
- X if (args[n + 1])
- X (void) tprintf(sender, ", ");
- X }
- X tprintf(sender, "\n");
- X
- X /* print Reply-To: field */
- X (void) tprintf(sender, "Reply-To: %s@%s%s\n",
- X from, internode(orignode), realfrom);
- X }
- X
- X /* done with header, now send message text */
- X
- X tprintf(sender, "\n");
- X while (ffgets(buffer, BUFSIZ, packet))
- X (void) tputs(buffer, sender);
- X
- X /* News messages are a little bit more compilicated. News
- X article has been saved in temp file, and now we need to
- X read it through, replace Reply-To with correct return address
- X taken from origin row, nodelist, or if not found, echo feed.
- X Then really send mail to newssender. */
- X
- X if (area)
- X {
- X debug(1, "Reading back news article");
- X rewind(sender);
- X
- X if (badtemp)
- X fclose(badtemp);
- X
- X if ((badtemp =
- X fopen(strcpy(badname, mktemp("/tmp/funpXXXXXX")), "w+"))
- X == NULL)
- X {
- X log("$Cannot open tmp file %s", badname);
- X goto error;
- X }
- X
- X while (fgets(buffer, BUFSIZ, sender))
- X {
- X if (!strncmp(buffer, "Reply-To:", 9))
- X {
- X if (search_name(from))
- X {
- X debug(1, "%s is not a sysop, try his name", from);
- X if (fromnode.zone != -1)
- X originnode = fromnode;
- X else
- X {
- X debug(1, "No node in his name, try * Origin", from);
- X if (originnode.zone == -1)
- X {
- X debug(1, "No * Origin, replace with echo feed");
- X originnode = orignode;
- X }
- X else
- X debug(2, "Origin %s", ascnode(originnode));
- X }
- X }
- X
- X (void) tprintf(newssender, "Reply-To: %s@%s%s\n",
- X from, internode(originnode), realfrom);
- X
- X /* Set Comment-To field */
- X if (search_name(to))
- X {
- X debug(1, "%s is not a sysop, try * Origin", to);
- X if (originnode.zone == -1)
- X {
- X debug(1, "No * Origin, replace with echo feed");
- X originnode = orignode;
- X }
- X else
- X debug(2, "Origin %s", ascnode(originnode));
- X }
- X
- X (void) tprintf(newssender, "Comment-To: %s@%s%s\n", to,
- X internode(originnode), realto);
- X }
- X else
- X (void) tputs(buffer, newssender);
- X }
- X fclose(newssender); /* sender will vanish when its closed! */
- X }
- X
- X /* done with this msg, wait process to finish */
- X (void) fclose(sender);
- X while ((n = wait(&stat_loc)) != pid && n != -1);
- X
- X debug(2, "Wait status: %o", stat_loc);
- X if (stat_loc)
- X savebad(badtemp);
- X
- X fclose(badtemp);
- X unlink(badname);
- X
- X debug(1, "Done with message");
- X
- X /* free argument-list */
- X for (n = 0; args[n]; n++)
- X free(args[n]);
- X continue;
- X
- X /* in the case of error skip text of message */
- X error:
- X while ((c = getc(packet)) && c != EOF);
- X
- X /* free argument-list */
- X for (n = 0; args[n]; n++)
- X free(args[n]);
- X }
- X
- X if (messagetype != MSGTYPE && messagetype != EOF && messagetype != 0)
- X log("Strange ending: %d", messagetype);
- X
- X debug(1, "Done with packet");
- X}
- X
- X/* ARGSUSED */
- Xint
- Xmain(argc, argv, envp)
- X int argc;
- X char **argv, **envp;
- X{
- X struct dirent *dir;
- X DIR *dp;
- X int c;
- X FILE *packet;
- X char files[BUFLEN];
- X Node node;
- X bool nocheck = False;
- X char *error, *p;
- X Node packetnode;
- X
- X node.zone = -1;
- X while ((c = getopt(argc, argv, "if:vV:")) != EOF)
- X switch (c)
- X {
- X case 'V':
- X version = optarg;
- X break;
- X case 'i':
- X nocheck = True;
- X break;
- X case 'v':
- X verbose++;
- X break;
- X case 'f':
- X if (parsefnetaddress(optarg, &node)) exit(1);
- X break;
- X default:
- X fprintf(stderr,
- X "Usage: %s [-v] [-f [[<zone>:]<net>/]<node>[.<point>]]\n",
- X *argv);
- X exit(EX_USAGE);
- X }
- X
- X /* create name for unpacking */
- X if (node.zone == -1)
- X (void) strcpy(files, "");
- X else
- X {
- X sprintipacketname(files, node);
- X /* Cut sequence number off */
- X if (p = strrchr(files, ".")) *p = 0;
- X }
- X
- X debug(2, "Unpacking packets beginning with %s", files);
- X
- X /* try to update nodelist-index */
- X if (error = update_index())
- X {
- X if (*error == '$')
- X log("$Cannot update nodelist-index: %s", error + 1);
- X else
- X log("Cannot update nodelist-index: %s", error);
- X exit(EX_OSERR);
- X }
- X
- X if (chdir(sprintfs("%s/in", SPOOL)) == -1)
- X {
- X log("$Cannot chdir to %s/in", SPOOL);
- X exit(EX_OSERR);
- X };
- X
- X if (dp = opendir("."))
- X {
- X while (dir = readdir(dp))
- X if (!strncmp(dir->d_name, files, strlen(files)) && *dir->d_name != '.')
- X {
- X
- X /* this packet is right */
- X debug(1, "Unpacking %s", dir->d_name);
- X
- X /* open packet */
- X if (packet = fopen(dir->d_name, "r"))
- X {
- X if (read_header(packet))
- X {
- X if (feof(packet))
- X log("Missing packet header");
- X else
- X log("Error reading header, errno %d : %s",
- X errno, sys_errlist[errno]);
- X }
- X else
- X {
- X packetnode.zone = int16(header.orig_zone);
- X packetnode.net = int16(header.orig_net);
- X packetnode.node = int16(header.orig_node);
- X packetnode.point = 0; /* no points in fidonet header? */
- X debug(1, "Packet from %s", ascnode(packetnode));
- X debug(1, "Time %02d:%02d:%02d %d.%d.%d",
- X int16(header.hour),
- X int16(header.minute), int16(header.second),
- X int16(header.day), int16(header.month),
- X int16(header.year));
- X debug(1, "Max baud rate %d, version %d, product %d, x %d",
- X int16(header.rate), int16(header.ver),
- X header.product, header.x1);
- X debug(1, "Pwd \"%s\"", header.pwd_kludge);
- X }
- X
- X if (nocheck || ((int16(header.dest_zone) == MY_ZONE ||
- X int16(header.dest_zone) == 0) &&
- X int16(header.dest_node) == MY_NODE &&
- X int16(header.dest_net) == MY_NET))
- X unpack(packet, packetnode);
- X else
- X log("Packet is to %d:%d/%d",
- X int16(header.dest_zone),
- X int16(header.dest_net),
- X int16(header.dest_node));
- X (void) fclose(packet);
- X
- X /* Move packet to unpacked directory. */
- X if (link(dir->d_name,
- X sprintfs("%s/%s", UNPACKED_DIR, dir->d_name)))
- X log("$Could not link packet %s", dir->d_name);
- X else
- X if (unlink(dir->d_name))
- X log("$Could not unlink packet %s", dir->d_name);
- X }
- X else
- X log("$Unable open packet %s", dir->d_name);
- X }
- X (void) closedir(dp);
- X }
- X else
- X {
- X log("$Unable to open spool directory");
- X exit(EX_OSERR);
- X }
- X exit(EX_OK);
- X /* NOTREACHED */
- X}
- SHAR_EOF
- chmod 0644 funpack.c || echo "restore of funpack.c fails"
- echo "x - extracting fcall.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > fcall.c &&
- X#ifndef lint
- Xstatic char *sccsid = "@(#)%M% %I% Teemu Torma %H%";
- X#endif
- X
- X/* Dial to host-fido for mail.
- X
- X @(#)Copyright (c) 1987 by Teemu Torma
- X
- X Permission is given to distribute this program and alter this code as
- X needed to adapt it to forign systems provided that this header is
- X included and that the original author's name is preserved. */
- X
- X#include <stdio.h>
- X#include <string.h>
- X#include <ctype.h>
- X#include <signal.h>
- X#include <termio.h>
- X#include <dial.h>
- X#include <sys/types.h>
- X#include <dirent.h>
- X#include <time.h>
- X#include "hsu.h"
- X#include "config.h"
- X#include "fnet.h"
- X#include "fio.h"
- X#include "nodelist.h"
- X
- Xextern unsigned sleep();
- Xextern void exit();
- Xextern int getopt();
- Xextern int optind;
- Xextern char *optarg;
- X
- Xint line = -1;
- Xint verbose = INIT_VERBOSE;
- X
- X/* Macros to check timeout */
- X
- X#define SetStart() (stime = time((long *) 0))
- X#define Timeout(t) (time((long *) 0) - stime > (t))
- X
- X/* States for session sender. */
- X
- X#define SendInit (0)
- X#define WaitCxD (1)
- X#define WhackCRs (2)
- X#define WaitClear (3)
- X#define SendMail (4)
- X#define CheckMail (5)
- X#define SendFiles (6)
- X#define CheckFiles (7)
- X#define TryPickup (8)
- X
- X/* States for session receiver. */
- X
- X#define WaitTsync (9)
- X#define RecMail (10)
- X#define XRecEnd (11)
- X#define RecFiles (12)
- X#define ChkFiles (13)
- X#define AllowPickup (14)
- X
- X/* States to break up the loops */
- X
- X#define Error (-1)
- X#define Done (-2)
- X
- X/* For debugging */
- X
- Xstatic char devicebuffer[100];
- XCALL call; /* call structure for dial(3) */
- X
- X/* Show dialer's error code as message */
- X
- Xvoid
- Xlog_dialerr(code)
- X int code;
- X{
- X switch (code)
- X {
- X case INTRPT:
- X log("Interrupt occured during dialing");
- X break;
- X case D_HUNG:
- X log("Dialer hung (no return from write)");
- X break;
- X case NO_ANS:
- X log("No answer");
- X break;
- X case ILL_BD:
- X log("Illegal baud-rate");
- X break;
- X case A_PROB:
- X log("Acu problem (open() failure)");
- X break;
- X case L_PROB:
- X log("Line problem (open() failure)");
- X break;
- X case NO_Ldv:
- X log("Can't open LDEVS file");
- X break;
- X case DV_NT_A:
- X log("Requested device not available");
- X break;
- X case DV_NT_K:
- X log("Requested device %s, line %s telno %s speed %d baud %d, not known",
- X call.device, call.line, call.telno, call.speed, call.baud);
- X break;
- X case NO_BD_A:
- X log("No device available at requested baud");
- X break;
- X case NO_BD_K:
- X log("No device known at requested baud");
- X break;
- X case DV_NT_E:
- X log("Requested speed does not match");
- X break;
- X default:
- X log("Dial error %d", code);
- X }
- X}
- X
- X/* Trapper for signals to quit gracefully. Be must do undial to get lock-
- X file removed */
- X
- Xint
- Xquit(sig)
- X int sig;
- X{
- X (void) signal(SIGINT, SIG_IGN);
- X (void) signal(SIGQUIT, SIG_IGN);
- X (void) signal(SIGTERM, SIG_IGN);
- X (void) signal(SIGHUP, SIG_IGN);
- X
- X if (line >= 0)
- X undial(line);
- X if (sig >= 0)
- X log("Caught signal %d", sig);
- X exit(1);
- X /* NOTREACHED */
- X}
- X
- X/* Send files in batch protocol */
- X
- Xbool
- Xsendfiles()
- X{
- X/* if (batchsend("fio.h")) */
- X return batchsend((char *) 0);
- X/* else return 0; */
- X}
- X
- Xbool recfiles()
- X{
- X return batchrec((char *) 0);
- X}
- X
- X/* ARGSUSED */
- Xint
- Xmain(argc, argv, envp)
- X int argc;
- X char **argv, **envp;
- X{
- X struct termio tio; /* terminal state */
- X int c;
- X time_t stime;
- X int retry_time = 0, no_retrys = 0, wait_line = 0;
- X int state = SendInit, receive_retrys = MAX_SEND_RETRIES;
- X bool ok, pickup = False;
- X Node *node, tnode;
- X char phonenumber[100];
- X char packetname[100], ipacketname[100];
- X char *error, *p;
- X
- X /* try to update nodelist-index */
- X if (error = update_index())
- X {
- X if (*error == '$')
- X log("$Cannot update nodelist-index: %s", error + 1);
- X else
- X log("Cannot update nodelist-index: %s", error);
- X exit(EX_OSERR);
- X }
- X
- X if (chdir(SPOOL) < 0)
- X {
- X log("$Can not chdir to %s", SPOOL);
- X exit(1);
- X }
- X
- X strcpy(packetname, "packet.out");
- X strcpy(ipacketname, "packet.junk");
- X
- X call.attr = &tio;
- X call.baud = 0;
- X call.speed = 0;
- X call.line = NULL;
- X call.telno = NULL;
- X call.modem = 0;
- X call.device = devicebuffer;
- X call.dev_len = sizeof(devicebuffer);
- X
- X tio.c_iflag = IGNPAR | IGNBRK;
- X tio.c_oflag = 0;
- X tio.c_cflag = CS8 | CREAD | HUPCL | CLOCAL;
- X tio.c_lflag = NOFLSH;
- X tio.c_cc[VMIN] = 1;
- X tio.c_cc[VTIME] = 0;
- X
- X if (signal(SIGINT, SIG_IGN) != SIG_IGN)
- X (void) signal(SIGINT, quit);
- X if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
- X (void) signal(SIGTERM, quit);
- X if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
- X (void) signal(SIGQUIT, quit);
- X if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
- X (void) signal(SIGHUP, quit);
- X
- X while ((c = getopt(argc, argv, "vmdp:l:b:s:r:n:w:f:")) != EOF)
- X switch (c)
- X {
- X case 'd':
- X pickup = True;
- X break;
- X case 'p':
- X call.telno = optarg;
- X break;
- X case 'v':
- X verbose++;
- X break;
- X case 'l':
- X call.line = optarg;
- X break;
- X case 'b':
- X call.baud = atoi(optarg);
- X break;
- X case 's':
- X call.speed = atoi(optarg);
- X break;
- X case 'r':
- X retry_time = atoi(optarg);
- X break;
- X case 'n':
- X no_retrys = atoi(optarg);
- X break;
- X case 'w':
- X wait_line = atoi(optarg);
- X break;
- X case 'm':
- X call.modem = 1;
- X break;
- X case 'f':
- X
- X /* Fidonet address to call */
- X
- X if (parsefnetaddress(optarg, &tnode)) exit(1);
- X if (!(node = node_entry(tnode))) {
- X log("Could not get node information");
- X exit(1);
- X }
- X
- X /* Use either maximum speed set or maximum speed of fido system */
- X
- X if (node->speed > MAXBAUD) {
- X if (!call.baud) {
- X call.baud = call.speed = MAXBAUD;
- X }
- X } else {
- X call.baud = call.speed = node->speed;
- X }
- X if (call.baud < MINBAUD) call.baud = call.speed = MINBAUD;
- X
- X /* Translate phone number from nodelist, if not set */
- X
- X if (!call.telno) {
- X dial_translation(phonenumber, node->phone);
- X call.telno = phonenumber;
- X }
- X
- X sprintpacketname(packetname, *node);
- X sprintipacketname(ipacketname, *node);
- X break;
- X
- X default:
- X log("Illegal option for fcall");
- X exit(1);
- X }
- X
- X while (state >= SendInit && state < AllowPickup)
- X switch (state)
- X {
- X case SendInit:
- X if (call.telno)
- X log("Dialing to %s", call.telno);
- X line = dial(call);
- X state = WaitCxD;
- X break;
- X case WaitCxD:
- X if (line == NO_ANS && retry_time)
- X if (--no_retrys < 0)
- X {
- X log("Too many retries in call");
- X state = Error;
- X }
- X else
- X {
- X log("No answer, redial in %d seconds", retry_time);
- X (void) sleep((unsigned) retry_time);
- X state = SendInit;
- X }
- X else
- X if ((line == DV_NT_A || line == NO_BD_A) && wait_line)
- X {
- X log("No free lines, waiting %d seconds", wait_line);
- X (void) sleep((unsigned) wait_line);
- X }
- X else {
- X if (line >= 0)
- X {
- X log("Call succeeded");
- X state = WhackCRs;
- X debug(1, "Wait %d seconds before start", PREWAIT);
- X (void) sleep((unsigned) PREWAIT);
- X }
- X else
- X {
- X log_dialerr(line);
- X log("Dial failed");
- X state = Error;
- X }
- X }
- X break;
- X case WhackCRs:
- X SetStart();
- X while (state == WhackCRs)
- X if (Timeout(30))
- X {
- X log("No response");
- X state = Error;
- X }
- X else if (readline(1) == '\r')
- X {
- X debug(1, "Got CR, wait 1 second");
- X (void) sleep((unsigned) 1);
- X state = WaitClear;
- X }
- X else
- X {
- X debug(2, "Sending <sp><cr>");
- X sendline(' ');
- X sendline('\r');
- X }
- X break;
- X case WaitTsync:
- X SetStart();
- X while (state == WaitTsync)
- X if (Timeout(60))
- X {
- X log("Garbage, no Tsync, Call ok (?)");
- X state = AllowPickup;
- X }
- X else if ((c = readline(1)) == TSYNCH)
- X {
- X debug(1, "Received TSYNCH");
- X state = RecMail;
- X }
- X else if (c == ENQ)
- X {
- X debug(1, "Got ENQ, nothing to pick up");
- X state = AllowPickup;
- X }
- X break;
- X case RecMail:
- X ok = xtrec(sprintfs("in/%s", ipacketname), False);
- X state = XRecEnd;
- X break;
- X case XRecEnd:
- X if (ok)
- X {
- X log("Mail received successfully");
- X
- X /* Flush input */
- X
- X (void) sleep((unsigned) 1);
- X
- X SetStart();
- X while (state == XRecEnd)
- X if (Timeout(60))
- X {
- X log("Garbage on line");
- X state = Error;
- X break;
- X }
- X else if (readline(1) == TIMEOUT)
- X {
- X debug(1, "Line is clear, rec files");
- X state = RecFiles;
- X }
- X }
- X else
- X {
- X log("Receiving mail failed or nothing to receive");
- X log("Moving received packet in/%s to %s", ipacketname,
- X p = sprintfs("%s/%s", BADARTICLES, ipacketname));
- X if (link(sprintfs("in/%s", ipacketname), p))
- X log("$Could not link packet in/%s", ipacketname);
- X else
- X if (unlink(sprintfs("in/%s", ipacketname)))
- X log("$Could not unlink packet in/%s", ipacketname);
- X
- X state = Error;
- X }
- X break;
- X case RecFiles:
- X ok = recfiles();
- X state = ChkFiles;
- X break;
- X case ChkFiles:
- X if (ok)
- X {
- X log("Files received succesfully");
- X (void) sleep((unsigned) 2);
- X state = AllowPickup;
- X }
- X else
- X {
- X log("Files not received ok");
- X state = Error;
- X }
- X break;
- X case WaitClear:
- X SetStart();
- X while (state == WaitClear)
- X if (Timeout(60))
- X {
- X log("Garbage on line");
- X state = Error;
- X break;
- X }
- X else if (readline(WAITCLEAR) == TIMEOUT)
- X {
- X debug(1, "Line is clear, send TSYNCH");
- X sendline(TSYNCH);
- X clear_input();
- X state = SendMail;
- X }
- X break;
- X case SendMail:
- X ok = xtsend(sprintfs("out/%s", packetname), False);
- X if (!ok && receive_retrys--)
- X state = WaitClear;
- X else
- X state = CheckMail;
- X
- X break;
- X case CheckMail:
- X if (ok)
- X {
- X log("Mail sent successfully");
- X log("Moving mail packet out/%s to %s", packetname,
- X p = sprintfs("%s/%s.%s", SENTBUNDLE_DIR, packetname,
- X baseit(sequencer(OPACKETSEQUENCE))));
- X if (link(sprintfs("out/%s", packetname), p))
- X log("$Could not link packet out/%s", packetname);
- X else
- X if (unlink(sprintfs("out/%s", packetname)))
- X log("$Could not unlink packet out/%s",packetname);
- X
- X sequencer(OPACKETSEQUENCE);
- X state = SendFiles;
- X }
- X else
- X {
- X log("Mail send failed");
- X state = Error;
- X }
- X break;
- X case SendFiles:
- X ok = sendfiles();
- X state = CheckFiles;
- X break;
- X case CheckFiles:
- X if (ok)
- X {
- X log("Files sent successfully");
- X state = TryPickup;
- X }
- X else
- X {
- X log("Files not send ok");
- X state = Error;
- X }
- X break;
- X case TryPickup:
- X log("Send successful");
- X if (pickup)
- X {
- X log("Starting mail pickup");
- X state = WaitTsync;
- X }
- X else
- X state = Done;
- X break;
- X }
- X
- X if (state == Error) {
- X log("Conversation failed");
- X } else {
- X log("Conversation complete");
- X }
- X
- X if (line >= 0) {
- X (void) sleep((unsigned) 5);
- X undial(line);
- X }
- X exit(0);
- X /* NOTREACHED */
- X}
- SHAR_EOF
- chmod 0644 fcall.c || echo "restore of fcall.c fails"
- echo "x - extracting fio.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > fio.c &&
- X#ifndef lint
- Xstatic char *sccsid = "@(#)%M% %I% Teemu Torma %H%";
- X#endif
- X
- X/* Routines for io for fidonet software.
- X
- X @(#)Copyright (c) 1987 by Teemu Torma
- X
- X Permission is given to distribute this program and alter this code as
- X needed to adapt it to forign systems provided that this header is
- X included and that the original author's name is preserved. */
- X
- X#include <stdio.h>
- X#include <signal.h>
- X#include <termio.h>
- X#include <sys/types.h>
- X#include "fnet.h"
- X#include "fio.h"
- X
- X/* number of characters in input buffer */
- Xint nchars = 0;
- X
- X#ifdef DEBUG
- X/* This is for protocol debugging logs */
- X#define DEBUG_STATE_READ 1
- X#define DEBUG_STATE_WRITE 2
- X#endif
- X
- X/* Signal trapper for readline. */
- X
- Xstatic int
- Xtrap(sig)
- X int sig;
- X{
- X (void) signal(sig, trap);
- X return 0;
- X}
- X
- X/* Read one character from line. We will do buffering up to BUFBIZ
- X characters. TIMEOUT will be returned it readline timeouts */
- X
- Xint
- Xreadline(timeout)
- X int timeout;
- X{
- X int c;
- X static unsigned char buffer[BUFSIZ];
- X static int pos = 0;
- X void (*alrm)();
- X
- X if (pos < nchars)
- X /* there are characters in buffer */
- X c = buffer[pos++];
- X else
- X {
- X /* trap alarm signals and set timeout value */
- X alrm = signal(SIGALRM, trap);
- X (void) alarm((unsigned) timeout);
- X
- X /* read characters */
- X nchars = read(line, (char *) buffer, BUFSIZ);
- X#ifdef NEEDED
- X if (!receiving_data) debug(10, "Read returned %d", nchars);
- X#endif
- X
- X /* turn off alarm and return function value */
- X (void) alarm((unsigned) 0);
- X (void) signal(SIGALRM, alrm);
- X
- X /* if we got characters return first of them, otherwise return
- X TIMEOUT */
- X
- X if (nchars <= 0)
- X c = TIMEOUT;
- X else
- X {
- X c = buffer[pos = 0];
- X pos++;
- X }
- X }
- X
- X if (!receiving_data) debug(8, "< %02x", c);
- X return c;
- X}
- X
- X/* Flush line. Both terminal buffers and input buffer of readline will
- X be flushed */
- X
- Xvoid
- Xflush()
- X{
- X (void) ioctl(line, TCFLSH, 0);
- X nchars = 0;
- X}
- X
- X/* Send character c to line. This also clears readline's input buffer
- X but not terminal buffers because it might takes too much time.
- X Tue Nov 8 13:49:27 1988
- X No more clearing buffer, as I try to make it sealink compatible.
- X */
- X
- Xvoid
- Xsendline(c)
- X int c;
- X{
- X unsigned char cc = (c & 0377);
- X
- X debug(8, "> %02x", cc);
- X (void) write(line, (char *) &cc, 1);
- X#ifdef NO_SEALINK
- X nchars = 0;
- X#endif
- X}
- X
- Xclear_input()
- SHAR_EOF
- echo "End of part 3"
- echo "File fio.c is continued in part 4"
- echo "4" > s2_seq_.tmp
- exit 0
-
-