Commit | Line | Data |
---|---|---|
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 | ||
1b38f4e9 | 12 | static char *SccsId = "@(#)tty.c 1.4 %G%"; |
80741a9f KS |
13 | |
14 | static int c_erase; /* Current erase char */ | |
15 | static int c_kill; /* Current kill char */ | |
1b38f4e9 KS |
16 | static int hadcont; /* Saw continue signal */ |
17 | static jmp_buf rewrite; /* Place to go when continued */ | |
80741a9f KS |
18 | #ifndef TIOCSTI |
19 | static int ttyset; /* We must now do erase/kill */ | |
20 | #endif | |
21 | ||
22 | /* | |
23 | * Read all relevant header fields. | |
24 | */ | |
25 | ||
26 | grabh(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 | ||
111 | char * | |
112 | readtty(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) { | |
160 | redo: | |
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 | */ | |
206 | ttycont(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 | */ | |
218 | signull(s) | |
219 | {} |