THIS IS A TEST INSTANCE ONLY! REPOSITORIES CAN BE DELETED AT ANY TIME!

Git Source Code Mirror - This is a publish-only repository and all pull requests are ignored. Please follow Documentation/SubmittingPatches procedure for any of your improvements.
git
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

128 lines
2.5KB

  1. #include "cache.h"
  2. #include "pkt-line.h"
  3. #include <sys/socket.h>
  4. #include <netinet/in.h>
  5. static const char daemon_usage[] = "git-daemon [--inetd | --port=n]";
  6. static int upload(char *dir, int dirlen)
  7. {
  8. if (chdir(dir) < 0)
  9. return -1;
  10. chdir(".git");
  11. /*
  12. * Security on the cheap.
  13. *
  14. * We want a readable HEAD, usable "objects" directory, and
  15. * a "git-daemon-export-ok" flag that says that the other side
  16. * is ok with us doing this.
  17. */
  18. if (access("git-daemon-export-ok", F_OK) ||
  19. access("objects/00", X_OK) ||
  20. access("HEAD", R_OK))
  21. return -1;
  22. /* git-upload-pack only ever reads stuff, so this is safe */
  23. execlp("git-upload-pack", "git-upload-pack", ".", NULL);
  24. return -1;
  25. }
  26. static int execute(void)
  27. {
  28. static char line[1000];
  29. int len;
  30. len = packet_read_line(0, line, sizeof(line));
  31. if (len && line[len-1] == '\n')
  32. line[--len] = 0;
  33. if (!strncmp("git-upload-pack /", line, 17))
  34. return upload(line + 16, len - 16);
  35. fprintf(stderr, "got bad connection '%s'\n", line);
  36. return -1;
  37. }
  38. static void handle(int incoming, struct sockaddr_in *addr, int addrlen)
  39. {
  40. if (fork()) {
  41. close(incoming);
  42. return;
  43. }
  44. dup2(incoming, 0);
  45. dup2(incoming, 1);
  46. close(incoming);
  47. exit(execute());
  48. }
  49. static int serve(int port)
  50. {
  51. int sockfd;
  52. struct sockaddr_in addr;
  53. sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_IP);
  54. if (sockfd < 0)
  55. die("unable to open socket (%s)", strerror(errno));
  56. memset(&addr, 0, sizeof(addr));
  57. addr.sin_port = htons(port);
  58. addr.sin_family = AF_INET;
  59. if (bind(sockfd, (void *)&addr, sizeof(addr)) < 0)
  60. die("unable to bind to port %d (%s)", port, strerror(errno));
  61. if (listen(sockfd, 5) < 0)
  62. die("unable to listen to port %d (%s)", port, strerror(errno));
  63. for (;;) {
  64. struct sockaddr_in in;
  65. socklen_t addrlen = sizeof(in);
  66. int incoming = accept(sockfd, (void *)&in, &addrlen);
  67. if (incoming < 0) {
  68. switch (errno) {
  69. case EAGAIN:
  70. case EINTR:
  71. case ECONNABORTED:
  72. continue;
  73. default:
  74. die("accept returned %s", strerror(errno));
  75. }
  76. }
  77. handle(incoming, &in, addrlen);
  78. }
  79. }
  80. int main(int argc, char **argv)
  81. {
  82. int port = DEFAULT_GIT_PORT;
  83. int inetd_mode = 0;
  84. int i;
  85. for (i = 1; i < argc; i++) {
  86. char *arg = argv[i];
  87. if (!strncmp(arg, "--port=", 7)) {
  88. char *end;
  89. unsigned long n;
  90. n = strtoul(arg+7, &end, 0);
  91. if (arg[7] && !*end) {
  92. port = n;
  93. continue;
  94. }
  95. }
  96. if (!strcmp(arg, "--inetd")) {
  97. inetd_mode = 1;
  98. continue;
  99. }
  100. usage(daemon_usage);
  101. }
  102. if (inetd_mode)
  103. return execute();
  104. return serve(port);
  105. }