- char *prog;
- const char **user_argv;
- struct commands *cmd;
- int devnull_fd;
- int count;
-
- /*
- * Always open file descriptors 0/1/2 to avoid clobbering files
- * in die(). It also avoids not messing up when the pipes are
- * dup'ed onto stdin/stdout/stderr in the child processes we spawn.
- */
- devnull_fd = open("/dev/null", O_RDWR);
- while (devnull_fd >= 0 && devnull_fd <= 2)
- devnull_fd = dup(devnull_fd);
- if (devnull_fd == -1)
- die("opening /dev/null failed");
- close (devnull_fd);
-
- if (argc == 2 && (!strcmp(argv[1], "-v") ||
- !strcmp(argv[1], "--version"))) {
- fprintf(stderr, "%s\n", version);
- return 0;
- }
- if (argc < 3)
- die("invalid arguments");
-
-#ifdef USE_DEFAULTS
- ini_parse("repo_shell.cfg", handler, &cfg);
-#else
- if (ini_parse(CFG_FILE, handler, &cfg) < 0)
- die("cannot read config file %s", CFG_FILE);
-#endif
-
- 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;
- struct passwd *pw;
- 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;
- }
-
- pw = getpwuid(getuid());
- exit(cmd->exec(cmd->name, arg, pw->pw_name));
- }
-
- if (!check_ssh_interactive(getuid()))
- die("only repository access is allowed");
-
- cd_to_homedir();
- count = split_cmdline(prog, &user_argv);
- if (count >= 0) {
- execvp(user_argv[0], (char *const *) user_argv);
- free(user_argv);
- die("unrecognized command '%s'", argv[2]);
- } else {
- free(prog);
- die("invalid command format '%s': %s", argv[2],
- split_cmdline_strerror(count));
- }
+ char *prog;
+ const char **user_argv;
+ struct commands *cmd;
+ int devnull_fd;
+ int count;
+ struct passwd *pw;
+
+ /*
+ * Always open file descriptors 0/1/2 to avoid clobbering files
+ * in die(). It also avoids not messing up when the pipes are
+ * dup'ed onto stdin/stdout/stderr in the child processes we spawn.
+ */
+ devnull_fd = open("/dev/null", O_RDWR);
+ while (devnull_fd >= 0 && devnull_fd <= 2)
+ devnull_fd = dup(devnull_fd);
+ if (devnull_fd == -1)
+ die("opening /dev/null failed");
+ close (devnull_fd);
+
+ if (argc == 2 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))) {
+ fprintf(stderr, "%s is a replacement login shell.\n"
+ " May be ran from the command line with one of these options:\n"
+ " -h|--help this text\n"
+ " -v|--version program version string\n"
+ " -t|--test <user> <repo> test access\n"
+ " -d|--detail <user> <repo> test access, outputting more detail\n"
+ , argv[0]);
+ return 0;
+ }
+
+ if (argc == 2 && (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version"))) {
+ fprintf(stderr, "%s\n", version);
+ return 0;
+ }
+
+ pw = getpwuid(getuid());
+ cfg.user = xstrdup(pw->pw_name);
+ if (ini_parse(CFG_FILE, ini_handler, &cfg) < 0)
+ die("cannot read config file %s", CFG_FILE);
+
+ if (argc == 1) {
+ if (!cfg.allow_interactive) {
+ fprintf(stderr, "\n");
+ die("only repository access is allowed");
+ }
+ reset_user();
+ argv[0] = SHELL;
+ execvp(argv[0], (char *const *) argv);
+ return 1;
+ }
+
+ if ((!strcmp(argv[1], "-d") || !strcmp(argv[1], "--detail"))) {
+ perms_t p;
+
+ if (argc !=4)
+ die("usage: %s -d|--detail <user> <repo>", argv[0]);
+ p = git_acl(argv[2], argv[3], cfg.git_acl_file);
+ fprintf(stderr,
+ "user '%s' repo '%s' perms '%s'\n via userid '%s' repoid '%s'\n",
+ argv[2], argv[3], git_acl_perms_as_str(p), git_acl_last_userid(),
+ git_acl_last_repoid());
+ return 0;
+ }
+
+ if ((!strcmp(argv[1], "-t") || !strcmp(argv[1], "--test"))) {
+ perms_t p;
+
+ if (argc !=4)
+ die("usage: %s -t|--test <user> <repo>", argv[0]);
+ p = git_acl(argv[2], argv[3], cfg.git_acl_file);
+ printf("%s\n", git_acl_perms_as_str(p));
+ return 0;
+ }
+
+ if (argc == 3) {
+ /* argv[0] = repo_shell, argv[1] = -c, argv[2] = cmd
+ * cmd = "svnserve -t" or "git-xxx '/path/to/repo.git'"
+ */
+ 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, cfg.user));
+ }
+ }
+
+ if (!cfg.allow_interactive)
+ die("only repository access is allowed");
+ reset_user();
+ cd_to_homedir();
+ argv[0] = SHELL;
+ execvp(argv[0], (char *const *) argv);