home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume16
/
deliver
/
part02
/
copymsg.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-11-14
|
6KB
|
315 lines
/* $Header: copymsg.c,v 1.1 88/06/06 09:38:13 chip Exp $
*
* Take the message from standard input and write it to two temp files,
* one for the header (including the empty line) and one for the body.
*
* $Log: copymsg.c,v $
* Revision 1.1 88/06/06 09:38:13 chip
* Initial revision
*
*/
#include "deliver.h"
/*
* Macros.
*/
/* Does a string start with "From "? */
#define ISFROM(p) ((p)[0] == 'F' && (p)[1] == 'r' && (p)[2] == 'o' \
&& (p)[3] == 'm' && (p)[4] == ' ')
/*
* Local functions.
*/
static char *tempfile();
static int tcreate();
/*----------------------------------------------------------------------
* Copy the message on the standard input to two temp files:
* one for the header and one for the body.
*/
int
copy_message()
{
char buf[BUFSIZ];
FILE *dfp[T_MAX];
char *p, *fsender, *fremote, *osender, *oremote;
long now;
int t, b, empty_line;
int ret = 0;
/*
* Create temporary files to hold the header and message body.
*/
for (t = 0; t < T_MAX; ++t)
{
int fd;
tfile[t] = tempfile();
if ((tfd[t] = tcreate(tfile[t])) == -1)
return -1;
if ((fd = dup(tfd[t])) == -1)
{
syserr("dup %s fd", ttype[t]);
return -1;
}
(void) lseek(fd, 0L, 0);
if ((dfp[t] = fdopen(fd, "r+")) == NULL)
{
error("can't fdopen %s fd", ttype[t]);
return -1;
}
}
/* Debugging message for later examination of temp files. */
if (verbose)
{
message("header=%s, body=%s\n",
tfile[T_HEADER], tfile[T_BODY]);
}
/*
* If there is a From_ line, find the sender name therein.
*/
fsender = fremote = NULL;
b = (fgets(buf, GETSIZE(buf), stdin) ? TRUE : FALSE);
if (b && ISFROM(buf) && (p = strchr(buf, '\n')) != NULL)
{
b = FALSE; /* Don't output two From_ lines */
*p = 0;
/* Find sender */
for (fsender = buf + 5; isspace(*fsender); ++fsender)
; /* until sender */
for (p = fsender; *p && !isspace(*p); ++p)
; /* until end of sender */
if (*p)
*p++ = '\0';
/* Find 'remote from' phrase (if any) */
for (fremote = p;
(fremote = strchr(fremote, 'r')) != NULL;
++fremote)
{
if (strncmp(fremote, "remote from", 11) == 0)
{
fremote += 11;
while (isspace(*fremote))
++fremote;
break;
}
}
}
/*
* Write a From_ line to the header file.
* If the user specified a sender name, use it;
* else if we found a From_ line, use the sender found therein;
* else use the user name of our real UID.
*/
if (sender && *sender)
{
osender = sender;
oremote = NULL;
}
else if (fsender)
{
osender = fsender;
oremote = fremote;
}
else
{
osender = real_ct->name;
oremote = NULL;
}
(void) fputs("From ", dfp[T_HEADER]);
if (oremote)
{
(void) fputs(oremote, dfp[T_HEADER]);
(void) fputc('!', dfp[T_HEADER]);
}
(void) fputs(osender, dfp[T_HEADER]);
(void) fputc(' ', dfp[T_HEADER]);
(void) time(&now);
(void) fputs(ctime(&now), dfp[T_HEADER]);
/*
* Copy the rest of the header (if any).
*/
for (; !feof(stdin); b = FALSE)
{
if (!b)
{
if (fgets(buf, GETSIZE(buf), stdin))
b = TRUE;
else
break;
}
/* Empty line means "end of header" */
if (buf[0] == '\n')
{
b = FALSE; /* Don't put this line in the body. */
break;
}
/*
* A line too long to fit in buf[] can't be a header line.
* At least, that's my opinion... :-)
*/
if (!strchr(buf, '\n'))
break;
/*
* If line begins with whitespace, it's a continuation.
* Else if line begins with From_ or '>', prepend '>'.
* Else if line doesn't look like a header, this must
* be the beginning of the body.
*/
if (isspace(buf[0]))
; /* continuation */
else if (ISFROM(buf) || (buf[0] == '>'))
(void) fputc('>', dfp[T_HEADER]);
else
{
/* look for the colon on a header label */
p = buf;
while (isalpha(*p) || *p == '-')
++p;
if ((p == buf) || (*p != ':'))
break; /* Not a header line! */
}
/* Write the line to the header file. */
(void) fputs(buf, dfp[T_HEADER]);
}
/*
* End the header file with a blank line.
* This enables us to simply concatenate it with the body file
* to produce a valid message.
*/
(void) fputc('\n', dfp[T_HEADER]);
/*
* Copy the body (if any).
*/
empty_line = FALSE;
for (; !feof(stdin); b = FALSE)
{
if (!b)
{
if (fgets(buf, GETSIZE(buf), stdin))
b = TRUE;
else
break;
}
if (ISFROM(buf))
(void) fputc('>', dfp[T_BODY]);
(void) fputs(buf, dfp[T_BODY]);
empty_line = (buf[0] == '\n');
/*
* Output the rest of a very long line.
* We do this here, instead of going around the loop,
* in order to avoid misinterpreting From_ strings
* that may be found in long lines.
*/
while (!strchr(buf, '\n')
&& !feof(stdin)
&& fgets(buf, GETSIZE(buf), stdin))
(void) fputs(buf, dfp[T_BODY]);
}
/* Ensure that the body ends with a blank line. */
if (! empty_line)
(void) fputc('\n', dfp[T_BODY]);
/*
* If we encountered any trouble writing to the temp files,
* let's not keep it secret.
*/
for (t = 0; t < T_MAX; ++t)
{
if (ferror(dfp[t]))
{
error("error writing to %s file %s\n",
ttype[t], tfile[t]);
ret = -1;
}
(void) fclose(dfp[t]);
}
/* Return error/success. */
return ret;
}
/*----------------------------------------------------------------------
* Return a pointer to a temporary filename, or NULL if error.
*/
static char *
tempfile()
{
static char template[] = "/tmp/dl.XXXXXX";
char *f;
f = zalloc(32);
(void) strcpy(f, template);
if (mktemp(f) == NULL)
{
error("can't create temporary file");
return NULL;
}
return f;
}
/*----------------------------------------------------------------------
* Create a file, or complain if it doesn't work.
*/
static int
tcreate(name)
char *name;
{
int fd;
if ((fd = open(name, O_RDWR|O_CREAT|O_EXCL, 0600)) == -1)
{
syserr("can't create %s", name);
return -1;
}
return fd;
}