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 22*1ae08745Sheppo /* 23*1ae08745Sheppo * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24*1ae08745Sheppo * Use is subject to license terms. 25*1ae08745Sheppo */ 26*1ae08745Sheppo 27*1ae08745Sheppo #pragma ident "%Z%%M% %I% %E% SMI" 28*1ae08745Sheppo 29*1ae08745Sheppo /* 30*1ae08745Sheppo * VNTSD main 31*1ae08745Sheppo * 32*1ae08745Sheppo * VNTSD takes the following options: 33*1ae08745Sheppo * -i <device instance> 34*1ae08745Sheppo * VCC device instance to use, e.g. virtual-console-concentrator@0. 35*1ae08745Sheppo * Required option. 36*1ae08745Sheppo * -p <ip address> 37*1ae08745Sheppo * IP address VNTSD listens to. 38*1ae08745Sheppo * -d 39*1ae08745Sheppo * Do not daemonize. This is only available in a DEBUG build. 40*1ae08745Sheppo * -t timeout for inactivity 0 = indefinite 41*1ae08745Sheppo */ 42*1ae08745Sheppo 43*1ae08745Sheppo #include <stdio.h> 44*1ae08745Sheppo #include <sys/types.h> 45*1ae08745Sheppo #include <stdlib.h> 46*1ae08745Sheppo #include <string.h> 47*1ae08745Sheppo #include <unistd.h> 48*1ae08745Sheppo #include <sys/socket.h> 49*1ae08745Sheppo #include <arpa/inet.h> 50*1ae08745Sheppo #include <time.h> 51*1ae08745Sheppo #include <netinet/in.h> 52*1ae08745Sheppo #include <thread.h> 53*1ae08745Sheppo #include <signal.h> 54*1ae08745Sheppo #include <fcntl.h> 55*1ae08745Sheppo #include <ctype.h> 56*1ae08745Sheppo #include <libintl.h> 57*1ae08745Sheppo #include <locale.h> 58*1ae08745Sheppo #include <syslog.h> 59*1ae08745Sheppo #include "vntsd.h" 60*1ae08745Sheppo #include "chars.h" 61*1ae08745Sheppo 62*1ae08745Sheppo #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 63*1ae08745Sheppo #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't. */ 64*1ae08745Sheppo #endif 65*1ae08745Sheppo 66*1ae08745Sheppo /* global variables */ 67*1ae08745Sheppo 68*1ae08745Sheppo #ifdef DEBUG 69*1ae08745Sheppo int vntsddbg = 0x8; 70*1ae08745Sheppo #endif 71*1ae08745Sheppo 72*1ae08745Sheppo #define MINUTE 60 73*1ae08745Sheppo 74*1ae08745Sheppo static vntsd_t *vntsdp; 75*1ae08745Sheppo 76*1ae08745Sheppo 77*1ae08745Sheppo static void vntsd_exit(void); 78*1ae08745Sheppo /* Signal handler for SIGINT, SIGKILL and SIGHUP */ 79*1ae08745Sheppo static void 80*1ae08745Sheppo exit_sig_handler(int sig) 81*1ae08745Sheppo { 82*1ae08745Sheppo 83*1ae08745Sheppo char err_msg[VNTSD_LINE_LEN]; 84*1ae08745Sheppo 85*1ae08745Sheppo D1(stderr, "t@%d exit_sig_handler%d \n", thr_self(), sig); 86*1ae08745Sheppo 87*1ae08745Sheppo (void) snprintf(err_msg, sizeof (err_msg), "exit_sig_handler() sig=%d", 88*1ae08745Sheppo sig); 89*1ae08745Sheppo 90*1ae08745Sheppo vntsd_log(VNTSD_STATUS_EXIT_SIG, err_msg); 91*1ae08745Sheppo 92*1ae08745Sheppo exit(0); 93*1ae08745Sheppo } 94*1ae08745Sheppo 95*1ae08745Sheppo /* 96*1ae08745Sheppo * Before a thread reads in client's input, it attaches to vntsd timer so that 97*1ae08745Sheppo * it can be waken up if a client does not access the connection for 98*1ae08745Sheppo * VNTSD_INPUT_TIMEOUT(10) minutes. 99*1ae08745Sheppo */ 100*1ae08745Sheppo 101*1ae08745Sheppo /* attach a thread to timer */ 102*1ae08745Sheppo int 103*1ae08745Sheppo vntsd_attach_timer(vntsd_timeout_t *tmop) 104*1ae08745Sheppo { 105*1ae08745Sheppo int rv; 106*1ae08745Sheppo 107*1ae08745Sheppo if (vntsdp->timeout == 0) { 108*1ae08745Sheppo return (VNTSD_SUCCESS); 109*1ae08745Sheppo } 110*1ae08745Sheppo 111*1ae08745Sheppo (void) mutex_lock(&vntsdp->tmo_lock); 112*1ae08745Sheppo rv = vntsd_que_append(&vntsdp->tmoq, (void *)tmop); 113*1ae08745Sheppo (void) mutex_unlock(&vntsdp->tmo_lock); 114*1ae08745Sheppo return (rv); 115*1ae08745Sheppo } 116*1ae08745Sheppo 117*1ae08745Sheppo /* detach a thread from timer */ 118*1ae08745Sheppo int 119*1ae08745Sheppo vntsd_detach_timer(vntsd_timeout_t *tmop) 120*1ae08745Sheppo { 121*1ae08745Sheppo int rv; 122*1ae08745Sheppo 123*1ae08745Sheppo if (vntsdp->timeout == 0) { 124*1ae08745Sheppo return (VNTSD_SUCCESS); 125*1ae08745Sheppo } 126*1ae08745Sheppo 127*1ae08745Sheppo (void) mutex_lock(&vntsdp->tmo_lock); 128*1ae08745Sheppo rv = vntsd_que_rm(&vntsdp->tmoq, (void *)tmop); 129*1ae08745Sheppo (void) mutex_unlock(&vntsdp->tmo_lock); 130*1ae08745Sheppo 131*1ae08745Sheppo return (rv); 132*1ae08745Sheppo } 133*1ae08745Sheppo 134*1ae08745Sheppo /* check threadd's timeout */ 135*1ae08745Sheppo static boolean_t 136*1ae08745Sheppo chk_timeout(vntsd_timeout_t *tmop) 137*1ae08745Sheppo { 138*1ae08745Sheppo tmop->minutes++; 139*1ae08745Sheppo 140*1ae08745Sheppo if (tmop->minutes == vntsdp->timeout) { 141*1ae08745Sheppo /* wake up the thread */ 142*1ae08745Sheppo tmop->clientp->status |= VNTSD_CLIENT_TIMEOUT; 143*1ae08745Sheppo (void) thr_kill(tmop->tid, SIGALRM); 144*1ae08745Sheppo } 145*1ae08745Sheppo 146*1ae08745Sheppo /* return false to walk the queue */ 147*1ae08745Sheppo return (B_FALSE); 148*1ae08745Sheppo } 149*1ae08745Sheppo 150*1ae08745Sheppo /* reset timer */ 151*1ae08745Sheppo static boolean_t 152*1ae08745Sheppo reset_timeout(vntsd_timeout_t *tmop, thread_t tid) 153*1ae08745Sheppo { 154*1ae08745Sheppo if (tmop->tid == tid) { 155*1ae08745Sheppo tmop->minutes = 0; 156*1ae08745Sheppo } 157*1ae08745Sheppo /* return false to walk the queue */ 158*1ae08745Sheppo return (B_FALSE); 159*1ae08745Sheppo } 160*1ae08745Sheppo 161*1ae08745Sheppo void 162*1ae08745Sheppo vntsd_reset_timer(thread_t tid) 163*1ae08745Sheppo { 164*1ae08745Sheppo if (vntsdp->timeout == 0) { 165*1ae08745Sheppo return; 166*1ae08745Sheppo } 167*1ae08745Sheppo 168*1ae08745Sheppo (void) mutex_lock(&vntsdp->tmo_lock); 169*1ae08745Sheppo (void) vntsd_que_find(vntsdp->tmoq, (compare_func_t)reset_timeout, 170*1ae08745Sheppo (void*)tid); 171*1ae08745Sheppo (void) mutex_unlock(&vntsdp->tmo_lock); 172*1ae08745Sheppo } 173*1ae08745Sheppo 174*1ae08745Sheppo /* 175*1ae08745Sheppo * When alarm goes off, wake up timeout threads. Alarm is set off every 176*1ae08745Sheppo * minutes. 177*1ae08745Sheppo */ 178*1ae08745Sheppo static void 179*1ae08745Sheppo vntsd_alarm_sig_handler(int sig) 180*1ae08745Sheppo { 181*1ae08745Sheppo static thread_t main_thread = 0; 182*1ae08745Sheppo 183*1ae08745Sheppo D1(stderr, "t@%d alarm signal %d\n", thr_self(), sig); 184*1ae08745Sheppo if (vntsdp->timeout == 0) { 185*1ae08745Sheppo DERR(stderr, "t@%d alarm signal should not recv %d\n", 186*1ae08745Sheppo thr_self(), sig); 187*1ae08745Sheppo return; 188*1ae08745Sheppo } 189*1ae08745Sheppo 190*1ae08745Sheppo 191*1ae08745Sheppo if (main_thread == 0) { 192*1ae08745Sheppo /* initialize thread id */ 193*1ae08745Sheppo main_thread = thr_self(); 194*1ae08745Sheppo } else if (main_thread != thr_self()) { 195*1ae08745Sheppo /* get signal because thread is timeout */ 196*1ae08745Sheppo return; 197*1ae08745Sheppo } 198*1ae08745Sheppo 199*1ae08745Sheppo /* in main thread */ 200*1ae08745Sheppo (void) mutex_lock(&vntsdp->tmo_lock); 201*1ae08745Sheppo 202*1ae08745Sheppo /* wake up timeout threads */ 203*1ae08745Sheppo (void) vntsd_que_walk(vntsdp->tmoq, (el_func_t)chk_timeout); 204*1ae08745Sheppo (void) mutex_unlock(&vntsdp->tmo_lock); 205*1ae08745Sheppo 206*1ae08745Sheppo /* reset alarm */ 207*1ae08745Sheppo (void) alarm(MINUTE); 208*1ae08745Sheppo } 209*1ae08745Sheppo 210*1ae08745Sheppo /* got a SIGUSER1 siginal */ 211*1ae08745Sheppo static void 212*1ae08745Sheppo vntsd_sig_handler(int sig) 213*1ae08745Sheppo { 214*1ae08745Sheppo char err_msg[VNTSD_LINE_LEN]; 215*1ae08745Sheppo 216*1ae08745Sheppo (void) snprintf(err_msg, sizeof (err_msg), "sig_handler() sig=%d", 217*1ae08745Sheppo sig); 218*1ae08745Sheppo 219*1ae08745Sheppo if (sig != SIGUSR1) { 220*1ae08745Sheppo vntsd_log(VNTSD_STATUS_SIG, err_msg); 221*1ae08745Sheppo } 222*1ae08745Sheppo } 223*1ae08745Sheppo 224*1ae08745Sheppo /* vntsd exits */ 225*1ae08745Sheppo static void 226*1ae08745Sheppo vntsd_exit(void) 227*1ae08745Sheppo { 228*1ae08745Sheppo D1(stderr, "t@%d vntsd_exit\n", thr_self()); 229*1ae08745Sheppo 230*1ae08745Sheppo (void) mutex_lock(&vntsdp->lock); 231*1ae08745Sheppo 232*1ae08745Sheppo if (vntsdp->timeout > 0) { 233*1ae08745Sheppo /* cancel the timer */ 234*1ae08745Sheppo (void) alarm(0); 235*1ae08745Sheppo } 236*1ae08745Sheppo /* delete all groups */ 237*1ae08745Sheppo vntsd_free_que(&vntsdp->grouppq, (clean_func_t)vntsd_clean_group); 238*1ae08745Sheppo 239*1ae08745Sheppo /* close control port */ 240*1ae08745Sheppo (void) close(vntsdp->ctrl_fd); 241*1ae08745Sheppo 242*1ae08745Sheppo assert(vntsdp->tmoq == NULL); 243*1ae08745Sheppo (void) mutex_unlock(&vntsdp->lock); 244*1ae08745Sheppo 245*1ae08745Sheppo /* clean up vntsdp */ 246*1ae08745Sheppo (void) mutex_destroy(&vntsdp->tmo_lock); 247*1ae08745Sheppo (void) mutex_destroy(&vntsdp->lock); 248*1ae08745Sheppo free(vntsdp); 249*1ae08745Sheppo closelog(); 250*1ae08745Sheppo } 251*1ae08745Sheppo 252*1ae08745Sheppo /* 253*1ae08745Sheppo * vntsd_help() 254*1ae08745Sheppo * print out valid command line options 255*1ae08745Sheppo */ 256*1ae08745Sheppo static void 257*1ae08745Sheppo vntsd_help(void) 258*1ae08745Sheppo { 259*1ae08745Sheppo 260*1ae08745Sheppo (void) fprintf(stderr, gettext("Usage: vntsd -i <VCC device instance> " 261*1ae08745Sheppo "[-p <listen address>] [-t <timeout in minutes>]\n")); 262*1ae08745Sheppo } 263*1ae08745Sheppo 264*1ae08745Sheppo 265*1ae08745Sheppo #ifdef DEBUG 266*1ae08745Sheppo #define DEBUG_OPTIONS "d" 267*1ae08745Sheppo #else 268*1ae08745Sheppo #define DEBUG_OPTIONS "" 269*1ae08745Sheppo #endif 270*1ae08745Sheppo 271*1ae08745Sheppo int 272*1ae08745Sheppo main(int argc, char ** argv) 273*1ae08745Sheppo { 274*1ae08745Sheppo char *path; 275*1ae08745Sheppo struct pollfd poll_drv[1]; 276*1ae08745Sheppo struct sigaction act; 277*1ae08745Sheppo char *listen_addr = NULL; 278*1ae08745Sheppo pid_t pid; 279*1ae08745Sheppo int i; 280*1ae08745Sheppo int option; 281*1ae08745Sheppo int sz; 282*1ae08745Sheppo int fd; 283*1ae08745Sheppo int n; 284*1ae08745Sheppo 285*1ae08745Sheppo /* internationalization */ 286*1ae08745Sheppo (void) setlocale(LC_MESSAGES, ""); 287*1ae08745Sheppo (void) textdomain(TEXT_DOMAIN); 288*1ae08745Sheppo vntsd_init_esctable_msgs(); 289*1ae08745Sheppo 290*1ae08745Sheppo /* initialization */ 291*1ae08745Sheppo bzero(&act, sizeof (act)); 292*1ae08745Sheppo 293*1ae08745Sheppo vntsdp = calloc(sizeof (vntsd_t), 1); 294*1ae08745Sheppo if (vntsdp == NULL) { 295*1ae08745Sheppo vntsd_log(VNTSD_ERR_NO_MEM, "main:vntsdp"); 296*1ae08745Sheppo exit(1); 297*1ae08745Sheppo } 298*1ae08745Sheppo 299*1ae08745Sheppo vntsdp->ctrl_fd = -1; 300*1ae08745Sheppo vntsdp->devinst = NULL; 301*1ae08745Sheppo 302*1ae08745Sheppo (void) mutex_init(&vntsdp->lock, USYNC_THREAD|LOCK_ERRORCHECK, NULL); 303*1ae08745Sheppo (void) mutex_init(&vntsdp->tmo_lock, USYNC_THREAD|LOCK_ERRORCHECK, 304*1ae08745Sheppo NULL); 305*1ae08745Sheppo 306*1ae08745Sheppo /* get CLI options */ 307*1ae08745Sheppo while ((option = getopt(argc, argv, "i:t:p:"DEBUG_OPTIONS)) != EOF) { 308*1ae08745Sheppo switch (option) { 309*1ae08745Sheppo #ifdef DEBUG 310*1ae08745Sheppo case 'd': 311*1ae08745Sheppo vntsdp->options |= VNTSD_OPT_DAEMON_OFF; 312*1ae08745Sheppo break; 313*1ae08745Sheppo #endif 314*1ae08745Sheppo case 'i': 315*1ae08745Sheppo vntsdp->devinst = optarg; 316*1ae08745Sheppo break; 317*1ae08745Sheppo case 'p': 318*1ae08745Sheppo listen_addr = optarg; 319*1ae08745Sheppo break; 320*1ae08745Sheppo 321*1ae08745Sheppo case 't': 322*1ae08745Sheppo n = sscanf(optarg, "%d", &(vntsdp->timeout)); 323*1ae08745Sheppo if (n != 1) { 324*1ae08745Sheppo vntsdp->timeout = -1; 325*1ae08745Sheppo } 326*1ae08745Sheppo break; 327*1ae08745Sheppo 328*1ae08745Sheppo default: 329*1ae08745Sheppo vntsd_help(); 330*1ae08745Sheppo exit(1); 331*1ae08745Sheppo } 332*1ae08745Sheppo } 333*1ae08745Sheppo 334*1ae08745Sheppo if ((vntsdp->devinst == NULL) || (vntsdp->timeout == -1)) { 335*1ae08745Sheppo vntsd_help(); 336*1ae08745Sheppo exit(1); 337*1ae08745Sheppo } 338*1ae08745Sheppo 339*1ae08745Sheppo if (listen_addr == NULL || strcmp(listen_addr, "localhost") == 0) { 340*1ae08745Sheppo /* by default listen on loopback interface */ 341*1ae08745Sheppo vntsdp->ip_addr.s_addr = htonl(INADDR_LOOPBACK); 342*1ae08745Sheppo } else if (strcmp(listen_addr, "any") == 0) { 343*1ae08745Sheppo vntsdp->ip_addr.s_addr = htonl(INADDR_ANY); 344*1ae08745Sheppo } else { 345*1ae08745Sheppo vntsdp->ip_addr.s_addr = inet_addr(listen_addr); 346*1ae08745Sheppo if (vntsdp->ip_addr.s_addr == (in_addr_t)(-1)) { 347*1ae08745Sheppo (void) fprintf(stderr, 348*1ae08745Sheppo gettext("Invalid listen address '%s'\n"), 349*1ae08745Sheppo listen_addr); 350*1ae08745Sheppo exit(1); 351*1ae08745Sheppo } 352*1ae08745Sheppo } 353*1ae08745Sheppo 354*1ae08745Sheppo D3(stderr, "options = %llx, instance = %s, listen = %s\n", 355*1ae08745Sheppo vntsdp->options, vntsdp->devinst, 356*1ae08745Sheppo listen_addr ? listen_addr : "<null>"); 357*1ae08745Sheppo 358*1ae08745Sheppo /* open VCC driver control port */ 359*1ae08745Sheppo sz = strlen(VCC_DEVICE_CTL_PATH) + strlen(vntsdp->devinst) + 1; 360*1ae08745Sheppo path = calloc(sz, 1); 361*1ae08745Sheppo if (path == NULL) { 362*1ae08745Sheppo vntsd_log(VNTSD_ERR_NO_MEM, "main(): alloc dev path"); 363*1ae08745Sheppo exit(1); 364*1ae08745Sheppo } 365*1ae08745Sheppo (void) snprintf(path, sz-1, VCC_DEVICE_CTL_PATH, vntsdp->devinst, 366*1ae08745Sheppo sizeof (vntsdp->devinst)); 367*1ae08745Sheppo vntsdp->ctrl_fd = open(path, O_RDWR); 368*1ae08745Sheppo free(path); 369*1ae08745Sheppo 370*1ae08745Sheppo if (vntsdp->ctrl_fd == -1) { 371*1ae08745Sheppo /* 372*1ae08745Sheppo * do not print error if device is not present 373*1ae08745Sheppo * the daemon is probably being started incorrectly 374*1ae08745Sheppo */ 375*1ae08745Sheppo if (errno != ENOENT) { 376*1ae08745Sheppo syslog(LOG_ERR, 377*1ae08745Sheppo "Error opening VCC device control port: %s", 378*1ae08745Sheppo strerror(errno)); 379*1ae08745Sheppo } 380*1ae08745Sheppo exit(1); 381*1ae08745Sheppo } 382*1ae08745Sheppo if ((vntsdp->options & VNTSD_OPT_DAEMON_OFF) == 0) { 383*1ae08745Sheppo /* daemonize it */ 384*1ae08745Sheppo pid = fork(); 385*1ae08745Sheppo if (pid < 0) { 386*1ae08745Sheppo perror("fork"); 387*1ae08745Sheppo exit(1); 388*1ae08745Sheppo } 389*1ae08745Sheppo if (pid > 0) { 390*1ae08745Sheppo /* parent */ 391*1ae08745Sheppo exit(0); 392*1ae08745Sheppo } 393*1ae08745Sheppo 394*1ae08745Sheppo /* 395*1ae08745Sheppo * child process (daemon) 396*1ae08745Sheppo * 397*1ae08745Sheppo * Close all file descriptors other than 2 and the ctrl fd. 398*1ae08745Sheppo */ 399*1ae08745Sheppo (void) close(0); 400*1ae08745Sheppo (void) close(1); 401*1ae08745Sheppo for (i = 3; i < vntsdp->ctrl_fd; i++) { 402*1ae08745Sheppo (void) close(i); 403*1ae08745Sheppo } 404*1ae08745Sheppo closefrom(vntsdp->ctrl_fd + 1); 405*1ae08745Sheppo 406*1ae08745Sheppo /* obtain a new process group */ 407*1ae08745Sheppo (void) setsid(); 408*1ae08745Sheppo fd = open("/dev/null", O_RDWR); 409*1ae08745Sheppo if (fd < 0) { 410*1ae08745Sheppo syslog(LOG_ERR, "Can not open /dev/null"); 411*1ae08745Sheppo exit(1); 412*1ae08745Sheppo } 413*1ae08745Sheppo /* handle standard I/O */ 414*1ae08745Sheppo if (dup2(fd, 0) < 0) { 415*1ae08745Sheppo syslog(LOG_ERR, "Failed dup2()"); 416*1ae08745Sheppo exit(1); 417*1ae08745Sheppo } 418*1ae08745Sheppo 419*1ae08745Sheppo if (dup2(fd, 1) < 0) { 420*1ae08745Sheppo syslog(LOG_ERR, "Failed dup2()"); 421*1ae08745Sheppo exit(1); 422*1ae08745Sheppo } 423*1ae08745Sheppo 424*1ae08745Sheppo /* ignore terminal signals */ 425*1ae08745Sheppo (void) signal(SIGTSTP, SIG_IGN); 426*1ae08745Sheppo (void) signal(SIGTTOU, SIG_IGN); 427*1ae08745Sheppo (void) signal(SIGTTIN, SIG_IGN); 428*1ae08745Sheppo } 429*1ae08745Sheppo 430*1ae08745Sheppo 431*1ae08745Sheppo /* set up signal handlers */ 432*1ae08745Sheppo 433*1ae08745Sheppo /* exit signals */ 434*1ae08745Sheppo act.sa_handler = exit_sig_handler; 435*1ae08745Sheppo 436*1ae08745Sheppo (void) sigemptyset(&act.sa_mask); 437*1ae08745Sheppo (void) sigaction(SIGINT, &act, NULL); 438*1ae08745Sheppo (void) sigaction(SIGTERM, &act, NULL); 439*1ae08745Sheppo (void) sigaction(SIGHUP, &act, NULL); 440*1ae08745Sheppo 441*1ae08745Sheppo /* vntsd internal signals */ 442*1ae08745Sheppo act.sa_handler = vntsd_sig_handler; 443*1ae08745Sheppo (void) sigemptyset(&act.sa_mask); 444*1ae08745Sheppo (void) sigaction(SIGUSR1, &act, NULL); 445*1ae08745Sheppo 446*1ae08745Sheppo 447*1ae08745Sheppo act.sa_handler = vntsd_alarm_sig_handler; 448*1ae08745Sheppo (void) sigemptyset(&act.sa_mask); 449*1ae08745Sheppo (void) sigaction(SIGALRM, &act, NULL); 450*1ae08745Sheppo 451*1ae08745Sheppo 452*1ae08745Sheppo /* setup exit */ 453*1ae08745Sheppo (void) atexit(vntsd_exit); 454*1ae08745Sheppo 455*1ae08745Sheppo 456*1ae08745Sheppo 457*1ae08745Sheppo /* initialization */ 458*1ae08745Sheppo openlog("vntsd", LOG_CONS, LOG_DAEMON); 459*1ae08745Sheppo 460*1ae08745Sheppo 461*1ae08745Sheppo /* set alarm */ 462*1ae08745Sheppo if (vntsdp->timeout > 0) { 463*1ae08745Sheppo (void) alarm(MINUTE); 464*1ae08745Sheppo } 465*1ae08745Sheppo 466*1ae08745Sheppo vntsdp->tid = thr_self(); 467*1ae08745Sheppo 468*1ae08745Sheppo /* get exiting consoles from vcc */ 469*1ae08745Sheppo vntsd_get_config(vntsdp); 470*1ae08745Sheppo 471*1ae08745Sheppo for (; ; ) { 472*1ae08745Sheppo /* poll vcc for configuration change */ 473*1ae08745Sheppo bzero(poll_drv, sizeof (poll_drv)); 474*1ae08745Sheppo 475*1ae08745Sheppo poll_drv[0].fd = vntsdp->ctrl_fd; 476*1ae08745Sheppo poll_drv[0].events = POLLIN; 477*1ae08745Sheppo 478*1ae08745Sheppo if (poll(poll_drv, 1, -1) == -1) { 479*1ae08745Sheppo if (errno == EINTR) { 480*1ae08745Sheppo /* wake up because a consle was deleted */ 481*1ae08745Sheppo vntsd_delete_cons(vntsdp); 482*1ae08745Sheppo continue; 483*1ae08745Sheppo } 484*1ae08745Sheppo vntsd_log(VNTSD_ERR_VCC_POLL, 485*1ae08745Sheppo "vcc control poll err! aborting.."); 486*1ae08745Sheppo exit(1); 487*1ae08745Sheppo } 488*1ae08745Sheppo 489*1ae08745Sheppo D1(stderr, "t@%d driver event %x\n", thr_self(), 490*1ae08745Sheppo poll_drv[0].revents); 491*1ae08745Sheppo 492*1ae08745Sheppo vntsd_daemon_wakeup(vntsdp); 493*1ae08745Sheppo 494*1ae08745Sheppo } 495*1ae08745Sheppo 496*1ae08745Sheppo /*NOTREACHED*/ 497*1ae08745Sheppo return (0); 498*1ae08745Sheppo } 499*1ae08745Sheppo 500*1ae08745Sheppo /* export ip_addr */ 501*1ae08745Sheppo struct in_addr 502*1ae08745Sheppo vntsd_ip_addr(void) 503*1ae08745Sheppo { 504*1ae08745Sheppo return (vntsdp->ip_addr); 505*1ae08745Sheppo } 506*1ae08745Sheppo 507*1ae08745Sheppo /* 508*1ae08745Sheppo * ioctl to vcc control port 509*1ae08745Sheppo * Supported ioctls interface are: 510*1ae08745Sheppo * ioctl code parameters return data 511*1ae08745Sheppo * VCC_NUM_CONSOLE none uint_t no consoles 512*1ae08745Sheppo * VCC_CONS_TBL none array of vcc_cons_t 513*1ae08745Sheppo * VCC_INQUIRY none vcc_response_t response 514*1ae08745Sheppo * VCC_CONS_INFO uint_t portno vcc_cons_t 515*1ae08745Sheppo * VCC_CONS_STATUS uint_t portno 516*1ae08745Sheppo * VCC_FORCE_CLOSE uint_t portno 517*1ae08745Sheppo */ 518*1ae08745Sheppo int 519*1ae08745Sheppo vntsd_vcc_ioctl(int ioctl_code, uint_t portno, void *buf) 520*1ae08745Sheppo { 521*1ae08745Sheppo D1(stderr, "t@%d vcc_ioctl@%d code=%x\n", thr_self(), portno, 522*1ae08745Sheppo ioctl_code); 523*1ae08745Sheppo 524*1ae08745Sheppo if ((ioctl_code == (VCC_CONS_INFO)) || 525*1ae08745Sheppo (ioctl_code == (VCC_FORCE_CLOSE))) { 526*1ae08745Sheppo /* construct vcc in buf */ 527*1ae08745Sheppo *((uint_t *)buf) = portno; 528*1ae08745Sheppo } 529*1ae08745Sheppo 530*1ae08745Sheppo if (ioctl(vntsdp->ctrl_fd, ioctl_code, (caddr_t)buf)) { 531*1ae08745Sheppo /* control port get error */ 532*1ae08745Sheppo syslog(LOG_ERR, "vcc control port error! abort vntsd"); 533*1ae08745Sheppo (void) thr_kill(vntsdp->tid, SIGINT); 534*1ae08745Sheppo return (VNTSD_STATUS_VCC_IO_ERR); 535*1ae08745Sheppo } 536*1ae08745Sheppo 537*1ae08745Sheppo return (VNTSD_SUCCESS); 538*1ae08745Sheppo } 539*1ae08745Sheppo 540*1ae08745Sheppo /* 541*1ae08745Sheppo * check if a vcc i/o error is caused by removal of a console. If so notify 542*1ae08745Sheppo * all clients connected to the console and wake up main thread to cleanup 543*1ae08745Sheppo * the console. 544*1ae08745Sheppo */ 545*1ae08745Sheppo int 546*1ae08745Sheppo vntsd_vcc_err(vntsd_cons_t *consp) 547*1ae08745Sheppo { 548*1ae08745Sheppo vntsd_group_t *groupp; 549*1ae08745Sheppo 550*1ae08745Sheppo assert(consp); 551*1ae08745Sheppo groupp = consp->group; 552*1ae08745Sheppo assert(groupp); 553*1ae08745Sheppo 554*1ae08745Sheppo if (consp->status & VNTSD_CONS_DELETED) { 555*1ae08745Sheppo /* console was deleted */ 556*1ae08745Sheppo return (VNTSD_STATUS_VCC_IO_ERR); 557*1ae08745Sheppo } 558*1ae08745Sheppo 559*1ae08745Sheppo if (vntsd_vcc_cons_alive(consp)) { 560*1ae08745Sheppo /* console is ok */ 561*1ae08745Sheppo return (VNTSD_STATUS_CONTINUE); 562*1ae08745Sheppo } 563*1ae08745Sheppo 564*1ae08745Sheppo /* console needs to be deleted */ 565*1ae08745Sheppo (void) mutex_lock(&consp->lock); 566*1ae08745Sheppo consp->status |= VNTSD_CONS_DELETED; 567*1ae08745Sheppo 568*1ae08745Sheppo /* signal all clients to disconnect from console */ 569*1ae08745Sheppo (void) vntsd_que_walk(consp->clientpq, 570*1ae08745Sheppo (el_func_t)vntsd_notify_client_cons_del); 571*1ae08745Sheppo (void) mutex_unlock(&consp->lock); 572*1ae08745Sheppo 573*1ae08745Sheppo /* mark the group */ 574*1ae08745Sheppo (void) mutex_lock(&groupp->lock); 575*1ae08745Sheppo groupp->status |= VNTSD_GROUP_CLEAN_CONS; 576*1ae08745Sheppo (void) mutex_unlock(&groupp->lock); 577*1ae08745Sheppo 578*1ae08745Sheppo /* signal main thread to deleted console */ 579*1ae08745Sheppo (void) thr_kill(vntsdp->tid, SIGUSR1); 580*1ae08745Sheppo 581*1ae08745Sheppo return (VNTSD_STATUS_VCC_IO_ERR); 582*1ae08745Sheppo } 583