Annotation of src/usr.bin/mail/tty.c, Revision 1.16
1.16 ! millert 1: /* $OpenBSD: tty.c,v 1.15 2001/11/21 20:41:56 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.14 millert 39: static const char sccsid[] = "@(#)tty.c 8.2 (Berkeley) 4/20/95";
1.2 deraadt 40: #else
1.16 ! millert 41: static const char rcsid[] = "$OpenBSD: tty.c,v 1.15 2001/11/21 20:41:56 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.13 millert 54: #include <errno.h>
1.1 deraadt 55:
1.5 millert 56: static cc_t c_erase; /* Current erase char */
57: static cc_t c_kill; /* Current kill char */
1.1 deraadt 58: #ifndef TIOCSTI
1.5 millert 59: static int ttyset; /* We must now do erase/kill */
1.1 deraadt 60: #endif
1.13 millert 61: static volatile sig_atomic_t ttysignal; /* Interrupted by a signal? */
1.1 deraadt 62:
63: /*
64: * Read all relevant header fields.
65: */
66: int
1.14 millert 67: grabh(struct header *hp, int gflags)
1.1 deraadt 68: {
69: struct termios ttybuf;
70: #ifndef TIOCSTI
1.13 millert 71: struct sigaction savequit;
1.10 millert 72: #else
73: # ifdef TIOCEXT
1.13 millert 74: int extproc;
1.12 millert 75: int flag;
76: # endif /* TIOCEXT */
1.1 deraadt 77: #endif
1.13 millert 78: struct sigaction savetstp;
79: struct sigaction savettou;
80: struct sigaction savettin;
81: struct sigaction act;
82: char *s;
83: int error;
84:
85: sigemptyset(&act.sa_mask);
86: act.sa_flags = SA_RESTART;
87: act.sa_handler = SIG_DFL;
88: (void)sigaction(SIGTSTP, &act, &savetstp);
89: (void)sigaction(SIGTTOU, &act, &savettou);
90: (void)sigaction(SIGTTIN, &act, &savettin);
91: error = 1;
1.1 deraadt 92: #ifndef TIOCSTI
93: ttyset = 0;
94: #endif
95: if (tcgetattr(fileno(stdin), &ttybuf) < 0) {
1.3 millert 96: warn("tcgetattr");
1.1 deraadt 97: return(-1);
98: }
99: c_erase = ttybuf.c_cc[VERASE];
100: c_kill = ttybuf.c_cc[VKILL];
101: #ifndef TIOCSTI
102: ttybuf.c_cc[VERASE] = 0;
103: ttybuf.c_cc[VKILL] = 0;
1.13 millert 104: act.sa_handler = SIG_IGN;
105: if (sigaction(SIGQUIT, &act, &savequit) == 0 &&
106: savequit.sa_handler == SIG_DFL)
107: (void)sigaction(SIGQUIT, &savequit, NULL);
1.1 deraadt 108: #else
1.10 millert 109: # ifdef TIOCEXT
110: extproc = ((ttybuf.c_lflag & EXTPROC) ? 1 : 0);
111: if (extproc) {
112: flag = 0;
113: if (ioctl(fileno(stdin), TIOCEXT, &flag) < 0)
114: warn("TIOCEXT: off");
115: }
116: # endif /* TIOCEXT */
1.1 deraadt 117: #endif
118: if (gflags & GTO) {
119: #ifndef TIOCSTI
1.14 millert 120: if (!ttyset && hp->h_to != NULL)
1.1 deraadt 121: ttyset++, tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
122: #endif
1.13 millert 123: s = readtty("To: ", detract(hp->h_to, 0));
124: if (s == NULL)
125: goto out;
126: hp->h_to = extract(s, GTO);
1.1 deraadt 127: }
128: if (gflags & GSUBJECT) {
129: #ifndef TIOCSTI
1.5 millert 130: if (!ttyset && hp->h_subject != NULL)
1.1 deraadt 131: ttyset++, tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
132: #endif
1.13 millert 133: s = readtty("Subject: ", hp->h_subject);
134: if (s == NULL)
135: goto out;
136: hp->h_subject = s;
1.1 deraadt 137: }
138: if (gflags & GCC) {
139: #ifndef TIOCSTI
1.14 millert 140: if (!ttyset && hp->h_cc != NULL)
1.1 deraadt 141: ttyset++, tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
142: #endif
1.13 millert 143: s = readtty("Cc: ", detract(hp->h_cc, 0));
144: if (s == NULL)
145: goto out;
146: hp->h_cc = extract(s, GCC);
1.1 deraadt 147: }
148: if (gflags & GBCC) {
149: #ifndef TIOCSTI
1.14 millert 150: if (!ttyset && hp->h_bcc != NULL)
1.1 deraadt 151: ttyset++, tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
152: #endif
1.13 millert 153: s = readtty("Bcc: ", detract(hp->h_bcc, 0));
154: if (s == NULL)
155: goto out;
156: hp->h_bcc = extract(s, GBCC);
1.1 deraadt 157: }
1.13 millert 158: error = 0;
1.1 deraadt 159: out:
1.13 millert 160: (void)sigaction(SIGTSTP, &savetstp, NULL);
161: (void)sigaction(SIGTTOU, &savettou, NULL);
162: (void)sigaction(SIGTTIN, &savettin, NULL);
1.1 deraadt 163: #ifndef TIOCSTI
164: ttybuf.c_cc[VERASE] = c_erase;
165: ttybuf.c_cc[VKILL] = c_kill;
166: if (ttyset)
167: tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
1.13 millert 168: (void)sigaction(SIGQUIT, &savequit, NULL);
1.10 millert 169: #else
170: # ifdef TIOCEXT
171: if (extproc) {
172: flag = 1;
173: if (ioctl(fileno(stdin), TIOCEXT, &flag) < 0)
174: warn("TIOCEXT: on");
175: }
176: # endif /* TIOCEXT */
1.1 deraadt 177: #endif
1.13 millert 178: return(error);
1.1 deraadt 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: char *
1.14 millert 188: readtty(char *pr, char *src)
1.1 deraadt 189: {
1.16 ! millert 190: struct sigaction act, saveint;
1.1 deraadt 191: char ch, canonb[BUFSIZ];
1.13 millert 192: char *cp, *cp2;
1.14 millert 193: sigset_t oset;
1.13 millert 194: int c;
1.1 deraadt 195:
196: fputs(pr, stdout);
197: fflush(stdout);
1.5 millert 198: if (src != NULL && strlen(src) > BUFSIZ - 2) {
1.3 millert 199: puts("too long to edit");
1.1 deraadt 200: return(src);
201: }
202: #ifndef TIOCSTI
1.5 millert 203: if (src != NULL)
1.15 millert 204: cp = copy(src, canonb); /* safe, bounds checked above */
1.1 deraadt 205: else
206: cp = copy("", canonb);
207: fputs(canonb, stdout);
208: fflush(stdout);
209: #else
1.5 millert 210: cp = src == NULL ? "" : src;
1.2 deraadt 211: while ((c = *cp++) != '\0') {
1.1 deraadt 212: if ((c_erase != _POSIX_VDISABLE && c == c_erase) ||
213: (c_kill != _POSIX_VDISABLE && c == c_kill)) {
214: ch = '\\';
215: ioctl(0, TIOCSTI, &ch);
216: }
217: ch = c;
218: ioctl(0, TIOCSTI, &ch);
219: }
220: cp = canonb;
221: *cp = 0;
222: #endif
223: cp2 = cp;
224: while (cp2 < canonb + BUFSIZ)
225: *cp2++ = 0;
226: cp2 = cp;
1.13 millert 227: sigemptyset(&act.sa_mask);
228: act.sa_flags = 0; /* Note: will not restart syscalls */
229: act.sa_handler = ttyint;
1.16 ! millert 230: (void)sigaction(SIGINT, &act, &saveint);
1.13 millert 231: act.sa_handler = ttystop;
232: (void)sigaction(SIGTSTP, &act, NULL);
233: (void)sigaction(SIGTTOU, &act, NULL);
234: (void)sigaction(SIGTTIN, &act, NULL);
235: (void)sigprocmask(SIG_UNBLOCK, &intset, &oset);
1.1 deraadt 236: clearerr(stdin);
237: while (cp2 < canonb + BUFSIZ) {
238: c = getc(stdin);
1.13 millert 239: switch (ttysignal) {
240: case SIGINT:
241: ttysignal = 0;
242: cp2 = NULL;
243: c = EOF;
244: /* FALLTHROUGH */
245: case 0:
246: break;
247: default:
248: ttysignal = 0;
249: goto redo;
250: }
1.1 deraadt 251: if (c == EOF || c == '\n')
252: break;
253: *cp2++ = c;
254: }
1.13 millert 255: act.sa_handler = SIG_DFL;
256: sigemptyset(&act.sa_mask);
257: act.sa_flags = SA_RESTART;
258: (void)sigprocmask(SIG_SETMASK, &oset, NULL);
259: (void)sigaction(SIGTSTP, &act, NULL);
260: (void)sigaction(SIGTTOU, &act, NULL);
261: (void)sigaction(SIGTTIN, &act, NULL);
1.16 ! millert 262: (void)sigaction(SIGINT, &saveint, NULL);
1.13 millert 263: if (cp2 == NULL)
264: return(NULL); /* user hit ^C */
265: *cp2 = '\0';
1.1 deraadt 266: if (c == EOF && ferror(stdin)) {
267: redo:
1.5 millert 268: cp = strlen(canonb) > 0 ? canonb : NULL;
1.1 deraadt 269: clearerr(stdin);
1.13 millert 270: /* XXX - make iterative, not recursive */
1.1 deraadt 271: return(readtty(pr, cp));
272: }
273: #ifndef TIOCSTI
1.5 millert 274: if (cp == NULL || *cp == '\0')
1.1 deraadt 275: return(src);
276: cp2 = cp;
277: if (!ttyset)
1.5 millert 278: return(strlen(canonb) > 0 ? savestr(canonb) : NULL);
1.1 deraadt 279: while (*cp != '\0') {
280: c = *cp++;
281: if (c_erase != _POSIX_VDISABLE && c == c_erase) {
282: if (cp2 == canonb)
283: continue;
284: if (cp2[-1] == '\\') {
285: cp2[-1] = c;
286: continue;
287: }
288: cp2--;
289: continue;
290: }
291: if (c_kill != _POSIX_VDISABLE && c == c_kill) {
292: if (cp2 == canonb)
293: continue;
294: if (cp2[-1] == '\\') {
295: cp2[-1] = c;
296: continue;
297: }
298: cp2 = canonb;
299: continue;
300: }
301: *cp2++ = c;
302: }
303: *cp2 = '\0';
304: #endif
305: if (equal("", canonb))
1.13 millert 306: return("");
1.1 deraadt 307: return(savestr(canonb));
308: }
309:
310: /*
311: * Receipt continuation.
312: */
313: void
1.14 millert 314: ttystop(int s)
1.1 deraadt 315: {
1.13 millert 316: struct sigaction act, oact;
1.2 deraadt 317: sigset_t nset;
1.13 millert 318: int save_errno;
1.1 deraadt 319:
1.13 millert 320: /*
321: * Save old handler and set to default.
322: * Unblock receipt of 's' and then resend it.
323: */
324: save_errno = errno;
325: (void)sigemptyset(&act.sa_mask);
326: act.sa_flags = SA_RESTART;
327: act.sa_handler = SIG_DFL;
328: (void)sigaction(s, &act, &oact);
1.8 millert 329: (void)sigemptyset(&nset);
330: (void)sigaddset(&nset, s);
331: (void)sigprocmask(SIG_UNBLOCK, &nset, NULL);
332: (void)kill(0, s);
333: (void)sigprocmask(SIG_BLOCK, &nset, NULL);
1.13 millert 334: (void)sigaction(s, &oact, NULL);
335: ttysignal = s;
336: errno = save_errno;
1.1 deraadt 337: }
338:
339: /*ARGSUSED*/
340: void
1.14 millert 341: ttyint(int s)
1.1 deraadt 342: {
1.13 millert 343:
344: ttysignal = s;
1.1 deraadt 345: }