Mini Shell
#!/usr/bin/sh
# -*- mode: shell-script; sh-shell: "/bin/sh" -*-
# Copyright (C) 2018, 2021 g10 Code GmbH
#
# This file is free software; as a special exception the author gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
#
# This file is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# SPDX-License-Identifier: FSFULLR
#### start of functions for this script
#
# Bourne shell functions for config file in pkg-config style, so that
# we can share such a config file between pkg-config and script
#
#
# get_var: Get the variable value of NAME
#
# Variables are recorded in the shell variables named "VAR_<NAME>"
#
get_var () {
___name=$1
eval echo \$VAR_$___name
}
#
# get_attr: Get the attribute value of KEY
#
# Attributes are recorded in the shell variables named "ATTR_<KEY>"
#
get_attr () {
___name=$1
eval echo \$ATTR_$___name
}
# variant of get_attr for list (separated by ',')
get_attr_l () {
(IFS=', '; echo "$(get_attr $1)")
}
# Remove ${varname} part in the beginning of a string.
remove_var_expr () {
___varname=$1
shift
expr "$*" : "\${$___varname}\\(.*\\)"
}
# Given a string, substitute variables.
substitute_vars () {
__string="$1"
__varname=""
__result=""
while [ -n "$__string" ]; do
case "$__string" in
\$\$*)
__result="$__result\$"
__string="${__string#\$\$}"
;;
\${*}*)
__varname="${__string#\$\{}"
__varname="${__varname%%\}*}"
__result="$__result$(get_var $__varname)"
__string=$(remove_var_expr $__varname $__string)
;;
*)
__result="$__result$(printf %c "$__string")"
__string="${__string#$(printf %c "$__string")}"
;;
esac
done
echo "$__result"
}
#
# Read a config from stdin
#
# Variables:
# For VAR=VALUE, value is stored in the shell variable VAR_*.
#
# Attributes:
# For KEY: VALUE, value is stored in the shell variable ATTR_*.
#
read_config_from_stdin () {
_filename=$1
_line=""
_varname=""
_value=""
_key=""
_reading_attrs=""
while read _line; do
if [ -z "$_line" ]; then
_reading_attrs=yes
continue
elif [ -z "$_reading_attrs" ]; then
case "$_line" in
*=*)
_varname="${_line%%=*}"
_value="${_line#*=}"
VAR_list="$VAR_list${VAR_list:+ }VAR_$_varname"
read VAR_$_varname <<EOF1
$(substitute_vars "$_value")
EOF1
continue
;;
*) _reading_attrs=yes ;;
esac
fi
if [ -n "$_reading_attrs" ]; then
case "$_line" in
*:\ *)
_key="${_line%%:\ *}"
_value="${_line#*:\ }"
if expr "$_key" : ".*\..*" >/dev/null; then
_key="${_key%.*}_${_key#*.}"
fi
ATTR_list="$ATTR_list${ATTR_list:+ }ATTR_$_key"
read ATTR_$_key <<EOF2
$(substitute_vars "$_value")
EOF2
;;
*:|*:\ ) ;;
*)
echo "Error reading $_filename: $_line" 1>&2
exit 1
;;
esac
fi
done
}
find_file_in_path () {
_f=$1
_p=$2
_saved_IFS="$IFS"
_arg=""
IFS=":" # On Windows it should be ";"???
for _arg in $_p; do
if [ -r $_arg/$_f ]; then
RESULT="$_arg/$_f"
IFS="$_saved_IFS"
return 0
fi
done
IFS="$_saved_IFS"
RESULT=""
return 1
}
read_config_file () {
if ! find_file_in_path $1.pc $2; then
if [ -z "$want_exists" ]; then
echo "Can't find $1.pc" 1>&2
fi
exit 1
fi
read_config_from_stdin $RESULT < $RESULT
}
cleanup_vars_attrs () {
eval unset $VAR_list VAR_list
eval unset $ATTR_list ATTR_list
}
not_listed_yet () {
___m=$1
___arg=""
shift
for ___arg; do
if [ $___m = $___arg ]; then
return 1
fi
done
return 0
}
list_only_once () {
__result=""
__arg=""
for __arg; do
if not_listed_yet $__arg $__result; then
__result="$__result${__result:+ }$__arg"
fi
done
echo $__result
}
list_only_once_for_libs () {
__result=""
__rev_list=""
__arg=""
# Scan the list and eliminate duplicates for non-"-lxxx"
# the resulted list is in reverse order
for __arg; do
case "$__arg" in
-l*)
# As-is
__rev_list="$__arg${__rev_list:+ }$__rev_list"
;;
*)
if not_listed_yet $__arg $__rev_list; then
__rev_list="$__arg${__rev_list:+ }$__rev_list"
fi
;;
esac
done
# Scan again
for __arg in $__rev_list; do
case "$__arg" in
-l*)
if not_listed_yet $__arg $__result; then
__result="$__arg${__result:+ }$__result"
fi
;;
*)
# As-is
__result="$__arg${__result:+ }$__result"
;;
esac
done
echo $__result
}
arg1_is_same () {
[ "$1" = "=" -o "$1" = ">=" -o "$1" = "<=" ]
}
arg1_is_less () {
[ "$1" = "!=" -o "$1" = "<" -o "$1" = "<=" ]
}
arg1_is_great () {
[ "$1" = "!=" -o "$1" = ">" -o "$1" = ">=" ]
}
#
# Evaluate comparison between versions in RPM way
#
eval_compare_version () {
___str1="$1"
___cmp="$2"
___str2="$3"
___char1=""
___char2=""
___chunk1=""
___chunk2=""
while [ -n "$___str1" -a -n "$___str2" ]; do
# Trim anything that's not alnum or tilde from the front
___str1="$(expr "$___str1" : '[^0-9A-Za-z~]*\(.*\)')"
___str2="$(expr "$___str2" : '[^0-9A-Za-z~]*\(.*\)')"
# Get the first character
___char1=${___str1%${___str1#?}}
___char2=${___str2%${___str2#?}}
if [ "$___char1" = ~ -o "$___char2" = ~ ]; then
if [ "$___char1" != ~ ]; then
arg1_is_great $___cmp
return
fi
if [ "$___char2" != ~ ]; then
arg1_is_less $___cmp
return
fi
___str1=${___str1#~}
___str2=${___str2#~}
continue
fi
if [ -z "$___char1" -o -z "$___char2" ]; then
break
fi
case "$___char1$___char2" in
[0-9][A-Za-z])
arg1_is_great $___cmp
return
;;
[A-Za-z][0-9])
arg1_is_less $___cmp
return
;;
[0-9][0-9])
___chunk1="$(expr "$___str1" : '\([0-9]*\)')"
___chunk2="$(expr "$___str2" : '\([0-9]*\)')"
;;
[A-Za-z][A-Za-z])
___chunk1="$(expr "$___str1" : '\([A-Za-z]*\)')"
___chunk2="$(expr "$___str2" : '\([A-Za-z]*\)')"
;;
esac
# Compare chunks numerically if digits, or lexicographically
if expr "$___chunk1" "!=" "$___chunk2" >/dev/null; then
if expr "$___chunk1" ">" "$___chunk2" >/dev/null; then
arg1_is_great $___cmp
return
else
arg1_is_less $___cmp
return
fi
fi
# Remove the chunk
___str1="${___str1#$___chunk1}"
___str2="${___str2#$___chunk2}"
done
# Either STR1, STR2 or both is empty here
if [ -n "$___str1" ]; then
case "$___str1" in
~*) arg1_is_less $___cmp ;;
*) arg1_is_great $___cmp ;;
esac
elif [ -n "$___str2" ]; then
case "$___str2" in
~*) arg1_is_great $___cmp ;;
*) arg1_is_less $___cmp ;;
esac
else
arg1_is_same $___cmp
fi
}
#
# Recursively solve package dependencies
#
# Result is in the PKG_LIST variable
#
all_required_config_files () {
all_list=""
new_list=""
p=""
pkg=""
cmp=""
list=$*
while [ -n "$list" ]; do
for p in $list; do
if [ -z "$pkg" ]; then
pkg=$p
elif [ -z "$cmp" ]; then
case "$p" in
"="|"!="|"<"|">"|"<="|">=") cmp=$p ;;
*)
read_config_file $pkg $PKG_CONFIG_PATH
all_list="$all_list${all_list:+ }$pkg"
new_list="$new_list${new_list:+ }$(get_attr_l Requires)"
if [ -n "$enable_static" ]; then
new_list="$new_list${new_list:+ }$(get_attr_l Requires_private)"
fi
cleanup_vars_attrs
pkg=$p
;;
esac
else
read_config_file $pkg $PKG_CONFIG_PATH
if ! eval_compare_version "$(get_attr Version)" $cmp $p; then
echo "Version mismatch for $pkg $cmp $p: $(get_attr Version)" 1>&2
exit 1
fi
all_list="$all_list${all_list:+ }$pkg"
new_list="$new_list${new_list:+ }$(get_attr_l Requires)"
if [ -n "$enable_static" ]; then
new_list="$new_list${new_list:+ }$(get_attr_l Requires_private)"
fi
cleanup_vars_attrs
pkg=""
cmp=""
fi
done
if [ -n "$cmp" ]; then
echo "No version after comparison operator ($cmp): $pkg" 1>&2
exit 1
elif [ -n "$pkg" ]; then
read_config_file $pkg $PKG_CONFIG_PATH
all_list="$all_list${all_list:+ }$pkg"
new_list="$new_list${new_list:+ }$(get_attr_l Requires)"
if [ -n "$enable_static" ]; then
new_list="$new_list${new_list:+ }$(get_attr_l Requires_private)"
fi
cleanup_vars_attrs
fi
list="$new_list"
new_list=""
done
PKG_LIST=$(list_only_once $all_list)
}
#
# Modify -I or -L by PKG_CONFIG_SYSROOT_DIR variable
#
sysroot () {
_opt="$1"
_result=""
shift
while [ $# -gt 0 ]; do
if [ $1 = $_opt ]; then
_result="$_result${_result:+ }$_opt"
shift
_result="$_result $PKG_CONFIG_SYSROOT_DIR$1"
elif expr "x$1" : "^x$_opt" >/dev/null; then
_result="$_result${_result:+ }$_opt$PKG_CONFIG_SYSROOT_DIR$(expr "x$1" : "^x$_opt\(.*\)")"
else
_result="$_result${_result:+ }$1"
fi
shift
done
echo "$_result"
}
# Show usage
usage () {
cat <<EOF
Usage: gpgrt-config [--libdir=LIBDIR] [OPTIONS] MODULES
Options:
[--exists]
[--modversion]
[--libs]
[--cflags]
[--static]
[--variable=VARNAME]
EOF
exit $1
}
#### end of functions for this script
myname=${0##*/}
if [ $myname = gpgrt-config ]; then
default_module="gpg-error"
else
default_module=${myname%-config}
fi
# First stage to process --libdir option
libdir=""
while test $# -gt 0; do
case $1 in
--libdir=*)
libdir=${1#--libdir=}
shift
;;
*)
break
;;
esac
done
if [ x"${PKG_CONFIG_LIBDIR:+set}" = xset -a -z "$PKG_CONFIG_LIBDIR" ]; then
# The variable set as empty, we use PKG_CONFIG_PATH in this case,
# ignoring --libdir option
if [ -z "$PKG_CONFIG_PATH" ]; then
echo "Please have valid PKG_CONFIG_PATH if PKG_CONFIG_LIBDIR is empty" 1>&2
exit 1
fi
else
if [ -n "$libdir" ]; then
# --libdir option is available, it overrides existing PKG_CONFIG_LIBDIR
PKG_CONFIG_LIBDIR=$libdir/pkgconfig
fi
if [ -z "$PKG_CONFIG_LIBDIR" ]; then
if [ -z "$PKG_CONFIG_PATH" ]; then
echo "Please use --libdir=LIBDIR option or set PKG_CONFIG_LIBDIR" 1>&2
echo "Or set PKG_CONFIG_PATH" 1>&2
exit 1
fi
else
# PKG_CONFIG_LIBDIR is available here
# Modify PKG_CONFIG_PATH, prepending PKG_CONFIG_LIBDIR
PKG_CONFIG_PATH="$PKG_CONFIG_LIBDIR${PKG_CONFIG_PATH:+:}$PKG_CONFIG_PATH"
fi
fi
# PKG_CONFIG_PATH is ready here
#
if test $# -eq 0; then
usage 1 1>&2
fi
# Second stage to do the main functionality
module_list=""
want_var=""
want_attr=""
want_cflags=""
want_libs=""
want_exists=""
enable_static=""
cflags=""
libs=""
mtcflags=""
mtlibs=""
output=""
mt="no"
VAR_list=VAR_pc_sysrootdir
if [ -z "$PKG_CONFIG_SYSROOT_DIR" ]; then
VAR_pc_sysrootdir="/"
else
VAR_pc_sysrootdir="$PKG_CONFIG_SYSROOT_DIR"
fi
while test $# -gt 0; do
case $1 in
#### pkg-config incompatible options: begin
--prefix)
# In future, use --variable=prefix instead.
want_var=prefix
;;
--exec-prefix)
# In future, use --variable=exec_prefix instead.
want_var=exec_prefix
;;
--version)
# In future, use --modversion instead.
want_attr=Version
;;
--api-version)
# In future, use --variable=api_version instead.
want_var=api_version
;;
--host)
# In future, use --variable=host instead.
want_var=host
;;
--mt)
# In future, use --variable=mtcflags or --variable=mtlibs.
mt=yes
;;
#### pkg-config incompatible options: end
--modversion)
want_attr=Version
;;
--exists)
want_exists=yes
;;
--cflags)
want_cflags=yes
;;
--libs)
want_libs=yes
;;
--static)
enable_static=yes
;;
--variable=*)
want_var=${1#*=}
;;
--help)
usage 0
;;
--*)
usage 1 1>&2
;;
*)
# Modules
module_list="$module_list${module_list:+ }$1"
;;
esac
shift
done
if [ -z "$module_list" ]; then
module_list=$default_module
elif expr "$module_list" : "=\|!=\|<\|>\|<=\|>=" >/dev/null; then
module_list="$default_module $module_list"
fi
all_required_config_files $module_list
for p in $PKG_LIST; do
read_config_file $p $PKG_CONFIG_PATH
# For want_var or want_attr, get it from the first package
if [ -n "$want_var" ]; then
output="$(get_var $want_var)"
break
elif [ -n "$want_attr" ]; then
output="$(get_attr $want_attr)"
break
else
cflags="$cflags${cflags:+ }$(get_attr Cflags)"
libs="$libs${libs:+ }$(get_attr Libs)"
if [ -n "$enable_static" ]; then
libs="$libs${libs:+ }$(get_attr Libs_private)"
fi
if [ $p = "gpg-error" ]; then
mtcflags="$(get_var mtcflags)"
mtlibs="$(get_var mtlibs)"
fi
fi
cleanup_vars_attrs
done
if [ -z "$want_var" -a -z "$want_attr" ]; then
if [ -n "$want_cflags" ]; then
output="$output${output:+ }$(sysroot -I $(list_only_once $cflags))"
# Backward compatibility to old gpg-error-config
if [ $mt = yes -a -n "$mtcflags" ]; then
output="$output${output:+ }$mtcflags"
fi
fi
if [ -n "$want_libs" ]; then
output="$output${output:+ }$(sysroot -L $(list_only_once_for_libs $libs))"
# Backward compatibility to old gpg-error-config
if [ $mt = yes -a -n "$mtlibs" ]; then
output="$output${output:+ }$mtlibs"
fi
fi
fi
if [ -z "$want_exists" ]; then
echo "$output"
fi
exit 0
Zerion Mini Shell 1.0