handle ~ in expand() without running a shell, better error messages
[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
KB
18#ifndef lint
19static char sccsid[] = "@(#)tty.c 5.7 (Berkeley) %G%";
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
KS
32static int hadcont; /* Saw continue signal */
33static jmp_buf rewrite; /* Place to go when continued */
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;
46#ifndef TIOCSTI
828615a1 47 int (*saveint)(), (*savequit)();
80741a9f 48#endif
1b38f4e9 49 int (*savecont)();
80741a9f
KS
50 int errs;
51
828615a1 52 savecont = signal(SIGCONT, SIG_DFL);
80741a9f
KS
53 errs = 0;
54#ifndef TIOCSTI
55 ttyset = 0;
56#endif
57 if (gtty(fileno(stdin), &ttybuf) < 0) {
58 perror("gtty");
59 return(-1);
60 }
61 c_erase = ttybuf.sg_erase;
62 c_kill = ttybuf.sg_kill;
63#ifndef TIOCSTI
64 ttybuf.sg_erase = 0;
65 ttybuf.sg_kill = 0;
828615a1
EW
66 if ((saveint = signal(SIGINT, SIG_IGN)) == SIG_DFL)
67 signal(SIGINT, SIG_DFL);
68 if ((savequit = signal(SIGQUIT, SIG_IGN)) == SIG_DFL)
69 signal(SIGQUIT, SIG_DFL);
80741a9f
KS
70#endif
71 if (gflags & GTO) {
72#ifndef TIOCSTI
3d6f01e5 73 if (!ttyset && hp->h_to != NIL)
80741a9f
KS
74 ttyset++, stty(fileno(stdin), &ttybuf);
75#endif
3d6f01e5
EW
76 hp->h_to =
77 extract(readtty("To: ", detract(hp->h_to, 0)), GTO);
80741a9f
KS
78 }
79 if (gflags & GSUBJECT) {
80#ifndef TIOCSTI
81 if (!ttyset && hp->h_subject != NOSTR)
82 ttyset++, stty(fileno(stdin), &ttybuf);
83#endif
84 hp->h_subject = readtty("Subject: ", hp->h_subject);
80741a9f
KS
85 }
86 if (gflags & GCC) {
87#ifndef TIOCSTI
3d6f01e5 88 if (!ttyset && hp->h_cc != NIL)
80741a9f
KS
89 ttyset++, stty(fileno(stdin), &ttybuf);
90#endif
3d6f01e5
EW
91 hp->h_cc =
92 extract(readtty("Cc: ", detract(hp->h_cc, 0)), GCC);
80741a9f
KS
93 }
94 if (gflags & GBCC) {
95#ifndef TIOCSTI
3d6f01e5 96 if (!ttyset && hp->h_bcc != NIL)
80741a9f
KS
97 ttyset++, stty(fileno(stdin), &ttybuf);
98#endif
3d6f01e5
EW
99 hp->h_bcc =
100 extract(readtty("Bcc: ", detract(hp->h_bcc, 0)), GBCC);
80741a9f 101 }
828615a1 102 signal(SIGCONT, savecont);
80741a9f
KS
103#ifndef TIOCSTI
104 ttybuf.sg_erase = c_erase;
105 ttybuf.sg_kill = c_kill;
106 if (ttyset)
107 stty(fileno(stdin), &ttybuf);
828615a1
EW
108 signal(SIGINT, saveint);
109 signal(SIGQUIT, savequit);
80741a9f
KS
110#endif
111 return(errs);
112}
113
114/*
115 * Read up a header from standard input.
116 * The source string has the preliminary contents to
117 * be read.
118 *
119 */
120
121char *
122readtty(pr, src)
123 char pr[], src[];
124{
338c4a5d 125 char ch, canonb[BUFSIZ];
828615a1 126 int c;
80741a9f 127 register char *cp, *cp2;
001d60ad 128 int ttycont();
80741a9f 129
1b38f4e9
KS
130 fputs(pr, stdout);
131 fflush(stdout);
80741a9f
KS
132 if (src != NOSTR && strlen(src) > BUFSIZ - 2) {
133 printf("too long to edit\n");
134 return(src);
135 }
136#ifndef TIOCSTI
137 if (src != NOSTR)
138 cp = copy(src, canonb);
139 else
140 cp = copy("", canonb);
141 fputs(canonb, stdout);
142 fflush(stdout);
143#else
1b38f4e9
KS
144 cp = src == NOSTR ? "" : src;
145 while (c = *cp++) {
80741a9f
KS
146 if (c == c_erase || c == c_kill) {
147 ch = '\\';
148 ioctl(0, TIOCSTI, &ch);
149 }
338c4a5d
SL
150 ch = c;
151 ioctl(0, TIOCSTI, &ch);
80741a9f
KS
152 }
153 cp = canonb;
419b1e01 154 *cp = 0;
80741a9f 155#endif
1b38f4e9
KS
156 cp2 = cp;
157 while (cp2 < canonb + BUFSIZ)
158 *cp2++ = 0;
159 cp2 = cp;
160 if (setjmp(rewrite))
161 goto redo;
828615a1 162 signal(SIGCONT, ttycont);
7bfe8da7 163 clearerr(stdin);
1b38f4e9
KS
164 while (cp2 < canonb + BUFSIZ) {
165 c = getc(stdin);
166 if (c == EOF || c == '\n')
167 break;
168 *cp2++ = c;
169 }
170 *cp2 = 0;
828615a1 171 signal(SIGCONT, SIG_DFL);
1b38f4e9
KS
172 if (c == EOF && ferror(stdin) && hadcont) {
173redo:
174 hadcont = 0;
175 cp = strlen(canonb) > 0 ? canonb : NOSTR;
176 clearerr(stdin);
177 return(readtty(pr, cp));
178 }
80741a9f 179#ifndef TIOCSTI
ea394d88 180 if (cp == NOSTR || *cp == '\0')
80741a9f 181 return(src);
ea394d88 182 cp2 = cp;
80741a9f
KS
183 if (!ttyset)
184 return(strlen(canonb) > 0 ? savestr(canonb) : NOSTR);
185 while (*cp != '\0') {
186 c = *cp++;
187 if (c == c_erase) {
188 if (cp2 == canonb)
189 continue;
190 if (cp2[-1] == '\\') {
191 cp2[-1] = c;
192 continue;
193 }
194 cp2--;
195 continue;
196 }
197 if (c == c_kill) {
198 if (cp2 == canonb)
199 continue;
200 if (cp2[-1] == '\\') {
201 cp2[-1] = c;
202 continue;
203 }
204 cp2 = canonb;
205 continue;
206 }
207 *cp2++ = c;
208 }
209 *cp2 = '\0';
210#endif
211 if (equal("", canonb))
212 return(NOSTR);
213 return(savestr(canonb));
214}
1b38f4e9
KS
215
216/*
217 * Receipt continuation.
218 */
828615a1 219/*ARGSUSED*/
1b38f4e9
KS
220ttycont(s)
221{
1b38f4e9 222 hadcont++;
1b38f4e9
KS
223 longjmp(rewrite, 1);
224}