#ifndef	lint
static char sccsid[] = "%Z%%M% %I% %E%";
#endif

/*
 * Copyright (c) 1989 by Sun Microsystems, Inc.
 */

#include "cbratp.h"
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <sgtty.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <sys/file.h>
#include <sys/wait.h>

#define	HELPER_VERSION	1
int news_pid;
char *host = NULL;

usage()
{
    (void) fprintf(stderr, "usage: %s [-f ttydevice] [-h] ", myname);
    (void) fprintf(stderr, "[-b baudrate] ");
#ifdef	DEBUG
    (void) fprintf(stderr, "[-d debugfilename] ");
#endif	/*DEBUG*/
    (void) fprintf(stderr, "[-r] ");
    (void) fprintf(stderr, "[-s statfilename] [-i]\n");
    (void) fprintf(stderr, "       -b: set baudrate\n");
    (void) fprintf(stderr, "       -f: set tty device\n");
    (void) fprintf(stderr, "       -h: Use IP/TCP, and not RS232\n");
#ifdef	DEBUG
    (void) fprintf(stderr, "       -d: debug mode, output to file\n");
#endif	/*DEBUG*/
    (void) fprintf(stderr, "       -r: set RTS/CTS flow control\n");
    (void) fprintf(stderr, "       -s: generate stats, output to file\n");
    (void) fprintf(stderr, "       -i: immediate startup\n");
    exit(1);
}


/* This routine interferes with load in dload.c.  Load currently blocks
   SIGCHLD this interaction may need to be fixed someday.
 */
static void
reaper()
{
    union wait  status;
#ifdef  DEBUG
    int pid;

    while ((pid = wait3(&status, WNOHANG, (struct rusage *) 0)) > 0) {
        (void) fprintf(rs232_debugfile, "Reaped %d, retcode=0%o\n",
						pid, status.w_retcode);
    }
#else
    while (wait3(&status, WNOHANG, (struct rusage *) 0) > 0)
	;
#endif	/*DEBUG*/
}

static void
sighup_handler()
{
    register int i;
    
    for (i=getdtablesize()-1; i>0; i--)
	(void) close(i);
    sleep(3);
    reaper();
    /*lseek(0, -16L, 0);	/* will logout */
    exit(0);
}

main(argc, argv)
    int	argc;
    char **argv;
{
    int i;
    int iflag = 0;
    char *tty = "/dev/tty";
    int baudrate = 0;
    int rtscts = 0;
    extern char	*optarg;
    extern int	optind;
    extern char	*strrchr();

    if ((myname = strrchr(*argv, '/')) == NULL)
	myname = *argv;
    else
	myname++;
#ifdef	DEBUG
    rs232_debugfile = stdout;
#endif	/*DEBUG*/
    while ((i = getopt(argc, argv, "b:d:f:s:hir")) != -1)
	switch (i) {
	case 'b':
	    baudrate = atoi(optarg);
	    break;
	case 'r':
	    rtscts = 1;
	    break;
	case 'i':
	    iflag++;
	    break;
	case 's':
	    rs232_stats = fopen(optarg, "w");
	    break;
#ifdef	DEBUG
	case 'd':
	    if (rs232_debugfile = fopen(optarg, "w"))
		rs232_debug++;
	    break;
#endif	/*DEBUG*/
	case 'f':
	    tty = optarg;
	    break;
	case 'h':
	    host = "Use TCP";
	    break;
	case '?':
	    usage();
	}

#ifdef	DEBUG
    (void) setlinebuf(rs232_debugfile);
#endif	/*DEBUG*/
    (void) initialize_helper(tty);
    if (!rs232init(tty, baudrate, rtscts)) {
	(void) fprintf(stderr, "can't init %s\n", tty);
	exit(1);
    }
    version.version = HELPER_VERSION;
    initpktmode();
    rs232rawemit(213);
    rs232flush();

    if ((int) signal(SIGPIPE, SIG_IGN) < 0)
	perror("signal: SIGPIPE");
    if ((int) signal(SIGFPE, SIG_IGN) < 0)
	perror("signal: SIGFPE");
    if ((int) signal(SIGHUP, sighup_handler) < 0)
	perror("signal: SIGHUP");

    if (iflag == 0) {
	do {
	    (void) rs232ready();
	} while ((i = rs232rawkey()) != 231);
    }
    pkt_mode = 1;
    for (;;)
	wakeup_io();
}



initialize_helper(tty)
    char *tty;
{
    int tty_fd;

    (void) signal (SIGCHLD, reaper);
    news_pid = getpid();
    (void) gethostname(my_hostname, sizeof my_hostname);
    my_hostname[sizeof my_hostname - 1] = 0;

    /* Setup tty parameters for all terminal emulators that will start */
    if (host != NULL)
	return;
    
    tty_fd = open(tty, O_RDWR, 0);
    if (tty_fd < 0)
        (void) ttysw_saveparms(2);       /* Try stderr */
    else {
        (void) ttysw_saveparms(tty_fd);
        (void) close(tty_fd);
    }
}


/* ttysw_saveparms and we_setptyparms have been copied from the suntool libaray: * "@(#)ttysw_stty.c 10.5 86/09/03 Copyr 1983 Sun Micro"; */
 
/*
 * Ttysw parameter setting mechanism using given tty settings.
 */
 
/*
 * Determine ttyfd tty settings and cache in environment.
 */
ttysw_saveparms(ttyfd)
    int         ttyfd;
{
    int         ldisc,
                localmodes;
    struct sgttyb mode;
    struct tchars tchars;
    struct ltchars ltchars;

    if (host != NULL)
	return;

    /*                      
     * Get line discipline.
     */
    (void) ioctl(ttyfd, TIOCGETD, &ldisc);
    /* 
     * Get tty parameters
     */  
    (void) ioctl(ttyfd, TIOCGETP, &mode);
    /*   
     * Get local modes
     */  
    (void) ioctl(ttyfd, TIOCLGET, &localmodes);
    /*
     * Get terminal characters
     */  
    (void) ioctl(ttyfd, TIOCGETC, &tchars);
    /*
     * Get local special characters
     */  
    (void) ioctl(ttyfd, TIOCGLTC, &ltchars);
    /*
     * Write environment variable
     */  
    (void) we_setptyparms(ldisc, localmodes, &mode, &tchars, &ltchars);
}

#define WE_TTYPARMS     "WINDOW_TTYPARMS"
#define WE_TTYPARMSLEN  120

/*
 * Save tty settings in environment.
 */
we_setptyparms(ldisc, localmodes, mode, tchars, ltchars)
    int         ldisc,
                localmodes;
    struct sgttyb *mode;
    struct tchars *tchars;
    struct ltchars *ltchars;
{
    char        str[WE_TTYPARMSLEN];

    str[0] = '\0';
    /*
     * %c cannot be used to write the character valued fields because they
     * often have a value of \0.
     */  
    (void) sprintf(str,
                "%D,%D,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
               ldisc, localmodes, mode->sg_ispeed, mode->sg_ospeed,
               mode->sg_erase, mode->sg_kill, mode->sg_flags,
               tchars->t_intrc, tchars->t_quitc, tchars->t_startc,
               tchars->t_stopc, tchars->t_eofc, tchars->t_brkc,
               ltchars->t_suspc, ltchars->t_dsuspc, ltchars->t_rprntc,
               ltchars->t_flushc, ltchars->t_werasc, ltchars->t_lnextc);
    (void) setenv(WE_TTYPARMS, str);
}
