1*1991Sheppo /* 2*1991Sheppo * CDDL HEADER START 3*1991Sheppo * 4*1991Sheppo * The contents of this file are subject to the terms of the 5*1991Sheppo * Common Development and Distribution License (the "License"). 6*1991Sheppo * You may not use this file except in compliance with the License. 7*1991Sheppo * 8*1991Sheppo * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*1991Sheppo * or http://www.opensolaris.org/os/licensing. 10*1991Sheppo * See the License for the specific language governing permissions 11*1991Sheppo * and limitations under the License. 12*1991Sheppo * 13*1991Sheppo * When distributing Covered Code, include this CDDL HEADER in each 14*1991Sheppo * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*1991Sheppo * If applicable, add the following below this CDDL HEADER, with the 16*1991Sheppo * fields enclosed by brackets "[]" replaced with your own identifying 17*1991Sheppo * information: Portions Copyright [yyyy] [name of copyright owner] 18*1991Sheppo * 19*1991Sheppo * CDDL HEADER END 20*1991Sheppo */ 21*1991Sheppo /* 22*1991Sheppo * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23*1991Sheppo * Use is subject to license terms. 24*1991Sheppo */ 25*1991Sheppo #pragma ident "%Z%%M% %I% %E% SMI" 26*1991Sheppo 27*1991Sheppo /* 28*1991Sheppo * Listen thread creates a console thread whenever there is a tcp client 29*1991Sheppo * made a conection to its port. In the console thread, if there are 30*1991Sheppo * multiple consoles in the group, client will be asked for a console selection. 31*1991Sheppo * a write thread for a console is created when first client connects to a 32*1991Sheppo * selected console and console thread becomes read thread for the client. 33*1991Sheppo */ 34*1991Sheppo 35*1991Sheppo #include <stdio.h> 36*1991Sheppo #include <stdlib.h> 37*1991Sheppo #include <string.h> 38*1991Sheppo #include <unistd.h> 39*1991Sheppo #include <sys/types.h> 40*1991Sheppo #include <sys/socket.h> 41*1991Sheppo #include <netinet/in.h> 42*1991Sheppo #include <thread.h> 43*1991Sheppo #include <synch.h> 44*1991Sheppo #include <signal.h> 45*1991Sheppo #include <assert.h> 46*1991Sheppo #include <ctype.h> 47*1991Sheppo #include <syslog.h> 48*1991Sheppo #include <libintl.h> 49*1991Sheppo #include <netdb.h> 50*1991Sheppo #include "vntsd.h" 51*1991Sheppo #include "chars.h" 52*1991Sheppo 53*1991Sheppo /* display domain names in the group */ 54*1991Sheppo static boolean_t 55*1991Sheppo display_domain_name(vntsd_cons_t *consp, int *fd) 56*1991Sheppo { 57*1991Sheppo char buf[VNTSD_LINE_LEN]; 58*1991Sheppo char *status; 59*1991Sheppo 60*1991Sheppo 61*1991Sheppo if (consp->clientpq != NULL) { 62*1991Sheppo status = gettext("connected"); 63*1991Sheppo } else if (consp->status & VNTSD_CONS_DELETED) { 64*1991Sheppo status = gettext("removing..."); 65*1991Sheppo } else { 66*1991Sheppo status = gettext("online"); 67*1991Sheppo } 68*1991Sheppo 69*1991Sheppo (void) snprintf(buf, sizeof (buf), "%-20d%-30s%-25s%s", 70*1991Sheppo consp->cons_no, consp->domain_name, status, vntsd_eol); 71*1991Sheppo 72*1991Sheppo return (vntsd_write_fd(*fd, buf, strlen(buf)) != VNTSD_SUCCESS); 73*1991Sheppo } 74*1991Sheppo 75*1991Sheppo /* output connected message to tcp client */ 76*1991Sheppo static int 77*1991Sheppo write_connect_msg(vntsd_client_t *clientp, char *group_name, 78*1991Sheppo char *domain_name) 79*1991Sheppo { 80*1991Sheppo 81*1991Sheppo int rv = VNTSD_SUCCESS; 82*1991Sheppo char buf[VNTSD_LINE_LEN]; 83*1991Sheppo 84*1991Sheppo if ((rv = vntsd_write_client(clientp, vntsd_eol, VNTSD_EOL_LEN)) != 85*1991Sheppo VNTSD_SUCCESS) { 86*1991Sheppo return (rv); 87*1991Sheppo } 88*1991Sheppo 89*1991Sheppo (void) snprintf(buf, sizeof (buf), 90*1991Sheppo gettext("Connecting to console \"%s\" in group \"%s\" ...."), 91*1991Sheppo domain_name, group_name); 92*1991Sheppo 93*1991Sheppo if ((rv = vntsd_write_line(clientp, buf)) != VNTSD_SUCCESS) { 94*1991Sheppo return (rv); 95*1991Sheppo } 96*1991Sheppo 97*1991Sheppo if ((rv = vntsd_write_line(clientp, 98*1991Sheppo gettext("Press ~? for control options .."))) != 99*1991Sheppo VNTSD_SUCCESS) { 100*1991Sheppo return (rv); 101*1991Sheppo } 102*1991Sheppo 103*1991Sheppo return (VNTSD_SUCCESS); 104*1991Sheppo } 105*1991Sheppo 106*1991Sheppo static int 107*1991Sheppo create_write_thread(vntsd_cons_t *consp) 108*1991Sheppo { 109*1991Sheppo 110*1991Sheppo assert(consp); 111*1991Sheppo 112*1991Sheppo /* create write thread for the console */ 113*1991Sheppo (void) mutex_lock(&consp->lock); 114*1991Sheppo if (thr_create(NULL, 0, (thr_func_t)vntsd_write_thread, 115*1991Sheppo (void *)consp, NULL, &consp->wr_tid)) { 116*1991Sheppo 117*1991Sheppo DERR(stderr, "t@%d create_rd_wr_thread@%d: " 118*1991Sheppo "create write thread failed\n", 119*1991Sheppo thr_self(), consp->cons_no); 120*1991Sheppo (void) close(consp->vcc_fd); 121*1991Sheppo consp->vcc_fd = -1; 122*1991Sheppo (void) mutex_unlock(&consp->lock); 123*1991Sheppo 124*1991Sheppo return (VNTSD_ERR_CREATE_WR_THR); 125*1991Sheppo } 126*1991Sheppo (void) mutex_unlock(&consp->lock); 127*1991Sheppo return (VNTSD_SUCCESS); 128*1991Sheppo } 129*1991Sheppo 130*1991Sheppo /* Display all domain consoles in a group. */ 131*1991Sheppo static int 132*1991Sheppo list_all_domains(vntsd_group_t *groupp, vntsd_client_t *clientp) 133*1991Sheppo { 134*1991Sheppo char vntsd_line[VNTSD_LINE_LEN]; 135*1991Sheppo int rv = VNTSD_SUCCESS; 136*1991Sheppo 137*1991Sheppo if ((rv = vntsd_write_client(clientp, vntsd_eol, VNTSD_EOL_LEN)) 138*1991Sheppo != VNTSD_SUCCESS) { 139*1991Sheppo return (rv); 140*1991Sheppo } 141*1991Sheppo 142*1991Sheppo /* 143*1991Sheppo * TRANSLATION_NOTE 144*1991Sheppo * The following three strings of the form "DOMAIN .." are table 145*1991Sheppo * headers and should be all uppercase. 146*1991Sheppo */ 147*1991Sheppo (void) snprintf(vntsd_line, sizeof (vntsd_line), 148*1991Sheppo "%-20s%-30s%-25s", 149*1991Sheppo gettext("DOMAIN ID"), gettext("DOMAIN NAME"), 150*1991Sheppo gettext("DOMAIN STATE")); 151*1991Sheppo 152*1991Sheppo if ((rv = vntsd_write_line(clientp, vntsd_line)) != VNTSD_SUCCESS) { 153*1991Sheppo return (rv); 154*1991Sheppo } 155*1991Sheppo 156*1991Sheppo (void) mutex_lock(&groupp->lock); 157*1991Sheppo 158*1991Sheppo if (vntsd_que_find(groupp->conspq, (compare_func_t)display_domain_name, 159*1991Sheppo &(clientp->sockfd)) != NULL) { 160*1991Sheppo rv = VNTSD_ERR_WRITE_CLIENT; 161*1991Sheppo } 162*1991Sheppo 163*1991Sheppo (void) mutex_unlock(&groupp->lock); 164*1991Sheppo 165*1991Sheppo return (rv); 166*1991Sheppo } 167*1991Sheppo 168*1991Sheppo /* display help */ 169*1991Sheppo static int 170*1991Sheppo display_help(vntsd_client_t *clientp) 171*1991Sheppo { 172*1991Sheppo int rv = VNTSD_SUCCESS; 173*1991Sheppo char *bufp; 174*1991Sheppo 175*1991Sheppo if ((rv = vntsd_write_client(clientp, vntsd_eol, VNTSD_EOL_LEN)) 176*1991Sheppo != VNTSD_SUCCESS) { 177*1991Sheppo return (rv); 178*1991Sheppo } 179*1991Sheppo 180*1991Sheppo /* 181*1991Sheppo * TRANSLATION_NOTE 182*1991Sheppo * The following three strings of the form ". -- ..." are help 183*1991Sheppo * messages for single character commands. Do not translate the 184*1991Sheppo * character before the --. 185*1991Sheppo */ 186*1991Sheppo bufp = gettext("h -- this help)"); 187*1991Sheppo 188*1991Sheppo if ((rv = vntsd_write_line(clientp, bufp)) != VNTSD_SUCCESS) { 189*1991Sheppo return (rv); 190*1991Sheppo } 191*1991Sheppo 192*1991Sheppo bufp = gettext("l -- list of consoles"); 193*1991Sheppo 194*1991Sheppo if ((rv = vntsd_write_line(clientp, bufp)) != VNTSD_SUCCESS) { 195*1991Sheppo return (rv); 196*1991Sheppo } 197*1991Sheppo 198*1991Sheppo bufp = gettext("q -- quit"); 199*1991Sheppo 200*1991Sheppo if ((rv = vntsd_write_line(clientp, bufp)) != VNTSD_SUCCESS) { 201*1991Sheppo return (rv); 202*1991Sheppo } 203*1991Sheppo 204*1991Sheppo /* 205*1991Sheppo * TRANSLATION_NOTE 206*1991Sheppo * In the following string, "id" is a short mnemonic for 207*1991Sheppo * "identifier" and both occurrences should be translated. 208*1991Sheppo */ 209*1991Sheppo 210*1991Sheppo bufp = gettext("[c[c ]]{id} -- connect to console of domain {id}"); 211*1991Sheppo 212*1991Sheppo if ((rv = vntsd_write_line(clientp, bufp)) != VNTSD_SUCCESS) { 213*1991Sheppo return (rv); 214*1991Sheppo } 215*1991Sheppo 216*1991Sheppo return (VNTSD_SUCCESS); 217*1991Sheppo } 218*1991Sheppo 219*1991Sheppo /* select a console to connect */ 220*1991Sheppo static int 221*1991Sheppo select_cons(vntsd_group_t *groupp, int num_cons, vntsd_cons_t **consp, 222*1991Sheppo vntsd_client_t *clientp, char c) 223*1991Sheppo { 224*1991Sheppo int cons_no = -2; 225*1991Sheppo int n; 226*1991Sheppo int i; 227*1991Sheppo char buf[VNTSD_LINE_LEN]; 228*1991Sheppo int rv; 229*1991Sheppo 230*1991Sheppo 231*1991Sheppo 232*1991Sheppo (void) mutex_lock(&groupp->lock); 233*1991Sheppo if (groupp->num_cons == 0) { 234*1991Sheppo (void) mutex_unlock(&groupp->lock); 235*1991Sheppo /* no console in this group */ 236*1991Sheppo return (VNTSD_STATUS_NO_CONS); 237*1991Sheppo } 238*1991Sheppo (void) mutex_unlock(&groupp->lock); 239*1991Sheppo 240*1991Sheppo if (num_cons == 1) { 241*1991Sheppo /* by pass selecting console */ 242*1991Sheppo *consp = (vntsd_cons_t *)(groupp->conspq->handle); 243*1991Sheppo return (VNTSD_SUCCESS); 244*1991Sheppo } 245*1991Sheppo 246*1991Sheppo 247*1991Sheppo if (isdigit(c)) { 248*1991Sheppo /* {id} input */ 249*1991Sheppo cons_no = c - '0'; 250*1991Sheppo } else if (c == 'c') { 251*1991Sheppo /* c{id} or c {id} input */ 252*1991Sheppo cons_no = -1; 253*1991Sheppo } else if (!isspace(c)) { 254*1991Sheppo return (VNTSD_ERR_INVALID_INPUT); 255*1991Sheppo } 256*1991Sheppo 257*1991Sheppo /* get client selections */ 258*1991Sheppo n = VNTSD_LINE_LEN; 259*1991Sheppo 260*1991Sheppo if ((rv = vntsd_read_line(clientp, buf, &n)) != VNTSD_SUCCESS) { 261*1991Sheppo return (rv); 262*1991Sheppo } 263*1991Sheppo 264*1991Sheppo /* parse command */ 265*1991Sheppo for (i = 0; i < n; i++) { 266*1991Sheppo if (cons_no == -1) { 267*1991Sheppo /* c{id} */ 268*1991Sheppo cons_no = atoi(buf + i); 269*1991Sheppo break; 270*1991Sheppo } 271*1991Sheppo 272*1991Sheppo if (isspace(buf[i]) && cons_no == -2) { 273*1991Sheppo /* skip space */ 274*1991Sheppo continue; 275*1991Sheppo } 276*1991Sheppo 277*1991Sheppo if (buf[i] == 'c') { 278*1991Sheppo /* c{id} or c {id} */ 279*1991Sheppo cons_no = -1; 280*1991Sheppo } else if (buf[i] == CR) { 281*1991Sheppo break; 282*1991Sheppo } else { 283*1991Sheppo return (VNTSD_ERR_INVALID_INPUT); 284*1991Sheppo } 285*1991Sheppo } 286*1991Sheppo 287*1991Sheppo if (cons_no < 0) { 288*1991Sheppo return (VNTSD_ERR_INVALID_INPUT); 289*1991Sheppo } 290*1991Sheppo 291*1991Sheppo /* get selected console */ 292*1991Sheppo (void) mutex_lock(&groupp->lock); 293*1991Sheppo 294*1991Sheppo *consp = (vntsd_cons_t *)vntsd_que_find(groupp->conspq, 295*1991Sheppo (compare_func_t)vntsd_cons_by_consno, &cons_no); 296*1991Sheppo 297*1991Sheppo if (*consp == NULL) { 298*1991Sheppo /* during console selection, the console has been deleted */ 299*1991Sheppo (void) mutex_unlock(&groupp->lock); 300*1991Sheppo 301*1991Sheppo return (VNTSD_ERR_INVALID_INPUT); 302*1991Sheppo } 303*1991Sheppo if ((*consp)->status & VNTSD_CONS_DELETED) { 304*1991Sheppo return (VNTSD_ERR_INVALID_INPUT); 305*1991Sheppo } 306*1991Sheppo 307*1991Sheppo (void) mutex_unlock(&groupp->lock); 308*1991Sheppo 309*1991Sheppo return (VNTSD_SUCCESS); 310*1991Sheppo } 311*1991Sheppo 312*1991Sheppo /* compare if there is a match console in the gorup */ 313*1991Sheppo static boolean_t 314*1991Sheppo find_cons_in_group(vntsd_cons_t *consp_in_group, vntsd_cons_t *consp) 315*1991Sheppo { 316*1991Sheppo if (consp_in_group == consp) { 317*1991Sheppo return (B_TRUE); 318*1991Sheppo } else { 319*1991Sheppo return (B_FALSE); 320*1991Sheppo } 321*1991Sheppo } 322*1991Sheppo 323*1991Sheppo /* connect a client to a console */ 324*1991Sheppo static int 325*1991Sheppo connect_cons(vntsd_cons_t *consp, vntsd_client_t *clientp) 326*1991Sheppo { 327*1991Sheppo int rv, rv1; 328*1991Sheppo vntsd_group_t *groupp; 329*1991Sheppo 330*1991Sheppo assert(consp); 331*1991Sheppo groupp = consp->group; 332*1991Sheppo assert(groupp); 333*1991Sheppo assert(clientp); 334*1991Sheppo 335*1991Sheppo (void) mutex_lock(&groupp->lock); 336*1991Sheppo 337*1991Sheppo /* check if console is valid */ 338*1991Sheppo consp = vntsd_que_find(groupp->conspq, 339*1991Sheppo (compare_func_t)find_cons_in_group, consp); 340*1991Sheppo 341*1991Sheppo if (consp == NULL) { 342*1991Sheppo (void) mutex_unlock(&groupp->lock); 343*1991Sheppo return (VNTSD_STATUS_NO_CONS); 344*1991Sheppo } 345*1991Sheppo if (consp->status & VNTSD_CONS_DELETED) { 346*1991Sheppo (void) mutex_unlock(&groupp->lock); 347*1991Sheppo return (VNTSD_STATUS_NO_CONS); 348*1991Sheppo } 349*1991Sheppo 350*1991Sheppo (void) mutex_lock(&consp->lock); 351*1991Sheppo (void) mutex_lock(&clientp->lock); 352*1991Sheppo 353*1991Sheppo 354*1991Sheppo clientp->cons = consp; 355*1991Sheppo 356*1991Sheppo /* enable daemon cmd */ 357*1991Sheppo clientp->status &= ~VNTSD_CLIENT_DISABLE_DAEMON_CMD; 358*1991Sheppo 359*1991Sheppo if (consp->clientpq == NULL) { 360*1991Sheppo /* first connect to console - a writer */ 361*1991Sheppo assert(consp->vcc_fd == -1); 362*1991Sheppo /* open vcc */ 363*1991Sheppo consp->vcc_fd = vntsd_open_vcc(consp->dev_name, consp->cons_no); 364*1991Sheppo if (consp->vcc_fd < 0) { 365*1991Sheppo (void) mutex_unlock(&clientp->lock); 366*1991Sheppo (void) mutex_unlock(&consp->lock); 367*1991Sheppo (void) mutex_unlock(&groupp->lock); 368*1991Sheppo assert(consp->group); 369*1991Sheppo return (vntsd_vcc_err(consp)); 370*1991Sheppo } 371*1991Sheppo } 372*1991Sheppo 373*1991Sheppo (void) mutex_unlock(&clientp->lock); 374*1991Sheppo 375*1991Sheppo /* 376*1991Sheppo * move the client from group's no console selected queue 377*1991Sheppo * to cons queue 378*1991Sheppo */ 379*1991Sheppo 380*1991Sheppo rv = vntsd_que_rm(&groupp->no_cons_clientpq, clientp); 381*1991Sheppo assert(rv == VNTSD_SUCCESS); 382*1991Sheppo 383*1991Sheppo rv = vntsd_que_append(&consp->clientpq, clientp); 384*1991Sheppo (void) mutex_unlock(&groupp->lock); 385*1991Sheppo 386*1991Sheppo if (rv != VNTSD_SUCCESS) { 387*1991Sheppo if (consp->clientpq->handle == clientp) { 388*1991Sheppo /* writer */ 389*1991Sheppo (void) close(consp->vcc_fd); 390*1991Sheppo consp->vcc_fd = -1; 391*1991Sheppo } 392*1991Sheppo 393*1991Sheppo (void) mutex_unlock(&consp->lock); 394*1991Sheppo return (rv); 395*1991Sheppo } 396*1991Sheppo 397*1991Sheppo (void) mutex_unlock(&consp->lock); 398*1991Sheppo 399*1991Sheppo if (consp->clientpq->handle == clientp) { 400*1991Sheppo /* create a write thread */ 401*1991Sheppo rv = create_write_thread(consp); 402*1991Sheppo if (rv != VNTSD_SUCCESS) { 403*1991Sheppo return (rv); 404*1991Sheppo } 405*1991Sheppo } 406*1991Sheppo 407*1991Sheppo /* write connecting message */ 408*1991Sheppo if ((rv = write_connect_msg(clientp, consp->group->group_name, 409*1991Sheppo consp->domain_name)) != VNTSD_SUCCESS) { 410*1991Sheppo return (rv); 411*1991Sheppo } 412*1991Sheppo 413*1991Sheppo /* process input from client */ 414*1991Sheppo rv = vntsd_read(clientp); 415*1991Sheppo 416*1991Sheppo /* client disconnected from the console */ 417*1991Sheppo (void) mutex_lock(&groupp->lock); 418*1991Sheppo 419*1991Sheppo /* remove client from console queue */ 420*1991Sheppo (void) mutex_lock(&consp->lock); 421*1991Sheppo rv1 = vntsd_que_rm(&consp->clientpq, clientp); 422*1991Sheppo assert(rv1 == VNTSD_SUCCESS); 423*1991Sheppo 424*1991Sheppo /* append client to group's no console selected queue */ 425*1991Sheppo rv1 = vntsd_que_append(&groupp->no_cons_clientpq, clientp); 426*1991Sheppo (void) mutex_unlock(&groupp->lock); 427*1991Sheppo 428*1991Sheppo if (consp->clientpq == NULL) { 429*1991Sheppo /* clean up console since there is no client connected to it */ 430*1991Sheppo assert(consp->vcc_fd != -1); 431*1991Sheppo 432*1991Sheppo /* close vcc port */ 433*1991Sheppo (void) close(consp->vcc_fd); 434*1991Sheppo consp->vcc_fd = -1; 435*1991Sheppo 436*1991Sheppo /* force write thread to exit */ 437*1991Sheppo assert(consp->wr_tid != (thread_t)-1); 438*1991Sheppo (void) thr_kill(consp->wr_tid, SIGUSR1); 439*1991Sheppo (void) mutex_unlock(&consp->lock); 440*1991Sheppo (void) thr_join(consp->wr_tid, NULL, NULL); 441*1991Sheppo (void) mutex_lock(&consp->lock); 442*1991Sheppo } 443*1991Sheppo 444*1991Sheppo if (consp->status & VNTSD_CONS_SIG_WAIT) { 445*1991Sheppo /* console is waiting for client to disconnect */ 446*1991Sheppo (void) cond_signal(&consp->cvp); 447*1991Sheppo } 448*1991Sheppo 449*1991Sheppo (void) mutex_unlock(&consp->lock); 450*1991Sheppo 451*1991Sheppo return (rv1 == VNTSD_SUCCESS ? rv : rv1); 452*1991Sheppo 453*1991Sheppo } 454*1991Sheppo 455*1991Sheppo /* read command line input */ 456*1991Sheppo static int 457*1991Sheppo read_cmd(vntsd_client_t *clientp, char *prompt, char *cmd) 458*1991Sheppo { 459*1991Sheppo int rv; 460*1991Sheppo 461*1991Sheppo /* disable daemon special command */ 462*1991Sheppo (void) mutex_lock(&clientp->lock); 463*1991Sheppo clientp->status |= VNTSD_CLIENT_DISABLE_DAEMON_CMD; 464*1991Sheppo (void) mutex_unlock(&clientp->lock); 465*1991Sheppo 466*1991Sheppo if ((rv = vntsd_write_client(clientp, vntsd_eol, VNTSD_EOL_LEN)) 467*1991Sheppo != VNTSD_SUCCESS) { 468*1991Sheppo return (rv); 469*1991Sheppo } 470*1991Sheppo 471*1991Sheppo if ((rv = vntsd_write_client(clientp, prompt, strlen(prompt))) 472*1991Sheppo != VNTSD_SUCCESS) { 473*1991Sheppo return (rv); 474*1991Sheppo } 475*1991Sheppo 476*1991Sheppo if ((rv = vntsd_read_data(clientp, cmd)) != VNTSD_SUCCESS) { 477*1991Sheppo return (rv); 478*1991Sheppo } 479*1991Sheppo if (*cmd == BS) { 480*1991Sheppo return (VNTSD_SUCCESS); 481*1991Sheppo } 482*1991Sheppo 483*1991Sheppo rv = vntsd_write_client(clientp, cmd, 1); 484*1991Sheppo 485*1991Sheppo *cmd = tolower(*cmd); 486*1991Sheppo 487*1991Sheppo return (rv); 488*1991Sheppo } 489*1991Sheppo 490*1991Sheppo /* reset client for selecting a console in the group */ 491*1991Sheppo static void 492*1991Sheppo client_init(vntsd_client_t *clientp) 493*1991Sheppo { 494*1991Sheppo (void) mutex_lock(&clientp->lock); 495*1991Sheppo clientp->cons = NULL; 496*1991Sheppo clientp->status = 0; 497*1991Sheppo (void) mutex_unlock(&clientp->lock); 498*1991Sheppo } 499*1991Sheppo 500*1991Sheppo /* clean up client and exit the thread */ 501*1991Sheppo static void 502*1991Sheppo client_fini(vntsd_group_t *groupp, vntsd_client_t *clientp) 503*1991Sheppo { 504*1991Sheppo 505*1991Sheppo assert(groupp); 506*1991Sheppo assert(clientp); 507*1991Sheppo 508*1991Sheppo /* disconnct client from tcp port */ 509*1991Sheppo assert(clientp->sockfd != -1); 510*1991Sheppo (void) close(clientp->sockfd); 511*1991Sheppo 512*1991Sheppo (void) mutex_lock(&groupp->lock); 513*1991Sheppo (void) vntsd_que_rm(&groupp->no_cons_clientpq, clientp); 514*1991Sheppo 515*1991Sheppo if ((groupp->no_cons_clientpq == NULL) && 516*1991Sheppo (groupp->status & VNTSD_GROUP_SIG_WAIT)) { 517*1991Sheppo /* group is waiting to be deleted */ 518*1991Sheppo groupp->status &= ~VNTSD_GROUP_SIG_WAIT; 519*1991Sheppo (void) cond_signal(&groupp->cvp); 520*1991Sheppo } 521*1991Sheppo (void) mutex_unlock(&groupp->lock); 522*1991Sheppo 523*1991Sheppo (void) mutex_destroy(&clientp->lock); 524*1991Sheppo free(clientp); 525*1991Sheppo 526*1991Sheppo thr_exit(0); 527*1991Sheppo } 528*1991Sheppo 529*1991Sheppo /* check client's status. exit if client quits or fatal errors */ 530*1991Sheppo static void 531*1991Sheppo console_chk_status(vntsd_group_t *groupp, vntsd_client_t *clientp, int status) 532*1991Sheppo { 533*1991Sheppo char err_msg[VNTSD_LINE_LEN]; 534*1991Sheppo 535*1991Sheppo D1(stderr, "t@%d console_chk_status() status=%d " 536*1991Sheppo "client status=%x num consoles=%d \n", 537*1991Sheppo thr_self(), status, clientp->status, groupp->num_cons); 538*1991Sheppo 539*1991Sheppo (void) snprintf(err_msg, VNTSD_LINE_LEN, "console_chk_status client%d" 540*1991Sheppo " num_cos=%d", clientp->sockfd, groupp->num_cons); 541*1991Sheppo 542*1991Sheppo if (groupp->num_cons == 0) { 543*1991Sheppo /* no more console in the group */ 544*1991Sheppo client_fini(groupp, clientp); 545*1991Sheppo } 546*1991Sheppo 547*1991Sheppo if (status == VNTSD_STATUS_INTR) { 548*1991Sheppo /* reason for signal? */ 549*1991Sheppo status = vntsd_cons_chk_intr(clientp); 550*1991Sheppo } 551*1991Sheppo 552*1991Sheppo switch (status) { 553*1991Sheppo 554*1991Sheppo case VNTSD_STATUS_CLIENT_QUIT: 555*1991Sheppo client_fini(groupp, clientp); 556*1991Sheppo return; 557*1991Sheppo 558*1991Sheppo case VNTSD_STATUS_RESELECT_CONS: 559*1991Sheppo assert(clientp->cons); 560*1991Sheppo if ((groupp->num_cons == 1) && 561*1991Sheppo (groupp->conspq->handle == clientp->cons)) { 562*1991Sheppo /* no other selection available */ 563*1991Sheppo client_fini(groupp, clientp); 564*1991Sheppo } else { 565*1991Sheppo client_init(clientp); 566*1991Sheppo } 567*1991Sheppo return; 568*1991Sheppo 569*1991Sheppo case VNTSD_STATUS_VCC_IO_ERR: 570*1991Sheppo if ((clientp->status & VNTSD_CLIENT_CONS_DELETED) == 0) { 571*1991Sheppo /* check if console was deleted */ 572*1991Sheppo status = vntsd_vcc_err(clientp->cons); 573*1991Sheppo } 574*1991Sheppo 575*1991Sheppo if (status != VNTSD_STATUS_CONTINUE) { 576*1991Sheppo /* console was deleted */ 577*1991Sheppo if (groupp->num_cons == 1) { 578*1991Sheppo client_fini(groupp, clientp); 579*1991Sheppo } 580*1991Sheppo } 581*1991Sheppo 582*1991Sheppo /* console is ok */ 583*1991Sheppo client_init(clientp); 584*1991Sheppo return; 585*1991Sheppo 586*1991Sheppo case VNTSD_STATUS_MOV_CONS_FORWARD: 587*1991Sheppo case VNTSD_STATUS_MOV_CONS_BACKWARD: 588*1991Sheppo if (groupp->num_cons == 1) { 589*1991Sheppo /* same console */ 590*1991Sheppo return; 591*1991Sheppo } 592*1991Sheppo 593*1991Sheppo /* get selected console */ 594*1991Sheppo (void) mutex_lock(&(clientp->cons->group->lock)); 595*1991Sheppo clientp->cons = vntsd_que_pos(clientp->cons->group->conspq, 596*1991Sheppo clientp->cons, 597*1991Sheppo (status == VNTSD_STATUS_MOV_CONS_FORWARD)?(1):(-1)); 598*1991Sheppo (void) mutex_unlock(&(clientp->cons->group->lock)); 599*1991Sheppo return; 600*1991Sheppo 601*1991Sheppo case VNTSD_SUCCESS: 602*1991Sheppo case VNTSD_STATUS_CONTINUE: 603*1991Sheppo case VNTSD_STATUS_NO_CONS: 604*1991Sheppo client_init(clientp); 605*1991Sheppo return; 606*1991Sheppo 607*1991Sheppo case VNTSD_ERR_INVALID_INPUT: 608*1991Sheppo return; 609*1991Sheppo 610*1991Sheppo default: 611*1991Sheppo /* fatal error */ 612*1991Sheppo vntsd_log(status, err_msg); 613*1991Sheppo client_fini(groupp, clientp); 614*1991Sheppo return; 615*1991Sheppo } 616*1991Sheppo } 617*1991Sheppo 618*1991Sheppo /* console thread */ 619*1991Sheppo void * 620*1991Sheppo vntsd_console_thread(vntsd_thr_arg_t *argp) 621*1991Sheppo { 622*1991Sheppo vntsd_group_t *groupp; 623*1991Sheppo vntsd_cons_t *consp; 624*1991Sheppo vntsd_client_t *clientp; 625*1991Sheppo 626*1991Sheppo char buf[MAXHOSTNAMELEN]; 627*1991Sheppo char prompt[72]; 628*1991Sheppo char cmd; 629*1991Sheppo int rv = VNTSD_SUCCESS; 630*1991Sheppo int num_cons; 631*1991Sheppo 632*1991Sheppo 633*1991Sheppo groupp = (vntsd_group_t *)argp->handle; 634*1991Sheppo clientp = (vntsd_client_t *)argp->arg; 635*1991Sheppo 636*1991Sheppo assert(groupp); 637*1991Sheppo assert(clientp); 638*1991Sheppo 639*1991Sheppo /* check if group is removed */ 640*1991Sheppo 641*1991Sheppo D1(stderr, "t@%d get_client_sel@%lld:client@%d\n", thr_self(), 642*1991Sheppo groupp->tcp_port, clientp->sockfd); 643*1991Sheppo 644*1991Sheppo bzero(buf, MAXHOSTNAMELEN); 645*1991Sheppo 646*1991Sheppo /* host name */ 647*1991Sheppo if (gethostname(buf, MAXHOSTNAMELEN)) { 648*1991Sheppo vntsd_log(VNTSD_STATUS_NO_HOST_NAME, "vntsd_console_thread()"); 649*1991Sheppo (void) snprintf(buf, sizeof (buf), "unkown host"); 650*1991Sheppo } 651*1991Sheppo 652*1991Sheppo if (snprintf(prompt, sizeof (prompt), 653*1991Sheppo "%s-vnts-%s: h,l,{id},c{id},c {id},q:", 654*1991Sheppo buf, groupp->group_name) >= sizeof (prompt)) { 655*1991Sheppo /* long prompt doesn't fit, use short one */ 656*1991Sheppo (void) snprintf(prompt, sizeof (prompt), 657*1991Sheppo "vnts: h,l,{id},c{id},c {id}, q:"); 658*1991Sheppo } 659*1991Sheppo 660*1991Sheppo 661*1991Sheppo for (;;) { 662*1991Sheppo cmd = ' '; 663*1991Sheppo D1(stderr, "t@%d console_thread()@%lld:client@%d\n", thr_self(), 664*1991Sheppo groupp->tcp_port, clientp->sockfd); 665*1991Sheppo 666*1991Sheppo num_cons = vntsd_chk_group_total_cons(groupp); 667*1991Sheppo 668*1991Sheppo if ((num_cons > 1) && (clientp->cons == NULL)) { 669*1991Sheppo /* console to connect to */ 670*1991Sheppo rv = read_cmd(clientp, prompt, &cmd); 671*1991Sheppo /* check error and may exit */ 672*1991Sheppo console_chk_status(groupp, clientp, rv); 673*1991Sheppo } 674*1991Sheppo 675*1991Sheppo switch (cmd) { 676*1991Sheppo 677*1991Sheppo case 'l': 678*1991Sheppo 679*1991Sheppo /* list domain names */ 680*1991Sheppo rv = list_all_domains(groupp, clientp); 681*1991Sheppo break; 682*1991Sheppo 683*1991Sheppo 684*1991Sheppo case 'q': 685*1991Sheppo 686*1991Sheppo rv = VNTSD_STATUS_CLIENT_QUIT; 687*1991Sheppo break; 688*1991Sheppo 689*1991Sheppo case 'h': 690*1991Sheppo rv = display_help(clientp); 691*1991Sheppo break; 692*1991Sheppo 693*1991Sheppo default: 694*1991Sheppo /* select console */ 695*1991Sheppo if (clientp->cons == NULL) { 696*1991Sheppo rv = select_cons(groupp, num_cons, 697*1991Sheppo &consp, clientp, cmd); 698*1991Sheppo if (rv == VNTSD_ERR_INVALID_INPUT) { 699*1991Sheppo rv = display_help(clientp); 700*1991Sheppo break; 701*1991Sheppo } 702*1991Sheppo } else { 703*1991Sheppo consp = clientp->cons; 704*1991Sheppo } 705*1991Sheppo assert(consp); 706*1991Sheppo 707*1991Sheppo /* connect to console */ 708*1991Sheppo rv = connect_cons(consp, clientp); 709*1991Sheppo D1(stderr, "t@%d console_thread()" 710*1991Sheppo "connect_cons returns %d\n", 711*1991Sheppo thr_self(), rv); 712*1991Sheppo break; 713*1991Sheppo 714*1991Sheppo } 715*1991Sheppo /* check error and may exit */ 716*1991Sheppo console_chk_status(groupp, clientp, rv); 717*1991Sheppo } 718*1991Sheppo 719*1991Sheppo /*NOTREACHED*/ 720*1991Sheppo return (NULL); 721*1991Sheppo } 722