xref: /onnv-gate/usr/src/cmd/vntsd/cmd.c (revision 9250:884a8abe56e5)
11991Sheppo /*
21991Sheppo  * CDDL HEADER START
31991Sheppo  *
41991Sheppo  * The contents of this file are subject to the terms of the
51991Sheppo  * Common Development and Distribution License (the "License").
61991Sheppo  * You may not use this file except in compliance with the License.
71991Sheppo  *
81991Sheppo  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91991Sheppo  * or http://www.opensolaris.org/os/licensing.
101991Sheppo  * See the License for the specific language governing permissions
111991Sheppo  * and limitations under the License.
121991Sheppo  *
131991Sheppo  * When distributing Covered Code, include this CDDL HEADER in each
141991Sheppo  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151991Sheppo  * If applicable, add the following below this CDDL HEADER, with the
161991Sheppo  * fields enclosed by brackets "[]" replaced with your own identifying
171991Sheppo  * information: Portions Copyright [yyyy] [name of copyright owner]
181991Sheppo  *
191991Sheppo  * CDDL HEADER END
201991Sheppo  */
211991Sheppo /*
228498SChris.Gerhard@sun.com  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
231991Sheppo  * Use is subject to license terms.
241991Sheppo  */
251991Sheppo 
261991Sheppo /*
271991Sheppo  * Vntsd handles two types of special commands, one is telnet
281991Sheppo  * commands and another is vntsd special commands.
291991Sheppo  * telnet commands supported are:
301991Sheppo  * WILL
311991Sheppo  * WONT
321991Sheppo  * DO
331991Sheppo  * DONT
341991Sheppo  *  TEL_ECHO
351991Sheppo  *  SUPRESS
361991Sheppo  *  LINEMODE
371991Sheppo  * BRK
381991Sheppo  * AYT
391991Sheppo  * HT
408498SChris.Gerhard@sun.com  * NOP
411991Sheppo  *
421991Sheppo  * Vntsd special commands are:
43*9250SZachary.Kissel@Sun.COM  *  Send break			(~#)
44*9250SZachary.Kissel@Sun.COM  *  Send alternate break	(~^B)
45*9250SZachary.Kissel@Sun.COM  *  Exit			(~.)
46*9250SZachary.Kissel@Sun.COM  *  Force write access		(~w)
47*9250SZachary.Kissel@Sun.COM  *  Console next		(~n)
48*9250SZachary.Kissel@Sun.COM  *  Console previous		(~p)
49*9250SZachary.Kissel@Sun.COM  *  Help			(~?)
501991Sheppo  */
511991Sheppo 
521991Sheppo #include <stdio.h>
531991Sheppo #include <stdlib.h>
541991Sheppo #include <string.h>
551991Sheppo #include <unistd.h>
561991Sheppo #include <sys/types.h>
571991Sheppo #include <sys/socket.h>
581991Sheppo #include <netinet/in.h>
591991Sheppo #include <thread.h>
601991Sheppo #include <ctype.h>
611991Sheppo #include <sys/termio.h>
621991Sheppo #include <libintl.h>
631991Sheppo #include <syslog.h>
641991Sheppo #include "vntsd.h"
651991Sheppo #include "chars.h"
661991Sheppo 
671991Sheppo char vntsd_eol[] = { CR, LF, 0};
681991Sheppo 
691991Sheppo typedef	int	    (*e_func_t)(vntsd_client_t *clientp);
701991Sheppo /* structure for daemon special cmd */
711991Sheppo typedef struct {
721991Sheppo 	char e_char;				/* char to match on */
731991Sheppo 	char *e_help;				/* help string */
741991Sheppo 	e_func_t e_func;			/* command */
751991Sheppo } esctable_t;
761991Sheppo 
771991Sheppo /* genbrk() -  send a break to vcc driver */
781991Sheppo static int
791991Sheppo genbrk(vntsd_client_t *clientp)
801991Sheppo {
811991Sheppo 
821991Sheppo 	vntsd_cons_t *consp;
831991Sheppo 
841991Sheppo 	assert(clientp);
851991Sheppo 	assert(clientp->cons);
861991Sheppo 
871991Sheppo 	consp = clientp->cons;
881991Sheppo 	D1(stderr, "t@%d genbrk fd=%d sockfd %d\n", thr_self(),
891991Sheppo 	    consp->vcc_fd, clientp->sockfd);
901991Sheppo 
911991Sheppo 	assert(consp->clientpq != NULL);
921991Sheppo 	if (consp->clientpq->handle != clientp) {
931991Sheppo 		/* reader */
941991Sheppo 		return (vntsd_write_line(clientp,
958498SChris.Gerhard@sun.com 		    gettext(VNTSD_NO_WRITE_ACCESS_MSG)));
961991Sheppo 	}
971991Sheppo 
981991Sheppo 	/* writer */
991991Sheppo 	if (ioctl(consp->vcc_fd, TCSBRK, NULL)) {
1001991Sheppo 		return (VNTSD_ERR_VCC_IOCTL);
1011991Sheppo 	}
1021991Sheppo 
1031991Sheppo 	return (VNTSD_STATUS_CONTINUE);
1041991Sheppo }
1051991Sheppo 
106*9250SZachary.Kissel@Sun.COM 
107*9250SZachary.Kissel@Sun.COM /* genaltbrk() - handle the alternate break sequence */
108*9250SZachary.Kissel@Sun.COM static int
109*9250SZachary.Kissel@Sun.COM genaltbrk(vntsd_client_t *clientp)
110*9250SZachary.Kissel@Sun.COM {
111*9250SZachary.Kissel@Sun.COM 	vntsd_cons_t *consp;
112*9250SZachary.Kissel@Sun.COM 	char brkseq[2] = { '~', CNTRL('B')};
113*9250SZachary.Kissel@Sun.COM 
114*9250SZachary.Kissel@Sun.COM 	assert(clientp);
115*9250SZachary.Kissel@Sun.COM 	assert(clientp->cons);
116*9250SZachary.Kissel@Sun.COM 
117*9250SZachary.Kissel@Sun.COM 	consp = clientp->cons;
118*9250SZachary.Kissel@Sun.COM 	D1(stderr, "t@%d genaltbrk fd=%d sockfd %d\n", thr_self(),
119*9250SZachary.Kissel@Sun.COM 	    consp->vcc_fd, clientp->sockfd);
120*9250SZachary.Kissel@Sun.COM 
121*9250SZachary.Kissel@Sun.COM 	assert(consp->clientpq != NULL);
122*9250SZachary.Kissel@Sun.COM 	if (consp->clientpq->handle != clientp) {
123*9250SZachary.Kissel@Sun.COM 		/* reader */
124*9250SZachary.Kissel@Sun.COM 		return (vntsd_write_line(clientp,
125*9250SZachary.Kissel@Sun.COM 		    gettext(VNTSD_NO_WRITE_ACCESS_MSG)));
126*9250SZachary.Kissel@Sun.COM 	}
127*9250SZachary.Kissel@Sun.COM 
128*9250SZachary.Kissel@Sun.COM 	/*
129*9250SZachary.Kissel@Sun.COM 	 * Unlike the genbrk() function we will just forward the break sequence
130*9250SZachary.Kissel@Sun.COM 	 * on to vcc and subsequently the underlying console driver. This will
131*9250SZachary.Kissel@Sun.COM 	 * involve sending the characters '~' and CNTRL('B').
132*9250SZachary.Kissel@Sun.COM 	 */
133*9250SZachary.Kissel@Sun.COM 	if ((vntsd_write_fd(clientp->cons->vcc_fd, brkseq, sizeof (brkseq))) ==
134*9250SZachary.Kissel@Sun.COM 	    VNTSD_SUCCESS)
135*9250SZachary.Kissel@Sun.COM 		return (VNTSD_STATUS_CONTINUE);
136*9250SZachary.Kissel@Sun.COM 	else
137*9250SZachary.Kissel@Sun.COM 		return (VNTSD_STATUS_VCC_IO_ERR);
138*9250SZachary.Kissel@Sun.COM }
139*9250SZachary.Kissel@Sun.COM 
1401991Sheppo /*
1411991Sheppo  * console_forward()  - cycle client to the next console
1421991Sheppo  * in the group queue.
1431991Sheppo  */
1441991Sheppo static int
1452956Sdtse console_forward(vntsd_client_t *clientp)
1461991Sheppo {
1472956Sdtse 	/* forward when there are mutiple consoles in the group */
1482956Sdtse 	if (clientp->cons->group->num_cons > 1)
1492956Sdtse 		return (VNTSD_STATUS_MOV_CONS_FORWARD);
1502956Sdtse 
1512956Sdtse 	return (VNTSD_STATUS_CONTINUE);
1522956Sdtse 
1531991Sheppo }
1541991Sheppo 
1551991Sheppo /*
1561991Sheppo  * console_backward()  - cycle client to the previous
1571991Sheppo  * console in the group queue.
1581991Sheppo  */
1591991Sheppo static int
1602956Sdtse console_backward(vntsd_client_t *clientp)
1611991Sheppo {
1622956Sdtse 	/* backward when there are mutiple consoles in the group */
1632956Sdtse 	if (clientp->cons->group->num_cons > 1)
1642956Sdtse 		return (VNTSD_STATUS_MOV_CONS_BACKWARD);
1652956Sdtse 
1662956Sdtse 	return (VNTSD_STATUS_CONTINUE);
1672956Sdtse 
1681991Sheppo }
1691991Sheppo 
1701991Sheppo /* acquire_write() - acquire write access to a console. */
1711991Sheppo static int
1721991Sheppo acquire_write(vntsd_client_t *clientp)
1731991Sheppo {
1741991Sheppo 	int	rv;
1751991Sheppo 	int	yes_no = 1;
1761991Sheppo 	vntsd_cons_t *consp;
1771991Sheppo 
1781991Sheppo 	assert(clientp);
1791991Sheppo 	consp = clientp->cons;
1801991Sheppo 	assert(consp);
1811991Sheppo 
1821991Sheppo 	if (consp->clientpq->handle == clientp) {
1831991Sheppo 		/* client is a  writer */
1841991Sheppo 		if ((rv = vntsd_write_line(clientp,
1858498SChris.Gerhard@sun.com 		    gettext("You have write permission"))) !=
1861991Sheppo 		    VNTSD_SUCCESS) {
1871991Sheppo 			return (rv);
1881991Sheppo 
1891991Sheppo 		}
1901991Sheppo 		return (VNTSD_STATUS_CONTINUE);
1911991Sheppo 	}
1921991Sheppo 
1931991Sheppo 	/* message to client */
1941991Sheppo 	if ((rv = vntsd_write_client(clientp, vntsd_eol, VNTSD_EOL_LEN))
1951991Sheppo 	    != VNTSD_SUCCESS) {
1961991Sheppo 		return (rv);
1971991Sheppo 	}
1981991Sheppo 
1991991Sheppo 	/*
2001991Sheppo 	 * TRANSLATION_NOTE
2011991Sheppo 	 * The following string should be formatted to fit on multiple lines
2021991Sheppo 	 * assuming a line width of at most 78 characters. There must be no
2031991Sheppo 	 * trailing newline.
2041991Sheppo 	 */
2051991Sheppo 	if ((rv = vntsd_write_lines(clientp,
2068498SChris.Gerhard@sun.com 	    gettext("Warning: another user currently "
2071991Sheppo 	    "has write permission\nto this console and forcibly removing "
2081991Sheppo 	    "him/her will terminate\nany current write action and all work "
2091991Sheppo 	    "will be lost."))) != VNTSD_SUCCESS) {
2101991Sheppo 		return (rv);
2111991Sheppo 	}
2121991Sheppo 
2131991Sheppo 	/* get client yes no */
2141991Sheppo 	if ((rv = vntsd_write_client(clientp, vntsd_eol,
2158498SChris.Gerhard@sun.com 	    VNTSD_EOL_LEN)) != VNTSD_SUCCESS) {
2161991Sheppo 		return (rv);
2171991Sheppo 	}
2181991Sheppo 
2191991Sheppo 	if ((rv = vntsd_get_yes_no(clientp,
2208498SChris.Gerhard@sun.com 	    gettext("Would you like to continue?"),
2218498SChris.Gerhard@sun.com 	    &yes_no)) != VNTSD_SUCCESS) {
2221991Sheppo 		return (rv);
2231991Sheppo 	}
2241991Sheppo 
2251991Sheppo 	if (yes_no == B_FALSE) {
2261991Sheppo 		/* client change mind no need to acquire  write access */
2271991Sheppo 		return (VNTSD_STATUS_CONTINUE);
2281991Sheppo 	}
2291991Sheppo 
2301991Sheppo 	return (VNTSD_STATUS_ACQUIRE_WRITER);
2311991Sheppo }
2321991Sheppo 
2331991Sheppo /* client_exit()  - disconnect client from the console. */
2341991Sheppo static int
2351991Sheppo client_exit(void)
2361991Sheppo {
2371991Sheppo 	return (VNTSD_STATUS_RESELECT_CONS);
2381991Sheppo }
2391991Sheppo 
2401991Sheppo static int daemon_cmd_help(vntsd_client_t *clientp);
2411991Sheppo 
2421991Sheppo /* table for daemon commands */
2431991Sheppo 
2441991Sheppo static esctable_t  etable[] = {
2451991Sheppo 
2461991Sheppo 	/* send a break to vcc */
2472109Slm66018 	{'#', "Send break",  genbrk},
2481991Sheppo 
249*9250SZachary.Kissel@Sun.COM 	/* alternate break sequence */
250*9250SZachary.Kissel@Sun.COM 	{CNTRL('B'), "Send alternate break", genaltbrk},
251*9250SZachary.Kissel@Sun.COM 
2521991Sheppo 	/* exit */
2532109Slm66018 	{'.', "Exit from this console",  (e_func_t)client_exit},
2541991Sheppo 
2551991Sheppo 	/* acquire write access */
2562109Slm66018 	{'w', "Force write access", acquire_write},
2571991Sheppo 
2581991Sheppo 	/* connect to next console in queue */
2592109Slm66018 	{'n', "Console next", (e_func_t)console_forward},
2601991Sheppo 
2611991Sheppo 	/* connect to previous console in queue */
2622109Slm66018 	{'p', "Console previous", (e_func_t)console_backward},
2631991Sheppo 
2641991Sheppo 	/* help must be next to last */
2652109Slm66018 	{'?', "Help", daemon_cmd_help},
2661991Sheppo 
2671991Sheppo 	/* table terminator */
2681991Sheppo 	{0, 0, 0}
2691991Sheppo };
2701991Sheppo 
2711991Sheppo void
2721991Sheppo vntsd_init_esctable_msgs(void)
2731991Sheppo {
2741991Sheppo 	esctable_t  *p;
2751991Sheppo 
2761991Sheppo 	for (p = etable; p->e_char != '\0'; p++) {
2771991Sheppo 		p->e_help = gettext(p->e_help);
2781991Sheppo 	}
2791991Sheppo }
2801991Sheppo 
2811991Sheppo /* daemon_cmd_help() - print help. */
2821991Sheppo static int
2831991Sheppo daemon_cmd_help(vntsd_client_t *clientp)
2841991Sheppo {
2851991Sheppo 	esctable_t  *p;
2861991Sheppo 	int	    rv;
2871991Sheppo 	char	    buf[VNTSD_LINE_LEN];
2881991Sheppo 
2891991Sheppo 	if ((rv = vntsd_write_client(clientp, vntsd_eol,
2908498SChris.Gerhard@sun.com 	    VNTSD_EOL_LEN)) != VNTSD_SUCCESS) {
2918498SChris.Gerhard@sun.com 		return (rv);
2921991Sheppo 	}
2931991Sheppo 
2941991Sheppo 	/*
2951991Sheppo 	 * TRANSLATION_NOTE
2961991Sheppo 	 * VNTSD is the name of the VNTS daemon and should not be translated.
2971991Sheppo 	 */
2981991Sheppo 	if ((rv = vntsd_write_line(clientp, gettext("VNTSD commands"))) !=
2991991Sheppo 	    VNTSD_SUCCESS) {
3001991Sheppo 		return (rv);
3011991Sheppo 	}
3021991Sheppo 
3031991Sheppo 	for (p = etable; p->e_char; p++) {
304*9250SZachary.Kissel@Sun.COM 
305*9250SZachary.Kissel@Sun.COM 		if (p->e_char == CNTRL('B')) {
306*9250SZachary.Kissel@Sun.COM 			(void) snprintf(buf, sizeof (buf), "~^B --%s",
307*9250SZachary.Kissel@Sun.COM 			    p->e_help);
308*9250SZachary.Kissel@Sun.COM 		} else {
309*9250SZachary.Kissel@Sun.COM 			(void) snprintf(buf, sizeof (buf),
310*9250SZachary.Kissel@Sun.COM 			    "~%c --%s", p->e_char, p->e_help);
311*9250SZachary.Kissel@Sun.COM 		}
3121991Sheppo 
3131991Sheppo 		if ((rv = vntsd_write_line(clientp, buf)) != VNTSD_SUCCESS) {
3141991Sheppo 			return (rv);
3151991Sheppo 		}
3161991Sheppo 	}
3171991Sheppo 
3181991Sheppo 	return (VNTSD_STATUS_CONTINUE);
3191991Sheppo }
3201991Sheppo 
3211991Sheppo /* exit from daemon command */
3221991Sheppo static int
3231991Sheppo exit_daemon_cmd(vntsd_client_t *clientp, int rv)
3241991Sheppo {
3251991Sheppo 	(void) mutex_lock(&clientp->lock);
3261991Sheppo 	clientp->status &= ~VNTSD_CLIENT_DISABLE_DAEMON_CMD;
3271991Sheppo 	(void) mutex_unlock(&clientp->lock);
3281991Sheppo 	return (rv);
3291991Sheppo }
3301991Sheppo 
3312336Snarayan /*
3322336Snarayan  * vntsd_process_daemon_cmd() - special commands
3332336Snarayan  * "<RET>~"  vntsd daemon commands
3342336Snarayan  * "<RET>~~" enter '~' character
3352336Snarayan  */
3361991Sheppo int
3371991Sheppo vntsd_process_daemon_cmd(vntsd_client_t *clientp, char c)
3381991Sheppo {
3391991Sheppo 	esctable_t *p;
3401991Sheppo 	int	    rv;
3412336Snarayan 	char	    prev_char;
3421991Sheppo 
3432336Snarayan 	prev_char = clientp->prev_char;
3442336Snarayan 
3452336Snarayan 	if (c != VNTSD_DAEMON_CMD || (prev_char != 0 && prev_char != CR)) {
3461991Sheppo 		/* not a daemon command */
3471991Sheppo 		return (VNTSD_SUCCESS);
3481991Sheppo 	}
3491991Sheppo 
3501991Sheppo 	if (clientp->status & VNTSD_CLIENT_DISABLE_DAEMON_CMD) {
3511991Sheppo 		return (VNTSD_STATUS_CONTINUE);
3521991Sheppo 	}
3531991Sheppo 
3541991Sheppo 	/* no reentry to process_daemon_cmd */
3551991Sheppo 	(void) mutex_lock(&clientp->lock);
3561991Sheppo 	clientp->status |= VNTSD_CLIENT_DISABLE_DAEMON_CMD;
3571991Sheppo 	(void) mutex_unlock(&clientp->lock);
3581991Sheppo 
3591991Sheppo 	D3(stderr, "t@%d process_daemon_cmd %d %d \n", thr_self(),
3601991Sheppo 	    clientp->cons->vcc_fd, clientp->sockfd);
3611991Sheppo 
3621991Sheppo 	/* read in command */
3631991Sheppo 	if ((rv = vntsd_read_char(clientp, &c)) != VNTSD_SUCCESS) {
3641991Sheppo 		return (exit_daemon_cmd(clientp, rv));
3651991Sheppo 	}
3661991Sheppo 
3672336Snarayan 	if (c == VNTSD_DAEMON_CMD) {
3682336Snarayan 		/*
3692336Snarayan 		 * received another '~'
3702336Snarayan 		 * a user types '~~' to get '~'
3712336Snarayan 		 */
3722336Snarayan 		(void) mutex_lock(&clientp->lock);
3732336Snarayan 		clientp->status &= ~VNTSD_CLIENT_DISABLE_DAEMON_CMD;
3742336Snarayan 		(void) mutex_unlock(&clientp->lock);
3752336Snarayan 		return (VNTSD_SUCCESS);
3762336Snarayan 	}
3772336Snarayan 
3781991Sheppo 	for (p = etable; p->e_char; p++) {
3791991Sheppo 		if (p->e_char == c) {
3801991Sheppo 			/* found match */
3811991Sheppo 			assert(p->e_func);
3821991Sheppo 			rv = (*p->e_func)(clientp);
3831991Sheppo 			return (exit_daemon_cmd(clientp, rv));
3841991Sheppo 		}
3851991Sheppo 	}
3861991Sheppo 
3871991Sheppo 	/* no match, print out the help */
3881991Sheppo 	p--;
3891991Sheppo 	assert(p->e_char == '?');
3901991Sheppo 	rv = (*p->e_func)(clientp);
3911991Sheppo 
3921991Sheppo 	return (exit_daemon_cmd(clientp, rv));
3931991Sheppo 
3941991Sheppo }
3951991Sheppo 
3961991Sheppo /* vntsd_set_telnet_options() - change  telnet client to  character mode. */
3971991Sheppo int
3981991Sheppo vntsd_set_telnet_options(int fd)
3991991Sheppo {
4001991Sheppo 	/* set client telnet options */
4011991Sheppo 	uint8_t buf[] = {IAC, DONT, LINEMODE, IAC, WILL, SUPRESS, IAC, WILL,
4021991Sheppo 		TEL_ECHO, IAC, DONT, TERM_TYPE, IAC, DONT, TERM_SP,
4031991Sheppo 		IAC, DONT, STATUS, IAC, DONT, FC, IAC, DONT, TM, IAC, DONT, ENV,
4041991Sheppo 		IAC, DONT, WIN_SIZE};
4051991Sheppo 
4061991Sheppo 	return (vntsd_write_fd(fd, (char *)buf, 30));
4071991Sheppo }
4081991Sheppo 
4091991Sheppo /*  vntsd_telnet_cmd() process telnet commands */
4101991Sheppo int
4111991Sheppo vntsd_telnet_cmd(vntsd_client_t *clientp, char c)
4121991Sheppo {
4131991Sheppo 	uint8_t	buf[4];
4141991Sheppo 	char	cmd;
4151991Sheppo 	int	rv = VNTSD_STATUS_CONTINUE;
4161991Sheppo 
4171991Sheppo 	bzero(buf, 4);
4181991Sheppo 
4191991Sheppo 	if ((uint8_t)c != IAC) {
4201991Sheppo 		/* not telnet cmd */
4211991Sheppo 		return (VNTSD_SUCCESS);
4221991Sheppo 	}
4231991Sheppo 
4241991Sheppo 	if ((rv = vntsd_read_char(clientp, &cmd)) != VNTSD_SUCCESS) {
4251991Sheppo 		return (rv);
4261991Sheppo 	}
4271991Sheppo 
4288498SChris.Gerhard@sun.com 	if ((uint8_t)cmd == WILL || (uint8_t)cmd == WONT ||
4298498SChris.Gerhard@sun.com 	    (uint8_t)cmd == DO || (uint8_t)cmd == DONT) {
4305757Sdtse 		if ((rv = vntsd_read_char(clientp, &c)) != VNTSD_SUCCESS) {
4315757Sdtse 			return (rv);
4325757Sdtse 		}
4331991Sheppo 	}
4341991Sheppo 
4351991Sheppo 
4361991Sheppo 	switch ((uint8_t)cmd) {
4371991Sheppo 
4381991Sheppo 	case WILL:
4391991Sheppo 
4401991Sheppo 		switch ((uint8_t)c) {
4411991Sheppo 		case TEL_ECHO:
4421991Sheppo 		case SUPRESS:
4431991Sheppo 		case LINEMODE:
4441991Sheppo 			break;
4451991Sheppo 		default:
4461991Sheppo 			syslog(LOG_ERR, "not support telnet WILL %x\n", c);
4471991Sheppo 			break;
4481991Sheppo 		}
4491991Sheppo 		break;
4501991Sheppo 
4511991Sheppo 	case  WONT:
4521991Sheppo 
4531991Sheppo 		switch ((uint8_t)c) {
4541991Sheppo 		case TEL_ECHO:
4551991Sheppo 		case SUPRESS:
4561991Sheppo 		case LINEMODE:
4571991Sheppo 		default:
4581991Sheppo 			syslog(LOG_ERR, "not support telnet WONT %x\n", c);
4591991Sheppo 			break;
4601991Sheppo 		}
4611991Sheppo 		break;
4621991Sheppo 
4631991Sheppo 	case DO:
4641991Sheppo 	case DONT:
4651991Sheppo 
4661991Sheppo 		buf[0] = IAC;
4671991Sheppo 		buf[1] = WILL;
4681991Sheppo 		buf[2] = c;
4691991Sheppo 		rv = vntsd_write_client(clientp, (char *)buf, 3);
4701991Sheppo 
4711991Sheppo 		break;
4721991Sheppo 
4731991Sheppo 	case BRK:
4741991Sheppo 
4751991Sheppo 		/* send break to vcc */
4761991Sheppo 		rv = genbrk(clientp);
4771991Sheppo 		break;
4781991Sheppo 
4791991Sheppo 	case IP:
4801991Sheppo 
4811991Sheppo 		break;
4821991Sheppo 
4838498SChris.Gerhard@sun.com 	case AYT: {
4848498SChris.Gerhard@sun.com 			static char aytresp[] = "vntsd here";
4851991Sheppo 
4868498SChris.Gerhard@sun.com 			rv = vntsd_write_client(clientp, aytresp,
4878498SChris.Gerhard@sun.com 			    sizeof (aytresp) - 1);
4888498SChris.Gerhard@sun.com 			break;
4898498SChris.Gerhard@sun.com 		}
4901991Sheppo 
4911991Sheppo 	case HT:
4928498SChris.Gerhard@sun.com 	case NOP:
4931991Sheppo 		return (VNTSD_STATUS_CONTINUE);
4941991Sheppo 
4951991Sheppo 	default:
4968498SChris.Gerhard@sun.com 		syslog(LOG_ERR, "not support telnet ctrl %2.2x\n", 0xff & cmd);
4971991Sheppo 		break;
4981991Sheppo 	}
4991991Sheppo 
5001991Sheppo 	if (rv == VNTSD_SUCCESS) {
5011991Sheppo 		return (VNTSD_STATUS_CONTINUE);
5021991Sheppo 	} else {
5031991Sheppo 		return (rv);
5041991Sheppo 	}
5051991Sheppo }
5061991Sheppo 
5071991Sheppo 
5081991Sheppo /*
5091991Sheppo  * vntsd_ctrl_cmd()   - control keys
5101991Sheppo  * read and write suspend are supported.
5111991Sheppo  */
5121991Sheppo int
5131991Sheppo vntsd_ctrl_cmd(vntsd_client_t *clientp, char c)
5141991Sheppo {
5151991Sheppo 	int	cmd;
5161991Sheppo 
5171991Sheppo 	D3(stderr, "t@%d vntsd_ctrl_cmd%d %d\n", thr_self(),
5181991Sheppo 	    clientp->cons->vcc_fd, clientp->sockfd);
5191991Sheppo 
5201991Sheppo 	if ((c != START) && (c != STOP)) {
5211991Sheppo 		/* not a supported control command */
5221991Sheppo 		return (VNTSD_SUCCESS);
5231991Sheppo 	}
5241991Sheppo 
5251991Sheppo 	if (c == START) {
5261991Sheppo 		D3(stderr, "t@%d client restart\n", thr_self());
5271991Sheppo 
5281991Sheppo 		/* send resume read */
5291991Sheppo 		cmd = 1;
5301991Sheppo 
5311991Sheppo 		if (ioctl(clientp->cons->vcc_fd, TCXONC, &cmd)) {
5321991Sheppo 			return (VNTSD_STATUS_VCC_IO_ERR);
5331991Sheppo 		}
5341991Sheppo 
5351991Sheppo 	}
5361991Sheppo 
5371991Sheppo 	if (c == STOP) {
5381991Sheppo 		D3(stderr, "t@%d client suspend\n", thr_self());
5391991Sheppo 
5401991Sheppo 		/* send suspend read */
5411991Sheppo 		cmd = 0;
5421991Sheppo 
5431991Sheppo 		if (ioctl(clientp->cons->vcc_fd, TCXONC, &cmd)) {
5441991Sheppo 			return (VNTSD_STATUS_VCC_IO_ERR);
5451991Sheppo 		}
5461991Sheppo 
5471991Sheppo 	}
5481991Sheppo 
5491991Sheppo 	return (VNTSD_STATUS_CONTINUE);
5501991Sheppo }
551