/* This file is part of Pies. Copyright (C) 2008, 2009 Sergey Poznyakoff Pies is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. Pies is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Pies. If not, see . */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "progname.h" #include "inttostr.h" #include "c-ctype.h" #include "xalloc.h" #define obstack_chunk_alloc xmalloc #define obstack_chunk_free free #include "obstack.h" #include "xvasprintf.h" #include "acl.h" #include "libpies.h" #define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0])) #define TESTTIME 2*60 #define SLEEPTIME 5*60 #define MAXSPAWN 10 #define RETR_OUT 0 #define RETR_ERR 1 enum redir_type { redir_null, redir_syslog, redir_file }; struct redirector { enum redir_type type; union { int prio; char *file; } v; }; typedef struct limits_rec *limits_record_t; enum return_action { action_restart, action_disable, }; #define STATUS_SIG_BIT 0x80000000 #define STATUS_CODE(c) ((c) & ~STATUS_SIG_BIT) struct action { struct action *next; size_t nstat; unsigned *status; enum return_action act; /* Action to take when the component terminates */ char *addr; /* Addresses to notify about it. */ char *message; /* Notification mail. */ char *command; /* Execute this command */ }; /* user privs */ struct pies_privs { char *user; int allgroups; gl_list_t groups; }; enum pies_comp_mode { /* Execute the component, no sockets are opened. This is the default Pies mode. */ pies_comp_exec, /* Open a socket and start a component with stdin/stdout bound to that socket. Corresponds to MeTA1 notion of `start_action = accept'. */ pies_comp_accept, /* Inetd mode: like above, but start the component only when an incoming connection is requested. Corresponds to `start_action = nostartaccept' in MeTA1. */ pies_comp_inetd, /* Open a socket, start a component, and pass the socket fd to the component via the UNIX domain socket. Corresponds to `start_action = pass' in MeTA1. */ pies_comp_pass_fd }; struct component { enum pies_comp_mode mode; char *tag; /* Entry tag (for diagnostics purposes) */ char *program; /* Program name */ char **argv; /* Program command line */ char **env; /* Program environment */ char *dir; /* Working directory */ gl_list_t prereq; /* Prerequisites */ gl_list_t depend; /* Dependency targets */ unsigned settle_timeout; /* Time needed for started prerequisites to settle */ /* FIXME: disabled and precious can be encoded as bits in mode */ int disabled; /* The componenet is disabled */ int precious; /* The component is precious (cannot be disabled) */ char *rmfile; /* Try to remove this file before starting */ struct pies_privs privs; /* UID/GIDS+groups to run under */ mode_t umask; /* Umask to install before starting */ limits_record_t limits; /* System limits */ struct pies_url *socket_url; /* Socket to listen on (if mode != pies_comp_exec) */ char *pass_fd_socket; /* Socket to pass fd on (if mode == pies_comp_pass_fd) */ pies_acl_t acl; /* Redirectors: */ int facility; /* Syslog facility. */ struct redirector redir[2]; /* Repeaters for stdout and stderr */ /* Actions to execute on various exit codes: */ struct action *act_head, *act_tail; struct action act_temp; /* Auxiliary object used during configuration */ }; extern int log_to_stderr; extern char *log_tag; extern int log_facility; extern unsigned long shutdown_timeout; extern struct component default_component; pies_acl_t pies_acl; extern limits_record_t pies_limits; void register_prog (struct component *comp); size_t progman_running_count (void); void progman_start (void); void progman_wake_sleeping (void); void progman_stop (void); void progman_cleanup (int expect_term); void progman_stop_component (const char *name); void progman_dump_stats (const char *filename); void progman_dump_prereq (void); void progman_dump_depmap (void); int progman_accept (int socket); int progman_build_depmap (void); void progman_create_sockets (void); struct component *progman_lookup_component (const char *tag); void log_setup (int want_stderr); void signal_setup (RETSIGTYPE (*sf)(int)); typedef struct pies_depmap *pies_depmap_t; typedef struct pies_depmap_pos *pies_depmap_pos_t; enum pies_depmap_direction { depmap_row = 0, depmap_col = !depmap_row }; pies_depmap_t depmap_alloc (unsigned count); pies_depmap_t depmap_copy (pies_depmap_t dpm); void depmap_set (pies_depmap_t dmap, unsigned row, unsigned col); int depmap_isset (pies_depmap_t dmap, unsigned row, unsigned col); void depmap_tc (pies_depmap_t dmap); unsigned depmap_first (pies_depmap_t dmap, enum pies_depmap_direction dir, unsigned coord, pies_depmap_pos_t *ppos); unsigned depmap_next (pies_depmap_t dmap, pies_depmap_pos_t pos); int assert_grecs_value_type (grecs_locus_t *locus, const grecs_value_t *value, int type); struct component *component_create (const char *name); void component_finish (struct component *comp, grecs_locus_t *locus); struct grecs_keyword *find_component_keyword (const char *ident); /* url.c */ struct pies_url { char *string; char *proto; char *host; int port; char *path; char *user; char *passwd; int argc; char **argv; }; int pies_url_create (struct pies_url **purl, const char *str); void pies_url_destroy (struct pies_url **purl); const char * pies_url_get_arg (struct pies_url *url, const char *argname); void pies_pause (void); int register_listener (int fd); int pass_fd (const char *socket, int fd); int create_socket (struct pies_url *url, const char *user, mode_t umask); int parse_limits (limits_record_t *plrec, char *str, char **endp); int set_limits (const char *name, limits_record_t lrec); void meta1_parser_set_debug (void); int meta1lex (void); int meta1error (char *s); int meta1parse (void); void logmsg (int prio, const char *fmt, ...); void logmsg_printf (int prio, const char *fmt, ...); void logmsg_vprintf (int prio, const char *fmt, va_list ap); extern unsigned debug_level; extern int source_info_option; void debug_msg (const char *fmt, ...); #define debug(lev, args) \ do \ if (debug_level >= lev) \ { \ if (source_info_option) \ logmsg_printf (LOG_DEBUG, "%s:%lu:%s: ", \ __FILE__, __LINE__, __FUNCTION__); \ debug_msg args; \ } \ while (0) /* meta.c */ struct metadef { char *kw; char *value; const char *(*expand) (struct metadef *, void *); char *storage; void *data; }; char *meta_expand_string (const char *string, struct metadef *def, void *data); void meta_free (struct metadef *def); /* addrfmt.c */ void sockaddr_to_str (const struct sockaddr *sa, int salen, char *bufptr, size_t buflen, size_t *plen); char *sockaddr_to_astr (const struct sockaddr *sa, int salen); /* userprivs.c */ int switch_to_privs (uid_t uid, gid_t gid, gl_list_t retain_groups); void pies_priv_setup (struct pies_privs *); void pies_epriv_setup (struct pies_privs *);