#include <sys/param.h>
#include <sys/sysctl.h>
#include <errno.h>
#include <paths.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#ifndef __has_include
#include <dirhelper_priv.h>
#else
#if __has_include(<dirhelper_priv.h>)
#include <dirhelper_priv.h>
#else
typedef enum {
DIRHELPER_USER_LOCAL = 0,
DIRHELPER_USER_LOCAL_TEMP,
DIRHELPER_USER_LOCAL_CACHE,
DIRHELPER_USER_LOCAL_LAST = DIRHELPER_USER_LOCAL_CACHE
} dirhelper_which_t;
#endif
#endif
#include "libc_private.h"
#if __DARWIN_UNIX03
static char *(*__dirhelper_func)(int, char *, size_t);
__attribute__((__visibility__("hidden")))
void
__confstr_init(const struct _libc_functions *funcs)
{
__dirhelper_func = funcs->dirhelper;
}
__attribute__((__visibility__("hidden")))
char *
__dirhelper(dirhelper_which_t which, char *path, size_t pathlen)
{
if (__dirhelper_func) {
return __dirhelper_func(which, path, pathlen);
} else {
return NULL;
}
}
#else // !__DARWIN_UNIX03
__attribute__((__visibility__("hidden")))
char *__dirhelper(dirhelper_which_t which, char *path, size_t pathlen);
#endif // !__DARWIN_UNIX03
#if __DARWIN_UNIX03
#define CONFSTR_ERR_RET 0
#else
#define CONFSTR_ERR_RET -1
#endif
size_t
confstr(name, buf, len)
int name;
char *buf;
size_t len;
{
size_t tlen;
int mib[2], sverrno;
char *p;
switch (name) {
case _CS_PATH:
mib[0] = CTL_USER;
mib[1] = USER_CS_PATH;
if (sysctl(mib, 2, NULL, &tlen, NULL, 0) == -1)
return (CONFSTR_ERR_RET);
if (len != 0 && buf != NULL) {
if ((p = malloc(tlen)) == NULL)
return (CONFSTR_ERR_RET);
if (sysctl(mib, 2, p, &tlen, NULL, 0) == -1) {
sverrno = errno;
free(p);
errno = sverrno;
return (CONFSTR_ERR_RET);
}
(void)strncpy(buf, p, len - 1);
buf[len - 1] = '\0';
free(p);
}
return (tlen);
case _CS_POSIX_V6_ILP32_OFF32_CFLAGS:
case _CS_XBS5_ILP32_OFF32_CFLAGS:
case _CS_POSIX_V6_ILP32_OFF32_LDFLAGS:
case _CS_XBS5_ILP32_OFF32_LDFLAGS:
case _CS_POSIX_V6_ILP32_OFF32_LIBS:
case _CS_XBS5_ILP32_OFF32_LIBS:
case _CS_XBS5_ILP32_OFF32_LINTFLAGS:
case _CS_POSIX_V6_ILP32_OFFBIG_LIBS:
case _CS_XBS5_ILP32_OFFBIG_LIBS:
case _CS_XBS5_ILP32_OFFBIG_LINTFLAGS:
case _CS_POSIX_V6_LP64_OFF64_LIBS:
case _CS_XBS5_LP64_OFF64_LIBS:
case _CS_XBS5_LP64_OFF64_LINTFLAGS:
case _CS_POSIX_V6_LPBIG_OFFBIG_LIBS:
case _CS_XBS5_LPBIG_OFFBIG_LIBS:
case _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS:
p = "";
goto docopy;
case _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS:
case _CS_XBS5_ILP32_OFFBIG_CFLAGS:
case _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS:
case _CS_XBS5_ILP32_OFFBIG_LDFLAGS:
p = "-W 32";
goto docopy;
case _CS_POSIX_V6_LP64_OFF64_CFLAGS:
case _CS_XBS5_LP64_OFF64_CFLAGS:
case _CS_POSIX_V6_LP64_OFF64_LDFLAGS:
case _CS_XBS5_LP64_OFF64_LDFLAGS:
case _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS:
case _CS_XBS5_LPBIG_OFFBIG_CFLAGS:
case _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS:
case _CS_XBS5_LPBIG_OFFBIG_LDFLAGS:
p = "-W 64";
goto docopy;
case _CS_POSIX_V6_WIDTH_RESTRICTED_ENVS:
if (sizeof(long) >= 8)
p = "_POSIX_V6_LP64_OFF64";
else
p = "_POSIX_V6_ILP32_OFFBIG";
docopy:
if (len != 0 && buf != NULL)
strlcpy(buf, p, len);
return (strlen(p) + 1);
case _CS_DARWIN_USER_DIR:
if ((p = alloca(PATH_MAX)) == NULL) {
errno = ENOMEM;
return (CONFSTR_ERR_RET);
}
if (__dirhelper(DIRHELPER_USER_LOCAL, p, PATH_MAX) == NULL) {
if (errno != ENOMEM)
errno = EIO;
return (CONFSTR_ERR_RET);
}
goto docopy;
case _CS_DARWIN_USER_TEMP_DIR:
if ((p = alloca(PATH_MAX)) == NULL) {
errno = ENOMEM;
return (CONFSTR_ERR_RET);
}
if (__dirhelper(DIRHELPER_USER_LOCAL_TEMP, p, PATH_MAX) == NULL) {
int dh_errno = errno;
if ((p = getenv("TMPDIR")) && access(p, W_OK) == 0)
goto docopy;
if (access(p = P_tmpdir, W_OK) == 0)
goto docopy;
if (dh_errno == ENOMEM)
errno = ENOMEM;
else
errno = EIO;
return (CONFSTR_ERR_RET);
}
goto docopy;
case _CS_DARWIN_USER_CACHE_DIR:
if ((p = alloca(PATH_MAX)) == NULL) {
errno = ENOMEM;
return (CONFSTR_ERR_RET);
}
if (__dirhelper(DIRHELPER_USER_LOCAL_CACHE, p, PATH_MAX) == NULL) {
if (errno != ENOMEM)
errno = EIO;
return (CONFSTR_ERR_RET);
}
goto docopy;
default:
errno = EINVAL;
return (0);
}
}