Commit | Line | Data |
---|---|---|
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 | 9 | static 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 |
21 | static int c_erase; /* Current erase char */ |
22 | static int c_kill; /* Current kill char */ | |
1b38f4e9 | 23 | static jmp_buf rewrite; /* Place to go when continued */ |
e44ee2f8 | 24 | static jmp_buf intjmp; /* Place to go when interrupted */ |
80741a9f KS |
25 | #ifndef TIOCSTI |
26 | static int ttyset; /* We must now do erase/kill */ | |
27 | #endif | |
28 | ||
29 | /* | |
30 | * Read all relevant header fields. | |
31 | */ | |
32 | ||
a0d23834 | 33 | int |
80741a9f KS |
34 | grabh(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 |
105 | out: |
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 | ||
127 | char * | |
128 | readtty(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 | 183 | redo: |
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 | 228 | void |
e44ee2f8 | 229 | ttystop(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 | 242 | void |
e44ee2f8 | 243 | ttyint(s) |
a0d23834 | 244 | int s; |
e44ee2f8 | 245 | { |
e44ee2f8 EW |
246 | longjmp(intjmp, 1); |
247 | } |