#include "internal.h"
#pragma mark Utilities
static bool
_parse_boot_arg_value(char *argsbuff, const char *which, char *where, size_t max)
{
bool found = false;
char *token = NULL;
char *argsstr = argsbuff;
static const char seps[] = { ' ', '\t', 0 };
while ((token = strsep(&argsstr, seps)) != NULL) {
bool is_boolean = false;
char *value = NULL;
char *equals = strchr(token, '=');
if (token[0] == '-') {
is_boolean = true;
} else if (equals) {
equals[0] = '\0';
value = &equals[1];
} else {
is_boolean = true;
}
if (strcmp(which, token) == 0) {
found = true;
if (!where) {
} else if (is_boolean || value == NULL) {
strlcpy(where, "", max);
} else {
strlcpy(where, value, max);
}
break;
}
}
return found;
}
static bool
_get_boot_arg_value(const char *which, char *where, size_t max)
{
bool found = false;
__os_free char *argsbuff = NULL;
size_t argsbuff_len = 0;
errno_t error = sysctlbyname_get_data_np("kern.bootargs",
(void **)&argsbuff, &argsbuff_len);
if (!error) {
found = _parse_boot_arg_value(argsbuff, which, where, max);
}
return found;
}
#pragma mark API
errno_t
sysctl_get_data_np(int mib[4], size_t mib_cnt, void **buff, size_t *buff_len)
{
errno_t error = 0;
int ret = 0;
size_t needed = 0;
void *mybuff = NULL;
ret = sysctl(mib, (unsigned int)mib_cnt, NULL, &needed, NULL, 0);
if (ret) {
error = errno;
goto __out;
}
mybuff = malloc(needed);
if (!mybuff) {
error = errno;
goto __out;
}
ret = sysctl(mib, (unsigned int)mib_cnt, mybuff, &needed, NULL, 0);
if (ret) {
error = errno;
goto __out;
}
*buff = mybuff;
*buff_len = needed;
__out:
if (error) {
free(mybuff);
}
return error;
}
errno_t
sysctlbyname_get_data_np(const char *mibdesc, void **buff, size_t *buff_len)
{
int ret = -1;
int error = -1;
int mib[4];
size_t mib_cnt = countof(mib);
ret = sysctlnametomib(mibdesc, mib, &mib_cnt);
if (ret) {
error = errno;
goto __out;
}
error = sysctl_get_data_np(mib, mib_cnt, buff, buff_len);
__out:
return error;
}
bool
os_parse_boot_arg_int(const char *which, int64_t *where)
{
bool found = false;
char buff[24] = {0};
char *endptr = NULL;
int64_t val = 0;
found = _get_boot_arg_value(which, buff, sizeof(buff));
if (!found || !where) {
goto __out;
}
val = strtoll(buff, &endptr, 0);
if (*endptr == 0) {
*where = val;
} else {
found = false;
}
__out:
return found;
}
bool
os_parse_boot_arg_string(const char *which, char *where, size_t maxlen)
{
return _get_boot_arg_value(which, where, maxlen);
}