]> asedeno.scripts.mit.edu Git - git.git/blobdiff - daemon.c
blame: --show-stats for easier optimization work.
[git.git] / daemon.c
index 69ea35c22dcff884899a083b678b0a4757e546ad..2a20ca55cbe912a8ddd4bea8b2476ae30215903a 100644 (file)
--- a/daemon.c
+++ b/daemon.c
@@ -1,20 +1,14 @@
-#include <signal.h>
-#include <sys/wait.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <sys/poll.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <syslog.h>
-#include <pwd.h>
-#include <grp.h>
-#include <limits.h>
-#include "pkt-line.h"
 #include "cache.h"
+#include "pkt-line.h"
 #include "exec_cmd.h"
 #include "interpolate.h"
 
+#include <syslog.h>
+
+#ifndef HOST_NAME_MAX
+#define HOST_NAME_MAX 256
+#endif
+
 static int log_syslog;
 static int verbose;
 static int reuseaddr;
@@ -71,7 +65,7 @@ static struct interp interp_table[] = {
        { "%IP", 0},
        { "%P", 0},
        { "%D", 0},
-       { "%%", "%"},
+       { "%%", 0},
 };
 
 
@@ -108,7 +102,7 @@ static void logreport(int priority, const char *err, va_list params)
        buf[buflen++] = '\n';
        buf[buflen] = '\0';
 
-       write(2, buf, buflen);
+       write_in_full(2, buf, buflen);
 }
 
 static void logerror(const char *err, ...)
@@ -378,9 +372,16 @@ static int upload_archive(void)
        return -1;
 }
 
+static int receive_pack(void)
+{
+       execl_git_cmd("receive-pack", ".", NULL);
+       return -1;
+}
+
 static struct daemon_service daemon_service[] = {
        { "upload-archive", "uploadarch", upload_archive, 0, 1 },
        { "upload-pack", "uploadpack", upload_pack, 1, 1 },
+       { "receive-pack", "receivepack", receive_pack, 0, 1 },
 };
 
 static void enable_service(const char *name, int ena) {
@@ -405,7 +406,11 @@ static void make_service_overridable(const char *name, int ena) {
        die("No such service %s", name);
 }
 
-static void parse_extra_args(char *extra_args, int buflen)
+/*
+ * Separate the "extra args" information as supplied by the client connection.
+ * Any resulting data is squirreled away in the given interpolation table.
+ */
+static void parse_extra_args(struct interp *table, char *extra_args, int buflen)
 {
        char *val;
        int vallen;
@@ -417,18 +422,17 @@ static void parse_extra_args(char *extra_args, int buflen)
                        val = extra_args + 5;
                        vallen = strlen(val) + 1;
                        if (*val) {
-                               char *port;
-                               char *save = xmalloc(vallen);   /* FIXME: Leak */
-
-                               interp_table[INTERP_SLOT_HOST].value = save;
-                               strlcpy(save, val, vallen);
-                               port = strrchr(save, ':');
+                               /* Split <host>:<port> at colon. */
+                               char *host = val;
+                               char *port = strrchr(host, ':');
                                if (port) {
                                        *port = 0;
                                        port++;
-                                       interp_table[INTERP_SLOT_PORT].value = port;
+                                       interp_set_entry(table, INTERP_SLOT_PORT, port);
                                }
+                               interp_set_entry(table, INTERP_SLOT_HOST, host);
                        }
+
                        /* On to the next one */
                        extra_args = val + vallen;
                }
@@ -438,13 +442,13 @@ static void parse_extra_args(char *extra_args, int buflen)
 void fill_in_extra_table_entries(struct interp *itable)
 {
        char *hp;
-       char *canon_host = NULL;
-       char *ipaddr = NULL;
 
        /*
         * Replace literal host with lowercase-ized hostname.
         */
        hp = interp_table[INTERP_SLOT_HOST].value;
+       if (!hp)
+               return;
        for ( ; *hp; hp++)
                *hp = tolower(*hp);
 
@@ -466,10 +470,12 @@ void fill_in_extra_table_entries(struct interp *itable)
                        for (ai = ai0; ai; ai = ai->ai_next) {
                                struct sockaddr_in *sin_addr = (void *)ai->ai_addr;
 
-                               canon_host = xstrdup(ai->ai_canonname);
                                inet_ntop(AF_INET, &sin_addr->sin_addr,
                                          addrbuf, sizeof(addrbuf));
-                               ipaddr = addrbuf;
+                               interp_set_entry(interp_table,
+                                                INTERP_SLOT_CANON_HOST, ai->ai_canonname);
+                               interp_set_entry(interp_table,
+                                                INTERP_SLOT_IP, addrbuf);
                                break;
                        }
                        freeaddrinfo(ai0);
@@ -483,7 +489,6 @@ void fill_in_extra_table_entries(struct interp *itable)
                static char addrbuf[HOST_NAME_MAX + 1];
 
                hent = gethostbyname(interp_table[INTERP_SLOT_HOST].value);
-               canon_host = xstrdup(hent->h_name);
 
                ap = hent->h_addr_list;
                memset(&sa, 0, sizeof sa);
@@ -493,12 +498,11 @@ void fill_in_extra_table_entries(struct interp *itable)
 
                inet_ntop(hent->h_addrtype, &sa.sin_addr,
                          addrbuf, sizeof(addrbuf));
-               ipaddr = addrbuf;
+
+               interp_set_entry(interp_table, INTERP_SLOT_CANON_HOST, hent->h_name);
+               interp_set_entry(interp_table, INTERP_SLOT_IP, addrbuf);
        }
 #endif
-
-       interp_table[INTERP_SLOT_CANON_HOST].value = canon_host;        /* FIXME: Leak */
-       interp_table[INTERP_SLOT_IP].value = xstrdup(ipaddr);           /* FIXME: Leak */
 }
 
 
@@ -539,11 +543,19 @@ static int execute(struct sockaddr *addr)
                loginfo("Extended attributes (%d bytes) exist <%.*s>",
                        (int) pktlen - len,
                        (int) pktlen - len, line + len + 1);
-       if (len && line[len-1] == '\n')
+       if (len && line[len-1] == '\n') {
                line[--len] = 0;
+               pktlen--;
+       }
+
+       /*
+        * Initialize the path interpolation table for this connection.
+        */
+       interp_clear_table(interp_table, ARRAY_SIZE(interp_table));
+       interp_set_entry(interp_table, INTERP_SLOT_PERCENT, "%");
 
        if (len != pktlen) {
-           parse_extra_args(line + len + 1, pktlen - len - 1);
+           parse_extra_args(interp_table, line + len + 1, pktlen - len - 1);
            fill_in_extra_table_entries(interp_table);
        }
 
@@ -553,7 +565,12 @@ static int execute(struct sockaddr *addr)
                if (!strncmp("git-", line, 4) &&
                    !strncmp(s->name, line + 4, namelen) &&
                    line[namelen + 4] == ' ') {
-                       interp_table[INTERP_SLOT_DIR].value = line+namelen+5;
+                       /*
+                        * Note: The directory here is probably context sensitive,
+                        * and might depend on the actual service being performed.
+                        */
+                       interp_set_entry(interp_table,
+                                        INTERP_SLOT_DIR, line + namelen + 5);
                        return run_service(interp_table, s);
                }
        }
@@ -818,7 +835,7 @@ static int socksetup(char *listen_addr, int listen_port, int **socklist_p)
 
 #else /* NO_IPV6 */
 
-static int socksetup(char *lisen_addr, int listen_port, int **socklist_p)
+static int socksetup(char *listen_addr, int listen_port, int **socklist_p)
 {
        struct sockaddr_in sin;
        int sockfd;