386BSD 0.1 development
[unix-history] / usr / src / usr.bin / mail / tty.c
CommitLineData
4f4122db
WJ
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, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35static char sccsid[] = "@(#)tty.c 5.12 (Berkeley) 4/1/91";
36#endif /* not lint */
37
38/*
39 * Mail -- a mail program
40 *
41 * Generally useful tty stuff.
42 */
43
44#include "rcv.h"
45
46static int c_erase; /* Current erase char */
47static int c_kill; /* Current kill char */
48static jmp_buf rewrite; /* Place to go when continued */
49static jmp_buf intjmp; /* Place to go when interrupted */
50#ifndef TIOCSTI
51static int ttyset; /* We must now do erase/kill */
52#endif
53
54/*
55 * Read all relevant header fields.
56 */
57
58grabh(hp, gflags)
59 struct header *hp;
60{
61 struct sgttyb ttybuf;
62 sig_t saveint;
63#ifndef TIOCSTI
64 sig_t savequit;
65#endif
66 sig_t savetstp;
67 sig_t savettou;
68 sig_t savettin;
69 int errs;
70 void ttyint();
71
72 savetstp = signal(SIGTSTP, SIG_DFL);
73 savettou = signal(SIGTTOU, SIG_DFL);
74 savettin = signal(SIGTTIN, SIG_DFL);
75 errs = 0;
76#ifndef TIOCSTI
77 ttyset = 0;
78#endif
79 if (ioctl(fileno(stdin), TIOCGETP, &ttybuf) < 0) {
80 perror("gtty");
81 return(-1);
82 }
83 c_erase = ttybuf.sg_erase;
84 c_kill = ttybuf.sg_kill;
85#ifndef TIOCSTI
86 ttybuf.sg_erase = 0;
87 ttybuf.sg_kill = 0;
88 if ((saveint = signal(SIGINT, SIG_IGN)) == SIG_DFL)
89 signal(SIGINT, SIG_DFL);
90 if ((savequit = signal(SIGQUIT, SIG_IGN)) == SIG_DFL)
91 signal(SIGQUIT, SIG_DFL);
92#else
93 if (setjmp(intjmp))
94 goto out;
95 saveint = signal(SIGINT, ttyint);
96#endif
97 if (gflags & GTO) {
98#ifndef TIOCSTI
99 if (!ttyset && hp->h_to != NIL)
100 ttyset++, stty(fileno(stdin), &ttybuf);
101#endif
102 hp->h_to =
103 extract(readtty("To: ", detract(hp->h_to, 0)), GTO);
104 }
105 if (gflags & GSUBJECT) {
106#ifndef TIOCSTI
107 if (!ttyset && hp->h_subject != NOSTR)
108 ttyset++, stty(fileno(stdin), &ttybuf);
109#endif
110 hp->h_subject = readtty("Subject: ", hp->h_subject);
111 }
112 if (gflags & GCC) {
113#ifndef TIOCSTI
114 if (!ttyset && hp->h_cc != NIL)
115 ttyset++, stty(fileno(stdin), &ttybuf);
116#endif
117 hp->h_cc =
118 extract(readtty("Cc: ", detract(hp->h_cc, 0)), GCC);
119 }
120 if (gflags & GBCC) {
121#ifndef TIOCSTI
122 if (!ttyset && hp->h_bcc != NIL)
123 ttyset++, stty(fileno(stdin), &ttybuf);
124#endif
125 hp->h_bcc =
126 extract(readtty("Bcc: ", detract(hp->h_bcc, 0)), GBCC);
127 }
128out:
129 signal(SIGTSTP, savetstp);
130 signal(SIGTTOU, savettou);
131 signal(SIGTTIN, savettin);
132#ifndef TIOCSTI
133 ttybuf.sg_erase = c_erase;
134 ttybuf.sg_kill = c_kill;
135 if (ttyset)
136 stty(fileno(stdin), &ttybuf);
137 signal(SIGQUIT, savequit);
138#endif
139 signal(SIGINT, saveint);
140 return(errs);
141}
142
143/*
144 * Read up a header from standard input.
145 * The source string has the preliminary contents to
146 * be read.
147 *
148 */
149
150char *
151readtty(pr, src)
152 char pr[], src[];
153{
154 char ch, canonb[BUFSIZ];
155 int c;
156 register char *cp, *cp2;
157 void ttystop();
158
159 fputs(pr, stdout);
160 fflush(stdout);
161 if (src != NOSTR && strlen(src) > BUFSIZ - 2) {
162 printf("too long to edit\n");
163 return(src);
164 }
165#ifndef TIOCSTI
166 if (src != NOSTR)
167 cp = copy(src, canonb);
168 else
169 cp = copy("", canonb);
170 fputs(canonb, stdout);
171 fflush(stdout);
172#else
173 cp = src == NOSTR ? "" : src;
174 while (c = *cp++) {
175 if (c == c_erase || c == c_kill) {
176 ch = '\\';
177 ioctl(0, TIOCSTI, &ch);
178 }
179 ch = c;
180 ioctl(0, TIOCSTI, &ch);
181 }
182 cp = canonb;
183 *cp = 0;
184#endif
185 cp2 = cp;
186 while (cp2 < canonb + BUFSIZ)
187 *cp2++ = 0;
188 cp2 = cp;
189 if (setjmp(rewrite))
190 goto redo;
191 signal(SIGTSTP, ttystop);
192 signal(SIGTTOU, ttystop);
193 signal(SIGTTIN, ttystop);
194 clearerr(stdin);
195 while (cp2 < canonb + BUFSIZ) {
196 c = getc(stdin);
197 if (c == EOF || c == '\n')
198 break;
199 *cp2++ = c;
200 }
201 *cp2 = 0;
202 signal(SIGTSTP, SIG_DFL);
203 signal(SIGTTOU, SIG_DFL);
204 signal(SIGTTIN, SIG_DFL);
205 if (c == EOF && ferror(stdin)) {
206redo:
207 cp = strlen(canonb) > 0 ? canonb : NOSTR;
208 clearerr(stdin);
209 return(readtty(pr, cp));
210 }
211#ifndef TIOCSTI
212 if (cp == NOSTR || *cp == '\0')
213 return(src);
214 cp2 = cp;
215 if (!ttyset)
216 return(strlen(canonb) > 0 ? savestr(canonb) : NOSTR);
217 while (*cp != '\0') {
218 c = *cp++;
219 if (c == c_erase) {
220 if (cp2 == canonb)
221 continue;
222 if (cp2[-1] == '\\') {
223 cp2[-1] = c;
224 continue;
225 }
226 cp2--;
227 continue;
228 }
229 if (c == c_kill) {
230 if (cp2 == canonb)
231 continue;
232 if (cp2[-1] == '\\') {
233 cp2[-1] = c;
234 continue;
235 }
236 cp2 = canonb;
237 continue;
238 }
239 *cp2++ = c;
240 }
241 *cp2 = '\0';
242#endif
243 if (equal("", canonb))
244 return(NOSTR);
245 return(savestr(canonb));
246}
247
248/*
249 * Receipt continuation.
250 */
251void
252ttystop(s)
253{
254 sig_t old_action = signal(s, SIG_DFL);
255
256 sigsetmask(sigblock(0) & ~sigmask(s));
257 kill(0, s);
258 sigblock(sigmask(s));
259 signal(s, old_action);
260 longjmp(rewrite, 1);
261}
262
263/*ARGSUSED*/
264void
265ttyint(s)
266{
267 longjmp(intjmp, 1);
268}