Annotation of src/usr.bin/mail/tty.c, Revision 1.11
1.11 ! millert 1: /* $OpenBSD: tty.c,v 1.10 1997/11/13 03:30:21 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.11 ! millert 41: static char rcsid[] = "$OpenBSD: tty.c,v 1.10 1997/11/13 03:30:21 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.10 millert 76: #else
77: # ifdef TIOCEXT
78: int extproc, flag;
79: #endif /* TIOCEXT */
1.1 deraadt 80: #endif
81: sig_t savetstp;
82: sig_t savettou;
83: sig_t savettin;
1.7 millert 84: int errs = 0;
1.2 deraadt 85: #ifdef __GNUC__
1.5 millert 86: /* Avoid siglongjmp clobbering */
1.4 millert 87: (void)&saveint;
1.7 millert 88: (void)&errs;
1.11 ! millert 89: # ifdef TIOCEXT
! 90: (void)&extproc;
! 91: #endif /* TIOCEXT */
1.2 deraadt 92: #endif
1.1 deraadt 93:
94: savetstp = signal(SIGTSTP, SIG_DFL);
95: savettou = signal(SIGTTOU, SIG_DFL);
96: savettin = signal(SIGTTIN, SIG_DFL);
97: errs = 0;
98: #ifndef TIOCSTI
99: ttyset = 0;
100: #endif
101: if (tcgetattr(fileno(stdin), &ttybuf) < 0) {
1.3 millert 102: warn("tcgetattr");
1.1 deraadt 103: return(-1);
104: }
105: c_erase = ttybuf.c_cc[VERASE];
106: c_kill = ttybuf.c_cc[VKILL];
107: #ifndef TIOCSTI
108: ttybuf.c_cc[VERASE] = 0;
109: ttybuf.c_cc[VKILL] = 0;
110: if ((saveint = signal(SIGINT, SIG_IGN)) == SIG_DFL)
1.8 millert 111: (void)signal(SIGINT, SIG_DFL);
1.1 deraadt 112: if ((savequit = signal(SIGQUIT, SIG_IGN)) == SIG_DFL)
1.8 millert 113: (void)signal(SIGQUIT, SIG_DFL);
1.1 deraadt 114: #else
1.10 millert 115: # ifdef TIOCEXT
116: extproc = ((ttybuf.c_lflag & EXTPROC) ? 1 : 0);
117: if (extproc) {
118: flag = 0;
119: if (ioctl(fileno(stdin), TIOCEXT, &flag) < 0)
120: warn("TIOCEXT: off");
121: }
122: # endif /* TIOCEXT */
1.7 millert 123: if (sigsetjmp(intjmp, 1)) {
124: errs = SIGINT;
1.1 deraadt 125: goto out;
1.7 millert 126: }
1.1 deraadt 127: saveint = signal(SIGINT, ttyint);
128: #endif
129: if (gflags & GTO) {
130: #ifndef TIOCSTI
131: if (!ttyset && hp->h_to != NIL)
132: ttyset++, tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
133: #endif
134: hp->h_to =
135: extract(readtty("To: ", detract(hp->h_to, 0)), GTO);
136: }
137: if (gflags & GSUBJECT) {
138: #ifndef TIOCSTI
1.5 millert 139: if (!ttyset && hp->h_subject != NULL)
1.1 deraadt 140: ttyset++, tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
141: #endif
142: hp->h_subject = readtty("Subject: ", hp->h_subject);
143: }
144: if (gflags & GCC) {
145: #ifndef TIOCSTI
146: if (!ttyset && hp->h_cc != NIL)
147: ttyset++, tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
148: #endif
149: hp->h_cc =
150: extract(readtty("Cc: ", detract(hp->h_cc, 0)), GCC);
151: }
152: if (gflags & GBCC) {
153: #ifndef TIOCSTI
154: if (!ttyset && hp->h_bcc != NIL)
155: ttyset++, tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
156: #endif
157: hp->h_bcc =
158: extract(readtty("Bcc: ", detract(hp->h_bcc, 0)), GBCC);
159: }
160: out:
1.8 millert 161: (void)signal(SIGTSTP, savetstp);
162: (void)signal(SIGTTOU, savettou);
163: (void)signal(SIGTTIN, savettin);
1.1 deraadt 164: #ifndef TIOCSTI
165: ttybuf.c_cc[VERASE] = c_erase;
166: ttybuf.c_cc[VKILL] = c_kill;
167: if (ttyset)
168: tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
1.8 millert 169: (void)signal(SIGQUIT, savequit);
1.10 millert 170: #else
171: # ifdef TIOCEXT
172: if (extproc) {
173: flag = 1;
174: if (ioctl(fileno(stdin), TIOCEXT, &flag) < 0)
175: warn("TIOCEXT: on");
176: }
177: # endif /* TIOCEXT */
1.1 deraadt 178: #endif
1.8 millert 179: (void)signal(SIGINT, saveint);
1.1 deraadt 180: return(errs);
181: }
182:
183: /*
184: * Read up a header from standard input.
185: * The source string has the preliminary contents to
186: * be read.
187: *
188: */
189:
190: char *
191: readtty(pr, src)
192: char pr[], src[];
193: {
194: char ch, canonb[BUFSIZ];
195: int c;
1.2 deraadt 196: char *cp, *cp2;
197: #if __GNUC__
1.5 millert 198: /* Avoid siglongjmp clobbering */
1.4 millert 199: (void)&c;
200: (void)&cp2;
1.2 deraadt 201: #endif
1.1 deraadt 202:
203: fputs(pr, stdout);
204: fflush(stdout);
1.5 millert 205: if (src != NULL && strlen(src) > BUFSIZ - 2) {
1.3 millert 206: puts("too long to edit");
1.1 deraadt 207: return(src);
208: }
209: #ifndef TIOCSTI
1.5 millert 210: if (src != NULL)
1.1 deraadt 211: cp = copy(src, canonb);
212: else
213: cp = copy("", canonb);
214: fputs(canonb, stdout);
215: fflush(stdout);
216: #else
1.5 millert 217: cp = src == NULL ? "" : src;
1.2 deraadt 218: while ((c = *cp++) != '\0') {
1.1 deraadt 219: if ((c_erase != _POSIX_VDISABLE && c == c_erase) ||
220: (c_kill != _POSIX_VDISABLE && c == c_kill)) {
221: ch = '\\';
222: ioctl(0, TIOCSTI, &ch);
223: }
224: ch = c;
225: ioctl(0, TIOCSTI, &ch);
226: }
227: cp = canonb;
228: *cp = 0;
229: #endif
230: cp2 = cp;
231: while (cp2 < canonb + BUFSIZ)
232: *cp2++ = 0;
233: cp2 = cp;
1.5 millert 234: if (sigsetjmp(rewrite, 1))
1.1 deraadt 235: goto redo;
1.8 millert 236: (void)signal(SIGTSTP, ttystop);
237: (void)signal(SIGTTOU, ttystop);
238: (void)signal(SIGTTIN, ttystop);
1.1 deraadt 239: clearerr(stdin);
240: while (cp2 < canonb + BUFSIZ) {
241: c = getc(stdin);
242: if (c == EOF || c == '\n')
243: break;
244: *cp2++ = c;
245: }
246: *cp2 = 0;
1.8 millert 247: (void)signal(SIGTSTP, SIG_DFL);
248: (void)signal(SIGTTOU, SIG_DFL);
249: (void)signal(SIGTTIN, SIG_DFL);
1.1 deraadt 250: if (c == EOF && ferror(stdin)) {
251: redo:
1.5 millert 252: cp = strlen(canonb) > 0 ? canonb : NULL;
1.1 deraadt 253: clearerr(stdin);
254: return(readtty(pr, cp));
255: }
256: #ifndef TIOCSTI
1.5 millert 257: if (cp == NULL || *cp == '\0')
1.1 deraadt 258: return(src);
259: cp2 = cp;
260: if (!ttyset)
1.5 millert 261: return(strlen(canonb) > 0 ? savestr(canonb) : NULL);
1.1 deraadt 262: while (*cp != '\0') {
263: c = *cp++;
264: if (c_erase != _POSIX_VDISABLE && c == c_erase) {
265: if (cp2 == canonb)
266: continue;
267: if (cp2[-1] == '\\') {
268: cp2[-1] = c;
269: continue;
270: }
271: cp2--;
272: continue;
273: }
274: if (c_kill != _POSIX_VDISABLE && c == c_kill) {
275: if (cp2 == canonb)
276: continue;
277: if (cp2[-1] == '\\') {
278: cp2[-1] = c;
279: continue;
280: }
281: cp2 = canonb;
282: continue;
283: }
284: *cp2++ = c;
285: }
286: *cp2 = '\0';
287: #endif
288: if (equal("", canonb))
1.5 millert 289: return(NULL);
1.1 deraadt 290: return(savestr(canonb));
291: }
292:
293: /*
294: * Receipt continuation.
295: */
296: void
297: ttystop(s)
298: int s;
299: {
300: sig_t old_action = signal(s, SIG_DFL);
1.2 deraadt 301: sigset_t nset;
1.1 deraadt 302:
1.8 millert 303: (void)sigemptyset(&nset);
304: (void)sigaddset(&nset, s);
305: (void)sigprocmask(SIG_UNBLOCK, &nset, NULL);
306: (void)kill(0, s);
307: (void)sigprocmask(SIG_BLOCK, &nset, NULL);
308: (void)signal(s, old_action);
1.5 millert 309: siglongjmp(rewrite, 1);
1.1 deraadt 310: }
311:
312: /*ARGSUSED*/
313: void
314: ttyint(s)
315: int s;
316: {
1.5 millert 317: siglongjmp(intjmp, 1);
1.1 deraadt 318: }