File: listingmodule

package info (click to toggle)
desktop-profiles 1.4.13
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 544 kB
  • ctags: 3
  • sloc: sh: 587; makefile: 71; perl: 55; csh: 8
file content (261 lines) | stat: -rw-r--r-- 10,515 bytes parent folder | download
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
#!/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
  OUR_USER=${2:-$USER}
  OUR_GROUPS=`groups $OUR_USER | sed "s/^\$OUR_USER : //"`
  
  # !... 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;
}