8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / vntsd / common.c
bloba550530ed3c67c0d7628a1ec14c80400dadf0b2e
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * supporting modules.
31 #include <stdio.h>
32 #include <sys/types.h>
33 #include <sys/ipc.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <unistd.h>
37 #include <sys/socket.h>
38 #include <sys/ipc.h>
39 #include <sys/shm.h>
40 #include <sys/sem.h>
41 #include <sys/poll.h>
42 #include <wait.h>
43 #include <time.h>
44 #include <netinet/in.h>
45 #include <thread.h>
46 #include <signal.h>
47 #include <ctype.h>
48 #include <langinfo.h>
49 #include <libintl.h>
50 #include <syslog.h>
51 #include "vntsd.h"
52 #include "chars.h"
54 /* vntsd_write_line() - write a line to TCP client */
55 int
56 vntsd_write_line(vntsd_client_t *clientp, char *line)
58 int rv;
60 rv = vntsd_write_client(clientp, line, strlen(line));
61 if (rv == VNTSD_SUCCESS) {
62 rv = vntsd_write_client(clientp, vntsd_eol, VNTSD_EOL_LEN);
65 return (rv);
68 /* vntsd_write_lines() write one or more lines to client. */
69 int
70 vntsd_write_lines(vntsd_client_t *clientp, char *lines)
72 char *buf;
73 char *line;
74 char *endofline;
76 buf = strdup(lines);
77 if (buf == NULL) {
78 return (VNTSD_ERR_NO_MEM);
81 line = buf;
83 while ((line != NULL) && (*line != '\0')) {
85 endofline = strchr(line, '\n');
86 if (endofline != NULL) {
87 *endofline = '\0';
90 (void) vntsd_write_line(clientp, line);
92 if (endofline != NULL)
93 line = endofline + 1;
94 else
95 line = NULL;
98 free(buf);
99 return (VNTSD_SUCCESS);
102 /* vntsd_get_yes_no() - read in a "y" or "n" */
104 vntsd_get_yes_no(vntsd_client_t *clientp, char *msg, int *yes_no)
106 char c;
107 char yesno[8];
108 int rv;
110 /* create [y/n] prompt */
111 (void) snprintf(yesno, sizeof (yesno), "[%c/%c] ",
112 *nl_langinfo(YESSTR), *nl_langinfo(NOSTR));
114 for (; ; ) {
115 if ((rv = vntsd_write_client(clientp, msg, strlen(msg)))
116 != VNTSD_SUCCESS) {
117 return (rv);
120 if ((rv = vntsd_write_client(clientp, yesno, strlen(yesno))) !=
121 VNTSD_SUCCESS) {
122 return (rv);
125 if ((rv = vntsd_read_data(clientp, &c))
126 != VNTSD_SUCCESS) {
127 return (rv);
130 /* echo */
131 if ((rv = vntsd_write_client(clientp, &c, 1)) !=
132 VNTSD_SUCCESS) {
133 return (rv);
136 if ((rv = vntsd_write_client(clientp, vntsd_eol,
137 VNTSD_EOL_LEN)) != VNTSD_SUCCESS) {
138 return (rv);
141 c = tolower(c);
143 if (c == *nl_langinfo(YESSTR)) {
144 *yes_no = B_TRUE;
145 return (VNTSD_SUCCESS);
148 if (c == *nl_langinfo(NOSTR)) {
149 *yes_no = B_FALSE;
150 return (VNTSD_SUCCESS);
153 if ((rv = vntsd_write_line(clientp,
154 gettext("Invalid response. Try again.")))
155 != VNTSD_SUCCESS) {
156 return (rv);
160 /*NOTREACHED*/
161 return (0);
164 /* vntsd_open_vcc() - open a vcc port */
166 vntsd_open_vcc(char *dev_name, uint_t cons_no)
168 int drvfd;
169 int sz;
170 char *path;
171 sz = strlen(VCC_DEVICE_PATH) + strlen(dev_name)+1;
173 path = calloc(sz, 1);
175 if (path == NULL) {
176 return (-1);
179 (void) snprintf(path, sz-1, VCC_DEVICE_PATH, dev_name);
181 for (; ; ) {
182 drvfd = open(path, O_RDWR);
184 if ((drvfd < 0) && (errno == EAGAIN)) {
185 if (vntsd_vcc_ioctl(VCC_FORCE_CLOSE, cons_no, &cons_no)
186 != VNTSD_SUCCESS) {
187 break;
189 } else {
190 break;
195 if (drvfd < 0) {
196 D1(stderr, "t@%d open_vcc@%s exit\n", thr_self(), dev_name);
197 free(path);
198 return (-1);
201 free(path);
202 return (drvfd);
205 /* vntsd_cons_by_consno() - match a console structure to cons no */
206 boolean_t
207 vntsd_cons_by_consno(vntsd_cons_t *consp, int *cons_id)
209 if (consp->status & VNTSD_CONS_DELETED) {
210 return (B_FALSE);
212 return (consp->cons_no == *cons_id);
215 /* vntsd_write_client() write to telnet client */
217 vntsd_write_client(vntsd_client_t *client, char *buffer, size_t sz)
219 int rv;
222 /* write to client */
223 rv = vntsd_write_fd(client->sockfd, buffer, sz);
225 /* client has output, reset timer */
226 vntsd_reset_timer(client->cons_tid);
228 return (rv);
231 /* vntsd_write_fd() write to tcp socket file descriptor */
233 vntsd_write_fd(int fd, void *buf, size_t sz)
235 int n;
237 while (sz > 0) {
238 n = write(fd, buf, sz);
239 if (n < 0) {
240 if (errno == EINTR) {
241 return (VNTSD_STATUS_INTR);
244 return (VNTSD_STATUS_CLIENT_QUIT);
247 if (n == 0) {
248 return (VNTSD_STATUS_CLIENT_QUIT);
251 buf = (caddr_t)buf + n;
252 sz -= n;
254 return (VNTSD_SUCCESS);
259 * vntsd_read_char() - read a char from TCP Clienti. Returns:
260 * VNTSD_SUCCESS, VNTSD_STATUS_CLIENT_QUIT or VNTSD_STATUS_INTR
263 vntsd_read_char(vntsd_client_t *clientp, char *c)
265 int n;
266 vntsd_timeout_t tmo;
267 int rv;
269 tmo.tid = thr_self();
270 tmo.minutes = 0;
271 tmo.clientp = clientp;
273 /* attach to timer */
274 if ((rv = vntsd_attach_timer(&tmo)) != VNTSD_SUCCESS) {
275 return (rv);
278 n = read(clientp->sockfd, c, 1);
280 /* detach from timer */
281 if ((rv = vntsd_detach_timer(&tmo)) != VNTSD_SUCCESS) {
282 return (rv);
285 if (n == 1) {
286 return (VNTSD_SUCCESS);
289 if (n == 0) {
290 return (VNTSD_STATUS_CLIENT_QUIT);
294 * read error or wake up by signal, either console is being removed or
295 * timeout occurs.
297 if (errno == EINTR) {
298 return (VNTSD_STATUS_INTR);
301 /* any other error, we close client */
302 return (VNTSD_STATUS_CLIENT_QUIT);
306 * vntsd_read_data() - handle special commands
307 * such as telnet, daemon and ctrl cmds. Returns:
308 * from vntsd_read_char:
309 * VNTSD_STATUS_CLIENT_QUIT
310 * VNTSD_STATUS_INTR
311 * from vnts_process_daemon_cmd:
312 * VNTSD_STATUS_RESELECT_CONS
313 * VNTSD_STATUS_MOV_CONS_FORWARD
314 * VNTSD_STATUS_MOV_CONS_BACKWARD
315 * VNTSD_STATUS_ACQURE_WRITER
316 * VNTSD_STATUS_CONTINUE
317 * from vntsd_telnet_cmd
318 * VNTSD_STATUS_CONTINUE
321 vntsd_read_data(vntsd_client_t *clientp, char *c)
323 int rv;
325 for (; ; ) {
326 if ((rv = vntsd_read_char(clientp, c)) != VNTSD_SUCCESS) {
327 return (rv);
330 /* daemon cmd? */
331 rv = vntsd_process_daemon_cmd(clientp, *c);
333 if (rv == VNTSD_SUCCESS) {
334 /* telnet cmd? */
335 rv = vntsd_telnet_cmd(clientp, *c);
338 if (rv == VNTSD_STATUS_CONTINUE) {
340 * either a daemon cmd or a telnet cmd
341 * was processed.
343 clientp->prev_char = 0;
344 continue;
347 return (rv);
350 /*NOTREACHED*/
351 return (0);
353 /* vntsd_read_line() - read a line from TCP client */
355 vntsd_read_line(vntsd_client_t *clientp, char *buf, int *in_sz)
357 char c;
358 int rv;
359 int out_sz = 0;
362 for (; ; ) {
364 if ((rv = vntsd_read_data(clientp, &c)) != VNTSD_SUCCESS) {
365 return (rv);
368 if (c == BS) {
369 /* back */
370 if ((rv = vntsd_write_client(clientp, &c, 1)) !=
371 VNTSD_SUCCESS) {
372 return (rv);
375 c = ' ';
376 if ((rv = vntsd_write_client(clientp, &c, 1)) !=
377 VNTSD_SUCCESS) {
378 return (rv);
381 buf--;
382 out_sz--;
383 continue;
385 /* echo */
386 if ((rv = vntsd_write_client(clientp, &c, 1)) !=
387 VNTSD_SUCCESS) {
388 return (rv);
391 *buf++ = c;
392 out_sz++;
394 if (c == CR) {
395 /* end of line */
396 *in_sz = out_sz;
397 return (VNTSD_SUCCESS);
400 if (out_sz == *in_sz) {
401 return (VNTSD_SUCCESS);
405 /*NOTREACHED*/
406 return (0);
409 /* free a client */
410 void
411 vntsd_free_client(vntsd_client_t *clientp)
414 if (clientp->sockfd != -1) {
415 (void) close(clientp->sockfd);
418 (void) mutex_destroy(&clientp->lock);
420 free(clientp);
424 /* check if a vcc console port still ok */
425 boolean_t
426 vntsd_vcc_cons_alive(vntsd_cons_t *consp)
428 vcc_console_t vcc_cons;
429 int rv;
431 assert(consp);
432 assert(consp->group);
434 /* construct current configuration */
435 (void) strncpy(vcc_cons.domain_name, consp->domain_name, MAXPATHLEN);
436 (void) strncpy(vcc_cons.group_name, consp->group->group_name,
437 MAXPATHLEN);
438 vcc_cons.tcp_port = consp->group->tcp_port;
439 vcc_cons.cons_no = consp->cons_no;
441 /* call vcc to verify */
442 rv = vntsd_vcc_ioctl(VCC_CONS_STATUS, consp->cons_no, &vcc_cons);
443 if (rv != VNTSD_SUCCESS) {
444 return (B_FALSE);
447 if (vcc_cons.cons_no == -1) {
448 /* port is gone */
449 return (B_FALSE);
452 /* port is ok */
453 return (B_TRUE);
457 /* add to total if a console is alive */
458 static boolean_t
459 total_cons(vntsd_cons_t *consp, int *num_cons)
461 int rv;
463 assert(consp->group);
464 rv = vntsd_vcc_err(consp);
465 if (rv == VNTSD_STATUS_CONTINUE) {
466 (*num_cons)++;
468 return (B_FALSE);
472 /* total alive consoles in a group */
474 vntsd_chk_group_total_cons(vntsd_group_t *groupp)
476 uint_t num_cons = 0;
478 (void) vntsd_que_find(groupp->conspq, (compare_func_t)total_cons,
479 &num_cons);
480 return (num_cons);
483 /* vntsd_log() log function for errors */
484 void
485 vntsd_log(vntsd_status_t status, char *msg)
487 char *status_msg = NULL;
488 int critical = 0;
490 switch (status) {
492 case VNTSD_SUCCESS:
493 status_msg = "STATUS_OK";
494 break;
496 case VNTSD_STATUS_CONTINUE:
497 status_msg = "CONTINUE";
498 break;
500 case VNTSD_STATUS_EXIT_SIG:
501 critical = 1;
502 status_msg = "KILL SIGNAL RECV";
503 break;
505 case VNTSD_STATUS_SIG:
506 status_msg = "SIG RECV";
507 break;
509 case VNTSD_STATUS_NO_HOST_NAME:
510 status_msg = "Warining NO HOST NAME";
511 break;
513 case VNTSD_STATUS_CLIENT_QUIT:
514 status_msg = "CLIENT CLOSED GROUP CONNECTION";
515 break;
517 case VNTSD_STATUS_RESELECT_CONS:
518 status_msg = "CLIENT RESELECTS CONSOLE";
519 break;
521 case VNTSD_STATUS_VCC_IO_ERR:
522 status_msg = "CONSOLE WAS DELETED";
523 break;
525 case VNTSD_STATUS_MOV_CONS_FORWARD:
526 status_msg = "MOVE CONSOLE FORWARD";
527 break;
529 case VNTSD_STATUS_MOV_CONS_BACKWARD:
530 status_msg = "MOVE CONSOLE BACKWARD";
531 break;
533 case VNTSD_STATUS_ACQUIRE_WRITER:
534 status_msg = "FORCE CONSOLE WRITE";
535 break;
537 case VNTSD_STATUS_INTR:
538 status_msg = "RECV SIGNAL";
539 break;
541 case VNTSD_STATUS_DISCONN_CONS:
542 status_msg = "DELETING CONSOLE";
543 break;
545 case VNTSD_STATUS_NO_CONS:
546 status_msg = "All console(s) in the group have been deleted.";
547 break;
549 case VNTSD_STATUS_AUTH_ENABLED:
550 critical = 1;
551 status_msg = "VNTSD_STATUS_AUTH_ENABLED";
552 break;
554 case VNTSD_ERR_NO_MEM:
555 critical = 1;
556 status_msg = "NO MEMORY";
557 break;
559 case VNTSD_ERR_NO_DRV:
560 critical = 1;
561 status_msg = "NO VCC DRIVER";
562 break;
564 case VNTSD_ERR_WRITE_CLIENT:
565 status_msg = "WRITE CLIENT ERR";
566 break;
568 case VNTSD_ERR_EL_NOT_FOUND:
569 critical = 1;
570 status_msg = "ELEMENT_NOT_FOUND";
571 break;
573 case VNTSD_ERR_VCC_CTRL_DATA:
574 critical = 1;
575 status_msg = "VCC CTRL DATA ERROR";
576 break;
578 case VNTSD_ERR_VCC_POLL:
579 critical = 1;
580 status_msg = "VCC POLL ERROR";
581 break;
583 case VNTSD_ERR_VCC_IOCTL:
584 critical = 1;
585 status_msg = "VCC IOCTL ERROR";
586 break;
588 case VNTSD_ERR_VCC_GRP_NAME:
589 critical = 1;
590 status_msg = "VCC GROUP NAME ERROR";
591 break;
593 case VNTSD_ERR_CREATE_LISTEN_THR:
594 critical = 1;
595 status_msg = "FAIL TO CREATE LISTEN THREAD";
596 break;
598 case VNTSD_ERR_CREATE_WR_THR:
599 critical = 1;
600 status_msg = "FAIL TO CREATE WRITE THREAD";
601 break;
603 case VNTSD_ERR_ADD_CONS_FAILED:
604 critical = 1;
605 status_msg = "FAIL TO ADD A CONSOLE";
606 break;
608 case VNTSD_ERR_LISTEN_SOCKET:
609 critical = 1;
610 status_msg = "LISTEN SOCKET ERROR";
611 break;
613 case VNTSD_ERR_LISTEN_OPTS:
614 critical = 1;
615 status_msg = "SET SOCKET OPTIONS ERROR";
616 break;
618 case VNTSD_ERR_LISTEN_BIND:
619 critical = 1;
620 status_msg = "BIND SOCKET ERROR";
621 break;
623 case VNTSD_STATUS_ACCEPT_ERR:
624 critical = 1;
625 status_msg = "LISTEN ACCEPT ERROR";
626 break;
628 case VNTSD_ERR_CREATE_CONS_THR:
629 critical = 1;
630 status_msg = "CREATE CONSOLE THREAD ERROR ";
631 break;
633 case VNTSD_ERR_SIG:
634 critical = 1;
635 status_msg = "RECV UNKNOWN SIG";
636 break;
638 case VNTSD_ERR_UNKNOWN_CMD:
639 critical = 1;
640 status_msg = "RECV UNKNOWN COMMAND";
641 break;
643 case VNTSD_ERR_CLIENT_TIMEOUT:
644 status_msg = "CLOSE CLIENT BECAUSE TIMEOUT";
645 break;
646 default:
647 status_msg = "Unknown status recv";
648 break;
652 if (critical) {
653 syslog(LOG_ERR, "%s: thread[%d] %s\n", status_msg,
654 thr_self(), msg);
656 #ifdef DEBUG
657 DERR(stderr, "%s: thread[%d] %s\n", status_msg, thr_self(), msg);
658 syslog(LOG_ERR, "%s: thread[%d] %s\n", status_msg, thr_self(), msg);
659 #endif