remote-fd.c 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. #include "builtin.h"
  2. #include "transport.h"
  3. static const char usage_msg[] =
  4. "git remote-fd <remote> <url>";
  5. /*
  6. * URL syntax:
  7. * 'fd::<inoutfd>[/<anything>]' Read/write socket pair
  8. * <inoutfd>.
  9. * 'fd::<infd>,<outfd>[/<anything>]' Read pipe <infd> and write
  10. * pipe <outfd>.
  11. * [foo] indicates 'foo' is optional. <anything> is any string.
  12. *
  13. * The data output to <outfd>/<inoutfd> should be passed unmolested to
  14. * git-receive-pack/git-upload-pack/git-upload-archive and output of
  15. * git-receive-pack/git-upload-pack/git-upload-archive should be passed
  16. * unmolested to <infd>/<inoutfd>.
  17. *
  18. */
  19. #define MAXCOMMAND 4096
  20. static void command_loop(int input_fd, int output_fd)
  21. {
  22. char buffer[MAXCOMMAND];
  23. while (1) {
  24. size_t i;
  25. if (!fgets(buffer, MAXCOMMAND - 1, stdin)) {
  26. if (ferror(stdin))
  27. die("Input error");
  28. return;
  29. }
  30. /* Strip end of line characters. */
  31. i = strlen(buffer);
  32. while (i > 0 && isspace(buffer[i - 1]))
  33. buffer[--i] = 0;
  34. if (!strcmp(buffer, "capabilities")) {
  35. printf("*connect\n\n");
  36. fflush(stdout);
  37. } else if (!strncmp(buffer, "connect ", 8)) {
  38. printf("\n");
  39. fflush(stdout);
  40. if (bidirectional_transfer_loop(input_fd,
  41. output_fd))
  42. die("Copying data between file descriptors failed");
  43. return;
  44. } else {
  45. die("Bad command: %s", buffer);
  46. }
  47. }
  48. }
  49. int cmd_remote_fd(int argc, const char **argv, const char *prefix)
  50. {
  51. int input_fd = -1;
  52. int output_fd = -1;
  53. char *end;
  54. if (argc != 3)
  55. usage(usage_msg);
  56. input_fd = (int)strtoul(argv[2], &end, 10);
  57. if ((end == argv[2]) || (*end != ',' && *end != '/' && *end))
  58. die("Bad URL syntax");
  59. if (*end == '/' || !*end) {
  60. output_fd = input_fd;
  61. } else {
  62. char *end2;
  63. output_fd = (int)strtoul(end + 1, &end2, 10);
  64. if ((end2 == end + 1) || (*end2 != '/' && *end2))
  65. die("Bad URL syntax");
  66. }
  67. command_loop(input_fd, output_fd);
  68. return 0;
  69. }