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