git/daemon.c

#define USE_THE_REPOSITORY_VARIABLE

#include "git-compat-util.h"
#include "abspath.h"
#include "config.h"
#include "environment.h"
#include "path.h"
#include "pkt-line.h"
#include "protocol.h"
#include "run-command.h"
#include "setup.h"
#include "strbuf.h"
#include "string-list.h"

#ifdef NO_INITGROUPS
#define initgroups
#endif

static enum log_destination {} log_destination =;
static int verbose;
static int reuseaddr;
static int informative_errors;

static const char daemon_usage[] =;

/* List of acceptable pathname prefixes */
static const char **ok_paths;
static int strict_paths;

/* If this is set, git-daemon-export-ok is not required */
static int export_all_trees;

/* Take all paths relative to this one if non-NULL */
static const char *base_path;
static const char *interpolated_path;
static int base_path_relaxed;

/* If defined, ~user notation is allowed and the string is inserted
 * after ~user/.  E.g. a request to git://host/~alice/frotz would
 * go to /home/alice/pub_git/frotz with --user-path=pub_git.
 */
static const char *user_path;

/* Timeout, and initial timeout */
static unsigned int timeout;
static unsigned int init_timeout;

struct hostinfo {};
#define HOSTINFO_INIT

static void lookup_hostname(struct hostinfo *hi);

static const char *get_canon_hostname(struct hostinfo *hi)
{}

static const char *get_ip_address(struct hostinfo *hi)
{}

static void logreport(int priority, const char *err, va_list params)
{}

__attribute__((format (printf, 1, 2)))
static void logerror(const char *err, ...)
{}

__attribute__((format (printf, 1, 2)))
static void loginfo(const char *err, ...)
{}

static void NORETURN daemon_die(const char *err, va_list params)
{}

static const char *path_ok(const char *directory, struct hostinfo *hi)
{}

daemon_service_fn;
struct daemon_service {};

static int daemon_error(const char *dir, const char *msg)
{}

static const char *access_hook;

static int run_access_hook(struct daemon_service *service, const char *dir,
			   const char *path, struct hostinfo *hi)
{}

static int run_service(const char *dir, struct daemon_service *service,
		       struct hostinfo *hi, const struct strvec *env)
{}

static void copy_to_log(int fd)
{}

static int run_service_command(struct child_process *cld)
{}

static int upload_pack(const struct strvec *env)
{}

static int upload_archive(const struct strvec *env)
{}

static int receive_pack(const struct strvec *env)
{}

static struct daemon_service daemon_service[] =;

static void enable_service(const char *name, int ena)
{}

static void make_service_overridable(const char *name, int ena)
{}

static void parse_host_and_port(char *hostport, char **host,
	char **port)
{}

/*
 * Sanitize a string from the client so that it's OK to be inserted into a
 * filesystem path. Specifically, we disallow directory separators, runs
 * of "..", and trailing and leading dots, which means that the client
 * cannot escape our base path via ".." traversal.
 */
static void sanitize_client(struct strbuf *out, const char *in)
{}

/*
 * Like sanitize_client, but we also perform any canonicalization
 * to make life easier on the admin.
 */
static void canonicalize_client(struct strbuf *out, const char *in)
{}

/*
 * Read the host as supplied by the client connection.
 *
 * Returns a pointer to the character after the NUL byte terminating the host
 * argument, or 'extra_args' if there is no host argument.
 */
static char *parse_host_arg(struct hostinfo *hi, char *extra_args, int buflen)
{}

static void parse_extra_args(struct hostinfo *hi, struct strvec *env,
			     char *extra_args, int buflen)
{}

/*
 * Locate canonical hostname and its IP address.
 */
static void lookup_hostname(struct hostinfo *hi)
{}

static void hostinfo_clear(struct hostinfo *hi)
{}

static void set_keep_alive(int sockfd)
{}

static int execute(void)
{}

static int addrcmp(const struct sockaddr_storage *s1,
    const struct sockaddr_storage *s2)
{}

static int max_connections =;

static unsigned int live_children;

static struct child {} *firstborn;

static void add_child(struct child_process *cld, struct sockaddr *addr, socklen_t addrlen)
{}

/*
 * This gets called if the number of connections grows
 * past "max_connections".
 *
 * We kill the newest connection from a duplicate IP.
 */
static void kill_some_child(void)
{}

static void check_dead_children(void)
{}

static struct strvec cld_argv =;
static void handle(int incoming, struct sockaddr *addr, socklen_t addrlen)
{}

static void child_handler(int signo UNUSED)
{}

static int set_reuse_addr(int sockfd)
{}

struct socketlist {};

static const char *ip2str(int family, struct sockaddr *sin, socklen_t len)
{}

#ifndef NO_IPV6

static int setup_named_sock(char *listen_addr, int listen_port, struct socketlist *socklist)
{}

#else /* NO_IPV6 */

static int setup_named_sock(char *listen_addr, int listen_port, struct socketlist *socklist)
{
	struct sockaddr_in sin;
	int sockfd;
	long flags;

	memset(&sin, 0, sizeof sin);
	sin.sin_family = AF_INET;
	sin.sin_port = htons(listen_port);

	if (listen_addr) {
		/* Well, host better be an IP address here. */
		if (inet_pton(AF_INET, listen_addr, &sin.sin_addr.s_addr) <= 0)
			return 0;
	} else {
		sin.sin_addr.s_addr = htonl(INADDR_ANY);
	}

	sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if (sockfd < 0)
		return 0;

	if (set_reuse_addr(sockfd)) {
		logerror("Could not set SO_REUSEADDR: %s", strerror(errno));
		close(sockfd);
		return 0;
	}

	set_keep_alive(sockfd);

	if ( bind(sockfd, (struct sockaddr *)&sin, sizeof sin) < 0 ) {
		logerror("Could not bind to %s: %s",
			 ip2str(AF_INET, (struct sockaddr *)&sin, sizeof(sin)),
			 strerror(errno));
		close(sockfd);
		return 0;
	}

	if (listen(sockfd, 5) < 0) {
		logerror("Could not listen to %s: %s",
			 ip2str(AF_INET, (struct sockaddr *)&sin, sizeof(sin)),
			 strerror(errno));
		close(sockfd);
		return 0;
	}

	flags = fcntl(sockfd, F_GETFD, 0);
	if (flags >= 0)
		fcntl(sockfd, F_SETFD, flags | FD_CLOEXEC);

	ALLOC_GROW(socklist->list, socklist->nr + 1, socklist->alloc);
	socklist->list[socklist->nr++] = sockfd;
	return 1;
}

#endif

static void socksetup(struct string_list *listen_addr, int listen_port, struct socketlist *socklist)
{}

static int service_loop(struct socketlist *socklist)
{}

#ifdef NO_POSIX_GOODIES

struct credentials;

static void drop_privileges(struct credentials *cred UNUSED)
{
	/* nothing */
}

static struct credentials *prepare_credentials(const char *user_name UNUSED,
					       const char *group_name UNUSED)
{
	die("--user not supported on this platform");
}

#else

struct credentials {};

static void drop_privileges(struct credentials *cred)
{}

static struct credentials *prepare_credentials(const char *user_name,
    const char *group_name)
{}
#endif

static int serve(struct string_list *listen_addr, int listen_port,
    struct credentials *cred)
{}

int cmd_main(int argc, const char **argv)
{}