/var/lib/sorcery/modules/libinitd
1 #---------------------------------------------------------------------
2 ##
3 ## @Synopsis Functions for automatic init-script installation.
4 ##
5 ## Installation steps performed by this script:
6 ## <pre>
7 ## pre install:
8 ## <li>Determine if the script is a facility provider, if it is then
9 ## ask the user whether it should be the default provider.
10 ##
11 ## install:
12 ## <ul>
13 ## <li>Determine which runlevel the script should be placed in.
14 ## <li>Make a backup if there already is a different version of the script in
15 ## the target location.
16 ## <li>Install the script with permissions 754.
17 ## <li>Determine if the script sources any config file from /etc/sysconfig.
18 ## <li>For each config file:
19 ## <ul>
20 ## <li>Install the config file if there is no existing copy installed.
21 ## </li>Otherwise merge new options into existing copy.
22 ## </ul></ul>
23 ##
24 ## post install:
25 ##
26 ## <li> When the spell has been installed successfully then change the
27 ## /etc/sysconfig/facilities-file if the user wanted the script to be a
28 ## default provider.
29 ## </pre>
30 ## @Copyright Copyright (C) 2003 The Source Mage Team <http://www.sourcemage.org>
31 ##
32 ##
33 ## @Contributors Robert Helgesson <rycee@home.se>
34 ##
35 #---------------------------------------------------------------------
36
37
38 #---------------------------------------------------------------------
39 ## @param new file
40 ## @param old file
41 ## Makes a backup of "old file" if it differs from "new file"
42 ##
43 #---------------------------------------------------------------------
44 function _init_make_backup()
45 {
46
47 # Don't bother if the old file doesn't exist
48 [ -f $2 ] || return
49
50 # Do the files differ? Return if they don't.
51 cmp -s $2 $1 && return
52
53 local savetime=$( date +'%Y%m%d%H%M' )
54 bck_file=$2.$savetime.backup
55
56 message "Making a backup of $2 due to differing content..."
57 mv $2 $bck_file
58 chmod 644 $bck_file
59
60 }
61
62
63 #---------------------------------------------------------------------
64 ## @param init script
65 ## @Stdout filelist
66 ## Extracts the files in /etc/sysconfig which are sourced by the script and
67 ## prints them to stdout separated by newlines.
68 ##
69 #---------------------------------------------------------------------
70 function _init_get_conf_files()
71 {
72
73 sed -n -f - $1 <<EOF
74 s!^\.\s\s*/etc/sysconfig/\([^[:space:]]*\).*!\1!p
75 s!^source\s\s*/etc/sysconfig/\([^[:space:]]*\).*!\1!p
76 EOF
77
78 }
79
80
81 #---------------------------------------------------------------------
82 ## @param new config file
83 ## @param old config file
84 ## Inserts new options from the new file into the old, existing, file
85 ##
86 #---------------------------------------------------------------------
87 function _init_merge_config_file()
88 {
89
90 # Get newly added options
91 local new_opts=$( sed -n -e 's/[[:space:]]*\([[:alnum:]_]*\)=.*/\1/p' $1 $2 |
92 sort | uniq -u )
93
94 # for now the file is always modified...
95 if [ -z "$new_opts" ] ; then
96 message " No new options to merge into $2..."
97 track_manual $2 # but we still need to track it.
98 return 0
99 fi
100
101 # no need for a backup when staging, since the installation will be deffered
102 if [[ $STAGED_INSTALL != on ]]; then
103 local savetime=$( date +'%Y%m%d%H%M' )
104 install -g root -o root $2 $2.$savetime.backup
105 fi
106
107 for opt in $new_opts ; do
108 message " Merging option $opt into $2..."
109 sed -n -f - $1 <<EOF >> $2
110 # If we encounter an empty line then clear hold space since another
111 # variable is coming up...
112 /^$/ { x ; d ; h ; }
113
114 # The variable we're looking for has come, add it to the hold space and
115 # then print everything, quit when done...
116 /^[[:space:]]*$opt=/ { H ; x ; p; q; }
117
118 # Default action, append line to hold space
119 H
120 EOF
121 done
122
123 }
124
125
126 #---------------------------------------------------------------------
127 ## @param configuration file...
128 ##
129 ## Installs or merges a list of init-script configuration-files.
130 ##
131 #---------------------------------------------------------------------
132 function _init_install_conf_files()
133 {
134
135 mkdir -p $INSTALL_ROOT/etc/sysconfig
136 for file in "$@" ; do
137 local target_file=${INSTALL_ROOT}/etc/sysconfig/$file
138 local file=$SCRIPT_DIRECTORY/init.d/$file.conf
139
140 if [ ! -f "$file" ] ; then
141 [ ! -f "$target_file" ] &&
142 message "${PROBLEM_COLOR}Unable to find file $file...${DEFAULT_COLOR}"
143 continue
144 fi
145
146 if [ -f "$target_file" ] ; then
147 check_if_modified "$target_file" &&
148 if [[ $STAGED_INSTALL == on ]]; then
149 mark_file_modified "$STAGE_DIRECTORY/TRANSL$target_file"
150 else
151 mark_file_modified "$target_file"
152 fi
153 _init_merge_config_file $file $target_file
154 else
155 install -m 644 -g root -o root $file $target_file
156 touch $target_file
157 fi
158 done
159
160 }
161
162
163 #---------------------------------------------------------------------
164 ## @param init script
165 ## @param previous cast instance's answers, if any
166 ## @param init script
167 ## Prepares installation of an init-script.
168 ## Creates the variable $INITPROVIDES which contains facility provided by the
169 ## script (if any)
170 ##
171 #---------------------------------------------------------------------
172 function init_prepare_install()
173 {
174
175 local service="$1"
176 local old_provides="$2"
177 local result_list="$3"
178 local script_path="$SCRIPT_DIRECTORY/init.d/$service"
179 local script_provides=$( grep '^[[:space:]]*PROVIDES' $script_path )
180 script_provides=$( eval "( ${script_provides:=:} ; echo \$PROVIDES ; )" )
181
182 [ -z "$script_provides" ] && return
183
184 local default=n
185 if test -f $INSTALL_ROOT/etc/sysconfig/facilities &&
186 grep -q "$script_provides=$service" \
187 $INSTALL_ROOT/etc/sysconfig/facilities ||
188 list_find "$service:$script_provides" $old_provides; then
189 default=y
190 fi
191 local question="Set $service to be the default provider of $script_provides?"
192 if query "$question" $default; then
193 list_add "$result_list" "$service:$script_provides"
194 fi
195 }
196
197
198 #---------------------------------------------------------------------
199 ## @param init script
200 ## * Makes a backup of an existing script.
201 ## * Installs the new script into the correct runlevel.
202 ## * Installs any config file used by the script.
203 ##
204 #---------------------------------------------------------------------
205 function init_install()
206 {
207
208 local enable_script="$1"
209 local script_name="$2"
210 local script_path="$SCRIPT_DIRECTORY/init.d/$script_name"
211 local script_runlevel=$( grep '^[[:space:]]*RUNLEVEL' $script_path )
212 script_runlevel=$( eval "( $script_runlevel ; echo \$RUNLEVEL )" )
213
214 [ "$script_runlevel" = "s" ] && script_runlevel="S"
215
216 if [ -z "$script_runlevel" ] ; then
217 message "Init script $script_name doesn't contain good RUNLEVEL variable..."
218 return
219 fi
220
221 message "Installing $script_name to runlevel $script_runlevel..."
222
223 (
224 . ${INSTALL_ROOT}/etc/sysconfig/init
225
226 # /etc/sysconfig/init might not exist yet so we define this in case
227 RUNLEVELS_DIR=${INSTALL_ROOT}${RUNLEVELS_DIR:-/etc/init.d/runlevels}
228
229 local runlevel_dir="$RUNLEVELS_DIR/%$script_runlevel"
230
231 if [ ! -d "$runlevel_dir" ] ; then
232 message -n "${PROBLEM_COLOR}"
233 message -n "Unable to install $script_name to runlevel $script_runlevel. "
234 message "Runlevel do not exist or is not implemented as a directory."
235 message -n ${DEFAULT_COLOR}
236 exit 1
237 else
238 _init_make_backup $script_path $runlevel_dir/$script_name
239 if [ "$enable_script" == "enabled" ] ; then
240 install -m 754 -g root -o root $script_path $runlevel_dir
241 message " script $script_name installed and ${MESSAGE_COLOR}enabled${DEFAULT_COLOR}. Disable with 'telinit disable $script_name'."
242 message "${MESSAGE_COLOR}If you want to [re]start the service now${DEFAULT_COLOR}, issue 'telinit run $script_name [re]start'."
243 else
244 install -m 644 -g root -o root $script_path $runlevel_dir
245 message " script $script_name installed and ${MESSAGE_COLOR}disabled${DEFAULT_COLOR}. Enable with 'telinit enable $script_name'."
246 fi
247 _init_install_conf_files $( _init_get_conf_files $script_path )
248 fi
249 )
250
251 }
252
253
254 #---------------------------------------------------------------------
255 ##
256 ## Does cleanup if necessary. Must be run _after_ installwatch has stopped.
257 ##
258 #---------------------------------------------------------------------
259 function init_post_install()
260 {
261 (
262 IFS="$WHITESPACE_IFS"
263 for sp in $INIT_PROVIDES ; do
264 mkdir -p $INSTALL_ROOT/etc/sysconfig
265 mark_file_modified "$INSTALL_ROOT/etc/sysconfig/facilities"
266 IFS=":"
267 set $sp # $1 - script name, $2 - facility
268 if ! sedit "s/^\([[:space:]]*$2\)=.*/\1=$1/" \
269 $INSTALL_ROOT/etc/sysconfig/facilities ; then
270 message -n "${PROBLEM_COLOR}Unable to modify facilities file to make "
271 message "$1 provider of $2.${DEFAULT_COLOR}"
272 else
273 message "Made $1 provider of $2"
274 fi
275 done
276 )
277 }
278
279 #---------------------------------------------------------------------
280 ##
281 ## This software is free software; you can redistribute it and/or modify
282 ## it under the terms of the GNU General Public License as published by
283 ## the Free Software Foundation; either version 2 of the License, or
284 ## (at your option) any later version.
285 ##
286 ## This software is distributed in the hope that it will be useful,
287 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
288 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
289 ## GNU General Public License for more details.
290 ##
291 ## You should have received a copy of the GNU General Public License
292 ## along with this software; if not, write to the Free Software
293 ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
294 ##
295 #---------------------------------------------------------------------