|
|
1.1 root 1: /*
2: * Copyright (c) 1980 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted
6: * provided that: (1) source distributions retain this entire copyright
7: * notice and comment, and (2) distributions including binaries display
8: * the following acknowledgement: ``This product includes software
9: * developed by the University of California, Berkeley and its contributors''
10: * in the documentation or other materials provided with the distribution
11: * and in all advertising materials mentioning features or use of this
12: * software. Neither the name of the University nor the names of its
13: * contributors may be used to endorse or promote products derived
14: * from this software without specific prior written permission.
15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18: */
19:
20: #ifndef lint
21: static char sccsid[] = "@(#)tty.c 5.11 (Berkeley) 6/1/90";
22: #endif /* not lint */
23:
24: /*
25: * Mail -- a mail program
26: *
27: * Generally useful tty stuff.
28: */
29:
30: #include "rcv.h"
31:
32: static int c_erase; /* Current erase char */
33: static int c_kill; /* Current kill char */
34: static jmp_buf rewrite; /* Place to go when continued */
35: static jmp_buf intjmp; /* Place to go when interrupted */
36: #ifndef TIOCSTI
37: static int ttyset; /* We must now do erase/kill */
38: #endif
39:
40: /*
41: * Read all relevant header fields.
42: */
43:
44: grabh(hp, gflags)
45: struct header *hp;
46: {
47: struct sgttyb ttybuf;
48: sig_t saveint;
49: #ifndef TIOCSTI
50: sig_t savequit;
51: #endif
52: sig_t savetstp;
53: sig_t savettou;
54: sig_t savettin;
55: int errs;
56: int ttyint();
57:
58: savetstp = signal(SIGTSTP, SIG_DFL);
59: savettou = signal(SIGTTOU, SIG_DFL);
60: savettin = signal(SIGTTIN, SIG_DFL);
61: errs = 0;
62: #ifndef TIOCSTI
63: ttyset = 0;
64: #endif
65: if (ioctl(fileno(stdin), TIOCGETP, &ttybuf) < 0) {
66: perror("gtty");
67: return(-1);
68: }
69: c_erase = ttybuf.sg_erase;
70: c_kill = ttybuf.sg_kill;
71: #ifndef TIOCSTI
72: ttybuf.sg_erase = 0;
73: ttybuf.sg_kill = 0;
74: if ((saveint = signal(SIGINT, SIG_IGN)) == SIG_DFL)
75: signal(SIGINT, SIG_DFL);
76: if ((savequit = signal(SIGQUIT, SIG_IGN)) == SIG_DFL)
77: signal(SIGQUIT, SIG_DFL);
78: #else
79: if (setjmp(intjmp))
80: goto out;
81: saveint = signal(SIGINT, ttyint);
82: #endif
83: if (gflags & GTO) {
84: #ifndef TIOCSTI
85: if (!ttyset && hp->h_to != NIL)
86: ttyset++, stty(fileno(stdin), &ttybuf);
87: #endif
88: hp->h_to =
89: extract(readtty("To: ", detract(hp->h_to, 0)), GTO);
90: }
91: if (gflags & GSUBJECT) {
92: #ifndef TIOCSTI
93: if (!ttyset && hp->h_subject != NOSTR)
94: ttyset++, stty(fileno(stdin), &ttybuf);
95: #endif
96: hp->h_subject = readtty("Subject: ", hp->h_subject);
97: }
98: if (gflags & GCC) {
99: #ifndef TIOCSTI
100: if (!ttyset && hp->h_cc != NIL)
101: ttyset++, stty(fileno(stdin), &ttybuf);
102: #endif
103: hp->h_cc =
104: extract(readtty("Cc: ", detract(hp->h_cc, 0)), GCC);
105: }
106: if (gflags & GBCC) {
107: #ifndef TIOCSTI
108: if (!ttyset && hp->h_bcc != NIL)
109: ttyset++, stty(fileno(stdin), &ttybuf);
110: #endif
111: hp->h_bcc =
112: extract(readtty("Bcc: ", detract(hp->h_bcc, 0)), GBCC);
113: }
114: out:
115: signal(SIGTSTP, savetstp);
116: signal(SIGTTOU, savettou);
117: signal(SIGTTIN, savettin);
118: #ifndef TIOCSTI
119: ttybuf.sg_erase = c_erase;
120: ttybuf.sg_kill = c_kill;
121: if (ttyset)
122: stty(fileno(stdin), &ttybuf);
123: signal(SIGQUIT, savequit);
124: #endif
125: signal(SIGINT, saveint);
126: return(errs);
127: }
128:
129: /*
130: * Read up a header from standard input.
131: * The source string has the preliminary contents to
132: * be read.
133: *
134: */
135:
136: char *
137: readtty(pr, src)
138: char pr[], src[];
139: {
140: char ch, canonb[BUFSIZ];
141: int c;
142: register char *cp, *cp2;
143: int ttystop();
144:
145: fputs(pr, stdout);
146: fflush(stdout);
147: if (src != NOSTR && strlen(src) > BUFSIZ - 2) {
148: printf("too long to edit\n");
149: return(src);
150: }
151: #ifndef TIOCSTI
152: if (src != NOSTR)
153: cp = copy(src, canonb);
154: else
155: cp = copy("", canonb);
156: fputs(canonb, stdout);
157: fflush(stdout);
158: #else
159: cp = src == NOSTR ? "" : src;
160: while (c = *cp++) {
161: if (c == c_erase || c == c_kill) {
162: ch = '\\';
163: ioctl(0, TIOCSTI, &ch);
164: }
165: ch = c;
166: ioctl(0, TIOCSTI, &ch);
167: }
168: cp = canonb;
169: *cp = 0;
170: #endif
171: cp2 = cp;
172: while (cp2 < canonb + BUFSIZ)
173: *cp2++ = 0;
174: cp2 = cp;
175: if (setjmp(rewrite))
176: goto redo;
177: signal(SIGTSTP, ttystop);
178: signal(SIGTTOU, ttystop);
179: signal(SIGTTIN, ttystop);
180: clearerr(stdin);
181: while (cp2 < canonb + BUFSIZ) {
182: c = getc(stdin);
183: if (c == EOF || c == '\n')
184: break;
185: *cp2++ = c;
186: }
187: *cp2 = 0;
188: signal(SIGTSTP, SIG_DFL);
189: signal(SIGTTOU, SIG_DFL);
190: signal(SIGTTIN, SIG_DFL);
191: if (c == EOF && ferror(stdin)) {
192: redo:
193: cp = strlen(canonb) > 0 ? canonb : NOSTR;
194: clearerr(stdin);
195: return(readtty(pr, cp));
196: }
197: #ifndef TIOCSTI
198: if (cp == NOSTR || *cp == '\0')
199: return(src);
200: cp2 = cp;
201: if (!ttyset)
202: return(strlen(canonb) > 0 ? savestr(canonb) : NOSTR);
203: while (*cp != '\0') {
204: c = *cp++;
205: if (c == c_erase) {
206: if (cp2 == canonb)
207: continue;
208: if (cp2[-1] == '\\') {
209: cp2[-1] = c;
210: continue;
211: }
212: cp2--;
213: continue;
214: }
215: if (c == c_kill) {
216: if (cp2 == canonb)
217: continue;
218: if (cp2[-1] == '\\') {
219: cp2[-1] = c;
220: continue;
221: }
222: cp2 = canonb;
223: continue;
224: }
225: *cp2++ = c;
226: }
227: *cp2 = '\0';
228: #endif
229: if (equal("", canonb))
230: return(NOSTR);
231: return(savestr(canonb));
232: }
233:
234: /*
235: * Receipt continuation.
236: */
237: ttystop(s)
238: {
239: sig_t old_action = signal(s, SIG_DFL);
240:
241: sigsetmask(sigblock(0) & ~sigmask(s));
242: kill(0, s);
243: sigblock(sigmask(s));
244: signal(s, old_action);
245: longjmp(rewrite, 1);
246: }
247:
248: /*ARGSUSED*/
249: ttyint(s)
250: {
251:
252: longjmp(intjmp, 1);
253: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.