[PATCH] rsh.c env and quoting cleanup, take 2
[git.git] / daemon.c
1 #include "cache.h"
2 #include "pkt-line.h"
3 #include <signal.h>
4 #include <sys/wait.h>
5 #include <sys/socket.h>
6 #include <sys/time.h>
7 #include <netdb.h>
8 #include <netinet/in.h>
9
10 static const char daemon_usage[] = "git-daemon [--inetd | --port=n]";
11
12 static int upload(char *dir, int dirlen)
13 {
14         if (chdir(dir) < 0)
15                 return -1;
16         chdir(".git");
17
18         /*
19          * Security on the cheap.
20          *
21          * We want a readable HEAD, usable "objects" directory, and 
22          * a "git-daemon-export-ok" flag that says that the other side
23          * is ok with us doing this.
24          */
25         if (access("git-daemon-export-ok", F_OK) ||
26             access("objects/00", X_OK) ||
27             access("HEAD", R_OK))
28                 return -1;
29
30         /*
31          * We'll ignore SIGTERM from now on, we have a
32          * good client.
33          */
34         signal(SIGTERM, SIG_IGN);
35
36         /* git-upload-pack only ever reads stuff, so this is safe */
37         execlp("git-upload-pack", "git-upload-pack", ".", NULL);
38         return -1;
39 }
40
41 static int execute(void)
42 {
43         static char line[1000];
44         int len;
45
46         len = packet_read_line(0, line, sizeof(line));
47
48         if (len && line[len-1] == '\n')
49                 line[--len] = 0;
50
51         if (!strncmp("git-upload-pack /", line, 17))
52                 return upload(line + 16, len - 16);
53
54         fprintf(stderr, "got bad connection '%s'\n", line);
55         return -1;
56 }
57
58
59 /*
60  * We count spawned/reaped separately, just to avoid any
61  * races when updating them from signals. The SIGCHLD handler
62  * will only update children_reaped, and the fork logic will
63  * only update children_spawned.
64  *
65  * MAX_CHILDREN should be a power-of-two to make the modulus
66  * operation cheap. It should also be at least twice
67  * the maximum number of connections we will ever allow.
68  */
69 #define MAX_CHILDREN 128
70
71 static int max_connections = 25;
72
73 /* These are updated by the signal handler */
74 static volatile unsigned int children_reaped = 0;
75 static pid_t dead_child[MAX_CHILDREN];
76
77 /* These are updated by the main loop */
78 static unsigned int children_spawned = 0;
79 static unsigned int children_deleted = 0;
80
81 static struct child {
82         pid_t pid;
83         int addrlen;
84         struct sockaddr_storage address;
85 } live_child[MAX_CHILDREN];
86
87 static void add_child(int idx, pid_t pid, struct sockaddr *addr, int addrlen)
88 {
89         live_child[idx].pid = pid;
90         live_child[idx].addrlen = addrlen;
91         memcpy(&live_child[idx].address, addr, addrlen);
92 }
93
94 /*
95  * Walk from "deleted" to "spawned", and remove child "pid".
96  *
97  * We move everything up by one, since the new "deleted" will
98  * be one higher.
99  */
100 static void remove_child(pid_t pid, unsigned deleted, unsigned spawned)
101 {
102         struct child n;
103
104         deleted %= MAX_CHILDREN;
105         spawned %= MAX_CHILDREN;
106         if (live_child[deleted].pid == pid) {
107                 live_child[deleted].pid = -1;
108                 return;
109         }
110         n = live_child[deleted];
111         for (;;) {
112                 struct child m;
113                 deleted = (deleted + 1) % MAX_CHILDREN;
114                 if (deleted == spawned)
115                         die("could not find dead child %d\n", pid);
116                 m = live_child[deleted];
117                 live_child[deleted] = n;
118                 if (m.pid == pid)
119                         return;
120                 n = m;
121         }
122 }
123
124 /*
125  * This gets called if the number of connections grows
126  * past "max_connections".
127  *
128  * We _should_ start off by searching for connections
129  * from the same IP, and if there is some address wth
130  * multiple connections, we should kill that first.
131  *
132  * As it is, we just "randomly" kill 25% of the connections,
133  * and our pseudo-random generator sucks too. I have no
134  * shame.
135  *
136  * Really, this is just a place-holder for a _real_ algorithm.
137  */
138 static void kill_some_children(int signo, unsigned start, unsigned stop)
139 {
140         start %= MAX_CHILDREN;
141         stop %= MAX_CHILDREN;
142         while (start != stop) {
143                 if (!(start & 3))
144                         kill(live_child[start].pid, signo);
145                 start = (start + 1) % MAX_CHILDREN;
146         }
147 }
148
149 static void check_max_connections(void)
150 {
151         for (;;) {
152                 int active;
153                 unsigned spawned, reaped, deleted;
154
155                 spawned = children_spawned;
156                 reaped = children_reaped;
157                 deleted = children_deleted;
158
159                 while (deleted < reaped) {
160                         pid_t pid = dead_child[deleted % MAX_CHILDREN];
161                         remove_child(pid, deleted, spawned);
162                         deleted++;
163                 }
164                 children_deleted = deleted;
165
166                 active = spawned - deleted;
167                 if (active <= max_connections)
168                         break;
169
170                 /* Kill some unstarted connections with SIGTERM */
171                 kill_some_children(SIGTERM, deleted, spawned);
172                 if (active <= max_connections << 1)
173                         break;
174
175                 /* If the SIGTERM thing isn't helping use SIGKILL */
176                 kill_some_children(SIGKILL, deleted, spawned);
177                 sleep(1);
178         }
179 }
180
181 static void handle(int incoming, struct sockaddr *addr, int addrlen)
182 {
183         pid_t pid = fork();
184
185         if (pid) {
186                 unsigned idx;
187
188                 close(incoming);
189                 if (pid < 0)
190                         return;
191
192                 idx = children_spawned % MAX_CHILDREN;
193                 children_spawned++;
194                 add_child(idx, pid, addr, addrlen);
195
196                 check_max_connections();
197                 return;
198         }
199
200         dup2(incoming, 0);
201         dup2(incoming, 1);
202         close(incoming);
203         exit(execute());
204 }
205
206 static void child_handler(int signo)
207 {
208         for (;;) {
209                 pid_t pid = waitpid(-1, NULL, WNOHANG);
210
211                 if (pid > 0) {
212                         unsigned reaped = children_reaped;
213                         dead_child[reaped % MAX_CHILDREN] = pid;
214                         children_reaped = reaped + 1;
215                         continue;
216                 }
217                 break;
218         }
219 }
220
221 static int serve(int port)
222 {
223         struct addrinfo hints, *ai0, *ai;
224         int gai;
225         int socknum = 0, *socklist = NULL;
226         int maxfd = -1;
227         fd_set fds_init, fds;
228         char pbuf[NI_MAXSERV];
229
230         signal(SIGCHLD, child_handler);
231
232         sprintf(pbuf, "%d", port);
233         memset(&hints, 0, sizeof(hints));
234         hints.ai_family = AF_UNSPEC;
235         hints.ai_socktype = SOCK_STREAM;
236         hints.ai_protocol = IPPROTO_TCP;
237         hints.ai_flags = AI_PASSIVE;
238
239         gai = getaddrinfo(NULL, pbuf, &hints, &ai0);
240         if (gai)
241                 die("getaddrinfo() failed: %s\n", gai_strerror(gai));
242
243         FD_ZERO(&fds_init);
244
245         for (ai = ai0; ai; ai = ai->ai_next) {
246                 int sockfd;
247                 int *newlist;
248
249                 sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
250                 if (sockfd < 0)
251                         continue;
252                 if (sockfd >= FD_SETSIZE) {
253                         error("too large socket descriptor.");
254                         close(sockfd);
255                         continue;
256                 }
257
258 #ifdef IPV6_V6ONLY
259                 if (ai->ai_family == AF_INET6) {
260                         int on = 1;
261                         setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY,
262                                    &on, sizeof(on));
263                         /* Note: error is not fatal */
264                 }
265 #endif
266
267                 if (bind(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) {
268                         close(sockfd);
269                         continue;       /* not fatal */
270                 }
271                 if (listen(sockfd, 5) < 0) {
272                         close(sockfd);
273                         continue;       /* not fatal */
274                 }
275
276                 newlist = realloc(socklist, sizeof(int) * (socknum + 1));
277                 if (!newlist)
278                         die("memory allocation failed: %s", strerror(errno));
279
280                 socklist = newlist;
281                 socklist[socknum++] = sockfd;
282
283                 FD_SET(sockfd, &fds_init);
284                 if (maxfd < sockfd)
285                         maxfd = sockfd;
286         }
287
288         freeaddrinfo(ai0);
289
290         if (socknum == 0)
291                 die("unable to allocate any listen sockets on port %u", port);
292
293         for (;;) {
294                 int i;
295                 fds = fds_init;
296                 
297                 if (select(maxfd + 1, &fds, NULL, NULL, NULL) < 0) {
298                         if (errno != EINTR) {
299                                 error("select failed, resuming: %s",
300                                       strerror(errno));
301                                 sleep(1);
302                         }
303                         continue;
304                 }
305
306                 for (i = 0; i < socknum; i++) {
307                         int sockfd = socklist[i];
308
309                         if (FD_ISSET(sockfd, &fds)) {
310                                 struct sockaddr_storage ss;
311                                 int sslen = sizeof(ss);
312                                 int incoming = accept(sockfd, (struct sockaddr *)&ss, &sslen);
313                                 if (incoming < 0) {
314                                         switch (errno) {
315                                         case EAGAIN:
316                                         case EINTR:
317                                         case ECONNABORTED:
318                                                 continue;
319                                         default:
320                                                 die("accept returned %s", strerror(errno));
321                                         }
322                                 }
323                                 handle(incoming, (struct sockaddr *)&ss, sslen);
324                         }
325                 }
326         }
327 }
328
329 int main(int argc, char **argv)
330 {
331         int port = DEFAULT_GIT_PORT;
332         int inetd_mode = 0;
333         int i;
334
335         for (i = 1; i < argc; i++) {
336                 char *arg = argv[i];
337
338                 if (!strncmp(arg, "--port=", 7)) {
339                         char *end;
340                         unsigned long n;
341                         n = strtoul(arg+7, &end, 0);
342                         if (arg[7] && !*end) {
343                                 port = n;
344                                 continue;
345                         }
346                 }
347
348                 if (!strcmp(arg, "--inetd")) {
349                         inetd_mode = 1;
350                         continue;
351                 }
352
353                 usage(daemon_usage);
354         }
355
356         if (inetd_mode) {
357                 fclose(stderr); //FIXME: workaround
358                 return execute();
359         }
360
361         return serve(port);
362 }