Merge branch 'jt/subprocess-handshake'
Code cleanup. * jt/subprocess-handshake: sub-process: refactor handshake to common function Documentation: migrate sub-process docs to header
This commit is contained in:
104
sub-process.c
104
sub-process.c
@ -108,3 +108,107 @@ int subprocess_start(struct hashmap *hashmap, struct subprocess_entry *entry, co
|
||||
hashmap_add(hashmap, entry);
|
||||
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;
|
||||
}
|
||||
|
||||
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("external filter requested unsupported filter capability '%s'",
|
||||
p);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int subprocess_handshake(struct subprocess_entry *entry,
|
||||
const char *welcome_prefix,
|
||||
int *versions,
|
||||
int *chosen_version,
|
||||
struct subprocess_capability *capabilities,
|
||||
unsigned int *supported_capabilities)
|
||||
{
|
||||
int retval;
|
||||
struct child_process *process = &entry->process;
|
||||
|
||||
sigchain_push(SIGPIPE, SIG_IGN);
|
||||
|
||||
retval = handshake_version(process, welcome_prefix, versions,
|
||||
chosen_version) ||
|
||||
handshake_capabilities(process, capabilities,
|
||||
supported_capabilities);
|
||||
|
||||
sigchain_pop(SIGPIPE);
|
||||
return retval;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user