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 /* 221ae08745Sheppo * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 231ae08745Sheppo * Use is subject to license terms. 241ae08745Sheppo */ 251ae08745Sheppo 261ae08745Sheppo #pragma ident "%Z%%M% %I% %E% SMI" 271ae08745Sheppo 281ae08745Sheppo /* 291ae08745Sheppo * Vntsd handles two types of special commands, one is telnet 301ae08745Sheppo * commands and another is vntsd special commands. 311ae08745Sheppo * telnet commands supported are: 321ae08745Sheppo * WILL 331ae08745Sheppo * WONT 341ae08745Sheppo * DO 351ae08745Sheppo * DONT 361ae08745Sheppo * TEL_ECHO 371ae08745Sheppo * SUPRESS 381ae08745Sheppo * LINEMODE 391ae08745Sheppo * BRK 401ae08745Sheppo * AYT 411ae08745Sheppo * HT 421ae08745Sheppo * 431ae08745Sheppo * Vntsd special commands are: 448e6a2a04Slm66018 * Send break (~#) 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 1061ae08745Sheppo /* 1071ae08745Sheppo * console_forward() - cycle client to the next console 1081ae08745Sheppo * in the group queue. 1091ae08745Sheppo */ 1101ae08745Sheppo static int 111*1e8f6090Sdtse console_forward(vntsd_client_t *clientp) 1121ae08745Sheppo { 113*1e8f6090Sdtse /* forward when there are mutiple consoles in the group */ 114*1e8f6090Sdtse if (clientp->cons->group->num_cons > 1) 1151ae08745Sheppo return (VNTSD_STATUS_MOV_CONS_FORWARD); 116*1e8f6090Sdtse 117*1e8f6090Sdtse return (VNTSD_STATUS_CONTINUE); 118*1e8f6090Sdtse 1191ae08745Sheppo } 1201ae08745Sheppo 1211ae08745Sheppo /* 1221ae08745Sheppo * console_backward() - cycle client to the previous 1231ae08745Sheppo * console in the group queue. 1241ae08745Sheppo */ 1251ae08745Sheppo static int 126*1e8f6090Sdtse console_backward(vntsd_client_t *clientp) 1271ae08745Sheppo { 128*1e8f6090Sdtse /* backward when there are mutiple consoles in the group */ 129*1e8f6090Sdtse if (clientp->cons->group->num_cons > 1) 1301ae08745Sheppo return (VNTSD_STATUS_MOV_CONS_BACKWARD); 131*1e8f6090Sdtse 132*1e8f6090Sdtse return (VNTSD_STATUS_CONTINUE); 133*1e8f6090Sdtse 1341ae08745Sheppo } 1351ae08745Sheppo 1361ae08745Sheppo /* acquire_write() - acquire write access to a console. */ 1371ae08745Sheppo static int 1381ae08745Sheppo acquire_write(vntsd_client_t *clientp) 1391ae08745Sheppo { 1401ae08745Sheppo int rv; 1411ae08745Sheppo int yes_no = 1; 1421ae08745Sheppo vntsd_cons_t *consp; 1431ae08745Sheppo 1441ae08745Sheppo assert(clientp); 1451ae08745Sheppo consp = clientp->cons; 1461ae08745Sheppo assert(consp); 1471ae08745Sheppo 1481ae08745Sheppo if (consp->clientpq->handle == clientp) { 1491ae08745Sheppo /* client is a writer */ 1501ae08745Sheppo if ((rv = vntsd_write_line(clientp, 1511ae08745Sheppo gettext("You have write permission"))) != 1521ae08745Sheppo VNTSD_SUCCESS) { 1531ae08745Sheppo return (rv); 1541ae08745Sheppo 1551ae08745Sheppo } 1561ae08745Sheppo return (VNTSD_STATUS_CONTINUE); 1571ae08745Sheppo } 1581ae08745Sheppo 1591ae08745Sheppo /* message to client */ 1601ae08745Sheppo if ((rv = vntsd_write_client(clientp, vntsd_eol, VNTSD_EOL_LEN)) 1611ae08745Sheppo != VNTSD_SUCCESS) { 1621ae08745Sheppo return (rv); 1631ae08745Sheppo } 1641ae08745Sheppo 1651ae08745Sheppo /* 1661ae08745Sheppo * TRANSLATION_NOTE 1671ae08745Sheppo * The following string should be formatted to fit on multiple lines 1681ae08745Sheppo * assuming a line width of at most 78 characters. There must be no 1691ae08745Sheppo * trailing newline. 1701ae08745Sheppo */ 1711ae08745Sheppo if ((rv = vntsd_write_lines(clientp, 1721ae08745Sheppo gettext("Warning: another user currently " 1731ae08745Sheppo "has write permission\nto this console and forcibly removing " 1741ae08745Sheppo "him/her will terminate\nany current write action and all work " 1751ae08745Sheppo "will be lost."))) != VNTSD_SUCCESS) { 1761ae08745Sheppo return (rv); 1771ae08745Sheppo } 1781ae08745Sheppo 1791ae08745Sheppo /* get client yes no */ 1801ae08745Sheppo if ((rv = vntsd_write_client(clientp, vntsd_eol, 1811ae08745Sheppo VNTSD_EOL_LEN)) != VNTSD_SUCCESS) { 1821ae08745Sheppo return (rv); 1831ae08745Sheppo } 1841ae08745Sheppo 1851ae08745Sheppo if ((rv = vntsd_get_yes_no(clientp, 1861ae08745Sheppo gettext("Would you like to continue?"), 1871ae08745Sheppo &yes_no)) != VNTSD_SUCCESS) { 1881ae08745Sheppo return (rv); 1891ae08745Sheppo } 1901ae08745Sheppo 1911ae08745Sheppo if (yes_no == B_FALSE) { 1921ae08745Sheppo /* client change mind no need to acquire write access */ 1931ae08745Sheppo return (VNTSD_STATUS_CONTINUE); 1941ae08745Sheppo } 1951ae08745Sheppo 1961ae08745Sheppo return (VNTSD_STATUS_ACQUIRE_WRITER); 1971ae08745Sheppo } 1981ae08745Sheppo 1991ae08745Sheppo /* client_exit() - disconnect client from the console. */ 2001ae08745Sheppo static int 2011ae08745Sheppo client_exit(void) 2021ae08745Sheppo { 2031ae08745Sheppo return (VNTSD_STATUS_RESELECT_CONS); 2041ae08745Sheppo } 2051ae08745Sheppo 2061ae08745Sheppo static int daemon_cmd_help(vntsd_client_t *clientp); 2071ae08745Sheppo 2081ae08745Sheppo /* table for daemon commands */ 2091ae08745Sheppo 2101ae08745Sheppo static esctable_t etable[] = { 2111ae08745Sheppo 2121ae08745Sheppo /* send a break to vcc */ 2138e6a2a04Slm66018 {'#', "Send break", genbrk}, 2141ae08745Sheppo 2151ae08745Sheppo /* exit */ 2168e6a2a04Slm66018 {'.', "Exit from this console", (e_func_t)client_exit}, 2171ae08745Sheppo 2181ae08745Sheppo /* acquire write access */ 2198e6a2a04Slm66018 {'w', "Force write access", acquire_write}, 2201ae08745Sheppo 2211ae08745Sheppo /* connect to next console in queue */ 2228e6a2a04Slm66018 {'n', "Console next", (e_func_t)console_forward}, 2231ae08745Sheppo 2241ae08745Sheppo /* connect to previous console in queue */ 2258e6a2a04Slm66018 {'p', "Console previous", (e_func_t)console_backward}, 2261ae08745Sheppo 2271ae08745Sheppo /* help must be next to last */ 2288e6a2a04Slm66018 {'?', "Help", daemon_cmd_help}, 2291ae08745Sheppo 2301ae08745Sheppo /* table terminator */ 2311ae08745Sheppo {0, 0, 0} 2321ae08745Sheppo }; 2331ae08745Sheppo 2341ae08745Sheppo void 2351ae08745Sheppo vntsd_init_esctable_msgs(void) 2361ae08745Sheppo { 2371ae08745Sheppo esctable_t *p; 2381ae08745Sheppo 2391ae08745Sheppo for (p = etable; p->e_char != '\0'; p++) { 2401ae08745Sheppo p->e_help = gettext(p->e_help); 2411ae08745Sheppo } 2421ae08745Sheppo } 2431ae08745Sheppo 2441ae08745Sheppo /* daemon_cmd_help() - print help. */ 2451ae08745Sheppo static int 2461ae08745Sheppo daemon_cmd_help(vntsd_client_t *clientp) 2471ae08745Sheppo { 2481ae08745Sheppo esctable_t *p; 2491ae08745Sheppo int rv; 2501ae08745Sheppo char buf[VNTSD_LINE_LEN]; 2511ae08745Sheppo 2521ae08745Sheppo if ((rv = vntsd_write_client(clientp, vntsd_eol, 2531ae08745Sheppo VNTSD_EOL_LEN)) != VNTSD_SUCCESS) { 2541ae08745Sheppo return (rv); 2551ae08745Sheppo } 2561ae08745Sheppo 2571ae08745Sheppo /* 2581ae08745Sheppo * TRANSLATION_NOTE 2591ae08745Sheppo * VNTSD is the name of the VNTS daemon and should not be translated. 2601ae08745Sheppo */ 2611ae08745Sheppo if ((rv = vntsd_write_line(clientp, gettext("VNTSD commands"))) != 2621ae08745Sheppo VNTSD_SUCCESS) { 2631ae08745Sheppo return (rv); 2641ae08745Sheppo } 2651ae08745Sheppo 2661ae08745Sheppo for (p = etable; p->e_char; p++) { 2671ae08745Sheppo (void) snprintf(buf, sizeof (buf), 2681ae08745Sheppo "~%c --%s", p->e_char, p->e_help); 2691ae08745Sheppo 2701ae08745Sheppo if ((rv = vntsd_write_line(clientp, buf)) != VNTSD_SUCCESS) { 2711ae08745Sheppo return (rv); 2721ae08745Sheppo } 2731ae08745Sheppo } 2741ae08745Sheppo 2751ae08745Sheppo return (VNTSD_STATUS_CONTINUE); 2761ae08745Sheppo } 2771ae08745Sheppo 2781ae08745Sheppo /* exit from daemon command */ 2791ae08745Sheppo static int 2801ae08745Sheppo exit_daemon_cmd(vntsd_client_t *clientp, int rv) 2811ae08745Sheppo { 2821ae08745Sheppo (void) mutex_lock(&clientp->lock); 2831ae08745Sheppo clientp->status &= ~VNTSD_CLIENT_DISABLE_DAEMON_CMD; 2841ae08745Sheppo (void) mutex_unlock(&clientp->lock); 2851ae08745Sheppo return (rv); 2861ae08745Sheppo } 2871ae08745Sheppo 288d10e4ef2Snarayan /* 289d10e4ef2Snarayan * vntsd_process_daemon_cmd() - special commands 290d10e4ef2Snarayan * "<RET>~" vntsd daemon commands 291d10e4ef2Snarayan * "<RET>~~" enter '~' character 292d10e4ef2Snarayan */ 2931ae08745Sheppo int 2941ae08745Sheppo vntsd_process_daemon_cmd(vntsd_client_t *clientp, char c) 2951ae08745Sheppo { 2961ae08745Sheppo esctable_t *p; 2971ae08745Sheppo int rv; 298d10e4ef2Snarayan char prev_char; 2991ae08745Sheppo 300d10e4ef2Snarayan prev_char = clientp->prev_char; 301d10e4ef2Snarayan clientp->prev_char = c; 302d10e4ef2Snarayan 303d10e4ef2Snarayan if (c != VNTSD_DAEMON_CMD || (prev_char != 0 && prev_char != CR)) { 3041ae08745Sheppo /* not a daemon command */ 3051ae08745Sheppo return (VNTSD_SUCCESS); 3061ae08745Sheppo } 3071ae08745Sheppo 3081ae08745Sheppo if (clientp->status & VNTSD_CLIENT_DISABLE_DAEMON_CMD) { 3091ae08745Sheppo return (VNTSD_STATUS_CONTINUE); 3101ae08745Sheppo } 3111ae08745Sheppo 3121ae08745Sheppo /* no reentry to process_daemon_cmd */ 3131ae08745Sheppo (void) mutex_lock(&clientp->lock); 3141ae08745Sheppo clientp->status |= VNTSD_CLIENT_DISABLE_DAEMON_CMD; 3151ae08745Sheppo (void) mutex_unlock(&clientp->lock); 3161ae08745Sheppo 3171ae08745Sheppo D3(stderr, "t@%d process_daemon_cmd %d %d \n", thr_self(), 3181ae08745Sheppo clientp->cons->vcc_fd, clientp->sockfd); 3191ae08745Sheppo 3201ae08745Sheppo /* read in command */ 3211ae08745Sheppo if ((rv = vntsd_read_char(clientp, &c)) != VNTSD_SUCCESS) { 3221ae08745Sheppo return (exit_daemon_cmd(clientp, rv)); 3231ae08745Sheppo } 3241ae08745Sheppo 325d10e4ef2Snarayan clientp->prev_char = c; 326d10e4ef2Snarayan if (c == VNTSD_DAEMON_CMD) { 327d10e4ef2Snarayan /* 328d10e4ef2Snarayan * received another '~' 329d10e4ef2Snarayan * a user types '~~' to get '~' 330d10e4ef2Snarayan */ 331d10e4ef2Snarayan (void) mutex_lock(&clientp->lock); 332d10e4ef2Snarayan clientp->status &= ~VNTSD_CLIENT_DISABLE_DAEMON_CMD; 333d10e4ef2Snarayan (void) mutex_unlock(&clientp->lock); 334d10e4ef2Snarayan return (VNTSD_SUCCESS); 335d10e4ef2Snarayan } 336d10e4ef2Snarayan 3371ae08745Sheppo for (p = etable; p->e_char; p++) { 3381ae08745Sheppo if (p->e_char == c) { 3391ae08745Sheppo /* found match */ 3401ae08745Sheppo assert(p->e_func); 3411ae08745Sheppo rv = (*p->e_func)(clientp); 3421ae08745Sheppo return (exit_daemon_cmd(clientp, rv)); 3431ae08745Sheppo } 3441ae08745Sheppo } 3451ae08745Sheppo 3461ae08745Sheppo /* no match, print out the help */ 3471ae08745Sheppo p--; 3481ae08745Sheppo assert(p->e_char == '?'); 3491ae08745Sheppo rv = (*p->e_func)(clientp); 3501ae08745Sheppo 3511ae08745Sheppo return (exit_daemon_cmd(clientp, rv)); 3521ae08745Sheppo 3531ae08745Sheppo } 3541ae08745Sheppo 3551ae08745Sheppo /* vntsd_set_telnet_options() - change telnet client to character mode. */ 3561ae08745Sheppo int 3571ae08745Sheppo vntsd_set_telnet_options(int fd) 3581ae08745Sheppo { 3591ae08745Sheppo /* set client telnet options */ 3601ae08745Sheppo uint8_t buf[] = {IAC, DONT, LINEMODE, IAC, WILL, SUPRESS, IAC, WILL, 3611ae08745Sheppo TEL_ECHO, IAC, DONT, TERM_TYPE, IAC, DONT, TERM_SP, 3621ae08745Sheppo IAC, DONT, STATUS, IAC, DONT, FC, IAC, DONT, TM, IAC, DONT, ENV, 3631ae08745Sheppo IAC, DONT, WIN_SIZE}; 3641ae08745Sheppo 3651ae08745Sheppo return (vntsd_write_fd(fd, (char *)buf, 30)); 3661ae08745Sheppo } 3671ae08745Sheppo 3681ae08745Sheppo /* vntsd_telnet_cmd() process telnet commands */ 3691ae08745Sheppo int 3701ae08745Sheppo vntsd_telnet_cmd(vntsd_client_t *clientp, char c) 3711ae08745Sheppo { 3721ae08745Sheppo uint8_t buf[4]; 3731ae08745Sheppo char cmd; 3741ae08745Sheppo int rv = VNTSD_STATUS_CONTINUE; 3751ae08745Sheppo 3761ae08745Sheppo bzero(buf, 4); 3771ae08745Sheppo 3781ae08745Sheppo if ((uint8_t)c != IAC) { 3791ae08745Sheppo /* not telnet cmd */ 3801ae08745Sheppo return (VNTSD_SUCCESS); 3811ae08745Sheppo } 3821ae08745Sheppo 3831ae08745Sheppo if ((rv = vntsd_read_char(clientp, &cmd)) != VNTSD_SUCCESS) { 3841ae08745Sheppo return (rv); 3851ae08745Sheppo } 3861ae08745Sheppo 3871ae08745Sheppo if ((rv = vntsd_read_char(clientp, &c)) != VNTSD_SUCCESS) { 3881ae08745Sheppo return (rv); 3891ae08745Sheppo } 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 4391ae08745Sheppo case AYT: 4401ae08745Sheppo 4411ae08745Sheppo rv = vntsd_write_client(clientp, &c, 1); 4421ae08745Sheppo break; 4431ae08745Sheppo 4441ae08745Sheppo case HT: 4451ae08745Sheppo return (VNTSD_STATUS_CONTINUE); 4461ae08745Sheppo 4471ae08745Sheppo default: 4481ae08745Sheppo syslog(LOG_ERR, "not support telnet ctrl %x\n", c); 4491ae08745Sheppo break; 4501ae08745Sheppo } 4511ae08745Sheppo 4521ae08745Sheppo if (rv == VNTSD_SUCCESS) { 4531ae08745Sheppo return (VNTSD_STATUS_CONTINUE); 4541ae08745Sheppo } else { 4551ae08745Sheppo return (rv); 4561ae08745Sheppo } 4571ae08745Sheppo } 4581ae08745Sheppo 4591ae08745Sheppo 4601ae08745Sheppo /* 4611ae08745Sheppo * vntsd_ctrl_cmd() - control keys 4621ae08745Sheppo * read and write suspend are supported. 4631ae08745Sheppo */ 4641ae08745Sheppo int 4651ae08745Sheppo vntsd_ctrl_cmd(vntsd_client_t *clientp, char c) 4661ae08745Sheppo { 4671ae08745Sheppo int cmd; 4681ae08745Sheppo 4691ae08745Sheppo D3(stderr, "t@%d vntsd_ctrl_cmd%d %d\n", thr_self(), 4701ae08745Sheppo clientp->cons->vcc_fd, clientp->sockfd); 4711ae08745Sheppo 4721ae08745Sheppo if ((c != START) && (c != STOP)) { 4731ae08745Sheppo /* not a supported control command */ 4741ae08745Sheppo return (VNTSD_SUCCESS); 4751ae08745Sheppo } 4761ae08745Sheppo 4771ae08745Sheppo if (c == START) { 4781ae08745Sheppo D3(stderr, "t@%d client restart\n", thr_self()); 4791ae08745Sheppo 4801ae08745Sheppo /* send resume read */ 4811ae08745Sheppo cmd = 1; 4821ae08745Sheppo 4831ae08745Sheppo if (ioctl(clientp->cons->vcc_fd, TCXONC, &cmd)) { 4841ae08745Sheppo return (VNTSD_STATUS_VCC_IO_ERR); 4851ae08745Sheppo } 4861ae08745Sheppo 4871ae08745Sheppo } 4881ae08745Sheppo 4891ae08745Sheppo if (c == STOP) { 4901ae08745Sheppo D3(stderr, "t@%d client suspend\n", thr_self()); 4911ae08745Sheppo 4921ae08745Sheppo /* send suspend read */ 4931ae08745Sheppo cmd = 0; 4941ae08745Sheppo 4951ae08745Sheppo if (ioctl(clientp->cons->vcc_fd, TCXONC, &cmd)) { 4961ae08745Sheppo return (VNTSD_STATUS_VCC_IO_ERR); 4971ae08745Sheppo } 4981ae08745Sheppo 4991ae08745Sheppo } 5001ae08745Sheppo 5011ae08745Sheppo return (VNTSD_STATUS_CONTINUE); 5021ae08745Sheppo } 503