1/*++ 2/* NAME 3/* trigger_server 3 4/* SUMMARY 5/* skeleton triggered mail subsystem 6/* SYNOPSIS 7/* #include <mail_server.h> 8/* 9/* NORETURN trigger_server_main(argc, argv, service, key, value, ...) 10/* int argc; 11/* char **argv; 12/* void (*service)(char *buf, int len, char *service_name, char **argv); 13/* int key; 14/* DESCRIPTION 15/* This module implements a skeleton for triggered 16/* mail subsystems: mail subsystem programs that wake up on 17/* client request and perform some activity without further 18/* client interaction. This module supports local IPC via FIFOs 19/* and via UNIX-domain sockets. The resulting program expects to be 20/* run from the \fBmaster\fR process. 21/* 22/* trigger_server_main() is the skeleton entry point. It should be 23/* called from the application main program. The skeleton does the 24/* generic command-line options processing, initialization of 25/* configurable parameters, and connection management. 26/* The skeleton never returns. 27/* 28/* Arguments: 29/* .IP "void (*service)(char *buf, int len, char *service_name, char **argv)" 30/* A pointer to a function that is called by the skeleton each time 31/* a client connects to the program's service port. The function is 32/* run after the program has irrevocably dropped its privileges. 33/* The buffer argument specifies the data read from the trigger port; 34/* this data corresponds to one or more trigger requests. 35/* The len argument specifies how much client data is available. 36/* The maximal size of the buffer is specified via the 37/* TRIGGER_BUF_SIZE manifest constant. 38/* The service name argument corresponds to the service name in the 39/* master.cf file. 40/* The argv argument specifies command-line arguments left over 41/* after options processing. 42/* The \fBserver\fR argument provides the following information: 43/* .PP 44/* Optional arguments are specified as a null-terminated (key, value) 45/* list. Keys and expected values are: 46/* .IP "MAIL_SERVER_INT_TABLE (CONFIG_INT_TABLE *)" 47/* A table with configurable parameters, to be loaded from the 48/* global Postfix configuration file. Tables are loaded in the 49/* order as specified, and multiple instances of the same type 50/* are allowed. 51/* .IP "MAIL_SERVER_LONG_TABLE (CONFIG_LONG_TABLE *)" 52/* A table with configurable parameters, to be loaded from the 53/* global Postfix configuration file. Tables are loaded in the 54/* order as specified, and multiple instances of the same type 55/* are allowed. 56/* .IP "MAIL_SERVER_STR_TABLE (CONFIG_STR_TABLE *)" 57/* A table with configurable parameters, to be loaded from the 58/* global Postfix configuration file. Tables are loaded in the 59/* order as specified, and multiple instances of the same type 60/* are allowed. 61/* .IP "MAIL_SERVER_BOOL_TABLE (CONFIG_BOOL_TABLE *)" 62/* A table with configurable parameters, to be loaded from the 63/* global Postfix configuration file. Tables are loaded in the 64/* order as specified, and multiple instances of the same type 65/* are allowed. 66/* .IP "MAIL_SERVER_TIME_TABLE (CONFIG_TIME_TABLE *)" 67/* A table with configurable parameters, to be loaded from the 68/* global Postfix configuration file. Tables are loaded in the 69/* order as specified, and multiple instances of the same type 70/* are allowed. 71/* .IP "MAIL_SERVER_RAW_TABLE (CONFIG_RAW_TABLE *)" 72/* A table with configurable parameters, to be loaded from the 73/* global Postfix configuration file. Tables are loaded in the 74/* order as specified, and multiple instances of the same type 75/* are allowed. Raw parameters are not subjected to $name 76/* evaluation. 77/* .IP "MAIL_SERVER_NINT_TABLE (CONFIG_NINT_TABLE *)" 78/* A table with configurable parameters, to be loaded from the 79/* global Postfix configuration file. Tables are loaded in the 80/* order as specified, and multiple instances of the same type 81/* are allowed. 82/* .IP "MAIL_SERVER_NBOOL_TABLE (CONFIG_NBOOL_TABLE *)" 83/* A table with configurable parameters, to be loaded from the 84/* global Postfix configuration file. Tables are loaded in the 85/* order as specified, and multiple instances of the same type 86/* are allowed. 87/* .IP "MAIL_SERVER_PRE_INIT (void *(char *service_name, char **argv))" 88/* A pointer to a function that is called once 89/* by the skeleton after it has read the global configuration file 90/* and after it has processed command-line arguments, but before 91/* the skeleton has optionally relinquished the process privileges. 92/* .sp 93/* Only the last instance of this parameter type is remembered. 94/* .IP "MAIL_SERVER_POST_INIT (void *(char *service_name, char **argv))" 95/* A pointer to a function that is called once 96/* by the skeleton after it has optionally relinquished the process 97/* privileges, but before servicing client connection requests. 98/* .sp 99/* Only the last instance of this parameter type is remembered. 100/* .IP "MAIL_SERVER_LOOP (int *(char *service_name, char **argv))" 101/* A pointer to function that is executed from 102/* within the event loop, whenever an I/O or timer event has happened, 103/* or whenever nothing has happened for a specified amount of time. 104/* The result value of the function specifies how long to wait until 105/* the next event. Specify -1 to wait for "as long as it takes". 106/* .sp 107/* Only the last instance of this parameter type is remembered. 108/* .IP "MAIL_SERVER_EXIT (void *(char *service_name, char **argv))" 109/* A pointer to function that is executed immediately before normal 110/* process termination. 111/* .sp 112/* Only the last instance of this parameter type is remembered. 113/* .IP "MAIL_SERVER_PRE_ACCEPT (void *(char *service_name, char **argv))" 114/* Function to be executed prior to accepting a new request. 115/* .sp 116/* Only the last instance of this parameter type is remembered. 117/* .IP "MAIL_SERVER_IN_FLOW_DELAY (none)" 118/* Pause $in_flow_delay seconds when no "mail flow control token" 119/* is available. A token is consumed for each connection request. 120/* .IP MAIL_SERVER_SOLITARY 121/* This service must be configured with process limit of 1. 122/* .IP MAIL_SERVER_UNLIMITED 123/* This service must be configured with process limit of 0. 124/* .IP MAIL_SERVER_PRIVILEGED 125/* This service must be configured as privileged. 126/* .IP "MAIL_SERVER_WATCHDOG (int *)" 127/* Override the default 1000s watchdog timeout. The value is 128/* used after command-line and main.cf file processing. 129/* .PP 130/* The var_use_limit variable limits the number of clients that 131/* a server can service before it commits suicide. 132/* This value is taken from the global \fBmain.cf\fR configuration 133/* file. Setting \fBvar_use_limit\fR to zero disables the client limit. 134/* 135/* The var_idle_limit variable limits the time that a service 136/* receives no client connection requests before it commits suicide. 137/* This value is taken from the global \fBmain.cf\fR configuration 138/* file. Setting \fBvar_use_limit\fR to zero disables the idle limit. 139/* DIAGNOSTICS 140/* Problems and transactions are logged to \fBsyslogd\fR(8). 141/* BUGS 142/* Works with FIFO-based services only. 143/* SEE ALSO 144/* master(8), master process 145/* syslogd(8) system logging 146/* LICENSE 147/* .ad 148/* .fi 149/* The Secure Mailer license must be distributed with this software. 150/* AUTHOR(S) 151/* Wietse Venema 152/* IBM T.J. Watson Research 153/* P.O. Box 704 154/* Yorktown Heights, NY 10598, USA 155/*--*/ 156 157/* System library. */ 158 159#include <sys_defs.h> 160#include <sys/socket.h> 161#include <unistd.h> 162#include <signal.h> 163#include <syslog.h> 164#include <stdlib.h> 165#include <limits.h> 166#include <string.h> 167#include <errno.h> 168#include <fcntl.h> 169#include <stdarg.h> 170#ifdef STRCASECMP_IN_STRINGS_H 171#include <strings.h> 172#endif 173#include <time.h> 174 175/* Utility library. */ 176 177#include <msg.h> 178#include <msg_syslog.h> 179#include <msg_vstream.h> 180#include <chroot_uid.h> 181#include <vstring.h> 182#include <vstream.h> 183#include <msg_vstream.h> 184#include <mymalloc.h> 185#include <events.h> 186#include <iostuff.h> 187#include <stringops.h> 188#include <sane_accept.h> 189#include <myflock.h> 190#include <safe_open.h> 191#include <listen.h> 192#include <watchdog.h> 193#include <split_at.h> 194 195/* Global library. */ 196 197#include <mail_params.h> 198#include <mail_task.h> 199#include <debug_process.h> 200#include <mail_conf.h> 201#include <mail_dict.h> 202#include <resolve_local.h> 203#include <mail_flow.h> 204#include <mail_version.h> 205 206/* Process manager. */ 207 208#include "master_proto.h" 209 210/* Application-specific */ 211 212#include "mail_server.h" 213 214 /* 215 * Global state. 216 */ 217static int use_count; 218 219static TRIGGER_SERVER_FN trigger_server_service; 220static char *trigger_server_name; 221static char **trigger_server_argv; 222static void (*trigger_server_accept) (int, char *); 223static void (*trigger_server_onexit) (char *, char **); 224static void (*trigger_server_pre_accept) (char *, char **); 225static VSTREAM *trigger_server_lock; 226static int trigger_server_in_flow_delay; 227static unsigned trigger_server_generation; 228static int trigger_server_watchdog = 1000; 229 230/* trigger_server_exit - normal termination */ 231 232static NORETURN trigger_server_exit(void) 233{ 234 if (trigger_server_onexit) 235 trigger_server_onexit(trigger_server_name, trigger_server_argv); 236 exit(0); 237} 238 239/* trigger_server_abort - terminate after abnormal master exit */ 240 241static void trigger_server_abort(int unused_event, char *unused_context) 242{ 243 if (msg_verbose) 244 msg_info("master disconnect -- exiting"); 245 trigger_server_exit(); 246} 247 248/* trigger_server_timeout - idle time exceeded */ 249 250static void trigger_server_timeout(int unused_event, char *unused_context) 251{ 252 if (msg_verbose) 253 msg_info("idle timeout -- exiting"); 254 trigger_server_exit(); 255} 256 257/* trigger_server_wakeup - wake up application */ 258 259static void trigger_server_wakeup(int fd) 260{ 261 char buf[TRIGGER_BUF_SIZE]; 262 int len; 263 264 /* 265 * Commit suicide when the master process disconnected from us. Don't 266 * drop the already accepted client request after "postfix reload"; that 267 * would be rude. 268 */ 269 if (master_notify(var_pid, trigger_server_generation, MASTER_STAT_TAKEN) < 0) 270 /* void */ ; 271 if (trigger_server_in_flow_delay && mail_flow_get(1) < 0) 272 doze(var_in_flow_delay * 1000000); 273 if ((len = read(fd, buf, sizeof(buf))) >= 0) 274 trigger_server_service(buf, len, trigger_server_name, 275 trigger_server_argv); 276 if (master_notify(var_pid, trigger_server_generation, MASTER_STAT_AVAIL) < 0) 277 trigger_server_abort(EVENT_NULL_TYPE, EVENT_NULL_CONTEXT); 278 if (var_idle_limit > 0) 279 event_request_timer(trigger_server_timeout, (char *) 0, var_idle_limit); 280 /* Avoid integer wrap-around in a persistent process. */ 281 if (use_count < INT_MAX) 282 use_count++; 283} 284 285/* trigger_server_accept_fifo - accept fifo client request */ 286 287static void trigger_server_accept_fifo(int unused_event, char *context) 288{ 289 const char *myname = "trigger_server_accept_fifo"; 290 int listen_fd = CAST_CHAR_PTR_TO_INT(context); 291 292 if (trigger_server_lock != 0 293 && myflock(vstream_fileno(trigger_server_lock), INTERNAL_LOCK, 294 MYFLOCK_OP_NONE) < 0) 295 msg_fatal("select unlock: %m"); 296 297 if (msg_verbose) 298 msg_info("%s: trigger arrived", myname); 299 300 /* 301 * Read whatever the other side wrote into the FIFO. The FIFO read end is 302 * non-blocking so we won't get stuck when multiple processes wake up. 303 */ 304 if (trigger_server_pre_accept) 305 trigger_server_pre_accept(trigger_server_name, trigger_server_argv); 306 trigger_server_wakeup(listen_fd); 307} 308 309/* trigger_server_accept_local - accept socket client request */ 310 311static void trigger_server_accept_local(int unused_event, char *context) 312{ 313 const char *myname = "trigger_server_accept_local"; 314 int listen_fd = CAST_CHAR_PTR_TO_INT(context); 315 int time_left = 0; 316 int fd; 317 318 if (msg_verbose) 319 msg_info("%s: trigger arrived", myname); 320 321 /* 322 * Read a message from a socket. Be prepared for accept() to fail because 323 * some other process already got the connection. The socket is 324 * non-blocking so we won't get stuck when multiple processes wake up. 325 * Don't get stuck when the client connects but sends no data. Restart 326 * the idle timer if this was a false alarm. 327 */ 328 if (var_idle_limit > 0) 329 time_left = event_cancel_timer(trigger_server_timeout, (char *) 0); 330 331 if (trigger_server_pre_accept) 332 trigger_server_pre_accept(trigger_server_name, trigger_server_argv); 333 fd = LOCAL_ACCEPT(listen_fd); 334 if (trigger_server_lock != 0 335 && myflock(vstream_fileno(trigger_server_lock), INTERNAL_LOCK, 336 MYFLOCK_OP_NONE) < 0) 337 msg_fatal("select unlock: %m"); 338 if (fd < 0) { 339 if (errno != EAGAIN) 340 msg_error("accept connection: %m"); 341 if (time_left >= 0) 342 event_request_timer(trigger_server_timeout, (char *) 0, time_left); 343 return; 344 } 345 close_on_exec(fd, CLOSE_ON_EXEC); 346 if (read_wait(fd, 10) == 0) 347 trigger_server_wakeup(fd); 348 else if (time_left >= 0) 349 event_request_timer(trigger_server_timeout, (char *) 0, time_left); 350 close(fd); 351} 352 353#ifdef MASTER_XPORT_NAME_PASS 354 355/* trigger_server_accept_pass - accept descriptor */ 356 357static void trigger_server_accept_pass(int unused_event, char *context) 358{ 359 const char *myname = "trigger_server_accept_pass"; 360 int listen_fd = CAST_CHAR_PTR_TO_INT(context); 361 int time_left = 0; 362 int fd; 363 364 if (msg_verbose) 365 msg_info("%s: trigger arrived", myname); 366 367 /* 368 * Read a message from a socket. Be prepared for accept() to fail because 369 * some other process already got the connection. The socket is 370 * non-blocking so we won't get stuck when multiple processes wake up. 371 * Don't get stuck when the client connects but sends no data. Restart 372 * the idle timer if this was a false alarm. 373 */ 374 if (var_idle_limit > 0) 375 time_left = event_cancel_timer(trigger_server_timeout, (char *) 0); 376 377 if (trigger_server_pre_accept) 378 trigger_server_pre_accept(trigger_server_name, trigger_server_argv); 379 fd = pass_accept(listen_fd); 380 if (trigger_server_lock != 0 381 && myflock(vstream_fileno(trigger_server_lock), INTERNAL_LOCK, 382 MYFLOCK_OP_NONE) < 0) 383 msg_fatal("select unlock: %m"); 384 if (fd < 0) { 385 if (errno != EAGAIN) 386 msg_error("accept connection: %m"); 387 if (time_left >= 0) 388 event_request_timer(trigger_server_timeout, (char *) 0, time_left); 389 return; 390 } 391 close_on_exec(fd, CLOSE_ON_EXEC); 392 if (read_wait(fd, 10) == 0) 393 trigger_server_wakeup(fd); 394 else if (time_left >= 0) 395 event_request_timer(trigger_server_timeout, (char *) 0, time_left); 396 close(fd); 397} 398 399#endif 400 401/* trigger_server_main - the real main program */ 402 403NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,...) 404{ 405 const char *myname = "trigger_server_main"; 406 char *root_dir = 0; 407 char *user_name = 0; 408 int debug_me = 0; 409 int daemon_mode = 1; 410 char *service_name = basename(argv[0]); 411 VSTREAM *stream = 0; 412 int delay; 413 int c; 414 int socket_count = 1; 415 int fd; 416 va_list ap; 417 MAIL_SERVER_INIT_FN pre_init = 0; 418 MAIL_SERVER_INIT_FN post_init = 0; 419 MAIL_SERVER_LOOP_FN loop = 0; 420 int key; 421 char buf[TRIGGER_BUF_SIZE]; 422 int len; 423 char *transport = 0; 424 char *lock_path; 425 VSTRING *why; 426 int alone = 0; 427 int zerolimit = 0; 428 WATCHDOG *watchdog; 429 char *oname_val; 430 char *oname; 431 char *oval; 432 const char *err; 433 char *generation; 434 int msg_vstream_needed = 0; 435 int redo_syslog_init = 0; 436 437 /* 438 * Process environment options as early as we can. 439 */ 440 if (getenv(CONF_ENV_VERB)) 441 msg_verbose = 1; 442 if (getenv(CONF_ENV_DEBUG)) 443 debug_me = 1; 444 445 /* 446 * Don't die when a process goes away unexpectedly. 447 */ 448 signal(SIGPIPE, SIG_IGN); 449 450 /* 451 * Don't die for frivolous reasons. 452 */ 453#ifdef SIGXFSZ 454 signal(SIGXFSZ, SIG_IGN); 455#endif 456 457 /* 458 * May need this every now and then. 459 */ 460 var_procname = mystrdup(basename(argv[0])); 461 set_mail_conf_str(VAR_PROCNAME, var_procname); 462 463 /* 464 * Initialize logging and exit handler. Do the syslog first, so that its 465 * initialization completes before we enter the optional chroot jail. 466 */ 467 msg_syslog_init(mail_task(var_procname), LOG_PID, LOG_FACILITY); 468 if (msg_verbose) 469 msg_info("daemon started"); 470 471 /* 472 * Check the Postfix library version as soon as we enable logging. 473 */ 474 MAIL_VERSION_CHECK; 475 476 /* 477 * Initialize from the configuration file. Allow command-line options to 478 * override compiled-in defaults or configured parameter values. 479 */ 480 mail_conf_suck(); 481 482 /* 483 * Register dictionaries that use higher-level interfaces and protocols. 484 */ 485 mail_dict_init(); 486 487 /* 488 * After database open error, continue execution with reduced 489 * functionality. 490 */ 491 dict_allow_surrogate = 1; 492 493 /* 494 * Pick up policy settings from master process. Shut up error messages to 495 * stderr, because no-one is going to see them. 496 */ 497 opterr = 0; 498 while ((c = GETOPT(argc, argv, "cdDi:lm:n:o:s:St:uvVz")) > 0) { 499 switch (c) { 500 case 'c': 501 root_dir = "setme"; 502 break; 503 case 'd': 504 daemon_mode = 0; 505 break; 506 case 'D': 507 debug_me = 1; 508 break; 509 case 'i': 510 mail_conf_update(VAR_MAX_IDLE, optarg); 511 break; 512 case 'l': 513 alone = 1; 514 break; 515 case 'm': 516 mail_conf_update(VAR_MAX_USE, optarg); 517 break; 518 case 'n': 519 service_name = optarg; 520 break; 521 case 'o': 522 oname_val = mystrdup(optarg); 523 if ((err = split_nameval(oname_val, &oname, &oval)) != 0) 524 msg_fatal("invalid \"-o %s\" option value: %s", optarg, err); 525 mail_conf_update(oname, oval); 526 if (strcmp(oname, VAR_SYSLOG_NAME) == 0) 527 redo_syslog_init = 1; 528 myfree(oname_val); 529 break; 530 case 's': 531 if ((socket_count = atoi(optarg)) <= 0) 532 msg_fatal("invalid socket_count: %s", optarg); 533 break; 534 case 'S': 535 stream = VSTREAM_IN; 536 break; 537 case 't': 538 transport = optarg; 539 break; 540 case 'u': 541 user_name = "setme"; 542 break; 543 case 'v': 544 msg_verbose++; 545 break; 546 case 'V': 547 if (++msg_vstream_needed == 1) 548 msg_vstream_init(mail_task(var_procname), VSTREAM_ERR); 549 break; 550 case 'z': 551 zerolimit = 1; 552 break; 553 default: 554 msg_fatal("invalid option: %c", c); 555 break; 556 } 557 } 558 559 /* 560 * Initialize generic parameters. 561 */ 562 mail_params_init(); 563 if (redo_syslog_init) 564 msg_syslog_init(mail_task(var_procname), LOG_PID, LOG_FACILITY); 565 566 /* 567 * If not connected to stdin, stdin must not be a terminal. 568 */ 569 if (daemon_mode && stream == 0 && isatty(STDIN_FILENO)) { 570 msg_vstream_init(var_procname, VSTREAM_ERR); 571 msg_fatal("do not run this command by hand"); 572 } 573 574 /* 575 * Application-specific initialization. 576 */ 577 va_start(ap, service); 578 while ((key = va_arg(ap, int)) != 0) { 579 switch (key) { 580 case MAIL_SERVER_INT_TABLE: 581 get_mail_conf_int_table(va_arg(ap, CONFIG_INT_TABLE *)); 582 break; 583 case MAIL_SERVER_LONG_TABLE: 584 get_mail_conf_long_table(va_arg(ap, CONFIG_LONG_TABLE *)); 585 break; 586 case MAIL_SERVER_STR_TABLE: 587 get_mail_conf_str_table(va_arg(ap, CONFIG_STR_TABLE *)); 588 break; 589 case MAIL_SERVER_BOOL_TABLE: 590 get_mail_conf_bool_table(va_arg(ap, CONFIG_BOOL_TABLE *)); 591 break; 592 case MAIL_SERVER_TIME_TABLE: 593 get_mail_conf_time_table(va_arg(ap, CONFIG_TIME_TABLE *)); 594 break; 595 case MAIL_SERVER_RAW_TABLE: 596 get_mail_conf_raw_table(va_arg(ap, CONFIG_RAW_TABLE *)); 597 break; 598 case MAIL_SERVER_NINT_TABLE: 599 get_mail_conf_nint_table(va_arg(ap, CONFIG_NINT_TABLE *)); 600 break; 601 case MAIL_SERVER_NBOOL_TABLE: 602 get_mail_conf_nbool_table(va_arg(ap, CONFIG_NBOOL_TABLE *)); 603 break; 604 case MAIL_SERVER_PRE_INIT: 605 pre_init = va_arg(ap, MAIL_SERVER_INIT_FN); 606 break; 607 case MAIL_SERVER_POST_INIT: 608 post_init = va_arg(ap, MAIL_SERVER_INIT_FN); 609 break; 610 case MAIL_SERVER_LOOP: 611 loop = va_arg(ap, MAIL_SERVER_LOOP_FN); 612 break; 613 case MAIL_SERVER_EXIT: 614 trigger_server_onexit = va_arg(ap, MAIL_SERVER_EXIT_FN); 615 break; 616 case MAIL_SERVER_PRE_ACCEPT: 617 trigger_server_pre_accept = va_arg(ap, MAIL_SERVER_ACCEPT_FN); 618 break; 619 case MAIL_SERVER_IN_FLOW_DELAY: 620 trigger_server_in_flow_delay = 1; 621 break; 622 case MAIL_SERVER_SOLITARY: 623 if (stream == 0 && !alone) 624 msg_fatal("service %s requires a process limit of 1", 625 service_name); 626 break; 627 case MAIL_SERVER_UNLIMITED: 628 if (stream == 0 && !zerolimit) 629 msg_fatal("service %s requires a process limit of 0", 630 service_name); 631 break; 632 case MAIL_SERVER_PRIVILEGED: 633 if (user_name) 634 msg_fatal("service %s requires privileged operation", 635 service_name); 636 break; 637 case MAIL_SERVER_WATCHDOG: 638 trigger_server_watchdog = *va_arg(ap, int *); 639 break; 640 default: 641 msg_panic("%s: unknown argument type: %d", myname, key); 642 } 643 } 644 va_end(ap); 645 646 if (root_dir) 647 root_dir = var_queue_dir; 648 if (user_name) 649 user_name = var_mail_owner; 650 651 /* 652 * Can options be required? 653 * 654 * XXX Initially this code was implemented with UNIX-domain sockets, but 655 * Solaris <= 2.5 UNIX-domain sockets misbehave hopelessly when the 656 * client disconnects before the server has accepted the connection. 657 * Symptom: the server accept() fails with EPIPE or EPROTO, but the 658 * socket stays readable, so that the program goes into a wasteful loop. 659 * 660 * The initial fix was to use FIFOs, but those turn out to have their own 661 * problems, witness the workarounds in the fifo_listen() routine. 662 * Therefore we support both FIFOs and UNIX-domain sockets, so that the 663 * user can choose whatever works best. 664 * 665 * Well, I give up. Solaris UNIX-domain sockets still don't work properly, 666 * so it will have to limp along with a streams-specific alternative. 667 */ 668 if (stream == 0) { 669 if (transport == 0) 670 msg_fatal("no transport type specified"); 671 if (strcasecmp(transport, MASTER_XPORT_NAME_UNIX) == 0) 672 trigger_server_accept = trigger_server_accept_local; 673 else if (strcasecmp(transport, MASTER_XPORT_NAME_FIFO) == 0) 674 trigger_server_accept = trigger_server_accept_fifo; 675#ifdef MASTER_XPORT_NAME_PASS 676 else if (strcasecmp(transport, MASTER_XPORT_NAME_PASS) == 0) 677 trigger_server_accept = trigger_server_accept_pass; 678#endif 679 else 680 msg_fatal("unsupported transport type: %s", transport); 681 } 682 683 /* 684 * Retrieve process generation from environment. 685 */ 686 if ((generation = getenv(MASTER_GEN_NAME)) != 0) { 687 if (!alldig(generation)) 688 msg_fatal("bad generation: %s", generation); 689 OCTAL_TO_UNSIGNED(trigger_server_generation, generation); 690 if (msg_verbose) 691 msg_info("process generation: %s (%o)", 692 generation, trigger_server_generation); 693 } 694 695 /* 696 * Optionally start the debugger on ourself. 697 */ 698 if (debug_me) 699 debug_process(); 700 701 /* 702 * Traditionally, BSD select() can't handle multiple processes selecting 703 * on the same socket, and wakes up every process in select(). See TCP/IP 704 * Illustrated volume 2 page 532. We avoid select() collisions with an 705 * external lock file. 706 */ 707 if (stream == 0 && !alone) { 708 lock_path = concatenate(DEF_PID_DIR, "/", transport, 709 ".", service_name, (char *) 0); 710 why = vstring_alloc(1); 711 if ((trigger_server_lock = safe_open(lock_path, O_CREAT | O_RDWR, 0600, 712 (struct stat *) 0, -1, -1, why)) == 0) 713 msg_fatal("open lock file %s: %s", lock_path, vstring_str(why)); 714 close_on_exec(vstream_fileno(trigger_server_lock), CLOSE_ON_EXEC); 715 myfree(lock_path); 716 vstring_free(why); 717 } 718 719 /* 720 * Set up call-back info. 721 */ 722 trigger_server_service = service; 723 trigger_server_name = service_name; 724 trigger_server_argv = argv + optind; 725 726 /* 727 * Run pre-jail initialization. 728 */ 729 if (chdir(var_queue_dir) < 0) 730 msg_fatal("chdir(\"%s\"): %m", var_queue_dir); 731 if (pre_init) 732 pre_init(trigger_server_name, trigger_server_argv); 733 734 /* 735 * Optionally, restrict the damage that this process can do. 736 */ 737 resolve_local_init(); 738 tzset(); 739 chroot_uid(root_dir, user_name); 740 741 /* 742 * Run post-jail initialization. 743 */ 744 if (post_init) 745 post_init(trigger_server_name, trigger_server_argv); 746 747 /* 748 * Are we running as a one-shot server with the client connection on 749 * standard input? 750 */ 751 if (stream != 0) { 752 if ((len = read(vstream_fileno(stream), buf, sizeof(buf))) <= 0) 753 msg_fatal("read: %m"); 754 service(buf, len, trigger_server_name, trigger_server_argv); 755 vstream_fflush(stream); 756 trigger_server_exit(); 757 } 758 759 /* 760 * Running as a semi-resident server. Service connection requests. 761 * Terminate when we have serviced a sufficient number of clients, when 762 * no-one has been talking to us for a configurable amount of time, or 763 * when the master process terminated abnormally. 764 */ 765 if (var_idle_limit > 0) 766 event_request_timer(trigger_server_timeout, (char *) 0, var_idle_limit); 767 for (fd = MASTER_LISTEN_FD; fd < MASTER_LISTEN_FD + socket_count; fd++) { 768 event_enable_read(fd, trigger_server_accept, CAST_INT_TO_CHAR_PTR(fd)); 769 close_on_exec(fd, CLOSE_ON_EXEC); 770 } 771 event_enable_read(MASTER_STATUS_FD, trigger_server_abort, (char *) 0); 772 close_on_exec(MASTER_STATUS_FD, CLOSE_ON_EXEC); 773 close_on_exec(MASTER_FLOW_READ, CLOSE_ON_EXEC); 774 close_on_exec(MASTER_FLOW_WRITE, CLOSE_ON_EXEC); 775 watchdog = watchdog_create(trigger_server_watchdog, 776 (WATCHDOG_FN) 0, (char *) 0); 777 778 /* 779 * The event loop, at last. 780 */ 781 while (var_use_limit == 0 || use_count < var_use_limit) { 782 if (trigger_server_lock != 0) { 783 watchdog_stop(watchdog); 784 if (myflock(vstream_fileno(trigger_server_lock), INTERNAL_LOCK, 785 MYFLOCK_OP_EXCLUSIVE) < 0) 786 msg_fatal("select lock: %m"); 787 } 788 watchdog_start(watchdog); 789 delay = loop ? loop(trigger_server_name, trigger_server_argv) : -1; 790 event_loop(delay); 791 } 792 trigger_server_exit(); 793} 794