#include "rcv.h"
#include <locale.h>
#ifdef SIGCONT
static void collcont(int);
#endif
static void collrub(int s);
static void cpout(char *str, FILE *ofd);
static int exwrite(char name[], FILE *ibuf);
static int forward(char ms[], FILE *obuf, int f);
static void intack(int);
static int forward(char ms[], FILE *obuf, int f);
static FILE *mesedit(FILE *ibuf, FILE *obuf, int c, struct header *hp);
static FILE *mespipe(FILE *ibuf, FILE *obuf, char cmd[]);
static void resetsigs(int resethup);
static int stripnulls(char *linebuf, int nread);
static void xhalt(void);
static char **Xaddone(char **hf, char news[]);
static int tabputs(const char *line, FILE *obuf);
static void (*savesig)(int);
static void (*savehup)(int);
#ifdef SIGCONT
static void (*savecont)(int);
#endif
static FILE *newi;
static FILE *newo;
static int ignintr;
static int hadintr;
static struct header *savehp;
static jmp_buf coljmp;
FILE *
collect(struct header *hp)
{
FILE *ibuf, *fbuf, *obuf;
int escape, eof;
long lc, cc;
int c, t;
int hdrs;
char linebuf[LINESIZE+1], *cp;
char *iprompt;
int inhead;
void (*sigpipe)(int), (*sigint)(int);
int fd = -1;
noreset++;
ibuf = obuf = NULL;
newi = newo = NULL;
if ((fd = open(tempMail, O_RDWR|O_CREAT|O_EXCL, 0600)) < 0 ||
(obuf = fdopen(fd, "w")) == NULL) {
perror(tempMail);
goto err;
}
newo = obuf;
if ((ibuf = fopen(tempMail, "r")) == NULL) {
perror(tempMail);
newo = NULL;
fclose(obuf);
goto err;
}
newi = ibuf;
removefile(tempMail);
ignintr = (int)value("ignore");
hadintr = 1;
inhead = 1;
savehp = hp;
# ifdef VMUNIX
if ((savesig = sigset(SIGINT, SIG_IGN)) != SIG_IGN)
sigset(SIGINT, ignintr ? intack : collrub), sigblock(sigmask(SIGINT));
if ((savehup = sigset(SIGHUP, SIG_IGN)) != SIG_IGN)
sigset(SIGHUP, collrub), sigblock(sigmask(SIGHUP));
# else
# ifdef OLD_BSD_SIGS
if ((savesig = sigset(SIGINT, SIG_IGN)) != SIG_IGN)
sigset(SIGINT, ignintr ? intack : collrub);
if ((savehup = sigset(SIGHUP, SIG_IGN)) != SIG_IGN)
sigset(SIGHUP, collrub);
# else
if ((savesig = sigset(SIGINT, SIG_IGN)) != SIG_IGN) {
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, SIGINT);
sigset(SIGINT, ignintr ? intack : collrub);
sigprocmask(SIG_BLOCK, &mask, NULL);
}
if ((savehup = sigset(SIGHUP, SIG_IGN)) != SIG_IGN) {
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, SIGHUP);
sigset(SIGHUP, collrub);
sigprocmask(SIG_BLOCK, &mask, NULL);
}
# endif
# endif
#ifdef SIGCONT
savecont = sigset(SIGCONT, collcont);
#endif
if (hp->h_subject == NOSTR) {
hp->h_subject = sflag;
sflag = NOSTR;
}
if (hp->h_cc == NOSTR) {
hp->h_cc = cflag;
cflag = NOSTR;
}
if (hp->h_bcc == NOSTR) {
hp->h_bcc = bflag;
bflag = NOSTR;
}
t = GMASK;
hdrs = 0;
if (intty && !tflag) {
if (hp->h_to == NOSTR)
hdrs |= GTO;
if (hp->h_subject == NOSTR && value("asksub"))
hdrs |= GSUBJECT;
if (hp->h_cc == NOSTR && value("askcc"))
hdrs |= GCC;
if (hp->h_bcc == NOSTR && value("askbcc"))
hdrs |= GBCC;
if (hdrs)
t &= ~GNL;
}
if (hp->h_seq != 0) {
puthead(hp, stdout, t, 0);
fflush(stdout);
}
if (setjmp(coljmp))
goto err;
escape = SENDESC;
if ((cp = value("escape")) != NOSTR)
escape = *cp;
eof = 0;
if ((cp = value("MAILX_HEAD")) != NOSTR) {
cpout( cp, obuf);
if (isatty(fileno(stdin)))
cpout( cp, stdout);
}
iprompt = value("iprompt");
fflush(obuf);
hadintr = 0;
for (;;) {
int nread, hasnulls;
# ifdef VMUNIX
int omask = sigblock(0) &~ (sigmask(SIGINT)|sigmask(SIGHUP));
# else
# ifndef OLD_BSD_SIGS
sigset_t omask;
sigprocmask(0, NULL, &omask);
sigdelset(&omask, SIGINT);
sigdelset(&omask, SIGHUP);
# endif
# endif
setjmp(coljmp);
# ifdef VMUNIX
sigsetmask(omask);
# else
# ifdef OLD_BSD_SIGS
sigrelse(SIGINT);
sigrelse(SIGHUP);
# else
sigprocmask(SIG_SETMASK, &omask, NULL);
# endif
# endif
if (intty && !tflag && outtty && iprompt)
fputs(iprompt, stdout);
flush();
if (hdrs) {
grabh(hp, hdrs, 1);
hdrs = 0;
continue;
}
if ((nread = getaline(linebuf,LINESIZE,stdin,&hasnulls)) == 0) {
if (intty && value("ignoreeof") != NOSTR) {
if (++eof > 35)
break;
printf(gettext(
"Use \".\" to terminate letter\n"));
continue;
}
break;
}
eof = 0;
hadintr = 0;
if (intty && equal(".\n", linebuf) &&
(value("dot") != NOSTR || value("ignoreeof") != NOSTR))
break;
if (tflag) {
char *cp2;
if (!inhead) {
writeit:
if (write(fileno(obuf),linebuf,nread) != nread)
goto werr;
continue;
}
if (linebuf[0] == '\n') {
inhead = 0;
continue;
}
if (!headerp(linebuf)) {
inhead = 0;
goto writeit;
}
if (hasnulls)
nread = stripnulls(linebuf, nread);
for (;;) {
char line2[LINESIZE];
c = getc(stdin);
ungetc(c, stdin);
if (!isspace(c) || c == '\n')
break;
if (readline(stdin, line2) < 0)
break;
for (cp2 = line2; *cp2 != 0 && isspace(*cp2);
cp2++)
;
if (strlen(linebuf) + strlen(cp2) >=
(unsigned)LINESIZE-2)
break;
cp = &linebuf[strlen(linebuf)];
while (cp > linebuf &&
(isspace(cp[-1]) || cp[-1] == '\\'))
cp--;
*cp++ = ' ';
strcpy(cp, cp2);
}
if ((c = strlen(linebuf)) > 0) {
cp = &linebuf[c-1];
while (cp > linebuf && isspace(*cp))
cp--;
*++cp = 0;
}
if (ishfield(linebuf, "to"))
hp->h_to = addto(hp->h_to, hcontents(linebuf));
else if (ishfield(linebuf, "subject"))
hp->h_subject =
addone(hp->h_subject, hcontents(linebuf));
else if (ishfield(linebuf, "cc"))
hp->h_cc = addto(hp->h_cc, hcontents(linebuf));
else if (ishfield(linebuf, "bcc"))
hp->h_bcc =
addto(hp->h_bcc, hcontents(linebuf));
else if (ishfield(linebuf, "default-options"))
hp->h_defopt =
addone(hp->h_defopt, hcontents(linebuf));
else
hp->h_others = Xaddone(hp->h_others, linebuf);
hp->h_seq++;
continue;
}
if ((linebuf[0] != escape) || (rflag != NOSTR) ||
(!intty && !(int)value("escapeok"))) {
if (write(fileno(obuf),linebuf,nread) != nread)
goto werr;
continue;
}
if ((nread > 1) && (linebuf[1] == escape)) {
if (write(fileno(obuf),linebuf+1,nread-1) != (nread-1))
goto werr;
continue;
}
if (hasnulls)
nread = stripnulls(linebuf, nread);
c = linebuf[1];
linebuf[nread - 1] = '\0';
switch (c) {
default:
printf(gettext("Unknown tilde escape.\n"));
break;
case 'a':
case 'A':
if (cp = value(c=='a' ? "sign":"Sign")) {
if (*cp)
cpout( cp, obuf);
if (isatty(fileno(stdin))) {
if (*cp)
cpout( cp, stdout);
}
}
break;
case 'i':
for (cp = &linebuf[2]; any(*cp, " \t"); cp++)
;
if (*cp)
cp = value(cp);
if (cp != NOSTR) {
if (*cp)
cpout(cp, obuf);
if (isatty(fileno(stdout))) {
if (*cp)
cpout(cp, stdout);
}
}
break;
case '!':
shell(&linebuf[2]);
break;
case ':':
case '_':
execute(&linebuf[2], 1);
iprompt = value("iprompt");
if (cp = value("escape"))
escape = *cp;
printf(gettext("(continue)\n"));
break;
case '.':
goto eofl;
case 'q':
case 'Q':
hadintr++;
collrub(SIGINT);
exit(1);
case 'x':
xhalt();
break;
case 'h':
if (!intty || !outtty) {
printf(gettext("~h: no can do!?\n"));
break;
}
grabh(hp, GMASK, (int)value("bsdcompat"));
printf(gettext("(continue)\n"));
break;
case 't':
hp->h_to = addto(hp->h_to, &linebuf[2]);
hp->h_seq++;
break;
case 's':
cp = &linebuf[2];
while (any(*cp, " \t"))
cp++;
hp->h_subject = savestr(cp);
hp->h_seq++;
break;
case 'c':
hp->h_cc = addto(hp->h_cc, &linebuf[2]);
hp->h_seq++;
break;
case 'b':
hp->h_bcc = addto(hp->h_bcc, &linebuf[2]);
hp->h_seq++;
break;
case 'R':
hp->h_defopt = addone(hp->h_defopt, myname);
hp->h_seq++;
fprintf(stderr, gettext("Return receipt marked.\n"));
receipt_flg = 1;
break;
case 'd':
copy(Getf("DEAD"), &linebuf[2]);
case '<':
case 'r': {
int ispip;
cp = &linebuf[2];
while (any(*cp, " \t"))
cp++;
if (*cp == '\0') {
printf(gettext("Interpolate what file?\n"));
break;
}
if (*cp=='!') {
ispip = 1;
if ((fbuf = npopen(++cp, "r"))==NULL) {
perror("");
break;
}
sigint = sigset(SIGINT, SIG_IGN);
} else {
ispip = 0;
cp = expand(cp);
if (cp == NOSTR)
break;
if (isdir(cp)) {
printf(gettext("%s: directory\n"), cp);
break;
}
if ((fbuf = fopen(cp, "r")) == NULL) {
perror(cp);
break;
}
}
printf("\"%s\" ", cp);
flush();
lc = cc = 0;
while ((t = getc(fbuf)) != EOF) {
if (t == '\n')
lc++;
if (putc(t, obuf) == EOF) {
if (ispip) {
npclose(fbuf);
sigset(SIGINT, sigint);
} else
fclose(fbuf);
goto werr;
}
cc++;
}
if (ispip) {
npclose(fbuf);
sigset(SIGINT, sigint);
} else
fclose(fbuf);
printf("%ld/%ld\n", lc, cc);
fflush(obuf);
break;
}
case 'w':
cp = &linebuf[2];
while (any(*cp, " \t"))
cp++;
if (*cp == '\0') {
fprintf(stderr, gettext("Write what file!?\n"));
break;
}
if ((cp = expand(cp)) == NOSTR)
break;
fflush(obuf);
rewind(ibuf);
exwrite(cp, ibuf);
break;
case 'm':
case 'M':
case 'f':
case 'F':
if (!rcvmode) {
printf(gettext(
"No messages to send from!?!\n"));
break;
}
cp = &linebuf[2];
while (any(*cp, " \t"))
cp++;
if (forward(cp, obuf, c) < 0)
goto werr;
fflush(obuf);
printf(gettext("(continue)\n"));
break;
case '?':
if ((fbuf = fopen(THELPFILE, "r")) == NULL) {
printf(gettext("No help just now.\n"));
break;
}
t = getc(fbuf);
while (t != -1) {
putchar(t);
t = getc(fbuf);
}
fclose(fbuf);
break;
case 'p': {
int nlines;
extern jmp_buf pipestop;
extern void brokpipe(int);
fflush(obuf);
rewind(ibuf);
fbuf = stdout;
if (setjmp(pipestop))
goto ret0;
if (intty && outtty && (cp = value("crt")) != NOSTR) {
nlines =
(*cp == '\0' ? screensize() : atoi(cp)) - 7;
while ((t = getc(ibuf)) != EOF) {
if (t == '\n')
if (--nlines <= 0)
break;
}
rewind(ibuf);
if (nlines <= 0) {
fbuf = npopen(MORE, "w");
if (fbuf == NULL) {
perror(MORE);
fbuf = stdout;
} else {
sigint = sigset(SIGINT, SIG_IGN);
sigpipe = sigset(SIGPIPE, brokpipe);
}
}
}
fprintf(fbuf, gettext("-------\nMessage contains:\n"));
puthead(hp, fbuf, GMASK, 0);
while ((t = getc(ibuf))!=EOF)
putc(t, fbuf);
ret0:
if (fbuf != stdout) {
npclose(fbuf);
sigset(SIGPIPE, sigpipe);
sigset(SIGINT, sigint);
}
printf(gettext("(continue)\n"));
break;
}
case '^':
case '|':
obuf = mespipe(ibuf, obuf, &linebuf[2]);
newo = obuf;
ibuf = newi;
newi = ibuf;
printf(gettext("(continue)\n"));
break;
case 'v':
case 'e':
if ((obuf = mesedit(ibuf, obuf, c, hp)) == NULL)
goto err;
newo = obuf;
ibuf = newi;
printf(gettext("(continue)\n"));
break;
}
fflush(obuf);
}
eofl:
fflush(obuf);
if ((cp = value("MAILX_TAIL")) != NOSTR) {
cpout( cp, obuf);
if (isatty(fileno(stdin)))
cpout( cp, stdout);
}
fclose(obuf);
rewind(ibuf);
resetsigs(0);
noreset = 0;
return(ibuf);
werr:
perror(tempMail);
fflush(obuf);
rewind(ibuf);
if (fsize(ibuf) > 0) {
char *deadletter;
deadletter = Getf("DEAD");
fprintf(stderr, gettext("Saving partial message in %s\n"),
deadletter);
if ((fbuf = fopen(deadletter,
value("appenddeadletter") == NOSTR ? "w" : "a")) != NULL) {
chmod(deadletter, DEADPERM);
puthead(hp, fbuf, GMASK|GCLEN, fsize(ibuf));
lcwrite(deadletter, ibuf, fbuf, value("appenddeadletter") != NOSTR);
fclose(fbuf);
} else
perror(deadletter);
}
err:
if (ibuf != NULL)
fclose(ibuf);
if (obuf != NULL)
fclose(obuf);
resetsigs(0);
noreset = 0;
return(NULL);
}
static void
resetsigs(int resethup)
{
(void) sigset(SIGINT, savesig);
if (resethup)
(void) sigset(SIGHUP, savehup);
#ifdef SIGCONT
# ifdef preSVr4
(void) sigset(SIGCONT, savecont);
# else
{
struct sigaction nsig;
nsig.sa_handler = (void (*)())savecont;
sigemptyset(&nsig.sa_mask);
nsig.sa_flags = SA_RESTART;
(void) sigaction(SIGCONT, &nsig, (struct sigaction*)0);
}
# endif
#endif
}
static int
exwrite(char name[], FILE *ibuf)
{
FILE *of;
struct stat junk;
void (*sigint)(int), (*sigpipe)(int);
int pi = (*name == '!');
if ((of = pi ? npopen(++name, "w") : fopen(name, "a")) == NULL) {
perror(name);
return(-1);
}
if (pi) {
sigint = sigset(SIGINT, SIG_IGN);
sigpipe = sigset(SIGPIPE, SIG_IGN);
}
lcwrite(name, ibuf, of, 0);
pi ? npclose(of) : fclose(of);
if (pi) {
sigset(SIGPIPE, sigpipe);
sigset(SIGINT, sigint);
}
return(0);
}
void
lcwrite(char *fn, FILE *fi, FILE *fo, int addnl)
{
int c;
long lc, cc;
printf("\"%s\" ", fn);
fflush(stdout);
lc = cc = 0;
while ((c = getc(fi)) != EOF) {
cc++;
if (putc(c, fo) == '\n')
lc++;
if (ferror(fo)) {
perror("");
return;
}
}
if (addnl) {
putc('\n', fo);
lc++;
cc++;
}
fflush(fo);
if (fferror(fo)) {
perror("");
return;
}
printf("%ld/%ld\n", lc, cc);
fflush(stdout);
}
static FILE *
mesedit(FILE *ibuf, FILE *obuf, int c, struct header *hp)
{
pid_t pid;
FILE *fbuf;
int t;
void (*sigint)(int);
#ifdef SIGCONT
void (*sigcont)(int);
#endif
struct stat sbuf;
char *edit;
char hdr[LINESIZE];
char *oto, *osubject, *occ, *obcc, **oothers;
int fd = -1;
if (stat(tempEdit, &sbuf) >= 0) {
printf(gettext("%s: file exists\n"), tempEdit);
goto out;
}
if ((fd = open(tempEdit, O_RDWR|O_CREAT|O_EXCL, 0600)) < 0 ||
(fbuf = fdopen(fd, "w")) == NULL) {
perror(tempEdit);
goto out;
}
fflush(obuf);
rewind(ibuf);
puthead(hp, fbuf, GMASK, 0);
while ((t = getc(ibuf)) != EOF)
putc(t, fbuf);
fflush(fbuf);
if (fferror(fbuf)) {
perror(tempEdit);
removefile(tempEdit);
goto out;
}
fclose(fbuf);
if ((edit = value(c == 'e' ? "EDITOR" : "VISUAL")) == NOSTR ||
*edit == '\0')
edit = c == 'e' ? EDITOR : VISUAL;
edit = safeexpand(edit);
pid = vfork();
if (pid == (pid_t)-1) {
perror("fork");
removefile(tempEdit);
goto out;
}
if (pid == 0) {
char ecmd[BUFSIZ];
char *Shell;
sigchild();
execlp(edit, edit, tempEdit, (char *)0);
snprintf(ecmd, sizeof (ecmd), "exec %s %s", edit, tempEdit);
if ((Shell = value("SHELL")) == NULL || *Shell=='\0')
Shell = SHELL;
execlp(Shell, Shell, "-c", ecmd, NULL);
perror(edit);
_exit(1);
}
sigint = sigset(SIGINT, SIG_IGN);
#ifdef SIGCONT
sigcont = sigset(SIGCONT, SIG_DFL);
#endif
while (wait((int *)0) != pid)
;
sigset(SIGINT, sigint);
#ifdef SIGCONT
sigset(SIGCONT, sigcont);
#endif
if ((fbuf = fopen(tempEdit, "r")) == NULL) {
perror(tempEdit);
removefile(tempEdit);
goto out;
}
removefile(tempEdit);
osubject = hp->h_subject;
oto = hp->h_to;
occ = hp->h_cc;
obcc = hp->h_bcc;
oothers = hp->h_others;
hp->h_to = hp->h_subject = hp->h_cc = hp->h_bcc = hp->h_defopt = NOSTR;
hp->h_others = NOSTRPTR;
hp->h_seq = 0;
while (gethfield(fbuf, hdr, 9999L) > 0) {
if (ishfield(hdr, "to"))
hp->h_to = addto(hp->h_to, hcontents(hdr));
else if (ishfield(hdr, "subject"))
hp->h_subject = addone(hp->h_subject, hcontents(hdr));
else if (ishfield(hdr, "cc"))
hp->h_cc = addto(hp->h_cc, hcontents(hdr));
else if (ishfield(hdr, "bcc"))
hp->h_bcc = addto(hp->h_bcc, hcontents(hdr));
else if (ishfield(hdr, "default-options"))
hp->h_defopt = addone(hp->h_defopt, hcontents(hdr));
else
hp->h_others = Xaddone(hp->h_others, hdr);
hp->h_seq++;
}
if (hp->h_seq == 0) {
hp->h_subject = osubject;
hp->h_to = oto;
hp->h_cc = occ;
hp->h_bcc = obcc;
hp->h_others = oothers;
printf(gettext(
"(Deleted headers restored to original values)\n"));
}
if ((fd = open(tempMail, O_RDWR|O_CREAT|O_EXCL, 0600)) < 0 ||
(obuf = fdopen(fd, "w")) == NULL) {
perror(tempMail);
fclose(fbuf);
goto out;
}
if ((ibuf = fopen(tempMail, "r")) == NULL) {
perror(tempMail);
removefile(tempMail);
fclose(fbuf);
fclose(obuf);
goto out;
}
removefile(tempMail);
if (strlen(hdr) != 0) {
fputs(hdr, obuf);
putc('\n', obuf);
}
while ((t = getc(fbuf)) != EOF)
putc(t, obuf);
fclose(fbuf);
fclose(newo);
fclose(newi);
newo = obuf;
newi = ibuf;
out:
return(newo);
}
static FILE *
mespipe(FILE *ibuf, FILE *obuf, char cmd[])
{
FILE *ni, *no;
pid_t pid;
int s;
void (*sigint)(int);
char *Shell;
int fd = -1;
newi = ibuf;
if ((fd = open(tempEdit, O_RDWR|O_CREAT|O_EXCL, 0600)) < 0 ||
(no = fdopen(fd, "w")) == NULL) {
perror(tempEdit);
return(obuf);
}
if ((ni = fopen(tempEdit, "r")) == NULL) {
perror(tempEdit);
fclose(no);
removefile(tempEdit);
return(obuf);
}
removefile(tempEdit);
fflush(obuf);
rewind(ibuf);
if ((Shell = value("SHELL")) == NULL || *Shell=='\0')
Shell = SHELL;
if ((pid = vfork()) == (pid_t)-1) {
perror("fork");
goto err;
}
if (pid == 0) {
sigchild();
close(0);
dup(fileno(ibuf));
close(1);
dup(fileno(no));
for (s = 4; s < 15; s++)
close(s);
execlp(Shell, Shell, "-c", cmd, (char *)0);
perror(Shell);
_exit(1);
}
sigint = sigset(SIGINT, SIG_IGN);
while (wait(&s) != pid)
;
sigset(SIGINT, sigint);
if (s != 0 || pid == (pid_t)-1) {
fprintf(stderr, gettext("\"%s\" failed!?\n"), cmd);
goto err;
}
if (fsize(ni) == 0) {
fprintf(stderr, gettext("No bytes from \"%s\" !?\n"), cmd);
goto err;
}
newi = ni;
fclose(ibuf);
fclose(obuf);
return(no);
err:
fclose(no);
fclose(ni);
return(obuf);
}
static char *indentprefix;
static int
forward(char ms[], FILE *obuf, int f)
{
int *msgvec, *ip;
msgvec = (int *) salloc((msgCount+1) * sizeof *msgvec);
if (msgvec == NOINTPTR)
return(0);
if (getmsglist(ms, msgvec, 0) < 0)
return(0);
if (*msgvec == 0) {
*msgvec = first(0, MMNORM);
if (*msgvec == 0) {
printf(gettext("No appropriate messages\n"));
return(0);
}
msgvec[1] = 0;
}
if (tolower(f) == 'm')
indentprefix = value("indentprefix");
printf(gettext("Interpolating:"));
for (ip = msgvec; *ip != 0; ip++) {
touch(*ip);
printf(" %d", *ip);
if (msend(&message[*ip-1], obuf, islower(f) ? M_IGNORE : 0,
tolower(f) == 'm' ? tabputs : fputs) < 0) {
perror(tempMail);
return(-1);
}
}
fflush(obuf);
if (fferror(obuf)) {
perror(tempMail);
return(-1);
}
printf("\n");
return(0);
}
static int
tabputs(const char *line, FILE *obuf)
{
if (indentprefix)
fputs(indentprefix, obuf);
else if (line[0] != '\n')
fputc('\t', obuf);
return (fputs(line, obuf));
}
#ifdef SIGCONT
static void
#ifdef __cplusplus
collcont(int)
#else
collcont(int s)
#endif
{
printf(gettext("(continue)\n"));
fflush(stdout);
}
#endif
static void
collrub(int s)
{
FILE *dbuf;
char *deadletter;
# ifdef OLD_BSD_SIGS
if (s == SIGHUP)
sigignore(SIGHUP);
# endif
if (s == SIGINT && hadintr == 0) {
hadintr++;
fflush(stdout);
fprintf(stderr,
gettext("\n(Interrupt -- one more to kill letter)\n"));
# ifdef OLD_BSD_SIGS
sigrelse(s);
# endif
longjmp(coljmp, 1);
}
fclose(newo);
rewind(newi);
if (s == SIGINT && value("save")==NOSTR || fsize(newi) == 0)
goto done;
deadletter = Getf("DEAD");
if ((dbuf = fopen(deadletter,
(value("appenddeadletter") == NOSTR ? "w" : "a"))) == NULL) {
perror(deadletter);
goto done;
}
chmod(deadletter, DEADPERM);
puthead(savehp, dbuf, GMASK|GCLEN, fsize(newi));
lcwrite(deadletter, newi, dbuf, value("appenddeadletter") != NOSTR);
fclose(dbuf);
done:
fclose(newi);
resetsigs(1);
if (rcvmode) {
if (s == SIGHUP)
hangup(s);
else
stop(s);
}
else
exit(1);
}
static void
#ifdef __cplusplus
intack(int)
#else
intack(int s)
#endif
{
puts("@");
fflush(stdout);
clearerr(stdin);
longjmp(coljmp,1);
}
int
getaline(char *line, int size, FILE *f, int *hasnulls)
{
int i, ch;
for (i = 0; (i < size) && ((ch=getc(f)) != EOF); ) {
if ( ch == '\0' )
*hasnulls = 1;
if ((line[i++] = (char)ch) == '\n') break;
}
line[i] = '\0';
return(i);
}
void
#ifdef __cplusplus
savedead(int)
#else
savedead(int s)
#endif
{
collrub(SIGINT);
exit(1);
}
char *
addto(char hf[], char news[])
{
char name[LINESIZE];
int comma = docomma(news);
while (news = yankword(news, name, sizeof (name), comma)) {
nstrcat(name, sizeof (name), ", ");
hf = addone(hf, name);
}
return hf;
}
char *
addone(char hf[], char news[])
{
char *cp, *cp2, *linebuf;
if (hf == NOSTR)
hf = savestr("");
if (*news == '\0')
return(hf);
linebuf = (char *)srealloc(hf, (unsigned)(strlen(hf) + strlen(news) + 2));
cp2 = strchr(linebuf, '\0');
if (cp2 > linebuf && cp2[-1] != ' ')
*cp2++ = ' ';
for (cp = news; any(*cp, " \t"); cp++)
;
while (*cp != '\0')
*cp2++ = *cp++;
*cp2 = '\0';
return(linebuf);
}
static int
nptrs(char **hf)
{
int i;
if (!hf)
return(0);
for (i = 0; *hf; hf++)
i++;
return(i);
}
static char **
Xaddone(char **hf, char news[])
{
char *linebuf;
char **ohf = hf;
int nhf = nptrs(hf);
if (hf == NOSTRPTR)
hf = (char**)salloc(sizeof(char*) * 2);
else
hf = (char**)srealloc(hf, sizeof(char*) * (nhf + 2));
if (hf == NOSTRPTR) {
fprintf(stderr, gettext("No room, header lost: %s\n"), news);
return(ohf);
}
linebuf = (char *)salloc((unsigned)(strlen(news) + 1));
strcpy(linebuf, news);
hf[nhf++] = linebuf;
hf[nhf] = NOSTR;
return(hf);
}
static void
cpout(char *str, FILE *ofd)
{
char *cp = str;
while (*cp) {
if (*cp == '\\') {
switch (*(cp+1)) {
case 'n':
putc('\n', ofd);
cp++;
break;
case 't':
putc('\t', ofd);
cp++;
break;
default:
putc('\\', ofd);
}
} else {
putc(*cp, ofd);
}
cp++;
}
putc('\n', ofd);
fflush(ofd);
}
static void
xhalt(void)
{
fclose(newo);
fclose(newi);
sigset(SIGINT, savesig);
sigset(SIGHUP, savehup);
if (rcvmode)
stop(0);
exit(1);
}
static int
stripnulls(char *linebuf, int nread)
{
int i, j;
for (i = 0; i < nread; i++)
if (linebuf[i] == '\0')
break;
for (j = i; j < nread; j++)
if (linebuf[j] != '\0')
linebuf[i++] = linebuf[j];
linebuf[i] = '\0';
return(i);
}