xref: /titanic_44/usr/src/cmd/vntsd/cmd.c (revision 41c9e69b58fe2a9435d761668499423fa1466a5a)
11ae08745Sheppo /*
21ae08745Sheppo  * CDDL HEADER START
31ae08745Sheppo  *
41ae08745Sheppo  * The contents of this file are subject to the terms of the
51ae08745Sheppo  * Common Development and Distribution License (the "License").
61ae08745Sheppo  * You may not use this file except in compliance with the License.
71ae08745Sheppo  *
81ae08745Sheppo  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91ae08745Sheppo  * or http://www.opensolaris.org/os/licensing.
101ae08745Sheppo  * See the License for the specific language governing permissions
111ae08745Sheppo  * and limitations under the License.
121ae08745Sheppo  *
131ae08745Sheppo  * When distributing Covered Code, include this CDDL HEADER in each
141ae08745Sheppo  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151ae08745Sheppo  * If applicable, add the following below this CDDL HEADER, with the
161ae08745Sheppo  * fields enclosed by brackets "[]" replaced with your own identifying
171ae08745Sheppo  * information: Portions Copyright [yyyy] [name of copyright owner]
181ae08745Sheppo  *
191ae08745Sheppo  * CDDL HEADER END
201ae08745Sheppo  */
211ae08745Sheppo /*
22a93081c1SChris Gerhard  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
231ae08745Sheppo  * Use is subject to license terms.
241ae08745Sheppo  */
251ae08745Sheppo 
261ae08745Sheppo /*
271ae08745Sheppo  * Vntsd handles two types of special commands, one is telnet
281ae08745Sheppo  * commands and another is vntsd special commands.
291ae08745Sheppo  * telnet commands supported are:
301ae08745Sheppo  * WILL
311ae08745Sheppo  * WONT
321ae08745Sheppo  * DO
331ae08745Sheppo  * DONT
341ae08745Sheppo  *  TEL_ECHO
351ae08745Sheppo  *  SUPRESS
361ae08745Sheppo  *  LINEMODE
371ae08745Sheppo  * BRK
381ae08745Sheppo  * AYT
391ae08745Sheppo  * HT
40a93081c1SChris Gerhard  * NOP
411ae08745Sheppo  *
421ae08745Sheppo  * Vntsd special commands are:
438e6a2a04Slm66018  *  Send break			(~#)
44*41c9e69bSZach Kissel  *  Send alternate break	(~^B)
458e6a2a04Slm66018  *  Exit			(~.)
468e6a2a04Slm66018  *  Force write access		(~w)
478e6a2a04Slm66018  *  Console next		(~n)
488e6a2a04Slm66018  *  Console previous		(~p)
498e6a2a04Slm66018  *  Help			(~?)
501ae08745Sheppo  */
511ae08745Sheppo 
521ae08745Sheppo #include <stdio.h>
531ae08745Sheppo #include <stdlib.h>
541ae08745Sheppo #include <string.h>
551ae08745Sheppo #include <unistd.h>
561ae08745Sheppo #include <sys/types.h>
571ae08745Sheppo #include <sys/socket.h>
581ae08745Sheppo #include <netinet/in.h>
591ae08745Sheppo #include <thread.h>
601ae08745Sheppo #include <ctype.h>
611ae08745Sheppo #include <sys/termio.h>
621ae08745Sheppo #include <libintl.h>
631ae08745Sheppo #include <syslog.h>
641ae08745Sheppo #include "vntsd.h"
651ae08745Sheppo #include "chars.h"
661ae08745Sheppo 
671ae08745Sheppo char vntsd_eol[] = { CR, LF, 0};
681ae08745Sheppo 
691ae08745Sheppo typedef	int	    (*e_func_t)(vntsd_client_t *clientp);
701ae08745Sheppo /* structure for daemon special cmd */
711ae08745Sheppo typedef struct {
721ae08745Sheppo 	char e_char;				/* char to match on */
731ae08745Sheppo 	char *e_help;				/* help string */
741ae08745Sheppo 	e_func_t e_func;			/* command */
751ae08745Sheppo } esctable_t;
761ae08745Sheppo 
771ae08745Sheppo /* genbrk() -  send a break to vcc driver */
781ae08745Sheppo static int
791ae08745Sheppo genbrk(vntsd_client_t *clientp)
801ae08745Sheppo {
811ae08745Sheppo 
821ae08745Sheppo 	vntsd_cons_t *consp;
831ae08745Sheppo 
841ae08745Sheppo 	assert(clientp);
851ae08745Sheppo 	assert(clientp->cons);
861ae08745Sheppo 
871ae08745Sheppo 	consp = clientp->cons;
881ae08745Sheppo 	D1(stderr, "t@%d genbrk fd=%d sockfd %d\n", thr_self(),
891ae08745Sheppo 	    consp->vcc_fd, clientp->sockfd);
901ae08745Sheppo 
911ae08745Sheppo 	assert(consp->clientpq != NULL);
921ae08745Sheppo 	if (consp->clientpq->handle != clientp) {
931ae08745Sheppo 		/* reader */
941ae08745Sheppo 		return (vntsd_write_line(clientp,
951ae08745Sheppo 		    gettext(VNTSD_NO_WRITE_ACCESS_MSG)));
961ae08745Sheppo 	}
971ae08745Sheppo 
981ae08745Sheppo 	/* writer */
991ae08745Sheppo 	if (ioctl(consp->vcc_fd, TCSBRK, NULL)) {
1001ae08745Sheppo 		return (VNTSD_ERR_VCC_IOCTL);
1011ae08745Sheppo 	}
1021ae08745Sheppo 
1031ae08745Sheppo 	return (VNTSD_STATUS_CONTINUE);
1041ae08745Sheppo }
1051ae08745Sheppo 
106*41c9e69bSZach Kissel 
107*41c9e69bSZach Kissel /* genaltbrk() - handle the alternate break sequence */
108*41c9e69bSZach Kissel static int
109*41c9e69bSZach Kissel genaltbrk(vntsd_client_t *clientp)
110*41c9e69bSZach Kissel {
111*41c9e69bSZach Kissel 	vntsd_cons_t *consp;
112*41c9e69bSZach Kissel 	char brkseq[2] = { '~', CNTRL('B')};
113*41c9e69bSZach Kissel 
114*41c9e69bSZach Kissel 	assert(clientp);
115*41c9e69bSZach Kissel 	assert(clientp->cons);
116*41c9e69bSZach Kissel 
117*41c9e69bSZach Kissel 	consp = clientp->cons;
118*41c9e69bSZach Kissel 	D1(stderr, "t@%d genaltbrk fd=%d sockfd %d\n", thr_self(),
119*41c9e69bSZach Kissel 	    consp->vcc_fd, clientp->sockfd);
120*41c9e69bSZach Kissel 
121*41c9e69bSZach Kissel 	assert(consp->clientpq != NULL);
122*41c9e69bSZach Kissel 	if (consp->clientpq->handle != clientp) {
123*41c9e69bSZach Kissel 		/* reader */
124*41c9e69bSZach Kissel 		return (vntsd_write_line(clientp,
125*41c9e69bSZach Kissel 		    gettext(VNTSD_NO_WRITE_ACCESS_MSG)));
126*41c9e69bSZach Kissel 	}
127*41c9e69bSZach Kissel 
128*41c9e69bSZach Kissel 	/*
129*41c9e69bSZach Kissel 	 * Unlike the genbrk() function we will just forward the break sequence
130*41c9e69bSZach Kissel 	 * on to vcc and subsequently the underlying console driver. This will
131*41c9e69bSZach Kissel 	 * involve sending the characters '~' and CNTRL('B').
132*41c9e69bSZach Kissel 	 */
133*41c9e69bSZach Kissel 	if ((vntsd_write_fd(clientp->cons->vcc_fd, brkseq, sizeof (brkseq))) ==
134*41c9e69bSZach Kissel 	    VNTSD_SUCCESS)
135*41c9e69bSZach Kissel 		return (VNTSD_STATUS_CONTINUE);
136*41c9e69bSZach Kissel 	else
137*41c9e69bSZach Kissel 		return (VNTSD_STATUS_VCC_IO_ERR);
138*41c9e69bSZach Kissel }
139*41c9e69bSZach Kissel 
1401ae08745Sheppo /*
1411ae08745Sheppo  * console_forward()  - cycle client to the next console
1421ae08745Sheppo  * in the group queue.
1431ae08745Sheppo  */
1441ae08745Sheppo static int
1451e8f6090Sdtse console_forward(vntsd_client_t *clientp)
1461ae08745Sheppo {
1471e8f6090Sdtse 	/* forward when there are mutiple consoles in the group */
1481e8f6090Sdtse 	if (clientp->cons->group->num_cons > 1)
1491ae08745Sheppo 		return (VNTSD_STATUS_MOV_CONS_FORWARD);
1501e8f6090Sdtse 
1511e8f6090Sdtse 	return (VNTSD_STATUS_CONTINUE);
1521e8f6090Sdtse 
1531ae08745Sheppo }
1541ae08745Sheppo 
1551ae08745Sheppo /*
1561ae08745Sheppo  * console_backward()  - cycle client to the previous
1571ae08745Sheppo  * console in the group queue.
1581ae08745Sheppo  */
1591ae08745Sheppo static int
1601e8f6090Sdtse console_backward(vntsd_client_t *clientp)
1611ae08745Sheppo {
1621e8f6090Sdtse 	/* backward when there are mutiple consoles in the group */
1631e8f6090Sdtse 	if (clientp->cons->group->num_cons > 1)
1641ae08745Sheppo 		return (VNTSD_STATUS_MOV_CONS_BACKWARD);
1651e8f6090Sdtse 
1661e8f6090Sdtse 	return (VNTSD_STATUS_CONTINUE);
1671e8f6090Sdtse 
1681ae08745Sheppo }
1691ae08745Sheppo 
1701ae08745Sheppo /* acquire_write() - acquire write access to a console. */
1711ae08745Sheppo static int
1721ae08745Sheppo acquire_write(vntsd_client_t *clientp)
1731ae08745Sheppo {
1741ae08745Sheppo 	int	rv;
1751ae08745Sheppo 	int	yes_no = 1;
1761ae08745Sheppo 	vntsd_cons_t *consp;
1771ae08745Sheppo 
1781ae08745Sheppo 	assert(clientp);
1791ae08745Sheppo 	consp = clientp->cons;
1801ae08745Sheppo 	assert(consp);
1811ae08745Sheppo 
1821ae08745Sheppo 	if (consp->clientpq->handle == clientp) {
1831ae08745Sheppo 		/* client is a  writer */
1841ae08745Sheppo 		if ((rv = vntsd_write_line(clientp,
1851ae08745Sheppo 		    gettext("You have write permission"))) !=
1861ae08745Sheppo 		    VNTSD_SUCCESS) {
1871ae08745Sheppo 			return (rv);
1881ae08745Sheppo 
1891ae08745Sheppo 		}
1901ae08745Sheppo 		return (VNTSD_STATUS_CONTINUE);
1911ae08745Sheppo 	}
1921ae08745Sheppo 
1931ae08745Sheppo 	/* message to client */
1941ae08745Sheppo 	if ((rv = vntsd_write_client(clientp, vntsd_eol, VNTSD_EOL_LEN))
1951ae08745Sheppo 	    != VNTSD_SUCCESS) {
1961ae08745Sheppo 		return (rv);
1971ae08745Sheppo 	}
1981ae08745Sheppo 
1991ae08745Sheppo 	/*
2001ae08745Sheppo 	 * TRANSLATION_NOTE
2011ae08745Sheppo 	 * The following string should be formatted to fit on multiple lines
2021ae08745Sheppo 	 * assuming a line width of at most 78 characters. There must be no
2031ae08745Sheppo 	 * trailing newline.
2041ae08745Sheppo 	 */
2051ae08745Sheppo 	if ((rv = vntsd_write_lines(clientp,
2061ae08745Sheppo 	    gettext("Warning: another user currently "
2071ae08745Sheppo 	    "has write permission\nto this console and forcibly removing "
2081ae08745Sheppo 	    "him/her will terminate\nany current write action and all work "
2091ae08745Sheppo 	    "will be lost."))) != VNTSD_SUCCESS) {
2101ae08745Sheppo 		return (rv);
2111ae08745Sheppo 	}
2121ae08745Sheppo 
2131ae08745Sheppo 	/* get client yes no */
2141ae08745Sheppo 	if ((rv = vntsd_write_client(clientp, vntsd_eol,
2151ae08745Sheppo 	    VNTSD_EOL_LEN)) != VNTSD_SUCCESS) {
2161ae08745Sheppo 		return (rv);
2171ae08745Sheppo 	}
2181ae08745Sheppo 
2191ae08745Sheppo 	if ((rv = vntsd_get_yes_no(clientp,
2201ae08745Sheppo 	    gettext("Would you like to continue?"),
2211ae08745Sheppo 	    &yes_no)) != VNTSD_SUCCESS) {
2221ae08745Sheppo 		return (rv);
2231ae08745Sheppo 	}
2241ae08745Sheppo 
2251ae08745Sheppo 	if (yes_no == B_FALSE) {
2261ae08745Sheppo 		/* client change mind no need to acquire  write access */
2271ae08745Sheppo 		return (VNTSD_STATUS_CONTINUE);
2281ae08745Sheppo 	}
2291ae08745Sheppo 
2301ae08745Sheppo 	return (VNTSD_STATUS_ACQUIRE_WRITER);
2311ae08745Sheppo }
2321ae08745Sheppo 
2331ae08745Sheppo /* client_exit()  - disconnect client from the console. */
2341ae08745Sheppo static int
2351ae08745Sheppo client_exit(void)
2361ae08745Sheppo {
2371ae08745Sheppo 	return (VNTSD_STATUS_RESELECT_CONS);
2381ae08745Sheppo }
2391ae08745Sheppo 
2401ae08745Sheppo static int daemon_cmd_help(vntsd_client_t *clientp);
2411ae08745Sheppo 
2421ae08745Sheppo /* table for daemon commands */
2431ae08745Sheppo 
2441ae08745Sheppo static esctable_t  etable[] = {
2451ae08745Sheppo 
2461ae08745Sheppo 	/* send a break to vcc */
2478e6a2a04Slm66018 	{'#', "Send break",  genbrk},
2481ae08745Sheppo 
249*41c9e69bSZach Kissel 	/* alternate break sequence */
250*41c9e69bSZach Kissel 	{CNTRL('B'), "Send alternate break", genaltbrk},
251*41c9e69bSZach Kissel 
2521ae08745Sheppo 	/* exit */
2538e6a2a04Slm66018 	{'.', "Exit from this console",  (e_func_t)client_exit},
2541ae08745Sheppo 
2551ae08745Sheppo 	/* acquire write access */
2568e6a2a04Slm66018 	{'w', "Force write access", acquire_write},
2571ae08745Sheppo 
2581ae08745Sheppo 	/* connect to next console in queue */
2598e6a2a04Slm66018 	{'n', "Console next", (e_func_t)console_forward},
2601ae08745Sheppo 
2611ae08745Sheppo 	/* connect to previous console in queue */
2628e6a2a04Slm66018 	{'p', "Console previous", (e_func_t)console_backward},
2631ae08745Sheppo 
2641ae08745Sheppo 	/* help must be next to last */
2658e6a2a04Slm66018 	{'?', "Help", daemon_cmd_help},
2661ae08745Sheppo 
2671ae08745Sheppo 	/* table terminator */
2681ae08745Sheppo 	{0, 0, 0}
2691ae08745Sheppo };
2701ae08745Sheppo 
2711ae08745Sheppo void
2721ae08745Sheppo vntsd_init_esctable_msgs(void)
2731ae08745Sheppo {
2741ae08745Sheppo 	esctable_t  *p;
2751ae08745Sheppo 
2761ae08745Sheppo 	for (p = etable; p->e_char != '\0'; p++) {
2771ae08745Sheppo 		p->e_help = gettext(p->e_help);
2781ae08745Sheppo 	}
2791ae08745Sheppo }
2801ae08745Sheppo 
2811ae08745Sheppo /* daemon_cmd_help() - print help. */
2821ae08745Sheppo static int
2831ae08745Sheppo daemon_cmd_help(vntsd_client_t *clientp)
2841ae08745Sheppo {
2851ae08745Sheppo 	esctable_t  *p;
2861ae08745Sheppo 	int	    rv;
2871ae08745Sheppo 	char	    buf[VNTSD_LINE_LEN];
2881ae08745Sheppo 
2891ae08745Sheppo 	if ((rv = vntsd_write_client(clientp, vntsd_eol,
2901ae08745Sheppo 	    VNTSD_EOL_LEN)) != VNTSD_SUCCESS) {
2911ae08745Sheppo 		return (rv);
2921ae08745Sheppo 	}
2931ae08745Sheppo 
2941ae08745Sheppo 	/*
2951ae08745Sheppo 	 * TRANSLATION_NOTE
2961ae08745Sheppo 	 * VNTSD is the name of the VNTS daemon and should not be translated.
2971ae08745Sheppo 	 */
2981ae08745Sheppo 	if ((rv = vntsd_write_line(clientp, gettext("VNTSD commands"))) !=
2991ae08745Sheppo 	    VNTSD_SUCCESS) {
3001ae08745Sheppo 		return (rv);
3011ae08745Sheppo 	}
3021ae08745Sheppo 
3031ae08745Sheppo 	for (p = etable; p->e_char; p++) {
304*41c9e69bSZach Kissel 
305*41c9e69bSZach Kissel 		if (p->e_char == CNTRL('B')) {
306*41c9e69bSZach Kissel 			(void) snprintf(buf, sizeof (buf), "~^B --%s",
307*41c9e69bSZach Kissel 			    p->e_help);
308*41c9e69bSZach Kissel 		} else {
3091ae08745Sheppo 			(void) snprintf(buf, sizeof (buf),
3101ae08745Sheppo 			    "~%c --%s", p->e_char, p->e_help);
311*41c9e69bSZach Kissel 		}
3121ae08745Sheppo 
3131ae08745Sheppo 		if ((rv = vntsd_write_line(clientp, buf)) != VNTSD_SUCCESS) {
3141ae08745Sheppo 			return (rv);
3151ae08745Sheppo 		}
3161ae08745Sheppo 	}
3171ae08745Sheppo 
3181ae08745Sheppo 	return (VNTSD_STATUS_CONTINUE);
3191ae08745Sheppo }
3201ae08745Sheppo 
3211ae08745Sheppo /* exit from daemon command */
3221ae08745Sheppo static int
3231ae08745Sheppo exit_daemon_cmd(vntsd_client_t *clientp, int rv)
3241ae08745Sheppo {
3251ae08745Sheppo 	(void) mutex_lock(&clientp->lock);
3261ae08745Sheppo 	clientp->status &= ~VNTSD_CLIENT_DISABLE_DAEMON_CMD;
3271ae08745Sheppo 	(void) mutex_unlock(&clientp->lock);
3281ae08745Sheppo 	return (rv);
3291ae08745Sheppo }
3301ae08745Sheppo 
331d10e4ef2Snarayan /*
332d10e4ef2Snarayan  * vntsd_process_daemon_cmd() - special commands
333d10e4ef2Snarayan  * "<RET>~"  vntsd daemon commands
334d10e4ef2Snarayan  * "<RET>~~" enter '~' character
335d10e4ef2Snarayan  */
3361ae08745Sheppo int
3371ae08745Sheppo vntsd_process_daemon_cmd(vntsd_client_t *clientp, char c)
3381ae08745Sheppo {
3391ae08745Sheppo 	esctable_t *p;
3401ae08745Sheppo 	int	    rv;
341d10e4ef2Snarayan 	char	    prev_char;
3421ae08745Sheppo 
343d10e4ef2Snarayan 	prev_char = clientp->prev_char;
344d10e4ef2Snarayan 
345d10e4ef2Snarayan 	if (c != VNTSD_DAEMON_CMD || (prev_char != 0 && prev_char != CR)) {
3461ae08745Sheppo 		/* not a daemon command */
3471ae08745Sheppo 		return (VNTSD_SUCCESS);
3481ae08745Sheppo 	}
3491ae08745Sheppo 
3501ae08745Sheppo 	if (clientp->status & VNTSD_CLIENT_DISABLE_DAEMON_CMD) {
3511ae08745Sheppo 		return (VNTSD_STATUS_CONTINUE);
3521ae08745Sheppo 	}
3531ae08745Sheppo 
3541ae08745Sheppo 	/* no reentry to process_daemon_cmd */
3551ae08745Sheppo 	(void) mutex_lock(&clientp->lock);
3561ae08745Sheppo 	clientp->status |= VNTSD_CLIENT_DISABLE_DAEMON_CMD;
3571ae08745Sheppo 	(void) mutex_unlock(&clientp->lock);
3581ae08745Sheppo 
3591ae08745Sheppo 	D3(stderr, "t@%d process_daemon_cmd %d %d \n", thr_self(),
3601ae08745Sheppo 	    clientp->cons->vcc_fd, clientp->sockfd);
3611ae08745Sheppo 
3621ae08745Sheppo 	/* read in command */
3631ae08745Sheppo 	if ((rv = vntsd_read_char(clientp, &c)) != VNTSD_SUCCESS) {
3641ae08745Sheppo 		return (exit_daemon_cmd(clientp, rv));
3651ae08745Sheppo 	}
3661ae08745Sheppo 
367d10e4ef2Snarayan 	if (c == VNTSD_DAEMON_CMD) {
368d10e4ef2Snarayan 		/*
369d10e4ef2Snarayan 		 * received another '~'
370d10e4ef2Snarayan 		 * a user types '~~' to get '~'
371d10e4ef2Snarayan 		 */
372d10e4ef2Snarayan 		(void) mutex_lock(&clientp->lock);
373d10e4ef2Snarayan 		clientp->status &= ~VNTSD_CLIENT_DISABLE_DAEMON_CMD;
374d10e4ef2Snarayan 		(void) mutex_unlock(&clientp->lock);
375d10e4ef2Snarayan 		return (VNTSD_SUCCESS);
376d10e4ef2Snarayan 	}
377d10e4ef2Snarayan 
3781ae08745Sheppo 	for (p = etable; p->e_char; p++) {
3791ae08745Sheppo 		if (p->e_char == c) {
3801ae08745Sheppo 			/* found match */
3811ae08745Sheppo 			assert(p->e_func);
3821ae08745Sheppo 			rv = (*p->e_func)(clientp);
3831ae08745Sheppo 			return (exit_daemon_cmd(clientp, rv));
3841ae08745Sheppo 		}
3851ae08745Sheppo 	}
3861ae08745Sheppo 
3871ae08745Sheppo 	/* no match, print out the help */
3881ae08745Sheppo 	p--;
3891ae08745Sheppo 	assert(p->e_char == '?');
3901ae08745Sheppo 	rv = (*p->e_func)(clientp);
3911ae08745Sheppo 
3921ae08745Sheppo 	return (exit_daemon_cmd(clientp, rv));
3931ae08745Sheppo 
3941ae08745Sheppo }
3951ae08745Sheppo 
3961ae08745Sheppo /* vntsd_set_telnet_options() - change  telnet client to  character mode. */
3971ae08745Sheppo int
3981ae08745Sheppo vntsd_set_telnet_options(int fd)
3991ae08745Sheppo {
4001ae08745Sheppo 	/* set client telnet options */
4011ae08745Sheppo 	uint8_t buf[] = {IAC, DONT, LINEMODE, IAC, WILL, SUPRESS, IAC, WILL,
4021ae08745Sheppo 		TEL_ECHO, IAC, DONT, TERM_TYPE, IAC, DONT, TERM_SP,
4031ae08745Sheppo 		IAC, DONT, STATUS, IAC, DONT, FC, IAC, DONT, TM, IAC, DONT, ENV,
4041ae08745Sheppo 		IAC, DONT, WIN_SIZE};
4051ae08745Sheppo 
4061ae08745Sheppo 	return (vntsd_write_fd(fd, (char *)buf, 30));
4071ae08745Sheppo }
4081ae08745Sheppo 
4091ae08745Sheppo /*  vntsd_telnet_cmd() process telnet commands */
4101ae08745Sheppo int
4111ae08745Sheppo vntsd_telnet_cmd(vntsd_client_t *clientp, char c)
4121ae08745Sheppo {
4131ae08745Sheppo 	uint8_t	buf[4];
4141ae08745Sheppo 	char	cmd;
4151ae08745Sheppo 	int	rv = VNTSD_STATUS_CONTINUE;
4161ae08745Sheppo 
4171ae08745Sheppo 	bzero(buf, 4);
4181ae08745Sheppo 
4191ae08745Sheppo 	if ((uint8_t)c != IAC) {
4201ae08745Sheppo 		/* not telnet cmd */
4211ae08745Sheppo 		return (VNTSD_SUCCESS);
4221ae08745Sheppo 	}
4231ae08745Sheppo 
4241ae08745Sheppo 	if ((rv = vntsd_read_char(clientp, &cmd)) != VNTSD_SUCCESS) {
4251ae08745Sheppo 		return (rv);
4261ae08745Sheppo 	}
4271ae08745Sheppo 
428a93081c1SChris Gerhard 	if ((uint8_t)cmd == WILL || (uint8_t)cmd == WONT ||
429a93081c1SChris Gerhard 	    (uint8_t)cmd == DO || (uint8_t)cmd == DONT) {
4301ae08745Sheppo 		if ((rv = vntsd_read_char(clientp, &c)) != VNTSD_SUCCESS) {
4311ae08745Sheppo 			return (rv);
4321ae08745Sheppo 		}
433823fe29bSdtse 	}
4341ae08745Sheppo 
4351ae08745Sheppo 
4361ae08745Sheppo 	switch ((uint8_t)cmd) {
4371ae08745Sheppo 
4381ae08745Sheppo 	case WILL:
4391ae08745Sheppo 
4401ae08745Sheppo 		switch ((uint8_t)c) {
4411ae08745Sheppo 		case TEL_ECHO:
4421ae08745Sheppo 		case SUPRESS:
4431ae08745Sheppo 		case LINEMODE:
4441ae08745Sheppo 			break;
4451ae08745Sheppo 		default:
4461ae08745Sheppo 			syslog(LOG_ERR, "not support telnet WILL %x\n", c);
4471ae08745Sheppo 			break;
4481ae08745Sheppo 		}
4491ae08745Sheppo 		break;
4501ae08745Sheppo 
4511ae08745Sheppo 	case  WONT:
4521ae08745Sheppo 
4531ae08745Sheppo 		switch ((uint8_t)c) {
4541ae08745Sheppo 		case TEL_ECHO:
4551ae08745Sheppo 		case SUPRESS:
4561ae08745Sheppo 		case LINEMODE:
4571ae08745Sheppo 		default:
4581ae08745Sheppo 			syslog(LOG_ERR, "not support telnet WONT %x\n", c);
4591ae08745Sheppo 			break;
4601ae08745Sheppo 		}
4611ae08745Sheppo 		break;
4621ae08745Sheppo 
4631ae08745Sheppo 	case DO:
4641ae08745Sheppo 	case DONT:
4651ae08745Sheppo 
4661ae08745Sheppo 		buf[0] = IAC;
4671ae08745Sheppo 		buf[1] = WILL;
4681ae08745Sheppo 		buf[2] = c;
4691ae08745Sheppo 		rv = vntsd_write_client(clientp, (char *)buf, 3);
4701ae08745Sheppo 
4711ae08745Sheppo 		break;
4721ae08745Sheppo 
4731ae08745Sheppo 	case BRK:
4741ae08745Sheppo 
4751ae08745Sheppo 		/* send break to vcc */
4761ae08745Sheppo 		rv = genbrk(clientp);
4771ae08745Sheppo 		break;
4781ae08745Sheppo 
4791ae08745Sheppo 	case IP:
4801ae08745Sheppo 
4811ae08745Sheppo 		break;
4821ae08745Sheppo 
483a93081c1SChris Gerhard 	case AYT: {
484a93081c1SChris Gerhard 			static char aytresp[] = "vntsd here";
4851ae08745Sheppo 
486a93081c1SChris Gerhard 			rv = vntsd_write_client(clientp, aytresp,
487a93081c1SChris Gerhard 			    sizeof (aytresp) - 1);
4881ae08745Sheppo 			break;
489a93081c1SChris Gerhard 		}
4901ae08745Sheppo 
4911ae08745Sheppo 	case HT:
492a93081c1SChris Gerhard 	case NOP:
4931ae08745Sheppo 		return (VNTSD_STATUS_CONTINUE);
4941ae08745Sheppo 
4951ae08745Sheppo 	default:
496a93081c1SChris Gerhard 		syslog(LOG_ERR, "not support telnet ctrl %2.2x\n", 0xff & cmd);
4971ae08745Sheppo 		break;
4981ae08745Sheppo 	}
4991ae08745Sheppo 
5001ae08745Sheppo 	if (rv == VNTSD_SUCCESS) {
5011ae08745Sheppo 		return (VNTSD_STATUS_CONTINUE);
5021ae08745Sheppo 	} else {
5031ae08745Sheppo 		return (rv);
5041ae08745Sheppo 	}
5051ae08745Sheppo }
5061ae08745Sheppo 
5071ae08745Sheppo 
5081ae08745Sheppo /*
5091ae08745Sheppo  * vntsd_ctrl_cmd()   - control keys
5101ae08745Sheppo  * read and write suspend are supported.
5111ae08745Sheppo  */
5121ae08745Sheppo int
5131ae08745Sheppo vntsd_ctrl_cmd(vntsd_client_t *clientp, char c)
5141ae08745Sheppo {
5151ae08745Sheppo 	int	cmd;
5161ae08745Sheppo 
5171ae08745Sheppo 	D3(stderr, "t@%d vntsd_ctrl_cmd%d %d\n", thr_self(),
5181ae08745Sheppo 	    clientp->cons->vcc_fd, clientp->sockfd);
5191ae08745Sheppo 
5201ae08745Sheppo 	if ((c != START) && (c != STOP)) {
5211ae08745Sheppo 		/* not a supported control command */
5221ae08745Sheppo 		return (VNTSD_SUCCESS);
5231ae08745Sheppo 	}
5241ae08745Sheppo 
5251ae08745Sheppo 	if (c == START) {
5261ae08745Sheppo 		D3(stderr, "t@%d client restart\n", thr_self());
5271ae08745Sheppo 
5281ae08745Sheppo 		/* send resume read */
5291ae08745Sheppo 		cmd = 1;
5301ae08745Sheppo 
5311ae08745Sheppo 		if (ioctl(clientp->cons->vcc_fd, TCXONC, &cmd)) {
5321ae08745Sheppo 			return (VNTSD_STATUS_VCC_IO_ERR);
5331ae08745Sheppo 		}
5341ae08745Sheppo 
5351ae08745Sheppo 	}
5361ae08745Sheppo 
5371ae08745Sheppo 	if (c == STOP) {
5381ae08745Sheppo 		D3(stderr, "t@%d client suspend\n", thr_self());
5391ae08745Sheppo 
5401ae08745Sheppo 		/* send suspend read */
5411ae08745Sheppo 		cmd = 0;
5421ae08745Sheppo 
5431ae08745Sheppo 		if (ioctl(clientp->cons->vcc_fd, TCXONC, &cmd)) {
5441ae08745Sheppo 			return (VNTSD_STATUS_VCC_IO_ERR);
5451ae08745Sheppo 		}
5461ae08745Sheppo 
5471ae08745Sheppo 	}
5481ae08745Sheppo 
5491ae08745Sheppo 	return (VNTSD_STATUS_CONTINUE);
5501ae08745Sheppo }
551