rationalized handling of child processes, cleaned up mail1 some more
[unix-history] / usr / src / usr.bin / mail / tty.c
/*
* Copyright (c) 1980 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef lint
static char sccsid[] = "@(#)tty.c 5.7 (Berkeley) %G%";
#endif /* not lint */
/*
* Mail -- a mail program
*
* Generally useful tty stuff.
*/
#include "rcv.h"
static int c_erase; /* Current erase char */
static int c_kill; /* Current kill char */
static int hadcont; /* Saw continue signal */
static jmp_buf rewrite; /* Place to go when continued */
#ifndef TIOCSTI
static int ttyset; /* We must now do erase/kill */
#endif
/*
* Read all relevant header fields.
*/
grabh(hp, gflags)
struct header *hp;
{
struct sgttyb ttybuf;
#ifndef TIOCSTI
int (*saveint)(), (*savequit)();
#endif
int (*savecont)();
int errs;
savecont = signal(SIGCONT, SIG_DFL);
errs = 0;
#ifndef TIOCSTI
ttyset = 0;
#endif
if (gtty(fileno(stdin), &ttybuf) < 0) {
perror("gtty");
return(-1);
}
c_erase = ttybuf.sg_erase;
c_kill = ttybuf.sg_kill;
#ifndef TIOCSTI
ttybuf.sg_erase = 0;
ttybuf.sg_kill = 0;
if ((saveint = signal(SIGINT, SIG_IGN)) == SIG_DFL)
signal(SIGINT, SIG_DFL);
if ((savequit = signal(SIGQUIT, SIG_IGN)) == SIG_DFL)
signal(SIGQUIT, SIG_DFL);
#endif
if (gflags & GTO) {
#ifndef TIOCSTI
if (!ttyset && hp->h_to != NIL)
ttyset++, stty(fileno(stdin), &ttybuf);
#endif
hp->h_to =
extract(readtty("To: ", detract(hp->h_to, 0)), GTO);
}
if (gflags & GSUBJECT) {
#ifndef TIOCSTI
if (!ttyset && hp->h_subject != NOSTR)
ttyset++, stty(fileno(stdin), &ttybuf);
#endif
hp->h_subject = readtty("Subject: ", hp->h_subject);
}
if (gflags & GCC) {
#ifndef TIOCSTI
if (!ttyset && hp->h_cc != NIL)
ttyset++, stty(fileno(stdin), &ttybuf);
#endif
hp->h_cc =
extract(readtty("Cc: ", detract(hp->h_cc, 0)), GCC);
}
if (gflags & GBCC) {
#ifndef TIOCSTI
if (!ttyset && hp->h_bcc != NIL)
ttyset++, stty(fileno(stdin), &ttybuf);
#endif
hp->h_bcc =
extract(readtty("Bcc: ", detract(hp->h_bcc, 0)), GBCC);
}
signal(SIGCONT, savecont);
#ifndef TIOCSTI
ttybuf.sg_erase = c_erase;
ttybuf.sg_kill = c_kill;
if (ttyset)
stty(fileno(stdin), &ttybuf);
signal(SIGINT, saveint);
signal(SIGQUIT, savequit);
#endif
return(errs);
}
/*
* Read up a header from standard input.
* The source string has the preliminary contents to
* be read.
*
*/
char *
readtty(pr, src)
char pr[], src[];
{
char ch, canonb[BUFSIZ];
int c;
register char *cp, *cp2;
int ttycont();
fputs(pr, stdout);
fflush(stdout);
if (src != NOSTR && strlen(src) > BUFSIZ - 2) {
printf("too long to edit\n");
return(src);
}
#ifndef TIOCSTI
if (src != NOSTR)
cp = copy(src, canonb);
else
cp = copy("", canonb);
fputs(canonb, stdout);
fflush(stdout);
#else
cp = src == NOSTR ? "" : src;
while (c = *cp++) {
if (c == c_erase || c == c_kill) {
ch = '\\';
ioctl(0, TIOCSTI, &ch);
}
ch = c;
ioctl(0, TIOCSTI, &ch);
}
cp = canonb;
*cp = 0;
#endif
cp2 = cp;
while (cp2 < canonb + BUFSIZ)
*cp2++ = 0;
cp2 = cp;
if (setjmp(rewrite))
goto redo;
signal(SIGCONT, ttycont);
clearerr(stdin);
while (cp2 < canonb + BUFSIZ) {
c = getc(stdin);
if (c == EOF || c == '\n')
break;
*cp2++ = c;
}
*cp2 = 0;
signal(SIGCONT, SIG_DFL);
if (c == EOF && ferror(stdin) && hadcont) {
redo:
hadcont = 0;
cp = strlen(canonb) > 0 ? canonb : NOSTR;
clearerr(stdin);
return(readtty(pr, cp));
}
#ifndef TIOCSTI
if (cp == NOSTR || *cp == '\0')
return(src);
cp2 = cp;
if (!ttyset)
return(strlen(canonb) > 0 ? savestr(canonb) : NOSTR);
while (*cp != '\0') {
c = *cp++;
if (c == c_erase) {
if (cp2 == canonb)
continue;
if (cp2[-1] == '\\') {
cp2[-1] = c;
continue;
}
cp2--;
continue;
}
if (c == c_kill) {
if (cp2 == canonb)
continue;
if (cp2[-1] == '\\') {
cp2[-1] = c;
continue;
}
cp2 = canonb;
continue;
}
*cp2++ = c;
}
*cp2 = '\0';
#endif
if (equal("", canonb))
return(NOSTR);
return(savestr(canonb));
}
/*
* Receipt continuation.
*/
/*ARGSUSED*/
ttycont(s)
{
hadcont++;
longjmp(rewrite, 1);
}