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