aboutsummaryrefslogtreecommitdiffstats
path: root/libcoopgamma_get_method_and_site.c
blob: 73de04871ce04c6a29d8cc9b116a012da36c938d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/* See LICENSE file for copyright and license details. */
#include "common.h"


/**
 * Get the adjustment method and site
 * 
 * SIGCHLD must not be ignored or blocked
 * 
 * @param   method   The adjustment method, `NULL` for automatic
 * @param   site     The site, `NULL` for automatic
 * @param   methodp  Output pointer for the selected adjustment method,
 *                   which cannot be `NULL`. It is safe to call
 *                   this function with this parameter set to `NULL`.
 * @param   sitep    Output pointer for the selected site, which will
 *                   be `NULL` the method only supports one site or if
 *                   `site == NULL` and no site can be selected
 *                   automatically. It is safe to call this function
 *                   with this parameter set to `NULL`.
 * @return           Zero on success, -1 on error
 */
int
libcoopgamma_get_method_and_site(const char *restrict method, const char *restrict site,
                                 char **restrict methodp, char **restrict sitep)
{
	int saved_errno;
	char *raw;
	char *p;
	char *q;

	raw = libcoopgamma_query__(method, site, "-q");
	if (!raw)
		return -1;

	if (methodp) *methodp = NULL;
	if (sitep)   *sitep   = NULL;

	p = strchr(raw, '\n');
	if (!p) {
		errno = EBADMSG;
		goto fail;
	}
	*p++ = '\0';

	if (methodp) {
		*methodp = malloc(strlen(raw) + 1U);
		if (!*methodp)
			goto fail;
		strcpy(*methodp, raw);
	}

	if (site && *(q = &strchr(p, '\0')[-1])) {
		if (*q != '\n') {
			errno = EBADMSG;
			goto fail;
		}
		*q = '\0';
		*sitep = malloc(strlen(p) + 1U);
		if (!*sitep)
			goto fail;
		strcpy(*sitep, p);
	}

	free(raw);
	return 0;

fail:
	saved_errno = errno;
	if (methodp) {
		free(*methodp);
		*methodp = NULL;
	}
	free(raw);
	errno = saved_errno;
	return -1;
}