xref: /titanic_53/usr/src/cmd/vntsd/read.c (revision 1ae0874509b6811fdde1dfd46f0d93fd09867a3f)
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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
22*1ae08745Sheppo 
23*1ae08745Sheppo /*
24*1ae08745Sheppo  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
25*1ae08745Sheppo  * Use is subject to license terms.
26*1ae08745Sheppo  */
27*1ae08745Sheppo 
28*1ae08745Sheppo /*
29*1ae08745Sheppo  * read thread - Read from tcp client and write to vcc driver. There  are one
30*1ae08745Sheppo  * writer and multiple readers per console. The first client who connects to
31*1ae08745Sheppo  * a console get write access. An error message is returned to readers if they
32*1ae08745Sheppo  * attemp to input commands. Read thread accepts special daemon commands from
33*1ae08745Sheppo  * all clients.
34*1ae08745Sheppo  */
35*1ae08745Sheppo 
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 <ctype.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 /* write_vcc()  - write to vcc virtual console */
54*1ae08745Sheppo static int
55*1ae08745Sheppo write_vcc(vntsd_client_t *clientp, char c)
56*1ae08745Sheppo {
57*1ae08745Sheppo 	int	n;
58*1ae08745Sheppo 
59*1ae08745Sheppo 
60*1ae08745Sheppo 	assert(clientp);
61*1ae08745Sheppo 	assert(clientp->cons);
62*1ae08745Sheppo 
63*1ae08745Sheppo 	if (c == 0) {
64*1ae08745Sheppo 		return (VNTSD_SUCCESS);
65*1ae08745Sheppo 	}
66*1ae08745Sheppo 	n = write(clientp->cons->vcc_fd, &c, 1);
67*1ae08745Sheppo 
68*1ae08745Sheppo 	if (n < 0) {
69*1ae08745Sheppo 		/* write error */
70*1ae08745Sheppo 		if (errno == EINTR) {
71*1ae08745Sheppo 			return (vntsd_cons_chk_intr(clientp));
72*1ae08745Sheppo 		}
73*1ae08745Sheppo 
74*1ae08745Sheppo 		return (VNTSD_STATUS_VCC_IO_ERR);
75*1ae08745Sheppo 	}
76*1ae08745Sheppo 
77*1ae08745Sheppo 	assert(n != 0);
78*1ae08745Sheppo 	return (VNTSD_SUCCESS);
79*1ae08745Sheppo 
80*1ae08745Sheppo }
81*1ae08745Sheppo 
82*1ae08745Sheppo /*
83*1ae08745Sheppo  * acquire_writer() the client is going to be writer.
84*1ae08745Sheppo  * insert the client to the head of the console client queue.
85*1ae08745Sheppo  */
86*1ae08745Sheppo static int
87*1ae08745Sheppo acquire_writer(vntsd_client_t *clientp)
88*1ae08745Sheppo {
89*1ae08745Sheppo 	vntsd_cons_t	    *consp;
90*1ae08745Sheppo 	vntsd_client_t	    *writerp;
91*1ae08745Sheppo 	int		    rv;
92*1ae08745Sheppo 
93*1ae08745Sheppo 	D1(stderr, "t@%d:acuire_writer :client@%d\n", thr_self(),
94*1ae08745Sheppo 	    clientp->sockfd);
95*1ae08745Sheppo 
96*1ae08745Sheppo 	assert(clientp != NULL);
97*1ae08745Sheppo 	consp = clientp->cons;
98*1ae08745Sheppo 
99*1ae08745Sheppo 	assert(consp);
100*1ae08745Sheppo 
101*1ae08745Sheppo 	(void) mutex_lock(&consp->lock);
102*1ae08745Sheppo 
103*1ae08745Sheppo 	assert(consp->clientpq != NULL);
104*1ae08745Sheppo 	if (consp->clientpq->handle == clientp) {
105*1ae08745Sheppo 		/* clientp is a writer already */
106*1ae08745Sheppo 		(void) mutex_unlock(&consp->lock);
107*1ae08745Sheppo 		return (VNTSD_SUCCESS);
108*1ae08745Sheppo 	}
109*1ae08745Sheppo 
110*1ae08745Sheppo 	/* current writer */
111*1ae08745Sheppo 	writerp = (vntsd_client_t *)(consp->clientpq->handle);
112*1ae08745Sheppo 
113*1ae08745Sheppo 	(void) mutex_lock(&writerp->lock);
114*1ae08745Sheppo 
115*1ae08745Sheppo 	rv = vntsd_que_rm(&(consp->clientpq), clientp);
116*1ae08745Sheppo 	assert(rv == VNTSD_SUCCESS);
117*1ae08745Sheppo 
118*1ae08745Sheppo 	(void) mutex_lock(&clientp->lock);
119*1ae08745Sheppo 
120*1ae08745Sheppo 	/* move client to be first in the console queue */
121*1ae08745Sheppo 	consp->clientpq->handle = clientp;
122*1ae08745Sheppo 
123*1ae08745Sheppo 	/* move previous writer to be the second in the queue */
124*1ae08745Sheppo 	rv =  vntsd_que_insert_after(consp->clientpq, clientp, writerp);
125*1ae08745Sheppo 
126*1ae08745Sheppo 	(void) mutex_unlock(&consp->lock);
127*1ae08745Sheppo 	(void) mutex_unlock(&writerp->lock);
128*1ae08745Sheppo 	(void) mutex_unlock(&clientp->lock);
129*1ae08745Sheppo 
130*1ae08745Sheppo 	if (rv != VNTSD_SUCCESS) {
131*1ae08745Sheppo 		return (rv);
132*1ae08745Sheppo 	}
133*1ae08745Sheppo 
134*1ae08745Sheppo 	/* write warning message to the writer */
135*1ae08745Sheppo 
136*1ae08745Sheppo 	if ((rv = vntsd_write_line(writerp,
137*1ae08745Sheppo 	    gettext("Warning: Console connection forced into read-only mode")))
138*1ae08745Sheppo 	    != VNTSD_SUCCESS) {
139*1ae08745Sheppo 		return (rv);
140*1ae08745Sheppo 	}
141*1ae08745Sheppo 
142*1ae08745Sheppo 	return (VNTSD_SUCCESS);
143*1ae08745Sheppo }
144*1ae08745Sheppo 
145*1ae08745Sheppo /* interrupt handler */
146*1ae08745Sheppo int
147*1ae08745Sheppo vntsd_cons_chk_intr(vntsd_client_t *clientp)
148*1ae08745Sheppo {
149*1ae08745Sheppo 
150*1ae08745Sheppo 	if (clientp->status & VNTSD_CLIENT_TIMEOUT) {
151*1ae08745Sheppo 		return (VNTSD_STATUS_CLIENT_QUIT);
152*1ae08745Sheppo 	}
153*1ae08745Sheppo 	if (clientp->status & VNTSD_CLIENT_CONS_DELETED) {
154*1ae08745Sheppo 		return (VNTSD_STATUS_RESELECT_CONS);
155*1ae08745Sheppo 	}
156*1ae08745Sheppo 
157*1ae08745Sheppo 	if (clientp->status & VNTSD_CLIENT_IO_ERR) {
158*1ae08745Sheppo 		return (VNTSD_STATUS_CLIENT_QUIT);
159*1ae08745Sheppo 	}
160*1ae08745Sheppo 	return (VNTSD_STATUS_CONTINUE);
161*1ae08745Sheppo }
162*1ae08745Sheppo 
163*1ae08745Sheppo /* read from client */
164*1ae08745Sheppo static int
165*1ae08745Sheppo read_char(vntsd_client_t *clientp, char *c)
166*1ae08745Sheppo {
167*1ae08745Sheppo 	int	    rv;
168*1ae08745Sheppo 
169*1ae08745Sheppo 	for (; ; ) {
170*1ae08745Sheppo 
171*1ae08745Sheppo 		rv = vntsd_read_data(clientp, c);
172*1ae08745Sheppo 
173*1ae08745Sheppo 		switch (rv) {
174*1ae08745Sheppo 		case VNTSD_STATUS_CONTINUE:
175*1ae08745Sheppo 			break;
176*1ae08745Sheppo 
177*1ae08745Sheppo 		case VNTSD_STATUS_ACQUIRE_WRITER:
178*1ae08745Sheppo 			rv = acquire_writer(clientp);
179*1ae08745Sheppo 			if (rv != VNTSD_SUCCESS) {
180*1ae08745Sheppo 				return (rv);
181*1ae08745Sheppo 			}
182*1ae08745Sheppo 			break;
183*1ae08745Sheppo 		default:
184*1ae08745Sheppo 			return (rv);
185*1ae08745Sheppo 		}
186*1ae08745Sheppo 	}
187*1ae08745Sheppo }
188*1ae08745Sheppo 
189*1ae08745Sheppo /* vntsd_read worker */
190*1ae08745Sheppo int
191*1ae08745Sheppo vntsd_read(vntsd_client_t *clientp)
192*1ae08745Sheppo {
193*1ae08745Sheppo 	char		c;
194*1ae08745Sheppo 	int		rv;
195*1ae08745Sheppo 
196*1ae08745Sheppo 
197*1ae08745Sheppo 	assert(clientp);
198*1ae08745Sheppo 	D3(stderr, "t@%d vntsd_read@%d\n", thr_self(), clientp->sockfd);
199*1ae08745Sheppo 
200*1ae08745Sheppo 	for (; ; ) {
201*1ae08745Sheppo 
202*1ae08745Sheppo 		/* client input */
203*1ae08745Sheppo 		rv = read_char(clientp, &c);
204*1ae08745Sheppo 
205*1ae08745Sheppo 		if (rv == VNTSD_STATUS_INTR) {
206*1ae08745Sheppo 			rv = vntsd_cons_chk_intr(clientp);
207*1ae08745Sheppo 		}
208*1ae08745Sheppo 
209*1ae08745Sheppo 		if (rv != VNTSD_SUCCESS) {
210*1ae08745Sheppo 			return (rv);
211*1ae08745Sheppo 		}
212*1ae08745Sheppo 
213*1ae08745Sheppo 		assert(clientp->cons);
214*1ae08745Sheppo 		if (clientp->cons->clientpq->handle != clientp) {
215*1ae08745Sheppo 			/* reader - print  error message */
216*1ae08745Sheppo 			if ((c != CR) && (c != LF)) {
217*1ae08745Sheppo 				rv = vntsd_write_line(clientp,
218*1ae08745Sheppo 				    gettext(VNTSD_NO_WRITE_ACCESS_MSG));
219*1ae08745Sheppo 
220*1ae08745Sheppo 				/* check errors and may exit */
221*1ae08745Sheppo 				if (rv == VNTSD_STATUS_INTR) {
222*1ae08745Sheppo 					rv = vntsd_cons_chk_intr(clientp);
223*1ae08745Sheppo 				}
224*1ae08745Sheppo 
225*1ae08745Sheppo 				if (rv != VNTSD_SUCCESS) {
226*1ae08745Sheppo 					return (rv);
227*1ae08745Sheppo 				}
228*1ae08745Sheppo 
229*1ae08745Sheppo 			}
230*1ae08745Sheppo 
231*1ae08745Sheppo 			continue;
232*1ae08745Sheppo 		}
233*1ae08745Sheppo 
234*1ae08745Sheppo 		rv = vntsd_ctrl_cmd(clientp, c);
235*1ae08745Sheppo 
236*1ae08745Sheppo 		switch (rv) {
237*1ae08745Sheppo 		case VNTSD_STATUS_CONTINUE:
238*1ae08745Sheppo 			continue;
239*1ae08745Sheppo 			break;
240*1ae08745Sheppo 		case VNTSD_STATUS_INTR:
241*1ae08745Sheppo 			rv = vntsd_cons_chk_intr(clientp);
242*1ae08745Sheppo 			if (rv != VNTSD_SUCCESS) {
243*1ae08745Sheppo 				return (rv);
244*1ae08745Sheppo 			}
245*1ae08745Sheppo 			break;
246*1ae08745Sheppo 		case VNTSD_SUCCESS:
247*1ae08745Sheppo 			break;
248*1ae08745Sheppo 		default:
249*1ae08745Sheppo 			return (rv);
250*1ae08745Sheppo 		}
251*1ae08745Sheppo 
252*1ae08745Sheppo 		/* write to vcc */
253*1ae08745Sheppo 		rv = write_vcc(clientp, c);
254*1ae08745Sheppo 		if (rv == VNTSD_STATUS_INTR) {
255*1ae08745Sheppo 			rv = vntsd_cons_chk_intr(clientp);
256*1ae08745Sheppo 		}
257*1ae08745Sheppo 		if (rv != VNTSD_SUCCESS) {
258*1ae08745Sheppo 			return (rv);
259*1ae08745Sheppo 		}
260*1ae08745Sheppo 
261*1ae08745Sheppo 	}
262*1ae08745Sheppo 
263*1ae08745Sheppo 	/*NOTREACHED*/
264*1ae08745Sheppo 	return (NULL);
265*1ae08745Sheppo }
266