xref: /original-bsd/usr.bin/mail/tty.c (revision 2301fdfb)
1 /*
2  * Copyright (c) 1980 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 #ifndef lint
19 static char sccsid[] = "@(#)tty.c	5.7 (Berkeley) 06/29/88";
20 #endif /* not lint */
21 
22 /*
23  * Mail -- a mail program
24  *
25  * Generally useful tty stuff.
26  */
27 
28 #include "rcv.h"
29 
30 static	int	c_erase;		/* Current erase char */
31 static	int	c_kill;			/* Current kill char */
32 static	int	hadcont;		/* Saw continue signal */
33 static	jmp_buf	rewrite;		/* Place to go when continued */
34 #ifndef TIOCSTI
35 static	int	ttyset;			/* We must now do erase/kill */
36 #endif
37 
38 /*
39  * Read all relevant header fields.
40  */
41 
42 grabh(hp, gflags)
43 	struct header *hp;
44 {
45 	struct sgttyb ttybuf;
46 #ifndef TIOCSTI
47 	int (*saveint)(), (*savequit)();
48 #endif
49 	int (*savecont)();
50 	int errs;
51 
52 	savecont = signal(SIGCONT, SIG_DFL);
53 	errs = 0;
54 #ifndef TIOCSTI
55 	ttyset = 0;
56 #endif
57 	if (gtty(fileno(stdin), &ttybuf) < 0) {
58 		perror("gtty");
59 		return(-1);
60 	}
61 	c_erase = ttybuf.sg_erase;
62 	c_kill = ttybuf.sg_kill;
63 #ifndef TIOCSTI
64 	ttybuf.sg_erase = 0;
65 	ttybuf.sg_kill = 0;
66 	if ((saveint = signal(SIGINT, SIG_IGN)) == SIG_DFL)
67 		signal(SIGINT, SIG_DFL);
68 	if ((savequit = signal(SIGQUIT, SIG_IGN)) == SIG_DFL)
69 		signal(SIGQUIT, SIG_DFL);
70 #endif
71 	if (gflags & GTO) {
72 #ifndef TIOCSTI
73 		if (!ttyset && hp->h_to != NIL)
74 			ttyset++, stty(fileno(stdin), &ttybuf);
75 #endif
76 		hp->h_to =
77 			extract(readtty("To: ", detract(hp->h_to, 0)), GTO);
78 	}
79 	if (gflags & GSUBJECT) {
80 #ifndef TIOCSTI
81 		if (!ttyset && hp->h_subject != NOSTR)
82 			ttyset++, stty(fileno(stdin), &ttybuf);
83 #endif
84 		hp->h_subject = readtty("Subject: ", hp->h_subject);
85 	}
86 	if (gflags & GCC) {
87 #ifndef TIOCSTI
88 		if (!ttyset && hp->h_cc != NIL)
89 			ttyset++, stty(fileno(stdin), &ttybuf);
90 #endif
91 		hp->h_cc =
92 			extract(readtty("Cc: ", detract(hp->h_cc, 0)), GCC);
93 	}
94 	if (gflags & GBCC) {
95 #ifndef TIOCSTI
96 		if (!ttyset && hp->h_bcc != NIL)
97 			ttyset++, stty(fileno(stdin), &ttybuf);
98 #endif
99 		hp->h_bcc =
100 			extract(readtty("Bcc: ", detract(hp->h_bcc, 0)), GBCC);
101 	}
102 	signal(SIGCONT, savecont);
103 #ifndef TIOCSTI
104 	ttybuf.sg_erase = c_erase;
105 	ttybuf.sg_kill = c_kill;
106 	if (ttyset)
107 		stty(fileno(stdin), &ttybuf);
108 	signal(SIGINT, saveint);
109 	signal(SIGQUIT, savequit);
110 #endif
111 	return(errs);
112 }
113 
114 /*
115  * Read up a header from standard input.
116  * The source string has the preliminary contents to
117  * be read.
118  *
119  */
120 
121 char *
122 readtty(pr, src)
123 	char pr[], src[];
124 {
125 	char ch, canonb[BUFSIZ];
126 	int c;
127 	register char *cp, *cp2;
128 	int ttycont();
129 
130 	fputs(pr, stdout);
131 	fflush(stdout);
132 	if (src != NOSTR && strlen(src) > BUFSIZ - 2) {
133 		printf("too long to edit\n");
134 		return(src);
135 	}
136 #ifndef TIOCSTI
137 	if (src != NOSTR)
138 		cp = copy(src, canonb);
139 	else
140 		cp = copy("", canonb);
141 	fputs(canonb, stdout);
142 	fflush(stdout);
143 #else
144 	cp = src == NOSTR ? "" : src;
145 	while (c = *cp++) {
146 		if (c == c_erase || c == c_kill) {
147 			ch = '\\';
148 			ioctl(0, TIOCSTI, &ch);
149 		}
150 		ch = c;
151 		ioctl(0, TIOCSTI, &ch);
152 	}
153 	cp = canonb;
154 	*cp = 0;
155 #endif
156 	cp2 = cp;
157 	while (cp2 < canonb + BUFSIZ)
158 		*cp2++ = 0;
159 	cp2 = cp;
160 	if (setjmp(rewrite))
161 		goto redo;
162 	signal(SIGCONT, ttycont);
163 	clearerr(stdin);
164 	while (cp2 < canonb + BUFSIZ) {
165 		c = getc(stdin);
166 		if (c == EOF || c == '\n')
167 			break;
168 		*cp2++ = c;
169 	}
170 	*cp2 = 0;
171 	signal(SIGCONT, SIG_DFL);
172 	if (c == EOF && ferror(stdin) && hadcont) {
173 redo:
174 		hadcont = 0;
175 		cp = strlen(canonb) > 0 ? canonb : NOSTR;
176 		clearerr(stdin);
177 		return(readtty(pr, cp));
178 	}
179 #ifndef TIOCSTI
180 	if (cp == NOSTR || *cp == '\0')
181 		return(src);
182 	cp2 = cp;
183 	if (!ttyset)
184 		return(strlen(canonb) > 0 ? savestr(canonb) : NOSTR);
185 	while (*cp != '\0') {
186 		c = *cp++;
187 		if (c == c_erase) {
188 			if (cp2 == canonb)
189 				continue;
190 			if (cp2[-1] == '\\') {
191 				cp2[-1] = c;
192 				continue;
193 			}
194 			cp2--;
195 			continue;
196 		}
197 		if (c == c_kill) {
198 			if (cp2 == canonb)
199 				continue;
200 			if (cp2[-1] == '\\') {
201 				cp2[-1] = c;
202 				continue;
203 			}
204 			cp2 = canonb;
205 			continue;
206 		}
207 		*cp2++ = c;
208 	}
209 	*cp2 = '\0';
210 #endif
211 	if (equal("", canonb))
212 		return(NOSTR);
213 	return(savestr(canonb));
214 }
215 
216 /*
217  * Receipt continuation.
218  */
219 /*ARGSUSED*/
220 ttycont(s)
221 {
222 	hadcont++;
223 	longjmp(rewrite, 1);
224 }
225