From: Junio C Hamano Date: Wed, 27 Oct 2010 04:50:03 +0000 (-0700) Subject: Merge branch 'as/daemon-multi-listen' X-Git-Tag: v1.7.4-rc0~165 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/e6202dfe0021e2662eb4e19e6d01e33081608b5e?ds=inline;hp=-c Merge branch 'as/daemon-multi-listen' * as/daemon-multi-listen: daemon: allow more than one host address given via --listen daemon: add helper function named_sock_setup --- e6202dfe0021e2662eb4e19e6d01e33081608b5e diff --combined Documentation/git-daemon.txt index 2f0ddf6fe8,685aa58cec..5054f790a1 --- a/Documentation/git-daemon.txt +++ b/Documentation/git-daemon.txt @@@ -9,15 -9,15 +9,15 @@@ SYNOPSI -------- [verse] 'git daemon' [--verbose] [--syslog] [--export-all] - [--timeout=n] [--init-timeout=n] [--max-connections=n] - [--strict-paths] [--base-path=path] [--base-path-relaxed] - [--user-path | --user-path=path] - [--interpolated-path=pathtemplate] - [--reuseaddr] [--detach] [--pid-file=file] - [--enable=service] [--disable=service] - [--allow-override=service] [--forbid-override=service] - [--inetd | [--listen=host_or_ipaddr] [--port=n] [--user=user [--group=group]] - [directory...] + [--timeout=] [--init-timeout=] [--max-connections=] + [--strict-paths] [--base-path=] [--base-path-relaxed] + [--user-path | --user-path=] + [--interpolated-path=] + [--reuseaddr] [--detach] [--pid-file=] + [--enable=] [--disable=] + [--allow-override=] [--forbid-override=] + [--inetd | [--listen=] [--port=] [--user= [--group=]] + [...] DESCRIPTION ----------- @@@ -48,7 -48,7 +48,7 @@@ OPTION 'git daemon' will refuse to start when this option is enabled and no whitelist is specified. ---base-path=path:: +--base-path=:: Remap all the path requests as relative to the given path. This is sort of "GIT root" - if you run 'git daemon' with '--base-path=/srv/git' on example.com, then if you later try to pull @@@ -61,7 -61,7 +61,7 @@@ This is useful for switching to --base-path usage, while still allowing the old paths. ---interpolated-path=pathtemplate:: +--interpolated-path=:: To support virtual hosting, an interpolated path template can be used to dynamically construct alternate paths. The template supports %H for the target hostname as supplied by the client but @@@ -80,27 -80,28 +80,28 @@@ Have the server run as an inetd service. Implies --syslog. Incompatible with --port, --listen, --user and --group options. ---listen=host_or_ipaddr:: +--listen=:: Listen on a specific IP address or hostname. IP addresses can be either an IPv4 address or an IPv6 address if supported. If IPv6 is not supported, then --listen=hostname is also not supported and --listen must be given an IPv4 address. + Can be given more than once. Incompatible with '--inetd' option. ---port=n:: +--port=:: Listen on an alternative port. Incompatible with '--inetd' option. ---init-timeout=n:: +--init-timeout=:: Timeout between the moment the connection is established and the client request is received (typically a rather low value, since that should be basically immediate). ---timeout=n:: +--timeout=:: Timeout for specific client sub-requests. This includes the time it takes for the server to process the sub-request and the time spent waiting for the next client's request. ---max-connections=n:: +--max-connections=:: Maximum number of concurrent clients, defaults to 32. Set it to zero for no limit. @@@ -109,7 -110,7 +110,7 @@@ --verbose, thus by default only error conditions will be logged. --user-path:: ---user-path=path:: +--user-path=:: Allow {tilde}user notation to be used in requests. When specified with no parameter, requests to git://host/{tilde}alice/foo is taken as a request to access @@@ -129,12 -130,12 +130,12 @@@ --detach:: Detach from the shell. Implies --syslog. ---pid-file=file:: +--pid-file=:: Save the process id in 'file'. Ignored when the daemon is run under `--inetd`. ---user=user:: ---group=group:: +--user=:: +--group=:: Change daemon's uid and gid before entering the service loop. When only `--user` is given without `--group`, the primary group ID for the user is used. The values of @@@ -145,16 -146,16 +146,16 @@@ Giving these options is an error when u the facility of inet daemon to achieve the same before spawning 'git daemon' if needed. ---enable=service:: ---disable=service:: +--enable=:: +--disable=:: Enable/disable the service site-wide per default. Note that a service disabled site-wide can still be enabled per repository if it is marked overridable and the repository enables the service with a configuration item. ---allow-override=service:: ---forbid-override=service:: +--allow-override=:: +--forbid-override=:: Allow/forbid overriding the site-wide default with per repository configuration. By default, all the services are overridable. diff --combined daemon.c index 9326d3a1fa,d6e20c6771..7ccd097e1d --- a/daemon.c +++ b/daemon.c @@@ -3,6 -3,7 +3,7 @@@ #include "exec_cmd.h" #include "run-command.h" #include "strbuf.h" + #include "string-list.h" #include @@@ -20,15 -21,15 +21,15 @@@ static int reuseaddr static const char daemon_usage[] = "git daemon [--verbose] [--syslog] [--export-all]\n" -" [--timeout=n] [--init-timeout=n] [--max-connections=n]\n" -" [--strict-paths] [--base-path=path] [--base-path-relaxed]\n" -" [--user-path | --user-path=path]\n" -" [--interpolated-path=path]\n" -" [--reuseaddr] [--detach] [--pid-file=file]\n" -" [--[enable|disable|allow-override|forbid-override]=service]\n" -" [--inetd | [--listen=host_or_ipaddr] [--port=n]\n" -" [--user=user [--group=group]]\n" -" [directory...]"; +" [--timeout=] [--init-timeout=] [--max-connections=]\n" +" [--strict-paths] [--base-path=] [--base-path-relaxed]\n" +" [--user-path | --user-path=]\n" +" [--interpolated-path=]\n" +" [--reuseaddr] [--detach] [--pid-file=]\n" +" [--(enable|disable|allow-override|forbid-override)=]\n" +" [--inetd | [--listen=] [--port=]\n" +" [--user= [--group=]]\n" +" [...]"; /* List of acceptable pathname prefixes */ static char **ok_paths; @@@ -734,11 -735,17 +735,17 @@@ static int set_reuse_addr(int sockfd &on, sizeof(on)); } + struct socketlist { + int *list; + size_t nr; + size_t alloc; + }; + #ifndef NO_IPV6 - static int socksetup(char *listen_addr, int listen_port, int **socklist_p) + static int setup_named_sock(char *listen_addr, int listen_port, struct socketlist *socklist) { - int socknum = 0, *socklist = NULL; + int socknum = 0; int maxfd = -1; char pbuf[NI_MAXSERV]; struct addrinfo hints, *ai0, *ai; @@@ -753,8 -760,10 +760,10 @@@ hints.ai_flags = AI_PASSIVE; gai = getaddrinfo(listen_addr, pbuf, &hints, &ai0); - if (gai) - die("getaddrinfo() failed: %s", gai_strerror(gai)); + if (gai) { + logerror("getaddrinfo() for %s failed: %s", listen_addr, gai_strerror(gai)); + return 0; + } for (ai = ai0; ai; ai = ai->ai_next) { int sockfd; @@@ -795,8 -804,9 +804,9 @@@ if (flags >= 0) fcntl(sockfd, F_SETFD, flags | FD_CLOEXEC); - socklist = xrealloc(socklist, sizeof(int) * (socknum + 1)); - socklist[socknum++] = sockfd; + ALLOC_GROW(socklist->list, socklist->nr + 1, socklist->alloc); + socklist->list[socklist->nr++] = sockfd; + socknum++; if (maxfd < sockfd) maxfd = sockfd; @@@ -804,13 -814,12 +814,12 @@@ freeaddrinfo(ai0); - *socklist_p = socklist; return socknum; } #else /* NO_IPV6 */ - static int socksetup(char *listen_addr, int listen_port, int **socklist_p) + static int setup_named_sock(char *listen_addr, int listen_port, struct socketlist *socklist) { struct sockaddr_in sin; int sockfd; @@@ -851,22 -860,39 +860,39 @@@ if (flags >= 0) fcntl(sockfd, F_SETFD, flags | FD_CLOEXEC); - *socklist_p = xmalloc(sizeof(int)); - **socklist_p = sockfd; + ALLOC_GROW(socklist->list, socklist->nr + 1, socklist->alloc); + socklist->list[socklist->nr++] = sockfd; return 1; } #endif - static int service_loop(int socknum, int *socklist) + static void socksetup(struct string_list *listen_addr, int listen_port, struct socketlist *socklist) + { + if (!listen_addr->nr) + setup_named_sock(NULL, listen_port, socklist); + else { + int i, socknum; + for (i = 0; i < listen_addr->nr; i++) { + socknum = setup_named_sock(listen_addr->items[i].string, + listen_port, socklist); + + if (socknum == 0) + logerror("unable to allocate any listen sockets for host %s on port %u", + listen_addr->items[i].string, listen_port); + } + } + } + + static int service_loop(struct socketlist *socklist) { struct pollfd *pfd; int i; - pfd = xcalloc(socknum, sizeof(struct pollfd)); + pfd = xcalloc(socklist->nr, sizeof(struct pollfd)); - for (i = 0; i < socknum; i++) { - pfd[i].fd = socklist[i]; + for (i = 0; i < socklist->nr; i++) { + pfd[i].fd = socklist->list[i]; pfd[i].events = POLLIN; } @@@ -877,7 -903,7 +903,7 @@@ check_dead_children(); - if (poll(pfd, socknum, -1) < 0) { + if (poll(pfd, socklist->nr, -1) < 0) { if (errno != EINTR) { logerror("Poll failed, resuming: %s", strerror(errno)); @@@ -886,7 -912,7 +912,7 @@@ continue; } - for (i = 0; i < socknum; i++) { + for (i = 0; i < socklist->nr; i++) { if (pfd[i].revents & POLLIN) { struct sockaddr_storage ss; unsigned int sslen = sizeof(ss); @@@ -946,27 -972,27 +972,27 @@@ static void store_pid(const char *path die_errno("failed to write pid file '%s'", path); } - static int serve(char *listen_addr, int listen_port, struct passwd *pass, gid_t gid) + static int serve(struct string_list *listen_addr, int listen_port, struct passwd *pass, gid_t gid) { - int socknum, *socklist; + struct socketlist socklist = { NULL, 0, 0 }; - socknum = socksetup(listen_addr, listen_port, &socklist); - if (socknum == 0) - die("unable to allocate any listen sockets on host %s port %u", - listen_addr, listen_port); + socksetup(listen_addr, listen_port, &socklist); + if (socklist.nr == 0) + die("unable to allocate any listen sockets on port %u", + listen_port); if (pass && gid && (initgroups(pass->pw_name, gid) || setgid (gid) || setuid(pass->pw_uid))) die("cannot drop privileges"); - return service_loop(socknum, socklist); + return service_loop(&socklist); } int main(int argc, char **argv) { int listen_port = 0; - char *listen_addr = NULL; + struct string_list listen_addr = STRING_LIST_INIT_NODUP; int inetd_mode = 0; const char *pid_file = NULL, *user_name = NULL, *group_name = NULL; int detach = 0; @@@ -981,7 -1007,7 +1007,7 @@@ char *arg = argv[i]; if (!prefixcmp(arg, "--listen=")) { - listen_addr = xstrdup_tolower(arg + 9); + string_list_append(&listen_addr, xstrdup_tolower(arg + 9)); continue; } if (!prefixcmp(arg, "--port=")) { @@@ -1106,7 -1132,7 +1132,7 @@@ if (inetd_mode && (group_name || user_name)) die("--user and --group are incompatible with --inetd"); - if (inetd_mode && (listen_port || listen_addr)) + if (inetd_mode && (listen_port || (listen_addr.nr > 0))) die("--listen= and --port= are incompatible with --inetd"); else if (listen_port == 0) listen_port = DEFAULT_GIT_PORT; @@@ -1161,5 -1187,5 +1187,5 @@@ if (pid_file) store_pid(pid_file); - return serve(listen_addr, listen_port, pass, gid); + return serve(&listen_addr, listen_port, pass, gid); }