4.4BSD snapshot (revision 8.1); add 1993 to copyright
[unix-history] / usr / src / usr.bin / mail / tty.c
CommitLineData
761330fe 1/*
a12ff486
KB
2 * Copyright (c) 1980, 1993
3 * The Regents of the University of California. All rights reserved.
0c5f72fb 4 *
f15db449 5 * %sccs.include.redist.c%
761330fe
DF
6 */
7
acfc7e9b 8#ifndef lint
a12ff486 9static char sccsid[] = "@(#)tty.c 8.1 (Berkeley) %G%";
acfc7e9b 10#endif /* not lint */
80741a9f
KS
11
12/*
13 * Mail -- a mail program
14 *
15 * Generally useful tty stuff.
16 */
17
18#include "rcv.h"
a0d23834 19#include "extern.h"
80741a9f 20
80741a9f
KS
21static int c_erase; /* Current erase char */
22static int c_kill; /* Current kill char */
1b38f4e9 23static jmp_buf rewrite; /* Place to go when continued */
e44ee2f8 24static jmp_buf intjmp; /* Place to go when interrupted */
80741a9f
KS
25#ifndef TIOCSTI
26static int ttyset; /* We must now do erase/kill */
27#endif
28
29/*
30 * Read all relevant header fields.
31 */
32
a0d23834 33int
80741a9f
KS
34grabh(hp, gflags)
35 struct header *hp;
a0d23834 36 int gflags;
80741a9f
KS
37{
38 struct sgttyb ttybuf;
e62a1467 39 sig_t saveint;
80741a9f 40#ifndef TIOCSTI
e62a1467 41 sig_t savequit;
80741a9f 42#endif
e62a1467
EW
43 sig_t savetstp;
44 sig_t savettou;
45 sig_t savettin;
80741a9f 46 int errs;
a6714963 47 void ttyint();
80741a9f 48
e44ee2f8
EW
49 savetstp = signal(SIGTSTP, SIG_DFL);
50 savettou = signal(SIGTTOU, SIG_DFL);
51 savettin = signal(SIGTTIN, SIG_DFL);
80741a9f
KS
52 errs = 0;
53#ifndef TIOCSTI
54 ttyset = 0;
55#endif
9a7dcab2 56 if (ioctl(fileno(stdin), TIOCGETP, &ttybuf) < 0) {
80741a9f
KS
57 perror("gtty");
58 return(-1);
59 }
60 c_erase = ttybuf.sg_erase;
61 c_kill = ttybuf.sg_kill;
62#ifndef TIOCSTI
63 ttybuf.sg_erase = 0;
64 ttybuf.sg_kill = 0;
828615a1
EW
65 if ((saveint = signal(SIGINT, SIG_IGN)) == SIG_DFL)
66 signal(SIGINT, SIG_DFL);
67 if ((savequit = signal(SIGQUIT, SIG_IGN)) == SIG_DFL)
68 signal(SIGQUIT, SIG_DFL);
e44ee2f8
EW
69#else
70 if (setjmp(intjmp))
71 goto out;
72 saveint = signal(SIGINT, ttyint);
80741a9f
KS
73#endif
74 if (gflags & GTO) {
75#ifndef TIOCSTI
3d6f01e5 76 if (!ttyset && hp->h_to != NIL)
80741a9f
KS
77 ttyset++, stty(fileno(stdin), &ttybuf);
78#endif
3d6f01e5
EW
79 hp->h_to =
80 extract(readtty("To: ", detract(hp->h_to, 0)), GTO);
80741a9f
KS
81 }
82 if (gflags & GSUBJECT) {
83#ifndef TIOCSTI
84 if (!ttyset && hp->h_subject != NOSTR)
85 ttyset++, stty(fileno(stdin), &ttybuf);
86#endif
87 hp->h_subject = readtty("Subject: ", hp->h_subject);
80741a9f
KS
88 }
89 if (gflags & GCC) {
90#ifndef TIOCSTI
3d6f01e5 91 if (!ttyset && hp->h_cc != NIL)
80741a9f
KS
92 ttyset++, stty(fileno(stdin), &ttybuf);
93#endif
3d6f01e5
EW
94 hp->h_cc =
95 extract(readtty("Cc: ", detract(hp->h_cc, 0)), GCC);
80741a9f
KS
96 }
97 if (gflags & GBCC) {
98#ifndef TIOCSTI
3d6f01e5 99 if (!ttyset && hp->h_bcc != NIL)
80741a9f
KS
100 ttyset++, stty(fileno(stdin), &ttybuf);
101#endif
3d6f01e5
EW
102 hp->h_bcc =
103 extract(readtty("Bcc: ", detract(hp->h_bcc, 0)), GBCC);
80741a9f 104 }
e44ee2f8
EW
105out:
106 signal(SIGTSTP, savetstp);
107 signal(SIGTTOU, savettou);
108 signal(SIGTTIN, savettin);
80741a9f
KS
109#ifndef TIOCSTI
110 ttybuf.sg_erase = c_erase;
111 ttybuf.sg_kill = c_kill;
112 if (ttyset)
113 stty(fileno(stdin), &ttybuf);
828615a1 114 signal(SIGQUIT, savequit);
80741a9f 115#endif
e44ee2f8 116 signal(SIGINT, saveint);
80741a9f
KS
117 return(errs);
118}
119
120/*
121 * Read up a header from standard input.
122 * The source string has the preliminary contents to
123 * be read.
124 *
125 */
126
127char *
128readtty(pr, src)
129 char pr[], src[];
130{
338c4a5d 131 char ch, canonb[BUFSIZ];
828615a1 132 int c;
80741a9f 133 register char *cp, *cp2;
a6714963 134 void ttystop();
80741a9f 135
1b38f4e9
KS
136 fputs(pr, stdout);
137 fflush(stdout);
80741a9f
KS
138 if (src != NOSTR && strlen(src) > BUFSIZ - 2) {
139 printf("too long to edit\n");
140 return(src);
141 }
142#ifndef TIOCSTI
143 if (src != NOSTR)
144 cp = copy(src, canonb);
145 else
146 cp = copy("", canonb);
147 fputs(canonb, stdout);
148 fflush(stdout);
149#else
1b38f4e9
KS
150 cp = src == NOSTR ? "" : src;
151 while (c = *cp++) {
80741a9f
KS
152 if (c == c_erase || c == c_kill) {
153 ch = '\\';
154 ioctl(0, TIOCSTI, &ch);
155 }
338c4a5d
SL
156 ch = c;
157 ioctl(0, TIOCSTI, &ch);
80741a9f
KS
158 }
159 cp = canonb;
419b1e01 160 *cp = 0;
80741a9f 161#endif
1b38f4e9
KS
162 cp2 = cp;
163 while (cp2 < canonb + BUFSIZ)
164 *cp2++ = 0;
165 cp2 = cp;
166 if (setjmp(rewrite))
167 goto redo;
e44ee2f8
EW
168 signal(SIGTSTP, ttystop);
169 signal(SIGTTOU, ttystop);
170 signal(SIGTTIN, ttystop);
7bfe8da7 171 clearerr(stdin);
1b38f4e9
KS
172 while (cp2 < canonb + BUFSIZ) {
173 c = getc(stdin);
174 if (c == EOF || c == '\n')
175 break;
176 *cp2++ = c;
177 }
178 *cp2 = 0;
e44ee2f8
EW
179 signal(SIGTSTP, SIG_DFL);
180 signal(SIGTTOU, SIG_DFL);
181 signal(SIGTTIN, SIG_DFL);
182 if (c == EOF && ferror(stdin)) {
1b38f4e9 183redo:
1b38f4e9
KS
184 cp = strlen(canonb) > 0 ? canonb : NOSTR;
185 clearerr(stdin);
186 return(readtty(pr, cp));
187 }
80741a9f 188#ifndef TIOCSTI
ea394d88 189 if (cp == NOSTR || *cp == '\0')
80741a9f 190 return(src);
ea394d88 191 cp2 = cp;
80741a9f
KS
192 if (!ttyset)
193 return(strlen(canonb) > 0 ? savestr(canonb) : NOSTR);
194 while (*cp != '\0') {
195 c = *cp++;
196 if (c == c_erase) {
197 if (cp2 == canonb)
198 continue;
199 if (cp2[-1] == '\\') {
200 cp2[-1] = c;
201 continue;
202 }
203 cp2--;
204 continue;
205 }
206 if (c == c_kill) {
207 if (cp2 == canonb)
208 continue;
209 if (cp2[-1] == '\\') {
210 cp2[-1] = c;
211 continue;
212 }
213 cp2 = canonb;
214 continue;
215 }
216 *cp2++ = c;
217 }
218 *cp2 = '\0';
219#endif
220 if (equal("", canonb))
221 return(NOSTR);
222 return(savestr(canonb));
223}
1b38f4e9
KS
224
225/*
226 * Receipt continuation.
227 */
a6714963 228void
e44ee2f8 229ttystop(s)
a0d23834 230 int s;
1b38f4e9 231{
e62a1467 232 sig_t old_action = signal(s, SIG_DFL);
e44ee2f8
EW
233
234 sigsetmask(sigblock(0) & ~sigmask(s));
235 kill(0, s);
236 sigblock(sigmask(s));
237 signal(s, old_action);
1b38f4e9
KS
238 longjmp(rewrite, 1);
239}
e44ee2f8
EW
240
241/*ARGSUSED*/
a6714963 242void
e44ee2f8 243ttyint(s)
a0d23834 244 int s;
e44ee2f8 245{
e44ee2f8
EW
246 longjmp(intjmp, 1);
247}