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