static void daemonize(void) { switch (fork()) { case 0: break; case -1: die_errno("fork failed"); default: exit(0); } if (setsid() == -1) die_errno("setsid failed"); close(0); close(1); close(2); sanitize_stdfds(); }
int main(int argc, const char **argv) { /* * Always open file descriptors 0/1/2 to avoid clobbering files * in die(). It also avoids messing up when the pipes are dup'ed * onto stdin/stdout/stderr in the child processes we spawn. */ sanitize_stdfds(); git_extract_argv0_path(argv[0]); git_setup_gettext(); attr_start(); restore_sigpipe_to_default(); return cmd_main(argc, argv); }
int daemonize(void) { #ifdef NO_POSIX_GOODIES errno = ENOSYS; return -1; #else switch (fork()) { case 0: break; case -1: die_errno("fork failed"); default: exit(0); } if (setsid() == -1) die_errno("setsid failed"); close(0); close(1); close(2); sanitize_stdfds(); return 0; #endif }
int main(int argc, char **argv) { int listen_port = 0; struct string_list listen_addr = STRING_LIST_INIT_NODUP; int serve_mode = 0, inetd_mode = 0; const char *pid_file = NULL, *user_name = NULL, *group_name = NULL; int detach = 0; struct credentials *cred = NULL; int i; git_setup_gettext(); git_extract_argv0_path(argv[0]); for (i = 1; i < argc; i++) { char *arg = argv[i]; if (!prefixcmp(arg, "--listen=")) { string_list_append(&listen_addr, xstrdup_tolower(arg + 9)); continue; } if (!prefixcmp(arg, "--port=")) { char *end; unsigned long n; n = strtoul(arg+7, &end, 0); if (arg[7] && !*end) { listen_port = n; continue; } } if (!strcmp(arg, "--serve")) { serve_mode = 1; continue; } if (!strcmp(arg, "--inetd")) { inetd_mode = 1; log_syslog = 1; continue; } if (!strcmp(arg, "--verbose")) { verbose = 1; continue; } if (!strcmp(arg, "--syslog")) { log_syslog = 1; continue; } if (!strcmp(arg, "--export-all")) { export_all_trees = 1; continue; } if (!prefixcmp(arg, "--access-hook=")) { access_hook = arg + 14; continue; } if (!prefixcmp(arg, "--timeout=")) { timeout = atoi(arg+10); continue; } if (!prefixcmp(arg, "--init-timeout=")) { init_timeout = atoi(arg+15); continue; } if (!prefixcmp(arg, "--max-connections=")) { max_connections = atoi(arg+18); if (max_connections < 0) max_connections = 0; /* unlimited */ continue; } if (!strcmp(arg, "--strict-paths")) { strict_paths = 1; continue; } if (!prefixcmp(arg, "--base-path=")) { base_path = arg+12; continue; } if (!strcmp(arg, "--base-path-relaxed")) { base_path_relaxed = 1; continue; } if (!prefixcmp(arg, "--interpolated-path=")) { interpolated_path = arg+20; continue; } if (!strcmp(arg, "--reuseaddr")) { reuseaddr = 1; continue; } if (!strcmp(arg, "--user-path")) { user_path = ""; continue; } if (!prefixcmp(arg, "--user-path=")) { user_path = arg + 12; continue; } if (!prefixcmp(arg, "--pid-file=")) { pid_file = arg + 11; continue; } if (!strcmp(arg, "--detach")) { detach = 1; log_syslog = 1; continue; } if (!prefixcmp(arg, "--user="******"--group=")) { group_name = arg + 8; continue; } if (!prefixcmp(arg, "--enable=")) { enable_service(arg + 9, 1); continue; } if (!prefixcmp(arg, "--disable=")) { enable_service(arg + 10, 0); continue; } if (!prefixcmp(arg, "--allow-override=")) { make_service_overridable(arg + 17, 1); continue; } if (!prefixcmp(arg, "--forbid-override=")) { make_service_overridable(arg + 18, 0); continue; } if (!prefixcmp(arg, "--informative-errors")) { informative_errors = 1; continue; } if (!prefixcmp(arg, "--no-informative-errors")) { informative_errors = 0; continue; } if (!strcmp(arg, "--")) { ok_paths = &argv[i+1]; break; } else if (arg[0] != '-') { ok_paths = &argv[i]; break; } usage(daemon_usage); } if (log_syslog) { openlog("git-daemon", LOG_PID, LOG_DAEMON); set_die_routine(daemon_die); } else /* avoid splitting a message in the middle */ setvbuf(stderr, NULL, _IOFBF, 4096); if (inetd_mode && (detach || group_name || user_name)) die("--detach, --user and --group are incompatible with --inetd"); 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; if (group_name && !user_name) die("--group supplied without --user"); if (user_name) cred = prepare_credentials(user_name, group_name); if (strict_paths && (!ok_paths || !*ok_paths)) die("option --strict-paths requires a whitelist"); if (base_path && !is_directory(base_path)) die("base-path '%s' does not exist or is not a directory", base_path); if (inetd_mode) { if (!freopen("/dev/null", "w", stderr)) die_errno("failed to redirect stderr to /dev/null"); } if (inetd_mode || serve_mode) return execute(); if (detach) daemonize(); else sanitize_stdfds(); if (pid_file) store_pid(pid_file); /* prepare argv for serving-processes */ cld_argv = xmalloc(sizeof (char *) * (argc + 2)); cld_argv[0] = argv[0]; /* git-daemon */ cld_argv[1] = "--serve"; for (i = 1; i < argc; ++i) cld_argv[i+1] = argv[i]; cld_argv[argc+1] = NULL; return serve(&listen_addr, listen_port, cred); }
int main(int argc, char **argv) { int listen_port = 0; 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; struct passwd *pass = NULL; struct group *group; gid_t gid = 0; int i; git_extract_argv0_path(argv[0]); for (i = 1; i < argc; i++) { char *arg = argv[i]; if (!prefixcmp(arg, "--listen=")) { string_list_append(&listen_addr, xstrdup_tolower(arg + 9)); continue; } if (!prefixcmp(arg, "--port=")) { char *end; unsigned long n; n = strtoul(arg+7, &end, 0); if (arg[7] && !*end) { listen_port = n; continue; } } if (!strcmp(arg, "--inetd")) { inetd_mode = 1; log_syslog = 1; continue; } if (!strcmp(arg, "--verbose")) { verbose = 1; continue; } if (!strcmp(arg, "--syslog")) { log_syslog = 1; continue; } if (!strcmp(arg, "--export-all")) { export_all_trees = 1; continue; } if (!prefixcmp(arg, "--timeout=")) { timeout = atoi(arg+10); continue; } if (!prefixcmp(arg, "--init-timeout=")) { init_timeout = atoi(arg+15); continue; } if (!prefixcmp(arg, "--max-connections=")) { max_connections = atoi(arg+18); if (max_connections < 0) max_connections = 0; /* unlimited */ continue; } if (!strcmp(arg, "--strict-paths")) { strict_paths = 1; continue; } if (!prefixcmp(arg, "--base-path=")) { base_path = arg+12; continue; } if (!strcmp(arg, "--base-path-relaxed")) { base_path_relaxed = 1; continue; } if (!prefixcmp(arg, "--interpolated-path=")) { interpolated_path = arg+20; continue; } if (!strcmp(arg, "--reuseaddr")) { reuseaddr = 1; continue; } if (!strcmp(arg, "--user-path")) { user_path = ""; continue; } if (!prefixcmp(arg, "--user-path=")) { user_path = arg + 12; continue; } if (!prefixcmp(arg, "--pid-file=")) { pid_file = arg + 11; continue; } if (!strcmp(arg, "--detach")) { detach = 1; log_syslog = 1; continue; } if (!prefixcmp(arg, "--user="******"--group=")) { group_name = arg + 8; continue; } if (!prefixcmp(arg, "--enable=")) { enable_service(arg + 9, 1); continue; } if (!prefixcmp(arg, "--disable=")) { enable_service(arg + 10, 0); continue; } if (!prefixcmp(arg, "--allow-override=")) { make_service_overridable(arg + 17, 1); continue; } if (!prefixcmp(arg, "--forbid-override=")) { make_service_overridable(arg + 18, 0); continue; } if (!strcmp(arg, "--")) { ok_paths = &argv[i+1]; break; } else if (arg[0] != '-') { ok_paths = &argv[i]; break; } usage(daemon_usage); } if (log_syslog) { openlog("git-daemon", LOG_PID, LOG_DAEMON); set_die_routine(daemon_die); } else /* avoid splitting a message in the middle */ setvbuf(stderr, NULL, _IOLBF, 0); if (inetd_mode && (group_name || user_name)) die("--user and --group are incompatible with --inetd"); 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; if (group_name && !user_name) die("--group supplied without --user"); if (user_name) { pass = getpwnam(user_name); if (!pass) die("user not found - %s", user_name); if (!group_name) gid = pass->pw_gid; else { group = getgrnam(group_name); if (!group) die("group not found - %s", group_name); gid = group->gr_gid; } } if (strict_paths && (!ok_paths || !*ok_paths)) die("option --strict-paths requires a whitelist"); if (base_path && !is_directory(base_path)) die("base-path '%s' does not exist or is not a directory", base_path); if (inetd_mode) { struct sockaddr_storage ss; struct sockaddr *peer = (struct sockaddr *)&ss; socklen_t slen = sizeof(ss); if (!freopen("/dev/null", "w", stderr)) die_errno("failed to redirect stderr to /dev/null"); if (getpeername(0, peer, &slen)) peer = NULL; return execute(peer); } if (detach) { daemonize(); loginfo("Ready to rumble"); } else sanitize_stdfds(); if (pid_file) store_pid(pid_file); return serve(&listen_addr, listen_port, pass, gid); }
int main(int argc, char **av) { const char **argv = (const char **) av; const char *cmd; startup_info = &git_startup_info; cmd = git_extract_argv0_path(argv[0]); if (!cmd) cmd = "git-help"; /* * Always open file descriptors 0/1/2 to avoid clobbering files * in die(). It also avoids messing up when the pipes are dup'ed * onto stdin/stdout/stderr in the child processes we spawn. */ sanitize_stdfds(); git_setup_gettext(); /* * "git-xxxx" is the same as "git xxxx", but we obviously: * * - cannot take flags in between the "git" and the "xxxx". * - cannot execute it externally (since it would just do * the same thing over again) * * So we just directly call the builtin handler, and die if * that one cannot handle it. */ if (starts_with(cmd, "git-")) { cmd += 4; argv[0] = cmd; handle_builtin(argc, argv); die("cannot handle %s as a builtin", cmd); } /* Look for flags.. */ argv++; argc--; handle_options(&argv, &argc, NULL); if (argc > 0) { if (starts_with(argv[0], "--")) argv[0] += 2; } else { /* The user didn't specify a command; give them help */ commit_pager_choice(); printf("usage: %s\n\n", git_usage_string); list_common_cmds_help(); printf("\n%s\n", _(git_more_info_string)); exit(1); } cmd = argv[0]; /* * We use PATH to find git commands, but we prepend some higher * precedence paths: the "--exec-path" option, the GIT_EXEC_PATH * environment, and the $(gitexecdir) from the Makefile at build * time. */ setup_path(); while (1) { static int done_help = 0; static int was_alias = 0; was_alias = run_argv(&argc, &argv); if (errno != ENOENT) break; if (was_alias) { fprintf(stderr, "Expansion of alias '%s' failed; " "'%s' is not a git command\n", cmd, argv[0]); exit(1); } if (!done_help) { cmd = argv[0] = help_unknown_cmd(cmd); done_help = 1; } else break; } fprintf(stderr, "Failed to run command '%s': %s\n", cmd, strerror(errno)); return 1; }
int main(int argc, char **argv) { char *prog; const char **user_argv; struct commands *cmd; int count; git_setup_gettext(); git_extract_argv0_path(argv[0]); /* * Always open file descriptors 0/1/2 to avoid clobbering files * in die(). It also avoids messing up when the pipes are dup'ed * onto stdin/stdout/stderr in the child processes we spawn. */ sanitize_stdfds(); /* * Special hack to pretend to be a CVS server */ if (argc == 2 && !strcmp(argv[1], "cvs server")) { argv--; } else if (argc == 1) { /* Allow the user to run an interactive shell */ cd_to_homedir(); if (access(COMMAND_DIR, R_OK | X_OK) == -1) { die("Interactive git shell is not enabled.\n" "hint: ~/" COMMAND_DIR " should exist " "and have read and execute access."); } run_shell(); exit(0); } else if (argc != 3 || strcmp(argv[1], "-c")) { /* * We do not accept any other modes except "-c" followed by * "cmd arg", where "cmd" is a very limited subset of git * commands or a command in the COMMAND_DIR */ die("Run with no arguments or with -c cmd"); } prog = xstrdup(argv[2]); if (!strncmp(prog, "git", 3) && isspace(prog[3])) /* Accept "git foo" as if the caller said "git-foo". */ prog[3] = '-'; for (cmd = cmd_list ; cmd->name ; cmd++) { int len = strlen(cmd->name); char *arg; if (strncmp(cmd->name, prog, len)) continue; arg = NULL; switch (prog[len]) { case '\0': arg = NULL; break; case ' ': arg = prog + len + 1; break; default: continue; } exit(cmd->exec(cmd->name, arg)); } cd_to_homedir(); count = split_cmdline(prog, &user_argv); if (count >= 0) { if (is_valid_cmd_name(user_argv[0])) { prog = make_cmd(user_argv[0]); user_argv[0] = prog; execv(user_argv[0], (char *const *) user_argv); } free(prog); free(user_argv); die("unrecognized command '%s'", argv[2]); } else { free(prog); die("invalid command format '%s': %s", argv[2], split_cmdline_strerror(count)); } }
int main(int argc, char **argv) { int listen_port = 0; char *listen_addr = NULL; int inetd_mode = 0; const char *pid_file = NULL, *user_name = NULL, *group_name = NULL; int detach = 0; struct passwd *pass = NULL; struct group *group; gid_t gid = 0; int i; /* Without this we cannot rely on waitpid() to tell * what happened to our children. */ signal(SIGCHLD, SIG_DFL); for (i = 1; i < argc; i++) { char *arg = argv[i]; if (!prefixcmp(arg, "--listen=")) { char *p = arg + 9; char *ph = listen_addr = xmalloc(strlen(arg + 9) + 1); while (*p) *ph++ = tolower(*p++); *ph = 0; continue; } if (!prefixcmp(arg, "--port=")) { char *end; unsigned long n; n = strtoul(arg+7, &end, 0); if (arg[7] && !*end) { listen_port = n; continue; } } if (!strcmp(arg, "--inetd")) { inetd_mode = 1; log_syslog = 1; continue; } if (!strcmp(arg, "--verbose")) { verbose = 1; continue; } if (!strcmp(arg, "--syslog")) { log_syslog = 1; continue; } if (!strcmp(arg, "--export-all")) { export_all_trees = 1; continue; } if (!prefixcmp(arg, "--timeout=")) { timeout = atoi(arg+10); continue; } if (!prefixcmp(arg, "--init-timeout=")) { init_timeout = atoi(arg+15); continue; } if (!strcmp(arg, "--strict-paths")) { strict_paths = 1; continue; } if (!prefixcmp(arg, "--base-path=")) { base_path = arg+12; continue; } if (!strcmp(arg, "--base-path-relaxed")) { base_path_relaxed = 1; continue; } if (!prefixcmp(arg, "--interpolated-path=")) { interpolated_path = arg+20; continue; } if (!strcmp(arg, "--reuseaddr")) { reuseaddr = 1; continue; } if (!strcmp(arg, "--user-path")) { user_path = ""; continue; } if (!prefixcmp(arg, "--user-path=")) { user_path = arg + 12; continue; } if (!prefixcmp(arg, "--pid-file=")) { pid_file = arg + 11; continue; } if (!strcmp(arg, "--detach")) { detach = 1; log_syslog = 1; continue; } if (!prefixcmp(arg, "--user="******"--group=")) { group_name = arg + 8; continue; } if (!prefixcmp(arg, "--enable=")) { enable_service(arg + 9, 1); continue; } if (!prefixcmp(arg, "--disable=")) { enable_service(arg + 10, 0); continue; } if (!prefixcmp(arg, "--allow-override=")) { make_service_overridable(arg + 17, 1); continue; } if (!prefixcmp(arg, "--forbid-override=")) { make_service_overridable(arg + 18, 0); continue; } if (!strcmp(arg, "--")) { ok_paths = &argv[i+1]; break; } else if (arg[0] != '-') { ok_paths = &argv[i]; break; } usage(daemon_usage); } if (log_syslog) { openlog("git-daemon", 0, LOG_DAEMON); set_die_routine(daemon_die); } if (inetd_mode && (group_name || user_name)) die("--user and --group are incompatible with --inetd"); if (inetd_mode && (listen_port || listen_addr)) die("--listen= and --port= are incompatible with --inetd"); else if (listen_port == 0) listen_port = DEFAULT_GIT_PORT; if (group_name && !user_name) die("--group supplied without --user"); if (user_name) { pass = getpwnam(user_name); if (!pass) die("user not found - %s", user_name); if (!group_name) gid = pass->pw_gid; else { group = getgrnam(group_name); if (!group) die("group not found - %s", group_name); gid = group->gr_gid; } } if (strict_paths && (!ok_paths || !*ok_paths)) die("option --strict-paths requires a whitelist"); if (base_path) { struct stat st; if (stat(base_path, &st) || !S_ISDIR(st.st_mode)) die("base-path '%s' does not exist or " "is not a directory", base_path); } if (inetd_mode) { struct sockaddr_storage ss; struct sockaddr *peer = (struct sockaddr *)&ss; socklen_t slen = sizeof(ss); freopen("/dev/null", "w", stderr); if (getpeername(0, peer, &slen)) peer = NULL; return execute(peer); } if (detach) daemonize(); else sanitize_stdfds(); if (pid_file) store_pid(pid_file); return serve(listen_addr, listen_port, pass, gid); }