[PATCH] Install git-verify-tag-script
[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 <netinet/in.h>
7 #include <arpa/inet.h>
8
9 static const char daemon_usage[] = "git-daemon [--inetd | --port=n]";
10
11 static int upload(char *dir, int dirlen)
12 {
13         if (chdir(dir) < 0)
14                 return -1;
15         chdir(".git");
16
17         /*
18          * Security on the cheap.
19          *
20          * We want a readable HEAD, usable "objects" directory, and 
21          * a "git-daemon-export-ok" flag that says that the other side
22          * is ok with us doing this.
23          */
24         if (access("git-daemon-export-ok", F_OK) ||
25             access("objects/00", X_OK) ||
26             access("HEAD", R_OK))
27                 return -1;
28
29         /*
30          * We'll ignore SIGTERM from now on, we have a
31          * good client.
32          */
33         signal(SIGTERM, SIG_IGN);
34
35         /* git-upload-pack only ever reads stuff, so this is safe */
36         execlp("git-upload-pack", "git-upload-pack", ".", NULL);
37         return -1;
38 }
39
40 static int execute(void)
41 {
42         static char line[1000];
43         int len;
44
45         len = packet_read_line(0, line, sizeof(line));
46
47         if (len && line[len-1] == '\n')
48                 line[--len] = 0;
49
50         if (!strncmp("git-upload-pack /", line, 17))
51                 return upload(line + 16, len - 16);
52
53         fprintf(stderr, "got bad connection '%s'\n", line);
54         return -1;
55 }
56
57
58 /*
59  * We count spawned/reaped separately, just to avoid any
60  * races when updating them from signals. The SIGCHLD handler
61  * will only update children_reaped, and the fork logic will
62  * only update children_spawned.
63  *
64  * MAX_CHILDREN should be a power-of-two to make the modulus
65  * operation cheap. It should also be at least twice
66  * the maximum number of connections we will ever allow.
67  */
68 #define MAX_CHILDREN 128
69
70 static int max_connections = 25;
71
72 /* These are updated by the signal handler */
73 static volatile unsigned int children_reaped = 0;
74 pid_t dead_child[MAX_CHILDREN];
75
76 /* These are updated by the main loop */
77 static unsigned int children_spawned = 0;
78 static unsigned int children_deleted = 0;
79
80 struct child {
81         pid_t pid;
82         int addrlen;
83         struct sockaddr_in address;
84 } live_child[MAX_CHILDREN];
85
86 static void add_child(int idx, pid_t pid, struct sockaddr_in *addr, int addrlen)
87 {
88         live_child[idx].pid = pid;
89         live_child[idx].addrlen = addrlen;
90         live_child[idx].address = *addr;
91 }
92
93 /*
94  * Walk from "deleted" to "spawned", and remove child "pid".
95  *
96  * We move everything up by one, since the new "deleted" will
97  * be one higher.
98  */
99 static void remove_child(pid_t pid, unsigned deleted, unsigned spawned)
100 {
101         struct child n;
102
103         deleted %= MAX_CHILDREN;
104         spawned %= MAX_CHILDREN;
105         if (live_child[deleted].pid == pid) {
106                 live_child[deleted].pid = -1;
107                 return;
108         }
109         n = live_child[deleted];
110         for (;;) {
111                 struct child m;
112                 deleted = (deleted + 1) % MAX_CHILDREN;
113                 if (deleted == spawned)
114                         die("could not find dead child %d\n", pid);
115                 m = live_child[deleted];
116                 live_child[deleted] = n;
117                 if (m.pid == pid)
118                         return;
119                 n = m;
120         }
121 }
122
123 /*
124  * This gets called if the number of connections grows
125  * past "max_connections".
126  *
127  * We _should_ start off by searching for connections
128  * from the same IP, and if there is some address wth
129  * multiple connections, we should kill that first.
130  *
131  * As it is, we just "randomly" kill 25% of the connections,
132  * and our pseudo-random generator sucks too. I have no
133  * shame.
134  *
135  * Really, this is just a place-holder for a _real_ algorithm.
136  */
137 static void kill_some_children(int signo, unsigned start, unsigned stop)
138 {
139         start %= MAX_CHILDREN;
140         stop %= MAX_CHILDREN;
141         while (start != stop) {
142                 if (!(start & 3))
143                         kill(live_child[start].pid, signo);
144                 start = (start + 1) % MAX_CHILDREN;
145         }
146 }
147
148 static void check_max_connections(void)
149 {
150         for (;;) {
151                 int active;
152                 unsigned spawned, reaped, deleted;
153
154                 spawned = children_spawned;
155                 reaped = children_reaped;
156                 deleted = children_deleted;
157
158                 while (deleted < reaped) {
159                         pid_t pid = dead_child[deleted % MAX_CHILDREN];
160                         remove_child(pid, deleted, spawned);
161                         deleted++;
162                 }
163                 children_deleted = deleted;
164
165                 active = spawned - deleted;
166                 if (active <= max_connections)
167                         break;
168
169                 /* Kill some unstarted connections with SIGTERM */
170                 kill_some_children(SIGTERM, deleted, spawned);
171                 if (active <= max_connections << 1)
172                         break;
173
174                 /* If the SIGTERM thing isn't helping use SIGKILL */
175                 kill_some_children(SIGKILL, deleted, spawned);
176                 sleep(1);
177         }
178 }
179
180 static void handle(int incoming, struct sockaddr_in *addr, int addrlen)
181 {
182         pid_t pid = fork();
183
184         if (pid) {
185                 unsigned idx;
186
187                 close(incoming);
188                 if (pid < 0)
189                         return;
190
191                 idx = children_spawned % MAX_CHILDREN;
192                 children_spawned++;
193                 add_child(idx, pid, addr, addrlen);
194
195                 check_max_connections();
196                 return;
197         }
198
199         dup2(incoming, 0);
200         dup2(incoming, 1);
201         close(incoming);
202         exit(execute());
203 }
204
205 static void child_handler(int signo)
206 {
207         for (;;) {
208                 pid_t pid = waitpid(-1, NULL, WNOHANG);
209
210                 if (pid > 0) {
211                         unsigned reaped = children_reaped;
212                         dead_child[reaped % MAX_CHILDREN] = pid;
213                         children_reaped = reaped + 1;
214                         continue;
215                 }
216                 break;
217         }
218 }
219
220 static int serve(int port)
221 {
222         int sockfd;
223         struct sockaddr_in addr;
224
225         signal(SIGCHLD, child_handler);
226         sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_IP);
227         if (sockfd < 0)
228                 die("unable to open socket (%s)", strerror(errno));
229         memset(&addr, 0, sizeof(addr));
230         addr.sin_port = htons(port);
231         addr.sin_family = AF_INET;
232         if (bind(sockfd, (void *)&addr, sizeof(addr)) < 0)
233                 die("unable to bind to port %d (%s)", port, strerror(errno));
234         if (listen(sockfd, 5) < 0)
235                 die("unable to listen to port %d (%s)", port, strerror(errno));
236
237         for (;;) {
238                 struct sockaddr_in in;
239                 socklen_t addrlen = sizeof(in);
240                 int incoming = accept(sockfd, (void *)&in, &addrlen);
241
242                 if (incoming < 0) {
243                         switch (errno) {
244                         case EAGAIN:
245                         case EINTR:
246                         case ECONNABORTED:
247                                 continue;
248                         default:
249                                 die("accept returned %s", strerror(errno));
250                         }
251                 }
252                 handle(incoming, &in, addrlen);
253         }
254 }
255
256 int main(int argc, char **argv)
257 {
258         int port = DEFAULT_GIT_PORT;
259         int inetd_mode = 0;
260         int i;
261
262         for (i = 1; i < argc; i++) {
263                 char *arg = argv[i];
264
265                 if (!strncmp(arg, "--port=", 7)) {
266                         char *end;
267                         unsigned long n;
268                         n = strtoul(arg+7, &end, 0);
269                         if (arg[7] && !*end) {
270                                 port = n;
271                                 continue;
272                         }
273                 }
274
275                 if (!strcmp(arg, "--inetd")) {
276                         inetd_mode = 1;
277                         continue;
278                 }
279
280                 usage(daemon_usage);
281         }
282
283         if (inetd_mode)
284                 return execute();
285
286         return serve(port);
287 }