[BACK]Return to tty.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / mail

Annotation of src/usr.bin/mail/tty.c, Revision 1.13

1.13    ! millert     1: /*     $OpenBSD: tty.c,v 1.12 2001/06/23 23:04:23 millert Exp $        */
1.3       millert     2: /*     $NetBSD: tty.c,v 1.7 1997/07/09 05:25:46 mikel Exp $    */
1.2       deraadt     3:
1.1       deraadt     4: /*
                      5:  * Copyright (c) 1980, 1993
                      6:  *     The Regents of the University of California.  All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. All advertising materials mentioning features or use of this software
                     17:  *    must display the following acknowledgement:
                     18:  *     This product includes software developed by the University of
                     19:  *     California, Berkeley and its contributors.
                     20:  * 4. Neither the name of the University nor the names of its contributors
                     21:  *    may be used to endorse or promote products derived from this software
                     22:  *    without specific prior written permission.
                     23:  *
                     24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     34:  * SUCH DAMAGE.
                     35:  */
                     36:
                     37: #ifndef lint
1.2       deraadt    38: #if 0
1.3       millert    39: static char sccsid[] = "@(#)tty.c      8.2 (Berkeley) 4/20/95";
1.2       deraadt    40: #else
1.13    ! millert    41: static char rcsid[] = "$OpenBSD: tty.c,v 1.12 2001/06/23 23:04:23 millert Exp $";
1.2       deraadt    42: #endif
1.1       deraadt    43: #endif /* not lint */
                     44:
                     45: /*
                     46:  * Mail -- a mail program
                     47:  *
                     48:  * Generally useful tty stuff.
                     49:  */
                     50:
                     51: #include "rcv.h"
                     52: #include "extern.h"
1.2       deraadt    53: #include <sys/ioctl.h>
1.13    ! millert    54: #include <errno.h>
1.1       deraadt    55:
1.5       millert    56: static cc_t            c_erase;        /* Current erase char */
                     57: static cc_t            c_kill;         /* Current kill char */
1.1       deraadt    58: #ifndef TIOCSTI
1.5       millert    59: static int             ttyset;         /* We must now do erase/kill */
1.1       deraadt    60: #endif
1.13    ! millert    61: static volatile sig_atomic_t   ttysignal;      /* Interrupted by a signal? */
1.1       deraadt    62:
                     63: /*
                     64:  * Read all relevant header fields.
                     65:  */
                     66:
                     67: int
                     68: grabh(hp, gflags)
                     69:        struct header *hp;
                     70:        int gflags;
                     71: {
                     72:        struct termios ttybuf;
                     73: #ifndef TIOCSTI
1.13    ! millert    74:        struct sigaction savequit;
1.10      millert    75: #else
                     76: # ifdef        TIOCEXT
1.13    ! millert    77:        int extproc;
1.12      millert    78:        int flag;
                     79: # endif /* TIOCEXT */
1.1       deraadt    80: #endif
1.13    ! millert    81:        struct sigaction savetstp;
        !            82:        struct sigaction savettou;
        !            83:        struct sigaction savettin;
        !            84:        struct sigaction act;
        !            85:        char *s;
        !            86:        int error;
        !            87:
        !            88:        sigemptyset(&act.sa_mask);
        !            89:        act.sa_flags = SA_RESTART;
        !            90:        act.sa_handler = SIG_DFL;
        !            91:        (void)sigaction(SIGTSTP, &act, &savetstp);
        !            92:        (void)sigaction(SIGTTOU, &act, &savettou);
        !            93:        (void)sigaction(SIGTTIN, &act, &savettin);
        !            94:        error = 1;
1.1       deraadt    95: #ifndef TIOCSTI
                     96:        ttyset = 0;
                     97: #endif
                     98:        if (tcgetattr(fileno(stdin), &ttybuf) < 0) {
1.3       millert    99:                warn("tcgetattr");
1.1       deraadt   100:                return(-1);
                    101:        }
                    102:        c_erase = ttybuf.c_cc[VERASE];
                    103:        c_kill = ttybuf.c_cc[VKILL];
                    104: #ifndef TIOCSTI
                    105:        ttybuf.c_cc[VERASE] = 0;
                    106:        ttybuf.c_cc[VKILL] = 0;
1.13    ! millert   107:        act.sa_handler = SIG_IGN;
        !           108:        if (sigaction(SIGQUIT, &act, &savequit) == 0 &&
        !           109:            savequit.sa_handler == SIG_DFL)
        !           110:                (void)sigaction(SIGQUIT, &savequit, NULL);
1.1       deraadt   111: #else
1.10      millert   112: # ifdef        TIOCEXT
                    113:        extproc = ((ttybuf.c_lflag & EXTPROC) ? 1 : 0);
                    114:        if (extproc) {
                    115:                flag = 0;
                    116:                if (ioctl(fileno(stdin), TIOCEXT, &flag) < 0)
                    117:                        warn("TIOCEXT: off");
                    118:        }
                    119: # endif /* TIOCEXT */
1.1       deraadt   120: #endif
                    121:        if (gflags & GTO) {
                    122: #ifndef TIOCSTI
                    123:                if (!ttyset && hp->h_to != NIL)
                    124:                        ttyset++, tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
                    125: #endif
1.13    ! millert   126:                s = readtty("To: ", detract(hp->h_to, 0));
        !           127:                if (s == NULL)
        !           128:                        goto out;
        !           129:                hp->h_to = extract(s, GTO);
1.1       deraadt   130:        }
                    131:        if (gflags & GSUBJECT) {
                    132: #ifndef TIOCSTI
1.5       millert   133:                if (!ttyset && hp->h_subject != NULL)
1.1       deraadt   134:                        ttyset++, tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
                    135: #endif
1.13    ! millert   136:                s = readtty("Subject: ", hp->h_subject);
        !           137:                if (s == NULL)
        !           138:                        goto out;
        !           139:                hp->h_subject = s;
1.1       deraadt   140:        }
                    141:        if (gflags & GCC) {
                    142: #ifndef TIOCSTI
                    143:                if (!ttyset && hp->h_cc != NIL)
                    144:                        ttyset++, tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
                    145: #endif
1.13    ! millert   146:                s = readtty("Cc: ", detract(hp->h_cc, 0));
        !           147:                if (s == NULL)
        !           148:                        goto out;
        !           149:                hp->h_cc = extract(s, GCC);
1.1       deraadt   150:        }
                    151:        if (gflags & GBCC) {
                    152: #ifndef TIOCSTI
                    153:                if (!ttyset && hp->h_bcc != NIL)
                    154:                        ttyset++, tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
                    155: #endif
1.13    ! millert   156:                s = readtty("Bcc: ", detract(hp->h_bcc, 0));
        !           157:                if (s == NULL)
        !           158:                        goto out;
        !           159:                hp->h_bcc = extract(s, GBCC);
1.1       deraadt   160:        }
1.13    ! millert   161:        error = 0;
1.1       deraadt   162: out:
1.13    ! millert   163:        (void)sigaction(SIGTSTP, &savetstp, NULL);
        !           164:        (void)sigaction(SIGTTOU, &savettou, NULL);
        !           165:        (void)sigaction(SIGTTIN, &savettin, NULL);
1.1       deraadt   166: #ifndef TIOCSTI
                    167:        ttybuf.c_cc[VERASE] = c_erase;
                    168:        ttybuf.c_cc[VKILL] = c_kill;
                    169:        if (ttyset)
                    170:                tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
1.13    ! millert   171:        (void)sigaction(SIGQUIT, &savequit, NULL);
1.10      millert   172: #else
                    173: # ifdef        TIOCEXT
                    174:        if (extproc) {
                    175:                flag = 1;
                    176:                if (ioctl(fileno(stdin), TIOCEXT, &flag) < 0)
                    177:                        warn("TIOCEXT: on");
                    178:        }
                    179: # endif /* TIOCEXT */
1.1       deraadt   180: #endif
1.13    ! millert   181:        return(error);
1.1       deraadt   182: }
                    183:
                    184: /*
                    185:  * Read up a header from standard input.
                    186:  * The source string has the preliminary contents to
                    187:  * be read.
                    188:  *
                    189:  */
                    190:
                    191: char *
                    192: readtty(pr, src)
                    193:        char pr[], src[];
                    194: {
1.13    ! millert   195:        struct sigaction act, oact;
        !           196:        sigset_t oset;
1.1       deraadt   197:        char ch, canonb[BUFSIZ];
1.13    ! millert   198:        char *cp, *cp2;
        !           199:        int c;
1.1       deraadt   200:
                    201:        fputs(pr, stdout);
                    202:        fflush(stdout);
1.5       millert   203:        if (src != NULL && strlen(src) > BUFSIZ - 2) {
1.3       millert   204:                puts("too long to edit");
1.1       deraadt   205:                return(src);
                    206:        }
                    207: #ifndef TIOCSTI
1.5       millert   208:        if (src != NULL)
1.1       deraadt   209:                cp = copy(src, canonb);
                    210:        else
                    211:                cp = copy("", canonb);
                    212:        fputs(canonb, stdout);
                    213:        fflush(stdout);
                    214: #else
1.5       millert   215:        cp = src == NULL ? "" : src;
1.2       deraadt   216:        while ((c = *cp++) != '\0') {
1.1       deraadt   217:                if ((c_erase != _POSIX_VDISABLE && c == c_erase) ||
                    218:                    (c_kill != _POSIX_VDISABLE && c == c_kill)) {
                    219:                        ch = '\\';
                    220:                        ioctl(0, TIOCSTI, &ch);
                    221:                }
                    222:                ch = c;
                    223:                ioctl(0, TIOCSTI, &ch);
                    224:        }
                    225:        cp = canonb;
                    226:        *cp = 0;
                    227: #endif
                    228:        cp2 = cp;
                    229:        while (cp2 < canonb + BUFSIZ)
                    230:                *cp2++ = 0;
                    231:        cp2 = cp;
1.13    ! millert   232:        sigemptyset(&act.sa_mask);
        !           233:        act.sa_flags = 0;               /* Note: will not restart syscalls */
        !           234:        act.sa_handler = ttyint;
        !           235:        (void)sigaction(SIGINT, &act, &oact);
        !           236:        act.sa_handler = ttystop;
        !           237:        (void)sigaction(SIGTSTP, &act, NULL);
        !           238:        (void)sigaction(SIGTTOU, &act, NULL);
        !           239:        (void)sigaction(SIGTTIN, &act, NULL);
        !           240:        (void)sigprocmask(SIG_UNBLOCK, &intset, &oset);
1.1       deraadt   241:        clearerr(stdin);
                    242:        while (cp2 < canonb + BUFSIZ) {
                    243:                c = getc(stdin);
1.13    ! millert   244:                switch (ttysignal) {
        !           245:                        case SIGINT:
        !           246:                                ttysignal = 0;
        !           247:                                cp2 = NULL;
        !           248:                                c = EOF;
        !           249:                                /* FALLTHROUGH */
        !           250:                        case 0:
        !           251:                                break;
        !           252:                        default:
        !           253:                                ttysignal = 0;
        !           254:                                goto redo;
        !           255:                }
1.1       deraadt   256:                if (c == EOF || c == '\n')
                    257:                        break;
                    258:                *cp2++ = c;
                    259:        }
1.13    ! millert   260:        act.sa_handler = SIG_DFL;
        !           261:        sigemptyset(&act.sa_mask);
        !           262:        act.sa_flags = SA_RESTART;
        !           263:        (void)sigprocmask(SIG_SETMASK, &oset, NULL);
        !           264:        (void)sigaction(SIGTSTP, &act, NULL);
        !           265:        (void)sigaction(SIGTTOU, &act, NULL);
        !           266:        (void)sigaction(SIGTTIN, &act, NULL);
        !           267:        (void)sigaction(SIGTTIN, &oact, NULL);
        !           268:        if (cp2 == NULL)
        !           269:                return(NULL);                   /* user hit ^C */
        !           270:        *cp2 = '\0';
1.1       deraadt   271:        if (c == EOF && ferror(stdin)) {
                    272: redo:
1.5       millert   273:                cp = strlen(canonb) > 0 ? canonb : NULL;
1.1       deraadt   274:                clearerr(stdin);
1.13    ! millert   275:                /* XXX - make iterative, not recursive */
1.1       deraadt   276:                return(readtty(pr, cp));
                    277:        }
                    278: #ifndef TIOCSTI
1.5       millert   279:        if (cp == NULL || *cp == '\0')
1.1       deraadt   280:                return(src);
                    281:        cp2 = cp;
                    282:        if (!ttyset)
1.5       millert   283:                return(strlen(canonb) > 0 ? savestr(canonb) : NULL);
1.1       deraadt   284:        while (*cp != '\0') {
                    285:                c = *cp++;
                    286:                if (c_erase != _POSIX_VDISABLE && c == c_erase) {
                    287:                        if (cp2 == canonb)
                    288:                                continue;
                    289:                        if (cp2[-1] == '\\') {
                    290:                                cp2[-1] = c;
                    291:                                continue;
                    292:                        }
                    293:                        cp2--;
                    294:                        continue;
                    295:                }
                    296:                if (c_kill != _POSIX_VDISABLE && c == c_kill) {
                    297:                        if (cp2 == canonb)
                    298:                                continue;
                    299:                        if (cp2[-1] == '\\') {
                    300:                                cp2[-1] = c;
                    301:                                continue;
                    302:                        }
                    303:                        cp2 = canonb;
                    304:                        continue;
                    305:                }
                    306:                *cp2++ = c;
                    307:        }
                    308:        *cp2 = '\0';
                    309: #endif
                    310:        if (equal("", canonb))
1.13    ! millert   311:                return("");
1.1       deraadt   312:        return(savestr(canonb));
                    313: }
                    314:
                    315: /*
                    316:  * Receipt continuation.
                    317:  */
                    318: void
                    319: ttystop(s)
                    320:        int s;
                    321: {
1.13    ! millert   322:        struct sigaction act, oact;
1.2       deraadt   323:        sigset_t nset;
1.13    ! millert   324:        int save_errno;
1.1       deraadt   325:
1.13    ! millert   326:        /*
        !           327:         * Save old handler and set to default.
        !           328:         * Unblock receipt of 's' and then resend it.
        !           329:         */
        !           330:        save_errno = errno;
        !           331:        (void)sigemptyset(&act.sa_mask);
        !           332:        act.sa_flags = SA_RESTART;
        !           333:        act.sa_handler = SIG_DFL;
        !           334:        (void)sigaction(s, &act, &oact);
1.8       millert   335:        (void)sigemptyset(&nset);
                    336:        (void)sigaddset(&nset, s);
                    337:        (void)sigprocmask(SIG_UNBLOCK, &nset, NULL);
                    338:        (void)kill(0, s);
                    339:        (void)sigprocmask(SIG_BLOCK, &nset, NULL);
1.13    ! millert   340:        (void)sigaction(s, &oact, NULL);
        !           341:        ttysignal = s;
        !           342:        errno = save_errno;
1.1       deraadt   343: }
                    344:
                    345: /*ARGSUSED*/
                    346: void
                    347: ttyint(s)
                    348:        int s;
                    349: {
1.13    ! millert   350:
        !           351:        ttysignal = s;
1.1       deraadt   352: }