xref: /onnv-gate/usr/src/cmd/vntsd/write.c (revision 2336:f53e467a926f)
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 /*
221991Sheppo  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
231991Sheppo  * Use is subject to license terms.
241991Sheppo  */
251991Sheppo #pragma ident	"%Z%%M%	%I%	%E% SMI"
261991Sheppo 
271991Sheppo /*
281991Sheppo  * write thread - read from vcc console and  write to tcp client. There are one
291991Sheppo  * writer and multiple readers per console. The first client who connects to
301991Sheppo  * a console get write access.
311991Sheppo  * Writer thread writes vcc data to all tcp clients that connected to
321991Sheppo  * the console.
331991Sheppo  */
341991Sheppo 
351991Sheppo #include <stdio.h>
361991Sheppo #include <stdio.h>
371991Sheppo #include <stdlib.h>
381991Sheppo #include <string.h>
391991Sheppo #include <unistd.h>
401991Sheppo #include <sys/types.h>
411991Sheppo #include <sys/socket.h>
421991Sheppo #include <netinet/in.h>
431991Sheppo #include <thread.h>
441991Sheppo #include <synch.h>
451991Sheppo #include <signal.h>
461991Sheppo #include <assert.h>
471991Sheppo #include <poll.h>
481991Sheppo #include <syslog.h>
491991Sheppo #include <libintl.h>
501991Sheppo #include "vntsd.h"
511991Sheppo #include "chars.h"
521991Sheppo 
53*2336Snarayan /* handle for writing all clients  */
54*2336Snarayan typedef	struct write_buf {
55*2336Snarayan 	uint_t	sz;	    /* data size */
56*2336Snarayan 	char	*buf;
57*2336Snarayan } write_buf_t;
58*2336Snarayan 
591991Sheppo /*
601991Sheppo  * check the state of write thread. exit if no more client connects to the
611991Sheppo  * console.
621991Sheppo  */
631991Sheppo static void
write_chk_status(vntsd_cons_t * consp,int status)641991Sheppo write_chk_status(vntsd_cons_t *consp, int status)
651991Sheppo {
661991Sheppo 
671991Sheppo 	if ((consp->status & VNTSD_CONS_DELETED) || (consp->clientpq == NULL)) {
681991Sheppo 		thr_exit(0);
691991Sheppo 	}
701991Sheppo 
711991Sheppo 	switch (status) {
721991Sheppo 	case VNTSD_STATUS_VCC_IO_ERR:
731991Sheppo 		assert(consp->group != NULL);
741991Sheppo 		if (vntsd_vcc_err(consp) != VNTSD_STATUS_CONTINUE) {
751991Sheppo 			thr_exit(0);
761991Sheppo 		}
771991Sheppo 		break;
781991Sheppo 	case VNTSD_STATUS_INTR:
791991Sheppo 		thr_exit(0);
801991Sheppo 	default:
811991Sheppo 		break;
821991Sheppo 
831991Sheppo 	}
841991Sheppo }
851991Sheppo 
861991Sheppo /*
871991Sheppo  * skip_terminal_null()
881991Sheppo  * scan terminal null character sequence (0x5e 0x40)
891991Sheppo  * return number of characters in the buf after skipping terminal null
90*2336Snarayan  * sequence. buf size must be at least sz+1.
911991Sheppo  */
921991Sheppo static int
skip_terminal_null(char * buf,int sz)93*2336Snarayan skip_terminal_null(char *buf, int sz)
941991Sheppo {
951991Sheppo 	int	    i, j;
961991Sheppo 	static int  term_null_seq = 0;
971991Sheppo 
981991Sheppo 	assert(sz >= 0);
991991Sheppo 
1001991Sheppo 	if (term_null_seq) {
1011991Sheppo 		/* skip 0x5e previously */
1021991Sheppo 		term_null_seq = 0;
1031991Sheppo 
1041991Sheppo 		if (buf[0] != 0x40) {
1051991Sheppo 			/* not terminal null sequence put 0x5e back */
1061991Sheppo 			for (i = sz; i > 0; i--) {
1071991Sheppo 				buf[i] = buf[i-1];
1081991Sheppo 			}
1091991Sheppo 
1101991Sheppo 			buf[0] = 0x5e;
1111991Sheppo 
1121991Sheppo 			sz++;
1131991Sheppo 		} else {
1141991Sheppo 			/* skip terminal null sequence */
1151991Sheppo 			sz--;
1161991Sheppo 
1171991Sheppo 			if (sz == 0) {
1181991Sheppo 				return (sz);
1191991Sheppo 			}
1201991Sheppo 
1211991Sheppo 			for (i = 0; i < sz; i++) {
1221991Sheppo 				buf[i] = buf[i+1];
1231991Sheppo 			}
1241991Sheppo 		}
1251991Sheppo 	}
1261991Sheppo 
1271991Sheppo 	for (; ; ) {
1281991Sheppo 		for (i = 0; i < sz; i++) {
1291991Sheppo 			if (buf[i]  == '\0') {
1301991Sheppo 				return (i);
1311991Sheppo 			}
1321991Sheppo 
1331991Sheppo 			if (buf[i] == 0x5e) {
1341991Sheppo 				/* possible terminal null sequence */
1351991Sheppo 				if (i == sz -1) {
1361991Sheppo 					/* last character in buffer */
1371991Sheppo 					term_null_seq = 1;
1381991Sheppo 					sz--;
1391991Sheppo 					buf[i] = 0;
1401991Sheppo 					return (sz);
1411991Sheppo 				}
1421991Sheppo 
1431991Sheppo 				if (buf[i+1] == 0x40) {
1441991Sheppo 					/* found terminal null sequence */
1451991Sheppo 					sz -= 2;
1461991Sheppo 					for (j = i; j < sz -i; j++) {
1471991Sheppo 						buf[j] = buf[j+2];
1481991Sheppo 					}
1491991Sheppo 					break;
1501991Sheppo 				}
1511991Sheppo 
1521991Sheppo 				if (buf[i+1] == '\0') {
1531991Sheppo 					buf[i] = 0;
1541991Sheppo 					term_null_seq = 1;
1551991Sheppo 					return (i);
1561991Sheppo 				}
1571991Sheppo 
1581991Sheppo 			}
1591991Sheppo 		}
1601991Sheppo 
1611991Sheppo 		if (i == sz) {
1621991Sheppo 			/* end of scan */
1631991Sheppo 			return (sz);
1641991Sheppo 		}
1651991Sheppo 	}
1661991Sheppo }
1671991Sheppo 
1681991Sheppo /* read data from vcc */
1691991Sheppo static int
read_vcc(vntsd_cons_t * consp,char * buf,ssize_t * sz)1701991Sheppo read_vcc(vntsd_cons_t *consp, char *buf, ssize_t *sz)
1711991Sheppo {
1721991Sheppo 	/* read from vcc */
1731991Sheppo 	*sz = read(consp->vcc_fd, buf, VNTSD_MAX_BUF_SIZE);
1741991Sheppo 
1751991Sheppo 	if (errno == EINTR) {
1761991Sheppo 		return (VNTSD_STATUS_INTR);
1771991Sheppo 	}
1781991Sheppo 
1791991Sheppo 	if ((*sz > 0)) {
1801991Sheppo 		return (VNTSD_SUCCESS);
1811991Sheppo 	}
1821991Sheppo 	return (VNTSD_STATUS_VCC_IO_ERR);
1831991Sheppo }
1841991Sheppo 
185*2336Snarayan /*
186*2336Snarayan  * write to a client
187*2336Snarayan  * this function is passed as a parameter to vntsd_que_find.
188*2336Snarayan  * for each client that connected to the console, vntsd_que_find
189*2336Snarayan  * applies this function.
190*2336Snarayan  */
1911991Sheppo static boolean_t
write_one_client(vntsd_client_t * clientp,write_buf_t * write_buf)192*2336Snarayan write_one_client(vntsd_client_t *clientp, write_buf_t *write_buf)
1931991Sheppo {
1941991Sheppo 	int rv;
1951991Sheppo 
196*2336Snarayan 	rv = vntsd_write_client(clientp, write_buf->buf, write_buf->sz);
1971991Sheppo 	if (rv != VNTSD_SUCCESS) {
1981991Sheppo 		(void) mutex_lock(&clientp->lock);
1991991Sheppo 		clientp->status |= VNTSD_CLIENT_IO_ERR;
2001991Sheppo 		assert(clientp->cons);
2011991Sheppo 		(void) thr_kill(clientp->cons_tid, NULL);
2021991Sheppo 		(void) mutex_unlock(&clientp->lock);
2031991Sheppo 	}
2041991Sheppo 	return (B_FALSE);
2051991Sheppo 
2061991Sheppo }
2071991Sheppo 
2081991Sheppo /* vntsd_write_thread() */
2091991Sheppo void*
vntsd_write_thread(vntsd_cons_t * consp)2101991Sheppo vntsd_write_thread(vntsd_cons_t *consp)
2111991Sheppo {
2121991Sheppo 	char		buf[VNTSD_MAX_BUF_SIZE+1];
2131991Sheppo 	int		sz;
2141991Sheppo 	int		rv;
215*2336Snarayan 	write_buf_t	write_buf;
2161991Sheppo 
2171991Sheppo 	D1(stderr, "t@%d vntsd_write@%d\n", thr_self(), consp->vcc_fd);
2181991Sheppo 
2191991Sheppo 	assert(consp);
2201991Sheppo 	write_chk_status(consp, VNTSD_SUCCESS);
2211991Sheppo 
2221991Sheppo 	for (; ; ) {
2231991Sheppo 		bzero(buf,  VNTSD_MAX_BUF_SIZE +1);
2241991Sheppo 
2251991Sheppo 		/* read data */
2261991Sheppo 		rv = read_vcc(consp, buf, &sz);
2271991Sheppo 
2281991Sheppo 		write_chk_status(consp, rv);
2291991Sheppo 
2301991Sheppo 		if (sz <= 0) {
2311991Sheppo 			continue;
2321991Sheppo 		}
2331991Sheppo 
2341991Sheppo 		/* has data */
235*2336Snarayan 		if ((sz = skip_terminal_null(buf, sz)) == 0) {
2361991Sheppo 			/* terminal null sequence */
2371991Sheppo 			continue;
2381991Sheppo 		}
2391991Sheppo 
240*2336Snarayan 		write_buf.sz = sz;
241*2336Snarayan 		write_buf.buf = buf;
2421991Sheppo 
2431991Sheppo 		/*
2441991Sheppo 		 * output data to all clients connected
2451991Sheppo 		 * to this console
2461991Sheppo 		 */
2471991Sheppo 
2481991Sheppo 		(void) mutex_lock(&consp->lock);
2491991Sheppo 		(void) vntsd_que_find(consp->clientpq,
250*2336Snarayan 		    (compare_func_t)write_one_client, &write_buf);
2511991Sheppo 		(void) mutex_unlock(&consp->lock);
2521991Sheppo 
2531991Sheppo 		write_chk_status(consp, VNTSD_SUCCESS);
2541991Sheppo 
2551991Sheppo 	}
2561991Sheppo 
2571991Sheppo 	/*NOTREACHED*/
2581991Sheppo 	return (NULL);
2591991Sheppo }
260