xref: /titanic_50/usr/src/cmd/vntsd/cmd.c (revision 1ae0874509b6811fdde1dfd46f0d93fd09867a3f)
1*1ae08745Sheppo /*
2*1ae08745Sheppo  * CDDL HEADER START
3*1ae08745Sheppo  *
4*1ae08745Sheppo  * The contents of this file are subject to the terms of the
5*1ae08745Sheppo  * Common Development and Distribution License (the "License").
6*1ae08745Sheppo  * You may not use this file except in compliance with the License.
7*1ae08745Sheppo  *
8*1ae08745Sheppo  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*1ae08745Sheppo  * or http://www.opensolaris.org/os/licensing.
10*1ae08745Sheppo  * See the License for the specific language governing permissions
11*1ae08745Sheppo  * and limitations under the License.
12*1ae08745Sheppo  *
13*1ae08745Sheppo  * When distributing Covered Code, include this CDDL HEADER in each
14*1ae08745Sheppo  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*1ae08745Sheppo  * If applicable, add the following below this CDDL HEADER, with the
16*1ae08745Sheppo  * fields enclosed by brackets "[]" replaced with your own identifying
17*1ae08745Sheppo  * information: Portions Copyright [yyyy] [name of copyright owner]
18*1ae08745Sheppo  *
19*1ae08745Sheppo  * CDDL HEADER END
20*1ae08745Sheppo  */
21*1ae08745Sheppo /*
22*1ae08745Sheppo  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23*1ae08745Sheppo  * Use is subject to license terms.
24*1ae08745Sheppo  */
25*1ae08745Sheppo 
26*1ae08745Sheppo #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*1ae08745Sheppo 
28*1ae08745Sheppo /*
29*1ae08745Sheppo  * Vntsd handles two types of special commands, one is telnet
30*1ae08745Sheppo  * commands and another is vntsd special commands.
31*1ae08745Sheppo  * telnet commands supported are:
32*1ae08745Sheppo  * WILL
33*1ae08745Sheppo  * WONT
34*1ae08745Sheppo  * DO
35*1ae08745Sheppo  * DONT
36*1ae08745Sheppo  *  TEL_ECHO
37*1ae08745Sheppo  *  SUPRESS
38*1ae08745Sheppo  *  LINEMODE
39*1ae08745Sheppo  * BRK
40*1ae08745Sheppo  * AYT
41*1ae08745Sheppo  * HT
42*1ae08745Sheppo  *
43*1ae08745Sheppo  * Vntsd special commands are:
44*1ae08745Sheppo  *  send break		(~#)
45*1ae08745Sheppo  *  exit		(~.)
46*1ae08745Sheppo  *  force write access	(~w)
47*1ae08745Sheppo  *  cycle console down	(~n)
48*1ae08745Sheppo  *  cycle console up	(~p)
49*1ae08745Sheppo  *  help		(~?)
50*1ae08745Sheppo  */
51*1ae08745Sheppo 
52*1ae08745Sheppo #include <stdio.h>
53*1ae08745Sheppo #include <stdlib.h>
54*1ae08745Sheppo #include <string.h>
55*1ae08745Sheppo #include <unistd.h>
56*1ae08745Sheppo #include <sys/types.h>
57*1ae08745Sheppo #include <sys/socket.h>
58*1ae08745Sheppo #include <netinet/in.h>
59*1ae08745Sheppo #include <thread.h>
60*1ae08745Sheppo #include <ctype.h>
61*1ae08745Sheppo #include <sys/termio.h>
62*1ae08745Sheppo #include <libintl.h>
63*1ae08745Sheppo #include <syslog.h>
64*1ae08745Sheppo #include "vntsd.h"
65*1ae08745Sheppo #include "chars.h"
66*1ae08745Sheppo 
67*1ae08745Sheppo char vntsd_eol[] = { CR, LF, 0};
68*1ae08745Sheppo 
69*1ae08745Sheppo typedef	int	    (*e_func_t)(vntsd_client_t *clientp);
70*1ae08745Sheppo /* structure for daemon special cmd */
71*1ae08745Sheppo typedef struct {
72*1ae08745Sheppo 	char e_char;				/* char to match on */
73*1ae08745Sheppo 	char *e_help;				/* help string */
74*1ae08745Sheppo 	e_func_t e_func;			/* command */
75*1ae08745Sheppo } esctable_t;
76*1ae08745Sheppo 
77*1ae08745Sheppo /* genbrk() -  send a break to vcc driver */
78*1ae08745Sheppo static int
79*1ae08745Sheppo genbrk(vntsd_client_t *clientp)
80*1ae08745Sheppo {
81*1ae08745Sheppo 
82*1ae08745Sheppo 	vntsd_cons_t *consp;
83*1ae08745Sheppo 
84*1ae08745Sheppo 	assert(clientp);
85*1ae08745Sheppo 	assert(clientp->cons);
86*1ae08745Sheppo 
87*1ae08745Sheppo 	consp = clientp->cons;
88*1ae08745Sheppo 	D1(stderr, "t@%d genbrk fd=%d sockfd %d\n", thr_self(),
89*1ae08745Sheppo 	    consp->vcc_fd, clientp->sockfd);
90*1ae08745Sheppo 
91*1ae08745Sheppo 	assert(consp->clientpq != NULL);
92*1ae08745Sheppo 	if (consp->clientpq->handle != clientp) {
93*1ae08745Sheppo 		/* reader */
94*1ae08745Sheppo 		return (vntsd_write_line(clientp,
95*1ae08745Sheppo 			    gettext(VNTSD_NO_WRITE_ACCESS_MSG)));
96*1ae08745Sheppo 	}
97*1ae08745Sheppo 
98*1ae08745Sheppo 	/* writer */
99*1ae08745Sheppo 	if (ioctl(consp->vcc_fd, TCSBRK, NULL)) {
100*1ae08745Sheppo 		return (VNTSD_ERR_VCC_IOCTL);
101*1ae08745Sheppo 	}
102*1ae08745Sheppo 
103*1ae08745Sheppo 	return (VNTSD_STATUS_CONTINUE);
104*1ae08745Sheppo }
105*1ae08745Sheppo 
106*1ae08745Sheppo /*
107*1ae08745Sheppo  * console_forward()  - cycle client to the next console
108*1ae08745Sheppo  * in the group queue.
109*1ae08745Sheppo  */
110*1ae08745Sheppo static int
111*1ae08745Sheppo console_forward(void)
112*1ae08745Sheppo {
113*1ae08745Sheppo 	return (VNTSD_STATUS_MOV_CONS_FORWARD);
114*1ae08745Sheppo }
115*1ae08745Sheppo 
116*1ae08745Sheppo /*
117*1ae08745Sheppo  * console_backward()  - cycle client to the previous
118*1ae08745Sheppo  * console in the group queue.
119*1ae08745Sheppo  */
120*1ae08745Sheppo static int
121*1ae08745Sheppo console_backward(void)
122*1ae08745Sheppo {
123*1ae08745Sheppo 	return (VNTSD_STATUS_MOV_CONS_BACKWARD);
124*1ae08745Sheppo }
125*1ae08745Sheppo 
126*1ae08745Sheppo /* acquire_write() - acquire write access to a console. */
127*1ae08745Sheppo static int
128*1ae08745Sheppo acquire_write(vntsd_client_t *clientp)
129*1ae08745Sheppo {
130*1ae08745Sheppo 	int	rv;
131*1ae08745Sheppo 	int	yes_no = 1;
132*1ae08745Sheppo 	vntsd_cons_t *consp;
133*1ae08745Sheppo 
134*1ae08745Sheppo 	assert(clientp);
135*1ae08745Sheppo 	consp = clientp->cons;
136*1ae08745Sheppo 	assert(consp);
137*1ae08745Sheppo 
138*1ae08745Sheppo 	if (consp->clientpq->handle == clientp) {
139*1ae08745Sheppo 		/* client is a  writer */
140*1ae08745Sheppo 		if ((rv = vntsd_write_line(clientp,
141*1ae08745Sheppo 			    gettext("You have write permission"))) !=
142*1ae08745Sheppo 		    VNTSD_SUCCESS) {
143*1ae08745Sheppo 			return (rv);
144*1ae08745Sheppo 
145*1ae08745Sheppo 		}
146*1ae08745Sheppo 		return (VNTSD_STATUS_CONTINUE);
147*1ae08745Sheppo 	}
148*1ae08745Sheppo 
149*1ae08745Sheppo 	/* message to client */
150*1ae08745Sheppo 	if ((rv = vntsd_write_client(clientp, vntsd_eol, VNTSD_EOL_LEN))
151*1ae08745Sheppo 	    != VNTSD_SUCCESS) {
152*1ae08745Sheppo 		return (rv);
153*1ae08745Sheppo 	}
154*1ae08745Sheppo 
155*1ae08745Sheppo 	/*
156*1ae08745Sheppo 	 * TRANSLATION_NOTE
157*1ae08745Sheppo 	 * The following string should be formatted to fit on multiple lines
158*1ae08745Sheppo 	 * assuming a line width of at most 78 characters. There must be no
159*1ae08745Sheppo 	 * trailing newline.
160*1ae08745Sheppo 	 */
161*1ae08745Sheppo 	if ((rv = vntsd_write_lines(clientp,
162*1ae08745Sheppo 			    gettext("Warning: another user currently "
163*1ae08745Sheppo 	    "has write permission\nto this console and forcibly removing "
164*1ae08745Sheppo 	    "him/her will terminate\nany current write action and all work "
165*1ae08745Sheppo 	    "will be lost."))) != VNTSD_SUCCESS) {
166*1ae08745Sheppo 		return (rv);
167*1ae08745Sheppo 	}
168*1ae08745Sheppo 
169*1ae08745Sheppo 	/* get client yes no */
170*1ae08745Sheppo 	if ((rv = vntsd_write_client(clientp, vntsd_eol,
171*1ae08745Sheppo 			    VNTSD_EOL_LEN)) != VNTSD_SUCCESS) {
172*1ae08745Sheppo 		return (rv);
173*1ae08745Sheppo 	}
174*1ae08745Sheppo 
175*1ae08745Sheppo 	if ((rv = vntsd_get_yes_no(clientp,
176*1ae08745Sheppo 			    gettext("Would you like to continue?"),
177*1ae08745Sheppo 			    &yes_no)) != VNTSD_SUCCESS) {
178*1ae08745Sheppo 		return (rv);
179*1ae08745Sheppo 	}
180*1ae08745Sheppo 
181*1ae08745Sheppo 	if (yes_no == B_FALSE) {
182*1ae08745Sheppo 		/* client change mind no need to acquire  write access */
183*1ae08745Sheppo 		return (VNTSD_STATUS_CONTINUE);
184*1ae08745Sheppo 	}
185*1ae08745Sheppo 
186*1ae08745Sheppo 	return (VNTSD_STATUS_ACQUIRE_WRITER);
187*1ae08745Sheppo }
188*1ae08745Sheppo 
189*1ae08745Sheppo /* client_exit()  - disconnect client from the console. */
190*1ae08745Sheppo static int
191*1ae08745Sheppo client_exit(void)
192*1ae08745Sheppo {
193*1ae08745Sheppo 	return (VNTSD_STATUS_RESELECT_CONS);
194*1ae08745Sheppo }
195*1ae08745Sheppo 
196*1ae08745Sheppo static int daemon_cmd_help(vntsd_client_t *clientp);
197*1ae08745Sheppo 
198*1ae08745Sheppo /* table for daemon commands */
199*1ae08745Sheppo 
200*1ae08745Sheppo static esctable_t  etable[] = {
201*1ae08745Sheppo 
202*1ae08745Sheppo 	/* send a break to vcc */
203*1ae08745Sheppo 	{'#', "send break",  genbrk},
204*1ae08745Sheppo 
205*1ae08745Sheppo 	/* exit */
206*1ae08745Sheppo 	{'.', "exit from this console",  (e_func_t)client_exit},
207*1ae08745Sheppo 
208*1ae08745Sheppo 	/* acquire write access */
209*1ae08745Sheppo 	{'w', "force write access", acquire_write},
210*1ae08745Sheppo 
211*1ae08745Sheppo 	/* connect to next console in queue */
212*1ae08745Sheppo 	{'n', "console down", (e_func_t)console_forward},
213*1ae08745Sheppo 
214*1ae08745Sheppo 	/* connect to previous console in queue */
215*1ae08745Sheppo 	{'p', "console up", (e_func_t)console_backward},
216*1ae08745Sheppo 
217*1ae08745Sheppo 	/* help must be next to last */
218*1ae08745Sheppo 	{'?', "_", daemon_cmd_help},
219*1ae08745Sheppo 
220*1ae08745Sheppo 	/* table terminator */
221*1ae08745Sheppo 	{0, 0, 0}
222*1ae08745Sheppo };
223*1ae08745Sheppo 
224*1ae08745Sheppo void
225*1ae08745Sheppo vntsd_init_esctable_msgs(void)
226*1ae08745Sheppo {
227*1ae08745Sheppo 	esctable_t  *p;
228*1ae08745Sheppo 
229*1ae08745Sheppo 	for (p = etable; p->e_char != '\0'; p++) {
230*1ae08745Sheppo 		p->e_help = gettext(p->e_help);
231*1ae08745Sheppo 	}
232*1ae08745Sheppo }
233*1ae08745Sheppo 
234*1ae08745Sheppo /* daemon_cmd_help() - print help. */
235*1ae08745Sheppo static int
236*1ae08745Sheppo daemon_cmd_help(vntsd_client_t *clientp)
237*1ae08745Sheppo {
238*1ae08745Sheppo 	esctable_t  *p;
239*1ae08745Sheppo 	int	    rv;
240*1ae08745Sheppo 	char	    buf[VNTSD_LINE_LEN];
241*1ae08745Sheppo 
242*1ae08745Sheppo 	if ((rv = vntsd_write_client(clientp, vntsd_eol,
243*1ae08745Sheppo 			    VNTSD_EOL_LEN)) != VNTSD_SUCCESS) {
244*1ae08745Sheppo 	    return (rv);
245*1ae08745Sheppo 	}
246*1ae08745Sheppo 
247*1ae08745Sheppo 	/*
248*1ae08745Sheppo 	 * TRANSLATION_NOTE
249*1ae08745Sheppo 	 * VNTSD is the name of the VNTS daemon and should not be translated.
250*1ae08745Sheppo 	 */
251*1ae08745Sheppo 	if ((rv = vntsd_write_line(clientp, gettext("VNTSD commands"))) !=
252*1ae08745Sheppo 	    VNTSD_SUCCESS) {
253*1ae08745Sheppo 		return (rv);
254*1ae08745Sheppo 	}
255*1ae08745Sheppo 
256*1ae08745Sheppo 	for (p = etable; p->e_char; p++) {
257*1ae08745Sheppo 		(void) snprintf(buf, sizeof (buf),
258*1ae08745Sheppo 				"~%c --%s", p->e_char, p->e_help);
259*1ae08745Sheppo 
260*1ae08745Sheppo 		if ((rv = vntsd_write_line(clientp, buf)) != VNTSD_SUCCESS) {
261*1ae08745Sheppo 			return (rv);
262*1ae08745Sheppo 		}
263*1ae08745Sheppo 	}
264*1ae08745Sheppo 
265*1ae08745Sheppo 	return (VNTSD_STATUS_CONTINUE);
266*1ae08745Sheppo }
267*1ae08745Sheppo 
268*1ae08745Sheppo /* exit from daemon command */
269*1ae08745Sheppo static int
270*1ae08745Sheppo exit_daemon_cmd(vntsd_client_t *clientp, int rv)
271*1ae08745Sheppo {
272*1ae08745Sheppo 	(void) mutex_lock(&clientp->lock);
273*1ae08745Sheppo 	clientp->status &= ~VNTSD_CLIENT_DISABLE_DAEMON_CMD;
274*1ae08745Sheppo 	(void) mutex_unlock(&clientp->lock);
275*1ae08745Sheppo 	return (rv);
276*1ae08745Sheppo }
277*1ae08745Sheppo 
278*1ae08745Sheppo /* vntsd_process_daemon_cmd() - special commands */
279*1ae08745Sheppo int
280*1ae08745Sheppo vntsd_process_daemon_cmd(vntsd_client_t *clientp, char c)
281*1ae08745Sheppo {
282*1ae08745Sheppo 	esctable_t *p;
283*1ae08745Sheppo 	int	    rv;
284*1ae08745Sheppo 
285*1ae08745Sheppo 	if (c != VNTSD_DAEMON_CMD) {
286*1ae08745Sheppo 		/* not a daemon command */
287*1ae08745Sheppo 		return (VNTSD_SUCCESS);
288*1ae08745Sheppo 	}
289*1ae08745Sheppo 
290*1ae08745Sheppo 	if (clientp->status & VNTSD_CLIENT_DISABLE_DAEMON_CMD) {
291*1ae08745Sheppo 		return (VNTSD_STATUS_CONTINUE);
292*1ae08745Sheppo 	}
293*1ae08745Sheppo 
294*1ae08745Sheppo 	/* no reentry to process_daemon_cmd */
295*1ae08745Sheppo 	(void) mutex_lock(&clientp->lock);
296*1ae08745Sheppo 	clientp->status |= VNTSD_CLIENT_DISABLE_DAEMON_CMD;
297*1ae08745Sheppo 	(void) mutex_unlock(&clientp->lock);
298*1ae08745Sheppo 
299*1ae08745Sheppo 	D3(stderr, "t@%d process_daemon_cmd %d %d \n", thr_self(),
300*1ae08745Sheppo 	    clientp->cons->vcc_fd, clientp->sockfd);
301*1ae08745Sheppo 
302*1ae08745Sheppo 	/* read in command */
303*1ae08745Sheppo 	if ((rv = vntsd_read_char(clientp, &c)) != VNTSD_SUCCESS) {
304*1ae08745Sheppo 		return (exit_daemon_cmd(clientp, rv));
305*1ae08745Sheppo 	}
306*1ae08745Sheppo 
307*1ae08745Sheppo 	for (p = etable; p->e_char; p++) {
308*1ae08745Sheppo 		if (p->e_char == c) {
309*1ae08745Sheppo 			/* found match */
310*1ae08745Sheppo 			assert(p->e_func);
311*1ae08745Sheppo 			rv = (*p->e_func)(clientp);
312*1ae08745Sheppo 			return (exit_daemon_cmd(clientp, rv));
313*1ae08745Sheppo 		}
314*1ae08745Sheppo 	}
315*1ae08745Sheppo 
316*1ae08745Sheppo 	/* no match, print out the help */
317*1ae08745Sheppo 	p--;
318*1ae08745Sheppo 	assert(p->e_char == '?');
319*1ae08745Sheppo 	rv = (*p->e_func)(clientp);
320*1ae08745Sheppo 
321*1ae08745Sheppo 	return (exit_daemon_cmd(clientp, rv));
322*1ae08745Sheppo 
323*1ae08745Sheppo }
324*1ae08745Sheppo 
325*1ae08745Sheppo /* vntsd_set_telnet_options() - change  telnet client to  character mode. */
326*1ae08745Sheppo int
327*1ae08745Sheppo vntsd_set_telnet_options(int fd)
328*1ae08745Sheppo {
329*1ae08745Sheppo 	/* set client telnet options */
330*1ae08745Sheppo 	uint8_t buf[] = {IAC, DONT, LINEMODE, IAC, WILL, SUPRESS, IAC, WILL,
331*1ae08745Sheppo 		TEL_ECHO, IAC, DONT, TERM_TYPE, IAC, DONT, TERM_SP,
332*1ae08745Sheppo 		IAC, DONT, STATUS, IAC, DONT, FC, IAC, DONT, TM, IAC, DONT, ENV,
333*1ae08745Sheppo 		IAC, DONT, WIN_SIZE};
334*1ae08745Sheppo 
335*1ae08745Sheppo 	return (vntsd_write_fd(fd, (char *)buf, 30));
336*1ae08745Sheppo }
337*1ae08745Sheppo 
338*1ae08745Sheppo /*  vntsd_telnet_cmd() process telnet commands */
339*1ae08745Sheppo int
340*1ae08745Sheppo vntsd_telnet_cmd(vntsd_client_t *clientp, char c)
341*1ae08745Sheppo {
342*1ae08745Sheppo 	uint8_t	buf[4];
343*1ae08745Sheppo 	char	cmd;
344*1ae08745Sheppo 	int	rv = VNTSD_STATUS_CONTINUE;
345*1ae08745Sheppo 
346*1ae08745Sheppo 	bzero(buf, 4);
347*1ae08745Sheppo 
348*1ae08745Sheppo 	if ((uint8_t)c != IAC) {
349*1ae08745Sheppo 		/* not telnet cmd */
350*1ae08745Sheppo 		return (VNTSD_SUCCESS);
351*1ae08745Sheppo 	}
352*1ae08745Sheppo 
353*1ae08745Sheppo 	if ((rv = vntsd_read_char(clientp, &cmd)) != VNTSD_SUCCESS) {
354*1ae08745Sheppo 		return (rv);
355*1ae08745Sheppo 	}
356*1ae08745Sheppo 
357*1ae08745Sheppo 	if ((rv = vntsd_read_char(clientp, &c)) != VNTSD_SUCCESS) {
358*1ae08745Sheppo 		return (rv);
359*1ae08745Sheppo 	}
360*1ae08745Sheppo 
361*1ae08745Sheppo 
362*1ae08745Sheppo 	switch ((uint8_t)cmd) {
363*1ae08745Sheppo 
364*1ae08745Sheppo 	case WILL:
365*1ae08745Sheppo 
366*1ae08745Sheppo 		switch ((uint8_t)c) {
367*1ae08745Sheppo 		case TEL_ECHO:
368*1ae08745Sheppo 		case SUPRESS:
369*1ae08745Sheppo 		case LINEMODE:
370*1ae08745Sheppo 			break;
371*1ae08745Sheppo 		default:
372*1ae08745Sheppo 			syslog(LOG_ERR, "not support telnet WILL %x\n", c);
373*1ae08745Sheppo 			break;
374*1ae08745Sheppo 		}
375*1ae08745Sheppo 		break;
376*1ae08745Sheppo 
377*1ae08745Sheppo 	case  WONT:
378*1ae08745Sheppo 
379*1ae08745Sheppo 		switch ((uint8_t)c) {
380*1ae08745Sheppo 		case TEL_ECHO:
381*1ae08745Sheppo 		case SUPRESS:
382*1ae08745Sheppo 		case LINEMODE:
383*1ae08745Sheppo 		default:
384*1ae08745Sheppo 			syslog(LOG_ERR, "not support telnet WONT %x\n", c);
385*1ae08745Sheppo 			break;
386*1ae08745Sheppo 		}
387*1ae08745Sheppo 		break;
388*1ae08745Sheppo 
389*1ae08745Sheppo 	case DO:
390*1ae08745Sheppo 	case DONT:
391*1ae08745Sheppo 
392*1ae08745Sheppo 		buf[0] = IAC;
393*1ae08745Sheppo 		buf[1] = WILL;
394*1ae08745Sheppo 		buf[2] = c;
395*1ae08745Sheppo 		rv = vntsd_write_client(clientp, (char *)buf, 3);
396*1ae08745Sheppo 
397*1ae08745Sheppo 		break;
398*1ae08745Sheppo 
399*1ae08745Sheppo 	case BRK:
400*1ae08745Sheppo 
401*1ae08745Sheppo 		/* send break to vcc */
402*1ae08745Sheppo 		rv = genbrk(clientp);
403*1ae08745Sheppo 		break;
404*1ae08745Sheppo 
405*1ae08745Sheppo 	case IP:
406*1ae08745Sheppo 
407*1ae08745Sheppo 		break;
408*1ae08745Sheppo 
409*1ae08745Sheppo 	case AYT:
410*1ae08745Sheppo 
411*1ae08745Sheppo 		rv = vntsd_write_client(clientp, &c, 1);
412*1ae08745Sheppo 		break;
413*1ae08745Sheppo 
414*1ae08745Sheppo 	case HT:
415*1ae08745Sheppo 		return (VNTSD_STATUS_CONTINUE);
416*1ae08745Sheppo 
417*1ae08745Sheppo 	default:
418*1ae08745Sheppo 		syslog(LOG_ERR, "not support telnet ctrl %x\n", c);
419*1ae08745Sheppo 		break;
420*1ae08745Sheppo 	}
421*1ae08745Sheppo 
422*1ae08745Sheppo 	if (rv == VNTSD_SUCCESS) {
423*1ae08745Sheppo 		return (VNTSD_STATUS_CONTINUE);
424*1ae08745Sheppo 	} else {
425*1ae08745Sheppo 		return (rv);
426*1ae08745Sheppo 	}
427*1ae08745Sheppo }
428*1ae08745Sheppo 
429*1ae08745Sheppo 
430*1ae08745Sheppo /*
431*1ae08745Sheppo  * vntsd_ctrl_cmd()   - control keys
432*1ae08745Sheppo  * read and write suspend are supported.
433*1ae08745Sheppo  */
434*1ae08745Sheppo int
435*1ae08745Sheppo vntsd_ctrl_cmd(vntsd_client_t *clientp, char c)
436*1ae08745Sheppo {
437*1ae08745Sheppo 	int	cmd;
438*1ae08745Sheppo 
439*1ae08745Sheppo 	D3(stderr, "t@%d vntsd_ctrl_cmd%d %d\n", thr_self(),
440*1ae08745Sheppo 	    clientp->cons->vcc_fd, clientp->sockfd);
441*1ae08745Sheppo 
442*1ae08745Sheppo 	if ((c != START) && (c != STOP)) {
443*1ae08745Sheppo 		/* not a supported control command */
444*1ae08745Sheppo 		return (VNTSD_SUCCESS);
445*1ae08745Sheppo 	}
446*1ae08745Sheppo 
447*1ae08745Sheppo 	if (c == START) {
448*1ae08745Sheppo 
449*1ae08745Sheppo 		D3(stderr, "t@%d client restart\n", thr_self());
450*1ae08745Sheppo 
451*1ae08745Sheppo 		/* send resume read */
452*1ae08745Sheppo 		cmd = 1;
453*1ae08745Sheppo 
454*1ae08745Sheppo 		if (ioctl(clientp->cons->vcc_fd, TCXONC, &cmd)) {
455*1ae08745Sheppo 			return (VNTSD_STATUS_VCC_IO_ERR);
456*1ae08745Sheppo 		}
457*1ae08745Sheppo 
458*1ae08745Sheppo 		/* send resume write */
459*1ae08745Sheppo 		cmd = 3;
460*1ae08745Sheppo 
461*1ae08745Sheppo 		if (ioctl(clientp->cons->vcc_fd, TCXONC, &cmd)) {
462*1ae08745Sheppo 			return (VNTSD_STATUS_VCC_IO_ERR);
463*1ae08745Sheppo 		}
464*1ae08745Sheppo 	}
465*1ae08745Sheppo 
466*1ae08745Sheppo 	if (c == STOP) {
467*1ae08745Sheppo 		D3(stderr, "t@%d client suspend\n", thr_self());
468*1ae08745Sheppo 
469*1ae08745Sheppo 		/* send suspend read */
470*1ae08745Sheppo 		cmd = 0;
471*1ae08745Sheppo 
472*1ae08745Sheppo 		if (ioctl(clientp->cons->vcc_fd, TCXONC, &cmd)) {
473*1ae08745Sheppo 			return (VNTSD_STATUS_VCC_IO_ERR);
474*1ae08745Sheppo 		}
475*1ae08745Sheppo 
476*1ae08745Sheppo 		/* send suspend write */
477*1ae08745Sheppo 		cmd = 2;
478*1ae08745Sheppo 
479*1ae08745Sheppo 		if (ioctl(clientp->cons->vcc_fd, TCXONC, &cmd)) {
480*1ae08745Sheppo 			perror("ioctl TCXONC");
481*1ae08745Sheppo 			return (VNTSD_STATUS_VCC_IO_ERR);
482*1ae08745Sheppo 		}
483*1ae08745Sheppo 	}
484*1ae08745Sheppo 
485*1ae08745Sheppo 	return (VNTSD_STATUS_CONTINUE);
486*1ae08745Sheppo }
487