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