YARN-5121. fix some container-executor portability issues. Contributed by Allen Wittenauer.
diff --git a/LICENSE.txt b/LICENSE.txt
index f4d869d..6910a09 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -414,6 +414,38 @@
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+For hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/compat/{fstatat|openat|unlinkat}.h:
+
+Copyright (c) 2012 The FreeBSD Foundation
+All rights reserved.
+
+This software was developed by Pawel Jakub Dawidek under sponsorship from
+the FreeBSD Foundation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+=============
+
 The binary distribution of this product bundles binaries of leveldb
 (http://code.google.com/p/leveldb/), which is available under the following
 license:
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/pom.xml b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/pom.xml
index a2f81d1..f10fa08 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/pom.xml
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/pom.xml
@@ -274,6 +274,18 @@
       </plugin>
 
       <plugin>
+        <groupId>org.apache.rat</groupId>
+        <artifactId>apache-rat-plugin</artifactId>
+        <configuration>
+          <excludes>
+            <exclude>src/main/native/container-executor/impl/compat/fstatat.h</exclude>
+            <exclude>src/main/native/container-executor/impl/compat/openat.h</exclude>
+            <exclude>src/main/native/container-executor/impl/compat/unlinkat.h</exclude>
+          </excludes>
+        </configuration>
+      </plugin>
+
+      <plugin>
         <groupId>org.apache.hadoop</groupId>
         <artifactId>hadoop-maven-plugins</artifactId>
         <executions>
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/CMakeLists.txt b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/CMakeLists.txt
index d4d6ae1..204b3ca 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/CMakeLists.txt
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/CMakeLists.txt
@@ -24,7 +24,20 @@
 string(REPLACE "-D_FILE_OFFSET_BITS=64" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
 
 include(CheckFunctionExists)
+check_function_exists(canonicalize_file_name HAVE_CANONICALIZE_FILE_NAME)
 check_function_exists(fcloseall HAVE_FCLOSEALL)
+check_function_exists(fchmodat HAVE_FCHMODAT)
+check_function_exists(fdopendir HAVE_FDOPENDIR)
+check_function_exists(fstatat HAVE_FSTATAT)
+check_function_exists(openat HAVE_OPENAT)
+check_function_exists(unlinkat HAVE_UNLINKAT)
+
+if(APPLE)
+  include_directories( /System/Library/Frameworks )
+  find_library(COCOA_LIBRARY Cocoa)
+  mark_as_advanced(COCOA_LIBRARY)
+  set(EXTRA_LIBS ${COCOA_LIBRARY})
+endif(APPLE)
 
 function(output_directory TGT DIR)
     set_target_properties(${TGT} PROPERTIES
@@ -46,6 +59,7 @@
 add_library(container
     main/native/container-executor/impl/configuration.c
     main/native/container-executor/impl/container-executor.c
+    main/native/container-executor/impl/get_executable.c
 )
 
 add_executable(container-executor
@@ -60,6 +74,6 @@
     main/native/container-executor/test/test-container-executor.c
 )
 target_link_libraries(test-container-executor
-    container
+    container ${EXTRA_LIBS}
 )
 output_directory(test-container-executor target/usr/local/bin)
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/config.h.cmake b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/config.h.cmake
index 0f7a490..0ab7bbd 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/config.h.cmake
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/config.h.cmake
@@ -20,6 +20,12 @@
 
 #cmakedefine HADOOP_CONF_DIR "@HADOOP_CONF_DIR@"
 
-#cmakedefine HAVE_FCLOSEALL "@HAVE_FCLOSEALL@"
+#cmakedefine HAVE_CANONICALIZE_FILE_NAME @HAVE_CANONICALIZE_FILE_NAME@
+#cmakedefine HAVE_FCHMODAT @HAVE_FCHMODAT@
+#cmakedefine HAVE_FCLOSEALL @HAVE_FCLOSEALL@
+#cmakedefine HAVE_FDOPENDIR @HAVE_FDOPENDIR@
+#cmakedefine HAVE_FSTATAT @HAVE_FSTATAT@
+#cmakedefine HAVE_OPENAT @HAVE_OPENAT@
+#cmakedefine HAVE_UNLINKAT @HAVE_UNLINKAT@
 
 #endif
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/compat/fchmodat.h b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/compat/fchmodat.h
new file mode 100644
index 0000000..7812b5d
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/compat/fchmodat.h
@@ -0,0 +1,56 @@
+/**
+ * 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.
+ */
+
+#ifndef _FCHMODAT_H_
+#define _FCHMODAT_H_
+
+#include <sys/stat.h>
+
+#include <unistd.h>
+
+#define AT_SYMLINK_NOFOLLOW 0x01
+
+static int
+fchmodat(int fd, const char *path, mode_t mode, int flag)
+{
+  int cfd, error, ret;
+
+  cfd = open(".", O_RDONLY | O_DIRECTORY);
+  if (cfd == -1)
+    return (-1);
+
+  if (fchdir(fd) == -1) {
+    error = errno;
+    (void)close(cfd);
+    errno = error;
+    return (-1);
+  }
+
+  if (flag == AT_SYMLINK_NOFOLLOW)
+    ret = lchmod(path, mode);
+  else
+    ret = chmod(path, mode);
+
+  error = errno;
+  (void)fchdir(cfd);
+  (void)close(cfd);
+  errno = error;
+  return (ret);
+}
+
+#endif  /* !_FCHMODAT_H_ */
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/compat/fdopendir.h b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/compat/fdopendir.h
new file mode 100644
index 0000000..1f9bdc3
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/compat/fdopendir.h
@@ -0,0 +1,52 @@
+/**
+ * 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.
+ */
+
+#ifndef _FDOPENDIR_H_
+#define _FDOPENDIR_H_
+
+#include <fcntl.h>
+#include <stdarg.h>
+#include <unistd.h>
+
+DIR *
+fdopendir(int fd)
+{
+  int cfd, error;
+  DIR *dfd;
+
+  cfd = open(".", O_RDONLY | O_DIRECTORY);
+  if (cfd == -1)
+    return (NULL);
+
+  if (fchdir(fd) == -1) {
+    error = errno;
+    (void)close(cfd);
+    errno = error;
+    return (NULL);
+  }
+
+  dfd=opendir(".");
+  error = errno;
+  (void)fchdir(cfd);
+  (void)close(cfd);
+  errno = error;
+  return (dfd);
+}
+
+#endif  /* !_FDOPENDIR_H_ */
+
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/compat/fstatat.h b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/compat/fstatat.h
new file mode 100644
index 0000000..e1b1658
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/compat/fstatat.h
@@ -0,0 +1,67 @@
+/*-
+ * Copyright (c) 2012 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _FSTATAT_H_
+#define _FSTATAT_H_
+
+#include <sys/stat.h>
+
+#include <unistd.h>
+
+#define AT_SYMLINK_NOFOLLOW 0x01
+
+static int
+fstatat(int fd, const char *path, struct stat *buf, int flag)
+{
+  int cfd, error, ret;
+
+  cfd = open(".", O_RDONLY | O_DIRECTORY);
+  if (cfd == -1)
+    return (-1);
+
+  if (fchdir(fd) == -1) {
+    error = errno;
+    (void)close(cfd);
+    errno = error;
+    return (-1);
+  }
+
+  if (flag == AT_SYMLINK_NOFOLLOW)
+    ret = lstat(path, buf);
+  else
+    ret = stat(path, buf);
+
+  error = errno;
+  (void)fchdir(cfd);
+  (void)close(cfd);
+  errno = error;
+  return (ret);
+}
+
+#endif  /* !_FSTATAT_H_ */
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/compat/openat.h b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/compat/openat.h
new file mode 100644
index 0000000..005be37
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/compat/openat.h
@@ -0,0 +1,74 @@
+/*-
+ * Copyright (c) 2012 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _OPENAT_H_
+#define _OPENAT_H_
+
+#include <fcntl.h>
+#include <stdarg.h>
+#include <unistd.h>
+
+static int
+openat(int fd, const char *path, int flags, ...)
+{
+  int cfd, ffd, error;
+
+  cfd = open(".", O_RDONLY | O_DIRECTORY);
+  if (cfd == -1)
+    return (-1);
+
+  if (fchdir(fd) == -1) {
+    error = errno;
+    (void)close(cfd);
+    errno = error;
+    return (-1);
+  }
+
+  if ((flags & O_CREAT) != 0) {
+    va_list ap;
+    int mode;
+
+    va_start(ap, flags);
+    mode = va_arg(ap, int);
+    va_end(ap);
+
+    ffd = open(path, flags, mode);
+  } else {
+    ffd = open(path, flags);
+  }
+
+  error = errno;
+  (void)fchdir(cfd);
+  (void)close(cfd);
+  errno = error;
+  return (ffd);
+}
+
+#endif  /* !_OPENAT_H_ */
+
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/compat/unlinkat.h b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/compat/unlinkat.h
new file mode 100644
index 0000000..a4977a1
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/compat/unlinkat.h
@@ -0,0 +1,67 @@
+/*-
+ * Copyright (c) 2012 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _UNLINKAT_H_
+#define _UNLINKAT_H_
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#define AT_REMOVEDIR  0x01
+
+static int
+unlinkat(int fd, const char *path, int flag)
+{
+  int cfd, error, ret;
+
+  cfd = open(".", O_RDONLY | O_DIRECTORY);
+  if (cfd == -1)
+    return (-1);
+
+  if (fchdir(fd) == -1) {
+    error = errno;
+    (void)close(cfd);
+    errno = error;
+    return (-1);
+  }
+
+  if (flag == AT_REMOVEDIR)
+    ret = rmdir(path);
+  else
+    ret = unlink(path);
+
+  error = errno;
+  (void)fchdir(cfd);
+  (void)close(cfd);
+  errno = error;
+  return (ret);
+}
+
+#endif  /* !_UNLINKAT_H_ */
+
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/configuration.c b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/configuration.c
index 3447524..69ceaf6 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/configuration.c
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/configuration.c
@@ -17,7 +17,7 @@
  */
 
 // ensure we get the posix version of dirname by including this first
-#include <libgen.h> 
+#include <libgen.h>
 
 #include "configuration.h"
 #include "container-executor.h"
@@ -68,7 +68,7 @@
     return 0;
   }
   if ((file_stat.st_mode & (S_IWGRP | S_IWOTH)) != 0) {
-    fprintf(ERRORFILE, 
+    fprintf(ERRORFILE,
 	    "File %s must not be world or group writable, but is %03lo\n",
 	    file, (unsigned long)file_stat.st_mode & (~S_IFMT));
     return 0;
@@ -92,8 +92,13 @@
     real_fname = buffer;
   }
 
+#ifdef HAVE_CANONICALIZE_FILE_NAME
+  char * ret = (real_fname == NULL) ? NULL : canonicalize_file_name(real_fname);
+#else
   char * ret = (real_fname == NULL) ? NULL : realpath(real_fname, NULL);
+#endif
 #ifdef DEBUG
+  fprintf(stderr,"ret = %s\n", ret);
   fprintf(stderr, "resolve_config_path(file_name=%s,root=%s)=%s\n",
           file_name, root ? root : "null", ret ? ret : "null");
 #endif
@@ -102,7 +107,7 @@
 
 /**
  * Ensure that the configuration file and all of the containing directories
- * are only writable by root. Otherwise, an attacker can change the 
+ * are only writable by root. Otherwise, an attacker can change the
  * configuration and potentially cause damage.
  * returns 0 if permissions are ok
  */
@@ -155,7 +160,7 @@
       exit(OUT_OF_MEMORY);
     }
     size_read = getline(&line,&linesize,conf_file);
- 
+
     //feof returns true only after we read past EOF.
     //so a file with no new line, at last can reach this place
     //if size_read returns negative check for eof condition
@@ -235,7 +240,7 @@
 
     free(line);
   }
- 
+
   //close the file
   fclose(conf_file);
 
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/configuration.h b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/configuration.h
index 8f87cb2..e7e5710 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/configuration.h
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/configuration.h
@@ -24,7 +24,7 @@
 
 /**
  * Ensure that the configuration file and all of the containing directories
- * are only writable by root. Otherwise, an attacker can change the 
+ * are only writable by root. Otherwise, an attacker can change the
  * configuration and potentially cause damage.
  * returns 0 if permissions are ok
  */
@@ -78,7 +78,7 @@
 
 /**
  * If str is a string of the form key=val, find 'key'
- * 
+ *
  * @param input    The input string
  * @param out      Where to put the output string.
  * @param out_len  The length of the output buffer.
@@ -91,7 +91,7 @@
 
 /**
  * If str is a string of the form key=val, find 'val'
- * 
+ *
  * @param input    The input string
  * @param out      Where to put the output string.
  * @param out_len  The length of the output buffer.
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.c b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.c
index e40101c..fef7173 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.c
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.c
@@ -40,6 +40,28 @@
 #include <sys/mount.h>
 #include <sys/wait.h>
 
+#include "config.h"
+
+#ifndef HAVE_FCHMODAT
+#include "compat/fchmodat.h"
+#endif
+
+#ifndef HAVE_FDOPENDIR
+#include "compat/fdopendir.h"
+#endif
+
+#ifndef HAVE_FSTATAT
+#include "compat/fstatat.h"
+#endif
+
+#ifndef HAVE_OPENAT
+#include "compat/openat.h"
+#endif
+
+#ifndef HAVE_UNLINKAT
+#include "compat/unlinkat.h"
+#endif
+
 static const int DEFAULT_MIN_USERID = 1000;
 
 static const char* DEFAULT_BANNED_USERS[] = {"yarn", "mapred", "hdfs", "bin", 0};
@@ -84,31 +106,14 @@
     return get_value(NM_GROUP_KEY, &executor_cfg);
 }
 
-/**
- * get the executable filename.
- */
-char* get_executable() {
-  char buffer[EXECUTOR_PATH_MAX];
-  snprintf(buffer, EXECUTOR_PATH_MAX, "/proc/%" PRId64 "/exe", (int64_t)getpid());
-  char *filename = malloc(EXECUTOR_PATH_MAX);
-  ssize_t len = readlink(buffer, filename, EXECUTOR_PATH_MAX);
-  if (len == -1) {
-    fprintf(ERRORFILE, "Can't get executable name from %s - %s\n", buffer,
-            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;
-}
-
 int check_executor_permissions(char *executable_file) {
 
   errno = 0;
+#ifdef HAVE_CANONICALIZE_FILE_NAME
+  char * resolved_path = canonicalize_file_name(executable_file);
+#else
   char * resolved_path = realpath(executable_file, NULL);
+#endif
   if (resolved_path == NULL) {
     fprintf(ERRORFILE,
         "Error resolving the canonical name for the executable : %s!",
@@ -119,7 +124,7 @@
   struct stat filestat;
   errno = 0;
   if (stat(resolved_path, &filestat) != 0) {
-    fprintf(ERRORFILE, 
+    fprintf(ERRORFILE,
             "Could not stat the executable : %s!.\n", strerror(errno));
     return -1;
   }
@@ -181,6 +186,7 @@
   return 0;
 }
 
+#ifdef __linux
 /**
  * Write the pid of the current process to the cgroup file.
  * cgroup_file: Path to cgroup file where pid needs to be written to.
@@ -218,6 +224,7 @@
 
   return 0;
 }
+#endif
 
 /**
  * Write the pid of the current process into the pid file.
@@ -384,7 +391,7 @@
  * priviledges.
  */
 int change_user(uid_t user, gid_t group) {
-  if (user == getuid() && user == geteuid() && 
+  if (user == getuid() && user == geteuid() &&
       group == getgid() && group == getegid()) {
     return 0;
   }
@@ -396,7 +403,7 @@
     return SETUID_OPER_FAILED;
   }
   if (setgid(group) != 0) {
-    fprintf(LOGFILE, "unable to set group to %d - %s\n", group, 
+    fprintf(LOGFILE, "unable to set group to %d - %s\n", group,
             strerror(errno));
     fprintf(LOGFILE, "Real: %d:%d; Effective: %d:%d\n",
 	    getuid(), getgid(), geteuid(), getegid());
@@ -415,7 +422,7 @@
 /**
  * Utility function to concatenate argB to argA using the concat_pattern.
  */
-char *concatenate(char *concat_pattern, char *return_path_name, 
+char *concatenate(char *concat_pattern, char *return_path_name,
                   int numArgs, ...) {
   va_list ap;
   va_start(ap, numArgs);
@@ -592,12 +599,12 @@
  * Function to prepare the container directories.
  * It creates the container work and log directories.
  */
-static int create_container_directories(const char* user, const char *app_id, 
+static int create_container_directories(const char* user, const char *app_id,
     const char *container_id, char* const* local_dir, char* const* log_dir, const char *work_dir) {
   // create dirs as 0750
   const mode_t perms = S_IRWXU | S_IRGRP | S_IXGRP;
   if (app_id == NULL || container_id == NULL || user == NULL || user_detail == NULL || user_detail->pw_name == NULL) {
-    fprintf(LOGFILE, 
+    fprintf(LOGFILE,
             "Either app_id, container_id or the user passed is null.\n");
     return -1;
   }
@@ -605,7 +612,7 @@
   int result = -1;
   char* const* local_dir_ptr;
   for(local_dir_ptr = local_dir; *local_dir_ptr != NULL; ++local_dir_ptr) {
-    char *container_dir = get_container_work_directory(*local_dir_ptr, user, app_id, 
+    char *container_dir = get_container_work_directory(*local_dir_ptr, user, app_id,
                                                 container_id);
     if (container_dir == NULL) {
       return -1;
@@ -720,7 +727,7 @@
     char *end_ptr = NULL;
     min_uid = strtol(min_uid_str, &end_ptr, 10);
     if (min_uid_str == end_ptr || *end_ptr != '\0') {
-      fprintf(LOGFILE, "Illegal value of %s for %s in configuration\n", 
+      fprintf(LOGFILE, "Illegal value of %s for %s in configuration\n",
 	      min_uid_str, MIN_USERID_KEY);
       fflush(LOGFILE);
       free(min_uid_str);
@@ -848,7 +855,7 @@
   }
   if (change_effective_user(user, group) != 0) {
     fprintf(LOGFILE, "Failed to change user to %i - %i\n", user, group);
- 
+
     ret = -1;
   }
   return ret;
@@ -881,14 +888,14 @@
  * The input stream is closed.
  * Return 0 if everything is ok.
  */
-static int copy_file(int input, const char* in_filename, 
+static int copy_file(int input, const char* in_filename,
 		     const char* out_filename, mode_t perm) {
   const int buffer_size = 128*1024;
   char buffer[buffer_size];
 
   int out_fd = open(out_filename, O_WRONLY|O_CREAT|O_EXCL|O_NOFOLLOW, perm);
   if (out_fd == -1) {
-    fprintf(LOGFILE, "Can't open %s for output - %s\n", out_filename, 
+    fprintf(LOGFILE, "Can't open %s for output - %s\n", out_filename,
             strerror(errno));
     fflush(LOGFILE);
     return -1;
@@ -910,13 +917,13 @@
     len = read(input, buffer, buffer_size);
   }
   if (len < 0) {
-    fprintf(LOGFILE, "Failed to read file %s - %s\n", in_filename, 
+    fprintf(LOGFILE, "Failed to read file %s - %s\n", in_filename,
 	    strerror(errno));
     close(out_fd);
     return -1;
   }
   if (close(out_fd) != 0) {
-    fprintf(LOGFILE, "Failed to close file %s - %s\n", out_filename, 
+    fprintf(LOGFILE, "Failed to close file %s - %s\n", out_filename,
 	    strerror(errno));
     return -1;
   }
@@ -1328,20 +1335,22 @@
   }
 
   if (pid != 0) {
+#ifdef __linux
     fprintf(LOGFILE, "Writing to cgroup task files...\n");
     // cgroups-based resource enforcement
     if (resources_key != NULL && ! strcmp(resources_key, "cgroups")) {
-     // write pid to cgroups
-     char* const* cgroup_ptr;
-     for (cgroup_ptr = resources_values; cgroup_ptr != NULL &&
+      // write pid to cgroups
+      char* const* cgroup_ptr;
+      for (cgroup_ptr = resources_values; cgroup_ptr != NULL &&
           *cgroup_ptr != NULL; ++cgroup_ptr) {
-       if (strcmp(*cgroup_ptr, "none") != 0 &&
+        if (strcmp(*cgroup_ptr, "none") != 0 &&
              write_pid_to_cgroup_as_root(*cgroup_ptr, pid) != 0) {
-         exit_code = WRITE_CGROUP_FAILED;
-         goto cleanup;
-       }
-     }
+          exit_code = WRITE_CGROUP_FAILED;
+          goto cleanup;
+        }
+      }
     }
+#endif
 
     // write pid to pidfile
     fprintf(LOGFILE, "Writing pid file...\n");
@@ -1481,7 +1490,7 @@
     goto cleanup;
   }
 
-  // setsid 
+  // setsid
   pid_t pid = setsid();
   if (pid == -1) {
     exit_code = SETSID_OPER_FAILED;
@@ -1496,12 +1505,13 @@
     goto cleanup;
   }
 
+#ifdef __linux
   fprintf(LOGFILE, "Writing to cgroup task files...\n");
   // cgroups-based resource enforcement
   if (resources_key != NULL && ! strcmp(resources_key, "cgroups")) {
     // write pid to cgroups
     char* const* cgroup_ptr;
-    for (cgroup_ptr = resources_values; cgroup_ptr != NULL && 
+    for (cgroup_ptr = resources_values; cgroup_ptr != NULL &&
          *cgroup_ptr != NULL; ++cgroup_ptr) {
       if (strcmp(*cgroup_ptr, "none") != 0 &&
             write_pid_to_cgroup_as_root(*cgroup_ptr, pid) != 0) {
@@ -1510,6 +1520,7 @@
       }
     }
   }
+#endif
 
   fprintf(LOGFILE, "Creating local dirs...\n");
   exit_code = create_local_dirs(user, app_id, container_id,
@@ -1569,11 +1580,8 @@
 
   if (kill(-pid, sig) < 0) {
     if(errno != ESRCH) {
-      fprintf(LOGFILE, 
-              "Error signalling process group %d with signal %d - %s\n", 
-              -pid, sig, strerror(errno));
-      fprintf(stderr, 
-              "Error signalling process group %d with signal %d - %s\n", 
+      fprintf(LOGFILE,
+              "Error signalling process group %d with signal %d - %s\n",
               -pid, sig, strerror(errno));
       fflush(LOGFILE);
       return UNABLE_TO_SIGNAL_CONTAINER;
@@ -1794,7 +1802,7 @@
  * full_path : the path to delete
  * needs_tt_user: the top level directory must be deleted by the tt user.
  */
-static int delete_path(const char *full_path, 
+static int delete_path(const char *full_path,
                        int needs_tt_user) {
   int ret;
 
@@ -1900,7 +1908,7 @@
 
   char *buf = stpncpy(path_tmp, dir_path, strlen(dir_path));
   *buf++ = '/';
-     
+
   dp = opendir(dir_path);
   if (dp != NULL) {
     while ((ep = readdir(dp)) != NULL) {
@@ -1934,7 +1942,7 @@
       get_kv_value(pair, mount_path, strlen(pair)) < 0) {
     fprintf(LOGFILE, "Failed to mount cgroup controller; invalid option: %s\n",
               pair);
-    result = -1; 
+    result = -1;
   } else {
     if (mount("none", mount_path, "cgroup", 0, controller) == 0) {
       char *buf = stpncpy(hier_path, mount_path, strlen(mount_path));
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.h b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.h
index df5b7d8..1bfa3a5 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.h
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.h
@@ -177,7 +177,7 @@
 // delete a directory (or file) recursively as the user. The directory
 // could optionally be relative to the baseDir set of directories (if the same
 // directory appears on multiple disk volumes, the disk volumes should be passed
-// as the baseDirs). If baseDirs is not specified, then dir_to_be_deleted is 
+// as the baseDirs). If baseDirs is not specified, then dir_to_be_deleted is
 // assumed as the absolute path
 int delete_as_user(const char *user,
                    const char *dir_to_be_deleted,
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/get_executable.c b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/get_executable.c
new file mode 100644
index 0000000..cd89735
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/get_executable.c
@@ -0,0 +1,127 @@
+/**
+ * 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
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/main.c b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/main.c
index 222467a..6fade5c 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/main.c
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/main.c
@@ -83,7 +83,7 @@
     fclose(LOGFILE);
     LOGFILE = NULL;
   }
-  
+
 if (ERRORFILE != NULL) {
     fflush(ERRORFILE);
     fclose(ERRORFILE);
@@ -96,19 +96,27 @@
 This function is to be called in every invocation of container-executor, irrespective
 of whether an explicit checksetup operation is requested. */
 
-static void assert_valid_setup(char *current_executable) {
+static void assert_valid_setup() {
+  int ret;
   char *executable_file = get_executable();
+  if (!executable_file) {
+    fprintf(ERRORFILE,"realpath of executable: %s\n",strerror(errno));
+    flush_and_close_log_files();
+    exit(-1);
+  }
 
   char *orig_conf_file = HADOOP_CONF_DIR "/" CONF_FILENAME;
-  char *conf_file = resolve_config_path(orig_conf_file, current_executable);
+  char *conf_file = resolve_config_path(orig_conf_file, executable_file);
 
   if (conf_file == NULL) {
+    free(executable_file);
     fprintf(ERRORFILE, "Configuration file %s not found.\n", orig_conf_file);
     flush_and_close_log_files();
     exit(INVALID_CONFIG_FILE);
   }
 
   if (check_configuration_permissions(conf_file) != 0) {
+    free(executable_file);
     flush_and_close_log_files();
     exit(INVALID_CONFIG_FILE);
   }
@@ -118,28 +126,42 @@
   // look up the node manager group in the config file
   char *nm_group = get_nodemanager_group();
   if (nm_group == NULL) {
+    free(executable_file);
     fprintf(ERRORFILE, "Can't get configured value for %s.\n", NM_GROUP_KEY);
     flush_and_close_log_files();
     exit(INVALID_CONFIG_FILE);
   }
   struct group *group_info = getgrnam(nm_group);
   if (group_info == NULL) {
+    free(executable_file);
     fprintf(ERRORFILE, "Can't get group information for %s - %s.\n", nm_group,
             strerror(errno));
     flush_and_close_log_files();
     exit(INVALID_CONFIG_FILE);
   }
   set_nm_uid(getuid(), group_info->gr_gid);
-  // if we are running from a setuid executable, make the real uid root
-  setuid(0);
-  // set the real and effective group id to the node manager group
-  setgid(group_info->gr_gid);
+  /*
+   * if we are running from a setuid executable, make the real uid root
+   * we're going to ignore this result just in case we aren't.
+   */
+  ret=setuid(0);
+
+  /*
+   * set the real and effective group id to the node manager group
+   * we're going to ignore this result just in case we aren't
+   */
+  ret=setgid(group_info->gr_gid);
+
+  /* make the unused var warning to away */
+  ret++;
 
   if (check_executor_permissions(executable_file) != 0) {
+    free(executable_file);
     fprintf(ERRORFILE, "Invalid permissions on container-executor binary.\n");
     flush_and_close_log_files();
     exit(INVALID_CONTAINER_EXEC_PERMISSIONS);
   }
+  free(executable_file);
 }
 
 
@@ -407,7 +429,7 @@
 
 int main(int argc, char **argv) {
   open_log_files();
-  assert_valid_setup(argv[0]);
+  assert_valid_setup();
 
   int operation;
   int ret = validate_arguments(argc, argv, &operation);
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/test/test-container-executor.c b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/test/test-container-executor.c
index e9ad370..a2dead2 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/test/test-container-executor.c
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/test/test-container-executor.c
@@ -29,7 +29,19 @@
 #include <sys/stat.h>
 #include <sys/wait.h>
 
-#define TEST_ROOT "/tmp/test-container-executor"
+#ifdef __APPLE__
+#include <CoreFoundation/CFString.h>
+#include <CoreFoundation/CFPreferences.h>
+
+#define TMPDIR "/private/tmp"
+#define RELTMPDIR "../.."
+#else
+#define RELTMPDIR ".."
+#define TMPDIR "/tmp"
+#endif
+
+#define TEST_ROOT TMPDIR "/test-container-executor"
+
 #define DONT_TOUCH_FILE "dont-touch-me"
 #define NM_LOCAL_DIRS       TEST_ROOT "/local-1%" TEST_ROOT "/local-2%" \
                TEST_ROOT "/local-3%" TEST_ROOT "/local-4%" TEST_ROOT "/local-5"
@@ -155,8 +167,8 @@
 }
 
 void test_get_user_directory() {
-  char *user_dir = get_user_directory("/tmp", "user");
-  char *expected = "/tmp/usercache/user";
+  char *user_dir = get_user_directory(TMPDIR, "user");
+  char *expected = TMPDIR "/usercache/user";
   if (strcmp(user_dir, expected) != 0) {
     printf("test_get_user_directory expected %s got %s\n", expected, user_dir);
     exit(1);
@@ -165,8 +177,8 @@
 }
 
 void test_get_app_directory() {
-  char *expected = "/tmp/usercache/user/appcache/app_200906101234_0001";
-  char *app_dir = (char *) get_app_directory("/tmp", "user",
+  char *expected = TMPDIR "/usercache/user/appcache/app_200906101234_0001";
+  char *app_dir = (char *) get_app_directory(TMPDIR, "user",
       "app_200906101234_0001");
   if (strcmp(app_dir, expected) != 0) {
     printf("test_get_app_directory expected %s got %s\n", expected, app_dir);
@@ -176,9 +188,9 @@
 }
 
 void test_get_container_directory() {
-  char *container_dir = get_container_work_directory("/tmp", "owen", "app_1",
+  char *container_dir = get_container_work_directory(TMPDIR, "owen", "app_1",
 						 "container_1");
-  char *expected = "/tmp/usercache/owen/appcache/app_1/container_1";
+  char *expected = TMPDIR"/usercache/owen/appcache/app_1/container_1";
   if (strcmp(container_dir, expected) != 0) {
     printf("Fail get_container_work_directory got %s expected %s\n",
 	   container_dir, expected);
@@ -188,9 +200,9 @@
 }
 
 void test_get_container_launcher_file() {
-  char *expected_file = ("/tmp/usercache/user/appcache/app_200906101234_0001"
+  char *expected_file = (TMPDIR"/usercache/user/appcache/app_200906101234_0001"
 			 "/launch_container.sh");
-  char *app_dir = get_app_directory("/tmp", "user",
+  char *app_dir = get_app_directory(TMPDIR, "user",
                                     "app_200906101234_0001");
   char *container_file =  get_container_launcher_file(app_dir);
   if (strcmp(container_file, expected_file) != 0) {
@@ -241,9 +253,9 @@
            TEST_ROOT "\n");
     exit(1);
   }
-  if (strcmp(resolve_config_path(".." TEST_ROOT, TEST_ROOT), TEST_ROOT) != 0) {
+  if (strcmp(resolve_config_path(RELTMPDIR TEST_ROOT, TEST_ROOT), TEST_ROOT) != 0) {
     printf("FAIL: failed to resolve config_name on a relative path name: "
-           ".." TEST_ROOT " (relative to " TEST_ROOT ")");
+           RELTMPDIR TEST_ROOT " (relative to " TEST_ROOT ")");
     exit(1);
   }
 }
@@ -266,9 +278,9 @@
     exit(1);
   }
   char* app_dir = get_app_directory(TEST_ROOT "/local-2", yarn_username, "app_1");
-  char* dont_touch = get_app_directory(TEST_ROOT "/local-2", yarn_username, 
+  char* dont_touch = get_app_directory(TEST_ROOT "/local-2", yarn_username,
                                        DONT_TOUCH_FILE);
-  char* container_dir = get_container_work_directory(TEST_ROOT "/local-2", 
+  char* container_dir = get_container_work_directory(TEST_ROOT "/local-2",
 					      yarn_username, "app_1", "container_1");
   char buffer[100000];
   sprintf(buffer, "mkdir -p %s/who/let/the/dogs/out/who/who", container_dir);
@@ -328,9 +340,9 @@
 
 void test_delete_app() {
   char* app_dir = get_app_directory(TEST_ROOT "/local-2", yarn_username, "app_2");
-  char* dont_touch = get_app_directory(TEST_ROOT "/local-2", yarn_username, 
+  char* dont_touch = get_app_directory(TEST_ROOT "/local-2", yarn_username,
                                        DONT_TOUCH_FILE);
-  char* container_dir = get_container_work_directory(TEST_ROOT "/local-2", 
+  char* container_dir = get_container_work_directory(TEST_ROOT "/local-2",
 					      yarn_username, "app_2", "container_1");
   char buffer[100000];
   sprintf(buffer, "mkdir -p %s/who/let/the/dogs/out/who/who", container_dir);
@@ -488,7 +500,7 @@
     exit(0);
   }
   printf("Child container launched as %" PRId64 "\n", (int64_t)child);
-  // there's a race condition for child calling change_user and us 
+  // there's a race condition for child calling change_user and us
   // calling signal_container_as_user, hence sleeping
   sleep(3);
   if (signal_container_as_user(yarn_username, child, SIGKILL) != 0) {
@@ -504,7 +516,7 @@
     exit(1);
   }
   if (WTERMSIG(status) != SIGKILL) {
-    printf("FAIL: child was killed with %d instead of %d\n", 
+    printf("FAIL: child was killed with %d instead of %d\n",
 	   WTERMSIG(status), SIGKILL);
     exit(1);
   }
@@ -550,7 +562,7 @@
   fflush(stderr);
   pid_t child = fork();
   if (child == -1) {
-    printf("FAIL: failed to fork process for init_app - %s\n", 
+    printf("FAIL: failed to fork process for init_app - %s\n",
 	   strerror(errno));
     exit(1);
   } else if (child == 0) {
@@ -632,7 +644,7 @@
     printf("FAIL: failed to seteuid back to user - %s\n", strerror(errno));
     exit(1);
   }
-  if (fprintf(script, "#!/bin/bash\n"
+  if (fprintf(script, "#!/usr/bin/env bash\n"
                      "touch foobar\n"
                      "exit 0") < 0) {
     printf("FAIL: fprintf failed - %s\n", strerror(errno));
@@ -644,17 +656,17 @@
   }
   fflush(stdout);
   fflush(stderr);
-  char* container_dir = get_container_work_directory(TEST_ROOT "/local-1", 
+  char* container_dir = get_container_work_directory(TEST_ROOT "/local-1",
 					      yarn_username, "app_4", "container_1");
   const char * pid_file = TEST_ROOT "/pid.txt";
 
   pid_t child = fork();
   if (child == -1) {
-    printf("FAIL: failed to fork process for init_app - %s\n", 
+    printf("FAIL: failed to fork process for init_app - %s\n",
 	   strerror(errno));
     exit(1);
   } else if (child == 0) {
-    if (launch_container_as_user(yarn_username, "app_4", "container_1", 
+    if (launch_container_as_user(yarn_username, "app_4", "container_1",
           container_dir, script_name, TEST_ROOT "/creds.txt", pid_file,
           local_dirs, log_dirs,
           "cgroups", cgroups_pids) != 0) {
@@ -802,7 +814,7 @@
 // effective user id. If executed by a super-user everything
 // gets tested. Here are different ways of execing the test binary:
 // 1. regular user assuming user == yarn user
-//    $ test-container-executor     
+//    $ test-container-executor
 // 2. regular user with a given yarn user
 //    $ test-container-executor yarn_user
 // 3. super user with a given user and assuming user == yarn user
@@ -810,6 +822,7 @@
 // 4. super user with a given user and a given yarn user
 //    # test-container-executor user yarn_user
 int main(int argc, char **argv) {
+  int ret;
   LOGFILE = stdout;
   ERRORFILE = stderr;
 
@@ -817,7 +830,7 @@
   if (system("chmod -R u=rwx " TEST_ROOT "; rm -fr " TEST_ROOT)) {
     exit(1);
   }
-  
+
   if (mkdirs(TEST_ROOT "/logs/userlogs", 0755) != 0) {
     exit(1);
   }
@@ -881,10 +894,36 @@
 
   test_check_user(0);
 
+#ifdef __APPLE__
+   printf("OS X: disabling CrashReporter\n");
+  /*
+   * disable the "unexpectedly quit" dialog box
+   * because we know we're going to make our container
+   * do exactly that.
+   */
+  CFStringRef crashType      = CFSTR("DialogType");
+  CFStringRef crashModeNone  = CFSTR("None");
+  CFStringRef crashAppID     = CFSTR("com.apple.CrashReporter");
+  CFStringRef crashOldMode   = CFPreferencesCopyAppValue(CFSTR("DialogType"), CFSTR("com.apple.CrashReporter"));
+
+  CFPreferencesSetAppValue(crashType, crashModeNone, crashAppID);
+  CFPreferencesAppSynchronize(crashAppID);
+#endif
+
   // the tests that change user need to be run in a subshell, so that
   // when they change user they don't give up our privs
   run_test_in_child("test_signal_container_group", test_signal_container_group);
 
+#ifdef __APPLE__
+  /*
+   * put the "unexpectedly quit" dialog back
+   */
+
+  CFPreferencesSetAppValue(crashType, crashOldMode, crashAppID);
+  CFPreferencesAppSynchronize(crashAppID);
+  printf("OS X: CrashReporter re-enabled\n");
+#endif
+
   // init app and run container can't be run if you aren't testing as root
   if (getuid() == 0) {
     // these tests do internal forks so that the change_owner and execs
@@ -893,7 +932,13 @@
     test_run_container();
   }
 
-  seteuid(0);
+  /*
+   * try to seteuid(0).  if it doesn't work, carry on anyway.
+   * we're going to capture the return value to get rid of a 
+   * compiler warning.
+   */
+  ret=seteuid(0);
+  ret++;
   // test_delete_user must run as root since that's how we use the delete_as_user
   test_delete_user();
   free_executor_configurations();
@@ -904,11 +949,19 @@
   }
 
   read_executor_config(TEST_ROOT "/test.cfg");
+#ifdef __APPLE__
+  username = "_uucp";
+  test_check_user(1);
+
+  username = "_networkd";
+  test_check_user(1);
+#else
   username = "bin";
   test_check_user(1);
 
   username = "sys";
   test_check_user(1);
+#endif
 
   run("rm -fr " TEST_ROOT);
   printf("\nFinished tests\n");