Print this page
Reduce lint
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/cmd/zoneadmd/zfd.c
+++ new/usr/src/cmd/zoneadmd/zfd.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 * Copyright 2016 Joyent, Inc. All rights reserved.
26 26 */
27 27
28 28 /*
29 29 * Zone file descriptor support is used as a mechanism for a process inside the
30 30 * zone to log messages to the GZ zoneadmd and also as a way to interact
31 31 * directly with the process (via zlogin -I). The zfd thread is modeled on
32 32 * the zcons thread so see the comment header in zcons.c for a general overview.
33 33 * Unlike with zcons, which has a single endpoint within the zone and a single
34 34 * endpoint used by zoneadmd, we setup multiple endpoints within the zone.
35 35 *
36 36 * The mode, which is controlled by the zone attribute "zlog-mode" is somewhat
37 37 * of a misnomer since its purpose has evolved. The attribute currently
38 38 * can have six values which are used to control:
39 39 * - how the zfd devices are used inside the zone
40 40 * - if the output on the device(s) is also teed into another stream within
41 41 * the zone
42 42 * - if we do logging in the GZ
43 43 * See the comment on get_mode_logmax() in this file, and the comment in
44 44 * uts/common/io/zfd.c for more details.
45 45 *
46 46 * Internally the zfd_mode_t struct holds the number of stdio devs (1 or 3),
47 47 * the number of additional devs corresponding to the zone attr value and the
48 48 * GZ logging flag.
49 49 *
50 50 * Note that although the mode indicates the number of devices needed, we always
51 51 * create all possible zfd devices for simplicity.
52 52 */
53 53
54 54 #include <sys/types.h>
55 55 #include <sys/socket.h>
56 56 #include <sys/stat.h>
57 57 #include <sys/termios.h>
58 58 #include <sys/zfd.h>
59 59 #include <sys/mkdev.h>
60 60
61 61 #include <assert.h>
62 62 #include <ctype.h>
63 63 #include <errno.h>
64 64 #include <fcntl.h>
65 65 #include <stdarg.h>
66 66 #include <stdio.h>
67 67 #include <stdlib.h>
68 68 #include <strings.h>
69 69 #include <stropts.h>
70 70 #include <thread.h>
71 71 #include <ucred.h>
72 72 #include <unistd.h>
73 73 #include <zone.h>
74 74 #include <signal.h>
75 75 #include <wchar.h>
76 76
77 77 #include <libdevinfo.h>
78 78 #include <libdevice.h>
79 79 #include <libzonecfg.h>
80 80
81 81 #include <syslog.h>
82 82 #include <sys/modctl.h>
83 83
84 84 #include "zoneadmd.h"
85 85
86 86 static zlog_t *zlogp;
87 87 static int shutting_down = 0;
88 88 static thread_t logger_tid;
89 89 static int logfd = -1;
90 90 static size_t log_sz = 0;
91 91 static size_t log_rot_sz = 0;
92 92
93 93 static void rotate_log();
94 94
95 95 /*
96 96 * The eventstream is a simple one-directional flow of messages implemented
97 97 * with a pipe. It is used to wake up the poller when it needs to shutdown.
98 98 */
99 99 static int eventstream[2] = {-1, -1};
100 100
101 101 #define LOGNAME "stdio.log"
102 102 #define ZLOG_MODE "zlog-mode"
103 103 #define LOG_MAXSZ "zlog-max-size"
104 104 #define ZFDNEX_DEVTREEPATH "/pseudo/zfdnex@2"
105 105 #define ZFDNEX_FILEPATH "/devices/pseudo/zfdnex@2"
106 106 #define SERVER_SOCKPATH ZONES_TMPDIR "/%s.server_%s"
107 107 #define ZTTY_RETRY 5
108 108
109 109 #define NUM_ZFD_DEVS 5
110 110
111 111 typedef struct zfd_mode {
112 112 uint_t zmode_n_stddevs;
113 113 uint_t zmode_n_addl_devs;
114 114 boolean_t zmode_gzlogging;
115 115 } zfd_mode_t;
116 116 static zfd_mode_t mode;
117 117
118 118 /*
119 119 * cb_data is only used by destroy_cb.
120 120 */
121 121 struct cb_data {
122 122 zlog_t *zlogp;
123 123 int killed;
124 124 };
125 125
126 126 /*
127 127 * destroy_zfd_devs() and its helper destroy_cb() tears down any zfd instances
128 128 * associated with this zone. If things went very wrong, we might have an
129 129 * incorrect number of instances hanging around. This routine hunts down and
130 130 * tries to remove all of them. Of course, if the fd is open, the instance will
131 131 * not detach, which is a potential issue.
132 132 */
133 133 static int
134 134 destroy_cb(di_node_t node, void *arg)
135 135 {
136 136 struct cb_data *cb = (struct cb_data *)arg;
137 137 char *prop_data;
138 138 char *tmp;
139 139 char devpath[MAXPATHLEN];
140 140 devctl_hdl_t hdl;
141 141
142 142 if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, "zfd_zname",
143 143 &prop_data) == -1)
144 144 return (DI_WALK_CONTINUE);
145 145
146 146 assert(prop_data != NULL);
147 147 if (strcmp(prop_data, zone_name) != 0) {
148 148 /* this is a zfd for a different zone */
149 149 return (DI_WALK_CONTINUE);
150 150 }
151 151
152 152 tmp = di_devfs_path(node);
153 153 (void) snprintf(devpath, sizeof (devpath), "/devices/%s", tmp);
154 154 di_devfs_path_free(tmp);
155 155
156 156 if ((hdl = devctl_device_acquire(devpath, 0)) == NULL) {
157 157 zerror(cb->zlogp, B_TRUE, "WARNING: zfd %s found, "
158 158 "but it could not be controlled.", devpath);
159 159 return (DI_WALK_CONTINUE);
160 160 }
161 161 if (devctl_device_remove(hdl) == 0) {
162 162 cb->killed++;
163 163 } else {
164 164 zerror(cb->zlogp, B_TRUE, "WARNING: zfd %s found, "
165 165 "but it could not be removed.", devpath);
166 166 }
167 167 devctl_release(hdl);
168 168 return (DI_WALK_CONTINUE);
169 169 }
170 170
171 171 static int
172 172 destroy_zfd_devs(zlog_t *zlogp)
173 173 {
174 174 di_node_t root;
175 175 struct cb_data cb;
176 176
177 177 bzero(&cb, sizeof (cb));
178 178 cb.zlogp = zlogp;
179 179
180 180 if ((root = di_init(ZFDNEX_DEVTREEPATH, DINFOCPYALL)) == DI_NODE_NIL) {
181 181 zerror(zlogp, B_TRUE, "di_init failed");
182 182 return (-1);
183 183 }
184 184
185 185 (void) di_walk_node(root, DI_WALK_CLDFIRST, (void *)&cb, destroy_cb);
186 186
187 187 di_fini(root);
188 188 return (0);
189 189 }
190 190
191 191 static void
192 192 make_tty(zlog_t *zlogp, int id)
193 193 {
194 194 int i;
195 195 int fd = -1;
196 196 char stdpath[MAXPATHLEN];
197 197
198 198 /*
199 199 * Open the master side of the dev and issue the ZFD_MAKETTY ioctl,
200 200 * which will cause the the various tty-related streams modules to be
201 201 * pushed when the slave opens the device.
202 202 *
203 203 * In very rare cases the open returns ENOENT if devfs doesn't have
204 204 * everything setup yet due to heavy zone startup load. Wait for
205 205 * 1 sec. and retry a few times. Even if we can't setup tty mode
206 206 * we still move on.
207 207 */
208 208 (void) snprintf(stdpath, sizeof (stdpath), "/dev/zfd/%s/master/%d",
209 209 zone_name, id);
210 210
211 211 for (i = 0; !shutting_down && i < ZTTY_RETRY; i++) {
212 212 fd = open(stdpath, O_RDWR | O_NOCTTY);
213 213 if (fd >= 0 || errno != ENOENT)
214 214 break;
215 215 (void) sleep(1);
216 216 }
217 217 if (fd == -1) {
218 218 zerror(zlogp, B_TRUE, "ERROR: could not open zfd %d for "
219 219 "zone %s to set tty mode", id, zone_name);
220 220 } else {
221 221 /*
222 222 * This ioctl can occasionally return ENXIO if devfs doesn't
223 223 * have everything plumbed up yet due to heavy zone startup
224 224 * load. Wait for 1 sec. and retry a few times before we give
225 225 * up.
226 226 */
227 227 for (i = 0; !shutting_down && i < ZTTY_RETRY; i++) {
228 228 if (ioctl(fd, ZFD_MAKETTY) == 0) {
229 229 break;
230 230 } else if (errno != ENXIO) {
231 231 break;
232 232 }
233 233 (void) sleep(1);
234 234 }
235 235 }
236 236
237 237 if (fd != -1)
238 238 (void) close(fd);
239 239 }
240 240
241 241 /*
242 242 * init_zfd_devs() drives the device-tree configuration of the zone fd devices.
243 243 * The general strategy is to use the libdevice (devctl) interfaces to
244 244 * instantiate all of new zone fd nodes. We do a lot of sanity checking, and
245 245 * are careful to reuse a dev if one exists.
246 246 *
247 247 * Once the devices are in the device tree, we kick devfsadm via
248 248 * di_devlink_init() to ensure that the appropriate symlinks (to the master and
249 249 * slave fd devices) are placed in /dev in the global zone.
250 250 */
251 251 static int
252 252 init_zfd_dev(zlog_t *zlogp, devctl_hdl_t bus_hdl, int id)
253 253 {
254 254 int rv = -1;
255 255 devctl_ddef_t ddef_hdl = NULL;
256 256 devctl_hdl_t dev_hdl = NULL;
257 257
258 258 if ((ddef_hdl = devctl_ddef_alloc("zfd", 0)) == NULL) {
259 259 zerror(zlogp, B_TRUE, "failed to allocate ddef handle");
260 260 goto error;
261 261 }
262 262
263 263 /*
264 264 * Set four properties on this node; the name of the zone, the dev name
265 265 * seen inside the zone, a flag which lets pseudo know that it is OK to
266 266 * automatically allocate an instance # for this device, and the last
267 267 * one tells the device framework not to auto-detach this node - we
268 268 * need the node to still be there when we ask devfsadmd to make links,
269 269 * and when we need to open it.
270 270 */
271 271 if (devctl_ddef_string(ddef_hdl, "zfd_zname", zone_name) == -1) {
272 272 zerror(zlogp, B_TRUE, "failed to create zfd_zname property");
273 273 goto error;
274 274 }
275 275 if (devctl_ddef_int(ddef_hdl, "zfd_id", id) == -1) {
276 276 zerror(zlogp, B_TRUE, "failed to create zfd_id property");
277 277 goto error;
278 278 }
279 279 if (devctl_ddef_int(ddef_hdl, "auto-assign-instance", 1) == -1) {
280 280 zerror(zlogp, B_TRUE, "failed to create auto-assign-instance "
281 281 "property");
282 282 goto error;
283 283 }
284 284 if (devctl_ddef_int(ddef_hdl, "ddi-no-autodetach", 1) == -1) {
285 285 zerror(zlogp, B_TRUE, "failed to create ddi-no-auto-detach "
286 286 "property");
287 287 goto error;
288 288 }
289 289 if (devctl_bus_dev_create(bus_hdl, ddef_hdl, 0, &dev_hdl) == -1) {
290 290 zerror(zlogp, B_TRUE, "failed to create zfd node");
291 291 goto error;
292 292 }
293 293 rv = 0;
294 294
295 295 error:
296 296 if (ddef_hdl)
297 297 devctl_ddef_free(ddef_hdl);
298 298 if (dev_hdl)
299 299 devctl_release(dev_hdl);
300 300 return (rv);
301 301 }
302 302
303 303 static int
304 304 init_zfd_devs(zlog_t *zlogp, zfd_mode_t *mode)
305 305 {
306 306 devctl_hdl_t bus_hdl = NULL;
307 307 di_devlink_handle_t dl = NULL;
308 308 int rv = -1;
309 309 int i;
310 310
311 311 /*
312 312 * Time to make the devices.
313 313 */
314 314 if ((bus_hdl = devctl_bus_acquire(ZFDNEX_FILEPATH, 0)) == NULL) {
315 315 zerror(zlogp, B_TRUE, "devctl_bus_acquire failed");
316 316 goto error;
317 317 }
318 318
319 319 for (i = 0; i < NUM_ZFD_DEVS; i++) {
320 320 if (init_zfd_dev(zlogp, bus_hdl, i) != 0)
321 321 goto error;
322 322 }
323 323
324 324 if ((dl = di_devlink_init("zfd", DI_MAKE_LINK)) == NULL) {
325 325 zerror(zlogp, B_TRUE, "failed to create devlinks");
326 326 goto error;
327 327 }
328 328
329 329 (void) di_devlink_fini(&dl);
330 330 rv = 0;
331 331
332 332 if (mode->zmode_n_stddevs == 1) {
333 333 /* We want the primary stream to look like a tty. */
334 334 make_tty(zlogp, 0);
335 335 }
336 336
337 337 error:
338 338 if (bus_hdl)
339 339 devctl_release(bus_hdl);
340 340 return (rv);
341 341 }
342 342
343 343 static int
344 344 init_server_sock(zlog_t *zlogp, int *servfd, char *nm)
345 345 {
346 346 int resfd = -1;
347 347 struct sockaddr_un servaddr;
348 348
349 349 bzero(&servaddr, sizeof (servaddr));
350 350 servaddr.sun_family = AF_UNIX;
351 351 (void) snprintf(servaddr.sun_path, sizeof (servaddr.sun_path),
352 352 SERVER_SOCKPATH, zone_name, nm);
353 353
354 354 if ((resfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
355 355 zerror(zlogp, B_TRUE, "server setup: could not create socket");
356 356 goto err;
357 357 }
358 358 (void) unlink(servaddr.sun_path);
359 359
360 360 if (bind(resfd, (struct sockaddr *)&servaddr, sizeof (servaddr))
361 361 == -1) {
362 362 zerror(zlogp, B_TRUE,
363 363 "server setup: could not bind to socket");
364 364 goto err;
365 365 }
366 366
367 367 if (listen(resfd, 4) == -1) {
368 368 zerror(zlogp, B_TRUE,
369 369 "server setup: could not listen on socket");
370 370 goto err;
371 371 }
372 372
373 373 *servfd = resfd;
374 374 return (0);
375 375
376 376 err:
377 377 (void) unlink(servaddr.sun_path);
378 378 if (resfd != -1)
379 379 (void) close(resfd);
380 380 return (-1);
381 381 }
382 382
383 383 static void
384 384 destroy_server_sock(int servfd, char *nm)
385 385 {
386 386 char path[MAXPATHLEN];
387 387
388 388 (void) snprintf(path, sizeof (path), SERVER_SOCKPATH, zone_name, nm);
389 389 (void) unlink(path);
390 390 (void) shutdown(servfd, SHUT_RDWR);
391 391 (void) close(servfd);
392 392 }
393 393
394 394 /*
395 395 * Read the "ident" string from the client's descriptor; this routine also
396 396 * tolerates being called with pid=NULL, for times when you want to "eat"
397 397 * the ident string from a client without saving it.
398 398 */
399 399 static int
400 400 get_client_ident(int clifd, pid_t *pid, char *locale, size_t locale_len,
401 401 uint_t *flagsp)
402 402 {
403 403 char buf[BUFSIZ], *bufp;
404 404 size_t buflen = sizeof (buf);
405 405 char c = '\0';
406 406 int i = 0, r;
407 407 ucred_t *cred = NULL;
408 408
409 409 /* "eat up the ident string" case, for simplicity */
410 410 if (pid == NULL) {
411 411 assert(locale == NULL && locale_len == 0);
412 412 while (read(clifd, &c, 1) == 1) {
413 413 if (c == '\n')
414 414 return (0);
415 415 }
416 416 }
417 417
418 418 bzero(buf, sizeof (buf));
419 419 while ((buflen > 1) && (r = read(clifd, &c, 1)) == 1) {
420 420 buflen--;
421 421 if (c == '\n')
422 422 break;
423 423
424 424 buf[i] = c;
425 425 i++;
426 426 }
427 427 if (r == -1)
428 428 return (-1);
429 429
430 430 /*
431 431 * We've filled the buffer, but still haven't seen \n. Keep eating
432 432 * until we find it; we don't expect this to happen, but this is
433 433 * defensive.
434 434 */
435 435 if (c != '\n') {
436 436 while ((r = read(clifd, &c, sizeof (c))) > 0)
437 437 if (c == '\n')
438 438 break;
439 439 }
440 440
441 441 /*
442 442 * Parse buffer for message of the form:
443 443 * IDENT <locale> <flags>
444 444 */
445 445 bufp = buf;
446 446 if (strncmp(bufp, "IDENT ", 6) != 0)
447 447 return (-1);
448 448 bufp += 6;
449 449
450 450 if (getpeerucred(clifd, &cred) == 0) {
451 451 *pid = ucred_getpid((const ucred_t *)cred);
452 452 ucred_free(cred);
453 453 } else {
454 454 return (-1);
455 455 }
456 456
457 457 while (*bufp != '\0' && isspace(*bufp))
458 458 bufp++;
459 459 buflen = strlen(bufp) - 1;
460 460 bufp[buflen - 1] = '\0';
461 461 (void) strlcpy(locale, bufp, locale_len);
462 462
463 463 *flagsp = atoi(&bufp[buflen]);
464 464
465 465 return (0);
466 466 }
467 467
468 468 static int
469 469 accept_client(int servfd, pid_t *pid, char *locale, size_t locale_len,
470 470 uint_t *flagsp)
471 471 {
472 472 int connfd;
473 473 struct sockaddr_un cliaddr;
474 474 socklen_t clilen;
475 475 int flags;
476 476
477 477 clilen = sizeof (cliaddr);
478 478 connfd = accept(servfd, (struct sockaddr *)&cliaddr, &clilen);
479 479 if (connfd == -1)
480 480 return (-1);
481 481 if (pid != NULL) {
482 482 if (get_client_ident(connfd, pid, locale, locale_len, flagsp)
483 483 == -1) {
484 484 (void) shutdown(connfd, SHUT_RDWR);
485 485 (void) close(connfd);
486 486 return (-1);
487 487 }
488 488 (void) write(connfd, "OK\n", 3);
489 489 }
490 490
491 491 flags = fcntl(connfd, F_GETFL, 0);
492 492 if (flags != -1)
493 493 (void) fcntl(connfd, F_SETFL, flags | O_NONBLOCK | FD_CLOEXEC);
494 494
495 495 return (connfd);
496 496 }
497 497
498 498 static void
499 499 reject_client(int servfd, pid_t clientpid)
500 500 {
501 501 int connfd;
502 502 struct sockaddr_un cliaddr;
503 503 socklen_t clilen;
504 504 char nak[MAXPATHLEN];
505 505
506 506 clilen = sizeof (cliaddr);
507 507 connfd = accept(servfd, (struct sockaddr *)&cliaddr, &clilen);
508 508
509 509 /*
510 510 * After getting its ident string, tell client to get lost.
511 511 */
512 512 if (get_client_ident(connfd, NULL, NULL, 0, NULL) == 0) {
513 513 (void) snprintf(nak, sizeof (nak), "%lu\n",
514 514 clientpid);
515 515 (void) write(connfd, nak, strlen(nak));
516 516 }
517 517 (void) shutdown(connfd, SHUT_RDWR);
518 518 (void) close(connfd);
519 519 }
520 520
521 521 static int
522 522 accept_socket(int servfd, pid_t verpid)
523 523 {
524 524 int connfd;
525 525 struct sockaddr_un cliaddr;
526 526 socklen_t clilen = sizeof (cliaddr);
527 527 ucred_t *cred = NULL;
528 528 pid_t rpid = -1;
529 529 int flags;
530 530
531 531 connfd = accept(servfd, (struct sockaddr *)&cliaddr, &clilen);
532 532 if (connfd == -1)
533 533 return (-1);
534 534
535 535 /* Confirm connecting process is who we expect */
536 536 if (getpeerucred(connfd, &cred) == 0) {
537 537 rpid = ucred_getpid((const ucred_t *)cred);
538 538 ucred_free(cred);
539 539 }
540 540 if (rpid == -1 || rpid != verpid) {
541 541 (void) shutdown(connfd, SHUT_RDWR);
542 542 (void) close(connfd);
543 543 return (-1);
544 544 }
545 545
546 546 flags = fcntl(connfd, F_GETFL, 0);
547 547 if (flags != -1)
548 548 (void) fcntl(connfd, F_SETFL, flags | O_NONBLOCK | FD_CLOEXEC);
549 549
550 550 return (connfd);
551 551 }
552 552
553 553 static void
554 554 ctlcmd_process(int sockfd, int stdoutfd, unsigned int *flags)
555 555 {
556 556 char buf[BUFSIZ];
557 557 int i;
558 558 for (i = 0; i < BUFSIZ-1; i++) {
559 559 char c;
560 560 if (read(sockfd, &c, 1) != 1 ||
561 561 c == '\n' || c == '\0') {
562 562 break;
563 563 }
564 564 buf[i] = c;
565 565 }
566 566 if (i == 0) {
567 567 goto fail;
568 568 }
569 569 buf[i+1] = '\0';
570 570
571 571 if (strncmp(buf, "TIOCSWINSZ ", 11) == 0) {
572 572 char *next = buf + 11;
573 573 struct winsize ws;
574 574 errno = 0;
575 575 ws.ws_row = strtol(next, &next, 10);
576 576 if (errno == EINVAL) {
577 577 goto fail;
578 578 }
579 579 ws.ws_col = strtol(next + 1, &next, 10);
580 580 if (errno == EINVAL) {
581 581 goto fail;
582 582 }
583 583 if (ioctl(stdoutfd, TIOCSWINSZ, &ws) == 0) {
584 584 (void) write(sockfd, "OK\n", 3);
585 585 return;
586 586 }
587 587 }
588 588 if (strncmp(buf, "SETFLAGS ", 9) == 0) {
589 589 char *next = buf + 9;
590 590 unsigned int result;
591 591 errno = 0;
592 592 result = strtoul(next, &next, 10);
593 593 if (errno == EINVAL) {
594 594 goto fail;
595 595 }
596 596 *flags = result;
597 597 (void) write(sockfd, "OK\n", 3);
598 598 return;
599 599 }
600 600 fail:
601 601 (void) write(sockfd, "FAIL\n", 5);
602 602 }
603 603
604 604 /*
605 605 * Check to see if the client at the other end of the socket is still alive; we
606 606 * know it is not if it throws EPIPE at us when we try to write an otherwise
607 607 * harmless 0-length message to it.
608 608 */
609 609 static int
610 610 test_client(int clifd)
611 611 {
612 612 if ((write(clifd, "", 0) == -1) && errno == EPIPE)
613 613 return (-1);
614 614 return (0);
615 615 }
616 616
617 617 /*
618 618 * Modify the input string with json escapes. Since the destination can thus
619 619 * be larger than the source, it may get truncated, although we do use a
620 620 * larger buffer.
621 621 */
622 622 static void
623 623 escape_json(char *sbuf, int slen, char *dbuf, int dlen)
624 624 {
625 625 int i;
626 626 mbstate_t mbr;
627 627 wchar_t c;
628 628 size_t sz;
629 629
630 630 bzero(&mbr, sizeof (mbr));
631 631
632 632 sbuf[slen] = '\0';
633 633 i = 0;
634 634 while (i < dlen && (sz = mbrtowc(&c, sbuf, MB_CUR_MAX, &mbr)) > 0) {
635 635 switch (c) {
636 636 case '\\':
637 637 dbuf[i++] = '\\';
638 638 dbuf[i++] = '\\';
639 639 break;
640 640
641 641 case '"':
642 642 dbuf[i++] = '\\';
643 643 dbuf[i++] = '"';
644 644 break;
645 645
646 646 case '\b':
647 647 dbuf[i++] = '\\';
648 648 dbuf[i++] = 'b';
649 649 break;
650 650
651 651 case '\f':
652 652 dbuf[i++] = '\\';
653 653 dbuf[i++] = 'f';
654 654 break;
655 655
656 656 case '\n':
657 657 dbuf[i++] = '\\';
658 658 dbuf[i++] = 'n';
659 659 break;
660 660
661 661 case '\r':
662 662 dbuf[i++] = '\\';
663 663 dbuf[i++] = 'r';
664 664 break;
665 665
666 666 case '\t':
667 667 dbuf[i++] = '\\';
668 668 dbuf[i++] = 't';
669 669 break;
670 670
671 671 default:
672 672 if ((c >= 0x00 && c <= 0x1f) ||
673 673 (c > 0x7f && c <= 0xffff)) {
674 674
675 675 i += snprintf(&dbuf[i], (dlen - i), "\\u%04x",
676 676 (int)(0xffff & c));
677 677 } else if (c >= 0x20 && c <= 0x7f) {
678 678 dbuf[i++] = 0xff & c;
679 679 }
680 680
681 681 break;
682 682 }
683 683 sbuf += sz;
684 684 }
685 685
686 686 if (i == dlen)
687 687 dbuf[--i] = '\0';
688 688 else
689 689 dbuf[i] = '\0';
690 690 }
691 691
692 692 /*
693 693 * We output to the log file as json.
694 694 * ex. for string 'msg\n' on the zone's stdout:
695 695 * {"log":"msg\n","stream":"stdout","time":"2014-10-24T20:12:11.101973117Z"}
696 696 *
697 697 * We use ns in the last field of the timestamp for compatability.
698 698 *
699 699 * We keep track of the size of the log file and rotate it when we exceed
700 700 * the log size limit (if one is set).
701 701 */
702 702 static void
703 703 wr_log_msg(char *buf, int len, int from)
704 704 {
705 705 struct timeval tv;
706 706 int olen;
707 707 char ts[64];
708 708 char nbuf[BUFSIZ * 2];
709 709 char obuf[BUFSIZ * 2];
710 710 static boolean_t log_wr_err = B_FALSE;
711 711
712 712 if (logfd == -1)
713 713 return;
714 714
715 715 escape_json(buf, len, nbuf, sizeof (nbuf));
716 716
717 717 if (gettimeofday(&tv, NULL) != 0)
718 718 return;
719 719 (void) strftime(ts, sizeof (ts), "%FT%T", gmtime(&tv.tv_sec));
720 720
721 721 olen = snprintf(obuf, sizeof (obuf),
722 722 "{\"log\":\"%s\",\"stream\":\"%s\",\"time\":\"%s.%ldZ\"}\n",
723 723 nbuf, (from == 1) ? "stdout" : "stderr", ts, tv.tv_usec * 1000);
724 724
725 725 if (write(logfd, obuf, olen) != olen) {
726 726 if (!log_wr_err) {
727 727 zerror(zlogp, B_TRUE, "log file write error");
728 728 log_wr_err = B_TRUE;
729 729 }
730 730 return;
731 731 }
732 732
733 733 log_sz += olen;
734 734 if (log_rot_sz > 0 && log_sz >= log_rot_sz)
735 735 rotate_log();
736 736 }
737 737
738 738 /*
739 739 * We want to sleep for a little while but need to be responsive if the zone is
740 740 * halting. We poll/sleep on the event stream so we can notice if we're halting.
741 741 * Return true if halting, otherwise false.
742 742 */
743 743 static boolean_t
744 744 halt_sleep(int slptime)
745 745 {
746 746 struct pollfd evfd[1];
747 747
748 748 evfd[0].fd = eventstream[1];
749 749 evfd[0].events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI;
750 750
751 751 if (poll(evfd, 1, slptime) > 0) {
752 752 /* zone halting */
753 753 return (B_TRUE);
754 754 }
755 755 return (B_FALSE);
756 756 }
757 757
758 758 /*
759 759 * This routine drives the logging and interactive I/O loop. It polls for
760 760 * input from the zone side of the fd (output to stdout/stderr), and from the
761 761 * client (input to the zone's stdin). Additionally, it polls on the server
762 762 * fd, and disconnects any clients that might try to hook up with the zone
763 763 * while the fd's are in use.
764 764 *
765 765 * Data from the zone's stdout and stderr is formatted in json and written to
766 766 * the log file whether an interactive client is connected or not.
767 767 *
768 768 * When the client first calls us up, it is expected to send a line giving its
769 769 * "identity"; this consists of the string 'IDENT <pid> <locale>'. This is so
770 770 * that we can report that the fd's are busy, along with some diagnostics
771 771 * about who has them busy; the locale is ignore here but kept for compatability
772 772 * with the zlogin code when running on the zone's console.
773 773 *
774 774 * We need to handle the case where there is no server within the zone (or
775 775 * the server gets stuck) and data that we're writing to the zone server's
776 776 * stdin fills the pipe. Because of the way the zfd device works writes can
777 777 * flow into the stream and simply be dropped, if there is no server, or writes
778 778 * could return -1 with EAGAIN if the server is stuck. Since we ignore errors
779 779 * on the write to stdin, we won't get blocked in that case but we'd like to
780 780 * avoid dropping initial input if the server within the zone hasn't started
781 781 * yet. To handle this we wait to read initial input until we detect that there
782 782 * is a server inside the zone. We have to poll for this so that we can
783 783 * re-run the ioctl to notice when a server shows up. This poll/wait is handled
784 784 * by halt_sleep() so that we can be responsive if the zone wants to halt.
785 785 * We only do this check to avoid dropping initial input so it is possible for
786 786 * the server within the zone to go away later. At that point zfd will just
787 787 * drop any new input flowing into the stream.
788 788 */
789 789 static void
790 790 do_zfd_io(int gzctlfd, int gzservfd, int gzerrfd, int stdinfd, int stdoutfd,
791 791 int stderrfd)
792 792 {
793 793 struct pollfd pollfds[8];
794 794 char ibuf[BUFSIZ + 1];
795 795 int cc, ret;
796 796 int ctlfd = -1;
797 797 int clifd = -1;
798 798 int clierrfd = -1;
799 799 int pollerr = 0;
800 800 char clilocale[MAXPATHLEN];
801 801 pid_t clipid = 0;
802 802 uint_t flags = 0;
803 803 boolean_t stdin_ready = B_FALSE;
804 804 int slptime = 250; /* initial poll sleep time in ms */
805 805
806 806 /* client control socket, watch for read events */
807 807 pollfds[0].fd = ctlfd;
808 808 pollfds[0].events = POLLIN | POLLRDNORM | POLLRDBAND |
809 809 POLLPRI | POLLERR | POLLHUP | POLLNVAL;
810 810
811 811 /* client socket, watch for read events */
812 812 pollfds[1].fd = clifd;
813 813 pollfds[1].events = pollfds[0].events;
814 814
815 815 /* stdout, watch for read events */
816 816 pollfds[2].fd = stdoutfd;
817 817 pollfds[2].events = pollfds[0].events;
818 818
819 819 /* stderr, watch for read events */
820 820 pollfds[3].fd = stderrfd;
821 821 pollfds[3].events = pollfds[0].events;
822 822
823 823 /* the server control socket; watch for new connections */
824 824 pollfds[4].fd = gzctlfd;
825 825 pollfds[4].events = POLLIN | POLLRDNORM;
826 826
827 827 /* the server stdin/out socket; watch for new connections */
828 828 pollfds[5].fd = gzservfd;
829 829 pollfds[5].events = POLLIN | POLLRDNORM;
830 830
831 831 /* the server stderr socket; watch for new connections */
832 832 pollfds[6].fd = gzerrfd;
833 833 pollfds[6].events = POLLIN | POLLRDNORM;
834 834
835 835 /* the eventstream; any input means the zone is halting */
836 836 pollfds[7].fd = eventstream[1];
837 837 pollfds[7].events = pollfds[0].events;
838 838
839 839 while (!shutting_down) {
840 840 pollfds[0].revents = pollfds[1].revents = 0;
841 841 pollfds[2].revents = pollfds[3].revents = 0;
842 842 pollfds[4].revents = pollfds[5].revents = 0;
843 843 pollfds[6].revents = pollfds[7].revents = 0;
844 844
845 845 ret = poll(pollfds, 8, -1);
846 846 if (ret == -1 && errno != EINTR) {
847 847 zerror(zlogp, B_TRUE, "poll failed");
848 848 /* we are hosed, close connection */
849 849 break;
850 850 }
851 851
852 852 /* control events from client */
853 853 if (pollfds[0].revents &
854 854 (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)) {
855 855 /* process control message */
856 856 ctlcmd_process(ctlfd, stdoutfd, &flags);
857 857 } else if (pollfds[0].revents) {
858 858 /* bail if any error occurs */
859 859 pollerr = pollfds[0].revents;
860 860 zerror(zlogp, B_FALSE, "closing connection "
861 861 "with control channel, pollerr %d\n", pollerr);
862 862 break;
863 863 }
864 864
865 865 /* event from client side */
866 866 if (pollfds[1].revents) {
867 867 if (stdin_ready) {
868 868 if (pollfds[1].revents & (POLLIN |
869 869 POLLRDNORM | POLLRDBAND | POLLPRI)) {
870 870 errno = 0;
871 871 cc = read(clifd, ibuf, BUFSIZ);
872 872 if (cc > 0) {
873 873 /*
874 874 * See comment for this
875 875 * function on what happens if
876 876 * there is no reader in the
877 877 * zone. EOF is handled below.
878 878 */
879 879 (void) write(stdinfd, ibuf, cc);
880 880 }
881 881 } else if (pollfds[1].revents & (POLLERR |
882 882 POLLNVAL)) {
883 883 pollerr = pollfds[1].revents;
884 884 zerror(zlogp, B_FALSE,
885 885 "closing connection "
886 886 "with client, pollerr %d\n",
887 887 pollerr);
888 888 break;
889 889 }
890 890
891 891 if (pollfds[1].revents & POLLHUP) {
892 892 if (flags & ZLOGIN_ZFD_EOF) {
893 893 /*
894 894 * Let the client know. We've
895 895 * already serviced any pending
896 896 * regular input. Let the
897 897 * stream clear since the EOF
898 898 * ioctl jumps to the head.
899 899 */
900 900 (void) ioctl(stdinfd, I_FLUSH);
901 901 if (halt_sleep(250))
902 902 break;
903 903 (void) ioctl(stdinfd, ZFD_EOF);
904 904 }
905 905 break;
906 906 }
907 907 } else {
908 908 if (ioctl(stdinfd, ZFD_HAS_SLAVE) == 0) {
909 909 stdin_ready = B_TRUE;
910 910 } else {
911 911 /*
912 912 * There is nothing in the zone to read
913 913 * our input. Presumably the user
914 914 * providing input expects something to
915 915 * show up, but that is no guarantee.
916 916 * Since we haven't serviced the pending
917 917 * input poll yet, we don't want to
918 918 * immediately loop around but we also
919 919 * need to be responsive if the zone is
920 920 * halting.
921 921 */
922 922 if (halt_sleep(slptime))
923 923 break;
924 924
925 925 if (slptime < 5000)
926 926 slptime += 250;
927 927 }
928 928 }
929 929 }
930 930
931 931 /* event from the zone's stdout */
932 932 if (pollfds[2].revents) {
933 933 if (pollfds[2].revents &
934 934 (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)) {
935 935 errno = 0;
936 936 cc = read(stdoutfd, ibuf, BUFSIZ);
937 937 if (cc <= 0 && (errno != EINTR) &&
938 938 (errno != EAGAIN))
939 939 break;
940 940 if (cc > 0) {
941 941 wr_log_msg(ibuf, cc, 1);
942 942
943 943 /*
944 944 * Lose output if no one is listening,
945 945 * otherwise pass it on.
946 946 */
947 947 if (clifd != -1)
948 948 (void) write(clifd, ibuf, cc);
949 949 }
950 950 } else {
951 951 pollerr = pollfds[2].revents;
952 952 zerror(zlogp, B_FALSE,
953 953 "closing connection with stdout zfd, "
954 954 "pollerr %d\n", pollerr);
955 955 break;
956 956 }
957 957 }
958 958
959 959 /* event from the zone's stderr */
960 960 if (pollfds[3].revents) {
961 961 if (pollfds[3].revents &
962 962 (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)) {
963 963 errno = 0;
964 964 cc = read(stderrfd, ibuf, BUFSIZ);
965 965 if (cc <= 0 && (errno != EINTR) &&
966 966 (errno != EAGAIN))
967 967 break;
968 968 if (cc > 0) {
969 969 wr_log_msg(ibuf, cc, 2);
970 970
971 971 /*
972 972 * Lose output if no one is listening,
973 973 * otherwise pass it on.
974 974 */
975 975 if (clierrfd != -1)
976 976 (void) write(clierrfd, ibuf,
977 977 cc);
978 978 }
979 979 } else {
980 980 pollerr = pollfds[3].revents;
981 981 zerror(zlogp, B_FALSE,
982 982 "closing connection with stderr zfd, "
983 983 "pollerr %d\n", pollerr);
984 984 break;
985 985 }
986 986 }
987 987
988 988 /* connect event from server control socket */
989 989 if (pollfds[4].revents) {
990 990 if (ctlfd != -1) {
991 991 /*
992 992 * Test the client to see if it is really
993 993 * still alive. If it has died but we
994 994 * haven't yet detected that, we might
995 995 * deny a legitimate connect attempt. If it
996 996 * is dead, we break out; once we tear down
997 997 * the old connection, the new connection
998 998 * will happen.
999 999 */
1000 1000 if (test_client(ctlfd) == -1) {
1001 1001 break;
1002 1002 }
1003 1003 /* we're already handling a client */
1004 1004 reject_client(gzctlfd, clipid);
1005 1005 } else {
1006 1006 ctlfd = accept_client(gzctlfd, &clipid,
1007 1007 clilocale, sizeof (clilocale), &flags);
1008 1008 if (ctlfd != -1) {
1009 1009 pollfds[0].fd = ctlfd;
1010 1010 } else {
1011 1011 break;
1012 1012 }
1013 1013 }
1014 1014 }
1015 1015
1016 1016 /* connect event from server stdin/out socket */
1017 1017 if (pollfds[5].revents) {
1018 1018 if (ctlfd == -1) {
1019 1019 /*
1020 1020 * This shouldn't happen since the client is
1021 1021 * expected to connect on the control socket
1022 1022 * first. If we see this, tear everything down
1023 1023 * and start over.
1024 1024 */
1025 1025 zerror(zlogp, B_FALSE, "GZ zfd stdin/stdout "
1026 1026 "connection attempt with no GZ control\n");
1027 1027 break;
1028 1028 }
1029 1029 assert(clifd == -1);
1030 1030 if ((clifd = accept_socket(gzservfd, clipid)) != -1) {
1031 1031 /* No need to watch for other new connections */
1032 1032 pollfds[5].fd = -1;
1033 1033 /* Client input is of interest, though */
1034 1034 pollfds[1].fd = clifd;
1035 1035 } else {
1036 1036 break;
1037 1037 }
1038 1038 }
1039 1039
1040 1040 /* connection event from server stderr socket */
1041 1041 if (pollfds[6].revents) {
1042 1042 if (ctlfd == -1) {
1043 1043 /*
1044 1044 * Same conditions apply to stderr as stdin/out.
1045 1045 */
1046 1046 zerror(zlogp, B_FALSE, "GZ zfd stderr "
1047 1047 "connection attempt with no GZ control\n");
1048 1048 break;
1049 1049 }
1050 1050 assert(clierrfd == -1);
1051 1051 if ((clierrfd = accept_socket(gzerrfd, clipid)) != -1) {
1052 1052 /* No need to watch for other new connections */
1053 1053 pollfds[6].fd = -1;
1054 1054 } else {
1055 1055 break;
1056 1056 }
1057 1057 }
1058 1058
1059 1059 /*
1060 1060 * Watch for events on the eventstream. This is how we get
1061 1061 * notified of the zone halting, etc. It provides us a
1062 1062 * "wakeup" from poll when important things happen, which
1063 1063 * is good.
1064 1064 */
1065 1065 if (pollfds[7].revents) {
1066 1066 break;
1067 1067 }
1068 1068 }
1069 1069
1070 1070 if (clifd != -1) {
1071 1071 (void) shutdown(clifd, SHUT_RDWR);
1072 1072 (void) close(clifd);
1073 1073 }
1074 1074
1075 1075 if (clierrfd != -1) {
1076 1076 (void) shutdown(clierrfd, SHUT_RDWR);
1077 1077 (void) close(clierrfd);
1078 1078 }
1079 1079 }
1080 1080
1081 1081 static int
1082 1082 open_fd(zlog_t *zlogp, int id, int rw)
1083 1083 {
1084 1084 int fd;
1085 1085 int flag = O_NONBLOCK | O_NOCTTY | O_CLOEXEC;
1086 1086 int retried = 0;
1087 1087 char stdpath[MAXPATHLEN];
1088 1088
1089 1089 (void) snprintf(stdpath, sizeof (stdpath), "/dev/zfd/%s/master/%d",
1090 1090 zone_name, id);
1091 1091 flag |= rw;
1092 1092
1093 1093 while (!shutting_down) {
1094 1094 if ((fd = open(stdpath, flag)) != -1) {
1095 1095 /*
1096 1096 * Setting RPROTDIS on the stream means that the
1097 1097 * control portion of messages received (which we don't
1098 1098 * care about) will be discarded by the stream head. If
1099 1099 * we allowed such messages, we wouldn't be able to use
1100 1100 * read(2), as it fails (EBADMSG) when a message with a
1101 1101 * control element is received.
1102 1102 */
1103 1103 if (ioctl(fd, I_SRDOPT, RNORM|RPROTDIS) == -1) {
1104 1104 zerror(zlogp, B_TRUE,
1105 1105 "failed to set options on zfd");
1106 1106 return (-1);
1107 1107 }
1108 1108 return (fd);
1109 1109 }
1110 1110
1111 1111 if (retried++ > 60)
1112 1112 break;
1113 1113
1114 1114 (void) sleep(1);
1115 1115 }
1116 1116
1117 1117 zerror(zlogp, B_TRUE, "failed to open zfd");
1118 1118 return (-1);
1119 1119 }
1120 1120
1121 1121 static void
1122 1122 open_logfile()
1123 1123 {
1124 1124 char logpath[MAXPATHLEN];
1125 1125
1126 1126 logfd = -1;
1127 1127 log_sz = 0;
1128 1128
1129 1129 (void) snprintf(logpath, sizeof (logpath), "%s/logs", zonepath);
1130 1130 (void) mkdir(logpath, 0700);
1131 1131
1132 1132 (void) snprintf(logpath, sizeof (logpath), "%s/logs/%s", zonepath,
1133 1133 LOGNAME);
1134 1134
1135 1135 if ((logfd = open(logpath, O_WRONLY | O_APPEND | O_CREAT,
1136 1136 0600)) == -1) {
1137 1137 zerror(zlogp, B_TRUE, "failed to open log file");
1138 1138 } else {
1139 1139 struct stat64 sb;
1140 1140
1141 1141 if (fstat64(logfd, &sb) == 0)
1142 1142 log_sz = sb.st_size;
1143 1143 }
1144 1144 }
1145 1145
1146 1146 static void
1147 1147 rotate_log()
1148 1148 {
1149 1149 time_t t;
1150 1150 struct tm gtm;
1151 1151 char onm[MAXPATHLEN], rnm[MAXPATHLEN];
1152 1152
1153 1153 if ((t = time(NULL)) == (time_t)-1 || gmtime_r(&t, >m) == NULL) {
1154 1154 zerror(zlogp, B_TRUE, "failed to format time");
1155 1155 return;
1156 1156 }
1157 1157
1158 1158 (void) snprintf(rnm, sizeof (rnm),
1159 1159 "%s/logs/%s.%d%02d%02dT%02d%02d%02dZ",
1160 1160 zonepath, LOGNAME, gtm.tm_year + 1900, gtm.tm_mon + 1, gtm.tm_mday,
1161 1161 gtm.tm_hour, gtm.tm_min, gtm.tm_sec);
1162 1162 (void) snprintf(onm, sizeof (onm), "%s/logs/%s", zonepath, LOGNAME);
1163 1163
1164 1164 (void) close(logfd);
1165 1165 if (rename(onm, rnm) != 0)
1166 1166 zerror(zlogp, B_TRUE, "failed to rotate log file");
1167 1167 open_logfile();
1168 1168 }
1169 1169
1170 1170
1171 1171 /* ARGSUSED */
1172 1172 void
1173 1173 hup_handler(int i)
1174 1174 {
1175 1175 if (logfd != -1) {
1176 1176 (void) close(logfd);
1177 1177 open_logfile();
1178 1178 }
1179 1179 }
1180 1180
1181 1181 /*
1182 1182 * Body of the worker thread to log the zfd's stdout and stderr to a log file
1183 1183 * and to perform interactive IO to the stdin, stdout and stderr zfd's.
1184 1184 *
1185 1185 * The stdin, stdout and stderr are from the perspective of the process inside
1186 1186 * the zone, so the zoneadmd view is opposite (i.e. we write to the stdin fd
1187 1187 * and read from the stdout/stderr fds).
1188 1188 */
1189 1189 static void
1190 1190 srvr(void *modearg)
1191 1191 {
1192 1192 zfd_mode_t *mode = (zfd_mode_t *)modearg;
1193 1193 int gzctlfd = -1;
1194 1194 int gzoutfd = -1;
1195 1195 int stdinfd = -1;
1196 1196 int stdoutfd = -1;
1197 1197 sigset_t blockset;
1198 1198 int gzerrfd = -1;
1199 1199 int stderrfd = -1;
1200 1200 int flags;
|
↓ open down ↓ |
1200 lines elided |
↑ open up ↑ |
1201 1201 int len;
1202 1202 char ibuf[BUFSIZ + 1];
1203 1203
1204 1204 if (!shutting_down && mode->zmode_gzlogging)
1205 1205 open_logfile();
1206 1206
1207 1207 /*
1208 1208 * This thread should receive SIGHUP so that it can close the log
1209 1209 * file, and reopen it, during log rotation.
1210 1210 */
1211 - sigset(SIGHUP, hup_handler);
1211 + (void) sigset(SIGHUP, hup_handler);
1212 1212 (void) sigfillset(&blockset);
1213 1213 (void) sigdelset(&blockset, SIGHUP);
1214 1214 (void) thr_sigsetmask(SIG_BLOCK, &blockset, NULL);
1215 1215
1216 1216 if (!shutting_down) {
1217 1217 if (pipe(eventstream) != 0) {
1218 1218 zerror(zlogp, B_TRUE, "failed to open logger control "
1219 1219 "pipe");
1220 1220 return;
1221 1221 }
1222 1222 }
1223 1223
1224 1224 while (!shutting_down) {
1225 1225 if (init_server_sock(zlogp, &gzctlfd, "ctl") == -1) {
1226 1226 zerror(zlogp, B_FALSE,
1227 1227 "server setup: control socket init failed");
1228 1228 goto death;
1229 1229 }
1230 1230 if (init_server_sock(zlogp, &gzoutfd, "out") == -1) {
1231 1231 zerror(zlogp, B_FALSE,
1232 1232 "server setup: stdout socket init failed");
1233 1233 goto death;
1234 1234 }
1235 1235 if (init_server_sock(zlogp, &gzerrfd, "err") == -1) {
1236 1236 zerror(zlogp, B_FALSE,
1237 1237 "server setup: stderr socket init failed");
1238 1238 goto death;
1239 1239 }
1240 1240
1241 1241 if (mode->zmode_n_stddevs == 1) {
1242 1242 if ((stdinfd = open_fd(zlogp, 0, O_RDWR)) == -1) {
1243 1243 goto death;
1244 1244 }
1245 1245 stdoutfd = stdinfd;
1246 1246 } else {
1247 1247 if ((stdinfd = open_fd(zlogp, 0, O_WRONLY)) == -1 ||
1248 1248 (stdoutfd = open_fd(zlogp, 1, O_RDONLY)) == -1 ||
1249 1249 (stderrfd = open_fd(zlogp, 2, O_RDONLY)) == -1) {
1250 1250 goto death;
1251 1251 }
1252 1252 }
1253 1253
1254 1254 do_zfd_io(gzctlfd, gzoutfd, gzerrfd, stdinfd, stdoutfd,
1255 1255 stderrfd);
1256 1256 death:
1257 1257 destroy_server_sock(gzctlfd, "ctl");
1258 1258 destroy_server_sock(gzoutfd, "out");
1259 1259 destroy_server_sock(gzerrfd, "err");
1260 1260
1261 1261 /* when shutting down, leave open until drained */
1262 1262 if (!shutting_down) {
1263 1263 (void) close(stdinfd);
1264 1264 if (mode->zmode_n_stddevs == 3) {
1265 1265 (void) close(stdoutfd);
1266 1266 (void) close(stderrfd);
1267 1267 }
1268 1268 }
1269 1269 }
1270 1270
1271 1271 /*
1272 1272 * Attempt to drain remaining log output from the zone prior to closing
1273 1273 * the file descriptors. This helps ensure that complete logs are
1274 1274 * captured during shutdown.
1275 1275 */
1276 1276 flags = fcntl(stdoutfd, F_GETFL, 0);
1277 1277 if (fcntl(stdoutfd, F_SETFL, flags | O_NONBLOCK) != -1) {
1278 1278 while ((len = read(stdoutfd, ibuf, BUFSIZ)) > 0)
1279 1279 wr_log_msg(ibuf, len, 1);
1280 1280 }
1281 1281 (void) close(stdoutfd);
1282 1282
1283 1283 if (mode->zmode_n_stddevs > 1) {
1284 1284 (void) close(stdinfd);
1285 1285 flags = fcntl(stderrfd, F_GETFL, 0);
1286 1286 if (fcntl(stderrfd, F_SETFL, flags | O_NONBLOCK) != -1) {
1287 1287 while ((len = read(stderrfd, ibuf, BUFSIZ)) > 0)
1288 1288 wr_log_msg(ibuf, len, 2);
1289 1289 }
1290 1290 (void) close(stderrfd);
1291 1291 }
1292 1292
1293 1293
1294 1294 (void) close(eventstream[0]);
1295 1295 eventstream[0] = -1;
1296 1296 (void) close(eventstream[1]);
1297 1297 eventstream[1] = -1;
1298 1298 if (logfd != -1)
1299 1299 (void) close(logfd);
1300 1300 }
1301 1301
1302 1302 /*
1303 1303 * The meaning of the original legacy values for the zlog-mode evolved over
1304 1304 * time, to the point where the old names no longer made sense. The current
1305 1305 * values are simply positional letters used to indicate various capabilities.
1306 1306 * The following table shows the meaning of the mode values, along with the
1307 1307 * legacy name which we continue to support for compatability. Any future
1308 1308 * capability can add a letter to the left and '-' is implied for existing
1309 1309 * strings.
1310 1310 *
1311 1311 * zlog-mode gz log - tty - ngz log
1312 1312 * --------- ------ --- -------
1313 1313 * gt- (int) y y n
1314 1314 * g-- (log) y n n
1315 1315 * gtn (nlint) y y y
1316 1316 * g-n (nolog) y n y
1317 1317 * -t- n y n
1318 1318 * --- n n n
1319 1319 *
1320 1320 * This function also obtains a maximum log size while it is reading the
1321 1321 * zone configuration.
1322 1322 */
1323 1323 static void
1324 1324 get_mode_logmax(zfd_mode_t *mode)
1325 1325 {
1326 1326 zone_dochandle_t handle;
1327 1327 struct zone_attrtab attr;
1328 1328
1329 1329 bzero(mode, sizeof (zfd_mode_t));
1330 1330
1331 1331 if ((handle = zonecfg_init_handle()) == NULL)
1332 1332 return;
1333 1333
1334 1334 if (zonecfg_get_handle(zone_name, handle) != Z_OK)
1335 1335 goto done;
1336 1336
1337 1337 if (zonecfg_setattrent(handle) != Z_OK)
1338 1338 goto done;
1339 1339 while (zonecfg_getattrent(handle, &attr) == Z_OK) {
1340 1340 if (strcmp(ZLOG_MODE, attr.zone_attr_name) == 0) {
1341 1341 if (strcmp("g--", attr.zone_attr_value) == 0 ||
1342 1342 strncmp("log", attr.zone_attr_value, 3) == 0) {
1343 1343 mode->zmode_gzlogging = B_TRUE;
1344 1344 mode->zmode_n_stddevs = 3;
1345 1345 mode->zmode_n_addl_devs = 0;
1346 1346 } else if (strcmp("g-n", attr.zone_attr_value) == 0 ||
1347 1347 strncmp("nolog", attr.zone_attr_value, 5) == 0) {
1348 1348 mode->zmode_gzlogging = B_TRUE;
1349 1349 mode->zmode_n_stddevs = 3;
1350 1350 mode->zmode_n_addl_devs = 2;
1351 1351 } else if (strcmp("gt-", attr.zone_attr_value) == 0 ||
1352 1352 strncmp("int", attr.zone_attr_value, 3) == 0) {
1353 1353 mode->zmode_gzlogging = B_TRUE;
1354 1354 mode->zmode_n_stddevs = 1;
1355 1355 mode->zmode_n_addl_devs = 0;
1356 1356 } else if (strcmp("gtn", attr.zone_attr_value) == 0 ||
1357 1357 strncmp("nlint", attr.zone_attr_value, 5) == 0) {
1358 1358 mode->zmode_gzlogging = B_TRUE;
1359 1359 mode->zmode_n_stddevs = 1;
1360 1360 mode->zmode_n_addl_devs = 1;
1361 1361 } else if (strcmp("-t-", attr.zone_attr_value) == 0) {
1362 1362 mode->zmode_gzlogging = B_FALSE;
1363 1363 mode->zmode_n_stddevs = 1;
1364 1364 mode->zmode_n_addl_devs = 0;
1365 1365 } else if (strcmp("---", attr.zone_attr_value) == 0) {
1366 1366 mode->zmode_gzlogging = B_FALSE;
1367 1367 mode->zmode_n_stddevs = 3;
1368 1368 mode->zmode_n_addl_devs = 0;
1369 1369 }
1370 1370
1371 1371 } else if (strcmp(LOG_MAXSZ, attr.zone_attr_name) == 0) {
1372 1372 char *p;
1373 1373 long lval;
1374 1374
1375 1375 p = attr.zone_attr_value;
1376 1376 lval = strtol(p, &p, 10);
|
↓ open down ↓ |
155 lines elided |
↑ open up ↑ |
1377 1377 if (*p == '\0')
1378 1378 log_rot_sz = (size_t)lval;
1379 1379 }
1380 1380 }
1381 1381 (void) zonecfg_endattrent(handle);
1382 1382
1383 1383 done:
1384 1384 zonecfg_fini_handle(handle);
1385 1385 }
1386 1386
1387 +/* ARGSUSED -- "id" might be used in the future. */
1387 1388 void
1388 1389 create_log_thread(zlog_t *logp, zoneid_t id)
1389 1390 {
1390 1391 int res;
1391 1392
1392 1393 shutting_down = 0;
1393 1394 zlogp = logp;
1394 1395
1395 1396 get_mode_logmax(&mode);
1396 1397 if (mode.zmode_n_stddevs == 0)
1397 1398 return;
1398 1399
1399 1400 if (init_zfd_devs(zlogp, &mode) == -1) {
1400 1401 zerror(zlogp, B_FALSE,
1401 1402 "zfd setup: device initialization failed");
1402 1403 return;
1403 1404 }
1404 1405
1405 1406 res = thr_create(NULL, 0, (void * (*)(void *))srvr, (void *)&mode, 0,
1406 1407 &logger_tid);
1407 1408 if (res != 0) {
1408 1409 zerror(zlogp, B_FALSE, "error %d creating logger thread", res);
1409 1410 logger_tid = 0;
1410 1411 }
1411 1412 }
1412 1413
1413 1414 void
1414 1415 destroy_log_thread()
1415 1416 {
1416 1417 if (logger_tid != 0) {
1417 1418 int stop = 1;
1418 1419
1419 1420 shutting_down = 1;
1420 1421 /* break out of poll to shutdown */
1421 1422 if (eventstream[0] != -1)
1422 1423 (void) write(eventstream[0], &stop, sizeof (stop));
1423 1424 (void) thr_join(logger_tid, NULL, NULL);
1424 1425 logger_tid = 0;
1425 1426 }
1426 1427
1427 1428 (void) destroy_zfd_devs(zlogp);
1428 1429 }
|
↓ open down ↓ |
32 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX