1625 lines
30 KiB
C
1625 lines
30 KiB
C
/*
|
|
* Copyright (c) 1980 Regents of the University of California.
|
|
* All rights reserved. The Berkeley software License Agreement
|
|
* specifies the terms and conditions for redistribution.
|
|
*/
|
|
|
|
#ifndef lint
|
|
static char *sccsid = "@(#)collect.c 5.2 (Berkeley) 6/21/85";
|
|
#endif /* !lint */
|
|
|
|
/*
|
|
* Mail -- a mail program
|
|
*
|
|
* Collect input from standard input, handling
|
|
* ~ escapes.
|
|
*/
|
|
|
|
#include "glob.h"
|
|
#include <sys/stat.h>
|
|
#include <ctype.h>
|
|
#include <termio.h>
|
|
#include <errno.h>
|
|
|
|
/*
|
|
* Read a message from standard output and return a read file to it
|
|
* or NULL on error.
|
|
*/
|
|
|
|
/*
|
|
* The following hokiness with global variables is so that on
|
|
* receipt of an interrupt signal, the partial message can be salted
|
|
* away on dead.letter. The output file must be available to flush,
|
|
* and the input to read. Several open files could be saved all through
|
|
* Mail if stdio allowed simultaneous read/write access.
|
|
*/
|
|
|
|
#if defined(SVR3) || defined(_SVR4_SOURCE)
|
|
static void (*savesig)(); /* Previous SIGINT value */
|
|
static void (*savehup)(); /* Previous SIGHUP value */
|
|
#ifdef VMUNIX
|
|
static void (*savecont)(); /* Previous SIGCONT value */
|
|
#endif /* VMUNIX */
|
|
#else
|
|
static int (*savesig)(); /* Previous SIGINT value */
|
|
static int (*savehup)(); /* Previous SIGHUP value */
|
|
#ifdef VMUNIX
|
|
static int (*savecont)(); /* Previous SIGCONT value */
|
|
#endif /* VMUNIX */
|
|
#endif /* SVR3 || _SVR4_SOURCE */
|
|
static FILE *newi; /* File for saving away */
|
|
static FILE *newo; /* Output side of same */
|
|
static int hf; /* Ignore interrups */
|
|
static int hadintr; /* Have seen one SIGINT so far */
|
|
|
|
static jmp_buf coljmp; /* To get back to work */
|
|
|
|
void collrub(int);
|
|
void resetsigs(FILE *, FILE *);
|
|
|
|
FILE *
|
|
collect(hp)
|
|
struct header *hp;
|
|
{
|
|
FILE *ibuf, *fbuf, *obuf;
|
|
int lc, cc, escape, eof, frtn;
|
|
register int c, t;
|
|
char linebuf[LINESIZE], *cp;
|
|
extern char tempMail[];
|
|
void collintsig(), collhupsig(), intack(), collcont();
|
|
char getsub;
|
|
struct tcmd *tcom;
|
|
int i;
|
|
|
|
noreset++;
|
|
ibuf = obuf = NULL;
|
|
if (value("ignore") != NOSTR)
|
|
hf = 1;
|
|
else
|
|
hf = 0;
|
|
hadintr = 0;
|
|
#ifdef VMUNIX
|
|
if ((savesig = sigset(SIGINT, SIG_IGN)) != SIG_IGN)
|
|
sigset(SIGINT, hf ? intack : collrub), sigblock(sigmask(SIGINT));
|
|
if ((savehup = sigset(SIGHUP, SIG_IGN)) != SIG_IGN)
|
|
sigset(SIGHUP, collrub), sigblock(sigmask(SIGHUP));
|
|
savecont = sigset(SIGCONT, collcont);
|
|
#else /* !VMUNIX */
|
|
savesig = signal(SIGINT, SIG_IGN);
|
|
savehup = signal(SIGHUP, SIG_IGN);
|
|
#endif /* VMUNIX */
|
|
newi = NULL;
|
|
newo = NULL;
|
|
if ((obuf = fopen(tempMail, "w")) == NULL) {
|
|
perror(tempMail);
|
|
resetsigs(ibuf, obuf);
|
|
return(NULL);
|
|
}
|
|
newo = obuf;
|
|
if ((ibuf = fopen(tempMail, "r")) == NULL) {
|
|
perror(tempMail);
|
|
newo = NULL;
|
|
fclose(obuf);
|
|
resetsigs(ibuf, obuf);
|
|
return(NULL);
|
|
}
|
|
newi = ibuf;
|
|
m_remove(tempMail);
|
|
|
|
/*
|
|
* If we are going to prompt for a subject,
|
|
* refrain from printing the new line after
|
|
* the headers.
|
|
*/
|
|
|
|
t = (GALLHDR|GNL)&~GBCC;
|
|
getsub = 0;
|
|
if (intty && sflag == NOSTR &&
|
|
hp->h_subject == NOSTR &&
|
|
((value("ask") || value("asksub")) ||
|
|
/* The default is "ask" and "asksub" */
|
|
(!value("ask") && !value("asksub"))))
|
|
{
|
|
t &= ~GNL;
|
|
getsub++;
|
|
}
|
|
if (value("noask") || value("noasksub")) {
|
|
t = (GALLHDR|GNL)&~GBCC;
|
|
getsub = 0;
|
|
}
|
|
if (hp->h_seq != 0) {
|
|
puthead(hp, stdout, t);
|
|
fflush(stdout);
|
|
}
|
|
escape = ESCAPE;
|
|
if ((cp = value("escape")) != NOSTR)
|
|
escape = *cp;
|
|
eof = 0;
|
|
for (;;) {
|
|
#ifdef VMUNIX
|
|
int omask = sigblock(0) &~ (sigmask(SIGINT)|sigmask(SIGHUP));
|
|
#endif
|
|
|
|
setjmp(coljmp);
|
|
#ifdef VMUNIX
|
|
sigsetmask(omask);
|
|
#else /* !VMUNIX */
|
|
if (savesig != SIG_IGN) {
|
|
if(hf) /* work around compiler bug; can't use ? : . 3/89 */
|
|
signal(SIGINT, intack);
|
|
else
|
|
signal(SIGINT, collintsig);
|
|
}
|
|
if (savehup != SIG_IGN)
|
|
signal(SIGHUP, collhupsig);
|
|
#endif /* VMUNIX */
|
|
fflush(stdout);
|
|
if (getsub) {
|
|
grabh(hp, GSUBJECT);
|
|
getsub = 0;
|
|
continue;
|
|
}
|
|
for (i=0; i<LINESIZE; i++)
|
|
linebuf[i] = 0;
|
|
if (readline(stdin, linebuf) <= 0) {
|
|
if (intty && value("ignoreeof") != NOSTR) {
|
|
if (++eof > 35)
|
|
break;
|
|
printf("Use \".\" to terminate letter\n");
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
eof = 0;
|
|
hadintr = 0;
|
|
if (intty && equal(".", linebuf) &&
|
|
(value("dot") != NOSTR || value("ignoreeof") != NOSTR))
|
|
break;
|
|
if (linebuf[0] != escape || rflag != NOSTR) {
|
|
if ((t = putline(obuf, linebuf)) < 0) {
|
|
resetsigs(ibuf, obuf);
|
|
return(NULL);
|
|
}
|
|
continue;
|
|
}
|
|
if ((linebuf[0] == escape) && (linebuf[1] == escape)) {
|
|
if (putline(obuf, &linebuf[1]) < 0) {
|
|
resetsigs(ibuf, obuf);
|
|
return(NULL);
|
|
}
|
|
}
|
|
else if (linebuf[1] == '.') {
|
|
frtn = 0;
|
|
goto eofl;
|
|
}
|
|
else {
|
|
tcom = tlex(&linebuf[1], &cp);
|
|
if (tcom == TNONE)
|
|
printf("Unknown command: \"%s\"\n",
|
|
&linebuf[1]);
|
|
else {
|
|
switch(tcom->tc_argtype) {
|
|
case TNOARG:
|
|
frtn = (*tcom->tc_func)(0);
|
|
break;
|
|
|
|
case TSTR:
|
|
frtn = (*tcom->tc_func)(cp);
|
|
break;
|
|
|
|
case THDR:
|
|
frtn = (*tcom->tc_func)(hp);
|
|
break;
|
|
|
|
case TBUF:
|
|
frtn = (*tcom->tc_func)(&ibuf, &obuf);
|
|
break;
|
|
|
|
case THDRSTR:
|
|
frtn = (*tcom->tc_func)(hp, cp);
|
|
break;
|
|
|
|
case TBUFSTR:
|
|
frtn = (*tcom->tc_func)(&ibuf, &obuf,
|
|
cp);
|
|
break;
|
|
|
|
case TBUFHDR:
|
|
frtn = (*tcom->tc_func)(&ibuf, &obuf,
|
|
hp);
|
|
break;
|
|
}
|
|
if (frtn)
|
|
return(NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
eofl:
|
|
/*
|
|
* Don't use the .signature feature for X/Open's mailx
|
|
*/
|
|
if (ismailx)
|
|
goto nodotsignature;
|
|
{
|
|
char xsigned[PATHSIZE];
|
|
char xsigned2[PATHSIZE];
|
|
struct name *names;
|
|
int remote;
|
|
|
|
|
|
/*
|
|
* Signature search:
|
|
* 1. If no '!' in "to" field try ~/.lsignature
|
|
* otherwise try ~/.rsignature.
|
|
* 2. If no such file, try ~/.signature (also
|
|
* used by netnews).
|
|
*/
|
|
strncpy(xsigned, homedir, PATHSIZE);
|
|
xsigned[PATHSIZE - 1] = '\0';
|
|
strncpy(xsigned2,homedir, PATHSIZE);
|
|
xsigned2[PATHSIZE - 1] = '\0';
|
|
remote = 0;
|
|
if (0 != hp->h_to) {
|
|
names = usermap(extract(hp->h_to));
|
|
while (names != NULL) {
|
|
if (strchr(names->n_name,'!')
|
|
|| strchr(names->n_name,'@')) {
|
|
remote++;
|
|
break;
|
|
}
|
|
names = names->n_flink;
|
|
}
|
|
strcat(xsigned, ((remote != 0) ?
|
|
"/.rsignature" : "/.lsignature"));
|
|
}
|
|
strcat(xsigned2,"/.signature");
|
|
if (((fbuf = fopen(xsigned, "r")) != NULL) ||
|
|
((fbuf = fopen(xsigned2, "r")) != NULL)) {
|
|
fflush(stdout);
|
|
fflush(stderr);
|
|
lc = 0;
|
|
cc = 0;
|
|
while (readline(fbuf, linebuf) > 0) {
|
|
lc++;
|
|
if ((t = putline(obuf, linebuf)) < 0) {
|
|
fclose(fbuf);
|
|
resetsigs(ibuf, obuf);
|
|
return(NULL);
|
|
}
|
|
cc += t;
|
|
}
|
|
fclose(fbuf);
|
|
}
|
|
}
|
|
nodotsignature:
|
|
fclose(obuf);
|
|
rewind(ibuf);
|
|
sigset(SIGINT, savesig);
|
|
sigset(SIGHUP, savehup);
|
|
#ifdef VMUNIX
|
|
sigset(SIGCONT, savecont);
|
|
sigsetmask(0);
|
|
#endif /* VMUNIX */
|
|
noreset = 0;
|
|
return(ibuf);
|
|
}
|
|
|
|
|
|
void
|
|
resetsigs(FILE *ibuf, FILE *obuf)
|
|
{
|
|
if (ibuf != NULL)
|
|
fclose(ibuf);
|
|
if (obuf != NULL)
|
|
fclose(obuf);
|
|
sigset(SIGINT, savesig);
|
|
sigset(SIGHUP, savehup);
|
|
#ifdef VMUNIX
|
|
sigset(SIGCONT, savecont);
|
|
sigsetmask(0);
|
|
#endif /* VMUNIX */
|
|
noreset = 0;
|
|
return;
|
|
}
|
|
|
|
|
|
esctocmd(str)
|
|
char *str;
|
|
{
|
|
execute(str, 1);
|
|
printf("(continue)\n");
|
|
return(0);
|
|
}
|
|
|
|
tintr()
|
|
{
|
|
hadintr++;
|
|
collrub(SIGINT);
|
|
safe_exit(1);
|
|
}
|
|
|
|
/*
|
|
* Grab the "usual" headers and any others that are now in use.
|
|
*/
|
|
grabhdrs(hp)
|
|
struct header *hp;
|
|
{
|
|
if (!intty || !outtty)
|
|
printf("~h: no can do!?\n");
|
|
else {
|
|
grabh(hp, GTO|GCC|GBCC|GSUBJECT|hp->h_optusedmask);
|
|
printf("(continue)\n");
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
/*
|
|
* Grab all the headers.
|
|
*/
|
|
graballhdrs(hp)
|
|
struct header *hp;
|
|
{
|
|
if (!intty || !outtty)
|
|
printf("~H: no can do!?\n");
|
|
else {
|
|
grabh(hp, GREGHDR);
|
|
printf("(continue)\n");
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
/*
|
|
* Add to the In-Reply-To list.
|
|
*/
|
|
addirt(hp, str)
|
|
struct header *hp;
|
|
char *str;
|
|
{
|
|
if (notempty(str)) {
|
|
hp->h_inreplyto = addto(hp->h_inreplyto, str);
|
|
hp->h_optusedmask |= GIRT;
|
|
}
|
|
hp->h_seq++;
|
|
return(0);
|
|
}
|
|
|
|
|
|
/*
|
|
* Add to the Keywords list.
|
|
*/
|
|
addkey(hp, str)
|
|
struct header *hp;
|
|
char *str;
|
|
{
|
|
if (notempty(str)) {
|
|
hp->h_keywords = addto(hp->h_keywords, str);
|
|
hp->h_optusedmask |= GKEY;
|
|
}
|
|
hp->h_seq++;
|
|
return(0);
|
|
}
|
|
|
|
/*
|
|
* Add to the To list.
|
|
*/
|
|
addt(hp, str)
|
|
struct header *hp;
|
|
char *str;
|
|
{
|
|
hp->h_to = addto(hp->h_to, str);
|
|
hp->h_seq++;
|
|
return(0);
|
|
}
|
|
|
|
/*
|
|
* Set the Subject list.
|
|
*/
|
|
setsubj(hp, str)
|
|
struct header *hp;
|
|
char *str;
|
|
{
|
|
while (isspace(*str))
|
|
str++;
|
|
hp->h_subject = savestr(str);
|
|
hp->h_seq++;
|
|
return(0);
|
|
}
|
|
|
|
/*
|
|
* Add to the cc list.
|
|
*/
|
|
addcc(hp, str)
|
|
struct header *hp;
|
|
char *str;
|
|
{
|
|
hp->h_cc = addto(hp->h_cc, str);
|
|
hp->h_seq++;
|
|
return(0);
|
|
}
|
|
|
|
/*
|
|
* Add to the bcc list.
|
|
*/
|
|
addbcc(hp, str)
|
|
struct header *hp;
|
|
char *str;
|
|
{
|
|
hp->h_bcc = addto(hp->h_bcc, str);
|
|
hp->h_seq++;
|
|
return(0);
|
|
}
|
|
|
|
/*
|
|
* Set the Comments line.
|
|
*/
|
|
setcomments(hp, str)
|
|
struct header *hp;
|
|
char *str;
|
|
{
|
|
while (isspace(*str))
|
|
str++;
|
|
if (*str != '\0')
|
|
hp->h_optusedmask |= GCOM;
|
|
else
|
|
hp->h_optusedmask &= ~GCOM;
|
|
hp->h_comments = savestr(str);
|
|
hp->h_seq++;
|
|
return(0);
|
|
}
|
|
|
|
/*
|
|
* Insert the value of the named variable: 'sign', followed by a newline
|
|
* character, into the text of the message. If the string is 'unset' or
|
|
* NULL, the message will not be changed.
|
|
*/
|
|
insert_sign(ibufp, obufp)
|
|
FILE **ibufp, **obufp;
|
|
{
|
|
return(insert_val(ibufp, obufp, "sign"));
|
|
}
|
|
|
|
/*
|
|
* Insert the value of the named variable: 'Sign', followed by a newline
|
|
* character, into the text of the message. If the string is 'unset' or
|
|
* NULL, the message will not be changed.
|
|
*/
|
|
insert_Sign(ibufp, obufp)
|
|
FILE **ibufp, **obufp;
|
|
{
|
|
return(insert_val(ibufp, obufp, "Sign"));
|
|
}
|
|
|
|
/*
|
|
* Insert the value of the named variable, followed by a newline character,
|
|
* into the text of the message. If the string is 'unset' or NULL, the
|
|
* message will not be changed.
|
|
*/
|
|
|
|
insert_val(ibufp, obufp, str)
|
|
FILE **ibufp, **obufp;
|
|
char *str;
|
|
{
|
|
int i;
|
|
char *cp, *cp1, linebuf[LINESIZE];
|
|
|
|
if (*str == '\0') {
|
|
/* nothing to insert, just leave */
|
|
return(0);
|
|
}
|
|
#ifdef DANCDEBUG
|
|
fprintf(stderr, "insert_val: str=%x %x %x %x %x %x\n",
|
|
*str, *(str+1), *(str+2), *(str+3), *(str+4), *(str+5));
|
|
#endif
|
|
/*
|
|
* Strip off leading blanks
|
|
*/
|
|
cp1 = str;
|
|
while (isspace(*cp1))
|
|
cp1++;
|
|
|
|
#ifdef DANCDEBUG
|
|
fprintf(stderr, "insert_val: *(cp1+0-->cp1+6)=%x %x %x %x %x %x %x\n",
|
|
*cp1, *(cp1+1), *(cp1+2), *(cp1+3), *(cp1+4), *(cp1+5), *(cp1+6));
|
|
#endif
|
|
|
|
if ((*cp1 == 0) || (cp = value(cp1)) == NOSTR) {
|
|
/* nothing to insert, just leave */
|
|
return(0);
|
|
}
|
|
/*
|
|
* This code to test "*cp" for zero seems redundant, but
|
|
* needs to be done. There are cases where the above return
|
|
* from 'value()' has 'cp' being non-zero where the first character
|
|
* of the sttring pointed to by 'cp' is zero.
|
|
*/
|
|
if (*cp == '\0') {
|
|
/* nothing to insert, just leave */
|
|
return(0);
|
|
}
|
|
|
|
#ifdef DANCDEBUG
|
|
fprintf(stderr, "insert_val: value returned: *(cp+0-->cp+19)=\n");
|
|
fprintf(stderr,
|
|
"%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n",
|
|
*(cp+0), *(cp+1), *(cp+2), *(cp+3), *(cp+4), *(cp+5),
|
|
*(cp+6), *(cp+7), *(cp+8), *(cp+9), *(cp+10), *(cp+11),
|
|
*(cp+12), *(cp+13), *(cp+14), *(cp+15), *(cp+16), *(cp+17),
|
|
*(cp+18), *(cp+19));
|
|
#endif
|
|
|
|
for (i=0; i<LINESIZE; i++)
|
|
linebuf[i] = 0;
|
|
/*
|
|
* Convert the passed string characters: "\t" and "\n"
|
|
* to one character: '\t' and '\n', respectively.
|
|
*/
|
|
cp1 = cp;
|
|
for (i=0; i<strlen(cp); i++) {
|
|
switch(*cp1) {
|
|
case '\\':
|
|
if ((cp1+2) <= (cp + strlen(cp))) {
|
|
if (*(cp1+1) == '\\')
|
|
cp1++;
|
|
if (*(cp1+1) == 't') {
|
|
linebuf[i] = '\t';
|
|
cp1 += 2;
|
|
break;
|
|
}
|
|
if (*(cp1+1) == 'n') {
|
|
linebuf[i] = '\n';
|
|
cp1 += 2;
|
|
break;
|
|
}
|
|
}
|
|
linebuf[i] = *cp1++;
|
|
break;
|
|
default:
|
|
linebuf[i] = *cp1++;
|
|
}
|
|
}
|
|
if (putline(*obufp, linebuf) < 0) {
|
|
resetsigs(*ibufp, *obufp);
|
|
return(1);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
/*
|
|
* Read deadletter into message.
|
|
*/
|
|
getdead(ibufp, obufp)
|
|
FILE **ibufp, **obufp;
|
|
{
|
|
return(getfile(ibufp, obufp, deadletter));
|
|
}
|
|
|
|
/*
|
|
* Read file into message
|
|
*/
|
|
getfile(ibufp, obufp, str)
|
|
FILE **ibufp, **obufp;
|
|
char *str;
|
|
{
|
|
register int lc, cc, t, lcc;
|
|
char *cp, linebuf[LINESIZE];
|
|
FILE *fbuf;
|
|
int i;
|
|
|
|
cp = str;
|
|
while (isspace(*cp))
|
|
cp++;
|
|
if (*cp == '\0') {
|
|
printf("Interpolate what file?\n");
|
|
return(0);
|
|
}
|
|
if (*cp == '!') {
|
|
cp = expandbang(cp);
|
|
if (cp == NOSTR)
|
|
return(0);
|
|
if (strlen(cp) == 0)
|
|
return(0);
|
|
cc = 0;
|
|
lc = 0;
|
|
while (*cp) {
|
|
lcc = 0;
|
|
for (i=0; i<LINESIZE; i++) {
|
|
if ((*cp == '\n') || (*cp == '\0')) {
|
|
linebuf[i] = '\0';
|
|
cp++;
|
|
lc++;
|
|
if ((t=putline(*obufp, linebuf)) < 0) {
|
|
resetsigs(*ibufp, *obufp);
|
|
return(1);
|
|
}
|
|
lcc = 0;
|
|
cc += t;
|
|
if (*(cp - 1) == '\0')
|
|
cp--;
|
|
break;
|
|
} else {
|
|
linebuf[i] = *cp++;
|
|
lcc++;
|
|
}
|
|
}
|
|
if (lcc) {
|
|
linebuf[LINESIZE - 1] = '\0';
|
|
lc++;
|
|
if ((t=putline(*obufp, linebuf)) < 0) {
|
|
resetsigs(*ibufp, *obufp);
|
|
return(1);
|
|
}
|
|
lcc = 0;
|
|
cc += t;
|
|
}
|
|
}
|
|
fflush(*obufp);
|
|
printf("\"%s\" ", str+1);
|
|
printf("%ld/%ld\n", lc, cc);
|
|
fflush(stdout);
|
|
return(0);
|
|
} else
|
|
cp = expand(cp);
|
|
if (cp == NOSTR)
|
|
return(0);
|
|
if (isdir(cp)) {
|
|
printf("%s: directory\n", cp);
|
|
return(0);
|
|
}
|
|
if ((fbuf = fopen(cp, "r")) == NULL) {
|
|
printf("%s: %s\n", cp, strerror(errno));
|
|
return(0);
|
|
}
|
|
printf("\"%s\" ", cp);
|
|
fflush(stdout);
|
|
lc = 0;
|
|
cc = 0;
|
|
while (readline(fbuf, linebuf) > 0) {
|
|
lc++;
|
|
if ((t = putline(*obufp, linebuf)) < 0) {
|
|
fclose(fbuf);
|
|
resetsigs(*ibufp, *obufp);
|
|
return(1);
|
|
}
|
|
cc += t;
|
|
}
|
|
fclose(fbuf);
|
|
printf("%d/%d\n", lc, cc);
|
|
return(0);
|
|
}
|
|
|
|
/*
|
|
* Add to the References list.
|
|
*/
|
|
addref(hp, str)
|
|
struct header *hp;
|
|
char *str;
|
|
{
|
|
if (notempty(str)) {
|
|
hp->h_references = addto(hp->h_references, str);
|
|
hp->h_optusedmask |= GREF;
|
|
}
|
|
hp->h_seq++;
|
|
return(0);
|
|
}
|
|
|
|
|
|
/*
|
|
* Add to Reply-to header field.
|
|
*/
|
|
addreplyto(hp, str)
|
|
struct header *hp;
|
|
char *str;
|
|
{
|
|
if (notempty(str)) {
|
|
hp->h_replyto = addto(hp->h_replyto, str);
|
|
hp->h_optusedmask |= GRT;
|
|
}
|
|
hp->h_seq++;
|
|
return(0);
|
|
}
|
|
|
|
/*
|
|
* Set the Return-Receipt-To header field.
|
|
*/
|
|
addrtnrcpt(hp, str)
|
|
struct header *hp;
|
|
char *str;
|
|
{
|
|
if (notempty(str)) {
|
|
hp->h_rtnrcpt = addto(hp->h_rtnrcpt, str);
|
|
hp->h_optusedmask |= GRR;
|
|
}
|
|
else if (hp->h_rtnrcpt == NOSTR) {
|
|
hp->h_rtnrcpt = addto(hp->h_rtnrcpt, myname);
|
|
hp->h_optusedmask |= GRR;
|
|
hp->h_seq++;
|
|
printf("Return receipt to \"%s\" added.\n", myname);
|
|
}
|
|
else {
|
|
hp->h_rtnrcpt = NOSTR;
|
|
hp->h_optusedmask &= ~GRR;
|
|
hp->h_seq++;
|
|
printf("Return receipt removed.\n");
|
|
}
|
|
printf("(continue)\n");
|
|
return(0);
|
|
}
|
|
|
|
/*
|
|
* Write the message on a file.
|
|
*/
|
|
putfile(ibufp, obufp, str)
|
|
FILE **ibufp, **obufp;
|
|
char *str;
|
|
{
|
|
char *cp;
|
|
extern char tempMail[];
|
|
|
|
cp = str;
|
|
while (isspace(*cp))
|
|
cp++;
|
|
if (*cp == '\0') {
|
|
fprintf(stderr, "Write what file!?\n");
|
|
return(0);
|
|
}
|
|
if ((cp = expand(cp)) == NOSTR)
|
|
return(0);
|
|
fflush(*obufp);
|
|
if (ferror(*obufp)) {
|
|
perror(tempMail);
|
|
return(0);
|
|
}
|
|
rewind(*ibufp);
|
|
exwrite(cp, *ibufp, 1);
|
|
return(0);
|
|
}
|
|
|
|
/*
|
|
* Interpolate the named messages with shift, if we
|
|
* are in receiving mail mode. Does the
|
|
* standard list processing garbage.
|
|
*/
|
|
fFgetmessage(ibufp, obufp, str, cmdfF)
|
|
FILE **ibufp, **obufp;
|
|
char *str;
|
|
char *cmdfF;
|
|
{
|
|
char *cp;
|
|
|
|
if (!rcvmode) {
|
|
printf("No messages to send from!?!\n");
|
|
return(0);
|
|
}
|
|
cp = str;
|
|
while (isspace(*cp))
|
|
cp++;
|
|
if (forward(cp, *obufp, cmdfF) < 0) {
|
|
resetsigs(*ibufp, *obufp);
|
|
return(1);
|
|
}
|
|
printf("(continue)\n");
|
|
return(0);
|
|
}
|
|
|
|
fgetmessage(ibufp, obufp, str)
|
|
FILE **ibufp, **obufp;
|
|
char *str;
|
|
{
|
|
return(fFgetmessage(ibufp, obufp, str, "f"));
|
|
}
|
|
|
|
Fgetmessage(ibufp, obufp, str)
|
|
FILE **ibufp, **obufp;
|
|
char *str;
|
|
{
|
|
return(fFgetmessage(ibufp, obufp, str, "F"));
|
|
}
|
|
|
|
/*
|
|
* Interpolate the named messages without shift, if we
|
|
* are in receiving mail mode. Does the
|
|
* standard list processing garbage.
|
|
*/
|
|
mMgetmessage(ibufp, obufp, str, cmdmM)
|
|
FILE **ibufp, **obufp;
|
|
char *str;
|
|
char *cmdmM;
|
|
{
|
|
char *cp;
|
|
|
|
if (!rcvmode) {
|
|
printf("No messages to send from!?!\n");
|
|
return(0);
|
|
}
|
|
cp = str;
|
|
while (isspace(*cp))
|
|
cp++;
|
|
if (forward(cp, *obufp, cmdmM) < 0) {
|
|
resetsigs(*ibufp, *obufp);
|
|
return(1);
|
|
}
|
|
printf("(continue)\n");
|
|
return(0);
|
|
}
|
|
|
|
Mgetmessage(ibufp, obufp, str)
|
|
FILE **ibufp, **obufp;
|
|
char *str;
|
|
{
|
|
return(mMgetmessage(ibufp, obufp, str, "M"));
|
|
}
|
|
|
|
mgetmessage(ibufp, obufp, str)
|
|
FILE **ibufp, **obufp;
|
|
char *str;
|
|
{
|
|
return(mMgetmessage(ibufp, obufp, str, "m"));
|
|
}
|
|
|
|
/*
|
|
* Print the help file.
|
|
*/
|
|
helpme()
|
|
{
|
|
register int t;
|
|
FILE *fbuf;
|
|
char *cp;
|
|
|
|
if (ismailx)
|
|
cp = TXHELPFILE;
|
|
else
|
|
cp = THELPFILE;
|
|
if ((fbuf = fopen(cp, "r")) == NULL) {
|
|
perror(cp);
|
|
return(0);
|
|
}
|
|
t = getc(fbuf);
|
|
while (t != -1) {
|
|
putchar(t);
|
|
t = getc(fbuf);
|
|
}
|
|
fclose(fbuf);
|
|
printf("(continue)\n");
|
|
return(0);
|
|
}
|
|
|
|
/*
|
|
* Print out the current state of the
|
|
* message without altering anything.
|
|
*/
|
|
printmessage(ibufp, obufp, hp)
|
|
FILE **ibufp, **obufp;
|
|
struct header *hp;
|
|
{
|
|
register int t;
|
|
extern char tempMail[];
|
|
|
|
fflush(*obufp);
|
|
if (ferror(*obufp)) {
|
|
perror(tempMail);
|
|
return(0);
|
|
}
|
|
rewind(*ibufp);
|
|
{
|
|
FILE * pbuf;
|
|
extern jmp_buf pipestop;
|
|
extern void brokpipe();
|
|
int nwcols;
|
|
char *cp;
|
|
|
|
pbuf = stdout;
|
|
if (setjmp(pipestop)) {
|
|
if (pbuf != stdout)
|
|
pclose(pbuf);
|
|
sigset(SIGPIPE, SIG_DFL);
|
|
return(0);
|
|
}
|
|
if (intty && outtty) {
|
|
nwcols = getwincols();
|
|
if (getheadlen(hp, nwcols)
|
|
+ gettextlen(*ibufp, nwcols) + 2
|
|
> getwinlines(0)) {
|
|
if (!ismailx)
|
|
cp = MORE;
|
|
else {
|
|
cp = value("PAGER");
|
|
if (cp == NULL || *cp == '\0')
|
|
cp = MORE;
|
|
}
|
|
pbuf = popen(cp, "w");
|
|
if (pbuf == NULL) {
|
|
perror(cp);
|
|
pbuf = stdout;
|
|
} else
|
|
sigset(SIGPIPE, brokpipe);
|
|
}
|
|
}
|
|
|
|
fprintf(pbuf, "-------\nMessage contains:\n");
|
|
puthead(hp, pbuf, GALLHDR|GNL);
|
|
t = getc(*ibufp);
|
|
while (t != EOF) {
|
|
putc(t, pbuf);
|
|
t = getc(*ibufp);
|
|
}
|
|
if (pbuf != stdout)
|
|
pclose(pbuf);
|
|
}
|
|
printf("(continue)\n");
|
|
return(0);
|
|
}
|
|
|
|
/*
|
|
* Pipe message through command.
|
|
* Collect output as new message.
|
|
*/
|
|
|
|
pipemessage(ibufp, obufp, str)
|
|
FILE **ibufp, **obufp;
|
|
char *str;
|
|
{
|
|
*obufp = mespipe(*ibufp, *obufp, str);
|
|
newo = *obufp;
|
|
*ibufp = newi;
|
|
newi = *ibufp;
|
|
printf("(continue)\n");
|
|
return(0);
|
|
}
|
|
|
|
/*
|
|
* Edit the current message body only using EDITOR.
|
|
*/
|
|
eeditmsgbody(ibufp, obufp, hp)
|
|
FILE **ibufp, **obufp;
|
|
{
|
|
if ((*obufp = mesedit(*ibufp, *obufp, hp, 'e', 0)) == NULL) {
|
|
resetsigs(*ibufp, *obufp);
|
|
return(1);
|
|
}
|
|
newo = *obufp;
|
|
*ibufp = newi;
|
|
printf("(continue)\n");
|
|
return(0);
|
|
}
|
|
|
|
/*
|
|
* Edit the current message body only using VISUAL.
|
|
*/
|
|
veditmsgbody(ibufp, obufp, hp)
|
|
FILE **ibufp, **obufp;
|
|
{
|
|
if ((*obufp = mesedit(*ibufp, *obufp, hp, 'v', 0)) == NULL) {
|
|
resetsigs(*ibufp, *obufp);
|
|
return(1);
|
|
}
|
|
newo = *obufp;
|
|
*ibufp = newi;
|
|
printf("(continue)\n");
|
|
return(0);
|
|
}
|
|
|
|
/*
|
|
* Edit the complete message including the headers using EDITOR.
|
|
*/
|
|
eeditmsg(ibufp, obufp, hp)
|
|
FILE **ibufp, **obufp;
|
|
struct header *hp;
|
|
{
|
|
if ((*obufp = mesedit(*ibufp, *obufp, hp, 'e', 1)) == NULL) {
|
|
resetsigs(*ibufp, *obufp);
|
|
return(1);
|
|
}
|
|
newo = *obufp;
|
|
*ibufp = newi;
|
|
printf("(continue)\n");
|
|
return(0);
|
|
}
|
|
|
|
/*
|
|
* Edit the complete message including the headers using VISUAL.
|
|
*/
|
|
veditmsg(ibufp, obufp, hp)
|
|
FILE **ibufp, **obufp;
|
|
struct header *hp;
|
|
{
|
|
if ((*obufp = mesedit(*ibufp, *obufp, hp, 'v', 1)) == NULL) {
|
|
resetsigs(*ibufp, *obufp);
|
|
return(1);
|
|
}
|
|
newo = *obufp;
|
|
*ibufp = newi;
|
|
printf("(continue)\n");
|
|
return(0);
|
|
}
|
|
|
|
/*
|
|
* Set the Encrypt field.
|
|
*/
|
|
setencrypt(hp, str)
|
|
struct header *hp;
|
|
char *str;
|
|
{
|
|
while (isspace(*str))
|
|
str++;
|
|
if (*str != '\0')
|
|
hp->h_optusedmask |= GEN;
|
|
else
|
|
hp->h_optusedmask &= ~GEN;
|
|
hp->h_encrypt = savestr(str);
|
|
hp->h_seq++;
|
|
return(0);
|
|
}
|
|
|
|
notempty(str)
|
|
char *str;
|
|
{
|
|
while(isspace(*str))
|
|
str++;
|
|
return(*str != '\0');
|
|
}
|
|
|
|
/*
|
|
* Write a file, ex-like if f set.
|
|
*/
|
|
|
|
exwrite(name, ibuf, f)
|
|
char name[];
|
|
FILE *ibuf;
|
|
{
|
|
register FILE *of;
|
|
register int c;
|
|
long cc;
|
|
int lc;
|
|
char *type;
|
|
struct stat junk;
|
|
|
|
if (f) {
|
|
printf("\"%s\" ", name);
|
|
fflush(stdout);
|
|
}
|
|
type = "w";
|
|
if (stat(name, &junk) >= 0 && (junk.st_mode & S_IFMT) == S_IFREG) {
|
|
if (!ismailx) {
|
|
/*
|
|
* The file exists and we are running 'Mail'. So,
|
|
* to preserve backward compatibilty we will now
|
|
* error terminate.
|
|
*/
|
|
if (!f)
|
|
fprintf(stderr, "%s: ", name);
|
|
fprintf(stderr, "File exists\n");
|
|
return(-1);
|
|
}
|
|
/*
|
|
* The file exists and we are running 'mailx'. So, the
|
|
* spec says that if the file exists, then we should append
|
|
* this message to the existing file.
|
|
*/
|
|
type = "a+";
|
|
}
|
|
if ((of = fopen(name, type)) == NULL) {
|
|
perror("");
|
|
return(-1);
|
|
}
|
|
lc = 0;
|
|
cc = 0;
|
|
while ((c = getc(ibuf)) != EOF) {
|
|
cc++;
|
|
if (c == '\n')
|
|
lc++;
|
|
putc(c, of);
|
|
if (ferror(of)) {
|
|
perror(name);
|
|
fclose(of);
|
|
return(-1);
|
|
}
|
|
}
|
|
fclose(of);
|
|
printf("%d/%ld\n", lc, cc);
|
|
fflush(stdout);
|
|
return(0);
|
|
}
|
|
|
|
/*
|
|
* Edit the message being collected on ibuf and obuf.
|
|
* Write the message out onto some poorly-named temp file
|
|
* and point an editor at it.
|
|
*
|
|
* On return, make the edit file the new temp file.
|
|
*/
|
|
|
|
FILE *
|
|
mesedit(ibuf, obuf, hp, cmd, dohdr)
|
|
FILE *ibuf, *obuf;
|
|
struct header *hp;
|
|
int cmd, dohdr;
|
|
{
|
|
int pid, s;
|
|
FILE *fbuf;
|
|
register int t;
|
|
#if defined(SVR3) || defined(_SVR4_SOURCE)
|
|
void (*sig)(), (*scont)(), signull();
|
|
#else
|
|
int (*sig)(), (*scont)(), signull();
|
|
#endif
|
|
struct stat sbuf;
|
|
extern char tempEdit[], tempMail[];
|
|
register char *edit;
|
|
char *Shell;
|
|
|
|
sig = sigset(SIGINT, SIG_IGN);
|
|
#ifdef VMUNIX
|
|
scont = sigset(SIGCONT, signull);
|
|
#endif /* VMUNIX */
|
|
|
|
/* create a temp file */
|
|
if (stat(tempEdit, &sbuf) >= 0) {
|
|
printf("%s: file exists\n", tempEdit);
|
|
goto out;
|
|
}
|
|
close(creat(tempEdit, 0600));
|
|
if ((fbuf = fopen(tempEdit, "w")) == NULL) {
|
|
perror(tempEdit);
|
|
goto out;
|
|
}
|
|
|
|
if (dohdr) {
|
|
if ((hp->h_subject == NOSTR) && sflag)
|
|
hp->h_subject = sflag;
|
|
/* write all current headers into the temp file */
|
|
puthead(hp, fbuf, GSUBJECT|GALLHDR|GSEP);
|
|
}
|
|
|
|
/* write out the message body collected so far */
|
|
fflush(obuf);
|
|
if (ferror(obuf)) {
|
|
perror(tempMail);
|
|
fclose(fbuf);
|
|
m_remove(tempEdit);
|
|
goto out;
|
|
}
|
|
rewind(ibuf);
|
|
t = getc(ibuf);
|
|
while (t != EOF) {
|
|
putc(t, fbuf);
|
|
t = getc(ibuf);
|
|
}
|
|
fflush(fbuf);
|
|
if (ferror(fbuf)) {
|
|
perror(tempEdit);
|
|
m_remove(tempEdit);
|
|
goto fix;
|
|
}
|
|
fclose(fbuf);
|
|
|
|
/* fork an editor on the message */
|
|
if (((edit = value(cmd == 'e' ? "EDITOR" : "VISUAL")) == NOSTR) ||
|
|
*edit == 0)
|
|
{
|
|
edit = cmd == 'e' ? EDITOR : VISUAL;
|
|
}
|
|
if (*edit != '/')
|
|
edit = cmd == 'e' ? EDITOR : VISUAL;
|
|
|
|
pid = fork();
|
|
if (pid == 0) {
|
|
/* CHILD - exec the editor. */
|
|
sigchild();
|
|
if (sig != SIG_IGN)
|
|
sigsys(SIGINT, SIG_DFL);
|
|
execl(edit, edit, tempEdit, 0);
|
|
if (!ismailx) {
|
|
perror(edit);
|
|
_exit(1);
|
|
} else {
|
|
if (errno == ENOEXEC) {
|
|
/* CHILD - exec the editor. */
|
|
sigchild();
|
|
if (sig != SIG_IGN)
|
|
sigsys(SIGINT, SIG_DFL);
|
|
Shell = SHELL_XPG4;
|
|
execl(Shell, Shell, "-c", edit, 0);
|
|
perror(edit);
|
|
_exit(1);
|
|
}
|
|
}
|
|
}
|
|
if (pid == -1) {
|
|
/* ERROR - issue warning and get out. */
|
|
perror("fork");
|
|
m_remove(tempEdit);
|
|
goto out;
|
|
}
|
|
/* PARENT - wait for the child (editor) to complete. */
|
|
while (wait(&s) != pid)
|
|
;
|
|
|
|
/* Check the results. */
|
|
if ((s & 0377) != 0) {
|
|
printf("Fatal error in \"%s\"\n", edit);
|
|
m_remove(tempEdit);
|
|
goto out;
|
|
}
|
|
|
|
/* If necessary, extract the headers from the resulting file. */
|
|
if (dohdr && extracthead(hp, tempEdit) < 0) {
|
|
perror(tempEdit);
|
|
m_remove(tempEdit);
|
|
goto out;
|
|
}
|
|
|
|
/* Switch files */
|
|
if ((fbuf = fopen(tempEdit, "a")) == NULL) {
|
|
perror(tempEdit);
|
|
m_remove(tempEdit);
|
|
goto out;
|
|
}
|
|
if ((ibuf = fopen(tempEdit, "r")) == NULL) {
|
|
perror(tempEdit);
|
|
fclose(fbuf);
|
|
m_remove(tempEdit);
|
|
goto out;
|
|
}
|
|
m_remove(tempEdit);
|
|
fclose(obuf);
|
|
fclose(newi);
|
|
obuf = fbuf;
|
|
goto out;
|
|
fix:
|
|
perror(tempEdit);
|
|
out:
|
|
#ifdef VMUNIX
|
|
sigset(SIGCONT, scont);
|
|
#endif /* VMUNIX */
|
|
sigset(SIGINT, sig);
|
|
newi = ibuf;
|
|
return(obuf);
|
|
}
|
|
|
|
/*
|
|
* Pipe the message through the command.
|
|
* Old message is on stdin of command;
|
|
* New message collected from stdout.
|
|
* Sh -c must return 0 to accept the new message.
|
|
*/
|
|
|
|
FILE *
|
|
mespipe(ibuf, obuf, cmd)
|
|
FILE *ibuf, *obuf;
|
|
char cmd[];
|
|
{
|
|
register FILE *ni, *no;
|
|
int pid, s;
|
|
#if defined(SVR3) || defined(_SVR4_SOURCE)
|
|
void (*savesig)();
|
|
#else
|
|
int (*savesig)();
|
|
#endif
|
|
char *Shell;
|
|
extern char tempEdit[], tempMail[];
|
|
|
|
newi = ibuf;
|
|
if ((no = fopen(tempEdit, "w")) == NULL) {
|
|
perror(tempEdit);
|
|
return(obuf);
|
|
}
|
|
if ((ni = fopen(tempEdit, "r")) == NULL) {
|
|
perror(tempEdit);
|
|
fclose(no);
|
|
m_remove(tempEdit);
|
|
return(obuf);
|
|
}
|
|
m_remove(tempEdit);
|
|
savesig = sigset(SIGINT, SIG_IGN);
|
|
fflush(obuf);
|
|
if (ferror(obuf)) {
|
|
perror(tempMail);
|
|
fclose(ni);
|
|
fclose(no);
|
|
m_remove(tempEdit);
|
|
return(obuf);
|
|
}
|
|
rewind(ibuf);
|
|
if (((Shell = value("SHELL")) == NULL) || (Shell[0] == '\0'))
|
|
Shell = "/bin/sh";
|
|
if ((pid = fork()) == -1) {
|
|
perror("fork");
|
|
goto err;
|
|
}
|
|
if (pid == 0) {
|
|
/*
|
|
* stdin = current message.
|
|
* stdout = new message.
|
|
*/
|
|
sigchild();
|
|
close(0);
|
|
dup(fileno(ibuf));
|
|
close(1);
|
|
dup(fileno(no));
|
|
for (s = 4; s < 15; s++)
|
|
close(s);
|
|
execl(Shell, Shell, "-c", cmd, 0);
|
|
perror(Shell);
|
|
_exit(1);
|
|
}
|
|
while (wait(&s) != pid)
|
|
;
|
|
if (s != 0 || pid == -1) {
|
|
fprintf(stderr, "\"%s\" failed!?\n", cmd);
|
|
goto err;
|
|
}
|
|
if (fsize(ni) == 0) {
|
|
fprintf(stderr, "No bytes from \"%s\" !?\n", cmd);
|
|
goto err;
|
|
}
|
|
|
|
/*
|
|
* Take new files.
|
|
*/
|
|
|
|
newi = ni;
|
|
fclose(ibuf);
|
|
fclose(obuf);
|
|
sigset(SIGINT, savesig);
|
|
return(no);
|
|
|
|
err:
|
|
fclose(no);
|
|
fclose(ni);
|
|
sigset(SIGINT, savesig);
|
|
return(obuf);
|
|
}
|
|
|
|
/*
|
|
* Interpolate the named messages into the current
|
|
* message, preceding each line with a tab or user-defined
|
|
* string.
|
|
*
|
|
* Return a count of the number of characters now in
|
|
* the message, or -1 if an error is encountered writing
|
|
* the message temporary. The flag argument is 'm' if we
|
|
* should shift over and 'f' if not.
|
|
*/
|
|
forward(ms, obuf, f)
|
|
char ms[];
|
|
FILE *obuf;
|
|
char *f;
|
|
{
|
|
register int *msgvec, *ip;
|
|
int lcnt;
|
|
long ccnt;
|
|
extern char tempMail[];
|
|
int suppresstype;
|
|
|
|
msgvec = (int *) salloc((msgCount+1) * sizeof *msgvec);
|
|
if (msgvec == (int *) NOSTR)
|
|
return(0);
|
|
if (getmsglist(ms, msgvec, 0) < 0)
|
|
return(0);
|
|
if (*msgvec == NULL) {
|
|
*msgvec = first(0, MMNORM);
|
|
if (*msgvec == NULL) {
|
|
printf("No appropriate messages\n");
|
|
return(0);
|
|
}
|
|
msgvec[1] = NULL;
|
|
}
|
|
printf("Interpolating:");
|
|
for (ip = msgvec; *ip != NULL; ip++) {
|
|
touch(*ip);
|
|
printf(" %d", *ip);
|
|
if (!ismailx) {
|
|
if (*f == 'm') {
|
|
if (transmit(&message[*ip-1], obuf) < 0L) {
|
|
perror(tempMail);
|
|
return(-1);
|
|
}
|
|
} else
|
|
if (send_msg(&message[*ip-1], obuf,
|
|
NO_SUPPRESS, &lcnt, &ccnt, 0) < 0)
|
|
{
|
|
perror(tempMail);
|
|
return(-1);
|
|
}
|
|
} else {
|
|
if ((*f == 'm') || (*f == 'f'))
|
|
suppresstype = SUPPRESS_IGN;
|
|
else
|
|
suppresstype = NO_SUPPRESS;
|
|
|
|
if (send_msg(&message[*ip-1], obuf,
|
|
suppresstype, &lcnt, &ccnt, f) < 0) {
|
|
perror(tempMail);
|
|
return(-1);
|
|
}
|
|
}
|
|
}
|
|
printf("\n");
|
|
return(0);
|
|
}
|
|
|
|
/*
|
|
* Send message described by the passed pointer to the
|
|
* passed output buffer. Insert a tab or user-defined
|
|
* character in front of each line. Return a count of
|
|
* the characters sent, or -1 on error.
|
|
*/
|
|
|
|
long
|
|
transmit(mailp, obuf)
|
|
struct message *mailp;
|
|
FILE *obuf;
|
|
{
|
|
register struct message *mp;
|
|
register int ch;
|
|
char *istr;
|
|
u_long c, n;
|
|
int bol;
|
|
FILE *ibuf;
|
|
|
|
if (ismailx) {
|
|
if ((istr = value("indentprefix")) == NOSTR)
|
|
istr = "\t";
|
|
} else {
|
|
if ((istr = value("mprefix")) == NOSTR)
|
|
istr = "\t";
|
|
}
|
|
mp = mailp;
|
|
ibuf = setinput(mp);
|
|
c = mp->m_size;
|
|
n = c;
|
|
bol = 1;
|
|
while (c-- > 0L) {
|
|
if (bol) {
|
|
bol = 0;
|
|
fprintf(obuf, "%s", istr);
|
|
n++;
|
|
if (ferror(obuf)) {
|
|
perror("transmit");
|
|
return(-1L);
|
|
}
|
|
}
|
|
ch = getc(ibuf);
|
|
if (ch == '\n')
|
|
bol++;
|
|
putc(ch, obuf);
|
|
if (ferror(obuf)) {
|
|
perror("transmit");
|
|
return(-1L);
|
|
}
|
|
}
|
|
return(n);
|
|
}
|
|
|
|
/*
|
|
* Print (continue) when continued after ^Z.
|
|
*/
|
|
void
|
|
collcont(s)
|
|
{
|
|
|
|
printf("(continue)\n");
|
|
fflush(stdout);
|
|
}
|
|
|
|
/*
|
|
* On interrupt, go here to save the partial
|
|
* message on ~/dead.letter.
|
|
* Then restore signals and execute the normal
|
|
* signal routine. We only come here if signals
|
|
* were previously set anyway.
|
|
*/
|
|
|
|
#ifndef VMUNIX
|
|
void
|
|
collintsig()
|
|
{
|
|
signal(SIGINT, SIG_IGN);
|
|
collrub(SIGINT);
|
|
}
|
|
|
|
void
|
|
collhupsig()
|
|
{
|
|
signal(SIGHUP, SIG_IGN);
|
|
collrub(SIGHUP);
|
|
}
|
|
#endif /* !VMUNIX */
|
|
|
|
void
|
|
collrub(s)
|
|
{
|
|
register FILE *dbuf;
|
|
register int c;
|
|
|
|
if (s == SIGINT && hadintr == 0) {
|
|
hadintr++;
|
|
fflush(stdout);
|
|
fprintf(stderr, "\n(Interrupt -- one more to kill letter)\n");
|
|
longjmp(coljmp, 1);
|
|
}
|
|
fclose(newo);
|
|
rewind(newi);
|
|
if (s == SIGINT && value("nosave") != NOSTR || fsize(newi) == 0)
|
|
goto done;
|
|
if ((dbuf = fopen(deadletter, "w")) == NULL)
|
|
goto done;
|
|
chmod(deadletter, 0600);
|
|
while ((c = getc(newi)) != EOF)
|
|
putc(c, dbuf);
|
|
fclose(dbuf);
|
|
|
|
done:
|
|
fclose(newi);
|
|
sigset(SIGINT, savesig);
|
|
sigset(SIGHUP, savehup);
|
|
#ifdef VMUNIX
|
|
sigset(SIGCONT, savecont);
|
|
#endif /* VMUNIX */
|
|
if (rcvmode) {
|
|
if (s == SIGHUP)
|
|
hangup(SIGHUP);
|
|
else
|
|
stop(s);
|
|
}
|
|
else
|
|
safe_exit(1);
|
|
}
|
|
|
|
/*
|
|
* Acknowledge an interrupt signal from the tty by typing an @
|
|
*/
|
|
|
|
void
|
|
intack(s)
|
|
{
|
|
|
|
puts("@");
|
|
fflush(stdout);
|
|
clearerr(stdin);
|
|
|
|
if (hf)
|
|
longjmp(coljmp, 1);
|
|
}
|
|
|
|
/*
|
|
* Add a string to the end of a header entry field.
|
|
*/
|
|
|
|
char *
|
|
addto(hf, news)
|
|
char hf[], news[];
|
|
{
|
|
register char *cp, *cp2, *linebuf;
|
|
|
|
for (cp = news; isspace(*cp); cp++)
|
|
;
|
|
if (*cp == '\0')
|
|
return(hf);
|
|
if (hf == NOSTR)
|
|
hf = cp = "";
|
|
linebuf = salloc(strlen(hf) + strlen(news) + 2);
|
|
cp2 = linebuf;
|
|
*cp2 = '\0';
|
|
if (hf != cp) {
|
|
for (cp = hf; isspace(*cp); cp++)
|
|
;
|
|
for (cp2 = linebuf; *cp;)
|
|
*cp2++ = *cp++;
|
|
}
|
|
for (cp = news; isspace(*cp); cp++)
|
|
;
|
|
if ((cp2 != linebuf) && (*cp != '\0'))
|
|
*cp2++ = ',';
|
|
while (*cp != '\0') {
|
|
if (isspace(*cp)) {
|
|
for (; isspace(*cp); cp++);
|
|
*cp2++ = ',';
|
|
}
|
|
*cp2++ = *cp++;
|
|
}
|
|
*cp2 = '\0';
|
|
return(linebuf);
|
|
}
|