/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Listen thread creates a console thread whenever there is a tcp client
* made a conection to its port. In the console thread, if there are
* multiple consoles in the group, client will be asked for a console selection.
* a write thread for a console is created when first client connects to a
* selected console and console thread becomes read thread for the client.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <thread.h>
#include <synch.h>
#include <signal.h>
#include <assert.h>
#include <ctype.h>
#include <syslog.h>
#include <libintl.h>
#include <netdb.h>
#include "vntsd.h"
#include "chars.h"
/* display domain names in the group */
static boolean_t
{
char *status;
} else {
}
}
/* output connected message to tcp client */
static int
char *domain_name)
{
return (rv);
}
gettext("Connecting to console \"%s\" in group \"%s\" ...."),
return (rv);
}
gettext("Press ~? for control options .."))) !=
return (rv);
}
return (VNTSD_SUCCESS);
}
static int
{
/* create write thread for the console */
"create write thread failed\n",
return (VNTSD_ERR_CREATE_WR_THR);
}
return (VNTSD_SUCCESS);
}
/* Display all domain consoles in a group. */
static int
{
!= VNTSD_SUCCESS) {
return (rv);
}
/*
* TRANSLATION_NOTE
* The following three strings of the form "DOMAIN .." are table
* headers and should be all uppercase.
*/
"%-20s%-30s%-25s",
gettext("DOMAIN STATE"));
return (rv);
}
}
return (rv);
}
/* display help */
static int
{
char *bufp;
!= VNTSD_SUCCESS) {
return (rv);
}
/*
* TRANSLATION_NOTE
* The following three strings of the form ". -- ..." are help
* messages for single character commands. Do not translate the
* character before the --.
*/
return (rv);
}
return (rv);
}
return (rv);
}
/*
* TRANSLATION_NOTE
* In the following string, "id" is a short mnemonic for
* "identifier" and both occurrences should be translated.
*/
" or domain {name}");
return (rv);
}
return (VNTSD_SUCCESS);
}
/* cons_by_name() - find a console structure according to a ldom's name */
static boolean_t
{
return (B_FALSE);
}
}
/* name_to_cons_no - convert a ldom's name to its consno */
static int
{
return (-1);
}
}
/* select a console to connect */
static int
vntsd_client_t *clientp, char c)
{
int n;
int i;
int rv;
/* no console in this group */
return (VNTSD_STATUS_NO_CONS);
}
/* c{id} or n{name} */
n = VNTSD_LINE_LEN;
return (rv);
}
/* parse command */
for (i = 0; i < n; i++) {
switch (c) {
case 'c':
/* c{id} or c {id} */
continue;
}
return (VNTSD_ERR_INVALID_INPUT);
}
break;
case 'n':
/* n{name) or n {name} */
continue;
}
buf[n-1] = 0;
break;
default:
/* should never get here */
return (VNTSD_ERR_INVALID_INPUT);
}
/* got user selection */
break;
}
if (cons_no < 0) {
return (VNTSD_ERR_INVALID_INPUT);
}
/* get selected console */
/* during console selection, the console has been deleted */
return (VNTSD_ERR_INVALID_INPUT);
}
return (VNTSD_ERR_INVALID_INPUT);
}
return (VNTSD_SUCCESS);
}
/* compare if there is a match console in the gorup */
static boolean_t
{
if (consp_in_group == consp) {
return (B_TRUE);
} else {
return (B_FALSE);
}
}
/* connect a client to a console */
static int
{
/* check if console is valid */
return (VNTSD_STATUS_NO_CONS);
}
return (VNTSD_STATUS_NO_CONS);
}
/* enable daemon cmd */
/*
* the first connection to a console - a writer
* and the console has not opened.
*/
return (vntsd_vcc_err(consp));
}
}
/*
* move the client from group's no console selected queue
* to cons queue
*/
if (rv != VNTSD_SUCCESS) {
/* writer */
}
return (rv);
}
/* create a write thread */
if (rv != VNTSD_SUCCESS) {
return (rv);
}
}
/* write connecting message */
return (rv);
}
/* process input from client */
/* client disconnected from the console */
/* remove client from console queue */
/* append client to group's no console selected queue */
/* clean up console since there is no client connected to it */
/* force write thread to exit */
}
/* console is waiting for client to disconnect */
}
}
/* read command line input */
static int
{
int rv;
/* disable daemon special command */
!= VNTSD_SUCCESS) {
return (rv);
}
!= VNTSD_SUCCESS) {
return (rv);
}
return (rv);
}
return (VNTSD_SUCCESS);
}
return (rv);
}
/* reset client for selecting a console in the group */
static void
{
}
/* is there any connection to a given console? */
static boolean_t
{
has_client = B_TRUE;
return (has_client);
}
/*
* close one opened console.
* This function is passed to vntsd_que_walk to close one console.
* The function returns B_FALSE so that vntsd_que_walk will
* continue to apply the function to all consoles in the group.
*/
static boolean_t
{
}
return (B_FALSE);
}
/* clean up client and exit the thread */
static void
{
/* disconnct client from tcp port */
/*
* close all consoles in the group if the client is the
* last one connected to the group
*/
}
/*
* group is waiting to be deleted. - signal the group's
* listen thread - the VNTSD_GROUP_SIG_WAIT state will
* be cleared when the listen thread exits.
*/
}
thr_exit(0);
}
/* check client's status. exit if client quits or fatal errors */
static void
{
"client status=%x num consoles=%d \n",
/*
* obtain group lock to protect groupp->num_cons.
* When groupp->num_cons == 0, close client and exit the tread.
*/
/* no more console in the group */
return;
}
if (status == VNTSD_STATUS_INTR) {
/* reason for signal? */
}
switch (status) {
case VNTSD_STATUS_CLIENT_QUIT:
return;
/*
* domain was deleted before client connects to it
* connect to other console in the same group
*/
return;
}
/* no other selection available */
} else {
}
return;
case VNTSD_STATUS_VCC_IO_ERR:
/* check if console was deleted */
}
if (status != VNTSD_STATUS_CONTINUE) {
/* console was deleted */
return;
}
}
/* console is ok */
return;
/* same console */
return;
}
/* get selected console */
return;
case VNTSD_SUCCESS:
case VNTSD_STATUS_CONTINUE:
return;
case VNTSD_STATUS_NO_CONS:
/*
* there are two cases when the status is VNTSD_SATATUS_NO_CONS.
* case 1. the console was removed but there is at least one
* another console in the group that client can connect to.
* case 2. there is no console in the group. Client needs to
* be disconnected from vntsd.
*/
} else {
}
return;
case VNTSD_ERR_INVALID_INPUT:
return;
default:
/* fatal error */
return;
}
}
/* console thread */
void *
{
char cmd;
int num_cons;
/* free argp, which was allocated in listen thread */
/* check if group is removed */
/* host name */
}
"%s-vnts-%s: h, l, c{id}, n{name}, q:",
/* long prompt doesn't fit, use short one */
"vnts: h, l, c{id}, n{name}, q:");
}
for (;;) {
cmd = ' ';
/* console to connect to */
/* check error and may exit */
/* any console is removed from group? */
if (num_cons <= 1) {
cmd = ' ';
}
}
switch (cmd) {
case 'l':
/* list domain names */
break;
case 'q':
break;
case ' ':
if (num_cons == 0) {
/* no console in the group */
break;
}
if (num_cons == 1) {
/* by pass selecting console */
consp = (vntsd_cons_t *)
} else {
continue;
}
} else {
}
/* connect to console */
break;
case 'c':
case 'n':
/* select console */
if (rv == VNTSD_ERR_INVALID_INPUT) {
break;
}
/*
* all consoles in the group
* may be gone before this client
* could select one.
*/
if (rv != VNTSD_SUCCESS)
break;
} else {
}
/* connect to console */
"connect_cons returns %d\n",
break;
case 'h':
default:
break;
}
/* check error and may exit */
}
/*NOTREACHED*/
return (NULL);
}