Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/mailx/tty.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the BSD package *
4
*Copyright (c) 1978-2006 The Regents of the University of California an*
5
* *
6
* Redistribution and use in source and binary forms, with or *
7
* without modification, are permitted provided that the following *
8
* conditions are met: *
9
* *
10
* 1. Redistributions of source code must retain the above *
11
* copyright notice, this list of conditions and the *
12
* following disclaimer. *
13
* *
14
* 2. Redistributions in binary form must reproduce the above *
15
* copyright notice, this list of conditions and the *
16
* following disclaimer in the documentation and/or other *
17
* materials provided with the distribution. *
18
* *
19
* 3. Neither the name of The Regents of the University of California*
20
* names of its contributors may be used to endorse or *
21
* promote products derived from this software without *
22
* specific prior written permission. *
23
* *
24
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
25
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
26
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
27
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
28
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS *
29
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
30
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED *
31
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
32
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON *
33
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, *
34
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY *
35
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *
36
* POSSIBILITY OF SUCH DAMAGE. *
37
* *
38
* Redistribution and use in source and binary forms, with or without *
39
* modification, are permitted provided that the following conditions *
40
* are met: *
41
* 1. Redistributions of source code must retain the above copyright *
42
* notice, this list of conditions and the following disclaimer. *
43
* 2. Redistributions in binary form must reproduce the above copyright *
44
* notice, this list of conditions and the following disclaimer in *
45
* the documentation and/or other materials provided with the *
46
* distribution. *
47
* 3. Neither the name of the University nor the names of its *
48
* contributors may be used to endorse or promote products derived *
49
* from this software without specific prior written permission. *
50
* *
51
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" *
52
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
53
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
54
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS *
55
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *
56
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *
57
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF *
58
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND *
59
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, *
60
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT *
61
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF *
62
* SUCH DAMAGE. *
63
* *
64
* Kurt Shoens (UCB) *
65
* gsf *
66
* *
67
***********************************************************************/
68
#pragma prototyped
69
/*
70
* Mail -- a mail program
71
*
72
* Interactive header editing.
73
*/
74
75
#include "mailx.h"
76
77
/*
78
* tty stuff swiped from ksh
79
*/
80
81
#ifdef _hdr_termios
82
# include <termios.h>
83
# if __sgi__ || sgi /* special hack to eliminate ^M problem */
84
# ifndef ECHOCTL
85
# define ECHOCTL ECHOE
86
# endif /* ECHOCTL */
87
# ifndef CNSUSP
88
# define CNSUSP CNSWTCH
89
# endif /* CNSUSP */
90
# endif /* sgi */
91
# ifdef _NEXT_SOURCE
92
# define _lib_tcgetattr 1
93
# define _lib_tcgetpgrp 1
94
# endif /* _NEXT_SOURCE */
95
#else
96
# if defined(_sys_termios) && defined(_lib_tcgetattr)
97
# include <sys/termios.h>
98
# define _hdr_termios
99
# else
100
# undef _sys_termios
101
# endif /* _sys_termios */
102
#endif /* _hdr_termios */
103
104
#ifdef _hdr_termios
105
# undef _hdr_sgtty
106
# undef tcgetattr
107
# undef tcsetattr
108
# undef tcgetpgrp
109
# undef tcsetpgrp
110
# undef cfgetospeed
111
# ifndef TCSANOW
112
# define TCSANOW TCSETS
113
# define TCSADRAIN TCSETSW
114
# define TCSAFLUSH TCSETSF
115
# endif /* TCSANOW */
116
/* The following corrects bugs in some implementations */
117
# if defined(TCSADFLUSH) && !defined(TCSAFLUSH)
118
# define TCSAFLUSH TCSADFLUSH
119
# endif /* TCSADFLUSH */
120
# ifndef _lib_tcgetattr
121
# undef tcgetattr
122
# define tcgetattr(fd,tty) ioctl(fd, TCGETS, tty)
123
# undef tcsetattr
124
# define tcsetattr(fd,action,tty) ioctl(fd, action, tty)
125
# undef cfgetospeed
126
# define cfgetospeed(tp) ((tp)->c_cflag & CBAUD)
127
# endif /* _lib_tcgetattr */
128
# undef TIOCGETC
129
# if SHOPT_OLDTERMIO /* use both termios and termio */
130
# ifdef _hdr_termio
131
# include <termio.h>
132
# else
133
# ifdef _sys_termio
134
# include <sys/termio.h>
135
# define _hdr_termio 1
136
# else
137
# undef SHOPT_OLDTERMIO
138
# endif /* _sys_termio */
139
# endif /* _hdr_termio */
140
# endif /* SHOPT_OLDTERMIO */
141
#else
142
# define cfgetospeed(tp) ((tp)->c_cflag & CBAUD)
143
# undef SHOPT_OLDTERMIO
144
# ifdef _hdr_termio
145
# include <termio.h>
146
# else
147
# ifdef _sys_termio
148
# include <sys/termio.h>
149
# define _hdr_termio 1
150
# endif /* _sys_termio */
151
# endif /* _hdr_termio */
152
# ifdef _hdr_termio
153
# define termios termio
154
# undef TIOCGETC
155
# define tcgetattr(fd,tty) ioctl(fd, TCGETA, tty)
156
# define tcsetattr(fd,action,tty) ioctl(fd, action, tty)
157
158
# ifdef _sys_bsdtty
159
# include <sys/bsdtty.h>
160
# endif /* _sys_bsdtty */
161
# else
162
# ifdef _hdr_sgtty
163
# include <sgtty.h>
164
# ifndef LPENDIN
165
# ifdef _sys_nttyio
166
# include <sys/nttyio.h>
167
# endif /* _sys_nttyio */
168
# endif /* LPENDIN */
169
# define termios sgttyb
170
# ifdef TIOCSETN
171
# undef TCSETAW
172
# endif /* TIOCSETN */
173
# ifdef TIOCGETP
174
# define tcgetattr(fd,tty) ioctl(fd, TIOCGETP, tty)
175
# define tcsetattr(fd,action,tty) ioctl(fd, action, tty)
176
# else
177
# define tcgetattr(fd,tty) gtty(fd, tty)
178
# define tcsetattr(fd,action,tty) stty(fd, tty)
179
# endif /* TIOCGETP */
180
# endif /* _hdr_sgtty */
181
# endif /* hdr_termio */
182
183
# ifndef TCSANOW
184
# ifdef TCSETAW
185
# define TCSANOW TCSETA
186
# ifdef u370
187
/* delays are too long, don't wait for output to drain */
188
# define TCSADRAIN TCSETA
189
# else
190
# define TCSADRAIN TCSETAW
191
# endif /* u370 */
192
# define TCSAFLUSH TCSETAF
193
# else
194
# ifdef TIOCSETN
195
# define TCSANOW TIOCSETN
196
# define TCSADRAIN TIOCSETN
197
# define TCSAFLUSH TIOCSETP
198
# endif /* TIOCSETN */
199
# endif /* TCSETAW */
200
# endif /* TCSANOW */
201
#endif /* _hdr_termios */
202
203
/* set ECHOCTL if driver can echo control charaters as ^c */
204
#ifdef LCTLECH
205
# ifndef ECHOCTL
206
# define ECHOCTL LCTLECH
207
# endif /* !ECHOCTL */
208
#endif /* LCTLECH */
209
#ifdef LNEW_CTLECH
210
# ifndef ECHOCTL
211
# define ECHOCTL LNEW_CTLECH
212
# endif /* !ECHOCTL */
213
#endif /* LNEW_CTLECH */
214
#ifdef LNEW_PENDIN
215
# ifndef PENDIN
216
# define PENDIN LNEW_PENDIN
217
# endif /* !PENDIN */
218
#endif /* LNEW_PENDIN */
219
#ifndef ECHOCTL
220
# ifndef VEOL
221
# define RAWONLY 1
222
# endif /* !VEOL */
223
#endif /* !ECHOCTL */
224
225
/*
226
* Output label on wfd and return next char on rfd with no echo.
227
* Return < -1 is -(signal + 1).
228
*/
229
230
int
231
ttyquery(int rfd, int wfd, const char* label)
232
{
233
register int r;
234
int n;
235
unsigned char c;
236
struct termios old;
237
struct termios tty;
238
239
if (!label)
240
n = 0;
241
else if (n = strlen(label))
242
write(wfd, label, n);
243
tcgetattr(rfd, &old);
244
tty = old;
245
tty.c_cc[VTIME] = 0;
246
tty.c_cc[VMIN] = 1;
247
tty.c_lflag &= ~(ICANON|ECHO|ECHOK|ISIG);
248
tcsetattr(rfd, TCSADRAIN, &tty);
249
if ((r = read(rfd, &c, 1)) == 1) {
250
if (c == old.c_cc[VEOF])
251
r = -1;
252
else if (c == old.c_cc[VINTR])
253
r = -(SIGINT + 1);
254
else if (c == old.c_cc[VQUIT])
255
r = -(SIGQUIT + 1);
256
else if (c == '\r')
257
r = '\n';
258
else
259
r = c;
260
}
261
tcsetattr(rfd, TCSADRAIN, &old);
262
if (n) {
263
write(wfd, "\r", 1);
264
while (n-- > 0)
265
write(wfd, " ", 1);
266
write(wfd, "\r", 1);
267
}
268
return r;
269
}
270
271
/*
272
* Edit buf on rfd,wfd with label.
273
* Do not backspace over label.
274
*/
275
276
int
277
ttyedit(int rfd, int wfd, const char* label, char* buf, size_t size)
278
{
279
register int r;
280
register int last = strlen(buf);
281
unsigned char c;
282
struct termios old;
283
struct termios tty;
284
285
size--;
286
if (label)
287
write(wfd, label, strlen(label));
288
if (last)
289
write(wfd, buf, last);
290
tcgetattr(rfd, &old);
291
tty = old;
292
tty.c_cc[VTIME] = 0;
293
tty.c_cc[VMIN] = 1;
294
tty.c_lflag &= ~(ICANON|ECHO|ECHOK|ISIG);
295
tcsetattr(rfd, TCSADRAIN, &tty);
296
for (;;) {
297
if ((r = read(rfd, &c, 1)) <= 0)
298
break;
299
if (c == old.c_cc[VERASE]) {
300
if (last == 0)
301
write(wfd, "\a", 1);
302
else {
303
write(wfd, "\b \b", 3);
304
last--;
305
}
306
}
307
else if (c == old.c_cc[VKILL]) {
308
memset(buf, '\b', last);
309
write(wfd, buf, last);
310
memset(buf, ' ', last);
311
write(wfd, buf, last);
312
memset(buf, '\b', last);
313
write(wfd, buf, last);
314
last = 0;
315
}
316
else if (c == old.c_cc[VEOF]) {
317
r = last;
318
break;
319
}
320
else if (c == old.c_cc[VINTR]) {
321
r = -(SIGINT + 1);
322
break;
323
}
324
else if (c == old.c_cc[VQUIT]) {
325
r = -(SIGQUIT + 1);
326
break;
327
}
328
else if (last > size) {
329
r = -1;
330
break;
331
}
332
else {
333
if (c == '\r')
334
c = '\n';
335
buf[last++] = c;
336
write(wfd, &buf[last - 1], 1);
337
if (c == '\n') {
338
r = --last;
339
break;
340
}
341
r = last;
342
}
343
}
344
tcsetattr(rfd, TCSADRAIN, &old);
345
if (r >= 0)
346
buf[last] = 0;
347
return r;
348
}
349
350
/*
351
* Edit the fields in type.
352
*/
353
354
void
355
grabedit(struct header* hp, unsigned long type)
356
{
357
register char* s;
358
register const struct lab* lp;
359
int r;
360
sig_t saveint;
361
sig_t savequit;
362
char buf[LINESIZE];
363
364
fflush(stdout);
365
if ((saveint = signal(SIGINT, SIG_IGN)) == SIG_DFL)
366
signal(SIGINT, SIG_DFL);
367
if ((savequit = signal(SIGQUIT, SIG_IGN)) == SIG_DFL)
368
signal(SIGQUIT, SIG_DFL);
369
r = 0;
370
for (lp = state.hdrtab; lp->name; lp++)
371
if (type & lp->type) {
372
if (!(s = detract(hp, lp->type)))
373
s = "";
374
if (strlen(s) >= sizeof(buf)) {
375
note(0, "%sfield too long to edit", lp->name);
376
continue;
377
}
378
strcpy(buf, s);
379
if ((r = ttyedit(0, 1, lp->name, buf, sizeof(buf))) < 0)
380
break;
381
headclear(hp, lp->type);
382
extract(hp, lp->type, buf);
383
}
384
if (saveint != SIG_DFL)
385
signal(SIGINT, saveint);
386
if (savequit != SIG_DFL)
387
signal(SIGQUIT, savequit);
388
if (r < -1)
389
kill(0, -(r + 1));
390
}
391
392