1*1de7b4b8SPedro F. Giffuni /*-
27f4c7948SUgen J.S. Antsilevich * Copyright (c) 1995 Ugen J.S.Antsilevich
37f4c7948SUgen J.S. Antsilevich *
47f4c7948SUgen J.S. Antsilevich * Redistribution and use in source forms, with and without modification,
57f4c7948SUgen J.S. Antsilevich * are permitted provided that this entire comment appears intact.
67f4c7948SUgen J.S. Antsilevich *
77f4c7948SUgen J.S. Antsilevich * Redistribution in binary form may occur without any restrictions.
87f4c7948SUgen J.S. Antsilevich * Obviously, it would be nice if you gave credit where credit is due
97f4c7948SUgen J.S. Antsilevich * but requiring it would be too onerous.
107f4c7948SUgen J.S. Antsilevich *
117f4c7948SUgen J.S. Antsilevich * This software is provided ``AS IS'' without any warranties of any kind.
127f4c7948SUgen J.S. Antsilevich *
137f4c7948SUgen J.S. Antsilevich * Snoop stuff.
147f4c7948SUgen J.S. Antsilevich */
157f4c7948SUgen J.S. Antsilevich
168d43ce09SDima Dorfman #include <sys/param.h>
177f4c7948SUgen J.S. Antsilevich #include <sys/fcntl.h>
182bb69a48SOllivier Robert #include <sys/filio.h>
197f4c7948SUgen J.S. Antsilevich #include <sys/snoop.h>
20ac89160aSBruce Evans #include <sys/stat.h>
21fc66e618SDima Dorfman #include <sys/linker.h>
22fc66e618SDima Dorfman #include <sys/module.h>
23ac89160aSBruce Evans
24dc763e50SPhilippe Charnier #include <err.h>
25f8da56fdSChristian S.J. Peron #include <errno.h>
26ac89160aSBruce Evans #include <locale.h>
271a37aa56SDavid E. O'Brien #include <paths.h>
28ac89160aSBruce Evans #include <signal.h>
29ac89160aSBruce Evans #include <stdio.h>
30ac89160aSBruce Evans #include <stdlib.h>
31ac89160aSBruce Evans #include <string.h>
322bb69a48SOllivier Robert #include <sysexits.h>
33ac89160aSBruce Evans #include <termcap.h>
34ac89160aSBruce Evans #include <termios.h>
354c995cc6SBruce Evans #include <time.h>
36ac89160aSBruce Evans #include <unistd.h>
377f4c7948SUgen J.S. Antsilevich
387f4c7948SUgen J.S. Antsilevich #define MSG_INIT "Snoop started."
397f4c7948SUgen J.S. Antsilevich #define MSG_OFLOW "Snoop stopped due to overflow. Reconnecting."
407f4c7948SUgen J.S. Antsilevich #define MSG_CLOSED "Snoop stopped due to tty close. Reconnecting."
417f4c7948SUgen J.S. Antsilevich #define MSG_CHANGE "Snoop device change by user request."
42c1209799SUgen J.S. Antsilevich #define MSG_NOWRITE "Snoop device change due to write failure."
437f4c7948SUgen J.S. Antsilevich
44cb95dc24SPaul Traina #define DEV_NAME_LEN 1024 /* for /dev/ttyXX++ */
457f4c7948SUgen J.S. Antsilevich #define MIN_SIZE 256
467f4c7948SUgen J.S. Antsilevich
477f4c7948SUgen J.S. Antsilevich #define CHR_SWITCH 24 /* Ctrl+X */
487f4c7948SUgen J.S. Antsilevich #define CHR_CLEAR 23 /* Ctrl+V */
497f4c7948SUgen J.S. Antsilevich
5048462fb1SWarner Losh static void clear(void);
5148462fb1SWarner Losh static void timestamp(const char *);
5248462fb1SWarner Losh static void set_tty(void);
5348462fb1SWarner Losh static void unset_tty(void);
5448462fb1SWarner Losh static void fatal(int, const char *);
5548462fb1SWarner Losh static int open_snp(void);
5648462fb1SWarner Losh static void cleanup(int);
5748462fb1SWarner Losh static void usage(void) __dead2;
5848462fb1SWarner Losh static void setup_scr(void);
5948462fb1SWarner Losh static void attach_snp(void);
6048462fb1SWarner Losh static void detach_snp(void);
6148462fb1SWarner Losh static void set_dev(const char *);
6248462fb1SWarner Losh static void ask_dev(char *, const char *);
637f4c7948SUgen J.S. Antsilevich
647f4c7948SUgen J.S. Antsilevich int opt_reconn_close = 0;
657f4c7948SUgen J.S. Antsilevich int opt_reconn_oflow = 0;
667f4c7948SUgen J.S. Antsilevich int opt_interactive = 1;
677f4c7948SUgen J.S. Antsilevich int opt_timestamp = 0;
68c1209799SUgen J.S. Antsilevich int opt_write = 0;
695009d1beSJordan K. Hubbard int opt_no_switch = 0;
701995d3a4SDima Dorfman const char *opt_snpdev;
717f4c7948SUgen J.S. Antsilevich
727f4c7948SUgen J.S. Antsilevich char dev_name[DEV_NAME_LEN];
737f4c7948SUgen J.S. Antsilevich int snp_io;
747f4c7948SUgen J.S. Antsilevich int std_in = 0, std_out = 1;
757f4c7948SUgen J.S. Antsilevich
767f4c7948SUgen J.S. Antsilevich int clear_ok = 0;
772bb69a48SOllivier Robert struct termios otty;
788d43ce09SDima Dorfman char tbuf[1024], gbuf[1024];
797f4c7948SUgen J.S. Antsilevich
808d43ce09SDima Dorfman static void
clear(void)8148462fb1SWarner Losh clear(void)
827f4c7948SUgen J.S. Antsilevich {
83f1007076SEd Schouten
847f4c7948SUgen J.S. Antsilevich if (clear_ok)
858d43ce09SDima Dorfman tputs(gbuf, 1, putchar);
867f4c7948SUgen J.S. Antsilevich fflush(stdout);
877f4c7948SUgen J.S. Antsilevich }
887f4c7948SUgen J.S. Antsilevich
898d43ce09SDima Dorfman static void
timestamp(const char * buf)9048462fb1SWarner Losh timestamp(const char *buf)
917f4c7948SUgen J.S. Antsilevich {
927f4c7948SUgen J.S. Antsilevich time_t t;
937f4c7948SUgen J.S. Antsilevich char btmp[1024];
94f1007076SEd Schouten
957f4c7948SUgen J.S. Antsilevich clear();
967f4c7948SUgen J.S. Antsilevich printf("\n---------------------------------------------\n");
977f4c7948SUgen J.S. Antsilevich t = time(NULL);
987f4c7948SUgen J.S. Antsilevich strftime(btmp, 1024, "Time: %d %b %H:%M", localtime(&t));
997f4c7948SUgen J.S. Antsilevich printf("%s\n", btmp);
1007f4c7948SUgen J.S. Antsilevich printf("%s\n", buf);
1017f4c7948SUgen J.S. Antsilevich printf("---------------------------------------------\n");
1027f4c7948SUgen J.S. Antsilevich fflush(stdout);
1037f4c7948SUgen J.S. Antsilevich }
1047f4c7948SUgen J.S. Antsilevich
1058d43ce09SDima Dorfman static void
set_tty(void)10648462fb1SWarner Losh set_tty(void)
1077f4c7948SUgen J.S. Antsilevich {
1082bb69a48SOllivier Robert struct termios ntty;
109020539b6SJordan K. Hubbard
1102bb69a48SOllivier Robert ntty = otty;
1112bb69a48SOllivier Robert ntty.c_lflag &= ~ICANON; /* disable canonical operation */
1122bb69a48SOllivier Robert ntty.c_lflag &= ~ECHO;
1132bb69a48SOllivier Robert #ifdef FLUSHO
1142bb69a48SOllivier Robert ntty.c_lflag &= ~FLUSHO;
1152bb69a48SOllivier Robert #endif
1162bb69a48SOllivier Robert #ifdef PENDIN
1172bb69a48SOllivier Robert ntty.c_lflag &= ~PENDIN;
1182bb69a48SOllivier Robert #endif
1192bb69a48SOllivier Robert #ifdef IEXTEN
1202bb69a48SOllivier Robert ntty.c_lflag &= ~IEXTEN;
1212bb69a48SOllivier Robert #endif
1222bb69a48SOllivier Robert ntty.c_cc[VMIN] = 1; /* minimum of one character */
1232bb69a48SOllivier Robert ntty.c_cc[VTIME] = 0; /* timeout value */
1242bb69a48SOllivier Robert
1252bb69a48SOllivier Robert ntty.c_cc[VINTR] = 07; /* ^G */
1262bb69a48SOllivier Robert ntty.c_cc[VQUIT] = 07; /* ^G */
1272bb69a48SOllivier Robert tcsetattr(std_in, TCSANOW, &ntty);
1287f4c7948SUgen J.S. Antsilevich }
1297f4c7948SUgen J.S. Antsilevich
1308d43ce09SDima Dorfman static void
unset_tty(void)13148462fb1SWarner Losh unset_tty(void)
1327f4c7948SUgen J.S. Antsilevich {
1330ba64b27SEd Schouten
1342bb69a48SOllivier Robert tcsetattr(std_in, TCSANOW, &otty);
1357f4c7948SUgen J.S. Antsilevich }
1367f4c7948SUgen J.S. Antsilevich
1378d43ce09SDima Dorfman static void
fatal(int error,const char * buf)13848462fb1SWarner Losh fatal(int error, const char *buf)
1397f4c7948SUgen J.S. Antsilevich {
1400ba64b27SEd Schouten
1417f4c7948SUgen J.S. Antsilevich unset_tty();
1427f4c7948SUgen J.S. Antsilevich if (buf)
1438d43ce09SDima Dorfman errx(error, "fatal: %s", buf);
144dc763e50SPhilippe Charnier else
1458d43ce09SDima Dorfman exit(error);
1467f4c7948SUgen J.S. Antsilevich }
1477f4c7948SUgen J.S. Antsilevich
1488d43ce09SDima Dorfman static int
open_snp(void)14948462fb1SWarner Losh open_snp(void)
1507f4c7948SUgen J.S. Antsilevich {
1512e37c8eaSEd Schouten int f, mode;
152c1209799SUgen J.S. Antsilevich
153c1209799SUgen J.S. Antsilevich if (opt_write)
154c1209799SUgen J.S. Antsilevich mode = O_RDWR;
155c1209799SUgen J.S. Antsilevich else
156c1209799SUgen J.S. Antsilevich mode = O_RDONLY;
157c1209799SUgen J.S. Antsilevich
1581995d3a4SDima Dorfman if (opt_snpdev == NULL)
1592e37c8eaSEd Schouten f = open(_PATH_DEV "snp", mode);
1601995d3a4SDima Dorfman else
1612e37c8eaSEd Schouten f = open(opt_snpdev, mode);
1622e37c8eaSEd Schouten if (f == -1)
163dc763e50SPhilippe Charnier fatal(EX_OSFILE, "cannot open snoop device");
1642e37c8eaSEd Schouten
1652e37c8eaSEd Schouten return (f);
1667f4c7948SUgen J.S. Antsilevich }
1677f4c7948SUgen J.S. Antsilevich
1688d43ce09SDima Dorfman static void
cleanup(int signo __unused)16948462fb1SWarner Losh cleanup(int signo __unused)
1707f4c7948SUgen J.S. Antsilevich {
1710ba64b27SEd Schouten
1727f4c7948SUgen J.S. Antsilevich if (opt_timestamp)
1737f4c7948SUgen J.S. Antsilevich timestamp("Logging Exited.");
1747f4c7948SUgen J.S. Antsilevich close(snp_io);
1757f4c7948SUgen J.S. Antsilevich unset_tty();
1762bb69a48SOllivier Robert exit(EX_OK);
1777f4c7948SUgen J.S. Antsilevich }
1787f4c7948SUgen J.S. Antsilevich
179dc763e50SPhilippe Charnier static void
usage(void)18048462fb1SWarner Losh usage(void)
1817f4c7948SUgen J.S. Antsilevich {
1820ba64b27SEd Schouten
183dc763e50SPhilippe Charnier fprintf(stderr, "usage: watch [-ciotnW] [tty name]\n");
1842bb69a48SOllivier Robert exit(EX_USAGE);
1857f4c7948SUgen J.S. Antsilevich }
1867f4c7948SUgen J.S. Antsilevich
1878d43ce09SDima Dorfman static void
setup_scr(void)18848462fb1SWarner Losh setup_scr(void)
1897f4c7948SUgen J.S. Antsilevich {
1908d43ce09SDima Dorfman char *cbuf = gbuf, *term;
191f1007076SEd Schouten
1927f4c7948SUgen J.S. Antsilevich if (!opt_interactive)
1937f4c7948SUgen J.S. Antsilevich return;
1947f4c7948SUgen J.S. Antsilevich if ((term = getenv("TERM")))
1957f4c7948SUgen J.S. Antsilevich if (tgetent(tbuf, term) == 1)
1967f4c7948SUgen J.S. Antsilevich if (tgetstr("cl", &cbuf))
1977f4c7948SUgen J.S. Antsilevich clear_ok = 1;
1987f4c7948SUgen J.S. Antsilevich set_tty();
1998a9c3560SAndrey A. Chernov clear();
2007f4c7948SUgen J.S. Antsilevich }
2017f4c7948SUgen J.S. Antsilevich
2028d43ce09SDima Dorfman static void
detach_snp(void)20348462fb1SWarner Losh detach_snp(void)
2047f4c7948SUgen J.S. Antsilevich {
2056ed0b39dSRuslan Ermilov int fd;
206cb95dc24SPaul Traina
2076ed0b39dSRuslan Ermilov fd = -1;
2086ed0b39dSRuslan Ermilov ioctl(snp_io, SNPSTTY, &fd);
2097f4c7948SUgen J.S. Antsilevich }
2107f4c7948SUgen J.S. Antsilevich
2118d43ce09SDima Dorfman static void
attach_snp(void)21248462fb1SWarner Losh attach_snp(void)
2137f4c7948SUgen J.S. Antsilevich {
214cb74d4b2SOlivier Houchard int snp_tty;
215cb74d4b2SOlivier Houchard
216cb74d4b2SOlivier Houchard snp_tty = open(dev_name, O_RDONLY | O_NONBLOCK);
217cb74d4b2SOlivier Houchard if (snp_tty < 0)
218cb74d4b2SOlivier Houchard fatal(EX_DATAERR, "can't open device");
2197f4c7948SUgen J.S. Antsilevich if (ioctl(snp_io, SNPSTTY, &snp_tty) != 0)
220dc763e50SPhilippe Charnier fatal(EX_UNAVAILABLE, "cannot attach to tty");
221cb74d4b2SOlivier Houchard close(snp_tty);
2227f4c7948SUgen J.S. Antsilevich if (opt_timestamp)
2237f4c7948SUgen J.S. Antsilevich timestamp("Logging Started.");
2247f4c7948SUgen J.S. Antsilevich }
2257f4c7948SUgen J.S. Antsilevich
2268d43ce09SDima Dorfman static void
set_dev(const char * name)22748462fb1SWarner Losh set_dev(const char *name)
2287f4c7948SUgen J.S. Antsilevich {
229cb95dc24SPaul Traina char buf[DEV_NAME_LEN];
230cb95dc24SPaul Traina struct stat sb;
2317f4c7948SUgen J.S. Antsilevich
2321a37aa56SDavid E. O'Brien if (strlen(name) > 5 && !strncmp(name, _PATH_DEV, sizeof _PATH_DEV - 1)) {
2332bb69a48SOllivier Robert snprintf(buf, sizeof buf, "%s", name);
23448462fb1SWarner Losh } else {
235c1209799SUgen J.S. Antsilevich if (strlen(name) == 2)
2361a37aa56SDavid E. O'Brien sprintf(buf, "%s%s", _PATH_TTY, name);
237c1209799SUgen J.S. Antsilevich else
2381a37aa56SDavid E. O'Brien sprintf(buf, "%s%s", _PATH_DEV, name);
239c1209799SUgen J.S. Antsilevich }
2407f4c7948SUgen J.S. Antsilevich
2412bb69a48SOllivier Robert if (*name == '\0' || stat(buf, &sb) < 0)
242dc763e50SPhilippe Charnier fatal(EX_DATAERR, "bad device name");
2432bb69a48SOllivier Robert
2442bb69a48SOllivier Robert if ((sb.st_mode & S_IFMT) != S_IFCHR)
245dc763e50SPhilippe Charnier fatal(EX_DATAERR, "must be a character device");
2467f4c7948SUgen J.S. Antsilevich
247ec15b81bSXin LI strlcpy(dev_name, buf, sizeof(dev_name));
248cb74d4b2SOlivier Houchard
2497f4c7948SUgen J.S. Antsilevich attach_snp();
2507f4c7948SUgen J.S. Antsilevich }
2517f4c7948SUgen J.S. Antsilevich
2527f4c7948SUgen J.S. Antsilevich void
ask_dev(char * dbuf,const char * msg)25348462fb1SWarner Losh ask_dev(char *dbuf, const char *msg)
2547f4c7948SUgen J.S. Antsilevich {
2557f4c7948SUgen J.S. Antsilevich char buf[DEV_NAME_LEN];
2567f4c7948SUgen J.S. Antsilevich int len;
2577f4c7948SUgen J.S. Antsilevich
2587f4c7948SUgen J.S. Antsilevich clear();
2597f4c7948SUgen J.S. Antsilevich unset_tty();
2607f4c7948SUgen J.S. Antsilevich
2617f4c7948SUgen J.S. Antsilevich if (msg)
2627f4c7948SUgen J.S. Antsilevich printf("%s\n", msg);
2638d43ce09SDima Dorfman if (dbuf)
2648d43ce09SDima Dorfman printf("Enter device name [%s]:", dbuf);
2657f4c7948SUgen J.S. Antsilevich else
2667f4c7948SUgen J.S. Antsilevich printf("Enter device name:");
2677f4c7948SUgen J.S. Antsilevich
2687f4c7948SUgen J.S. Antsilevich if (fgets(buf, DEV_NAME_LEN - 1, stdin)) {
2697f4c7948SUgen J.S. Antsilevich len = strlen(buf);
2707f4c7948SUgen J.S. Antsilevich if (buf[len - 1] == '\n')
2717f4c7948SUgen J.S. Antsilevich buf[len - 1] = '\0';
2727f4c7948SUgen J.S. Antsilevich if (buf[0] != '\0' && buf[0] != ' ')
2738d43ce09SDima Dorfman strcpy(dbuf, buf);
2747f4c7948SUgen J.S. Antsilevich }
2757f4c7948SUgen J.S. Antsilevich set_tty();
2767f4c7948SUgen J.S. Antsilevich }
2777f4c7948SUgen J.S. Antsilevich
278c1209799SUgen J.S. Antsilevich #define READB_LEN 5
2797f4c7948SUgen J.S. Antsilevich
280e46b89dcSPeter Wemm int
main(int ac,char * av[])28148462fb1SWarner Losh main(int ac, char *av[])
2827f4c7948SUgen J.S. Antsilevich {
2835cfe0423SPeter Grehan int ch, res, rv, nread;
284ba964e50SThomas Moestl size_t b_size = MIN_SIZE;
2855cfe0423SPeter Grehan char *buf, chb[READB_LEN];
2867f4c7948SUgen J.S. Antsilevich fd_set fd_s;
2877f4c7948SUgen J.S. Antsilevich
2883e37ec67SAndrey A. Chernov (void) setlocale(LC_TIME, "");
2893e37ec67SAndrey A. Chernov
2907f4c7948SUgen J.S. Antsilevich if (isatty(std_out))
2917f4c7948SUgen J.S. Antsilevich opt_interactive = 1;
2927f4c7948SUgen J.S. Antsilevich else
2937f4c7948SUgen J.S. Antsilevich opt_interactive = 0;
2947f4c7948SUgen J.S. Antsilevich
2951995d3a4SDima Dorfman while ((ch = getopt(ac, av, "Wciotnf:")) != -1)
2967f4c7948SUgen J.S. Antsilevich switch (ch) {
297c1209799SUgen J.S. Antsilevich case 'W':
298c1209799SUgen J.S. Antsilevich opt_write = 1;
299c1209799SUgen J.S. Antsilevich break;
3007f4c7948SUgen J.S. Antsilevich case 'c':
3017f4c7948SUgen J.S. Antsilevich opt_reconn_close = 1;
3027f4c7948SUgen J.S. Antsilevich break;
3037f4c7948SUgen J.S. Antsilevich case 'i':
3047f4c7948SUgen J.S. Antsilevich opt_interactive = 1;
3057f4c7948SUgen J.S. Antsilevich break;
3067f4c7948SUgen J.S. Antsilevich case 'o':
3077f4c7948SUgen J.S. Antsilevich opt_reconn_oflow = 1;
3087f4c7948SUgen J.S. Antsilevich break;
3097f4c7948SUgen J.S. Antsilevich case 't':
3107f4c7948SUgen J.S. Antsilevich opt_timestamp = 1;
3117f4c7948SUgen J.S. Antsilevich break;
3125009d1beSJordan K. Hubbard case 'n':
3135009d1beSJordan K. Hubbard opt_no_switch = 1;
3145009d1beSJordan K. Hubbard break;
3151995d3a4SDima Dorfman case 'f':
3161995d3a4SDima Dorfman opt_snpdev = optarg;
3171995d3a4SDima Dorfman break;
3187f4c7948SUgen J.S. Antsilevich case '?':
3197f4c7948SUgen J.S. Antsilevich default:
320dc763e50SPhilippe Charnier usage();
3217f4c7948SUgen J.S. Antsilevich }
3227f4c7948SUgen J.S. Antsilevich
32379e6a2c0SJilles Tjoelker tcgetattr(std_in, &otty);
32479e6a2c0SJilles Tjoelker
325fc66e618SDima Dorfman if (modfind("snp") == -1)
326fc66e618SDima Dorfman if (kldload("snp") == -1 || modfind("snp") == -1)
327fc66e618SDima Dorfman warn("snp module not available");
328fc66e618SDima Dorfman
3297f4c7948SUgen J.S. Antsilevich signal(SIGINT, cleanup);
3307f4c7948SUgen J.S. Antsilevich
3317f4c7948SUgen J.S. Antsilevich snp_io = open_snp();
332f8da56fdSChristian S.J. Peron setup_scr();
3337f4c7948SUgen J.S. Antsilevich
3347f4c7948SUgen J.S. Antsilevich if (*(av += optind) == NULL) {
3355009d1beSJordan K. Hubbard if (opt_interactive && !opt_no_switch)
3367f4c7948SUgen J.S. Antsilevich ask_dev(dev_name, MSG_INIT);
3377f4c7948SUgen J.S. Antsilevich else
338dc763e50SPhilippe Charnier fatal(EX_DATAERR, "no device name given");
3397f4c7948SUgen J.S. Antsilevich } else
340ec15b81bSXin LI strlcpy(dev_name, *av, sizeof(dev_name));
3417f4c7948SUgen J.S. Antsilevich
3427f4c7948SUgen J.S. Antsilevich set_dev(dev_name);
3437f4c7948SUgen J.S. Antsilevich
3447f4c7948SUgen J.S. Antsilevich if (!(buf = (char *) malloc(b_size)))
345dc763e50SPhilippe Charnier fatal(EX_UNAVAILABLE, "malloc failed");
3467f4c7948SUgen J.S. Antsilevich
3477f4c7948SUgen J.S. Antsilevich FD_ZERO(&fd_s);
3487f4c7948SUgen J.S. Antsilevich
3490ba64b27SEd Schouten for (;;) {
3507f4c7948SUgen J.S. Antsilevich if (opt_interactive)
3517f4c7948SUgen J.S. Antsilevich FD_SET(std_in, &fd_s);
3527f4c7948SUgen J.S. Antsilevich FD_SET(snp_io, &fd_s);
3537f4c7948SUgen J.S. Antsilevich res = select(snp_io + 1, &fd_s, NULL, NULL, NULL);
3547f4c7948SUgen J.S. Antsilevich if (opt_interactive && FD_ISSET(std_in, &fd_s)) {
355c1209799SUgen J.S. Antsilevich
356c1209799SUgen J.S. Antsilevich if ((res = ioctl(std_in, FIONREAD, &nread)) != 0)
357dc763e50SPhilippe Charnier fatal(EX_OSERR, "ioctl(FIONREAD)");
358c1209799SUgen J.S. Antsilevich if (nread > READB_LEN)
359c1209799SUgen J.S. Antsilevich nread = READB_LEN;
3608d43ce09SDima Dorfman rv = read(std_in, chb, nread);
361ba964e50SThomas Moestl if (rv == -1 || rv != nread)
362dc763e50SPhilippe Charnier fatal(EX_IOERR, "read (stdin) failed");
363c1209799SUgen J.S. Antsilevich
364c1209799SUgen J.S. Antsilevich switch (chb[0]) {
3657f4c7948SUgen J.S. Antsilevich case CHR_CLEAR:
3667f4c7948SUgen J.S. Antsilevich clear();
3677f4c7948SUgen J.S. Antsilevich break;
3687f4c7948SUgen J.S. Antsilevich case CHR_SWITCH:
36922f94a0aSRobert Watson if (!opt_no_switch) {
370c1209799SUgen J.S. Antsilevich detach_snp();
3717f4c7948SUgen J.S. Antsilevich ask_dev(dev_name, MSG_CHANGE);
3727f4c7948SUgen J.S. Antsilevich set_dev(dev_name);
3737f4c7948SUgen J.S. Antsilevich break;
37422f94a0aSRobert Watson }
3757f4c7948SUgen J.S. Antsilevich default:
376c1209799SUgen J.S. Antsilevich if (opt_write) {
3778d43ce09SDima Dorfman rv = write(snp_io, chb, nread);
378ba964e50SThomas Moestl if (rv == -1 || rv != nread) {
379c1209799SUgen J.S. Antsilevich detach_snp();
3805009d1beSJordan K. Hubbard if (opt_no_switch)
38148462fb1SWarner Losh fatal(EX_IOERR,
38248462fb1SWarner Losh "write failed");
383c1209799SUgen J.S. Antsilevich ask_dev(dev_name, MSG_NOWRITE);
384c1209799SUgen J.S. Antsilevich set_dev(dev_name);
385c1209799SUgen J.S. Antsilevich }
386c1209799SUgen J.S. Antsilevich }
387c1209799SUgen J.S. Antsilevich
3887f4c7948SUgen J.S. Antsilevich }
3897f4c7948SUgen J.S. Antsilevich }
3907f4c7948SUgen J.S. Antsilevich if (!FD_ISSET(snp_io, &fd_s))
3917f4c7948SUgen J.S. Antsilevich continue;
3927f4c7948SUgen J.S. Antsilevich
393ba964e50SThomas Moestl if ((res = ioctl(snp_io, FIONREAD, &nread)) != 0)
394dc763e50SPhilippe Charnier fatal(EX_OSERR, "ioctl(FIONREAD)");
3957f4c7948SUgen J.S. Antsilevich
396ba964e50SThomas Moestl switch (nread) {
3977f4c7948SUgen J.S. Antsilevich case SNP_OFLOW:
3987f4c7948SUgen J.S. Antsilevich if (opt_reconn_oflow)
3997f4c7948SUgen J.S. Antsilevich attach_snp();
4005009d1beSJordan K. Hubbard else if (opt_interactive && !opt_no_switch) {
4017f4c7948SUgen J.S. Antsilevich ask_dev(dev_name, MSG_OFLOW);
4027f4c7948SUgen J.S. Antsilevich set_dev(dev_name);
4037f4c7948SUgen J.S. Antsilevich } else
4048d43ce09SDima Dorfman cleanup(-1);
4052f92b79fSMike Heffner break;
4067f4c7948SUgen J.S. Antsilevich case SNP_DETACH:
4077f4c7948SUgen J.S. Antsilevich case SNP_TTYCLOSE:
4087f4c7948SUgen J.S. Antsilevich if (opt_reconn_close)
4097f4c7948SUgen J.S. Antsilevich attach_snp();
4105009d1beSJordan K. Hubbard else if (opt_interactive && !opt_no_switch) {
4117f4c7948SUgen J.S. Antsilevich ask_dev(dev_name, MSG_CLOSED);
4127f4c7948SUgen J.S. Antsilevich set_dev(dev_name);
4137f4c7948SUgen J.S. Antsilevich } else
4148d43ce09SDima Dorfman cleanup(-1);
4152f92b79fSMike Heffner break;
4167f4c7948SUgen J.S. Antsilevich default:
4177f4c7948SUgen J.S. Antsilevich if (nread < (b_size / 2) && (b_size / 2) > MIN_SIZE) {
4187f4c7948SUgen J.S. Antsilevich free(buf);
4197f4c7948SUgen J.S. Antsilevich if (!(buf = (char *) malloc(b_size / 2)))
420dc763e50SPhilippe Charnier fatal(EX_UNAVAILABLE, "malloc failed");
4217f4c7948SUgen J.S. Antsilevich b_size = b_size / 2;
4227f4c7948SUgen J.S. Antsilevich }
4237f4c7948SUgen J.S. Antsilevich if (nread > b_size) {
4247f4c7948SUgen J.S. Antsilevich b_size = (nread % 2) ? (nread + 1) : (nread);
4257f4c7948SUgen J.S. Antsilevich free(buf);
4267f4c7948SUgen J.S. Antsilevich if (!(buf = (char *) malloc(b_size)))
427dc763e50SPhilippe Charnier fatal(EX_UNAVAILABLE, "malloc failed");
4287f4c7948SUgen J.S. Antsilevich }
4298d43ce09SDima Dorfman rv = read(snp_io, buf, nread);
430ba964e50SThomas Moestl if (rv == -1 || rv != nread)
431dc763e50SPhilippe Charnier fatal(EX_IOERR, "read failed");
4328d43ce09SDima Dorfman rv = write(std_out, buf, nread);
433ba964e50SThomas Moestl if (rv == -1 || rv != nread)
434dc763e50SPhilippe Charnier fatal(EX_IOERR, "write failed");
4357f4c7948SUgen J.S. Antsilevich }
4367f4c7948SUgen J.S. Antsilevich } /* While */
4371e7ae6a9SPhilippe Charnier return(0);
4387f4c7948SUgen J.S. Antsilevich }
439