text: /**
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements.  See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership.  The ASF licenses this file
   * to you under the Apache License, Version 2.0 (the
   * "License"); you may not use this file except in compliance
   * with the License.  You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  /*
   * This code implements OS-specific ways to get the absolute
   * filename of the executable.  Typically, one would use
   * realpath(argv[0]) (or equivalent), however, because this
   * code runs as setuid and will be used later on to determine
   * relative paths, we want something a big more secure
   * since argv[0] is replaceable by malicious code.
   *
   * NOTE! The value returned will be free()'d later on!
   *
   */
  
  #include <errno.h>
  #include <stdio.h>
  #include <string.h>
  #include <stdlib.h>
  #include <unistd.h>
  #include "config.h"
  #include "configuration.h"
  #include "container-executor.h"
  
  /*
   * A generic function to read a link and return
   * the value for use with System V procfs.
   * With much thanks to Tom Killian, Roger Faulkner,
   * and Ron Gomes, this is pretty generic code.
   *
   * The various BSDs do not have (reliably)
   * have /proc. Custom implementations follow.
   */
  
  char *__get_exec_readproc(char *procfn) {
    char *filename;
    ssize_t len;
  
    filename = malloc(EXECUTOR_PATH_MAX);
    if (!filename) {
      fprintf(ERRORFILE,"cannot allocate memory for filename: %s\n",strerror(errno));
      exit(-1);
    }
    len = readlink(procfn, filename, EXECUTOR_PATH_MAX);
    if (len == -1) {
      fprintf(ERRORFILE,"Can't get executable name from %s - %s\n", procfn,
              strerror(errno));
      exit(-1);
    } else if (len >= EXECUTOR_PATH_MAX) {
      fprintf(ERRORFILE,"Executable name %.*s is longer than %d characters.\n",
              EXECUTOR_PATH_MAX, filename, EXECUTOR_PATH_MAX);
      exit(-1);
    }
    filename[len] = '\0';
    return filename;
  }
  
  #ifdef __APPLE__
  
  /*
   * Mac OS X doesn't have a procfs, but there is
   * libproc which we can use instead.  It is available
   * in most modern versions of OS X as of this writing (2016).
   */
  
  #include <libproc.h>
  
  char* get_executable() {
    char *filename;
    pid_t pid;
  
    filename = malloc(PROC_PIDPATHINFO_MAXSIZE);
    if (!filename) {
      fprintf(ERRORFILE,"cannot allocate memory for filename: %s\n",strerror(errno));
      exit(-1);
    }
    pid = getpid();
    if (proc_pidpath(pid,filename,PROC_PIDPATHINFO_MAXSIZE) <= 0) {
      fprintf(ERRORFILE,"Can't get executable name from pid %u - %s\n", pid,
              strerror(errno));
      exit(-1);
    }
    return filename;
  }
  
  #elif defined(__linux)
  
  
  char* get_executable() {
    return __get_exec_readproc("/proc/self/exe");
  }
  
  #elif defined(__sun)
  
  /*
   * It's tempting to use getexecname(), but there is no guarantee
   * we will get a full path and worse, we'd be reliant on getcwd()
   * being where our exec is at. Instead, we'll use the /proc
   * method, using the "invisible" /proc/self link that only the
   * process itself can see. (Anyone that tells you /proc/self
   * doesn't exist on Solaris hasn't read the proc(4) man page.)
   */
  
  char* get_executable() {
    return __get_exec_readproc("/proc/self/path/a.out");
  }
  
  #else
  
  #error Cannot safely determine executable path on this operating system.
  
  #endif
  