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