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 #pragma ident "%Z%%M% %I% %E% SMI" 26*1ae08745Sheppo 27*1ae08745Sheppo /* 28*1ae08745Sheppo * write thread - read from vcc console and write to tcp client. There are one 29*1ae08745Sheppo * writer and multiple readers per console. The first client who connects to 30*1ae08745Sheppo * a console get write access. 31*1ae08745Sheppo * Writer thread writes vcc data to all tcp clients that connected to 32*1ae08745Sheppo * the console. 33*1ae08745Sheppo */ 34*1ae08745Sheppo 35*1ae08745Sheppo #include <stdio.h> 36*1ae08745Sheppo #include <stdio.h> 37*1ae08745Sheppo #include <stdlib.h> 38*1ae08745Sheppo #include <string.h> 39*1ae08745Sheppo #include <unistd.h> 40*1ae08745Sheppo #include <sys/types.h> 41*1ae08745Sheppo #include <sys/socket.h> 42*1ae08745Sheppo #include <netinet/in.h> 43*1ae08745Sheppo #include <thread.h> 44*1ae08745Sheppo #include <synch.h> 45*1ae08745Sheppo #include <signal.h> 46*1ae08745Sheppo #include <assert.h> 47*1ae08745Sheppo #include <poll.h> 48*1ae08745Sheppo #include <syslog.h> 49*1ae08745Sheppo #include <libintl.h> 50*1ae08745Sheppo #include "vntsd.h" 51*1ae08745Sheppo #include "chars.h" 52*1ae08745Sheppo 53*1ae08745Sheppo /* 54*1ae08745Sheppo * check the state of write thread. exit if no more client connects to the 55*1ae08745Sheppo * console. 56*1ae08745Sheppo */ 57*1ae08745Sheppo static void 58*1ae08745Sheppo write_chk_status(vntsd_cons_t *consp, int status) 59*1ae08745Sheppo { 60*1ae08745Sheppo 61*1ae08745Sheppo if ((consp->status & VNTSD_CONS_DELETED) || (consp->clientpq == NULL)) { 62*1ae08745Sheppo thr_exit(0); 63*1ae08745Sheppo } 64*1ae08745Sheppo 65*1ae08745Sheppo switch (status) { 66*1ae08745Sheppo case VNTSD_STATUS_VCC_IO_ERR: 67*1ae08745Sheppo assert(consp->group != NULL); 68*1ae08745Sheppo if (vntsd_vcc_err(consp) != VNTSD_STATUS_CONTINUE) { 69*1ae08745Sheppo thr_exit(0); 70*1ae08745Sheppo } 71*1ae08745Sheppo break; 72*1ae08745Sheppo case VNTSD_STATUS_INTR: 73*1ae08745Sheppo thr_exit(0); 74*1ae08745Sheppo default: 75*1ae08745Sheppo break; 76*1ae08745Sheppo 77*1ae08745Sheppo } 78*1ae08745Sheppo } 79*1ae08745Sheppo 80*1ae08745Sheppo /* 81*1ae08745Sheppo * skip_terminal_null() 82*1ae08745Sheppo * scan terminal null character sequence (0x5e 0x40) 83*1ae08745Sheppo * return number of characters in the buf after skipping terminal null 84*1ae08745Sheppo * sequence. 85*1ae08745Sheppo */ 86*1ae08745Sheppo static int 87*1ae08745Sheppo skip_terminal_null(char *buf, int buf_sz, int sz) 88*1ae08745Sheppo { 89*1ae08745Sheppo int i, j; 90*1ae08745Sheppo static int term_null_seq = 0; 91*1ae08745Sheppo 92*1ae08745Sheppo assert(sz >= 0); 93*1ae08745Sheppo 94*1ae08745Sheppo if (buf_sz < sz+1) { 95*1ae08745Sheppo return (-1); 96*1ae08745Sheppo } 97*1ae08745Sheppo 98*1ae08745Sheppo if (term_null_seq) { 99*1ae08745Sheppo /* skip 0x5e previously */ 100*1ae08745Sheppo term_null_seq = 0; 101*1ae08745Sheppo 102*1ae08745Sheppo if (buf[0] != 0x40) { 103*1ae08745Sheppo /* not terminal null sequence put 0x5e back */ 104*1ae08745Sheppo for (i = sz; i > 0; i--) { 105*1ae08745Sheppo buf[i] = buf[i-1]; 106*1ae08745Sheppo } 107*1ae08745Sheppo 108*1ae08745Sheppo buf[0] = 0x5e; 109*1ae08745Sheppo 110*1ae08745Sheppo sz++; 111*1ae08745Sheppo } else { 112*1ae08745Sheppo /* skip terminal null sequence */ 113*1ae08745Sheppo sz--; 114*1ae08745Sheppo 115*1ae08745Sheppo if (sz == 0) { 116*1ae08745Sheppo return (sz); 117*1ae08745Sheppo } 118*1ae08745Sheppo 119*1ae08745Sheppo for (i = 0; i < sz; i++) { 120*1ae08745Sheppo buf[i] = buf[i+1]; 121*1ae08745Sheppo } 122*1ae08745Sheppo } 123*1ae08745Sheppo } 124*1ae08745Sheppo 125*1ae08745Sheppo for (; ; ) { 126*1ae08745Sheppo for (i = 0; i < sz; i++) { 127*1ae08745Sheppo if (buf[i] == '\0') { 128*1ae08745Sheppo return (i); 129*1ae08745Sheppo } 130*1ae08745Sheppo 131*1ae08745Sheppo if (buf[i] == 0x5e) { 132*1ae08745Sheppo /* possible terminal null sequence */ 133*1ae08745Sheppo if (i == sz -1) { 134*1ae08745Sheppo /* last character in buffer */ 135*1ae08745Sheppo term_null_seq = 1; 136*1ae08745Sheppo sz--; 137*1ae08745Sheppo buf[i] = 0; 138*1ae08745Sheppo return (sz); 139*1ae08745Sheppo } 140*1ae08745Sheppo 141*1ae08745Sheppo if (buf[i+1] == 0x40) { 142*1ae08745Sheppo /* found terminal null sequence */ 143*1ae08745Sheppo sz -= 2; 144*1ae08745Sheppo for (j = i; j < sz -i; j++) { 145*1ae08745Sheppo buf[j] = buf[j+2]; 146*1ae08745Sheppo } 147*1ae08745Sheppo break; 148*1ae08745Sheppo } 149*1ae08745Sheppo 150*1ae08745Sheppo if (buf[i+1] == '\0') { 151*1ae08745Sheppo buf[i] = 0; 152*1ae08745Sheppo term_null_seq = 1; 153*1ae08745Sheppo return (i); 154*1ae08745Sheppo } 155*1ae08745Sheppo 156*1ae08745Sheppo } 157*1ae08745Sheppo } 158*1ae08745Sheppo 159*1ae08745Sheppo if (i == sz) { 160*1ae08745Sheppo /* end of scan */ 161*1ae08745Sheppo return (sz); 162*1ae08745Sheppo } 163*1ae08745Sheppo } 164*1ae08745Sheppo } 165*1ae08745Sheppo 166*1ae08745Sheppo /* read data from vcc */ 167*1ae08745Sheppo static int 168*1ae08745Sheppo read_vcc(vntsd_cons_t *consp, char *buf, ssize_t *sz) 169*1ae08745Sheppo { 170*1ae08745Sheppo /* read from vcc */ 171*1ae08745Sheppo *sz = read(consp->vcc_fd, buf, VNTSD_MAX_BUF_SIZE); 172*1ae08745Sheppo 173*1ae08745Sheppo if (errno == EINTR) { 174*1ae08745Sheppo return (VNTSD_STATUS_INTR); 175*1ae08745Sheppo } 176*1ae08745Sheppo 177*1ae08745Sheppo if ((*sz > 0)) { 178*1ae08745Sheppo return (VNTSD_SUCCESS); 179*1ae08745Sheppo } 180*1ae08745Sheppo return (VNTSD_STATUS_VCC_IO_ERR); 181*1ae08745Sheppo } 182*1ae08745Sheppo 183*1ae08745Sheppo static int s_sz; 184*1ae08745Sheppo /* write to a client */ 185*1ae08745Sheppo static boolean_t 186*1ae08745Sheppo write_all_clients(vntsd_client_t *clientp, char *buf) 187*1ae08745Sheppo { 188*1ae08745Sheppo int rv; 189*1ae08745Sheppo 190*1ae08745Sheppo rv = vntsd_write_client(clientp, buf, s_sz); 191*1ae08745Sheppo if (rv != VNTSD_SUCCESS) { 192*1ae08745Sheppo (void) mutex_lock(&clientp->lock); 193*1ae08745Sheppo clientp->status |= VNTSD_CLIENT_IO_ERR; 194*1ae08745Sheppo assert(clientp->cons); 195*1ae08745Sheppo (void) thr_kill(clientp->cons_tid, NULL); 196*1ae08745Sheppo (void) mutex_unlock(&clientp->lock); 197*1ae08745Sheppo } 198*1ae08745Sheppo return (B_FALSE); 199*1ae08745Sheppo 200*1ae08745Sheppo } 201*1ae08745Sheppo 202*1ae08745Sheppo /* vntsd_write_thread() */ 203*1ae08745Sheppo void* 204*1ae08745Sheppo vntsd_write_thread(vntsd_cons_t *consp) 205*1ae08745Sheppo { 206*1ae08745Sheppo char buf[VNTSD_MAX_BUF_SIZE+1]; 207*1ae08745Sheppo int sz; 208*1ae08745Sheppo int rv; 209*1ae08745Sheppo 210*1ae08745Sheppo D1(stderr, "t@%d vntsd_write@%d\n", thr_self(), consp->vcc_fd); 211*1ae08745Sheppo 212*1ae08745Sheppo assert(consp); 213*1ae08745Sheppo write_chk_status(consp, VNTSD_SUCCESS); 214*1ae08745Sheppo 215*1ae08745Sheppo for (; ; ) { 216*1ae08745Sheppo bzero(buf, VNTSD_MAX_BUF_SIZE +1); 217*1ae08745Sheppo 218*1ae08745Sheppo /* read data */ 219*1ae08745Sheppo rv = read_vcc(consp, buf, &sz); 220*1ae08745Sheppo 221*1ae08745Sheppo write_chk_status(consp, rv); 222*1ae08745Sheppo 223*1ae08745Sheppo if (sz <= 0) { 224*1ae08745Sheppo continue; 225*1ae08745Sheppo } 226*1ae08745Sheppo 227*1ae08745Sheppo /* has data */ 228*1ae08745Sheppo if ((s_sz = skip_terminal_null(buf, sz+1, sz)) == 0) { 229*1ae08745Sheppo /* terminal null sequence */ 230*1ae08745Sheppo continue; 231*1ae08745Sheppo } 232*1ae08745Sheppo 233*1ae08745Sheppo assert(s_sz > 0); 234*1ae08745Sheppo 235*1ae08745Sheppo /* 236*1ae08745Sheppo * output data to all clients connected 237*1ae08745Sheppo * to this console 238*1ae08745Sheppo */ 239*1ae08745Sheppo 240*1ae08745Sheppo (void) mutex_lock(&consp->lock); 241*1ae08745Sheppo (void) vntsd_que_find(consp->clientpq, 242*1ae08745Sheppo (compare_func_t)write_all_clients, buf); 243*1ae08745Sheppo (void) mutex_unlock(&consp->lock); 244*1ae08745Sheppo 245*1ae08745Sheppo write_chk_status(consp, VNTSD_SUCCESS); 246*1ae08745Sheppo 247*1ae08745Sheppo } 248*1ae08745Sheppo 249*1ae08745Sheppo /*NOTREACHED*/ 250*1ae08745Sheppo return (NULL); 251*1ae08745Sheppo } 252