Branch
Hash :
7b089321
Author :
Date :
2025-01-01T09:24:36
maint: run 'make update-copyright'
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
#!/bin/sh
# Execute a C# program.
# Copyright (C) 2003-2025 Free Software Foundation, Inc.
# Written by Bruno Haible <bruno@clisp.org>, 2003.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# This uses the same choices as csharpexec.c, but instead of relying on the
# environment settings at run time, it uses the environment variables
# present at configuration time.
#
# This is a separate shell script, because the various C# interpreters have
# different command line options.
#
# Usage: /bin/sh csharpexec.sh [OPTION] program.exe [ARGUMENTS]
# Options:
# -L DIRECTORY search for C# libraries also in DIRECTORY
# func_tmpdir
# creates a temporary directory.
# Sets variable
# - tmp pathname of freshly created temporary directory
func_tmpdir ()
{
# Use the environment variable TMPDIR, falling back to /tmp. This allows
# users to specify a different temporary directory, for example, if their
# /tmp is filled up or too small.
: "${TMPDIR=/tmp}"
{
# Use the mktemp program if available. If not available, hide the error
# message.
tmp=`(umask 077 && mktemp -d -q "$TMPDIR/gtXXXXXX") 2>/dev/null` &&
test -n "$tmp" && test -d "$tmp"
} ||
{
# Use a simple mkdir command. It is guaranteed to fail if the directory
# already exists. $RANDOM is bash specific and expands to empty in shells
# other than bash, ksh and zsh. Its use does not increase security;
# rather, it minimizes the probability of failure in a very cluttered /tmp
# directory.
tmp=$TMPDIR/gt$$-$RANDOM
(umask 077 && mkdir "$tmp")
} ||
{
echo "$0: cannot create a temporary directory in $TMPDIR" >&2
{ (exit 1); exit 1; }
}
}
libdirs_mono=
libdirs_dotnet=
prog=
while test $# != 0; do
case "$1" in
-L)
libdirs_mono="${libdirs_mono:+$libdirs_mono@MONO_PATH_SEPARATOR@}$2"
libdirs_dotnet="${libdirs_dotnet:+$libdirs_dotnet|}$2"
shift
;;
-*)
echo "csharpexec: unknown option '$1'" 1>&2
exit 1
;;
*)
prog="$1"
break
;;
esac
shift
done
if test -z "$prog"; then
echo "csharpexec: no program specified" 1>&2
exit 1
fi
case "$prog" in
*.exe) ;;
*)
echo "csharpexec: program is not a .exe" 1>&2
exit 1
;;
esac
if test -n "@HAVE_MONO@"; then
CONF_MONO_PATH='@MONO_PATH@'
if test -n "$libdirs_mono"; then
MONO_PATH="$libdirs_mono${CONF_MONO_PATH:+@MONO_PATH_SEPARATOR@$CONF_MONO_PATH}"
else
MONO_PATH="$CONF_MONO_PATH"
fi
export MONO_PATH
test -z "$CSHARP_VERBOSE" || echo mono "$@" 1>&2
exec mono "$@"
else
if test -n "@HAVE_DOTNET@"; then
# Invoke 'dotnet $prog ...'.
# Documentation:
# <https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet#options-for-running-an-application>
# This could be optimized on Windows platforms, because C# .exe files are
# directly executable there. But there's no point in optimizing specifically
# a non-free platform, especially since it would increase the test matrix.
shift
# On Windows, assume that 'dotnet' is a native Windows program, not a Cygwin program.
prog_arg="$prog"
case "@build_os@" in
cygwin*)
prog_arg=`cygpath -w "$prog"`
;;
esac
# Handle the -L options.
# The way this works is that we have to copy (or symlink) the DLLs into the
# directory where FOO.exe resides.
# Maybe there is another way to do this, but I haven't found it, trying
# - the --additionalprobingpath command-line option,
# - the additionalProbingPaths property in runtimeconfig.json,
# - adding a --deps deps.json option,
# cf. <https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet#options-for-running-an-application>
# and <https://github.com/dotnet/runtime/blob/main/docs/design/features/host-probing.md>.
tmpfiles=
if test -n "$libdirs_dotnet"; then
# Make sure the added DLLs are removed when this script terminates.
func_cleanup_tmpfiles()
{
saved_IFS="$IFS"
IFS='|'
for file in $tmpfiles; do
IFS="$saved_IFS"
rm -f "$file"
done
IFS="$saved_IFS"
}
trap func_cleanup_tmpfiles HUP INT QUIT PIPE TERM
trap 'exit_status=$?; func_cleanup_tmpfiles; exit $exit_status' EXIT
# Copy the DLLs.
prog_dir=`dirname "$prog"`
saved_IFS="$IFS"
IFS='|'
for dir in $libdirs_dotnet; do
IFS="$saved_IFS"
for file in `cd "$dir" && echo *.dll`; do
if test -f "$prog_dir/$file"; then
# A DLL of this name is already at the expected location.
:
else
tmpfiles="${tmpfiles:+$tmpfiles|}$prog_dir/$file"
cp "$dir/$file" "$prog_dir/$file" || exit 1
fi
done
done
IFS="$saved_IFS"
fi
if test -f "${prog%.exe}.runtimeconfig.json"; then
# There is already a FOO.runtimeconfig.json alongside FOO.exe.
dotnet exec "$prog_arg" "$@"
result=$?
else
# dotnet needs a FOO.runtimeconfig.json alongside FOO.exe in order to
# execute FOO.exe. Create a dummy one in a temporary directory
# (because the directory where FOO.exe sits is not necessarily writable).
# Documentation of this file format:
# <https://learn.microsoft.com/en-us/dotnet/core/runtime-config/>
func_tmpdir
runtimeconfig="$tmp"/runtimeconfig.json
dotnet --list-runtimes | sed -n -e 's/Microsoft.NETCore.App \([^ ]*\) .*/{ "runtimeOptions": { "framework": { "name": "Microsoft.NETCore.App", "version": "\1" } } }/p' > "$runtimeconfig"
runtimeconfig_arg="$runtimeconfig"
case "@build_os@" in
cygwin*)
runtimeconfig_arg=`cygpath -w "$runtimeconfig"`
;;
esac
test -z "$CSHARP_VERBOSE" || echo dotnet exec --runtimeconfig "$runtimeconfig_arg" "$prog_arg" "$@" 1>&2
dotnet exec --runtimeconfig "$runtimeconfig_arg" "$prog_arg" "$@"
result=$?
rm -f "$runtimeconfig"
rmdir "$tmp"
fi
exit $result
else
if test -n "@HAVE_CLIX@"; then
CONF_CLIX_PATH='@CLIX_PATH@'
if test -n "$libdirs_mono"; then
@CLIX_PATH_VAR@="$libdirs_mono${CONF_CLIX_PATH:+@MONO_PATH_SEPARATOR@$CONF_CLIX_PATH}"
else
@CLIX_PATH_VAR@="$CONF_CLIX_PATH"
fi
export @CLIX_PATH_VAR@
shift
# On Windows, assume that 'clix' is a native Windows program,
# not a Cygwin program.
case "@build_os@" in
cygwin*)
prog=`cygpath -w "$prog"`
;;
esac
test -z "$CSHARP_VERBOSE" || echo clix "$prog" "$@" 1>&2
exec clix "$prog" "$@"
else
echo 'C# virtual machine not found, try installing mono or dotnet, then reconfigure' 1>&2
exit 1
fi
fi
fi