FIDOGATE 04/06

Martin Junius mj at dfv.rwth-aachen.de
Fri May 24 19:47:37 AEST 1991


---- Cut Here and feed the following to sh ----
#!/bin/sh
# This is part 04 of a multipart archive
# ============= funcs.c ==============
if test -f 'funcs.c' -a X"$1" != X"-c"; then
    echo 'x - skipping funcs.c (File already exists)'
else
echo 'x - extracting funcs.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'funcs.c' &&
/*:ts=4*/
/*****************************************************************************
X * FIDOGATE --- Gateway software UNIX <-> FIDO
X *
X * $Id: funcs.c,v 1.8 91/05/21 08:48:10 mj Exp $
X *
X * Miscancelleus functions, logging, sequence numberic etc.
X *
X * $Log:   funcs.c,v $
X * Revision 1.8  91/05/21  08:48:10  mj
X * Less verbose log().
X * 
X * Revision 1.7  90/12/02  21:21:57  mj
X * Changed program header to mention both authors of the original
X * software posted to alt.sources.
X * 
X * Revision 1.6  90/11/05  20:49:53  mj
X * Changed my signature in all program headers.
X * 
X * Revision 1.5  90/11/01  14:33:39  mj
X * Added function xtol()
X * 
X * Revision 1.4  90/10/29  21:19:14  mj
X * Added functions strnicmp() and stricmp().
X * 
X * Revision 1.3  90/09/08  18:45:54  mj
X * Some changes.
X * 
X * Revision 1.2  90/08/12  14:14:09  mj
X * Removed unused code.
X * 
X * Revision 1.1  90/06/28  22:04:15  mj
X * Much rework of the sources, no more hsu.h and other clean up.
X * rmail improved, now handles special XENIX quirks.
X * 
X * Revision 1.0  90/06/21  19:01:04  mj
X * Initial revision
X * 
X *
X *****************************************************************************
X * This version hacked and maintained by:
X *    _____ _____
X *   |     |___  |   Martin Junius     FIDO:    2:242/6.1   2:242/6.0
X *   | | | |   | |   Republikplatz 3   DOMAIN:  mju at dfv.rwth-aachen.de
X *   |_|_|_|_____|   D-5100 Aachen     Tel. (Voice) 0241-86931
X *
X * Original version of these programs and files:
X *
X *   Teemu Torma
X *   Heikki Suonsivu   FIDO: 2:504/1   UUCP: ...!mcsun!santra!hsu
X *
X *****************************************************************************/
X
#include "fidogate.h"
X
#include <varargs.h>
#include <unistd.h>
X
#include "shuffle.h"
X
X
/*
X * We supply our own version of the toupper()/tolower()
X * macros, because the exact behaviour of those in
X * <ctype.h> varies among systems.
X */
X
#undef _toupper
#undef _tolower
#undef toupper
#undef tolower
X
#define _toupper(c) ((c)-'a'+'A')
#define _tolower(c) ((c)-'A'+'a')
#define toupper(c)  (islower(c) ? _toupper(c) : (c))
#define tolower(c)  (isupper(c) ? _tolower(c) : (c))
X
X
X
#define labs(n) (((n) < 0l) ? (-(n)) : (n))
X
extern void exit(), perror();
extern long atol();
extern time_t time();
X
X
/***** strnicmp() --- compare n chars of strings ignoring case ***************/
X
int strnicmp(sa, sb, len)
register char *sa, *sb;
int len;
{
X   while(len--)
X       if(tolower(*sa) == tolower(*sb)) {
X           sa++;
X           sb++;
X       }
X       else if(tolower(*sa) < tolower(*sb))
X           return(-1);
X       else
X           return(1);
X   return(0);
}
X
X
X
/***** stricmp() --- compare strings ignoring case ***************************/
X
int stricmp(sa, sb)
register char *sa, *sb;
{
X   while(tolower(*sa) == tolower(*sb)) {
X       if(!*sa)
X           return(0);
X       sa++;
X       sb++;
X   }
X   return(tolower(*sa) - tolower(*sb));
}
X
X
X
/***** xtol() --- convert hex string to long *********************************/
X
long xtol(s)
char *s;
{
long val = 0;
int n;
X
X   while(*s) {
X       n = toupper(*s) - (isalpha(*s) ? 'A'-10 : '0');
X       val = val*16 + n;
X       s++;
X   }
X   return(val);
}
X
X
X
FILE *logfp = NULL;
X
/* Lock file descriptor up to the end. If yur system doesn't have lockf()
X   (also known as locking()), or other region or file locking function
X   or system call, this should be done with lock-files. */
X
int
lock(fd)
X     int fd;
{
#ifdef LOCK_LOCKF
X  return lockf(fd, F_LOCK, 0l);
#else
X  return locking(fd, F_LOCK, 0l);
#endif
}
X
/* Unlock file descriptor up to the end. Routine which calls this should
X   first seek to original position. */
X
int
unlock(fd)
X     int fd;
{
#ifdef LOCK_LOCKF
X  return lockf(fd, F_ULOCK, 0l);
#else
X  return locking(fd, F_ULOCK, 0l);
#endif
}
X
/* Return ascii-date in specified format. If format string is null, return
X   date as date(1) returns it. Format is same than date(1) has, in addition
X   %z, which means timezone name. Clock is the time to convert, if NULL,
X   we'll use current time. */
X
char *
date(fmt, clock)
X     char *fmt;
X     time_t *clock;
{
X  /* names for weekdays */
X  static char *weekdays[] = {
X    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
X  };
X
X  /* names for months */
X  static char *months[] = {
X    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
X    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
X  };
X
X  static char buffer[80];
X  char *bp = buffer;
X  time_t _clock;
X  struct tm *tm;
X
X  if (!clock)
X    _clock = time((long *) 0);
X  tm = localtime(clock ? clock : &_clock);
X
X  /* if no format string, this is default */
X  if (!fmt)
X    fmt = "%a %h %d %T %z 19%y";
X
X  for (*bp = 0; *fmt; fmt++)
X    switch (*fmt)
X      {
X      case '%':
X        switch (*++fmt)
X          {
X            /* newline */
X          case 'n':
X            *bp++ = '\n';
X            break;
X            /* tabulator */
X          case 't':
X            *bp++ = '\t';
X            break;
X            /* month number 1-12 */
X          case 'm':
X            (void) sprintf(bp, "%02d", tm->tm_mon + 1);
X            while (*bp)
X              bp++;
X            break;
X            /* day of month 1-31 */
X          case 'd':
X            (void) sprintf(bp, "%2d", tm->tm_mday);
X            while (*bp)
X              bp++;
X            break;
X          case 'q':
X            (void) sprintf(bp, "%02d", tm->tm_mday);
X            while (*bp)
X              bp++;
X            break;
X            /* year 00-99 */
X          case 'y':
X            (void) sprintf(bp, "%02d", tm->tm_year);
X            while (*bp)
X              bp++;
X            break;
X            /* date in format YY/MM/DD */
X          case 'D':
X            (void) sprintf(bp, "%02d/%02d/%02d", tm->tm_year,
X                           tm->tm_mon + 1, tm->tm_mday);
X            while (*bp)
X              bp++;
X            break;
X            /* hour 0-23 */
X          case 'H':
X            (void) sprintf(bp, "%02d", tm->tm_hour);
X            while (*bp)
X              bp++;
X            break;
X            /* minutes 0-59 */
X          case 'M':
X            (void) sprintf(bp, "%02d", tm->tm_min);
X            while (*bp)
X              bp++;
X            break;
X            /* seconds 0-59 */
X          case 'S':
X            (void) sprintf(bp, "%02d", tm->tm_sec);
X            while (*bp)
X              bp++;
X            break;
X            /* time in format HH:MM:SS */
X          case 'T':
X            (void) sprintf(bp, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min,
X                           tm->tm_sec);
X            while (*bp)
X              bp++;
X            break;
X            /* day of year 1-356 */
X          case 'j':
X            (void) sprintf(bp, "%03d", tm->tm_yday + 1);
X            while (*bp)
X              bp++;
X            break;
X            /* weekday 0-6 */
X          case 'w':
X            (void) sprintf(bp, "%d", tm->tm_wday);
X            while (*bp)
X              bp++;
X            break;
X            /* name of weekday 'Mon', 'Tue', ... , 'Sun' */
X          case 'a':
X            (void) strcpy(bp, weekdays[tm->tm_wday]);
X            while (*bp)
X              bp++;
X            break;
X            /* name of month 'Jan', 'Feb', ... , 'Dec' */
X          case 'h':
X            (void) strcpy(bp, months[tm->tm_mon]);
X            while (*bp)
X              bp++;
X            break;
X            /* name of timezone, e.g. EST */
X          case 'z':
X            (void) strcpy(bp, *tzname);
X            while (*bp)
X              bp++;
X            break;
X            /* numeric time zone, e.g. +0200 */
X          case 'o':
X            (void) sprintf(bp, "%c%02ld%02ld", (timezone <= 0l) ? '+' : '-',
X                           (labs(timezone) / (60l * 60l)),
X                           (labs(timezone) % (60l * 60l)));
X            while (*bp)
X              bp++;
X            break;
X          case 'l':
X            /* military time zone, Z = UT, A = -1, M = -12, (J not used),
X               N = +1, Y = +12.. */
X            *bp = (timezone == 0l) ? 'Z' : ((int) (labs(timezone) /
X                                                   (60l * 60l)) +
X                                            ((timezone < 0l) ? 'M' : '@'));
X            if (timezone > 0l && *bp >= 'J')
X              (*bp)++;
X            *++bp = 0;
X            break;
X          default:
X            *bp++ = *fmt;
X            break;
X          }
X        break;
X      default:
X        *bp++ = *fmt;
X        break;
X      }
X
X  *bp = 0;
X  return buffer;
}
X
X
X
/*
X * strerror()  ---  get string from sys_errlist[]
X */
X
char *
strerror(errnum)
int errnum;
{
extern int sys_nerr;
extern char *sys_errlist[];
X
X   if (errnum > 0 && errnum < sys_nerr)
X       return sys_errlist[errnum];
X   return "";
}
X
X
X
/*
X * Log to logfile. If logfile is not open, open it.
X *
X * If first character in format string is '$', print also errno. If external
X * variable verbose is set, logging will be done also to stderr.
X */
X
/**VARARGS**/
void
log(va_alist)
va_dcl
{
va_list args;
char *fmt;
X
X   va_start(args);
X
X   fmt = va_arg(args, char *);
X
X   if(!logfp)
X       if ((logfp = fopen(LOGFILE, "a")) == NULL) {
X           perror("Cannot open log file");
X           return;
X       }
X
X   (void) fprintf(logfp, "%s: ", date("%d %h %y %H:%M", (long *) 0));
X   (void) vfprintf(logfp, *fmt == '$' ? fmt + 1 : fmt, args);
X   if (*fmt == '$')
X       (void) fprintf(logfp, "\n\t\terrno = %d (%s)\n", errno, strerror(errno));
X   else
X       (void) fprintf(logfp, "\n");
X   (void) fflush(logfp);
X
X   /*
X    * if verbose is set, print also to stderr (without date)
X    */
X   if (verbose) {
X       (void) vfprintf(stderr, *fmt == '$' ? fmt + 1 : fmt, args);
X       if (*fmt == '$')
X           (void) fprintf(stderr, "\n\t\terrno = %d (%s)\n", errno, strerror(errno));
X       else
X           (void) fprintf(stderr, "\n");
X       (void) fflush(stderr);
X   }
X
X   va_end(args);
}
X
X
X
/*
X * Debug output. First argument should be number, rest are used arguments
X * for vfprintf(3S). If external variable verbose has equal or greater
X * value than first number, vfprintf(3S) will be used to print other
X * arguments to stderr.
X */
X
/**VARARGS**/
void
debug(va_alist)
va_dcl
{
va_list args;
char *fmt;
int debug_level;
X
X   va_start(args);
X
X   debug_level = va_arg(args, int);
X   fmt = va_arg(args, char *);
X
X   if (debug_level <= verbose) {
X       if (*fmt != '>' && *fmt != '<')
X       (void) vfprintf(stderr, fmt, args);
X       (void) fprintf(stderr, "\n");
X   }
X
X   va_end(args);
}
X
X
X
/* Get next job number. New sequemnt number will be taken from file
X   LIBDIR/seq, which is in ascii-format and new number will be saved
X   back there. */
X
long
job_number()
{
X   return sequencer(JOBSEQ);
}
X
/* General sequencer */
X
long
sequencer(filename)
X     char *filename;
{
X  char seqfile[128], buffer[14];
X  FILE *fp;
X  long seqn = 0;
X
X  (void) sprintf(seqfile, "%s", filename);
X  if ((fp = fopen(seqfile, "r+")) == NULL)
X    {
X      if (errno == ENOENT)
X    {
X      if ((fp = fopen(seqfile, "w+")) == NULL)
X        {
X          log("$Can not create seq-file %s", seqfile);
X          exit(EX_OSFILE);
X        }
X      fputs("1", fp);
X      fclose(fp);
X      if ((fp = fopen(seqfile, "r+")) == NULL)
X        {
X          log("$Can not open new seq-file %s", seqfile);
X          exit(EX_OSFILE);
X        }
X    }
X      else
X    {
X      log("$Can not open seq-file %s", seqfile);
X      exit(EX_OSFILE);
X    }
X    }
X
X  (void) lock(fileno(fp));
X  if (fgets(buffer, 14, fp))
X    seqn = atol(buffer);
X  else
X    seqn = 0; /* This can theoretically fail */
X
X  seqn++;
X  (void) rewind(fp);
X  (void) fprintf(fp, "%ld\n", seqn);
X  (void) unlock(fileno(fp));
X  (void) fclose(fp);
X  return seqn;
}
X
/* Returns current last sequence number */
long
getsequencer(filename)
X     char *filename;
{
X  char seqfile[128], buffer[14];
X  FILE *fp;
X  long seqn = 0;
X
X  (void) sprintf(seqfile, "%s", filename);
X  if ((fp = fopen(seqfile, "r+")) == NULL)
X    {
X      if (errno == ENOENT)
X    {
X      if ((fp = fopen(seqfile, "w+")) == NULL)
X        {
X          log("$Can not create seq-file %s", seqfile);
X          exit(EX_OSFILE);
X        }
X      fputs("1", fp);
X      fclose(fp);
X      if ((fp = fopen(seqfile, "r+")) == NULL)
X        {
X          log("$Can not open new seq-file %s", seqfile);
X          exit(EX_OSFILE);
X        }
X    }
X      else
X    {
X      log("$Can not open seq-file %s", seqfile);
X      exit(EX_OSFILE);
X    }
X    }
X
X  (void) lock(fileno(fp));
X  if (fgets(buffer, 14, fp))
X    seqn = atol(buffer);
X  else
X    seqn = 0; /* This can theoretically fail */
X
X  (void) unlock(fileno(fp));
X  (void) fclose(fp);
X  return seqn;
}
X
/* Get full pathname for spoolfile with new job number. File is in
X   spool directory and contains prefix followed by four digit
X   job number. */
X
char *
spoolfile(prefix)
X     char *prefix;
{
X  static char file[BUFLEN];
X
X  (void) sprintf(file, "%s/%s%08ld", SPOOL, prefix, job_number());
X  return file;
}
X
/* Return basename of s */
X
char *
basename(s)
X     register char *s;
{
X  register char *p = s;
X
X  while (*s)
X    if (*s++ == '/')
X      p = s;
X  return p;
}
X
/* Open file with directory name and filename. */
X
FILE *
pfopen(dir, name, mode)
X     char *dir, *name, *mode;
{
X  char filename[128];
X
X  (void) strcpy(filename, dir);
X  (void) strcat(filename, "/");
X  (void) strcat(filename, name);
X
X  return fopen(filename, mode);
}
X
char *baseit(n)
X     long n;
{
X  static char tab[] =
X    "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
X  int count = 0;
X
X  SHUFFLEBUFFERS;
X
X  while (n)
X    {
X      tcharp[count] = tab[n % strlen(tab)];
X      n = n / strlen(tab);
X      count++;
X    }
X
X  tcharp[count] = 0;
X  return tcharp;
}
X
/* Create packet name for node given */
X
sprintpacketname(s, node)
X     char *s;
X     Node node;
{
X  sprintf(s, "%s%s.%s.%s", node.point ?
X      sprintfs("%s.", baseit( (long) node.point)) : "",
X      baseit( (long) node.node), baseit( (long) node.net),
X      baseit( (long) node.zone));
}
X
/* Create packet name for inbound xx.xx.xx.xx.num. If point
X   number is 0, don't include it. All numbers are in ~63-base to squeeze
X   them to as small space as possible. It could be more sensible solution
X   to make them directory trees but I would need more time for that. This
X   trick makes finding packets difficult.
X   */
X
sprintipacketname(s, node)
X     char *s;
X     Node node;
{
X  sprintf(s, "%s%s.%s.%s.%s", node.point ?
X      sprintfs("%s.", baseit( (long) node.point)) : "",
X      baseit( (long) node.node), baseit( (long) node.net),
X      baseit( (long) node.zone), baseit(sequencer(IPACKETSEQUENCE)));
}
X
X
X
/*
X * Get line from config file. If *-character is in first column, report
X * EOF, and otherwise return line with comments stripped. This causes
X * effect, that each section in configuration file looks like it's own
X * file. Arguments and return value are the same than with fgets(3S).
X */
X
char *
getcl(buffer, len, fp)
char *buffer;
int len;
FILE *fp;
{
char *cp;
X
X   while (fgets(buffer, len, fp)) {
X       buffer[strlen(buffer) - 1] = 0;
X       if (*buffer == '*')
X           return (char *) NULL;
X       /* everything after #-sign is comment */
X       if (cp = strchr(buffer, '#'))
X           *cp = 0;
X       /* if there's something left, return it */
X       if (*buffer)
X           return buffer;
X   }
X   return (char *) NULL;
}
X
X
X
/* Scan config file to specified section. This mechanism is not very
X   effective, but otherwise it would get too complicated. */
X
void
section(number, config)
X     int number;
X     FILE *config;
{
X  char buffer[BUFLEN];
X
X  (void) rewind(config);
X  while (--number)
X    while (getcl(buffer, BUFLEN, config))
X      /* skip section */;
}
X
/* Get header field from file. */
X
#define MAX_HEADER_LEN 256
X
char *mheader(fp, headername)
X     FILE *fp;
X     char *headername;
{
X  static char header[MAX_HEADER_LEN];
X  long position;
X
X  position = ftell(fp);
X
X  rewind(fp);
X
X  /* Blank line terminates also, there shouldn't be any headers
X     after it any more */
X
X  while (fgets(header, MAX_HEADER_LEN, fp) && *header != '\n')
X    if (!strncmp(header, headername, strlen(headername)))
X      {
X    /* Remove \n at end */
X    header[strlen(header) - 1] = 0;
X    fseek(fp, position, 0);
X    return header + strlen(headername);
X      }
X
X  /* Not found, return empty string */
X
X  fseek(fp, position, 0);
X  return "";
}
SHAR_EOF
chmod 0644 funcs.c ||
echo 'restore of funcs.c failed'
Wc_c="`wc -c < 'funcs.c'`"
test 15896 -eq "$Wc_c" ||
    echo 'funcs.c: original size 15896, current size' "$Wc_c"
fi
# ============= rmail.c ==============
if test -f 'rmail.c' -a X"$1" != X"-c"; then
    echo 'x - skipping rmail.c (File already exists)'
else
echo 'x - extracting rmail.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'rmail.c' &&
/*:ts=4*/
/*****************************************************************************
X * FIDOGATE --- Gateway software UNIX <-> FIDO
X *
X * $Id: rmail.c,v 1.12 91/05/07 23:59:33 mj Exp $
X *
X * Replacement for rmail.
X * This program performs two functions:
X * - it checks for mail addressed to the FIDO domain (.fidonet.org)
X *   and passes these messages to rfmail
X * - It does some rudimentary transforming for domain style addresses
X *
X * This is just a small hack. For real mail processing use
X * sendmail or smail, which are much better at those things.
X *
X * $Log:   rmail.c,v $
X * Revision 1.12  91/05/07  23:59:33  mj
X * Uses new function isfido() to determine wheter address is for FIDO or
X * not. Also supports rerouting of UUCP bang addresses to UUCP feed.
X * 
X * Revision 1.11  91/04/28  21:40:55  mj
X * Reroute mail to .uucp also via UUCPFEED.
X * 
X * Revision 1.10  91/03/29  18:13:50  mj
X * Improved routing for new Reply-To: adresses.
X * 
X * Revision 1.9  91/01/05  13:08:58  mj
X * Recognize MY_HOSTNAME.MY_DOMAIN as local address.
X * 
X * Revision 1.8  90/12/09  17:35:50  mj
X * Readdress mail to UUCPFEED. Removed unnessary `GATEWAY' code.
X * 
X * Revision 1.7  90/12/02  21:22:32  mj
X * Changed program header to mention both authors of the original
X * software posted to alt.sources.
X * 
X * Revision 1.6  90/11/05  20:51:06  mj
X * Changed my signature in all program headers.
X * 
X * Revision 1.5  90/07/11  17:57:50  mj
X * Removed an obscure bug while feeding letter to mail receiving
X * process. Once in a while the result was garbage. The cause was
X * that the temporary file was opened by both the parent and the
X * child process. Even if the child never ever does something to
X * this file, this seems to confuse the operating system.
X * 
X * Revision 1.4  90/07/07  17:54:47  mj
X * Improved version. Now rmail is able to get destination address
X * from message header, `To: ...' line. This has been implemented
X * to make rmail work with nn, 'cause this news reader doesn't pass
X * the address as a command line argument to rmail.
X * 
X * Revision 1.3  90/07/01  15:20:37  mj
X * Fixed some bugs in funpack caused by the removal of alloca().
X * No more core dumps, but heaven knows, why it works now. Strange.
X * 
X * Revision 1.2  90/07/01  13:46:12  mj
X * Removed all calls to alloca(). All unsave malloc()'s without
X * checking the returned pointer are now done via xmalloc().
X * Fixed a malloc() error in rmail.
X * 
X * Revision 1.1  90/06/28  22:04:56  mj
X * Much rework of the sources, no more hsu.h and other clean up.
X * rmail improved, now handles special XENIX quirks.
X * 
X * Revision 1.0  90/06/19  18:34:10  mj
X * Initial revision
X * 
X *
X *****************************************************************************
X * This version hacked and maintained by:
X *    _____ _____
X *   |     |___  |   Martin Junius     FIDO:    2:242/6.1   2:242/6.0
X *   | | | |   | |   Republikplatz 3   DOMAIN:  mju at dfv.rwth-aachen.de
X *   |_|_|_|_____|   D-5100 Aachen     Tel. (Voice) 0241-86931
X *
X * Original version of these programs and files:
X *
X *   Teemu Torma
X *   Heikki Suonsivu   FIDO: 2:504/1   UUCP: ...!mcsun!santra!hsu
X *
X *****************************************************************************/
X
#include "fidogate.h"
X
X
X
#define PROGRAMNAME "rmail $Revision: 1.12 $"
X
X
X
/*
X * This is special to XENIX:
X * On XENIX, one can't use rmail for sending mail, 'cause this
X * program doesn't generate a correct `From user ...' line for
X * locally created mail. One has to execute /usr/lib/mail/execmail
X * instead. But execmail *always* generates it's own `From ...'
X * line, even if there is already one in the mail. So for mail
X * of remote origin, e.g. those messages created by funpack, one
X * must instruct execmail to handle this right. This can be done
X * with the `-f' flags of execmail, whose argument replaces user
X * in `From user ...' line.
X */
#ifdef M_XENIX
# define EXECMAIL                           /* Use -f from, if neccessary */
# undef  RECVMAIL
# define RECVMAIL "/usr/lib/mail/execmail"  /* Force use of execmail */
#endif
X 
X
X
/* verbosity */
/* int verbose = 3; /**/
int verbose = INIT_VERBOSE; /**/
X
X
X
/*
X * For domain type addresses (name at system):
X *
X * Local adress converting:
X *     user at localhost.localdomain  ->  user
X * [.uucp domain to bang converting:                ]
X * [    user at system.uucp            ->  system!user ] disabled
X * [    user at system                 ->  system!user ]
X * Forward other messages to UUCP feed
X *     user at system.domain          ->  uucpfeed!domain!user
X * UUCP rerouting via UUCP feed
X *     system!user                 ->  uucpfeed!system!user
X */
X
char *process_address(addr)
char *addr;
{
static char hostname[256];
static char address[256];
static char newaddress[256];
char *p;
int len;
int not_uucp = FALSE;
X
X   gethostname(hostname, 20);
X   strcpy(address, addr);
X   debug(3, "Address to process: %s", addr);
X
X   if(p = strchr(address, '@')) {
X       /*
X        * Domain address: name at system.domain
X        *
X        * Isolate user name, p points to system.domain
X        */
X       *p++ = 0;
X       /*
X        * Remove suffix ".uucp"
X        */
X       len = strlen(p);
#if 0
X       if(len>5 && (!strcmp(p+len-5, ".uucp") || !strcmp(p+len-5, ".UUCP")))
X           p[len - 5] = 0;
X       else if(strchr(p, '.'))
#endif
X           not_uucp = TRUE;
X       /*
X        * If addressed to our hostname or full domain name,
X        * just send to user name
X        */
X       if(!strcmp(p, hostname))
X           *p = 0;
X       else {
X           strcat(hostname, MY_DOMAIN);
X           if(!strcmp(p, hostname))
X               *p = 0;
X       }
X       /*
X        * Construct converted address
X        */
X       if(!*p)                             /* Local address */
X           strcpy(newaddress, address);
X       else if(not_uucp)                   /* Address domain via UUCPFEED */
X           sprintf(newaddress, "%s!%s!%s", UUCPFEED, p, address);
X       else                                /* UUCP address */
X           sprintf(newaddress, "%s!%s", p, address);
X       debug(2, "Renamed %s to %s", addr, newaddress);
X       return strsave(newaddress);
X   }
X   else if(strchr(address, '!')) {
X       /*
X        * Bang address: system!user
X        */
X       sprintf(newaddress, "%s!%s", UUCPFEED, address);
X       return strsave(newaddress);
X   }
X   else
X       return strsave(address); 
}
X
X
X
/*
X * Get name from `From user ...' line.
X * Understood format of From line is:
X *     `From USER day mon dd hh:mm:ss [zone] yyyy [remote from SYSTEM]'
X * Destroys contents of buf!
X */
X
char *get_from_name(buf)
char *buf;
{
char *name, *system;
static char from[64];
X
X   name   = "anonymous";                   /* Defaults */
X   system = "";
X
X   buf += 5;                               /* Skip `From ' */
X   if(*buf) {
X       name = buf;
X       while(*buf && *buf!=' ' && *buf!='\t')
X           buf++;
X       if(*buf) {
X           *buf++ = 0;
X           /* Scan for `remote from ' */
X           while(strlen(buf) >= 12)        /* 12 = strlen("remote from") */
X               if(!strncmp(buf, "remote from ", 12)) {     /* gefunden! */
X                   buf += 12;
X                   system = buf;
X                   while(*buf && *buf!=' ' && *buf!='\t' && *buf!='\n')
X                       buf++;
X                   *buf = 0;
X                   break;
X               }
X               else
X                   buf++;
X       }
X   }
X   
X   if(*system) {
X       strcpy(from, system);
X       strcat(from, "!");
X   }
X   else
X       *from = 0;
X   strcat(from, name);
X       
X   return(from);
}
X
X
X
/*
X * get_to_name() --- Get destination address from `To: ...' line
X */
X
char *get_to_name(buffer)
char *buffer;
{
register char *cp, *np;
register int cnt;
static char to[64];
X
X   buffer += strlen("To: ");
X   *to = 0;
X
X   /*
X    * Parse the name from `To: ...' line. There are basically
X    * two formats:
X    *     `User Name <address>'    or
X    *     `address (User Name)'
X    * We'll try to figure it out which format sender uses.
X    */
X   if ((cp = strchr(buffer, '<')) && (np = strchr(cp, '>'))) {
X       /*
X        * Format is 'From: Name <address>'
X        */
X       for(np=cp+1, cnt=0; *np && *np!='>'; np++, cnt++)
X           to[cnt] = *np;
X       to[cnt] = 0;
X   }
X   else if ((cp = strchr(buffer, '(')) && (np = strchr(cp, ')'))) {
X       /*
X        * Format is 'From: address (Name)'
X        */
X       for(np=buffer, cnt=0; *np && *np!='(' && !isspace(*np); np++, cnt++)
X           to[cnt] = *np;
X       to[cnt] = 0;
X   }
X   else {
X       /*
X        * Not a recognized format, just copy
X        */
X       strncpy(to, buffer, 64);
X       to[63] = 0;
X       cnt = strlen(to);
X       if(to[cnt - 1] == '\n')
X           to[cnt - 1] = 0;
X   }
X   
X   return( *to ? to : NULL);
}
X
X   
X
/*
X * Open stream associated with programs standard input. Program is invoked
X * with given argument list. Popen(3S) would invoke mailer thru sh(1),
X * so this uses less memory and is faster.
X */
X
FILE *
open_mailer(program, args, pid)
char *program, **args;
int *pid;
{
FILE *fp;
int fd[2];
X
X   /* create pipe */
X   if (pipe(fd) == -1) {
X       perror("rmail: pipe");
X       exit(EX_OSERR);
X   }
X
X   switch (*pid = fork()) {
X       case -1:                                /* Error */
X           perror("rmail: fork failed");
X           exit(EX_OSERR);
X       case 0:                                 /* Child */
X           (void) close(0);
X           if (dup(fd[0]) == 0) {
X               (void) close(fd[0]);
X               (void) close(fd[1]);
X               (void) execvp(program, args);
X               perror(program);
X           }
X           else
X               perror("rmail: dup");
X           exit(EX_OSERR);
X       default:                                /* Parent */
X           (void) close(fd[0]);
X           if ((fp = fdopen(fd[1], "w")) == NULL) {
X               perror("rmail: fdopen");
X               exit(EX_OSERR);
X           }
X   }
X   return fp;
}
X
X
X
int main(argc, argv)
int argc;
char *argv[];
{
int cnt;
char **rargs, **fargs;
int rrec = 0, frec = 0, rargc = 1, fargc = 1;
int status = EX_OK;
FILE *mailer;
static char buffer[BUFSIZ];
int stat_loc, pid;
char *from;
char *to;
static char tempname[64];
FILE *temp;
int in_header_flag;
char *addr;
X
X   /*
X    * Allocate memory for argument lists of RECVMAIL and RFMAIL.
X    * 2 extra pointers are needed, 'cause we eventually insert
X    * `-f user' for XENIX execmail. 1 more extra pointer for
X    * address from `To: ...' line.
X    */
X   rargs = (char **)xmalloc( (argc + 4) * sizeof(char *) );
X   fargs = (char **)xmalloc( (argc + 4) * sizeof(char *) );
X
X   rargs[0] = RECVMAIL;
X   fargs[0] = RFMAIL;
X
X   /*
X    * Scan thru receiver list and put all receivers in fidonet in fido-
X    * mailer's receiver-list and all others in real rmails one. No
X    * options can be passed to fidomailer thru this, because it would
X    * be too difficult to determine which one goes to which one and
X    * there might be same options also. Somehow it's good that fidomailer
X    * is well hidden under this...
X    */
X   for (cnt = 1; cnt < argc; cnt++)
X       if (*argv[cnt] == '-')
X           rargs[rargc++] = strsave(argv[cnt]);
X       else {
X           if(isfido(argv[cnt])) {
X               /*
X                * Mail for FIDO.
X                */
X               debug(2, "Argument %d (receiver %d) in fidomailer: %s",
X                               fargc, frec + 1, argv[cnt]);
X               fargs[fargc++] = strsave(argv[cnt]);
X               frec++;
X           }
X           else {
X               /*
X                * Not a valid FIDO address, so this must be for UUCP.
X                * In this case process address further to convert
X                * internet domain address name at system.domain to
X                * UUCP bang address system!name.
X                * Beware: result of process_address() may be a FIDO
X                * address again, so another check is necessary.
X                */
X               addr = process_address(argv[cnt]);
X               if(isfido(addr)) {
X                   debug(2, "Argument %d (receiver %d) in fidomailer: %s",
X                                   fargc, frec + 1, addr);
X                   fargs[fargc++] = addr;
X                   frec++;
X               }
X               else {
X                   debug(2, "Argument %d (receiver %d) in rmail: %s",
X                                   rargc, rrec + 1, addr);
X                   rargs[rargc++] = addr;
X                   rrec++;
X               }
X           }
X       }
X
X   /*
X    * Open temporary file and copy mail from stdin to there
X    */
X   tmpnam(tempname);
X   temp = fopen(tempname, "w");
X   if(!temp) {
X       log("$Can't create temporary file %s", tempname);
X       exit(1);
X   }
X   *buffer = 0;
X   from = to = NULL;
X   in_header_flag = TRUE;
#ifdef EXECMAIL
X   /*
X    * Look form `From user ...' line
X    */
X   *buffer = 0;
X   fgets(buffer, BUFSIZ, stdin);
X   if(!strncmp(buffer, "From ", 5)) {
X       from = get_from_name(buffer);
X       debug(3, "from = %s", from);
X       *buffer = 0;
X   }
X   else {
X       from = NULL;
X       goto test_header;
X   }
#endif
X   while(fgets(buffer, BUFSIZ, stdin)) {
test_header:
X       if(in_header_flag) {
X           if(*buffer == '\n')
X               in_header_flag = FALSE;
X           else if(!strncmp(buffer, "To: ", 4)) {
X               to = get_to_name(buffer);
X               debug(3, "to = %s", to);
X           }
X       }
X       fputs(buffer, temp);
X   }
X   fclose(temp);
X
X   /*
X    * If no address on command line, then use the one from
X    * get_to_name()
X    */
X   if(!frec && !rrec && to) {
X       if(isfido(to)) {
X           debug(2, "Argument %d (receiver %d) in fidomailer: %s",
X                           fargc, frec + 1, to);
X           fargs[fargc++] = strsave(to);
X           frec++;
X       }
X       else {
X           addr = process_address(to);
X           if(isfido(addr)) {
X               debug(2, "Argument %d (receiver %d) in fidomailer: %s",
X                               fargc, frec + 1, addr);
X               fargs[fargc++] = addr;
X               frec++;
X           }
X           else {
X               debug(2, "Argument %d (receiver %d) in rmail: %s",
X                               rargc, rrec + 1, addr);
X               rargs[rargc++] = addr;
X               rrec++;
X           }
X       }
X   }
X
X   /*
X    * NULL terminate arument lists
X    */
X   rargs[rargc] = NULL;
X   fargs[fargc] = NULL;
X
X
X   if (rrec) {
X       /*
X        * Mail to UUCP, use rmail (or XENIX special: execmail)
X        */
X       debug(1, "Mail to UUCP, executing %s", RECVMAIL);
#ifdef EXECMAIL
X       /*
X        * Insert `-f FROM' into argument list of execmail (rargs[])
X        */
X       if(from) {
X           for(cnt=rargc; cnt>=1; cnt--)
X               rargs[cnt + 2] = rargs[cnt];
X           rargs[1] = "-f";
X           rargs[2] = from;
X           rargc += 2;
X       }
#endif /**EXECMAIL**/
X       /*
X        * Open mailer and feed letter to it
X        */
X        mailer = open_mailer(RECVMAIL, rargs, &pid);
X        temp = fopen(tempname, "r");
X        if(!temp) {
X           log("$Can't open %s again", tempname);
X           unlink(tempname);
X           exit(1);
X        }
X       while (fgets(buffer, BUFSIZ, temp))
X           fputs(buffer, mailer);
X        fclose(mailer);
X        /*
X         * Wait for rmail to exit
X         */
X       wait(&stat_loc);
X       if(!status)
X           status = (stat_loc & 0xff) == 0 ? (stat_loc >> 8) & 0xff : 1;
X   }
X
X   if (frec) {
X       /*
X        * Mail to FIDO, use rfmail
X        */
X       debug(1, "Mail to FIDO, executing %s", RFMAIL);
X       /*
X        * Open mailer and feed letter to it
X        */
X        mailer = open_mailer(RFMAIL, fargs, &pid);
X        temp = fopen(tempname, "r");
X        if(!temp) {
X           log("$Can't open %s again", tempname);
X           unlink(tempname);
X           exit(1);
X        }
X       while (fgets(buffer, BUFSIZ, temp))
X           fputs(buffer, mailer);
X        fclose(mailer);
X        /*
X         * Wait for rfmail to exit
X         */
X       wait(&stat_loc);
X       if(!status)
X           status = (stat_loc & 0xff) == 0 ? (stat_loc >> 8) & 0xff : 1;
X   }
X   
X   /*
X    * Remove temporary file
X    */
X   unlink(tempname);
X
X   exit(status);
}
SHAR_EOF
chmod 0644 rmail.c ||
echo 'restore of rmail.c failed'
Wc_c="`wc -c < 'rmail.c'`"
test 14095 -eq "$Wc_c" ||
    echo 'rmail.c: original size 14095, current size' "$Wc_c"
fi
# ============= fpack.c ==============
if test -f 'fpack.c' -a X"$1" != X"-c"; then
    echo 'x - skipping fpack.c (File already exists)'
else
echo 'x - extracting fpack.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'fpack.c' &&
/*:ts=4*/
/*****************************************************************************
X * FIDOGATE --- Gateway software UNIX <-> FIDO
X *
X * $Id: fpack.c,v 2.4 91/05/21 08:47:41 mj Exp $
X *
X * Create and update fidomail packets. Read mail messages from
X * spool directory and append them to packet. If packet doesn't
X * exist already, it will be created.
X *
X * $Log:   fpack.c,v $
X * Revision 2.4  91/05/21  08:47:41  mj
X * Moved log entry for NetMail to rfmail.
X * 
X * Revision 2.3  91/03/29  18:10:14  mj
X * No log entries for news.
X * 
X * Revision 2.2  90/12/09  18:35:27  mj
X * Rewrote some more code. Now support `X' header line and crash mail.
X * 
X * Revision 2.1  90/12/02  21:21:53  mj
X * Changed program header to mention both authors of the original
X * software posted to alt.sources.
X * 
X * Revision 2.0  90/11/23  21:49:24  mj
X * Major rewrite of fpack started: no more ugly messing around with
X * byte order, use machine independent function write_int() instead.
X * Removed some functions and macros.
X * 
X * Revision 1.3  90/11/05  20:49:38  mj
X * Changed my signature in all program headers.
X * 
X * Revision 1.2  90/07/29  18:10:52  mj
X * Place real net/node in message header for FIDO netmail. Also
X * a `^AFMPT x' kludge is generated in this case. Recipient of
X * our mail now gets real address from message, which should
X * make replying much easier.
X * 
X * Revision 1.1  90/06/28  22:04:07  mj
X * Much rework of the sources, no more hsu.h and other clean up.
X * rmail improved, now handles special XENIX quirks.
X * 
X * Revision 1.0  90/06/19  18:32:01  mj
X * Initial revision
X * 
X *
X *****************************************************************************
X * This version hacked and maintained by:
X *    _____ _____
X *   |     |___  |   Martin Junius     FIDO:    2:242/6.1   2:242/6.0
X *   | | | |   | |   Republikplatz 3   DOMAIN:  mju at dfv.rwth-aachen.de
X *   |_|_|_|_____|   D-5100 Aachen     Tel. (Voice) 0241-86931
X *
X * Original version of these programs and files:
X *
X *   Teemu Torma
X *   Heikki Suonsivu   FIDO: 2:504/1   UUCP: ...!mcsun!santra!hsu
X *
X *****************************************************************************/
X
#include "fidogate.h"
/*
#include <fcntl.h>
#include <sys/stat.h>
*/
X
X
#define PROGRAMNAME "fpack $Revision: 2.4 $"
X
X
X
extern time_t time();
extern int getopt();
extern int optind;
extern char *optarg;
extern unsigned sleep();
extern void exit();
extern void swab();
X
Node node;
int verbose = INIT_VERBOSE;
X
X
X
/*
X * Put string to file in null-terminated format.
X */
X
int put_string(fp, s)
FILE *fp;
char *s;
{
X   while (*s) {
X       putc(*s, fp);
X       s++;
X   }
X   putc(0, fp);
}
X
X
X
/*
X * Write 16-bit integer in 80x86 format, i.e. low byte first,
X * then high byte. Machine independent function.
X */
X
int write_int(value, fp)
int value;
FILE *fp;
{
X   putc(value & 0xff, fp);
X   putc((value >> 8) & 0xff, fp);
}
X
X
/*
X * Copy n-char String, force trailing `\0'
X */
X
char *strncpy0(d, s, n)
char *d, *s;
int n;
{
char *p;
X
X   p = strncpy(d, s, n);
X   d[n - 1] = 0;
X   return(p);
}
X   
X
X
/*
X * Write FIDO message header to mail packet. Information is taken
X * from input message header:
X *
X *     N node         Address to send to
X *     T name         Name of recipient
X *     F name         Name of sender
X *     S subject      Subject of message
X *     D date         Date of message (FTS-0001 format)
X *     X flags        Message flags: P=private, C=crash
X */
X
int write_hdr(source, packet)
FILE *source, *packet;
{
int private_flag = FALSE;
char buffer[BUFSIZ];
char from[SIZE_FROM],
X    to[SIZE_TO],
X    subject[SIZE_SUBJECT],
X    date[SIZE_DATE];
Node msg_node;
int attr = 0;
char *p;
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       buffer[strlen(buffer) - 1] = 0; /* strip newline */
X       switch(*buffer) {
X           case 'N':
X               if (parsefnetaddress(buffer, &msg_node)) {
X                   log("Invalid destination: %s", buffer);
X                   return FALSE;
X               }
X               break;
X           case 'F':
X               strncpy0(from, buffer + 2, SIZE_FROM);
X               break;
X           case 'T':
X               strncpy0(to,   buffer + 2, SIZE_TO);
X               break;
X           case 'S':
X               strncpy0(subject, buffer + 2, SIZE_SUBJECT);
X               break;
X           case 'D':
X               strncpy0(date, buffer + 2, SIZE_DATE);
X               break;
X           case 'P':                       /* Old `private' header */
X               attr |= ATTR_PRIVATE;
X               private_flag = TRUE;
X               break;
X           case 'X':                       /* New flags header */
X               for(p=buffer+2; *p; p++)
X                   switch(*p) {
X                       case 'P':
X                           attr |= ATTR_PRIVATE;
X                           private_flag = TRUE;
X                           break;
X                       case 'C':
X                           attr |= ATTR_CRASH;
X                           break;
X                   }
X               break;
X       }
X   }
X
X   /* Save all header values */
X   write_int(MSGTYPE, packet);                         /* save msg type */
X   write_int(private_flag ? REAL_NODE : MY_NODE, packet);/* save our node */
X   write_int(msg_node.node, packet);                   /* save messages node */
X   write_int(private_flag ? REAL_NET : MY_NET, packet);/* save our net */
X   write_int(msg_node.net, packet);                    /* save messages net */
X   write_int(attr, packet);                            /* save attributes */
X   write_int(0, packet);                               /* 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   /* done with this header */
X   return TRUE;
}
X
X
X
/*
X *  Write packet header for new packet.
X */
X
int write_pkthdr(packet)
FILE *packet;
{
Packet header;
int count;
struct tm *tm;
time_t clock = time((long *) 0);
X
X   tm = localtime(&clock);
X
X   /* create packet structure */
X   header.orig_node = MY_NODE;
X   header.dest_node = node.node;
X   header.orig_net  = MY_NET;
X   header.dest_net  = node.net;
X
X   /* save time for header (why all these fields?) */
X   header.year      = tm->tm_year + 1900;
X   header.month     = tm->tm_mon;
X   header.day       = tm->tm_mday;
X   header.hour      = tm->tm_hour + 1;
X   header.minute    = tm->tm_min;
X   header.second    = tm->tm_sec;
X
X   header.rate      = MAXBAUD;
X   header.ver       = HDRVER;
X   header.product   = 0;
X   header.x1        = 0;
#ifdef FIDO_V11w
X   for(count = 0; count < 16; count++)
X       header.fill[count] = 0;
#else
X   for(count = 0; count < 8; count++)
X       header.pwd_kludge[count] = 0;
X   header.orig_zone = MY_ZONE;
X   header.dest_zone = node.zone;
X   for (count = 0; count < 16; count++)
X       header.B_fill2[count] = 0;
X   header.B_fill3 = 0;
#endif
X   /* write header to file */
X   write_int(header.orig_node, packet);
X   write_int(header.dest_node, packet);
X   write_int(header.year     , packet);
X   write_int(header.month    , packet);
X   write_int(header.day      , packet);
X   write_int(header.hour     , packet);
X   write_int(header.minute   , packet);
X   write_int(header.second   , packet);
X   write_int(header.rate     , packet);
X   write_int(header.ver      , packet);
X   write_int(header.orig_net , packet);
X   write_int(header.dest_net , packet);
X   putc(     header.product  , packet);
X   putc(     header.x1       , packet);
X   for(count = 0; count < 8; count++)
X       putc(header.pwd_kludge[count], packet);
X   write_int(header.orig_zone, packet);
X   write_int(header.dest_zone, packet);
X   for(count = 0; count < 16; count++)
X       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(ferror(packet) || feof(packet)) {
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
int main(argc, argv)
int argc;
char *argv[];
{
DIR *dp;
struct dirent *dir;
FILE *msg, *packet;
char packet_name[16];
int c;
Node np;
char *error;
X
X   node.net = node.zone = -1;
X  
X   /* get options */
X   while ((c = getopt(argc, argv, "vf:")) != EOF)
X       switch (c) {
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               fprintf(stderr, "%s\n\n", PROGRAMNAME);
X               fprintf(stderr, "Usage: fpack [-v] [-f Z:N/N.P]\n\n");
X               exit(EX_USAGE);
X       }
X
X   /* make sure that we got net/node */
X   if (node.net == -1 || node.node == -1) {
X       node.zone  = REM_ZONE;
X       node.net   = REM_NET;
X       node.node  = REM_NODE;
X       node.point = REM_POINT;
X       strcpy(node.name, REM_NAME);
X   }
X
#if 0
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    }
#endif
X
X  /* goto spool directory, everything exiting happens there... */
X   if (chdir(SPOOL) == -1) {
X       log("$Can't chdir to %s", SPOOL);
X       exit(1);
X   }
X
#if 0
X   /* create packet name */
X   sprintpacketname(packet_name, node);
#else
X   /* MSDOS compatible packet names */
X   sprintf(packet_name, "%04x%04x.out", node.net, node.node);
#endif
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           log("$Can't open out/%s for update", packet_name);
X           exit(1);
X       }
X       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           log("$Can't open out/%s for writing", packet_name);
X           exit(1);
X       }
X       /* protect packet from users...*/
X       chmod(sprintfs("out/%s", packet_name), 0600);
X       /* write packet-header, if it fails, exit */
X       if (!write_pkthdr(packet)) {
X           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       sleep(5);
X
X   /* open spool directory */
X   dp = opendir(".");
X   if(!dp) {
X       log("$Can't open spool directory %s", SPOOL);
X       exit(1);
X    }
X   while (dir = readdir(dp)) {
X       /* check that file is for us */
X       if(dir->d_name[0]=='M' && dir->d_name[1]=='.') {
X           msg = fopen(dir->d_name, "r");
X           if(!msg) {
X               log("$Can't open mail %s for reading", dir->d_name);
X               continue;
X           }
X           debug(1, "Adding mailfile %s", dir->d_name);
X
X           /* save header */
X           if(write_hdr(msg, packet)) {
X               /* copy mail text, replace newlines with <cr> <lf> */
X               while ((c = getc(msg)) && c != EOF) {
X                   if (c == '\n')
X                       putc('\r', packet);
X                   putc(c, packet);
X               }
X               /* null-terminate msg text */
X               putc(0, packet);
X           }
X           fclose(msg);
X           if(unlink(dir->d_name) == -1)
X               log("$Unable to unlink %s", dir->d_name);
X       }
X   }
X   closedir(dp);
X
X   /* msg type 0 indicates end of packet */
X   write_int(0, packet);
X
X   fclose(packet);
X
X   exit(0);
}
SHAR_EOF
chmod 0644 fpack.c ||
echo 'restore of fpack.c failed'
Wc_c="`wc -c < 'fpack.c'`"
test 10575 -eq "$Wc_c" ||
    echo 'fpack.c: original size 10575, current size' "$Wc_c"
fi
true || echo 'restore of funpack.c failed'
echo End of part 4, continue with part 5
exit 0

--
 _____ _____
|     |___  |   Martin Junius     FIDO:    2:242/6.1   2:242/6.0
| | | |   | |   Republikplatz 3   DOMAIN:  mj at dfv.rwth-aachen.de
|_|_|_|_____|   D-5100 Aachen     Tel. (Voice) 0241-86931



More information about the Alt.sources mailing list