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 /* 22*a93081c1SChris 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 40*a93081c1SChris Gerhard * NOP 411ae08745Sheppo * 421ae08745Sheppo * Vntsd special commands are: 438e6a2a04Slm66018 * Send break (~#) 448e6a2a04Slm66018 * Exit (~.) 458e6a2a04Slm66018 * Force write access (~w) 468e6a2a04Slm66018 * Console next (~n) 478e6a2a04Slm66018 * Console previous (~p) 488e6a2a04Slm66018 * Help (~?) 491ae08745Sheppo */ 501ae08745Sheppo 511ae08745Sheppo #include <stdio.h> 521ae08745Sheppo #include <stdlib.h> 531ae08745Sheppo #include <string.h> 541ae08745Sheppo #include <unistd.h> 551ae08745Sheppo #include <sys/types.h> 561ae08745Sheppo #include <sys/socket.h> 571ae08745Sheppo #include <netinet/in.h> 581ae08745Sheppo #include <thread.h> 591ae08745Sheppo #include <ctype.h> 601ae08745Sheppo #include <sys/termio.h> 611ae08745Sheppo #include <libintl.h> 621ae08745Sheppo #include <syslog.h> 631ae08745Sheppo #include "vntsd.h" 641ae08745Sheppo #include "chars.h" 651ae08745Sheppo 661ae08745Sheppo char vntsd_eol[] = { CR, LF, 0}; 671ae08745Sheppo 681ae08745Sheppo typedef int (*e_func_t)(vntsd_client_t *clientp); 691ae08745Sheppo /* structure for daemon special cmd */ 701ae08745Sheppo typedef struct { 711ae08745Sheppo char e_char; /* char to match on */ 721ae08745Sheppo char *e_help; /* help string */ 731ae08745Sheppo e_func_t e_func; /* command */ 741ae08745Sheppo } esctable_t; 751ae08745Sheppo 761ae08745Sheppo /* genbrk() - send a break to vcc driver */ 771ae08745Sheppo static int 781ae08745Sheppo genbrk(vntsd_client_t *clientp) 791ae08745Sheppo { 801ae08745Sheppo 811ae08745Sheppo vntsd_cons_t *consp; 821ae08745Sheppo 831ae08745Sheppo assert(clientp); 841ae08745Sheppo assert(clientp->cons); 851ae08745Sheppo 861ae08745Sheppo consp = clientp->cons; 871ae08745Sheppo D1(stderr, "t@%d genbrk fd=%d sockfd %d\n", thr_self(), 881ae08745Sheppo consp->vcc_fd, clientp->sockfd); 891ae08745Sheppo 901ae08745Sheppo assert(consp->clientpq != NULL); 911ae08745Sheppo if (consp->clientpq->handle != clientp) { 921ae08745Sheppo /* reader */ 931ae08745Sheppo return (vntsd_write_line(clientp, 941ae08745Sheppo gettext(VNTSD_NO_WRITE_ACCESS_MSG))); 951ae08745Sheppo } 961ae08745Sheppo 971ae08745Sheppo /* writer */ 981ae08745Sheppo if (ioctl(consp->vcc_fd, TCSBRK, NULL)) { 991ae08745Sheppo return (VNTSD_ERR_VCC_IOCTL); 1001ae08745Sheppo } 1011ae08745Sheppo 1021ae08745Sheppo return (VNTSD_STATUS_CONTINUE); 1031ae08745Sheppo } 1041ae08745Sheppo 1051ae08745Sheppo /* 1061ae08745Sheppo * console_forward() - cycle client to the next console 1071ae08745Sheppo * in the group queue. 1081ae08745Sheppo */ 1091ae08745Sheppo static int 1101e8f6090Sdtse console_forward(vntsd_client_t *clientp) 1111ae08745Sheppo { 1121e8f6090Sdtse /* forward when there are mutiple consoles in the group */ 1131e8f6090Sdtse if (clientp->cons->group->num_cons > 1) 1141ae08745Sheppo return (VNTSD_STATUS_MOV_CONS_FORWARD); 1151e8f6090Sdtse 1161e8f6090Sdtse return (VNTSD_STATUS_CONTINUE); 1171e8f6090Sdtse 1181ae08745Sheppo } 1191ae08745Sheppo 1201ae08745Sheppo /* 1211ae08745Sheppo * console_backward() - cycle client to the previous 1221ae08745Sheppo * console in the group queue. 1231ae08745Sheppo */ 1241ae08745Sheppo static int 1251e8f6090Sdtse console_backward(vntsd_client_t *clientp) 1261ae08745Sheppo { 1271e8f6090Sdtse /* backward when there are mutiple consoles in the group */ 1281e8f6090Sdtse if (clientp->cons->group->num_cons > 1) 1291ae08745Sheppo return (VNTSD_STATUS_MOV_CONS_BACKWARD); 1301e8f6090Sdtse 1311e8f6090Sdtse return (VNTSD_STATUS_CONTINUE); 1321e8f6090Sdtse 1331ae08745Sheppo } 1341ae08745Sheppo 1351ae08745Sheppo /* acquire_write() - acquire write access to a console. */ 1361ae08745Sheppo static int 1371ae08745Sheppo acquire_write(vntsd_client_t *clientp) 1381ae08745Sheppo { 1391ae08745Sheppo int rv; 1401ae08745Sheppo int yes_no = 1; 1411ae08745Sheppo vntsd_cons_t *consp; 1421ae08745Sheppo 1431ae08745Sheppo assert(clientp); 1441ae08745Sheppo consp = clientp->cons; 1451ae08745Sheppo assert(consp); 1461ae08745Sheppo 1471ae08745Sheppo if (consp->clientpq->handle == clientp) { 1481ae08745Sheppo /* client is a writer */ 1491ae08745Sheppo if ((rv = vntsd_write_line(clientp, 1501ae08745Sheppo gettext("You have write permission"))) != 1511ae08745Sheppo VNTSD_SUCCESS) { 1521ae08745Sheppo return (rv); 1531ae08745Sheppo 1541ae08745Sheppo } 1551ae08745Sheppo return (VNTSD_STATUS_CONTINUE); 1561ae08745Sheppo } 1571ae08745Sheppo 1581ae08745Sheppo /* message to client */ 1591ae08745Sheppo if ((rv = vntsd_write_client(clientp, vntsd_eol, VNTSD_EOL_LEN)) 1601ae08745Sheppo != VNTSD_SUCCESS) { 1611ae08745Sheppo return (rv); 1621ae08745Sheppo } 1631ae08745Sheppo 1641ae08745Sheppo /* 1651ae08745Sheppo * TRANSLATION_NOTE 1661ae08745Sheppo * The following string should be formatted to fit on multiple lines 1671ae08745Sheppo * assuming a line width of at most 78 characters. There must be no 1681ae08745Sheppo * trailing newline. 1691ae08745Sheppo */ 1701ae08745Sheppo if ((rv = vntsd_write_lines(clientp, 1711ae08745Sheppo gettext("Warning: another user currently " 1721ae08745Sheppo "has write permission\nto this console and forcibly removing " 1731ae08745Sheppo "him/her will terminate\nany current write action and all work " 1741ae08745Sheppo "will be lost."))) != VNTSD_SUCCESS) { 1751ae08745Sheppo return (rv); 1761ae08745Sheppo } 1771ae08745Sheppo 1781ae08745Sheppo /* get client yes no */ 1791ae08745Sheppo if ((rv = vntsd_write_client(clientp, vntsd_eol, 1801ae08745Sheppo VNTSD_EOL_LEN)) != VNTSD_SUCCESS) { 1811ae08745Sheppo return (rv); 1821ae08745Sheppo } 1831ae08745Sheppo 1841ae08745Sheppo if ((rv = vntsd_get_yes_no(clientp, 1851ae08745Sheppo gettext("Would you like to continue?"), 1861ae08745Sheppo &yes_no)) != VNTSD_SUCCESS) { 1871ae08745Sheppo return (rv); 1881ae08745Sheppo } 1891ae08745Sheppo 1901ae08745Sheppo if (yes_no == B_FALSE) { 1911ae08745Sheppo /* client change mind no need to acquire write access */ 1921ae08745Sheppo return (VNTSD_STATUS_CONTINUE); 1931ae08745Sheppo } 1941ae08745Sheppo 1951ae08745Sheppo return (VNTSD_STATUS_ACQUIRE_WRITER); 1961ae08745Sheppo } 1971ae08745Sheppo 1981ae08745Sheppo /* client_exit() - disconnect client from the console. */ 1991ae08745Sheppo static int 2001ae08745Sheppo client_exit(void) 2011ae08745Sheppo { 2021ae08745Sheppo return (VNTSD_STATUS_RESELECT_CONS); 2031ae08745Sheppo } 2041ae08745Sheppo 2051ae08745Sheppo static int daemon_cmd_help(vntsd_client_t *clientp); 2061ae08745Sheppo 2071ae08745Sheppo /* table for daemon commands */ 2081ae08745Sheppo 2091ae08745Sheppo static esctable_t etable[] = { 2101ae08745Sheppo 2111ae08745Sheppo /* send a break to vcc */ 2128e6a2a04Slm66018 {'#', "Send break", genbrk}, 2131ae08745Sheppo 2141ae08745Sheppo /* exit */ 2158e6a2a04Slm66018 {'.', "Exit from this console", (e_func_t)client_exit}, 2161ae08745Sheppo 2171ae08745Sheppo /* acquire write access */ 2188e6a2a04Slm66018 {'w', "Force write access", acquire_write}, 2191ae08745Sheppo 2201ae08745Sheppo /* connect to next console in queue */ 2218e6a2a04Slm66018 {'n', "Console next", (e_func_t)console_forward}, 2221ae08745Sheppo 2231ae08745Sheppo /* connect to previous console in queue */ 2248e6a2a04Slm66018 {'p', "Console previous", (e_func_t)console_backward}, 2251ae08745Sheppo 2261ae08745Sheppo /* help must be next to last */ 2278e6a2a04Slm66018 {'?', "Help", daemon_cmd_help}, 2281ae08745Sheppo 2291ae08745Sheppo /* table terminator */ 2301ae08745Sheppo {0, 0, 0} 2311ae08745Sheppo }; 2321ae08745Sheppo 2331ae08745Sheppo void 2341ae08745Sheppo vntsd_init_esctable_msgs(void) 2351ae08745Sheppo { 2361ae08745Sheppo esctable_t *p; 2371ae08745Sheppo 2381ae08745Sheppo for (p = etable; p->e_char != '\0'; p++) { 2391ae08745Sheppo p->e_help = gettext(p->e_help); 2401ae08745Sheppo } 2411ae08745Sheppo } 2421ae08745Sheppo 2431ae08745Sheppo /* daemon_cmd_help() - print help. */ 2441ae08745Sheppo static int 2451ae08745Sheppo daemon_cmd_help(vntsd_client_t *clientp) 2461ae08745Sheppo { 2471ae08745Sheppo esctable_t *p; 2481ae08745Sheppo int rv; 2491ae08745Sheppo char buf[VNTSD_LINE_LEN]; 2501ae08745Sheppo 2511ae08745Sheppo if ((rv = vntsd_write_client(clientp, vntsd_eol, 2521ae08745Sheppo VNTSD_EOL_LEN)) != VNTSD_SUCCESS) { 2531ae08745Sheppo return (rv); 2541ae08745Sheppo } 2551ae08745Sheppo 2561ae08745Sheppo /* 2571ae08745Sheppo * TRANSLATION_NOTE 2581ae08745Sheppo * VNTSD is the name of the VNTS daemon and should not be translated. 2591ae08745Sheppo */ 2601ae08745Sheppo if ((rv = vntsd_write_line(clientp, gettext("VNTSD commands"))) != 2611ae08745Sheppo VNTSD_SUCCESS) { 2621ae08745Sheppo return (rv); 2631ae08745Sheppo } 2641ae08745Sheppo 2651ae08745Sheppo for (p = etable; p->e_char; p++) { 2661ae08745Sheppo (void) snprintf(buf, sizeof (buf), 2671ae08745Sheppo "~%c --%s", p->e_char, p->e_help); 2681ae08745Sheppo 2691ae08745Sheppo if ((rv = vntsd_write_line(clientp, buf)) != VNTSD_SUCCESS) { 2701ae08745Sheppo return (rv); 2711ae08745Sheppo } 2721ae08745Sheppo } 2731ae08745Sheppo 2741ae08745Sheppo return (VNTSD_STATUS_CONTINUE); 2751ae08745Sheppo } 2761ae08745Sheppo 2771ae08745Sheppo /* exit from daemon command */ 2781ae08745Sheppo static int 2791ae08745Sheppo exit_daemon_cmd(vntsd_client_t *clientp, int rv) 2801ae08745Sheppo { 2811ae08745Sheppo (void) mutex_lock(&clientp->lock); 2821ae08745Sheppo clientp->status &= ~VNTSD_CLIENT_DISABLE_DAEMON_CMD; 2831ae08745Sheppo (void) mutex_unlock(&clientp->lock); 2841ae08745Sheppo return (rv); 2851ae08745Sheppo } 2861ae08745Sheppo 287d10e4ef2Snarayan /* 288d10e4ef2Snarayan * vntsd_process_daemon_cmd() - special commands 289d10e4ef2Snarayan * "<RET>~" vntsd daemon commands 290d10e4ef2Snarayan * "<RET>~~" enter '~' character 291d10e4ef2Snarayan */ 2921ae08745Sheppo int 2931ae08745Sheppo vntsd_process_daemon_cmd(vntsd_client_t *clientp, char c) 2941ae08745Sheppo { 2951ae08745Sheppo esctable_t *p; 2961ae08745Sheppo int rv; 297d10e4ef2Snarayan char prev_char; 2981ae08745Sheppo 299d10e4ef2Snarayan prev_char = clientp->prev_char; 300d10e4ef2Snarayan 301d10e4ef2Snarayan if (c != VNTSD_DAEMON_CMD || (prev_char != 0 && prev_char != CR)) { 3021ae08745Sheppo /* not a daemon command */ 3031ae08745Sheppo return (VNTSD_SUCCESS); 3041ae08745Sheppo } 3051ae08745Sheppo 3061ae08745Sheppo if (clientp->status & VNTSD_CLIENT_DISABLE_DAEMON_CMD) { 3071ae08745Sheppo return (VNTSD_STATUS_CONTINUE); 3081ae08745Sheppo } 3091ae08745Sheppo 3101ae08745Sheppo /* no reentry to process_daemon_cmd */ 3111ae08745Sheppo (void) mutex_lock(&clientp->lock); 3121ae08745Sheppo clientp->status |= VNTSD_CLIENT_DISABLE_DAEMON_CMD; 3131ae08745Sheppo (void) mutex_unlock(&clientp->lock); 3141ae08745Sheppo 3151ae08745Sheppo D3(stderr, "t@%d process_daemon_cmd %d %d \n", thr_self(), 3161ae08745Sheppo clientp->cons->vcc_fd, clientp->sockfd); 3171ae08745Sheppo 3181ae08745Sheppo /* read in command */ 3191ae08745Sheppo if ((rv = vntsd_read_char(clientp, &c)) != VNTSD_SUCCESS) { 3201ae08745Sheppo return (exit_daemon_cmd(clientp, rv)); 3211ae08745Sheppo } 3221ae08745Sheppo 323d10e4ef2Snarayan if (c == VNTSD_DAEMON_CMD) { 324d10e4ef2Snarayan /* 325d10e4ef2Snarayan * received another '~' 326d10e4ef2Snarayan * a user types '~~' to get '~' 327d10e4ef2Snarayan */ 328d10e4ef2Snarayan (void) mutex_lock(&clientp->lock); 329d10e4ef2Snarayan clientp->status &= ~VNTSD_CLIENT_DISABLE_DAEMON_CMD; 330d10e4ef2Snarayan (void) mutex_unlock(&clientp->lock); 331d10e4ef2Snarayan return (VNTSD_SUCCESS); 332d10e4ef2Snarayan } 333d10e4ef2Snarayan 3341ae08745Sheppo for (p = etable; p->e_char; p++) { 3351ae08745Sheppo if (p->e_char == c) { 3361ae08745Sheppo /* found match */ 3371ae08745Sheppo assert(p->e_func); 3381ae08745Sheppo rv = (*p->e_func)(clientp); 3391ae08745Sheppo return (exit_daemon_cmd(clientp, rv)); 3401ae08745Sheppo } 3411ae08745Sheppo } 3421ae08745Sheppo 3431ae08745Sheppo /* no match, print out the help */ 3441ae08745Sheppo p--; 3451ae08745Sheppo assert(p->e_char == '?'); 3461ae08745Sheppo rv = (*p->e_func)(clientp); 3471ae08745Sheppo 3481ae08745Sheppo return (exit_daemon_cmd(clientp, rv)); 3491ae08745Sheppo 3501ae08745Sheppo } 3511ae08745Sheppo 3521ae08745Sheppo /* vntsd_set_telnet_options() - change telnet client to character mode. */ 3531ae08745Sheppo int 3541ae08745Sheppo vntsd_set_telnet_options(int fd) 3551ae08745Sheppo { 3561ae08745Sheppo /* set client telnet options */ 3571ae08745Sheppo uint8_t buf[] = {IAC, DONT, LINEMODE, IAC, WILL, SUPRESS, IAC, WILL, 3581ae08745Sheppo TEL_ECHO, IAC, DONT, TERM_TYPE, IAC, DONT, TERM_SP, 3591ae08745Sheppo IAC, DONT, STATUS, IAC, DONT, FC, IAC, DONT, TM, IAC, DONT, ENV, 3601ae08745Sheppo IAC, DONT, WIN_SIZE}; 3611ae08745Sheppo 3621ae08745Sheppo return (vntsd_write_fd(fd, (char *)buf, 30)); 3631ae08745Sheppo } 3641ae08745Sheppo 3651ae08745Sheppo /* vntsd_telnet_cmd() process telnet commands */ 3661ae08745Sheppo int 3671ae08745Sheppo vntsd_telnet_cmd(vntsd_client_t *clientp, char c) 3681ae08745Sheppo { 3691ae08745Sheppo uint8_t buf[4]; 3701ae08745Sheppo char cmd; 3711ae08745Sheppo int rv = VNTSD_STATUS_CONTINUE; 3721ae08745Sheppo 3731ae08745Sheppo bzero(buf, 4); 3741ae08745Sheppo 3751ae08745Sheppo if ((uint8_t)c != IAC) { 3761ae08745Sheppo /* not telnet cmd */ 3771ae08745Sheppo return (VNTSD_SUCCESS); 3781ae08745Sheppo } 3791ae08745Sheppo 3801ae08745Sheppo if ((rv = vntsd_read_char(clientp, &cmd)) != VNTSD_SUCCESS) { 3811ae08745Sheppo return (rv); 3821ae08745Sheppo } 3831ae08745Sheppo 384*a93081c1SChris Gerhard if ((uint8_t)cmd == WILL || (uint8_t)cmd == WONT || 385*a93081c1SChris Gerhard (uint8_t)cmd == DO || (uint8_t)cmd == DONT) { 3861ae08745Sheppo if ((rv = vntsd_read_char(clientp, &c)) != VNTSD_SUCCESS) { 3871ae08745Sheppo return (rv); 3881ae08745Sheppo } 389823fe29bSdtse } 3901ae08745Sheppo 3911ae08745Sheppo 3921ae08745Sheppo switch ((uint8_t)cmd) { 3931ae08745Sheppo 3941ae08745Sheppo case WILL: 3951ae08745Sheppo 3961ae08745Sheppo switch ((uint8_t)c) { 3971ae08745Sheppo case TEL_ECHO: 3981ae08745Sheppo case SUPRESS: 3991ae08745Sheppo case LINEMODE: 4001ae08745Sheppo break; 4011ae08745Sheppo default: 4021ae08745Sheppo syslog(LOG_ERR, "not support telnet WILL %x\n", c); 4031ae08745Sheppo break; 4041ae08745Sheppo } 4051ae08745Sheppo break; 4061ae08745Sheppo 4071ae08745Sheppo case WONT: 4081ae08745Sheppo 4091ae08745Sheppo switch ((uint8_t)c) { 4101ae08745Sheppo case TEL_ECHO: 4111ae08745Sheppo case SUPRESS: 4121ae08745Sheppo case LINEMODE: 4131ae08745Sheppo default: 4141ae08745Sheppo syslog(LOG_ERR, "not support telnet WONT %x\n", c); 4151ae08745Sheppo break; 4161ae08745Sheppo } 4171ae08745Sheppo break; 4181ae08745Sheppo 4191ae08745Sheppo case DO: 4201ae08745Sheppo case DONT: 4211ae08745Sheppo 4221ae08745Sheppo buf[0] = IAC; 4231ae08745Sheppo buf[1] = WILL; 4241ae08745Sheppo buf[2] = c; 4251ae08745Sheppo rv = vntsd_write_client(clientp, (char *)buf, 3); 4261ae08745Sheppo 4271ae08745Sheppo break; 4281ae08745Sheppo 4291ae08745Sheppo case BRK: 4301ae08745Sheppo 4311ae08745Sheppo /* send break to vcc */ 4321ae08745Sheppo rv = genbrk(clientp); 4331ae08745Sheppo break; 4341ae08745Sheppo 4351ae08745Sheppo case IP: 4361ae08745Sheppo 4371ae08745Sheppo break; 4381ae08745Sheppo 439*a93081c1SChris Gerhard case AYT: { 440*a93081c1SChris Gerhard static char aytresp[] = "vntsd here"; 4411ae08745Sheppo 442*a93081c1SChris Gerhard rv = vntsd_write_client(clientp, aytresp, 443*a93081c1SChris Gerhard sizeof (aytresp) - 1); 4441ae08745Sheppo break; 445*a93081c1SChris Gerhard } 4461ae08745Sheppo 4471ae08745Sheppo case HT: 448*a93081c1SChris Gerhard case NOP: 4491ae08745Sheppo return (VNTSD_STATUS_CONTINUE); 4501ae08745Sheppo 4511ae08745Sheppo default: 452*a93081c1SChris Gerhard syslog(LOG_ERR, "not support telnet ctrl %2.2x\n", 0xff & cmd); 4531ae08745Sheppo break; 4541ae08745Sheppo } 4551ae08745Sheppo 4561ae08745Sheppo if (rv == VNTSD_SUCCESS) { 4571ae08745Sheppo return (VNTSD_STATUS_CONTINUE); 4581ae08745Sheppo } else { 4591ae08745Sheppo return (rv); 4601ae08745Sheppo } 4611ae08745Sheppo } 4621ae08745Sheppo 4631ae08745Sheppo 4641ae08745Sheppo /* 4651ae08745Sheppo * vntsd_ctrl_cmd() - control keys 4661ae08745Sheppo * read and write suspend are supported. 4671ae08745Sheppo */ 4681ae08745Sheppo int 4691ae08745Sheppo vntsd_ctrl_cmd(vntsd_client_t *clientp, char c) 4701ae08745Sheppo { 4711ae08745Sheppo int cmd; 4721ae08745Sheppo 4731ae08745Sheppo D3(stderr, "t@%d vntsd_ctrl_cmd%d %d\n", thr_self(), 4741ae08745Sheppo clientp->cons->vcc_fd, clientp->sockfd); 4751ae08745Sheppo 4761ae08745Sheppo if ((c != START) && (c != STOP)) { 4771ae08745Sheppo /* not a supported control command */ 4781ae08745Sheppo return (VNTSD_SUCCESS); 4791ae08745Sheppo } 4801ae08745Sheppo 4811ae08745Sheppo if (c == START) { 4821ae08745Sheppo D3(stderr, "t@%d client restart\n", thr_self()); 4831ae08745Sheppo 4841ae08745Sheppo /* send resume read */ 4851ae08745Sheppo cmd = 1; 4861ae08745Sheppo 4871ae08745Sheppo if (ioctl(clientp->cons->vcc_fd, TCXONC, &cmd)) { 4881ae08745Sheppo return (VNTSD_STATUS_VCC_IO_ERR); 4891ae08745Sheppo } 4901ae08745Sheppo 4911ae08745Sheppo } 4921ae08745Sheppo 4931ae08745Sheppo if (c == STOP) { 4941ae08745Sheppo D3(stderr, "t@%d client suspend\n", thr_self()); 4951ae08745Sheppo 4961ae08745Sheppo /* send suspend read */ 4971ae08745Sheppo cmd = 0; 4981ae08745Sheppo 4991ae08745Sheppo if (ioctl(clientp->cons->vcc_fd, TCXONC, &cmd)) { 5001ae08745Sheppo return (VNTSD_STATUS_VCC_IO_ERR); 5011ae08745Sheppo } 5021ae08745Sheppo 5031ae08745Sheppo } 5041ae08745Sheppo 5051ae08745Sheppo return (VNTSD_STATUS_CONTINUE); 5061ae08745Sheppo } 507