static int handshake_capabilities(struct child_process *process, struct subprocess_capability *capabilities, unsigned int *supported_capabilities) { int i; char *line; for (i = 0; capabilities[i].name; i++) { if (packet_write_fmt_gently(process->in, "capability=%s\n", capabilities[i].name)) return error("Could not write requested capability"); } if (packet_flush_gently(process->in)) return error("Could not write flush packet"); while ((line = packet_read_line(process->out, NULL))) { const char *p; if (!skip_prefix(line, "capability=", &p)) continue; for (i = 0; capabilities[i].name && strcmp(p, capabilities[i].name); i++) ; if (capabilities[i].name) { if (supported_capabilities) *supported_capabilities |= capabilities[i].flag; } else { warning("subprocess '%s' requested unsupported capability '%s'", process->argv[0], p); } } return 0; }
static int handshake_version(struct child_process *process, const char *welcome_prefix, int *versions, int *chosen_version) { int version_scratch; int i; char *line; const char *p; if (!chosen_version) chosen_version = &version_scratch; if (packet_write_fmt_gently(process->in, "%s-client\n", welcome_prefix)) return error("Could not write client identification"); for (i = 0; versions[i]; i++) { if (packet_write_fmt_gently(process->in, "version=%d\n", versions[i])) return error("Could not write requested version"); } if (packet_flush_gently(process->in)) return error("Could not write flush packet"); if (!(line = packet_read_line(process->out, NULL)) || !skip_prefix(line, welcome_prefix, &p) || strcmp(p, "-server")) return error("Unexpected line '%s', expected %s-server", line ? line : "<flush packet>", welcome_prefix); if (!(line = packet_read_line(process->out, NULL)) || !skip_prefix(line, "version=", &p) || strtol_i(p, 10, chosen_version)) return error("Unexpected line '%s', expected version", line ? line : "<flush packet>"); if ((line = packet_read_line(process->out, NULL))) return error("Unexpected line '%s', expected flush", line); /* Check to make sure that the version received is supported */ for (i = 0; versions[i]; i++) { if (versions[i] == *chosen_version) break; } if (!versions[i]) return error("Version %d not supported", *chosen_version); return 0; }
int write_packetized_from_fd(int fd_in, int fd_out) { static char buf[LARGE_PACKET_DATA_MAX]; int err = 0; ssize_t bytes_to_write; while (!err) { bytes_to_write = xread(fd_in, buf, sizeof(buf)); if (bytes_to_write < 0) return COPY_READ_ERROR; if (bytes_to_write == 0) break; err = packet_write_gently(fd_out, buf, bytes_to_write); } if (!err) err = packet_flush_gently(fd_out); return err; }
int packet_writel(int fd, const char *line, ...) { va_list args; int err; va_start(args, line); for (;;) { if (!line) break; if (strlen(line) > LARGE_PACKET_DATA_MAX) return -1; err = packet_write_fmt_gently(fd, "%s\n", line); if (err) return err; line = va_arg(args, const char*); } va_end(args); return packet_flush_gently(fd); }
int write_packetized_from_buf(const char *src_in, size_t len, int fd_out) { int err = 0; size_t bytes_written = 0; size_t bytes_to_write; while (!err) { if ((len - bytes_written) > LARGE_PACKET_DATA_MAX) bytes_to_write = LARGE_PACKET_DATA_MAX; else bytes_to_write = len - bytes_written; if (bytes_to_write == 0) break; err = packet_write_gently(fd_out, src_in + bytes_written, bytes_to_write); bytes_written += bytes_to_write; } if (!err) err = packet_flush_gently(fd_out); return err; }