1 /* $NetBSD: tty.c,v 1.27 2006/11/28 18:45:32 christos Exp $ */
4 * Copyright (c) 1980, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
35 static char sccsid
[] = "@(#)tty.c 8.2 (Berkeley) 6/6/93";
37 __RCSID("$NetBSD: tty.c,v 1.27 2006/11/28 18:45:32 christos Exp $");
42 * Mail -- a mail program
44 * Generally useful tty stuff.
50 # include "complete.h"
54 static jmp_buf tty_jmpbuf
; /* Place to go when interrupted */
57 static cc_t c_erase
; /* Current erase char */
58 static cc_t c_kill
; /* Current kill char */
60 static int ttyset
; /* We must now do erase/kill */
62 #endif /* USE_EDITLINE */
65 * Read up a header from standard input.
66 * The source string has the preliminary contents to
69 * Returns: an salloc'ed copy of the line read if successful, or NULL
70 * if no characters were read or if an error occurred.
75 readtty(const char *pr
, char *src
)
79 line
= my_gets(&elm
.string
, pr
, src
);
82 (void)putc('\n', stdout
);
84 return line
? savestr(line
) : __UNCONST("");
87 #else /* not USE_EDITLINE */
90 readtty(const char *pr
, char *src
)
92 char canonb
[LINESIZE
];
99 (void)fputs(pr
, stdout
);
100 (void)fflush(stdout
);
101 if (src
!= NULL
&& strlen(src
) > sizeof(canonb
) - 2) {
102 (void)printf("too long to edit\n");
107 cp
= copy(src
, canonb
);
109 cp
= copy(__UNCONST(""), canonb
);
111 (void)fputs(canonb
, stdout
);
112 (void)fflush(stdout
);
114 cp
= src
== NULL
? __UNCONST("") : src
;
115 while ((c
= *cp
++) != '\0') {
116 if ((c_erase
!= _POSIX_VDISABLE
&& c
== c_erase
) ||
117 (c_kill
!= _POSIX_VDISABLE
&& c
== c_kill
)) {
119 (void)ioctl(0, TIOCSTI
, &ch
);
122 (void)ioctl(0, TIOCSTI
, &ch
);
129 while (cp2
< canonb
+ sizeof(canonb
) - 1) {
134 (void)putc('\n', stdout
);
143 if (c
== EOF
&& ferror(stdin
)) {
144 cp
= strlen(canonb
) > 0 ? canonb
: NULL
;
146 return readtty(pr
, cp
);
149 if (cp
== NULL
|| *cp
== '\0')
152 return strlen(canonb
) > 0 ? savestr(canonb
) : NULL
;
158 while (*cp
!= '\0') {
160 if (c_erase
!= _POSIX_VDISABLE
&& c
== c_erase
) {
163 if (cp2
[-1] == '\\') {
170 if (c_kill
!= _POSIX_VDISABLE
&& c
== c_kill
) {
173 if (cp2
[-1] == '\\') {
184 if (canonb
[0] == '\0')
185 return __UNCONST("");
186 return savestr(canonb
);
188 #endif /* USE_EDITLINE */
191 # define save_erase_and_kill(t) 0
194 save_erase_and_kill(struct termios
*t
)
200 if (tcgetattr(fileno(stdin
), t
) == -1) {
204 c_erase
= t
->c_cc
[VERASE
];
205 c_kill
= t
->c_cc
[VKILL
];
210 #if defined(USE_EDITLINE) || defined(TIOCSTI)
211 # define disable_erase_and_kill(t)
214 disable_erase_and_kill(struct termios
*t
)
219 t
->c_cc
[VERASE
] = _POSIX_VDISABLE
;
220 t
->c_cc
[VKILL
] = _POSIX_VDISABLE
;
221 (void)tcsetattr(fileno(stdin
), TCSADRAIN
, t
);
226 #if defined(USE_EDITLINE) || defined(TIOCSTI)
227 # define restore_erase_and_kill(t)
230 restore_erase_and_kill(struct termios
*t
)
235 t
->c_cc
[VERASE
] = c_erase
;
236 t
->c_cc
[VKILL
] = c_kill
;
237 (void)tcsetattr(fileno(stdin
), TCSADRAIN
, t
);
243 * Do a shell-like extraction of a line
244 * and make a list of name from it.
245 * Return the list or NULL if none found.
248 shextract(char *line
, int ntype
)
250 struct name
*begin
, *np
, *t
;
257 argc
= getrawlist(line
, argv
, (int)__arraycount(argv
));
258 for (i
= 0; i
< argc
; i
++) {
259 t
= nalloc(argv
[i
], ntype
);
273 tty_sigint(int signo __unused
)
276 longjmp(tty_jmpbuf
, 1);
280 * Read all relevant header fields.
281 * Returns 0 on success; 1 if there was an error or signal.
284 grabh(struct header
*hp
, int gflags
)
286 sig_t
volatile old_sigint
;
289 struct termios ttybuf
;
290 # if defined(TIOCSTI) && defined(TIOCEXT)
294 if (save_erase_and_kill(&ttybuf
))
297 # if defined(TIOCSTI) && defined(TIOCEXT)
298 extproc
= ((ttybuf
.c_lflag
& EXTPROC
) ? 1 : 0);
303 if (ioctl(fileno(stdin
), TIOCEXT
, &flag
) == -1)
304 warn("TIOCEXT: off");
307 #endif /* USE_EDITLINE */
310 old_sigint
= sig_signal(SIGINT
, tty_sigint
);
312 /* return here if we detect a SIGINT */
313 if ((retval
= setjmp(tty_jmpbuf
)) != 0) {
314 (void)putc('\n', stdout
);
319 * Do this irrespective of whether the initial string is empty.
320 * Otherwise, the editing is inconsistent.
322 disable_erase_and_kill(&ttybuf
);
326 extract(readtty("To: ", detract(hp
->h_to
, 0)), GTO
);
328 if (gflags
& GSUBJECT
) {
329 hp
->h_subject
= readtty("Subject: ", hp
->h_subject
);
333 extract(readtty("Cc: ", detract(hp
->h_cc
, 0)), GCC
);
337 extract(readtty("Bcc: ", detract(hp
->h_bcc
, 0)), GBCC
);
339 if (gflags
& GSMOPTS
) {
341 shextract(readtty("Smopts: ", detract(hp
->h_smopts
, 0)),
345 if (gflags
& GSMOPTS
) { /* XXX - Use a new flag for this? */
347 struct attachment
*ap
;
351 for (ap
= hp
->h_attach
; ap
; ap
= ap
->a_flink
)
353 (void)printf("Attachment%s: %d\n", i
> 1 ? "s" : "", i
);
358 restore_erase_and_kill(&ttybuf
);
361 # if defined(TIOCSTI) && defined(TIOCEXT)
365 if (ioctl(fileno(stdin
), TIOCEXT
, &flag
) == -1)
370 (void)sig_signal(SIGINT
, old_sigint
);