From a381013aaaf1b621d6e3a20302fb074b5f8a7667 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Wed, 28 Apr 2010 01:31:02 +0100 Subject: [PATCH] wip control --- backends/innduct.c | 162 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 142 insertions(+), 20 deletions(-) diff --git a/backends/innduct.c b/backends/innduct.c index 014447e..e9da15b 100644 --- a/backends/innduct.c +++ b/backends/innduct.c @@ -1,3 +1,13 @@ +/* + * todo + * - actually do something with readable on control master + * - option for realsockdir + * - manpage: document control master stuff + * - manpage: innconf is used for communicating with innd + * - debug this: + * build-lfs/backends/innduct --no-daemon -f `pwd`/fee sit dom + */ + /* * Newsfeeds file entries should look like this: * host.name.of.site[/exclude,exclude,...]\ @@ -163,6 +173,7 @@ perl -ne 'print if m/-8\<-/..m/-\>8-/; print "\f" if m/-\^L-/' backends/innduct. #include #include #include +#include #include #include #include @@ -173,6 +184,7 @@ perl -ne 'print if m/-8\<-/..m/-\>8-/; print "\f" if m/-\^L-/' backends/innduct. #include #include #include +#include #include #include #include @@ -304,7 +316,7 @@ static oop_rd_call peer_rd_err, peer_rd_ok; /* when changing defaults, remember to update the manpage */ static const char *sitename, *remote_host; -static const char *feedfile; +static const char *feedfile, *realsockdir="/tmp/innduct.control"; static int quiet_multiple=0; static int become_daemon=1; static int try_stream=1; @@ -458,7 +470,9 @@ struct Conn { static oop_source *loop; static ConnList conns; static ArticleList queue; -static char *path_lock, *path_flushing, *path_defer, *globpat_backlog; +static char *path_lock, *path_flushing, *path_defer, *path_control; +static char *globpat_backlog; +static pid_t self_pid; /* statemc_init initialises */ static StateMachineState sms; @@ -466,6 +480,9 @@ static FILE *defer; static InputFile *main_input_file, *flushing_input_file, *backlog_input_file; static int sm_period_counter; +/* control_init initialises */ +static int control_master; + /* initialisation to 0 is good */ static int until_connect, until_backlog_nextscan; static double accept_proportion; @@ -479,6 +496,7 @@ static void logcore(int sysloglevel, const char *fmt, ...) { if (become_daemon) { vsyslog(sysloglevel,fmt,al); } else { + if (self_pid) fprintf(stderr,"[%lu] ",(unsigned long)self_pid); vfprintf(stderr,fmt,al); putc('\n',stderr); } @@ -527,7 +545,7 @@ diewrap(fatal, " fatal", LOG_ERR, -1, 12); logwrap(syswarn, " warning", LOG_WARNING, errno); logwrap(warn, " warning", LOG_WARNING, -1); -logwrap(notice, "", LOG_NOTICE, -1); +logwrap(notice, " notice", LOG_NOTICE, -1); logwrap(info, " info", LOG_INFO, -1); logwrap(debug, " debug", LOG_DEBUG, -1); @@ -686,6 +704,100 @@ static int isewouldblock(int errnoval) { return errnoval==EWOULDBLOCK || errnoval==EAGAIN; } + +/*========== command and control connections ==========*/ + +#define NOCONTROL(...) do{ \ + syswarn("no control socket, because failed to " __VA_ARGS__); \ + goto nocontrol; \ + }while(0) + +static void control_init(void) { + char *real=0; + + union { + struct sockaddr sa; + struct sockaddr_un un; + } sa; + + memset(&sa,0,sizeof(sa)); + int maxlen= sizeof(sa.un.sun_path); + + int reallen= readlink(path_control, sa.un.sun_path, maxlen); + if (reallen<0) { + if (errno != ENOENT) + NOCONTROL("readlink control socket symlink path %s", path_control); + } + if (reallen >= maxlen) { + debug("control socket symlink path too long (r=%d)",reallen); + xunlink(path_control, "old (overlong) control socket symlink"); + reallen= -1; + } + + if (reallen<0) { + struct stat stab; + int r= lstat(realsockdir,&stab); + if (r) { + if (errno != ENOENT) NOCONTROL("lstat real socket dir %s", realsockdir); + + r= mkdir(realsockdir, 0700); + if (r) NOCONTROL("mkdir real socket dir %s", realsockdir); + + } else { + uid_t self= geteuid(); + if (!S_ISDIR(stab.st_mode) || + stab.st_uid != self || + stab.st_mode & 0077) { + warn("no control socket, because real socket directory" + " is somehow wrong (ISDIR=%d, uid=%lu (exp.%lu), mode %lo)", + !!S_ISDIR(stab.st_mode), + (unsigned long)stab.st_uid, (unsigned long)self, + (unsigned long)stab.st_mode & 0777UL); + goto nocontrol; + } + } + + real= xasprintf("%s/s%lx.%lx", realsockdir, + (unsigned long)xtime(), (unsigned long)self_pid); + int reallen= strlen(real); + + if (reallen >= maxlen) { + warn("no control socket, because tmpnam gave overly-long path" + " %s", real); + goto nocontrol; + } + r= symlink(real, path_control); + if (r) NOCONTROL("make control socket path %s a symlink to real" + " socket path %s", path_control, real); + memcpy(sa.un.sun_path, real, reallen); + } + + int r= unlink(sa.un.sun_path); + if (r && errno!=ENOENT) + NOCONTROL("remove old real socket %s", sa.un.sun_path); + + control_master= socket(PF_UNIX, SOCK_STREAM, 0); + if (control_master<0) NOCONTROL("create new control socket"); + + sa.un.sun_family= AF_UNIX; + int sl= strlen(sa.un.sun_path) + offsetof(struct sockaddr_un, sun_path); + r= bind(control_master, &sa.sa, sl); + if (r) NOCONTROL("bind to real socket path %s", sa.un.sun_path); + + r= listen(control_master, 5); + if (r) NOCONTROL("listen"); + + //loop->on_fd(loop, control_master, OOP_READ, control_master_readable, 0); + info("control socket ok, real path %s", sa.un.sun_path); + + return; + + nocontrol: + free(real); + xclose_perhaps(&control_master, "control master",0); + return; +} + /*========== management of connections ==========*/ static void conn_closefd(Conn *conn, const char *msgprefix) { @@ -1890,15 +2002,9 @@ static void startup_set_input_file(InputFile *f) { inputfile_reading_start(f); } -static void statemc_init(void) { - struct stat stab, stabf; - - path_lock= xasprintf("%s_lock", feedfile); - path_flushing= xasprintf("%s_flushing", feedfile); - path_defer= xasprintf("%s_defer", feedfile); - globpat_backlog= xasprintf("%s_backlog*", feedfile); - +static void statemc_lock(void) { int lockfd; + struct stat stab, stabf; for (;;) { lockfd= open(path_lock, O_CREAT|O_RDWR, 0600); @@ -1926,8 +2032,6 @@ static void statemc_init(void) { xclose(lockfd, "stale lockfile ", path_lock); } - pid_t self= getpid(); - if (self==-1) sysdie("getpid"); FILE *lockfile= fdopen(lockfd, "w"); if (!lockfile) sysdie("fdopen lockfile"); @@ -1936,21 +2040,26 @@ static void statemc_init(void) { if (r) sysdie("truncate lockfile to write new info"); if (fprintf(lockfile, "pid %ld\nsite %s\nfeedfile %s\nfqdn %s\n", - (unsigned long)self, sitename, feedfile, remote_host) == EOF || + (unsigned long)self_pid, + sitename, feedfile, remote_host) == EOF || fflush(lockfile)) sysfatal("write info to lockfile %s", path_lock); debug("startup: locked"); +} + +static void statemc_init(void) { + struct stat stabdefer; search_backlog_file(); int defer_noent; - xlstat_isreg(path_defer, &stab, &defer_noent, "defer file"); + xlstat_isreg(path_defer, &stabdefer, &defer_noent, "defer file"); if (defer_noent) { debug("startup: ductdefer ENOENT"); } else { - debug("startup: ductdefer nlink=%ld", (long)stab.st_nlink); - switch (stab.st_nlink==1) { + debug("startup: ductdefer nlink=%ld", (long)stabdefer.st_nlink); + switch (stabdefer.st_nlink==1) { case 1: open_defer(); /* so that we will later close it and rename it */ break; @@ -1960,7 +2069,7 @@ static void statemc_init(void) { break; default: die("defer file %s has unexpected link count %d", - path_defer, stab.st_nlink); + path_defer, stabdefer.st_nlink); } } @@ -2502,7 +2611,7 @@ EVERY(filepoll, 5,0, ({ })); static char *debug_report_ipf(InputFile *ipf) { - if (!ipf) return xasprintf("-"); + if (!ipf) return xasprintf("none"); const char *slash= strrchr(ipf->path,'/'); const char *path= slash ? slash+1 : ipf->path; @@ -2521,7 +2630,7 @@ EVERY(period, -1,0, ({ debug("PERIOD" " sms=%s[%d] conns=%d queue=%d until_connect=%d" " input_files main:%s old:%s flushing:%s" - " children connecting=%ld inndcomm_child=%ld" + " children connecting=%ld inndcomm=%ld" , sms_names[sms], sm_period_counter, conns.count, queue.count, until_connect, @@ -2816,6 +2925,12 @@ int main(int argc, char **argv) { /* set things up */ + path_lock= xasprintf("%s_lock", feedfile); + path_flushing= xasprintf("%s_flushing", feedfile); + path_defer= xasprintf("%s_defer", feedfile); + path_control= xasprintf("%s_control", feedfile); + globpat_backlog= xasprintf("%s_backlog*", feedfile); + oop_source_sys *sysloop= oop_sys_new(); if (!sysloop) sysdie("could not create liboop event loop"); loop= (oop_source*)sysloop; @@ -2850,8 +2965,15 @@ int main(int argc, char **argv) { if (child2) _exit(0); } + self_pid= getpid(); + if (self_pid==-1) sysdie("getpid"); + + statemc_lock(); + notice("starting"); + control_init(); + if (!filemon_method_init()) { warn("no file monitoring available, polling"); filepoll_schedule(); -- 2.30.2