From db7fe39b744d071bb0428c91e2eb84877f068dac Mon Sep 17 00:00:00 2001
From: Kurtis Rader <krader@skepticism.us>
Date: Thu, 2 May 2019 21:14:13 -0700
Subject: [PATCH] Preliminary support for Solaris

This is the bare minimum set of changes needed to allow building ksh on
OpenIndiana which is based on Illumos which is a fork of Open Solaris.
There are 25 test failures so more work is required.

I also had to make two changes to `meson` which I'll document separately.
---
 config_ast.h.in                      |  6 ++++++
 features/libpath.sh                  |  4 ++--
 features/meson.build                 |  5 +++++
 meson.build                          | 13 +++++++++++++
 scripts/libast_prereq.sh             |  2 +-
 src/cmd/ksh93/bltins/cd_pwd.c        |  4 ++++
 src/cmd/ksh93/meson.build            |  4 ++--
 src/lib/libast/comp/conf.sh          |  5 +++--
 src/lib/libast/meson.build           |  3 ++-
 src/lib/libast/misc/fgetcwd.c        |  4 ++++
 src/lib/libast/string/strperm.c      |  8 ++++++++
 src/lib/libast/tests/aso/meson.build |  1 +
 src/lib/libast/tm/tvtouch.c          |  8 ++++++++
 src/lib/libcmd/chmod.c               |  8 ++++++++
 src/lib/libcmd/uname.c               |  5 +++++
 src/lib/libdll/dlldefs.h             |  2 ++
 16 files changed, 74 insertions(+), 8 deletions(-)

diff --git a/config_ast.h.in b/config_ast.h.in
index a9d092982d5..7078c147cf5 100644
--- a/config_ast.h.in
+++ b/config_ast.h.in
@@ -175,6 +175,12 @@
 #mesondefine _ast_intmax_long
 #define _ast_fltmax_t long double
 
+// This shouldn't be necessary but old distros such as SVR4 (e.g., Solaris,
+// OpenIndiana) may not define this type. Rather than add a feature test just
+// define the type. Since the signature is identical on newer distros this
+// doesn't cause any problems.
+typedef void (*sig_t)(int);
+
 #if DEBUG_BUILD
 // If we're doing a debug build don't have any static (module private) functions.
 // This is needed on most platforms for dladdr() to give us an accurate backtrace.
diff --git a/features/libpath.sh b/features/libpath.sh
index c261ddb677a..a9040cfa85b 100755
--- a/features/libpath.sh
+++ b/features/libpath.sh
@@ -43,7 +43,7 @@ do	case $i in
 done
 if	test "$ok" = "1"
 then	libpath=lib:LD_LIBRARY_PATH
-	case $("$MESON_SOURCE_ROOT/bin/hosttype") in
+	case $("$MESON_SOURCE_ROOT/scripts/hosttype") in
 	sgi.*)	if	test -d /lib32
 		then	libpath="lib32:LD_LIBRARYN32_PATH:sgi.mips3|sgi.*-n32,$libpath"
 		fi
@@ -63,7 +63,7 @@ elif	test -x /lib/dld.sl
 then	libpath=lib:SHLIB_PATH
 elif	test -x /usr/lib/dyld
 then	libpath=lib:DYLD_LIBRARY_PATH
-else	case $("$MESON_SOURCE_ROOT/bin/hosttype") in
+else	case $("$MESON_SOURCE_ROOT/scripts/hosttype") in
 	ibm.*|mvs.*)
 		libpath=lib:LIBPATH
 		;;
diff --git a/features/meson.build b/features/meson.build
index 491e658c7f2..d5688d89f12 100644
--- a/features/meson.build
+++ b/features/meson.build
@@ -39,6 +39,11 @@ endif
 # libc, on others they are found in libm.
 libm_dep = cc.find_library('m', required: false, dirs: lib_dirs)
 
+# On some platforms the network functions (e.g., `socket()`) that we need are found in
+# libc, on others they are found in libsocket and libnsl.
+libsocket_dep = cc.find_library('socket', required: false, dirs: lib_dirs)
+libnsl_dep = cc.find_library('nsl', required: false, dirs: lib_dirs)
+
 # On some platforms `dladdr()` and related functions are found in libc,
 # on others they are found in libdl.
 libdl_dep = cc.find_library('dl', required: false, dirs: lib_dirs)
diff --git a/meson.build b/meson.build
index bcc9b885f6f..9200f913f96 100644
--- a/meson.build
+++ b/meson.build
@@ -12,6 +12,7 @@ endif
 # Global compiler flags aren't used by the feature tests. So instead put them
 # in an array that will be used by the feature tests.
 feature_test_args = ['-std=gnu99', '-D_GNU_SOURCE']
+
 if system == 'openbsd'
     # This is needed because OpenBSD installs a lot of stuff in
     # /usr/local/{include,lib} that would normally be in /usr/{include,lib}.
@@ -35,6 +36,18 @@ add_global_arguments('-std=gnu99', language: 'c')
 # GNU distros.
 add_global_arguments('-D_GNU_SOURCE', language: 'c')
 
+# Solaris/SunOS and its derivatives, such as IllumOS and OpenIndiana, need
+# special handling.
+#
+# TODO: Figure out the correct way to enable the POSIX extensions we require.
+# Defining __EXTENSIONS__ is almost certainly the wrong way to do this.
+if system == 'sunos' or system == 'solaris'
+    feature_test_args += ['-D__EXTENSIONS__', '-DAST_SUNOS']
+    add_global_arguments('-D__EXTENSIONS__', language: 'c')
+    add_global_arguments('-DAST_SUNOS', language: 'c')
+endif
+
+
 # The AST/ksh code is littered with aliasing that violates the assumptions the
 # compiler makes when `-fstrict-aliasing` is in effect so make sure those
 # optimizations are disabled.
diff --git a/scripts/libast_prereq.sh b/scripts/libast_prereq.sh
index fbbde45da66..92c5c0e2a46 100755
--- a/scripts/libast_prereq.sh
+++ b/scripts/libast_prereq.sh
@@ -18,7 +18,7 @@ INC_DIRS="$INC_DIRS -I$MESON_SOURCE_ROOT/src/lib/libast/include"
 INC_DIRS="$INC_DIRS -I$MESON_SOURCE_ROOT/src/lib/libast/features"
 INC_DIRS="$INC_DIRS -I$MESON_SOURCE_ROOT/src/cmd/std"
 
-if [ -z "$CC" ];
+if [ -z "$CC" ]
 then
     CC=cc
 fi
diff --git a/src/cmd/ksh93/bltins/cd_pwd.c b/src/cmd/ksh93/bltins/cd_pwd.c
index 4d7ca095474..927fd727f88 100644
--- a/src/cmd/ksh93/bltins/cd_pwd.c
+++ b/src/cmd/ksh93/bltins/cd_pwd.c
@@ -50,6 +50,10 @@
 #include "stk.h"
 #include "variables.h"
 
+#ifndef O_DIRECTORY
+#define O_DIRECTORY 0
+#endif
+
 //
 // Invalidate path name bindings to relative paths.
 //
diff --git a/src/cmd/ksh93/meson.build b/src/cmd/ksh93/meson.build
index 7a4dc7ee7d8..b0b133b402b 100644
--- a/src/cmd/ksh93/meson.build
+++ b/src/cmd/ksh93/meson.build
@@ -23,7 +23,7 @@ shared_c_args += [
 libksh = library('ksh', ksh93_files,
                  include_directories: [configuration_incdir, ksh93_incdir],
                  c_args: shared_c_args,
-                 dependencies: [libm_dep, libexecinfo_dep, libdl_dep],
+                 dependencies: [libm_dep, libexecinfo_dep, libdl_dep, libsocket_dep, libnsl_dep],
                  install: false)
 
 ksh93_exe = executable('ksh', ['sh/pmain.c'], c_args: shared_c_args,
@@ -35,7 +35,7 @@ ksh93_exe = executable('ksh', ['sh/pmain.c'], c_args: shared_c_args,
 shcomp_exe = executable('shcomp', ['sh/shcomp.c'], c_args: shared_c_args,
     include_directories: [configuration_incdir, ksh93_incdir],
     link_with: [libksh, libast, libcmd, libdll],
-    dependencies: [libm_dep, libexecinfo_dep, libdl_dep],
+    dependencies: [libm_dep, libexecinfo_dep, libdl_dep, libsocket_dep, libnsl_dep],
     install: true)
 
 install_man('ksh.1')
diff --git a/src/lib/libast/comp/conf.sh b/src/lib/libast/comp/conf.sh
index d456fc23a71..abda3529ed2 100755
--- a/src/lib/libast/comp/conf.sh
+++ b/src/lib/libast/comp/conf.sh
@@ -1,4 +1,5 @@
 #!/bin/sh
+set -x
 ########################################################################
 #                                                                      #
 #               This software is part of the ast package               #
@@ -48,7 +49,7 @@ PATH="$MESON_SOURCE_ROOT/scripts:$PATH"
 tmpdir=$(mktemp -dt ksh.XXXXXX)
 tmp=$tmpdir/conf
 cd $tmpdir || exit
-trap "rm -rf $tmpdir" EXIT
+trap "cd /tmp; rm -rf $tmpdir" EXIT
 
 # We need to create the Meson build directory that will contain the
 # dynamically generated source files.
@@ -338,7 +339,7 @@ sort -u > $tmp.g
 } > $tmp.t
 mv $tmp.t $tmp.g
 
-HOST=`"$MESON_SOURCE_ROOT/bin/hosttype" | sed -e 's,[0123456789.].*,,' | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ`
+HOST=`"$MESON_SOURCE_ROOT/scripts/hosttype" | sed -e 's,[0123456789.].*,,' | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ`
 case $HOST in
 '')     HOST=SYSTEM ;;
 esac
diff --git a/src/lib/libast/meson.build b/src/lib/libast/meson.build
index 2d97b14a627..d4af8589147 100644
--- a/src/lib/libast/meson.build
+++ b/src/lib/libast/meson.build
@@ -20,7 +20,8 @@ subdir('tm')
 libast = library('ast', libast_files,
                  include_directories: [configuration_incdir, libast_incdir],
                  c_args: libast_c_args,
-                 dependencies: [libm_dep, libiconv_dep, libcatgets_dep, libexecinfo_dep, libdl_dep],
+                 dependencies: [libm_dep, libiconv_dep, libcatgets_dep, libexecinfo_dep, libdl_dep,
+                                libsocket_dep, libnsl_dep],
                  install: get_option('default_library') == 'shared')
 
 # This library exists solely to support libast unit tests so that `sh_getenv()` and
diff --git a/src/lib/libast/misc/fgetcwd.c b/src/lib/libast/misc/fgetcwd.c
index 5cd2c201a86..31a032c2065 100644
--- a/src/lib/libast/misc/fgetcwd.c
+++ b/src/lib/libast/misc/fgetcwd.c
@@ -41,6 +41,10 @@
 
 #include "ast_dir.h"
 
+#ifndef O_DIRECTORY
+#define O_DIRECTORY 0
+#endif
+
 #ifndef ERANGE
 #define ERANGE E2BIG
 #endif
diff --git a/src/lib/libast/string/strperm.c b/src/lib/libast/string/strperm.c
index 7de2ea266cc..dd3a10f5b3c 100644
--- a/src/lib/libast/string/strperm.c
+++ b/src/lib/libast/string/strperm.c
@@ -40,6 +40,14 @@
 
 #include "modex.h"
 
+#ifndef ALLPERMS
+#ifdef S_ISTXT
+#define ALLPERMS (S_ISTXT | S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO)
+#else
+#define ALLPERMS (S_ISVTX | S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO)
+#endif
+#endif
+
 int strperm(const char *aexpr, char **e, int perm) {
     char *expr = (char *)aexpr;
     int c;
diff --git a/src/lib/libast/tests/aso/meson.build b/src/lib/libast/tests/aso/meson.build
index 81520a68709..e0ca56f2636 100644
--- a/src/lib/libast/tests/aso/meson.build
+++ b/src/lib/libast/tests/aso/meson.build
@@ -9,6 +9,7 @@ foreach test_name: tests
         c_args: shared_c_args,
         include_directories: [configuration_incdir, incdir],
         link_with: [libast, libenv],
+        dependencies: [libm_dep],
         install: false)
     test('API/aso/' + test_name, sh_exe, args: [test_driver, test_target, test_dir])
 endforeach
diff --git a/src/lib/libast/tm/tvtouch.c b/src/lib/libast/tm/tvtouch.c
index 21c5f93bfe0..3e7d80b0672 100644
--- a/src/lib/libast/tm/tvtouch.c
+++ b/src/lib/libast/tm/tvtouch.c
@@ -37,6 +37,14 @@
 
 #include "tv.h"
 
+#ifndef ALLPERMS
+#ifdef S_ISTXT
+#define ALLPERMS (S_ISTXT | S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO)
+#else
+#define ALLPERMS (S_ISVTX | S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO)
+#endif
+#endif
+
 // NOTE: These symbols aren't actually available to any code calling tvtouch() since they are not
 // defined in any header that such code could include. See the NOTE below.
 //
diff --git a/src/lib/libcmd/chmod.c b/src/lib/libcmd/chmod.c
index 65f78313f0e..7f60b1ad8da 100644
--- a/src/lib/libcmd/chmod.c
+++ b/src/lib/libcmd/chmod.c
@@ -41,6 +41,14 @@
 #include "sfio.h"
 #include "shcmd.h"
 
+#ifndef ALLPERMS
+#ifdef S_ISTXT
+#define ALLPERMS (S_ISTXT | S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO)
+#else
+#define ALLPERMS (S_ISVTX | S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO)
+#endif
+#endif
+
 static const char usage[] =
     "[-?\n@(#)$Id: chmod (AT&T Research) 2012-04-20 $\n]" USAGE_LICENSE
     "[+NAME?chmod - change the access permissions of files]"
diff --git a/src/lib/libcmd/uname.c b/src/lib/libcmd/uname.c
index 8c54eb36bb2..11e55e87a15 100644
--- a/src/lib/libcmd/uname.c
+++ b/src/lib/libcmd/uname.c
@@ -298,11 +298,16 @@ int b_uname(int argc, char **argv, Shbltin_t *context) {
         }
 #endif
         if (flags & OPT_domain) {
+#if AST_SUNOS
+            // TODO: Fix this for Solaris.
+            s = "domain.unknown";
+#else
             s = astconf("SRPC_DOMAIN", NULL, NULL);
             if (!(*s)) {
                 getdomainname(buf, sizeof(buf));
                 s = buf;
             }
+#endif
             sep = output(sep, flags, OPT_domain, s, "domain");
         }
         if (sep) sfputc(sfstdout, '\n');
diff --git a/src/lib/libdll/dlldefs.h b/src/lib/libdll/dlldefs.h
index 6743f7cdb65..01e8aef9d8c 100644
--- a/src/lib/libdll/dlldefs.h
+++ b/src/lib/libdll/dlldefs.h
@@ -33,7 +33,9 @@
 #include "ast.h"
 #include "cdt.h"
 
+#ifndef RTLD_PARENT
 #define RTLD_PARENT 0
+#endif
 
 #define DLL_INFO_PREVER 0x0001  // pre-suffix style version
 #define DLL_INFO_DOTVER 0x0002  // post-suffix style version
