aboutsummaryrefslogtreecommitdiff
path: root/src/net.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/net.c')
-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
--- /dev/null
+++ b/src/net.c
@@ -0,0 +1,227 @@
1/* wydawca - automatic release submission daemon
2 Copyright (C) 2007, 2009 Sergey Poznyakoff
3
4 Wydawca is free software; you can redistribute it and/or modify it
5 under the terms of the GNU General Public License as published by the
6 Free Software Foundation; either version 3 of the License, or (at your
7 option) any later version.
8
9 Wydawca is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with wydawca. If not, see <http://www.gnu.org/licenses/>. */
16
17#include "wydawca.h"
18
19static int
20open_listener ()
21{
22 int fd;
23
24 if (listen_sockaddr.sa == NULL)
25 {
26 logmsg (LOG_CRIT, _("listener address is not configured"));
27 exit (1);
28 }
29
30 fd = socket (listen_sockaddr.sa->sa_family, SOCK_STREAM, 0);
31 if (fd == -1)
32 {
33 logmsg (LOG_CRIT, _("cannot create socket: %s"),
34 strerror(errno));
35 exit (1);
36 }
37 if (listen_sockaddr.sa->sa_family == AF_UNIX)
38 {
39 struct stat st;
40 struct sockaddr_un *s_un = (struct sockaddr_un *) listen_sockaddr.sa;
41 if (stat (s_un->sun_path, &st))
42 {
43 if (errno != ENOENT)
44 {
45 logmsg (LOG_CRIT, _("%s: cannot stat socket: %s"),
46 s_un->sun_path, strerror (errno));
47 exit (1);
48 }
49 }
50 else
51 {
52 /* FIXME: Check permissions? */
53 if (!S_ISSOCK (st.st_mode))
54 {
55 logmsg (LOG_CRIT, _("%s: not a socket"),
56 s_un->sun_path, strerror (errno));
57 exit (1);
58 }
59 unlink (s_un->sun_path);
60 }
61 /* FIXME: Setup umask */
62 }
63 else
64 {
65 int yes = 1;
66 setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (void *) &yes, sizeof(yes));
67 }
68
69 if (bind (fd, listen_sockaddr.sa, listen_sockaddr.len) < 0)
70 {
71 logmsg (LOG_CRIT, _("cannot bind to local address: %s"),
72 strerror (errno));
73 close (fd);
74 exit (1);
75 }
76 if (listen (fd, 8) == -1)
77 {
78 logmsg (LOG_CRIT, "listen: %s", strerror (errno));
79 close (fd);
80 exit (1);
81 }
82
83 return fd;
84}
85
86static void
87trim_crlf (char *s)
88{
89 size_t len = strlen (s);
90 if (len > 0 && s[len-1] == '\n')
91 {
92 s[--len] = 0;
93 if (len > 0 && s[len-1] == '\r')
94 s[--len] = 0;
95 }
96}
97
98void
99handle_connection (FILE *fp)
100{
101 char *buf = NULL;
102 size_t buflen = 0;
103 const struct spool *spool;
104 char *p;
105 struct passwd *pw;
106
107 if (getline (&buf, &buflen, fp) <= 0)
108 return;
109 trim_crlf (buf);
110 if (debug_level)
111 logmsg (LOG_DEBUG, "recv: %s", buf);
112 spool = wydawca_find_spool (buf);
113 if (!spool)
114 {
115 fprintf (fp, "- Unknown service name\r\n");
116 free (buf);
117 return;
118 }
119 else if (spool->url)
120 fprintf (fp, "+ OK, URL %s\r\n", spool->url);
121 else
122 fprintf (fp, "+ OK, spool %s\r\n", spool->tag);
123
124 if (getline (&buf, &buflen, fp) <= 0)
125 {
126 logmsg (LOG_ERR, "protocol error");
127 free (buf);
128 return;
129 }
130
131 if (debug_level)
132 logmsg (LOG_DEBUG, "recv: %s", buf);
133
134 p = strchr (buf, ' ');
135 if (p)
136 {
137 *p++ = 0;
138 while (*p && (*p == ' ' || *p == '\t'))
139 p++;
140 }
141 else
142 p = "";
143
144 pw = getpwnam (buf);
145 if (pw)
146 schedule_job (spool, pw->pw_uid);
147 else
148 logmsg (LOG_ERR, "no such user: %s", buf);
149 free (buf);
150}
151
152static int reconfigure;
153static int terminate;
154
155RETSIGTYPE
156sig_hup (int sig)
157{
158 reconfigure = 1;
159 terminate = 1;
160}
161
162RETSIGTYPE
163sig_term (int sig)
164{
165 terminate = 1;
166}
167
168void
169wydawca_listener ()
170{
171 int ctlfd = open_listener ();
172
173 job_init ();
174 signal (SIGHUP, sig_hup);
175 signal (SIGTERM, sig_term);
176 signal (SIGQUIT, sig_term);
177 signal (SIGINT, sig_term);
178 while (!terminate)
179 {
180 int fd;
181 FILE *fp;
182 int rc;
183 fd_set rset;
184 struct timeval to, *pto;
185 union {
186 struct sockaddr sa;
187 struct sockaddr_in s_in;
188 struct sockaddr_un s_un;
189 } addr;
190 socklen_t len;
191
192 job_queue_runner ();
193 FD_ZERO (&rset);
194 FD_SET (ctlfd, &rset);
195
196 if (wakeup_interval)
197 {
198 to.tv_sec = wakeup_interval;
199 to.tv_usec = 0;
200 *pto = to;
201 }
202 else
203 pto = NULL;
204
205 rc = select (ctlfd + 1, &rset, NULL, NULL, pto);
206 if (rc == 0)
207 continue;
208 else if (rc < 0)
209 {
210 if (errno == EINTR)
211 continue;
212 logmsg (LOG_ERR, "select: %s", strerror (errno));
213 break;
214 }
215
216 len = sizeof (addr);
217 fd = accept (ctlfd, (struct sockaddr*) &addr, &len);
218 if (fd == -1)
219 continue;
220 /* FIXME: Check if the connection is allowed */
221 fp = fdopen (fd, "r+");
222 handle_connection (fp);
223 fclose (fp);
224 }
225}
226
227

Return to:

Send suggestions and report system problems to the System administrator.