check buffer size.
[unix-history] / usr / src / usr.bin / mail / tty.c
CommitLineData
2ae9f53f
SL
1#ifndef lint
2static char sccsid[] = "@(#)tty.c 2.7 (Berkeley) %G%";
3#endif
80741a9f
KS
4
5/*
6 * Mail -- a mail program
7 *
8 * Generally useful tty stuff.
9 */
10
11#include "rcv.h"
80741a9f 12
80741a9f
KS
13static int c_erase; /* Current erase char */
14static int c_kill; /* Current kill char */
1b38f4e9
KS
15static int hadcont; /* Saw continue signal */
16static jmp_buf rewrite; /* Place to go when continued */
80741a9f
KS
17#ifndef TIOCSTI
18static int ttyset; /* We must now do erase/kill */
19#endif
20
21/*
22 * Read all relevant header fields.
23 */
24
25grabh(hp, gflags)
26 struct header *hp;
27{
28 struct sgttyb ttybuf;
1b38f4e9 29 int ttycont(), signull();
80741a9f
KS
30#ifndef TIOCSTI
31 int (*savesigs[2])();
32#endif
1b38f4e9 33 int (*savecont)();
80741a9f
KS
34 register int s;
35 int errs;
36
ea394d88 37# ifdef VMUNIX
1b38f4e9 38 savecont = sigset(SIGCONT, signull);
ea394d88 39# endif VMUNIX
80741a9f
KS
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++)
9d9394d3
KS
54 if ((savesigs[s-SIGINT] = sigset(s, SIG_IGN)) == SIG_DFL)
55 sigset(s, SIG_DFL);
80741a9f
KS
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 }
ea394d88 93# ifdef VMUNIX
1b38f4e9 94 sigset(SIGCONT, savecont);
ea394d88 95# endif VMUNIX
80741a9f
KS
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++)
9d9394d3 102 sigset(s, savesigs[s-SIGINT]);
80741a9f
KS
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
114char *
115readtty(pr, src)
116 char pr[], src[];
117{
338c4a5d
SL
118 char ch, canonb[BUFSIZ];
119 int c, signull();
80741a9f
KS
120 register char *cp, *cp2;
121
1b38f4e9
KS
122 fputs(pr, stdout);
123 fflush(stdout);
80741a9f
KS
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
1b38f4e9
KS
136 cp = src == NOSTR ? "" : src;
137 while (c = *cp++) {
80741a9f
KS
138 if (c == c_erase || c == c_kill) {
139 ch = '\\';
140 ioctl(0, TIOCSTI, &ch);
141 }
338c4a5d
SL
142 ch = c;
143 ioctl(0, TIOCSTI, &ch);
80741a9f
KS
144 }
145 cp = canonb;
419b1e01 146 *cp = 0;
80741a9f 147#endif
1b38f4e9
KS
148 cp2 = cp;
149 while (cp2 < canonb + BUFSIZ)
150 *cp2++ = 0;
151 cp2 = cp;
152 if (setjmp(rewrite))
153 goto redo;
ea394d88 154# ifdef VMUNIX
1b38f4e9 155 sigset(SIGCONT, ttycont);
ea394d88 156# endif VMUNIX
7bfe8da7 157 clearerr(stdin);
1b38f4e9
KS
158 while (cp2 < canonb + BUFSIZ) {
159 c = getc(stdin);
160 if (c == EOF || c == '\n')
161 break;
162 *cp2++ = c;
163 }
164 *cp2 = 0;
ea394d88 165# ifdef VMUNIX
1b38f4e9 166 sigset(SIGCONT, signull);
ea394d88 167# endif VMUNIX
1b38f4e9
KS
168 if (c == EOF && ferror(stdin) && hadcont) {
169redo:
170 hadcont = 0;
171 cp = strlen(canonb) > 0 ? canonb : NOSTR;
172 clearerr(stdin);
173 return(readtty(pr, cp));
174 }
80741a9f 175#ifndef TIOCSTI
ea394d88 176 if (cp == NOSTR || *cp == '\0')
80741a9f 177 return(src);
ea394d88 178 cp2 = cp;
80741a9f
KS
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}
1b38f4e9 211
ea394d88 212# ifdef VMUNIX
1b38f4e9
KS
213/*
214 * Receipt continuation.
215 */
216ttycont(s)
217{
218
219 hadcont++;
1b38f4e9
KS
220 longjmp(rewrite, 1);
221}
ea394d88 222# endif VMUNIX
1b38f4e9
KS
223
224/*
225 * Null routine to satisfy
226 * silly system bug that denies us holding SIGCONT
227 */
228signull(s)
229{}