#include "rcv.h"
#include "extern.h"
static cc_t c_erase;
static cc_t c_kill;
static jmp_buf rewrite;
static jmp_buf intjmp;
int
grabh(struct header *hp, int gflags)
{
struct termios ttybuf;
sig_t saveint;
sig_t savetstp;
sig_t savettou;
sig_t savettin;
int errs;
int extproc, flag;
savetstp = signal(SIGTSTP, SIG_DFL);
savettou = signal(SIGTTOU, SIG_DFL);
savettin = signal(SIGTTIN, SIG_DFL);
errs = 0;
if (tcgetattr(fileno(stdin), &ttybuf) < 0) {
warn("tcgetattr(stdin)");
return (-1);
}
c_erase = ttybuf.c_cc[VERASE];
c_kill = ttybuf.c_cc[VKILL];
extproc = ((ttybuf.c_lflag & EXTPROC) ? 1 : 0);
if (extproc) {
flag = 0;
if (ioctl(fileno(stdin), TIOCEXT, &flag) < 0)
warn("TIOCEXT: off");
}
if (setjmp(intjmp))
goto out;
saveint = signal(SIGINT, ttyint);
if (gflags & GTO) {
hp->h_to =
extract(readtty("To: ", detract(hp->h_to, 0)), GTO);
}
if (gflags & GSUBJECT) {
hp->h_subject = readtty("Subject: ", hp->h_subject);
}
if (gflags & GCC) {
hp->h_cc =
extract(readtty("Cc: ", detract(hp->h_cc, 0)), GCC);
}
if (gflags & GBCC) {
hp->h_bcc =
extract(readtty("Bcc: ", detract(hp->h_bcc, 0)), GBCC);
}
out:
signal(SIGTSTP, savetstp);
signal(SIGTTOU, savettou);
signal(SIGTTIN, savettin);
if (extproc) {
flag = 1;
if (ioctl(fileno(stdin), TIOCEXT, &flag) < 0)
warn("TIOCEXT: on");
}
signal(SIGINT, saveint);
return (errs);
}
char *
readtty(const char *pr, char *src)
{
char ch, canonb[BUFSIZ];
int c;
char *cp, *cp2;
fputs(pr, stdout);
fflush(stdout);
if (src != NULL && strlen(src) > BUFSIZ - 2) {
printf("too long to edit\n");
return (src);
}
cp = src == NULL ? "" : src;
while ((c = *cp++) != '\0') {
if ((c_erase != _POSIX_VDISABLE && c == c_erase) ||
(c_kill != _POSIX_VDISABLE && c == c_kill)) {
ch = '\\';
ioctl(0, TIOCSTI, &ch);
}
ch = c;
ioctl(0, TIOCSTI, &ch);
}
cp = canonb;
*cp = '\0';
cp2 = cp;
while (cp2 < canonb + BUFSIZ)
*cp2++ = '\0';
cp2 = cp;
if (setjmp(rewrite))
goto redo;
signal(SIGTSTP, ttystop);
signal(SIGTTOU, ttystop);
signal(SIGTTIN, ttystop);
clearerr(stdin);
while (cp2 < canonb + BUFSIZ) {
c = getc(stdin);
if (c == EOF || c == '\n')
break;
*cp2++ = c;
}
*cp2 = '\0';
signal(SIGTSTP, SIG_DFL);
signal(SIGTTOU, SIG_DFL);
signal(SIGTTIN, SIG_DFL);
if (c == EOF && ferror(stdin)) {
redo:
cp = strlen(canonb) > 0 ? canonb : NULL;
clearerr(stdin);
return (readtty(pr, cp));
}
if (equal("", canonb))
return (NULL);
return (savestr(canonb));
}
void
ttystop(int s)
{
sig_t old_action = signal(s, SIG_DFL);
sigset_t nset;
sigemptyset(&nset);
sigaddset(&nset, s);
sigprocmask(SIG_BLOCK, &nset, NULL);
kill(0, s);
sigprocmask(SIG_UNBLOCK, &nset, NULL);
signal(s, old_action);
longjmp(rewrite, 1);
}
void
ttyint(int s)
{
longjmp(intjmp, 1);
}