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 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
|
#!/bin/sh
#
# This is a shell library containing utility functions the scripts in the
# desktop-profiles package. This library currently contains the following
# functions (see the comments with each function for more info):
# - test_requirement: takes a requirement and (optionally) a username,
# exit code indicates wether the requirement is met
# - test_profile_requirements: takes a profile's line (from the .listing
# file), and (optionally) a username, exit
# code indicates wether the requirements are
# met
# - for_each_requirement: first argument is a list of requirements, second
# argument is a command to be executed once for
# each requirement (with requirement as argument)
# - list_listings: returns a space separated list of all .listing files
# found in the directories contained in $LISTINGS_DIRS
# - filter_listings: returns matching profiles from the available listing
# files (output influenced by a number of environment
# variables, see below for a list)
#
# See desktop-profiles (7) for more information about using profiles through
# desktop-profiles and the format of the .listing files
#
# (c) 2004 Bart Cornelis <cobaco AT skolelinux no>
###############################################################################
###############################################################################
# test_requirement () - test wether the given requirement is fulfilled for a
# given user
#
# Note: won't work for not-current-user when command-requirments depend on
# the user's environment settings.
#
# $1 = requirement
# $2 = username (defaults to current user if absent)
#
# Each requirement is of one of the following forms:
# requirement | meaning
# --------------------------
# <group> | $USER is a member of <group>
# !<group> | $USER must not be member of group
# ! | always false (i.e. deactivate profile)
# $(command) | (shell) command exits succesfully
#
# returns succesfully ($?=0) if requirement is met
# returns 1 otherwise
###############################################################################
test_requirement(){
# if no requirement (given) -> then it's met
if (test "$1"x = x); then
exit;
fi;
# initialize needed variables. Do not give argument to groups when looking up the current
# user, to avoid expensive lookup with LDAP NSS.
if (test "$2"x = x) || (test "$USER" = "$2") ; then
OUR_USER="$USER"
OUR_GROUPS="`id -Gn`"
else
OUR_USER="$2"
OUR_GROUPS="`id -Gn -- $OUR_USER`"
fi
# !... requirement
if (echo "$1" | grep '^!' > /dev/null) ; then
GROUP=`echo "$1" | sed 's/^!//'`;
# deactivated profile
if (test "$GROUP"x = x); then
exit 1;
fi;
# user is not a member of given group
if (echo $OUR_GROUPS | grep -v $GROUP > /dev/null); then
exit;# success
fi;
# given command must exit succesfully
elif (echo "$1" | grep '^\$(.*)' > /dev/null); then
COMMAND="`echo "$1" | sed -e 's/^\$(//' -e 's/)$//'`";
sh -c "$COMMAND" > /dev/null;
exit $?;
# user is a member of given group
else
if (echo $OUR_GROUPS | grep $1 > /dev/null); then
exit;# success
fi;
fi;
# if we get here the requirement was not met
exit 1;
}
################################################################
# $1 = list of requirements
# $2 = '$2 $REQUIREMENT' will be executed for each REQUIREMENT
# $3- ... = extra arguments to pass to each $2 call
################################################################
for_each_requirement(){
PROFILE_REQUIREMENTS="$1";shift
COMMAND="$1";shift
EXTRA_ARGS="$@";
# requirements -> check one by one
while (test "$PROFILE_REQUIREMENTS"x != x); do
# attempt to get first (remaining) REQUIREMENT
C=1;
REQUIREMENT=`echo "$PROFILE_REQUIREMENTS" | cut --fields 1 --delimiter " "`;
# if command requirement
if (echo "$REQUIREMENT" | grep "^\$(" > /dev/null); then
#make sure we have the whole command (with params)
while (echo "$REQUIREMENT" | grep -v ')$' > /dev/null); do
C=`expr $C + 1`;
REQUIREMENT=`echo $PROFILE_REQUIREMENTS | cut --fields -$C --delimiter " "`;
done;
# prepare loop for next iteration
C=`expr $C + 1`;
PROFILE_REQUIREMENTS=`echo $PROFILE_REQUIREMENTS | cut --fields $C- --delimiter " " `;
else
# prepare loop for next iteration
PROFILE_REQUIREMENTS=`echo $PROFILE_REQUIREMENTS | sed -e "s/^$REQUIREMENT//" -e "s/^ *//"`;
fi;
"$COMMAND" "$REQUIREMENT" "$EXTRA_ARGS"
done;
}
###############################################################################
# test_profile_requirements() - test wether the given profile's requirements
# are met for a given user.
#
# Note: won't work for not-current-user when command-requirments depend on
# the user's environment settings.
#
# $1 = the profile line from the listing file
# $2 = username (defaults to current user if absent)
#
# returns succesfully ($?=0) if requirement is met
# returns 1 otherwise
###############################################################################
test_profile_requirements() {
PROFILE_REQUIREMENTS="$(echo $@ | cut --fields 5 --delimiter ";")";
# no requirements -> met
if (test "$PROFILE_REQUIREMENTS"x = x); then
exit;
fi;
# requirements -> check one by one
for_each_requirement "$PROFILE_REQUIREMENTS" test_requirement $2;
# all requirements are met (or we wouldn't get here)
exit;
}
################################################################################
# outputs a space separated list of all .listing files found in the directories
# contained in $LISTINGS_DIRS
################################################################################
list_listings () {
# Make sure the variable we need are initialized
LISTINGS_DIRS=${LISTINGS_DIRS:-'/etc/desktop-profiles'}
for DIR in $LISTINGS_DIRS; do
echo -n $(ls -1 $DIR/*.listing);
echo -n " ";
done;
echo;
}
###############################################################################
# filter_listings() - filters the profiles in the .listing files
# (criteria and output-format are set through a number of
# environment variables, as listed below)
#
# The following environment variables _may_ be used:
# - NAME_FILTER, LOCATION_FILTER, REQUIREMENT_FILTER,
# KIND_FILTER, and DESCRIPTION_FILTER: contain the regexp filter to be used
# on the corresponding field of the profile-line
# - PRECEDENCE_FILTER contains the second half of an expression to be passed to
# the test program (e.g. '-gt 0', '-ge 0', or '-lt 50')
# - OUR_USER: requirements need to be met for this user
# - FORMAT: don't just echo the profile-line from the .listing file, but use
# the specified format (may use the variables NAME, LOCATION, PRECEDENCE,
# REQUIREMENT, KIND, DESCRIPTION, FILE variables. First 6 refer to the
# the respective fields for that profile, FILE refers to the file the profile
# is listed in.
# NOTE: characters interpreted specially by the shell (such as ';') need
# to be escaped.
# - SORT_KEY: sort on field (NOTE: numeric)
# - SORT_ARGS: extra arguments to be given to the sort command (e.g. when
# sorting on the precedence field (3) you probably want to set this to
# '--general-numeric-sort --reverse')
# - LISTINGS_DIRS: the directory containing the .listing files to include
# (defaults to '/etc/desktop-profiles', probably shouldn't be changed ever)
#
# In absence of any set variables it will just output all available profiles
# sorted by name.
#
# The list-desktop-profile script from the desktop-profiles package offers an
# example of how to use this function.
###############################################################################
filter_listings () {
# Make sure the variable we need are initialized
SORT_KEY=${SORT_KEY:-1}
SORT_ARGS=${SORT_ARGS:-''}
NAME_FILTER=${NAME_FILTER:-''}
LOCATION_FILTER=${LOCATION_FILTER:-''}
PRECEDENCE_FILTER=${PRECEDENCE_FILTER:-''}
REQUIREMENT_FILTER=${REQUIREMENT_FILTER:-''}
KIND_FILTER=${KIND_FILTER:-''}
DESCRIPTION_FILTER=${DESCRIPTION_FILTER:-''}
OUR_USER=${OUR_USER:-''}
FORMAT=${FORMAT:-'$NAME\;$KIND\;$LOCATION\;$PRECEDENCE\;$REQUIREMENTS\;$DESCRIPTION'};
LISTINGS_LIST=$(list_listings)
# do the filtering
cat $LISTINGS_LIST | grep -v -e "^[[:space:]]*#" -e "^[[:space:]]*$" | sort $SORT_ARGS --key="$SORT_KEY" --field-separator=';' | \
while read PROFILE; do
# split fields
export NAME="`echo $PROFILE | cut --delimiter ';' --fields 1`";
export KIND="`echo $PROFILE | cut --delimiter ';' --fields 2`";
export LOCATION="`echo $PROFILE | cut --delimiter ';' --fields 3`";
export PRECEDENCE="`echo $PROFILE | cut --delimiter ';' --fields 4`";
export REQUIREMENTS="`echo $PROFILE | cut --delimiter ';' --fields 5`";
export DESCRIPTION="`echo $PROFILE | cut --delimiter ';' --fields 6`";
export FILE=`grep -l "^$NAME;" $LISTINGS_LIST`;
if (test "$PRECEDENCE"x = x); then
#unset = lower then anything, so set to insanely low value
NORM_PRECEDENCE='-999999999999999999';
else
NORM_PRECEDENCE=$PRECEDENCE;
fi;
# if filters don't match -> go to next profile
if ( (test "${NAME_FILTER:-''}" != '') && (echo "$NAME" | grep -v "$NAME_FILTER" > /dev/null) ) ||
( (test "${LOCATION_FILTER:-''}" != '') && (echo "$LOCATION" | grep -v "$LOCATION_FILTER" > /dev/null) ) ||
( (test "${PRECEDENCE_FILTER:-''}" != '') && !(test "$NORM_PRECEDENCE" $PRECEDENCE_FILTER) ) ||
( (test "${REQUIREMENT_FILTER:-''}" != '') && (echo "$REQUIREMENTS" | grep -v "$REQUIREMENT_FILTER" > /dev/null) ) ||
( (test "${KIND_FILTER:-''}" != '') && (echo "$KIND" | grep -v "$KIND_FILTER" > /dev/null) ) ||
( (test "${DESCRIPTION_FILTER:-''}" != '') && (echo "$DESCRIPTION" | grep -v "$DESCRIPTION_FILTER" > /dev/null) ); then
continue;
fi;
# if we have a username to match for, and requirements are not met
if (test "$OUR_USER" != '') &&
!(test_profile_requirements "$PROFILE" "$OUR_USER"); then
# -> go to next profile
continue;
fi;
# if we get here output the profile's information in the requested format
echo $(sh -c "echo $FORMAT");
done;
}
|