/* ** This file is derived from inetd.c ** "@(#)from: inetd.c 8.4 (Berkeley) 4/13/94"; ** as available in the OpenBSD source tree. ** It has been significantly modified to suit the needs as sendmail MCP. */ /* * Copyright (c) 1983, 1991, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef MCP_H #define MCP_H 1 /* $Id: mcp.h,v 1.26 2007/09/29 02:10:07 ca Exp $ */ #include "sm/generic.h" #include "sm/mcpdef.h" #include "sm/servid.h" #include "sm/sockcnf.h" #ifndef SM_MCP_USE_CONF # define SM_MCP_USE_CONF 1 #endif /* ** Missing: counter for respawns: disable service if too often ** within a certain time period. For now it's a simple failure counter. ** ** Need parameter expansion, e.g., %p -> pid, to allow different names ** for different invocations of the same program (e.g., name of socket ** over which fd is passed). ** ** Enforce order to start programs; currently simply done by listing ** them in the right (reverse) order in the configuration file. ** ** Need way to signal all children to stop, e.g., send a signal ** to them or some data over a control socket. For now: pass TERM/INT/HUP ** to all children. ** ** Communication/control socket (same as socket to pass fd?) ** Also listen on that socket for feedback. ** ** Check names etc for "sanity", e.g., se_prg: only letter/digit/_? ** ** Specify a "working" directory into which to chdir before running? */ typedef struct servtab_S servtab_T, *servtab_P; struct servtab_S { char const *se_prg; /* name of service */ char const *se_kw; /* keyword */ char const *se_title; /* title */ #if 0 char *se_proto; /* protocol used */ #endif sockspec_T se_socket; #define MCP_SOCKET_IS_TYPE(se, sock_type) \ ((se)->se_socket.sckspc_type == (sock_type)) #define MCP_SOCKET_IS_UNIX(se) MCP_SOCKET_IS_TYPE(se, SOCK_TYPE_UNIX) #define MCP_SOCKET_IS_INET(se) MCP_SOCKET_IS_TYPE(se, SOCK_TYPE_INET) #define se_port se_socket.sock_inet.inetsckspc_port #define se_addr se_socket.sock_inet.inetsckspc_addr #if MCP_OLD_SOCKET int se_port; /* port */ ipv4_T se_addr; /* address to bind(2) to */ #endif /* MCP_OLD_SOCKET */ int se_listen_len; /* backlog for listen(2) */ #define se_socket_name se_socket.sock_unix.unixsckspc_path #define se_socket_umask se_socket.sock_unix.unixsckspc_umask #define se_socket_user se_socket.sock_unix.unixsckspc_user #define se_socket_group se_socket.sock_unix.unixsckspc_group #if MCP_OLD_SOCKET char *se_socket_name; /* local (UNIX) socket */ mode_t se_socket_umask; /* umask for socket creation */ char *se_socket_user; /* socket owner: user name */ char *se_socket_group; /* socket owner: group name */ #endif /* MCP_OLD_SOCKET */ int se_minchild; /* min number of children */ int se_maxchild; /* max number of children */ #if MTA_USE_CPML int se_maxcpm; /* max connects per IP per minute */ #endif int se_numchild; /* current number of children */ int se_failed; /* failure counter */ time_t se_lastfail; pid_t *se_pids; /* array of child pids */ uint *se_ids; /* array of child ids */ char *se_pass_id; /* pass id to program (if not NULL) */ char *se_exsock; /* exchange socket */ char *se_user; /* user name to run as */ char *se_group; /* group name to run as */ #ifdef LOGIN_CAP char *se_class; /* login class name to run with */ #endif /* data for restart dependencies */ int se_nrestartdep; char *se_restartdep[SM_MCP_MAXRESTARTDEP + 1]; char *se_restartdeps; char *se_server; /* server program */ char *se_server_name; /* program without path */ char *se_workdir; /* working directory (chdir(2)) */ #define MAXARGV 64 char *se_args; /* program arguments (one string) */ char *se_argv[MAXARGV + 1]; /* program arguments */ int se_fd; /* open file descriptor */ int se_count; /* number started since se_time */ uint se_flags; /* see below */ #if 0 uint se_cflags; /* see below */ #else bool se_logf_id; /* use id in logfile */ #endif sm_sockaddr_T se_ctrladdr; /* bound address */ sockaddr_len_T se_ctrladdr_size; struct timeval se_time; /* start of se_count */ servtab_P se_next; /* pointer to next entry */ }; /* flags for service */ #define SE_FL_DISABLED 0x0001 /* service is disabled */ #define SE_FL_WAIT 0x0002 /* wait for service to return */ #define SE_FL_PASS 0x0004 /* pass fd to service */ #define SE_FL_ACCEPT 0x0008 /* accept locally */ /* wait for request: start only when connection comes in */ #define SE_FL_W4REQ 0x0010 #define SE_FL_RESTART 0x0020 /* restart this service */ #define SE_FL_LEADER 0x0040 /* process that causes restart */ #define SE_FL_CHECKED 0x0100 /* looked at during merge */ #define SE_FL_LOGF_ID 0x0200 /* use id in logfile */ #define SE_FL_UNRECOVERABLE 0x0400 /* failed with unrecoverable error */ #define SE_SET_FLAG(sep, fl) (sep)->se_flags |= (fl) #define SE_CLR_FLAG(sep, fl) (sep)->se_flags &= ~(fl) #define SE_IS_FLAG(sep, fl) (((sep)->se_flags & (fl)) != 0) #if 0 /* other configuration flags (separate, otherwise hard to handle in config) */ #define SE_CFL_LOGF_ID 0x0001 /* use id in logfile */ #define SE_SET_CFLAG(sep, fl) (sep)->se_cflags |= (fl) #define SE_CLR_CFLAG(sep, fl) (sep)->se_cflags &= ~(fl) #define SE_IS_CFLAG(sep, fl) (((sep)->se_cflags & (fl)) != 0) #else /* 0 */ #endif /* 0 */ /* ** MCP context ** Note: the distinction between flags and status isn't very clean. */ typedef struct mcp_ctx_S mcp_ctx_T, *mcp_ctx_P; struct mcp_ctx_S { uint mcp_status; uint mcp_flags; uint mcp_total_proc; /* sum of se_maxchild */ id_ctx_P mcp_id_ctx; }; #define MCP_OPT_IS_SET(opt) ((opt) != NULL && *(opt) != SM_MCP_DEFAULT_CHAR) void sm_exit(int _value); void #if SM_CHK_PRINTF PRINTFLIKE(2, 3) #endif m_syslog(int _priority, const char *_fmt, ...); #endif /* MCP_H */