| 745 | } |
| 746 | |
| 747 | static int execute(void) |
| 748 | { |
| 749 | char *line = packet_buffer; |
| 750 | int pktlen, len; |
| 751 | char *addr = getenv("REMOTE_ADDR"), *port = getenv("REMOTE_PORT"); |
| 752 | struct hostinfo hi = HOSTINFO_INIT; |
| 753 | struct strvec env = STRVEC_INIT; |
| 754 | |
| 755 | if (addr) |
| 756 | loginfo("Connection from %s:%s", addr, port ? port : "?"); |
| 757 | |
| 758 | set_keep_alive(0); |
| 759 | alarm(init_timeout ? init_timeout : timeout); |
| 760 | pktlen = packet_read(0, packet_buffer, sizeof(packet_buffer), 0); |
| 761 | alarm(0); |
| 762 | |
| 763 | len = strlen(line); |
| 764 | if (len && line[len-1] == '\n') |
| 765 | line[len-1] = 0; |
| 766 | |
| 767 | /* parse additional args hidden behind a NUL byte */ |
| 768 | if (len != pktlen) |
| 769 | parse_extra_args(&hi, &env, line + len + 1, pktlen - len - 1); |
| 770 | |
| 771 | for (size_t i = 0; i < ARRAY_SIZE(daemon_service); i++) { |
| 772 | struct daemon_service *s = &(daemon_service[i]); |
| 773 | const char *arg; |
| 774 | |
| 775 | if (skip_prefix(line, "git-", &arg) && |
| 776 | skip_prefix(arg, s->name, &arg) && |
| 777 | *arg++ == ' ') { |
| 778 | /* |
| 779 | * Note: The directory here is probably context sensitive, |
| 780 | * and might depend on the actual service being performed. |
| 781 | */ |
| 782 | int rc = run_service(arg, s, &hi, &env); |
| 783 | hostinfo_clear(&hi); |
| 784 | strvec_clear(&env); |
| 785 | return rc; |
| 786 | } |
| 787 | } |
| 788 | |
| 789 | hostinfo_clear(&hi); |
| 790 | strvec_clear(&env); |
| 791 | logerror("Protocol error: '%s'", line); |
| 792 | return -1; |
| 793 | } |
| 794 | |
| 795 | static int addrcmp(const struct sockaddr_storage *s1, |
| 796 | const struct sockaddr_storage *s2) |
no test coverage detected