summaryrefslogtreecommitdiffabout
path: root/src/net.c
Side-by-side diff
Diffstat (limited to 'src/net.c') (more/less context) (ignore whitespace changes)
-rw-r--r--src/net.c227
1 files changed, 227 insertions, 0 deletions
diff --git a/src/net.c b/src/net.c
new file mode 100644
index 0000000..efb6225
--- a/dev/null
+++ b/src/net.c
@@ -0,0 +1,227 @@
+/* wydawca - automatic release submission daemon
+ Copyright (C) 2007, 2009 Sergey Poznyakoff
+
+ Wydawca 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 of the License, or (at your
+ option) any later version.
+
+ Wydawca 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 wydawca. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "wydawca.h"
+
+static int
+open_listener ()
+{
+ int fd;
+
+ if (listen_sockaddr.sa == NULL)
+ {
+ logmsg (LOG_CRIT, _("listener address is not configured"));
+ exit (1);
+ }
+
+ fd = socket (listen_sockaddr.sa->sa_family, SOCK_STREAM, 0);
+ if (fd == -1)
+ {
+ logmsg (LOG_CRIT, _("cannot create socket: %s"),
+ strerror(errno));
+ exit (1);
+ }
+ if (listen_sockaddr.sa->sa_family == AF_UNIX)
+ {
+ struct stat st;
+ struct sockaddr_un *s_un = (struct sockaddr_un *) listen_sockaddr.sa;
+ if (stat (s_un->sun_path, &st))
+ {
+ if (errno != ENOENT)
+ {
+ logmsg (LOG_CRIT, _("%s: cannot stat socket: %s"),
+ s_un->sun_path, strerror (errno));
+ exit (1);
+ }
+ }
+ else
+ {
+ /* FIXME: Check permissions? */
+ if (!S_ISSOCK (st.st_mode))
+ {
+ logmsg (LOG_CRIT, _("%s: not a socket"),
+ s_un->sun_path, strerror (errno));
+ exit (1);
+ }
+ unlink (s_un->sun_path);
+ }
+ /* FIXME: Setup umask */
+ }
+ else
+ {
+ int yes = 1;
+ setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (void *) &yes, sizeof(yes));
+ }
+
+ if (bind (fd, listen_sockaddr.sa, listen_sockaddr.len) < 0)
+ {
+ logmsg (LOG_CRIT, _("cannot bind to local address: %s"),
+ strerror (errno));
+ close (fd);
+ exit (1);
+ }
+ if (listen (fd, 8) == -1)
+ {
+ logmsg (LOG_CRIT, "listen: %s", strerror (errno));
+ close (fd);
+ exit (1);
+ }
+
+ return fd;
+}
+
+static void
+trim_crlf (char *s)
+{
+ size_t len = strlen (s);
+ if (len > 0 && s[len-1] == '\n')
+ {
+ s[--len] = 0;
+ if (len > 0 && s[len-1] == '\r')
+ s[--len] = 0;
+ }
+}
+
+void
+handle_connection (FILE *fp)
+{
+ char *buf = NULL;
+ size_t buflen = 0;
+ const struct spool *spool;
+ char *p;
+ struct passwd *pw;
+
+ if (getline (&buf, &buflen, fp) <= 0)
+ return;
+ trim_crlf (buf);
+ if (debug_level)
+ logmsg (LOG_DEBUG, "recv: %s", buf);
+ spool = wydawca_find_spool (buf);
+ if (!spool)
+ {
+ fprintf (fp, "- Unknown service name\r\n");
+ free (buf);
+ return;
+ }
+ else if (spool->url)
+ fprintf (fp, "+ OK, URL %s\r\n", spool->url);
+ else
+ fprintf (fp, "+ OK, spool %s\r\n", spool->tag);
+
+ if (getline (&buf, &buflen, fp) <= 0)
+ {
+ logmsg (LOG_ERR, "protocol error");
+ free (buf);
+ return;
+ }
+
+ if (debug_level)
+ logmsg (LOG_DEBUG, "recv: %s", buf);
+
+ p = strchr (buf, ' ');
+ if (p)
+ {
+ *p++ = 0;
+ while (*p && (*p == ' ' || *p == '\t'))
+ p++;
+ }
+ else
+ p = "";
+
+ pw = getpwnam (buf);
+ if (pw)
+ schedule_job (spool, pw->pw_uid);
+ else
+ logmsg (LOG_ERR, "no such user: %s", buf);
+ free (buf);
+}
+
+static int reconfigure;
+static int terminate;
+
+RETSIGTYPE
+sig_hup (int sig)
+{
+ reconfigure = 1;
+ terminate = 1;
+}
+
+RETSIGTYPE
+sig_term (int sig)
+{
+ terminate = 1;
+}
+
+void
+wydawca_listener ()
+{
+ int ctlfd = open_listener ();
+
+ job_init ();
+ signal (SIGHUP, sig_hup);
+ signal (SIGTERM, sig_term);
+ signal (SIGQUIT, sig_term);
+ signal (SIGINT, sig_term);
+ while (!terminate)
+ {
+ int fd;
+ FILE *fp;
+ int rc;
+ fd_set rset;
+ struct timeval to, *pto;
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in s_in;
+ struct sockaddr_un s_un;
+ } addr;
+ socklen_t len;
+
+ job_queue_runner ();
+ FD_ZERO (&rset);
+ FD_SET (ctlfd, &rset);
+
+ if (wakeup_interval)
+ {
+ to.tv_sec = wakeup_interval;
+ to.tv_usec = 0;
+ *pto = to;
+ }
+ else
+ pto = NULL;
+
+ rc = select (ctlfd + 1, &rset, NULL, NULL, pto);
+ if (rc == 0)
+ continue;
+ else if (rc < 0)
+ {
+ if (errno == EINTR)
+ continue;
+ logmsg (LOG_ERR, "select: %s", strerror (errno));
+ break;
+ }
+
+ len = sizeof (addr);
+ fd = accept (ctlfd, (struct sockaddr*) &addr, &len);
+ if (fd == -1)
+ continue;
+ /* FIXME: Check if the connection is allowed */
+ fp = fdopen (fd, "r+");
+ handle_connection (fp);
+ fclose (fp);
+ }
+}
+
+

Return to:

Send suggestions and report system problems to the System administrator.