Annotation of src/usr.bin/mail/tty.c, Revision 1.7
1.7 ! millert 1: /* $OpenBSD: tty.c,v 1.6 1997/07/14 15:56:25 millert Exp $ */
1.3 millert 2: /* $NetBSD: tty.c,v 1.7 1997/07/09 05:25:46 mikel Exp $ */
1.2 deraadt 3:
1.1 deraadt 4: /*
5: * Copyright (c) 1980, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by the University of
19: * California, Berkeley and its contributors.
20: * 4. Neither the name of the University nor the names of its contributors
21: * may be used to endorse or promote products derived from this software
22: * without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34: * SUCH DAMAGE.
35: */
36:
37: #ifndef lint
1.2 deraadt 38: #if 0
1.3 millert 39: static char sccsid[] = "@(#)tty.c 8.2 (Berkeley) 4/20/95";
1.2 deraadt 40: #else
1.7 ! millert 41: static char rcsid[] = "$OpenBSD: tty.c,v 1.6 1997/07/14 15:56:25 millert Exp $";
1.2 deraadt 42: #endif
1.1 deraadt 43: #endif /* not lint */
44:
45: /*
46: * Mail -- a mail program
47: *
48: * Generally useful tty stuff.
49: */
50:
51: #include "rcv.h"
52: #include "extern.h"
1.2 deraadt 53: #include <sys/ioctl.h>
1.1 deraadt 54:
1.5 millert 55: static cc_t c_erase; /* Current erase char */
56: static cc_t c_kill; /* Current kill char */
57: static sigjmp_buf rewrite; /* Place to go when continued */
58: static sigjmp_buf intjmp; /* Place to go when interrupted */
1.1 deraadt 59: #ifndef TIOCSTI
1.5 millert 60: static int ttyset; /* We must now do erase/kill */
1.1 deraadt 61: #endif
62:
63: /*
64: * Read all relevant header fields.
65: */
66:
67: int
68: grabh(hp, gflags)
69: struct header *hp;
70: int gflags;
71: {
72: struct termios ttybuf;
73: sig_t saveint;
74: #ifndef TIOCSTI
75: sig_t savequit;
1.3 millert 76: #else
77: int extproc, flag;
1.1 deraadt 78: #endif
79: sig_t savetstp;
80: sig_t savettou;
81: sig_t savettin;
1.7 ! millert 82: int errs = 0;
1.2 deraadt 83: #ifdef __GNUC__
1.5 millert 84: /* Avoid siglongjmp clobbering */
1.3 millert 85: #ifdef TIOCSTI
1.4 millert 86: (void)&extproc;
1.3 millert 87: #endif
1.4 millert 88: (void)&saveint;
1.7 ! millert 89: (void)&errs;
1.2 deraadt 90: #endif
1.1 deraadt 91:
92: savetstp = signal(SIGTSTP, SIG_DFL);
93: savettou = signal(SIGTTOU, SIG_DFL);
94: savettin = signal(SIGTTIN, SIG_DFL);
95: errs = 0;
96: #ifndef TIOCSTI
97: ttyset = 0;
98: #endif
99: if (tcgetattr(fileno(stdin), &ttybuf) < 0) {
1.3 millert 100: warn("tcgetattr");
1.1 deraadt 101: return(-1);
102: }
103: c_erase = ttybuf.c_cc[VERASE];
104: c_kill = ttybuf.c_cc[VKILL];
105: #ifndef TIOCSTI
106: ttybuf.c_cc[VERASE] = 0;
107: ttybuf.c_cc[VKILL] = 0;
108: if ((saveint = signal(SIGINT, SIG_IGN)) == SIG_DFL)
109: signal(SIGINT, SIG_DFL);
110: if ((savequit = signal(SIGQUIT, SIG_IGN)) == SIG_DFL)
111: signal(SIGQUIT, SIG_DFL);
112: #else
1.3 millert 113: # ifdef TIOCEXT
114: extproc = ((ttybuf.c_lflag & EXTPROC) ? 1 : 0);
115: if (extproc) {
116: flag = 0;
117: if (ioctl(fileno(stdin), TIOCEXT, &flag) < 0)
118: warn("TIOCEXT: off");
119: }
120: # endif /* TIOCEXT */
1.7 ! millert 121: if (sigsetjmp(intjmp, 1)) {
! 122: errs = SIGINT;
1.1 deraadt 123: goto out;
1.7 ! millert 124: }
1.1 deraadt 125: saveint = signal(SIGINT, ttyint);
126: #endif
127: if (gflags & GTO) {
128: #ifndef TIOCSTI
129: if (!ttyset && hp->h_to != NIL)
130: ttyset++, tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
131: #endif
132: hp->h_to =
133: extract(readtty("To: ", detract(hp->h_to, 0)), GTO);
134: }
135: if (gflags & GSUBJECT) {
136: #ifndef TIOCSTI
1.5 millert 137: if (!ttyset && hp->h_subject != NULL)
1.1 deraadt 138: ttyset++, tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
139: #endif
140: hp->h_subject = readtty("Subject: ", hp->h_subject);
141: }
142: if (gflags & GCC) {
143: #ifndef TIOCSTI
144: if (!ttyset && hp->h_cc != NIL)
145: ttyset++, tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
146: #endif
147: hp->h_cc =
148: extract(readtty("Cc: ", detract(hp->h_cc, 0)), GCC);
149: }
150: if (gflags & GBCC) {
151: #ifndef TIOCSTI
152: if (!ttyset && hp->h_bcc != NIL)
153: ttyset++, tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
154: #endif
155: hp->h_bcc =
156: extract(readtty("Bcc: ", detract(hp->h_bcc, 0)), GBCC);
157: }
158: out:
159: signal(SIGTSTP, savetstp);
160: signal(SIGTTOU, savettou);
161: signal(SIGTTIN, savettin);
162: #ifndef TIOCSTI
163: ttybuf.c_cc[VERASE] = c_erase;
164: ttybuf.c_cc[VKILL] = c_kill;
165: if (ttyset)
166: tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
167: signal(SIGQUIT, savequit);
1.3 millert 168: #else
169: # ifdef TIOCEXT
170: if (extproc) {
171: flag = 1;
172: if (ioctl(fileno(stdin), TIOCEXT, &flag) < 0)
173: warn("TIOCEXT: on");
174: }
175: # endif /* TIOCEXT */
1.1 deraadt 176: #endif
177: signal(SIGINT, saveint);
178: return(errs);
179: }
180:
181: /*
182: * Read up a header from standard input.
183: * The source string has the preliminary contents to
184: * be read.
185: *
186: */
187:
188: char *
189: readtty(pr, src)
190: char pr[], src[];
191: {
192: char ch, canonb[BUFSIZ];
193: int c;
1.2 deraadt 194: char *cp, *cp2;
195: #if __GNUC__
1.5 millert 196: /* Avoid siglongjmp clobbering */
1.4 millert 197: (void)&c;
198: (void)&cp2;
1.2 deraadt 199: #endif
1.1 deraadt 200:
201: fputs(pr, stdout);
202: fflush(stdout);
1.5 millert 203: if (src != NULL && strlen(src) > BUFSIZ - 2) {
1.3 millert 204: puts("too long to edit");
1.1 deraadt 205: return(src);
206: }
207: #ifndef TIOCSTI
1.5 millert 208: if (src != NULL)
1.1 deraadt 209: cp = copy(src, canonb);
210: else
211: cp = copy("", canonb);
212: fputs(canonb, stdout);
213: fflush(stdout);
214: #else
1.5 millert 215: cp = src == NULL ? "" : src;
1.2 deraadt 216: while ((c = *cp++) != '\0') {
1.1 deraadt 217: if ((c_erase != _POSIX_VDISABLE && c == c_erase) ||
218: (c_kill != _POSIX_VDISABLE && c == c_kill)) {
219: ch = '\\';
220: ioctl(0, TIOCSTI, &ch);
221: }
222: ch = c;
223: ioctl(0, TIOCSTI, &ch);
224: }
225: cp = canonb;
226: *cp = 0;
227: #endif
228: cp2 = cp;
229: while (cp2 < canonb + BUFSIZ)
230: *cp2++ = 0;
231: cp2 = cp;
1.5 millert 232: if (sigsetjmp(rewrite, 1))
1.1 deraadt 233: goto redo;
234: signal(SIGTSTP, ttystop);
235: signal(SIGTTOU, ttystop);
236: signal(SIGTTIN, ttystop);
237: clearerr(stdin);
238: while (cp2 < canonb + BUFSIZ) {
239: c = getc(stdin);
240: if (c == EOF || c == '\n')
241: break;
242: *cp2++ = c;
243: }
244: *cp2 = 0;
245: signal(SIGTSTP, SIG_DFL);
246: signal(SIGTTOU, SIG_DFL);
247: signal(SIGTTIN, SIG_DFL);
248: if (c == EOF && ferror(stdin)) {
249: redo:
1.5 millert 250: cp = strlen(canonb) > 0 ? canonb : NULL;
1.1 deraadt 251: clearerr(stdin);
252: return(readtty(pr, cp));
253: }
254: #ifndef TIOCSTI
1.5 millert 255: if (cp == NULL || *cp == '\0')
1.1 deraadt 256: return(src);
257: cp2 = cp;
258: if (!ttyset)
1.5 millert 259: return(strlen(canonb) > 0 ? savestr(canonb) : NULL);
1.1 deraadt 260: while (*cp != '\0') {
261: c = *cp++;
262: if (c_erase != _POSIX_VDISABLE && c == c_erase) {
263: if (cp2 == canonb)
264: continue;
265: if (cp2[-1] == '\\') {
266: cp2[-1] = c;
267: continue;
268: }
269: cp2--;
270: continue;
271: }
272: if (c_kill != _POSIX_VDISABLE && c == c_kill) {
273: if (cp2 == canonb)
274: continue;
275: if (cp2[-1] == '\\') {
276: cp2[-1] = c;
277: continue;
278: }
279: cp2 = canonb;
280: continue;
281: }
282: *cp2++ = c;
283: }
284: *cp2 = '\0';
285: #endif
286: if (equal("", canonb))
1.5 millert 287: return(NULL);
1.1 deraadt 288: return(savestr(canonb));
289: }
290:
291: /*
292: * Receipt continuation.
293: */
294: void
295: ttystop(s)
296: int s;
297: {
298: sig_t old_action = signal(s, SIG_DFL);
1.2 deraadt 299: sigset_t nset;
1.1 deraadt 300:
1.2 deraadt 301: sigemptyset(&nset);
302: sigaddset(&nset, s);
1.6 millert 303: sigprocmask(SIG_UNBLOCK, &nset, NULL);
304: kill(0, s);
1.2 deraadt 305: sigprocmask(SIG_BLOCK, &nset, NULL);
1.1 deraadt 306: signal(s, old_action);
1.5 millert 307: siglongjmp(rewrite, 1);
1.1 deraadt 308: }
309:
310: /*ARGSUSED*/
311: void
312: ttyint(s)
313: int s;
314: {
1.5 millert 315: siglongjmp(intjmp, 1);
1.1 deraadt 316: }