# -*- Autoconf -*-

# SYNOPSIS
#
#   AX_CHECK_USER_NAMESPACE
#
# DESCRIPTION
#
#   This macro checks whether the local system supports Linux user namespaces.
#   If so, it calls AC_DEFINE(HAVE_USER_NAMESPACE).
#
# Copyright (C) The c-ares team
# SPDX-License-Identifier: MIT

AC_DEFUN([AX_CHECK_USER_NAMESPACE],[dnl
 AC_CACHE_CHECK([whether user namespaces are supported],
  ax_cv_user_namespace,[
  AC_LANG_PUSH([C])
  AC_RUN_IFELSE([AC_LANG_SOURCE([[
#define _GNU_SOURCE
#include <fcntl.h>
#include <sched.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>

int userfn(void *d) {
  usleep(100000);  /* synchronize by sleep */
  return (getuid() != 0);
}
char userst[1024*1024];
int main() {
  char buffer[1024];
  int rc, status, fd;
  pid_t child = clone(userfn, userst + 1024*1024, CLONE_NEWUSER|SIGCHLD, 0);
  if (child < 0) return 1;

  snprintf(buffer, sizeof(buffer), "/proc/%d/uid_map", child);
  fd = open(buffer, O_CREAT|O_WRONLY|O_TRUNC, 0755);
  snprintf(buffer, sizeof(buffer), "0 %d 1\n", getuid());
  write(fd, buffer, strlen(buffer));
  close(fd);

  rc = waitpid(child, &status, 0);
  if (rc <= 0) return 1;
  if (!WIFEXITED(status)) return 1;
  return WEXITSTATUS(status);
}
  ]])],[ax_cv_user_namespace=yes],[ax_cv_user_namespace=no],[ax_cv_user_namespace=no])
 AC_LANG_POP([C])
 ])
 if test "$ax_cv_user_namespace" = yes; then
   AC_DEFINE([HAVE_USER_NAMESPACE],[1],[Whether user namespaces are available])
 fi
]) # AX_CHECK_USER_NAMESPACE
