xref: /original-bsd/usr.bin/mail/tty.c (revision 5998a314)
1 #
2 
3 /*
4  * Mail -- a mail program
5  *
6  * Generally useful tty stuff.
7  */
8 
9 #include "rcv.h"
10 
11 static char *SccsId = "@(#)tty.c	2.3 03/15/82";
12 
13 static	int	c_erase;		/* Current erase char */
14 static	int	c_kill;			/* Current kill char */
15 static	int	hadcont;		/* Saw continue signal */
16 static	jmp_buf	rewrite;		/* Place to go when continued */
17 #ifndef TIOCSTI
18 static	int	ttyset;			/* We must now do erase/kill */
19 #endif
20 
21 /*
22  * Read all relevant header fields.
23  */
24 
25 grabh(hp, gflags)
26 	struct header *hp;
27 {
28 	struct sgttyb ttybuf;
29 	int ttycont(), signull();
30 #ifndef TIOCSTI
31 	int (*savesigs[2])();
32 #endif
33 	int (*savecont)();
34 	register int s;
35 	int errs;
36 
37 # ifdef VMUNIX
38 	savecont = sigset(SIGCONT, signull);
39 # endif VMUNIX
40 	errs = 0;
41 #ifndef TIOCSTI
42 	ttyset = 0;
43 #endif
44 	if (gtty(fileno(stdin), &ttybuf) < 0) {
45 		perror("gtty");
46 		return(-1);
47 	}
48 	c_erase = ttybuf.sg_erase;
49 	c_kill = ttybuf.sg_kill;
50 #ifndef TIOCSTI
51 	ttybuf.sg_erase = 0;
52 	ttybuf.sg_kill = 0;
53 	for (s = SIGINT; s <= SIGQUIT; s++)
54 		if ((savesigs[s-SIGINT] = sigset(s, SIG_IGN)) == SIG_DFL)
55 			sigset(s, SIG_DFL);
56 #endif
57 	if (gflags & GTO) {
58 #ifndef TIOCSTI
59 		if (!ttyset && hp->h_to != NOSTR)
60 			ttyset++, stty(fileno(stdin), &ttybuf);
61 #endif
62 		hp->h_to = readtty("To: ", hp->h_to);
63 		if (hp->h_to != NOSTR)
64 			hp->h_seq++;
65 	}
66 	if (gflags & GSUBJECT) {
67 #ifndef TIOCSTI
68 		if (!ttyset && hp->h_subject != NOSTR)
69 			ttyset++, stty(fileno(stdin), &ttybuf);
70 #endif
71 		hp->h_subject = readtty("Subject: ", hp->h_subject);
72 		if (hp->h_subject != NOSTR)
73 			hp->h_seq++;
74 	}
75 	if (gflags & GCC) {
76 #ifndef TIOCSTI
77 		if (!ttyset && hp->h_cc != NOSTR)
78 			ttyset++, stty(fileno(stdin), &ttybuf);
79 #endif
80 		hp->h_cc = readtty("Cc: ", hp->h_cc);
81 		if (hp->h_cc != NOSTR)
82 			hp->h_seq++;
83 	}
84 	if (gflags & GBCC) {
85 #ifndef TIOCSTI
86 		if (!ttyset && hp->h_bcc != NOSTR)
87 			ttyset++, stty(fileno(stdin), &ttybuf);
88 #endif
89 		hp->h_bcc = readtty("Bcc: ", hp->h_bcc);
90 		if (hp->h_bcc != NOSTR)
91 			hp->h_seq++;
92 	}
93 # ifdef VMUNIX
94 	sigset(SIGCONT, savecont);
95 # endif VMUNIX
96 #ifndef TIOCSTI
97 	ttybuf.sg_erase = c_erase;
98 	ttybuf.sg_kill = c_kill;
99 	if (ttyset)
100 		stty(fileno(stdin), &ttybuf);
101 	for (s = SIGINT; s <= SIGQUIT; s++)
102 		sigset(s, savesigs[s-SIGINT]);
103 #endif
104 	return(errs);
105 }
106 
107 /*
108  * Read up a header from standard input.
109  * The source string has the preliminary contents to
110  * be read.
111  *
112  */
113 
114 char *
115 readtty(pr, src)
116 	char pr[], src[];
117 {
118 	char canonb[BUFSIZ];
119 	int c, ch, signull();
120 	register char *cp, *cp2;
121 
122 	fputs(pr, stdout);
123 	fflush(stdout);
124 	if (src != NOSTR && strlen(src) > BUFSIZ - 2) {
125 		printf("too long to edit\n");
126 		return(src);
127 	}
128 #ifndef TIOCSTI
129 	if (src != NOSTR)
130 		cp = copy(src, canonb);
131 	else
132 		cp = copy("", canonb);
133 	fputs(canonb, stdout);
134 	fflush(stdout);
135 #else
136 	cp = src == NOSTR ? "" : src;
137 	while (c = *cp++) {
138 		if (c == c_erase || c == c_kill) {
139 			ch = '\\';
140 			ioctl(0, TIOCSTI, &ch);
141 		}
142 		ioctl(0, TIOCSTI, &c);
143 	}
144 	cp = canonb;
145 	*cp = 0;
146 #endif
147 	cp2 = cp;
148 	while (cp2 < canonb + BUFSIZ)
149 		*cp2++ = 0;
150 	cp2 = cp;
151 	if (setjmp(rewrite))
152 		goto redo;
153 # ifdef VMUNIX
154 	sigset(SIGCONT, ttycont);
155 # endif VMUNIX
156 	while (cp2 < canonb + BUFSIZ) {
157 		c = getc(stdin);
158 		if (c == EOF || c == '\n')
159 			break;
160 		*cp2++ = c;
161 	}
162 	*cp2 = 0;
163 # ifdef VMUNIX
164 	sigset(SIGCONT, signull);
165 # endif VMUNIX
166 	if (c == EOF && ferror(stdin) && hadcont) {
167 redo:
168 		hadcont = 0;
169 		cp = strlen(canonb) > 0 ? canonb : NOSTR;
170 		clearerr(stdin);
171 		return(readtty(pr, cp));
172 	}
173 #ifndef TIOCSTI
174 	if (cp == NOSTR || *cp == '\0')
175 		return(src);
176 	cp2 = cp;
177 	if (!ttyset)
178 		return(strlen(canonb) > 0 ? savestr(canonb) : NOSTR);
179 	while (*cp != '\0') {
180 		c = *cp++;
181 		if (c == c_erase) {
182 			if (cp2 == canonb)
183 				continue;
184 			if (cp2[-1] == '\\') {
185 				cp2[-1] = c;
186 				continue;
187 			}
188 			cp2--;
189 			continue;
190 		}
191 		if (c == c_kill) {
192 			if (cp2 == canonb)
193 				continue;
194 			if (cp2[-1] == '\\') {
195 				cp2[-1] = c;
196 				continue;
197 			}
198 			cp2 = canonb;
199 			continue;
200 		}
201 		*cp2++ = c;
202 	}
203 	*cp2 = '\0';
204 #endif
205 	if (equal("", canonb))
206 		return(NOSTR);
207 	return(savestr(canonb));
208 }
209 
210 # ifdef VMUNIX
211 /*
212  * Receipt continuation.
213  */
214 ttycont(s)
215 {
216 
217 	hadcont++;
218 	sigrelse(SIGCONT);
219 	longjmp(rewrite, 1);
220 }
221 # endif VMUNIX
222 
223 /*
224  * Null routine to satisfy
225  * silly system bug that denies us holding SIGCONT
226  */
227 signull(s)
228 {}
229