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