xref: /original-bsd/usr.bin/mail/tty.c (revision 8251a00e)
1 #ifndef lint
2 static char sccsid[] = "@(#)tty.c	2.7 (Berkeley) 08/11/83";
3 #endif
4 
5 /*
6  * Mail -- a mail program
7  *
8  * Generally useful tty stuff.
9  */
10 
11 #include "rcv.h"
12 
13 static	int	c_erase;		/* Current erase char */
14 static	int	c_kill;			/* Current kill char */
15 static	int	hadcont;		/* Saw continue signal */
16 static	jmp_buf	rewrite;		/* Place to go when continued */
17 #ifndef TIOCSTI
18 static	int	ttyset;			/* We must now do erase/kill */
19 #endif
20 
21 /*
22  * Read all relevant header fields.
23  */
24 
25 grabh(hp, gflags)
26 	struct header *hp;
27 {
28 	struct sgttyb ttybuf;
29 	int ttycont(), signull();
30 #ifndef TIOCSTI
31 	int (*savesigs[2])();
32 #endif
33 	int (*savecont)();
34 	register int s;
35 	int errs;
36 
37 # ifdef VMUNIX
38 	savecont = sigset(SIGCONT, signull);
39 # endif VMUNIX
40 	errs = 0;
41 #ifndef TIOCSTI
42 	ttyset = 0;
43 #endif
44 	if (gtty(fileno(stdin), &ttybuf) < 0) {
45 		perror("gtty");
46 		return(-1);
47 	}
48 	c_erase = ttybuf.sg_erase;
49 	c_kill = ttybuf.sg_kill;
50 #ifndef TIOCSTI
51 	ttybuf.sg_erase = 0;
52 	ttybuf.sg_kill = 0;
53 	for (s = SIGINT; s <= SIGQUIT; s++)
54 		if ((savesigs[s-SIGINT] = sigset(s, SIG_IGN)) == SIG_DFL)
55 			sigset(s, SIG_DFL);
56 #endif
57 	if (gflags & GTO) {
58 #ifndef TIOCSTI
59 		if (!ttyset && hp->h_to != NOSTR)
60 			ttyset++, stty(fileno(stdin), &ttybuf);
61 #endif
62 		hp->h_to = readtty("To: ", hp->h_to);
63 		if (hp->h_to != NOSTR)
64 			hp->h_seq++;
65 	}
66 	if (gflags & GSUBJECT) {
67 #ifndef TIOCSTI
68 		if (!ttyset && hp->h_subject != NOSTR)
69 			ttyset++, stty(fileno(stdin), &ttybuf);
70 #endif
71 		hp->h_subject = readtty("Subject: ", hp->h_subject);
72 		if (hp->h_subject != NOSTR)
73 			hp->h_seq++;
74 	}
75 	if (gflags & GCC) {
76 #ifndef TIOCSTI
77 		if (!ttyset && hp->h_cc != NOSTR)
78 			ttyset++, stty(fileno(stdin), &ttybuf);
79 #endif
80 		hp->h_cc = readtty("Cc: ", hp->h_cc);
81 		if (hp->h_cc != NOSTR)
82 			hp->h_seq++;
83 	}
84 	if (gflags & GBCC) {
85 #ifndef TIOCSTI
86 		if (!ttyset && hp->h_bcc != NOSTR)
87 			ttyset++, stty(fileno(stdin), &ttybuf);
88 #endif
89 		hp->h_bcc = readtty("Bcc: ", hp->h_bcc);
90 		if (hp->h_bcc != NOSTR)
91 			hp->h_seq++;
92 	}
93 # ifdef VMUNIX
94 	sigset(SIGCONT, savecont);
95 # endif VMUNIX
96 #ifndef TIOCSTI
97 	ttybuf.sg_erase = c_erase;
98 	ttybuf.sg_kill = c_kill;
99 	if (ttyset)
100 		stty(fileno(stdin), &ttybuf);
101 	for (s = SIGINT; s <= SIGQUIT; s++)
102 		sigset(s, savesigs[s-SIGINT]);
103 #endif
104 	return(errs);
105 }
106 
107 /*
108  * Read up a header from standard input.
109  * The source string has the preliminary contents to
110  * be read.
111  *
112  */
113 
114 char *
115 readtty(pr, src)
116 	char pr[], src[];
117 {
118 	char ch, canonb[BUFSIZ];
119 	int c, signull();
120 	register char *cp, *cp2;
121 
122 	fputs(pr, stdout);
123 	fflush(stdout);
124 	if (src != NOSTR && strlen(src) > BUFSIZ - 2) {
125 		printf("too long to edit\n");
126 		return(src);
127 	}
128 #ifndef TIOCSTI
129 	if (src != NOSTR)
130 		cp = copy(src, canonb);
131 	else
132 		cp = copy("", canonb);
133 	fputs(canonb, stdout);
134 	fflush(stdout);
135 #else
136 	cp = src == NOSTR ? "" : src;
137 	while (c = *cp++) {
138 		if (c == c_erase || c == c_kill) {
139 			ch = '\\';
140 			ioctl(0, TIOCSTI, &ch);
141 		}
142 		ch = c;
143 		ioctl(0, TIOCSTI, &ch);
144 	}
145 	cp = canonb;
146 	*cp = 0;
147 #endif
148 	cp2 = cp;
149 	while (cp2 < canonb + BUFSIZ)
150 		*cp2++ = 0;
151 	cp2 = cp;
152 	if (setjmp(rewrite))
153 		goto redo;
154 # ifdef VMUNIX
155 	sigset(SIGCONT, ttycont);
156 # endif VMUNIX
157 	clearerr(stdin);
158 	while (cp2 < canonb + BUFSIZ) {
159 		c = getc(stdin);
160 		if (c == EOF || c == '\n')
161 			break;
162 		*cp2++ = c;
163 	}
164 	*cp2 = 0;
165 # ifdef VMUNIX
166 	sigset(SIGCONT, signull);
167 # endif VMUNIX
168 	if (c == EOF && ferror(stdin) && hadcont) {
169 redo:
170 		hadcont = 0;
171 		cp = strlen(canonb) > 0 ? canonb : NOSTR;
172 		clearerr(stdin);
173 		return(readtty(pr, cp));
174 	}
175 #ifndef TIOCSTI
176 	if (cp == NOSTR || *cp == '\0')
177 		return(src);
178 	cp2 = cp;
179 	if (!ttyset)
180 		return(strlen(canonb) > 0 ? savestr(canonb) : NOSTR);
181 	while (*cp != '\0') {
182 		c = *cp++;
183 		if (c == c_erase) {
184 			if (cp2 == canonb)
185 				continue;
186 			if (cp2[-1] == '\\') {
187 				cp2[-1] = c;
188 				continue;
189 			}
190 			cp2--;
191 			continue;
192 		}
193 		if (c == c_kill) {
194 			if (cp2 == canonb)
195 				continue;
196 			if (cp2[-1] == '\\') {
197 				cp2[-1] = c;
198 				continue;
199 			}
200 			cp2 = canonb;
201 			continue;
202 		}
203 		*cp2++ = c;
204 	}
205 	*cp2 = '\0';
206 #endif
207 	if (equal("", canonb))
208 		return(NOSTR);
209 	return(savestr(canonb));
210 }
211 
212 # ifdef VMUNIX
213 /*
214  * Receipt continuation.
215  */
216 ttycont(s)
217 {
218 
219 	hadcont++;
220 	longjmp(rewrite, 1);
221 }
222 # endif VMUNIX
223 
224 /*
225  * Null routine to satisfy
226  * silly system bug that denies us holding SIGCONT
227  */
228 signull(s)
229 {}
230