From 8637044e5d6c13c4ddf8dc83440a59b060b25a3d Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Mon, 3 May 2010 13:34:27 +0100 Subject: [PATCH] Get rid of the control master symlink --- backends/innduct.c | 100 +++++++++++++-------------------------------- doc/man/innduct.8 | 55 +++++++++++-------------- 2 files changed, 52 insertions(+), 103 deletions(-) diff --git a/backends/innduct.c b/backends/innduct.c index d29e48f..c0404fc 100644 --- a/backends/innduct.c +++ b/backends/innduct.c @@ -355,7 +355,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, *realsockdir="/tmp/innduct.control"; +static const char *feedfile, *path_control; static int quiet_multiple=0; static int become_daemon=1, try_filemon=1; static int try_stream=1; @@ -368,7 +368,6 @@ static int target_max_feedfile_size=100000; static int period_seconds=60; static int filepoll_seconds=5; static int max_queue_per_ipf=-1; -static int realsockdir_any_perms=0; static int connection_setup_timeout=200; static int inndcomm_flush_timeout=100; @@ -518,8 +517,7 @@ struct Conn { /* main initialises */ static oop_source *loop; static ConnList conns; -static char *path_lock, *path_flushing, *path_defer; -static char *path_control, *path_dump; +static char *path_lock, *path_flushing, *path_defer, *path_dump; static char *globpat_backlog; static pid_t self_pid; @@ -1001,8 +999,6 @@ static void *control_master_readable(oop_source *lp, int master, }while(0) static void control_init(void) { - char *real=0; - union { struct sockaddr sa; struct sockaddr_un un; @@ -1011,66 +1007,24 @@ static void control_init(void) { 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 if (!realsockdir_any_perms) { - uid_t self= geteuid(); - if (!S_ISDIR(stab.st_mode) || - stab.st_uid != self || - stab.st_mode & 0007) { - 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 pathlen= strlen(path_control); + if (pathlen > maxlen) + NOCONTROL("control socket path %s too long (%d>%d)", + path_control, pathlen, maxlen); - int r= unlink(sa.un.sun_path); + int r= unlink(path_control); if (r && errno!=ENOENT) - NOCONTROL("remove old real socket %s", sa.un.sun_path); + NOCONTROL("remove old control socket %s", path_control); 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); + sa.un.sun_family= AF_UNIX; + memcpy(sa.un.sun_path, path_control, pathlen); + r= bind(control_master, &sa.sa, sl); - if (r) NOCONTROL("bind to real socket path %s", sa.un.sun_path); + if (r) NOCONTROL("bind to control socket path %s", sa.un.sun_path); r= listen(control_master, 5); if (r) NOCONTROL("listen"); @@ -1078,12 +1032,11 @@ static void control_init(void) { xsetnonblock(control_master, 1); loop->on_fd(loop, control_master, OOP_READ, control_master_readable, 0); - info("control socket ok, real path %s", sa.un.sun_path); + info("control socket ok, listening on %s", path_control); return; nocontrol: - free(real); xclose_perhaps(&control_master, "control master",0); return; } @@ -3411,10 +3364,11 @@ CCMD(dump) { } fprintf(f,"paths"); + DUMPV("%s", , feedfile); + DUMPV("%s", , path_control); DUMPV("%s", , path_lock); DUMPV("%s", , path_flushing); DUMPV("%s", , path_defer); - DUMPV("%s", , path_control); DUMPV("%s", , path_dump); DUMPV("%s", , globpat_backlog); fprintf(f,"\n"); @@ -3598,8 +3552,7 @@ static const Option innduct_options[]= { {0,"no-filemon", 0, &try_filemon, op_setint, 0 }, {'C',"inndconf", "F", &inndconffile, op_string }, {'P',"port", "PORT", &port, op_integer }, -{0,"ctrl-sock-dir", 0, &realsockdir, op_string }, -{0,"no-ctrl-sock-dir-perms-check",0,&realsockdir_any_perms, op_setint, 0 }, +{0,"cli", 0, &path_control, op_string }, {0,"help", 0, 0, help }, {0,"max-connections", "N", &max_connections, op_integer }, @@ -3649,6 +3602,14 @@ static void convert_to_periods_rndup(int *store) { *store /= period_seconds; } +static void assemble_path(const char **path_io, const char *suffix, + const char *what) { + const char *const specified= *path_io; + if (!specified[0]) badusage("%s, if specified, must be nonempty", what); + if (specified[strlen(specified)-1]=='/') + *path_io= xasprintf("%s%s%s", specified, sitename, suffix); +} + int main(int argc, char **argv) { if (!argv[1]) { printusage(stderr); @@ -3690,14 +3651,12 @@ int main(int argc, char **argv) { if (max_bad_data_ratio < 0 || max_bad_data_ratio > 100) badusage("bad input data ratio must be between 0..100"); max_bad_data_ratio *= 0.01; + + if (!feedfile) feedfile= xasprintf("%s/%s",innconf->pathoutgoing,sitename); + else assemble_path(&feedfile, "", "feed filename"); - if (!feedfile) { - feedfile= xasprintf("%s/%s",innconf->pathoutgoing,sitename); - } else if (!feedfile[0]) { - badusage("feed filename must be nonempty"); - } else if (feedfile[strlen(feedfile)-1]=='/') { - feedfile= xasprintf("%s%s",feedfile,sitename); - } + if (path_control) path_control= xasprintf("%s_cli", feedfile); + else assemble_path(&path_control, "%s_cli", "control socket path"); if (max_queue_per_ipf<0) max_queue_per_ipf= max_queue_per_conn * 2; @@ -3713,7 +3672,6 @@ int main(int argc, char **argv) { path_lock= xasprintf("%s_lock", feedfile); path_flushing= xasprintf("%s_flushing", feedfile); path_defer= xasprintf("%s_defer", feedfile); - path_control= xasprintf("%s_control", feedfile); path_dump= xasprintf("%s_dump", feedfile); globpat_backlog= xasprintf("%s_backlog*", feedfile); diff --git a/doc/man/innduct.8 b/doc/man/innduct.8 index fa6cede..055d083 100644 --- a/doc/man/innduct.8 +++ b/doc/man/innduct.8 @@ -106,26 +106,20 @@ Read instead of the default .BR inn.conf . .TP -.BI \-\-ctrl-sock-dir= CTRL-SOCK-DIR -Use -.I CTRL-SOCK-DIR -as the directory to contain the actual control socket. See -CONTROLLING INNDUCT, below. -If -.I CTRL-SOCK-DIR -does not exist it will be created with mode 0700; if it does -exist it must not be a symlink and must be owned by the user running -innduct and have no access for "other". If the control socket cannot -be set up (for this or any other reason), a warning is logged, but -such situations are not fatal for innduct's startup. The default is -.BR /tmp/innduct.control . -.TP -.BI \-\-no-ctrl-sock-dir-perms-check -Use an existing -.I CTRL-SOCK-DIR -even if it has unexpected permissions and ownership. Note that this -is not safe with the default value of -.IR CTRL-SOCK-DIR . +.BR \-\-cli= \fIDIR\fR / |\fIPATH\fR +Bind the control command line socket to +.IB DIR / site _cli +(if the value ends with a +.BR /) +or +.I PATH +(if it doesn't). See CONTROLLING INNDUCT, below. +This option may be essential, if the +path to +.I feedfile +is too long, as there is a fairly short limit on the paths to AF_UNIX +sockets. The default is +.IR feedfile \fB_cli\fR. .TP .BI \-\-port= PORT Connect to port @@ -324,29 +318,22 @@ If you want to stop innduct you can send it SIGTERM or SIGINT, or the control command, in which case it will report statistics so far and quickly exit. If innduct receives SIGKILL nothing will be broken or corrupted; you just won't see some of the article stats. +.LP innduct listens on an AF_UNIX socket, and provides a command-line interface which can be used to trigger various events and for -debugging. -.LP -The socket is called -.IB feedfile _control +debugging. The socket is called +.IB feedfile _cli and when connected reads and writes lines (with unix line endings). It can most easily be accessed with a program like .I netcat-openbsd (eg .B nc.openbsd -U -.IR feedfile \fB_control\fR) +.IR feedfile \fB_cli\fR) or .IR socat . -The CLI has as a prompt +The prompt is .IR site \fB|\fR. .LP -Because there is a fairly short limit on the length of pathnames used -for AF_UNIX sockets, innduct actually creates the socket with a unique -name in a different dedicated subdirectory of /tmp, and makes -.IB feedfile _control -a symlink to the real socket. -.LP The following control commands are supported: .TP .B h @@ -498,6 +485,10 @@ safely remove backlog files. \fIsomething\fR may not contain \fB#\fR you rename it to match the pattern \fIfeedfile\fR\fB_backlog\fR*, as otherwise innduct may find and process the file and read it to EOF before you have finished creating it. +.IP \fIfeedfile\fR_cli +.IX Item "control command line socket" +Default AF_UNIX listening socket for the control command line. See +CONTROLLING INNDUCT, above. .IP \fIfeedfile\fR_dump .IX Item "debug dump file" On request via a control connection innduct dumps a summary of its -- 2.30.2