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