root/usr/src/cmd/tip/tipout.c
/*
 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

/*
 * Copyright (c) 1983 Regents of the University of California.
 * All rights reserved.  The Berkeley software License Agreement
 * specifies the terms and conditions for redistribution.
 */

#include "tip.h"
#include <limits.h>

/*
 * tip
 *
 * lower fork of tip -- handles passive side
 *  reading from the remote host
 */

FILE    *fscript;
static  sigjmp_buf sigbuf;

/*
 * TIPOUT wait state routine --
 *   sent by TIPIN when it wants to posses the remote host
 */
void
intIOT(void)
{

        (void) write(repdes[1], &ccc, 1);
        (void) read(fildes[0], &ccc, 1);
        siglongjmp(sigbuf, 1);
}

/*
 * Scripting command interpreter --
 *  accepts script file name over the pipe and acts accordingly
 */
void
intEMT(void)
{
        char c, line[PATH_MAX];
        char *pline = line;
        char reply;

        (void) read(fildes[0], &c, 1);
        while (c != '\n' && line + sizeof (line) - pline > 1) {
                *pline++ = c;
                (void) read(fildes[0], &c, 1);
        }
        *pline = '\0';
        if (boolean(value(SCRIPT)) && fscript != NULL)
                (void) fclose(fscript);
        if (pline == line) {
                boolean(value(SCRIPT)) = FALSE;
                reply = 'y';
        } else {
                if ((fscript = fopen(line, "a")) == NULL)
                        reply = 'n';
                else {
                        reply = 'y';
                        boolean(value(SCRIPT)) = TRUE;
                }
        }
        (void) write(repdes[1], &reply, 1);
        siglongjmp(sigbuf, 1);
}

void
intTERM(void)
{

        if (boolean(value(SCRIPT)) && fscript != NULL)
                (void) fclose(fscript);
        exit(0);
}

void
intSYS(void)
{

        boolean(value(BEAUTIFY)) = !boolean(value(BEAUTIFY));
        siglongjmp(sigbuf, 1);
}

/*
 * ****TIPOUT   TIPOUT****
 */
void
tipout(void)
{
        char buf[BUFSIZ];
        char *cp;
        int cnt;
        sigset_t omask, bmask, tmask;

        (void) signal(SIGINT, SIG_IGN);
        (void) signal(SIGQUIT, SIG_IGN);
        /* attention from TIPIN */
        (void) signal(SIGEMT, (sig_handler_t)intEMT);
        /* time to go signal */
        (void) signal(SIGTERM, (sig_handler_t)intTERM);
        /* scripting going on signal */
        (void) signal(SIGIOT, (sig_handler_t)intIOT);
        /* for dial-ups */
        (void) signal(SIGHUP, (sig_handler_t)intTERM);
        /* beautify toggle */
        (void) signal(SIGSYS, (sig_handler_t)intSYS);
        (void) sigsetjmp(sigbuf, 1);

        (void) sigemptyset(&omask);
        (void) sigemptyset(&bmask);
        (void) sigaddset(&bmask, SIGEMT);
        (void) sigaddset(&bmask, SIGTERM);
        (void) sigaddset(&bmask, SIGIOT);
        (void) sigaddset(&bmask, SIGSYS);
        (void) sigemptyset(&tmask);
        (void) sigaddset(&tmask, SIGTERM);
        for (;;) {
                cnt = read(FD, buf, BUFSIZ);
                if (cnt <= 0) {
                        /*
                         * If dialback is specified, ignore the hangup
                         * and clear the hangup condition on the device.
                         */
                        if (cnt == 0 && DB) {
                                int fd;

                                DB = 0;
                                if ((fd = open(DV, O_RDWR)) >= 0) {
                                        if (fd != FD)
                                                (void) close(fd);
                                }
                                continue;
                        }
                        /* lost carrier */
                        if ((cnt < 0 && errno == EIO) ||
                            (cnt == 0)) {
                                (void) sigprocmask(SIG_BLOCK, &tmask, NULL);
                                intTERM();
                                /*NOTREACHED*/
                        }
                } else {
                        (void) sigprocmask(SIG_BLOCK, &bmask, &omask);
                        if (!noparity)
                                for (cp = buf; cp < buf + cnt; cp++)
                                        *cp &= 0177;

                        (void) write(1, buf, cnt);
                        if (boolean(value(SCRIPT)) && fscript != NULL) {
                                if (!boolean(value(BEAUTIFY))) {
                                        (void) fwrite(buf, 1, cnt, fscript);
                                } else {
                                        for (cp = buf; cp < buf + cnt; cp++)
                                                if ((*cp >= ' ' && *cp <= '~')||
                                                    any(*cp, value(EXCEPTIONS)))
                                                        (void) putc(*cp,
                                                            fscript);
                                }
                        }
                }
                (void) sigprocmask(SIG_SETMASK, &omask, NULL);
        }
}