xref: /csrg-svn/usr.bin/mail/tty.c (revision 68818)
122469Sdist /*
262083Sbostic  * Copyright (c) 1980, 1993
362083Sbostic  *	The Regents of the University of California.  All rights reserved.
433499Sbostic  *
542741Sbostic  * %sccs.include.redist.c%
622469Sdist  */
722469Sdist 
834905Sbostic #ifndef lint
9*68818Sdab static char sccsid[] = "@(#)tty.c	8.2 (Berkeley) 04/20/95";
1034905Sbostic #endif /* not lint */
111247Skas 
121247Skas /*
131247Skas  * Mail -- a mail program
141247Skas  *
151247Skas  * Generally useful tty stuff.
161247Skas  */
171247Skas 
181247Skas #include "rcv.h"
1954505Sbostic #include "extern.h"
201247Skas 
211247Skas static	int	c_erase;		/* Current erase char */
221247Skas static	int	c_kill;			/* Current kill char */
233422Skurt static	jmp_buf	rewrite;		/* Place to go when continued */
2437482Sedward static	jmp_buf	intjmp;			/* Place to go when interrupted */
251247Skas #ifndef TIOCSTI
261247Skas static	int	ttyset;			/* We must now do erase/kill */
271247Skas #endif
281247Skas 
291247Skas /*
301247Skas  * Read all relevant header fields.
311247Skas  */
321247Skas 
3354505Sbostic int
grabh(hp,gflags)341247Skas grabh(hp, gflags)
351247Skas 	struct header *hp;
3654505Sbostic 	int gflags;
371247Skas {
38*68818Sdab 	struct termios ttybuf;
3939612Sedward 	sig_t saveint;
401247Skas #ifndef TIOCSTI
4139612Sedward 	sig_t savequit;
42*68818Sdab #else
43*68818Sdab 	int extproc, flag;
441247Skas #endif
4539612Sedward 	sig_t savetstp;
4639612Sedward 	sig_t savettou;
4739612Sedward 	sig_t savettin;
481247Skas 	int errs;
4947707Sbostic 	void ttyint();
501247Skas 
5137482Sedward 	savetstp = signal(SIGTSTP, SIG_DFL);
5237482Sedward 	savettou = signal(SIGTTOU, SIG_DFL);
5337482Sedward 	savettin = signal(SIGTTIN, SIG_DFL);
541247Skas 	errs = 0;
551247Skas #ifndef TIOCSTI
561247Skas 	ttyset = 0;
571247Skas #endif
58*68818Sdab 	if (ioctl(fileno(stdin), TIOCGETA, &ttybuf) < 0) {
59*68818Sdab 		perror("TIOCGETA");
601247Skas 		return(-1);
611247Skas 	}
62*68818Sdab 	c_erase = ttybuf.c_cc[VERASE];
63*68818Sdab 	c_kill = ttybuf.c_cc[VKILL];
641247Skas #ifndef TIOCSTI
65*68818Sdab 	ttybuf.c_cc[VERASE] = 0;
66*68818Sdab 	ttybuf.c_cc[VKILL] = 0;
6731142Sedward 	if ((saveint = signal(SIGINT, SIG_IGN)) == SIG_DFL)
6831142Sedward 		signal(SIGINT, SIG_DFL);
6931142Sedward 	if ((savequit = signal(SIGQUIT, SIG_IGN)) == SIG_DFL)
7031142Sedward 		signal(SIGQUIT, SIG_DFL);
7137482Sedward #else
72*68818Sdab # ifdef	TIOCEXT
73*68818Sdab 	extproc = ((ttybuf.c_lflag & EXTPROC) ? 1 : 0);
74*68818Sdab 	if (extproc) {
75*68818Sdab 		flag = 0;
76*68818Sdab 		if (ioctl(fileno(stdin), TIOCEXT, &flag) < 0)
77*68818Sdab 			perror("TIOCEXT: off");
78*68818Sdab 	}
79*68818Sdab # endif /* TIOCEXT */
8037482Sedward 	if (setjmp(intjmp))
8137482Sedward 		goto out;
8237482Sedward 	saveint = signal(SIGINT, ttyint);
831247Skas #endif
841247Skas 	if (gflags & GTO) {
851247Skas #ifndef TIOCSTI
8634800Sedward 		if (!ttyset && hp->h_to != NIL)
87*68818Sdab 			ttyset++, tcsetattr(fileno(stdin), &ttybuf);
881247Skas #endif
8934800Sedward 		hp->h_to =
9034800Sedward 			extract(readtty("To: ", detract(hp->h_to, 0)), GTO);
911247Skas 	}
921247Skas 	if (gflags & GSUBJECT) {
931247Skas #ifndef TIOCSTI
941247Skas 		if (!ttyset && hp->h_subject != NOSTR)
95*68818Sdab 			ttyset++, tcsetattr(fileno(stdin), &ttybuf);
961247Skas #endif
971247Skas 		hp->h_subject = readtty("Subject: ", hp->h_subject);
981247Skas 	}
991247Skas 	if (gflags & GCC) {
1001247Skas #ifndef TIOCSTI
10134800Sedward 		if (!ttyset && hp->h_cc != NIL)
102*68818Sdab 			ttyset++, tcsetattr(fileno(stdin), &ttybuf);
1031247Skas #endif
10434800Sedward 		hp->h_cc =
10534800Sedward 			extract(readtty("Cc: ", detract(hp->h_cc, 0)), GCC);
1061247Skas 	}
1071247Skas 	if (gflags & GBCC) {
1081247Skas #ifndef TIOCSTI
10934800Sedward 		if (!ttyset && hp->h_bcc != NIL)
110*68818Sdab 			ttyset++, tcsetattr(fileno(stdin), &ttybuf);
1111247Skas #endif
11234800Sedward 		hp->h_bcc =
11334800Sedward 			extract(readtty("Bcc: ", detract(hp->h_bcc, 0)), GBCC);
1141247Skas 	}
11537482Sedward out:
11637482Sedward 	signal(SIGTSTP, savetstp);
11737482Sedward 	signal(SIGTTOU, savettou);
11837482Sedward 	signal(SIGTTIN, savettin);
1191247Skas #ifndef TIOCSTI
120*68818Sdab 	ttybuf.c_cc[VERASE] = c_erase;
121*68818Sdab 	ttybuf.c_cc[VKILL] = c_kill;
1221247Skas 	if (ttyset)
123*68818Sdab 		tcsetattr(fileno(stdin), &ttybuf);
12431142Sedward 	signal(SIGQUIT, savequit);
125*68818Sdab #else
126*68818Sdab # ifdef	TIOCEXT
127*68818Sdab 	if (extproc) {
128*68818Sdab 		flag = 1;
129*68818Sdab 		if (ioctl(fileno(stdin), TIOCEXT, &flag) < 0)
130*68818Sdab 			perror("TIOCEXT: on");
131*68818Sdab 	}
132*68818Sdab # endif /* TIOCEXT */
1331247Skas #endif
13437482Sedward 	signal(SIGINT, saveint);
1351247Skas 	return(errs);
1361247Skas }
1371247Skas 
1381247Skas /*
1391247Skas  * Read up a header from standard input.
1401247Skas  * The source string has the preliminary contents to
1411247Skas  * be read.
1421247Skas  *
1431247Skas  */
1441247Skas 
1451247Skas char *
readtty(pr,src)1461247Skas readtty(pr, src)
1471247Skas 	char pr[], src[];
1481247Skas {
14910828Ssam 	char ch, canonb[BUFSIZ];
15031142Sedward 	int c;
1511247Skas 	register char *cp, *cp2;
15247707Sbostic 	void ttystop();
1531247Skas 
1543422Skurt 	fputs(pr, stdout);
1553422Skurt 	fflush(stdout);
1561247Skas 	if (src != NOSTR && strlen(src) > BUFSIZ - 2) {
1571247Skas 		printf("too long to edit\n");
1581247Skas 		return(src);
1591247Skas 	}
1601247Skas #ifndef TIOCSTI
1611247Skas 	if (src != NOSTR)
1621247Skas 		cp = copy(src, canonb);
1631247Skas 	else
1641247Skas 		cp = copy("", canonb);
1651247Skas 	fputs(canonb, stdout);
1661247Skas 	fflush(stdout);
1671247Skas #else
1683422Skurt 	cp = src == NOSTR ? "" : src;
1693422Skurt 	while (c = *cp++) {
1701247Skas 		if (c == c_erase || c == c_kill) {
1711247Skas 			ch = '\\';
1721247Skas 			ioctl(0, TIOCSTI, &ch);
1731247Skas 		}
17410828Ssam 		ch = c;
17510828Ssam 		ioctl(0, TIOCSTI, &ch);
1761247Skas 	}
1771247Skas 	cp = canonb;
1782845Skas 	*cp = 0;
1791247Skas #endif
1803422Skurt 	cp2 = cp;
1813422Skurt 	while (cp2 < canonb + BUFSIZ)
1823422Skurt 		*cp2++ = 0;
1833422Skurt 	cp2 = cp;
1843422Skurt 	if (setjmp(rewrite))
1853422Skurt 		goto redo;
18637482Sedward 	signal(SIGTSTP, ttystop);
18737482Sedward 	signal(SIGTTOU, ttystop);
18837482Sedward 	signal(SIGTTIN, ttystop);
18914141Ssam 	clearerr(stdin);
1903422Skurt 	while (cp2 < canonb + BUFSIZ) {
1913422Skurt 		c = getc(stdin);
1923422Skurt 		if (c == EOF || c == '\n')
1933422Skurt 			break;
1943422Skurt 		*cp2++ = c;
1953422Skurt 	}
1963422Skurt 	*cp2 = 0;
19737482Sedward 	signal(SIGTSTP, SIG_DFL);
19837482Sedward 	signal(SIGTTOU, SIG_DFL);
19937482Sedward 	signal(SIGTTIN, SIG_DFL);
20037482Sedward 	if (c == EOF && ferror(stdin)) {
2013422Skurt redo:
2023422Skurt 		cp = strlen(canonb) > 0 ? canonb : NOSTR;
2033422Skurt 		clearerr(stdin);
2043422Skurt 		return(readtty(pr, cp));
2053422Skurt 	}
2061247Skas #ifndef TIOCSTI
2076223Skurt 	if (cp == NOSTR || *cp == '\0')
2081247Skas 		return(src);
2096223Skurt 	cp2 = cp;
2101247Skas 	if (!ttyset)
2111247Skas 		return(strlen(canonb) > 0 ? savestr(canonb) : NOSTR);
2121247Skas 	while (*cp != '\0') {
2131247Skas 		c = *cp++;
2141247Skas 		if (c == c_erase) {
2151247Skas 			if (cp2 == canonb)
2161247Skas 				continue;
2171247Skas 			if (cp2[-1] == '\\') {
2181247Skas 				cp2[-1] = c;
2191247Skas 				continue;
2201247Skas 			}
2211247Skas 			cp2--;
2221247Skas 			continue;
2231247Skas 		}
2241247Skas 		if (c == c_kill) {
2251247Skas 			if (cp2 == canonb)
2261247Skas 				continue;
2271247Skas 			if (cp2[-1] == '\\') {
2281247Skas 				cp2[-1] = c;
2291247Skas 				continue;
2301247Skas 			}
2311247Skas 			cp2 = canonb;
2321247Skas 			continue;
2331247Skas 		}
2341247Skas 		*cp2++ = c;
2351247Skas 	}
2361247Skas 	*cp2 = '\0';
2371247Skas #endif
2381247Skas 	if (equal("", canonb))
2391247Skas 		return(NOSTR);
2401247Skas 	return(savestr(canonb));
2411247Skas }
2423422Skurt 
2433422Skurt /*
2443422Skurt  * Receipt continuation.
2453422Skurt  */
24647707Sbostic void
ttystop(s)24737482Sedward ttystop(s)
24854505Sbostic 	int s;
2493422Skurt {
25039612Sedward 	sig_t old_action = signal(s, SIG_DFL);
25137482Sedward 
25237482Sedward 	sigsetmask(sigblock(0) & ~sigmask(s));
25337482Sedward 	kill(0, s);
25437482Sedward 	sigblock(sigmask(s));
25537482Sedward 	signal(s, old_action);
2563422Skurt 	longjmp(rewrite, 1);
2573422Skurt }
25837482Sedward 
25937482Sedward /*ARGSUSED*/
26047707Sbostic void
ttyint(s)26137482Sedward ttyint(s)
26254505Sbostic 	int s;
26337482Sedward {
26437482Sedward 	longjmp(intjmp, 1);
26537482Sedward }
266