File gswrap of Package gswrap.22075

#!/bin/bash
#
# Copyright (c) 2019 SuSE GmbH Nuernberg, Germany.
# Copyright (c) 2021 SuSE SUSE Software Solutions Germany GmbH.
# Copyright (c) 2019,2021 Werner Fink
#
# Wrapper script for ghostscript based on bwrap, the container setup
# utility, which does use e.g. unshare(2) system call to create a
# safe container environment.
#
# Please report bugfixes or comments at https://www.suse.com/feedback/
#
# 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 2.1 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, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#

ghostscript=@@GS@@

for prog in fuser realpath
do
   type $prog >& /dev/null && continue
   echo "GS: No $prog found in path" 1>&2
   exit 1
done

user=nobody
home="/home/$user"
uid=$(id -u "$user")
gid=$(id -g "$user")
lock=$(mktemp "${TMPDIR:-/tmp}/.gswrap-XXXXXXXXXX") || exit 1

unlock ()
{
    test -e "$lock" || return
    fuser -TERM "$lock"
    rm -f "$lock"
}

finish ()
{
    # Used with trap to copy output files back to original cwd or directory
    # to be able to hide the original cwd or directory from ghostscript process
    local dir="$1"
    local tmp="$2"
    if test -d "$tmp"
    then
	for ps in "$tmp/"*
	do
	    test -e "$ps"  || continue
	    test -p "$ps"  && continue
	    test -d "$dir" || continue
	    mv -f "$ps" "$dir"
	done
	rm -rf "$tmp"
    fi
    unlock
}

trap 'unlock' EXIT SIGINT SIGHUP

typeset -i safer=0
typeset    pipecmd=""
typeset -i pipepos
typeset -a opts=()
typeset -i o=0
for lib in $(ldd $ghostscript | sed -rn 's|.*=>[[:blank:]]+||;s|[[:blank:]]*(/[^[:blank:]]+)[[:blank:]]+.*|\1|p')
do
    opts[o++]=--ro-bind
    opts[o++]="$lib"
    opts[o++]="$lib"
done
for dir in /lib/tls /lib64/tls /lib64/x86_64 /usr/lib/ghostscript /usr/lib64/ghostscript /etc/ghostscript
do
    test -d "$dir" || continue
    opts[o++]=--ro-bind
    opts[o++]="$dir"
    opts[o++]="$dir"
done
typeset -a argv=("$@")
typeset -i c=0 argc=${#argv[@]}
for ((c=0; c < argc; c++))
do
    arg="${argv[c]}"
    case "$arg" in
    -dSAFER)
	let safer++
	;;
    -o)
	if ((c+1 >= argc))
	then
	    echo "GS: found -o without argument" 1>&2
	    exit 1
	else
	    unset argv[c]
	    argv[c+1]=-sOutputFile="${argv[c+1]}"
	fi
	;;
    -sOutputFile=*)
	case "${arg#-sOutputFile=}" in
	%stdout%|%stderr%|%stdout|%stderr|-|"")
	    continue ;;
	%pipe%*)
	    pipecmd="${arg#-sOutputFile=%pipe%}"
	    let pipepos=c
	    ;;
	esac
	file="${arg#-sOutputFile=}"
	dir="${file%/*}"
	file="${file##*/}"
	if test -n "$file"
	then
	    if test -n "$dir" -a "$dir" = "/dev"
	    then
		# Only /dev/null or /dev/zero allowed
		if test "$file" != null -a "$file" != zero
		then
		    echo "GS: only /dev/null or /dev/zero allowed" 1>&2
		    exit 1
		fi
		opts[o++]=--dir
		opts[o++]="$home/out"
	    elif test -n "$dir" -a -d "$dir"
	    then
		tmp=$(mktemp -d "$dir/.gswrap-XXXXXXXXXX") || exit 1
		trap "finish '$dir' '$tmp'" EXIT SIGINT SIGHUP
		opts[o++]=--bind
		opts[o++]="${tmp+"$tmp"}"
		opts[o++]="$home/out"
	    else
		tmp=$(mktemp -d "$PWD/.gswrap-XXXXXXXXXX") || exit 1
		trap "finish '$PWD' '$tmp'" EXIT SIGINT SIGHUP
		opts[o++]=--bind
		opts[o++]="${tmp+"$tmp"}"
		opts[o++]="$home/out"
	    fi
	fi
	argv[c]="-sOutputFile=$home/out/${file}"
	continue
	;;
    -sDEVICE=*)
	case "${arg#-sDEVICE=}" in
	x11*)
	    ;;
	*)
	    unset DISPLAY
	    ;;
	esac
	continue
	;;
    @*)
	opts[o++]=--ro-bind
	opts[o++]="${arg#@}"
	opts[o++]="$home/${arg#@}"
	continue
	;;
    -*)
	continue
	;;
    esac
    test -e "$arg" || continue
    if test "${arg##*/}" = "$arg"
    then
	opts[o++]=--ro-bind
	opts[o++]="$arg"
	opts[o++]="$home/$arg"
    else
	arg="$(realpath "$arg")" || exit 1
	argv[c]="$arg"
	test "$arg" != / || continue
	test "$arg" != /home || continue
	test "$arg" != $home || continue
	opts[o++]=--ro-bind
	opts[o++]="$arg"
	opts[o++]="$arg"
    fi
done
# If no -dSAFER then execute the orignal ghostscript program now
if ((safer == 0))
then
    exec -a ${0} $ghostscript ${1+"$@"}
fi
if test -n "$pipecmd"
then
    mkfifo -m 666 "${tmp}/fd"
    fd="${tmp}/fd"
    exec "$pipecmd" < $fd &
    argv[pipepos]="-sOutputFile=$home/fifo"
    opts[o++]=--bind
    opts[o++]="$fd"
    opts[o++]="$home/fifo"
fi
# User might have some own font configurations as well
if test -d /var/cache/fontconfig
then
    opts[o++]=--ro-bind
    opts[o++]="/var/cache/fontconfig"
    opts[o++]="/var/cache/fontconfig"
fi
if test -s "$HOME/.fonts.conf"
then
    opts[o++]=--ro-bind
    opts[o++]="${HOME+"$HOME"}/.fonts.conf"
    opts[o++]="$home/.fonts.conf"
fi
for dir in "$HOME/.fontconfig" "$HOME/.config/fontconfig" "$HOME/.cache/fontconfig"
do
    test -d "$dir" || continue
    opts[o++]=--ro-bind
    opts[o++]="$dir"
    opts[o++]="${home}${dir#$HOME}"
done
# Display
if test -n "$DISPLAY"
then
    : ${XAUTHORITY:="$HOME/.Xauthority"}
    for dir in /usr/lib/ghostscript /usr/lib64/ghostscript
    do
	test -d "$dir" || continue
	for x11 in $dir/*/X11.so
	do
	    test -e "$x11" || continue
	    for lib in $(ldd "$x11" | sed -rn 's|.*=>[[:blank:]]+||;s|[[:blank:]]*(/[^[:blank:]]+)[[:blank:]]+.*|\1|p')
	    do
		case "${opts[@]}" in
		*[:blank:]${lib}[:blank:]*) continue ;;
		esac
		opts[o++]=--ro-bind
		opts[o++]="$lib"
		opts[o++]="$lib"
	    done
	done
    done
#   for x11 in /tmp/.X11-unix /tmp/.XIM-unix /tmp/.ICE-unix /tmp/.font-unix /tmp/.X${DISPLAY##*:}-lock
    for x11 in /tmp/.X11-unix
    do
	test -e "${x11}" || continue
	opts[o++]=--ro-bind
	opts[o++]="${x11}"
	opts[o++]="${x11}"
    done
    opts[o++]=--ro-bind
    opts[o++]="${XAUTHORITY+"$XAUTHORITY"}"
    opts[o++]="$home/.Xauthority"
    opts[o++]=--setenv
    opts[o++]=XAUTHORITY
    opts[o++]="$home/.Xauthority"
    opts[o++]=--setenv
    opts[o++]=DISPLAY
    opts[o++]="${DISPLAY+"$DISPLAY"}"
    if test -n "${DISPLAY%:*}"
    then
	# For display over e.g. local network as with slogin -X skip --unshare-net
	# and allow hostname resolution via running nscd (that is nscd should be up)
 	opts[o++]=--ro-bind
 	opts[o++]="/var/run/nscd/socket"
 	opts[o++]="/var/run/nscd/socket"
	opts[o++]=--unshare-user-try
	opts[o++]=--unshare-ipc
	opts[o++]=--unshare-pid
	opts[o++]=--unshare-uts
	opts[o++]=--unshare-cgroup-try
    else
	opts[o++]=--unshare-all
    fi
    if test -n "${GHOSTVIEW}"
    then
	opts[o++]=--setenv
	opts[o++]=GHOSTVIEW
	opts[o++]="{GHOSTVIEW+"$GHOSTVIEW"}"
    fi
    if test -n "${GHOSTVIEW_COLORS}"
    then
	opts[o++]=--setenv
	opts[o++]=GHOSTVIEW_COLORS
	opts[o++]="${GHOSTVIEW+"$GHOSTVIEW_COLORS"}"
    fi
else
    opts[o++]=--unshare-all
fi
if test -e /proc/$$/uid_map
then
    opts[o++]=--uid
    opts[o++]="$uid"
fi
if test -e /proc/$$/gid_map
then
    opts[o++]=--gid
    opts[o++]="$gid"
fi
# This is for debugging only
# add you binary like /bin/ls or /usr/bin/strace for further usage
# as replacement or prefix of ghostscript in the last line.
# Clearly the `false´ should then changed to `true´
if false
then
    for bin in /usr/bin/strace
    do
	opts[o++]=--ro-bind
	opts[o++]="$bin"
	opts[o++]="$bin"
	for lib in $(ldd "$bin" | sed -rn 's|.*=>[[:blank:]]+||;s|[[:blank:]]*(/[^[:blank:]]+)[[:blank:]]+.*|\1|p')
	do
	    case "${opts[@]}" in
	    *[:blank:]${lib}[:blank:]*) continue ;;
	    esac
	    opts[o++]=--ro-bind
	    opts[o++]="$lib"
	    opts[o++]="$lib"
	done
    done
fi
unset o c argc arg
set -- "${argv[@]}"
set -euo pipefail
(exec -c -a gs /usr/bin/bwrap \
      --dev /dev \
      --proc /proc \
      --tmpfs /run \
      --tmpfs /tmp \
      --ro-bind /bin/false /bin/false \
      --ro-bind $ghostscript /usr/bin/gs \
      --ro-bind /usr/share/ghostscript /usr/share/ghostscript \
      --ro-bind /usr/share/fonts /usr/share/fonts \
      --ro-bind /etc/fonts /etc/fonts \
      --ro-bind "$lock" /tmp/.lock \
      --lock-file /tmp/.lock \
      --dir "/run/user/$uid" \
      --dir /var \
      --symlink ../run var/run \
      --symlink ../tmp var/tmp \
      --dir "$home" \
      --chdir "$home" \
      "${opts[@]}" \
      --new-session \
      --sync-fd 0 \
      --sync-fd 1 \
      --sync-fd 2 \
      --setenv XDG_RUNTIME_DIR "/run/user/$uid" \
      --setenv USER "$user" \
      --setenv LOGNAME "$user" \
      --setenv SHELL /bin/false \
      --setenv HOME "$home" \
      --setenv PATH /bin:/usr/bin \
      --setenv MAIL /dev/null \
      --die-with-parent \
      /usr/bin/gs ${1+"$@"})
rm -f "$lock"
openSUSE Build Service is sponsored by