xref: /illumos-gate/usr/src/cmd/vntsd/common.c (revision 28b1e50e)
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 /*
23*28b1e50eSSriharsha Basavapatna  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
241ae08745Sheppo  * Use is subject to license terms.
251ae08745Sheppo  */
261ae08745Sheppo 
271ae08745Sheppo /*
281ae08745Sheppo  * supporting modules.
291ae08745Sheppo  */
301ae08745Sheppo 
311ae08745Sheppo #include <stdio.h>
321ae08745Sheppo #include <sys/types.h>
331ae08745Sheppo #include <sys/ipc.h>
341ae08745Sheppo #include <stdlib.h>
351ae08745Sheppo #include <string.h>
361ae08745Sheppo #include <unistd.h>
371ae08745Sheppo #include <sys/socket.h>
381ae08745Sheppo #include <sys/ipc.h>
391ae08745Sheppo #include <sys/shm.h>
401ae08745Sheppo #include <sys/sem.h>
411ae08745Sheppo #include <sys/poll.h>
421ae08745Sheppo #include <wait.h>
431ae08745Sheppo #include <time.h>
441ae08745Sheppo #include <netinet/in.h>
451ae08745Sheppo #include <thread.h>
461ae08745Sheppo #include <signal.h>
471ae08745Sheppo #include <ctype.h>
481ae08745Sheppo #include <langinfo.h>
491ae08745Sheppo #include <libintl.h>
501ae08745Sheppo #include <syslog.h>
511ae08745Sheppo #include "vntsd.h"
521ae08745Sheppo #include "chars.h"
531ae08745Sheppo 
541ae08745Sheppo /*  vntsd_write_line() - write a line to TCP client */
551ae08745Sheppo int
vntsd_write_line(vntsd_client_t * clientp,char * line)561ae08745Sheppo vntsd_write_line(vntsd_client_t *clientp, char *line)
571ae08745Sheppo {
581ae08745Sheppo 	int rv;
591ae08745Sheppo 
601ae08745Sheppo 	rv = vntsd_write_client(clientp, line, strlen(line));
611ae08745Sheppo 	if (rv == VNTSD_SUCCESS) {
621ae08745Sheppo 		rv = vntsd_write_client(clientp, vntsd_eol, VNTSD_EOL_LEN);
631ae08745Sheppo 	}
641ae08745Sheppo 
651ae08745Sheppo 	return (rv);
661ae08745Sheppo }
671ae08745Sheppo 
681ae08745Sheppo /*  vntsd_write_lines() write one or more lines to client.  */
691ae08745Sheppo int
vntsd_write_lines(vntsd_client_t * clientp,char * lines)701ae08745Sheppo vntsd_write_lines(vntsd_client_t *clientp, char *lines)
711ae08745Sheppo {
721ae08745Sheppo 	char	*buf;
731ae08745Sheppo 	char	*line;
741ae08745Sheppo 	char 	*endofline;
751ae08745Sheppo 
761ae08745Sheppo 	buf = strdup(lines);
771ae08745Sheppo 	if (buf == NULL) {
781ae08745Sheppo 		return (VNTSD_ERR_NO_MEM);
791ae08745Sheppo 	}
801ae08745Sheppo 
811ae08745Sheppo 	line = buf;
821ae08745Sheppo 
831ae08745Sheppo 	while ((line != NULL) && (*line != '\0')) {
841ae08745Sheppo 
851ae08745Sheppo 		endofline = strchr(line, '\n');
861ae08745Sheppo 		if (endofline != NULL) {
871ae08745Sheppo 			*endofline = '\0';
881ae08745Sheppo 		}
891ae08745Sheppo 
901ae08745Sheppo 		(void) vntsd_write_line(clientp, line);
911ae08745Sheppo 
921ae08745Sheppo 		if (endofline != NULL)
931ae08745Sheppo 			line = endofline + 1;
941ae08745Sheppo 		else
951ae08745Sheppo 			line = NULL;
961ae08745Sheppo 	}
971ae08745Sheppo 
981ae08745Sheppo 	free(buf);
991ae08745Sheppo 	return (VNTSD_SUCCESS);
1001ae08745Sheppo }
1011ae08745Sheppo 
1021ae08745Sheppo /* vntsd_get_yes_no() -  read in a "y" or "n" */
1031ae08745Sheppo int
vntsd_get_yes_no(vntsd_client_t * clientp,char * msg,int * yes_no)1041ae08745Sheppo vntsd_get_yes_no(vntsd_client_t *clientp, char *msg, int *yes_no)
1051ae08745Sheppo {
1061ae08745Sheppo 	char	c;
1071ae08745Sheppo 	char	yesno[8];
1081ae08745Sheppo 	int	rv;
1091ae08745Sheppo 
1101ae08745Sheppo 	/* create [y/n] prompt */
1111ae08745Sheppo 	(void) snprintf(yesno, sizeof (yesno), "[%c/%c] ",
1121ae08745Sheppo 	    *nl_langinfo(YESSTR), *nl_langinfo(NOSTR));
1131ae08745Sheppo 
1141ae08745Sheppo 	for (; ; ) {
1151ae08745Sheppo 		if ((rv = vntsd_write_client(clientp, msg, strlen(msg)))
1161ae08745Sheppo 		    != VNTSD_SUCCESS) {
1171ae08745Sheppo 			return (rv);
1181ae08745Sheppo 		}
1191ae08745Sheppo 
1201ae08745Sheppo 		if ((rv = vntsd_write_client(clientp, yesno, strlen(yesno))) !=
1211ae08745Sheppo 		    VNTSD_SUCCESS) {
1221ae08745Sheppo 			return (rv);
1231ae08745Sheppo 		}
1241ae08745Sheppo 
1251ae08745Sheppo 		if ((rv = vntsd_read_data(clientp, &c))
1261ae08745Sheppo 		    != VNTSD_SUCCESS) {
1271ae08745Sheppo 			return (rv);
1281ae08745Sheppo 		}
1291ae08745Sheppo 
1301ae08745Sheppo 		/* echo */
1311ae08745Sheppo 		if ((rv = vntsd_write_client(clientp, &c, 1)) !=
1321ae08745Sheppo 		    VNTSD_SUCCESS) {
1331ae08745Sheppo 			return (rv);
1341ae08745Sheppo 		}
1351ae08745Sheppo 
1361ae08745Sheppo 		if ((rv = vntsd_write_client(clientp, vntsd_eol,
137*28b1e50eSSriharsha Basavapatna 		    VNTSD_EOL_LEN)) != VNTSD_SUCCESS) {
1381ae08745Sheppo 			return (rv);
1391ae08745Sheppo 		}
1401ae08745Sheppo 
1411ae08745Sheppo 		c = tolower(c);
1421ae08745Sheppo 
1431ae08745Sheppo 		if (c == *nl_langinfo(YESSTR)) {
1441ae08745Sheppo 			*yes_no = B_TRUE;
1451ae08745Sheppo 			return (VNTSD_SUCCESS);
1461ae08745Sheppo 		}
1471ae08745Sheppo 
1481ae08745Sheppo 		if (c == *nl_langinfo(NOSTR)) {
1491ae08745Sheppo 			*yes_no = B_FALSE;
1501ae08745Sheppo 			return (VNTSD_SUCCESS);
1511ae08745Sheppo 		}
1521ae08745Sheppo 
1531ae08745Sheppo 		if ((rv = vntsd_write_line(clientp,
1541ae08745Sheppo 		    gettext("Invalid response. Try again.")))
1551ae08745Sheppo 		    != VNTSD_SUCCESS) {
1561ae08745Sheppo 			return (rv);
1571ae08745Sheppo 		}
1581ae08745Sheppo 	}
1591ae08745Sheppo 
1601ae08745Sheppo 	/*NOTREACHED*/
1611ae08745Sheppo 	return (0);
1621ae08745Sheppo }
1631ae08745Sheppo 
1641ae08745Sheppo /* vntsd_open_vcc()  -  open a vcc port */
1651ae08745Sheppo int
vntsd_open_vcc(char * dev_name,uint_t cons_no)1661ae08745Sheppo vntsd_open_vcc(char *dev_name, uint_t cons_no)
1671ae08745Sheppo {
1681ae08745Sheppo 	int	drvfd;
1691ae08745Sheppo 	int	sz;
1701ae08745Sheppo 	char	*path;
1711ae08745Sheppo 	sz = strlen(VCC_DEVICE_PATH) + strlen(dev_name)+1;
1721ae08745Sheppo 
1731ae08745Sheppo 	path = calloc(sz, 1);
1741ae08745Sheppo 
1751ae08745Sheppo 	if (path == NULL) {
1761ae08745Sheppo 		return (-1);
1771ae08745Sheppo 	}
1781ae08745Sheppo 
1791ae08745Sheppo 	(void) snprintf(path, sz-1, VCC_DEVICE_PATH, dev_name);
1801ae08745Sheppo 
1811ae08745Sheppo 	for (; ; ) {
1821ae08745Sheppo 		drvfd = open(path, O_RDWR);
1831ae08745Sheppo 
1841ae08745Sheppo 		if ((drvfd < 0) && (errno == EAGAIN)) {
1851ae08745Sheppo 			if (vntsd_vcc_ioctl(VCC_FORCE_CLOSE, cons_no, &cons_no)
186*28b1e50eSSriharsha Basavapatna 			    != VNTSD_SUCCESS) {
1871ae08745Sheppo 				break;
188*28b1e50eSSriharsha Basavapatna 			}
1891ae08745Sheppo 		} else {
1901ae08745Sheppo 			break;
1911ae08745Sheppo 		}
1921ae08745Sheppo 	}
1931ae08745Sheppo 
1941ae08745Sheppo 
1951ae08745Sheppo 	if (drvfd < 0) {
1961ae08745Sheppo 		D1(stderr, "t@%d open_vcc@%s exit\n", thr_self(), dev_name);
1971ae08745Sheppo 		free(path);
1981ae08745Sheppo 		return (-1);
1991ae08745Sheppo 	}
2001ae08745Sheppo 
2011ae08745Sheppo 	free(path);
2021ae08745Sheppo 	return (drvfd);
2031ae08745Sheppo }
2041ae08745Sheppo 
2051ae08745Sheppo /* vntsd_cons_by_consno() - match a console structure to cons no */
2061ae08745Sheppo boolean_t
vntsd_cons_by_consno(vntsd_cons_t * consp,int * cons_id)2071ae08745Sheppo vntsd_cons_by_consno(vntsd_cons_t *consp, int *cons_id)
2081ae08745Sheppo {
2091ae08745Sheppo 	if (consp->status & VNTSD_CONS_DELETED) {
2101ae08745Sheppo 		return (B_FALSE);
2111ae08745Sheppo 	}
2121ae08745Sheppo 	return (consp->cons_no == *cons_id);
2131ae08745Sheppo }
2141ae08745Sheppo 
2151ae08745Sheppo /* vntsd_write_client() write to telnet client */
2161ae08745Sheppo int
vntsd_write_client(vntsd_client_t * client,char * buffer,size_t sz)2171ae08745Sheppo vntsd_write_client(vntsd_client_t *client, char *buffer, size_t sz)
2181ae08745Sheppo {
2191ae08745Sheppo 	int rv;
2201ae08745Sheppo 
2211ae08745Sheppo 
2221ae08745Sheppo 	/* write to client */
2231ae08745Sheppo 	rv = vntsd_write_fd(client->sockfd, buffer, sz);
2241ae08745Sheppo 
2251ae08745Sheppo 	/* client has output, reset timer */
2261ae08745Sheppo 	vntsd_reset_timer(client->cons_tid);
2271ae08745Sheppo 
2281ae08745Sheppo 	return (rv);
2291ae08745Sheppo }
2301ae08745Sheppo 
2311ae08745Sheppo /* vntsd_write_fd() write to tcp socket file descriptor  */
2321ae08745Sheppo int
vntsd_write_fd(int fd,void * buf,size_t sz)2331ae08745Sheppo vntsd_write_fd(int fd, void *buf, size_t sz)
2341ae08745Sheppo {
2351ae08745Sheppo 	int n;
2361ae08745Sheppo 
2371ae08745Sheppo 	while (sz > 0) {
2381ae08745Sheppo 		n = write(fd, buf, sz);
2391ae08745Sheppo 		if (n < 0) {
2401ae08745Sheppo 			if (errno == EINTR) {
2411ae08745Sheppo 				return (VNTSD_STATUS_INTR);
2421ae08745Sheppo 			}
2431ae08745Sheppo 
2441ae08745Sheppo 			return (VNTSD_STATUS_CLIENT_QUIT);
2451ae08745Sheppo 		}
2461ae08745Sheppo 
2471ae08745Sheppo 		if (n == 0) {
2481ae08745Sheppo 			return (VNTSD_STATUS_CLIENT_QUIT);
2491ae08745Sheppo 		}
2501ae08745Sheppo 
2511ae08745Sheppo 		buf =  (caddr_t)buf + n;
2521ae08745Sheppo 		sz -= n;
2531ae08745Sheppo 	}
2541ae08745Sheppo 	return (VNTSD_SUCCESS);
2551ae08745Sheppo 
2561ae08745Sheppo }
2571ae08745Sheppo 
2581ae08745Sheppo /*
2591ae08745Sheppo  * vntsd_read_char() - read a char from TCP Clienti. Returns:
2601ae08745Sheppo  * VNTSD_SUCCESS, VNTSD_STATUS_CLIENT_QUIT or VNTSD_STATUS_INTR
2611ae08745Sheppo  */
2621ae08745Sheppo int
vntsd_read_char(vntsd_client_t * clientp,char * c)2631ae08745Sheppo vntsd_read_char(vntsd_client_t *clientp, char *c)
2641ae08745Sheppo {
2651ae08745Sheppo 	int		n;
2661ae08745Sheppo 	vntsd_timeout_t tmo;
2671ae08745Sheppo 	int		rv;
2681ae08745Sheppo 
2691ae08745Sheppo 	tmo.tid = thr_self();
2701ae08745Sheppo 	tmo.minutes = 0;
2711ae08745Sheppo 	tmo.clientp = clientp;
2721ae08745Sheppo 
2731ae08745Sheppo 	/* attach to timer */
2741ae08745Sheppo 	if ((rv = vntsd_attach_timer(&tmo)) != VNTSD_SUCCESS) {
2751ae08745Sheppo 		return (rv);
2761ae08745Sheppo 	}
2771ae08745Sheppo 
2781ae08745Sheppo 	n = read(clientp->sockfd, c, 1);
2791ae08745Sheppo 
2801ae08745Sheppo 	/* detach from timer */
2811ae08745Sheppo 	if ((rv = vntsd_detach_timer(&tmo)) != VNTSD_SUCCESS) {
2821ae08745Sheppo 		return (rv);
2831ae08745Sheppo 	}
2841ae08745Sheppo 
2851ae08745Sheppo 	if (n == 1) {
2861ae08745Sheppo 		return (VNTSD_SUCCESS);
2871ae08745Sheppo 	}
2881ae08745Sheppo 
2891ae08745Sheppo 	if (n == 0) {
2901ae08745Sheppo 		return (VNTSD_STATUS_CLIENT_QUIT);
2911ae08745Sheppo 	}
2921ae08745Sheppo 
2931ae08745Sheppo 	/*
2941ae08745Sheppo 	 * read error or wake up by signal, either console is being removed or
2951ae08745Sheppo 	 * timeout occurs.
2961ae08745Sheppo 	 */
2971ae08745Sheppo 	if (errno == EINTR) {
2981ae08745Sheppo 		return (VNTSD_STATUS_INTR);
2991ae08745Sheppo 	}
3001ae08745Sheppo 
3011ae08745Sheppo 	/* any other error, we close client */
3021ae08745Sheppo 	return (VNTSD_STATUS_CLIENT_QUIT);
3031ae08745Sheppo }
3041ae08745Sheppo 
3051ae08745Sheppo /*
3061ae08745Sheppo  * vntsd_read_data() -  handle special commands
3071ae08745Sheppo  * such as telnet, daemon and ctrl cmds. Returns:
3081ae08745Sheppo  * from vntsd_read_char:
3091ae08745Sheppo  *	    VNTSD_STATUS_CLIENT_QUIT
3101ae08745Sheppo  *	    VNTSD_STATUS_INTR
3111ae08745Sheppo  * from vnts_process_daemon_cmd:
3121ae08745Sheppo  *	    VNTSD_STATUS_RESELECT_CONS
3131ae08745Sheppo  *	    VNTSD_STATUS_MOV_CONS_FORWARD
3141ae08745Sheppo  *	    VNTSD_STATUS_MOV_CONS_BACKWARD
3151ae08745Sheppo  *	    VNTSD_STATUS_ACQURE_WRITER
3161ae08745Sheppo  *	    VNTSD_STATUS_CONTINUE
3171ae08745Sheppo  * from vntsd_telnet_cmd
3181ae08745Sheppo  *	    VNTSD_STATUS_CONTINUE
3191ae08745Sheppo  */
3201ae08745Sheppo int
vntsd_read_data(vntsd_client_t * clientp,char * c)3211ae08745Sheppo vntsd_read_data(vntsd_client_t *clientp, char *c)
3221ae08745Sheppo {
3231ae08745Sheppo 	int rv;
3241ae08745Sheppo 
3251ae08745Sheppo 	for (; ; ) {
3261ae08745Sheppo 		if ((rv = vntsd_read_char(clientp, c)) != VNTSD_SUCCESS) {
327*28b1e50eSSriharsha Basavapatna 			return (rv);
3281ae08745Sheppo 		}
3291ae08745Sheppo 
3301ae08745Sheppo 		/* daemon cmd? */
3311ae08745Sheppo 		rv = vntsd_process_daemon_cmd(clientp, *c);
3321ae08745Sheppo 
3331ae08745Sheppo 		if (rv == VNTSD_SUCCESS) {
3341ae08745Sheppo 			/* telnet cmd? */
3351ae08745Sheppo 			rv = vntsd_telnet_cmd(clientp, *c);
3361ae08745Sheppo 		}
337