/var/lib/sorcery/modules/libcast
1 #!/bin/bash
2 #---------------------------------------------------------------------
3 ## @Synopsis Functions for dealing with the actual
4 ## @Synopsis compiling/installation of spells and walking through cast's 'pass 4' pipeline.
5 ## @Copyright Copyright (C) 2002 The Source Mage Team
6 ## @Copyright <http://www.sourcemage.org>
7 ## @Globals $SGL_LIBRARY_MODULES $GRIMOIRE $BUILD_API $USE_FUNCTIONS
8 ## A spell follows the following path during its installation:
9 ## PREPARE -> DETAILS -> PRE_BUILD -> BUILD, or COMPILE/INSTALL ->
10 ## POST_BUILD -> POST_INSTALL -> TRIGGERS
11 ## Each of these steps, along with some interim steps of dealing with
12 ## conflicts and security are handled here as well.
13 #---------------------------------------------------------------------
14
15 #---------------------------------------------------------------------
16 ## This is used to dynamically setup an api environment for a spell
17 ## into the build api that it is specified to use. (ie split BUILD or
18 ## no split BUILD).
19 #---------------------------------------------------------------------
20 function load_build_api() {
21
22 debug "libcast" "Starting load_build_api"
23
24 source $SGL_LIBRARY_MODULES/build_api/common
25 case $BUILD_API in
26 1) source $SGL_LIBRARY_MODULES/build_api/api1 ;;
27 2) source $SGL_LIBRARY_MODULES/build_api/api2 ;;
28 *) message "${PROBLEM_COLOR}Unknown build api version $BUILD_API, for" \
29 "$SPELL!!${DEFAULT_COLOR}"
30 message "Please update sorcery and see if the problem goes away."
31 message "If it doesnt this may be a bug, please contact" \
32 "the sorcery team. Thanks."
33 return 1 ;;
34 esac
35 load_functions_file
36 }
37
38 #---------------------------------------------------------------------
39 ## Load the grimoire and section level FUNCTIONS file
40 #---------------------------------------------------------------------
41 function load_functions_file() {
42 # the following allows spell writers to override certain functions
43 # in the build pipeline
44 USE_FUNCTIONS=${USE_FUNCTIONS:-on}
45 if [[ $USE_FUNCTIONS == "on" ]] ; then
46 [ -x $GRIMOIRE/FUNCTIONS ] && . $GRIMOIRE/FUNCTIONS
47 [ -x $SECTION_DIRECTORY/FUNCTIONS ] && . $SECTION_DIRECTORY/FUNCTIONS
48 elif [[ $USE_FUNCTIONS == "grimoire" ]] ; then
49 [ -x $GRIMOIRE/FUNCTIONS ] && . $GRIMOIRE/FUNCTIONS
50 elif [[ $USE_FUNCTIONS == "section" ]] ; then
51 [ -x $SECTION_DIRECTORY/FUNCTIONS ] && . $SECTION_DIRECTORY/FUNCTIONS
52 fi
53 return 0
54 }
55
56 #---------------------------------------------------------------------
57 ## Load the grimoire and section level 'libcompat' file
58 ## Spells use this for compatibility checking. It is supposed to be
59 ## lighter-weight than FUNCTIONS.
60 #---------------------------------------------------------------------
61 function load_libcompat() {
62 [ -x $GRIMOIRE/libcompat ] && . $GRIMOIRE/libcompat
63 [ -x $SECTION_DIRECTORY/libcompat ] && . $SECTION_DIRECTORY/libcompat
64 return 0
65 }
66
67 #---------------------------------------------------------------------
68 ## Loads up this environment with the special configuration values
69 ## that the spell needs. Typically the mode of communication between
70 ## CONFIGURE/DEPENDS to PRE_BUILD, BUILD, COMPILE, INSTALL, etc.
71 ## @Globals $SPELL_CONFIG $DEPENDS_CONFIG
72 #---------------------------------------------------------------------
73 function prepare_spell_config() {
74
75 SPELL_CONFIG=$DEPENDS_CONFIG/$SPELL
76 if ! [ -x $SPELL_CONFIG ]; then
77 touch $SPELL_CONFIG
78 chmod a+x $SPELL_CONFIG
79 fi
80
81 . $SPELL_CONFIG
82
83 }
84
85 #---------------------------------------------------------------------
86 ## Prompts the user about spells that are in conflict with the current
87 ## spell for later dispelling. If the user chooses not to
88 ## dispel the conflicting spell, the function returns 1
89 ## @param dis-allow conflict with anything in this list, normally used to prevent self conflicts
90 ## @param file to store output (conflicts to be removed), defaults to $CONFLICT_LIST
91 ## @return nothing if the user chose to dispel the conflicting spell
92 ## @return 1 if the user chooses not to dispel the conflicting spell
93 ## @return 1 or if there was a problem parsing the CONFLICTS file
94 #---------------------------------------------------------------------
95 function query_conflicts() {
96 debug "build_api/common" "Starting query_conflicts() on $SPELL"
97 local ignore_conflict=$1
98 local output=${2:-$CONFLICT_LIST}
99
100 # skip if the spell was already processed (avoids a double query for in-cast resurrects)
101 [[ -s $output ]] && awk -v s=$SPELL '{ if ($1 == s) {rc=1} } END {exit !rc}' $output && return 0
102
103 if [[ -x $SCRIPT_DIRECTORY/CONFLICTS ]]; then
104 local CONFLICTS=$(run_spell_file CONFLICTS conflicts) || return 1
105
106 local tmp conflicts to_dispel=""
107 for tmp in $CONFLICTS; do
108 local spell_and_default
109 explode $tmp ':' spell_and_default
110
111 # skip the spells we were told to ignore
112 list_find "$ignore_conflict" ${spell_and_default[0]} && continue
113
114 local text="${SPELL_COLOR}${SPELL}${MESSAGE_COLOR} conflicts with"
115 text="$text ${SPELL_COLOR}${spell_and_default[0]}${DEFAULT_COLOR}${QUERY_COLOR}."
116 text="$text Dispel"
117 text="$text ${SPELL_COLOR}${spell_and_default[0]}${MESSAGE_COLOR}?"
118
119 if query "$text" ${spell_and_default[1]}; then
120 list_add conflicts "${spell_and_default[0]}"
121 else
122 log_failure_reason "conflicts"
123 return 1
124 fi
125 done
126 if [[ $conflicts ]]; then
127 echo $SPELL $conflicts >> $output
128 fi
129 fi
130
131 return 0
132 }
133
134 #---------------------------------------------------------------------
135 ## Dispels the spells that are scheduled for a dispel due to conflicting
136 ## @param spell whose conflicts to dispel
137 ## @param file containing the list of conflicts
138 #---------------------------------------------------------------------
139 function dispel_conflicts() {
140 local spell=$1
141 local conflict_list=${2:-$CONFLICT_LIST}
142 local conflict
143
144 if [[ -s $conflict_list ]]; then
145 message "${MESSAGE_COLOR}Dispelling conflicts...$DEFAULT_COLOR"
146 else
147 return 0
148 fi
149
150 # no conflict is repeated, since we use list_add (idempotent) to construct it
151 for conflict in $(awk '{ if($1 == "'$1'") { $1=""; print $0;} }' "$conflict_list"); do
152 # don't break if it was already removed by another conflict
153 if spell_ok $conflict; then
154 dispel --nosustain --noqueue $conflict || return 1
155 fi
156 done
157 }
158
159 #---------------------------------------------------------------------
160 ## Prompts the user about possible security problems with the current
161 ## spell. Allows a safe way of failing a spell due to security problems.
162 ## @return 0 if there are no security problem or the user acknowledges them.
163 ## @return 1 if the user decides not to accept the security concerns
164 #---------------------------------------------------------------------
165 function run_security() {
166 debug "build_api/common" "Starting run_security() on $SPELL"
167 local rc=0
168 if [[ -f $SCRIPT_DIRECTORY/SECURITY ]]; then
169 message "${SPELL_COLOR}${SPELL}:${DEFAULT_COLOR}"
170 tee -a $SECURITY_LOG < $SCRIPT_DIRECTORY/SECURITY
171 if grep -q critical $SCRIPT_DIRECTORY/SECURITY; then
172 query "${RED}SECURITY CRITICAL: ${QUERY_COLOR}Do you still want to cast ${SPELL_COLOR}${SPELL}${DEFAULT_COLOR}${QUERY_COLOR}?" "n"
173 else
174 query "SECURITY: Do you still want to cast ${SPELL_COLOR}$SPELL${DEFAULT_COLOR}${QUERY_COLOR}?" "y"
175 fi
176 rc=$?
177 fi
178 [[ $rc != 0 ]] && log_failure_reason "security"
179 return $rc
180 }
181
182 function query_custom_cflags() {
183 if [[ $PER_SPELL_CFLAGS == on ]]; then
184 query "Would you like to set custom optimizations for this spell?" n ||
185 return 0
186
187 persistent_add USER_SPELL_CFLAGS
188 persistent_add USER_SPELL_CXXFLAGS
189 persistent_add USER_SPELL_LDFLAGS
190 persistent_add USER_SPELL_CPPFLAGS
191 local RESULTS KEY rc
192 while true ; do
193 # input box returns things of the form "RENAMED CFLAGS -O3 -march=foo ..."
194 # the ( ) interprits as an array, then using the magic power of set we
195 # get to use shift and $@ to get things done
196 RESULTS=(`eval dialog --stdout ' --extra-label Adjust --inputmenu \
197 "Custom Optimizations Menu" \
198 17 50 9 \
199 CFLAGS "$USER_SPELL_CFLAGS" \
200 CXXFLAGS "$USER_SPELL_CXXFLAGS" \
201 LDFLAGS "$USER_SPELL_LDFLAGS" \
202 CPPFLAGS "$USER_SPELL_CPPFLAGS"'`)
203 rc=$?
204 [[ $rc == 0 ]] || [[ $rc == 1 ]] && break
205 set ${RESULTS[*]}
206 KEY=$2
207 shift 2
208 case "$KEY" in
209 CFLAGS) USER_SPELL_CFLAGS="$@" ;;
210 CXXFLAGS) USER_SPELL_CXXFLAGS="$@" ;;
211 LDFLAGS) USER_SPELL_LDFLAGS="$@" ;;
212 CPPFLAGS) USER_SPELL_CPPFLAGS="$@" ;;
213 esac
214 done
215 fi
216 }
217
218 #---------------------------------------------------------------------
219 ## Asks the user about init and xinetd services
220 ##
221 ## expects $SCRIPT_DIRECTORY to be setable, any file one level deep in
222 ## $SCRIPT_DIRECTORY/xinetd.d or $SCRIPT_DIRECTORY/init.d is assumed to be
223 ## a service
224 ##
225 ## the following persistent variables may be set:
226 ## XINETD_ENABLED XINETD_DISABLED
227 ## INIT_ENABLED INIT_DISABLED
228 ## XINETD_INSTALLED XINETD_NOT_INSTALLED
229 ## INIT_INSTALLED INIT_NOT_INSTALLED
230 ##
231 ## They are all lists used by the list_add/list_find functions. The union
232 ## of FOO_ENABLED and FOO_DISABLED should be exactly equivalent to
233 ## FOO_INSTALLED. FOO_ENABLED and FOO_DISABLED have an empty intersection set.
234 #---------------------------------------------------------------------
235 function query_services() {
236 local XINETD_SCRIPTS
237 local INIT_SCRIPTS
238 local btmp xtmp itmp
239 local tmp retvar
240 local XINETD INIT BOTH found
241 local new_init_provides
242
243 test -d $SCRIPT_DIRECTORY/xinetd.d &&
244 XINETD_SCRIPTS=$(find $SCRIPT_DIRECTORY/xinetd.d -maxdepth 1 -type f \
245 -a -not -name '.*')
246
247 test -d $SCRIPT_DIRECTORY/init.d &&
248 INIT_SCRIPTS=$(find $SCRIPT_DIRECTORY/init.d -maxdepth 1 -type f \
249 -a -not -name '.*' -a -not -name '*.conf')
250
251 local new_init_inst new_init_ninst new_init_enab new_init_disab
252 local new_xinetd_inst new_xinetd_ninst new_xinetd_enab new_xinetd_disab
253
254 local xtmp_base itmp_base
255 for xtmp in $XINETD_SCRIPTS; do
256 smgl_basename $xtmp xtmp_base
257 for itmp in $INIT_SCRIPTS; do
258 smgl_basename $itmp itmp_base
259 if [[ $xtmp_base == $itmp_base ]] ; then
260 list_add BOTH $itmp_base
261 found=1
262 break
263 fi
264 done
265 done
266
267 for tmp in $INIT_SCRIPTS; do
268 smgl_basename "$tmp" tmp
269 list_find $tmp $BOTH || list_add INIT $tmp
270 # if the script is ESSENTIAL or RECOMMENDED default to yes unless
271 # the user previously said no
272 if grep -Fq 'ESSENTIAL=yes' $SCRIPT_DIRECTORY/init.d/$tmp ||
273 grep -Fq 'RECOMMENDED=yes' $SCRIPT_DIRECTORY/init.d/$tmp &&
274 ! list_find $tmp $INIT_NOT_INSTALLED; then
275 list_add INIT_INSTALLED $tmp
276 list_add INIT_ENABLED $tmp
277 list_remove INIT_DISABLED $tmp
278 fi
279 done
280
281 for tmp in $XINETD_SCRIPTS; do
282 smgl_basename "$tmp" tmp
283 list_find $tmp $BOTH || list_add XINETD $tmp
284 done
285
286 local d1 d2
287 for tmp in $BOTH ; do
288 message "${QUERY_COLOR}Would you like to install the init and/or" \
289 "xinetd script for $tmp?${DEFAULT_COLOR}"
290
291 if [[ $DEF_INIT_VS_XINETD == on ]]; then
292 d1=$DEF_INSTALL_INIT; d2=n
293 else
294 d1=n; d2=$DEF_INSTALL_XINETD
295 fi
296 dual_service_query $tmp choice "$XINETD_INSTALLED" "$XINETD_NOT_INSTALLED" \
297 "$INIT_INSTALLED" "$INIT_NOT_INSTALLED" \
298 "$d1" "$d2"
299 if [[ $choice == both ]] ; then
300 list_add new_init_inst $tmp
301 list_add new_xinetd_inst $tmp
302 message "${QUERY_COLOR}Would you like to enable $tmp through init" \
303 "and/or xinetd?${DEFAULT_COLOR}"
304
305 if [[ $DEF_INIT_VS_XINETD ]]; then
306 d1=$DEF_ENABLE_INIT; d2=n
307 else
308 d1=n;d2=$DEF_ENABLE_XINETD
309 fi
310 dual_service_query $tmp choice "$XINETD_ENABLED" "$XINETD_DISABLED" \
311 "$INIT_ENABLED" "$INIT_DISABLED" \
312 "$d1" "$d2"
313
314 case $choice in
315 both) list_add new_init_enab $tmp
316 list_add new_xinetd_enab $tmp
317 ;;
318 init) list_add new_init_enab $tmp
319 list_add new_xinetd_disab $tmp
320 ;;
321 xinetd) list_add new_init_disab $tmp
322 list_add new_xinetd_enab $tmp
323 ;;
324 neither) list_add new_init_disab $tmp
325 list_add new_xinetd_disab $tmp
326 ;;
327 esac
328 elif [[ $choice == init ]] ; then
329 list_add new_init_inst $tmp
330 list_add new_xinetd_ninst $tmp
331 if service_query $tmp "Enable init script $tmp?" "$INIT_ENABLED" \
332 "$INIT_DISABLED" "$DEF_ENABLE_INIT" \
333 new_init_enab new_init_disab; then
334 init_prepare_install "$tmp" "$INIT_PROVIDES" new_init_provides
335 fi
336 elif [[ $choice == xinetd ]] ; then
337 list_add new_init_ninst $tmp
338 list_add new_xinetd_inst $tmp
339 service_query $tmp "Enable xinetd script $tmp?" "$XINETD_ENABLED" \
340 "$XINETD_DISABLED" "$DEF_ENABLE_XINETD" \
341 new_xinetd_enab new_xinetd_disab
342 else
343 list_add new_init_ninst $tmp
344 list_add new_xinetd_ninst $tmp
345 fi
346 done
347
348 for tmp in $INIT; do
349 if grep -Fq 'ESSENTIAL=yes' $SCRIPT_DIRECTORY/init.d/$tmp ; then
350 message "Init script $tmp is \"ESSENTIAL\" for system startup," \
351 "\nit is recommended that you answer yes to the following" \
352 "\nqueries unless you know exactly what you're doing."
353 elif grep -Fq 'RECOMMENDED=yes' $SCRIPT_DIRECTORY/init.d/$tmp ; then
354 message "Init script $tmp is \"RECOMMENDED\" for system startup," \
355 "\nit is recommended that you answer yes to the following queries."
356 fi
357 if service_query $tmp "Install init script $tmp?" "$INIT_INSTALLED" \
358 "$INIT_NOT_INSTALLED" "$DEF_INSTALL_INIT" \
359 new_init_inst new_init_ninst; then
360 if service_query $tmp "Enable init script $tmp?" "$INIT_ENABLED" \
361 "$INIT_DISABLED" "$DEF_ENABLE_INIT" \
362 new_init_enab new_init_disab; then
363 init_prepare_install "$tmp" "$INIT_PROVIDES" new_init_provides
364 fi
365 fi
366 done
367 for tmp in $XINETD; do
368 if service_query $tmp "Install xinetd script $tmp?" "$XINETD_INSTALLED" \
369 "$XINETD_NOT_INSTALLED" "$DEF_INSTALL_XINETD" \
370 new_xinetd_inst new_xinetd_ninst; then
371 service_query $tmp "Enable xinetd script $tmp?" "$XINETD_ENABLED" \
372 "$XINETD_DISABLED" "$DEF_ENABLE_XINETD" \
373 new_xinetd_enab new_xinetd_disab
374 fi
375 done
376
377 # removing all of these is necessary incase some init/xinetd scripts were
378 # originally in the spell but were later removed, besides its harmless
379 persistent_remove INIT_INSTALLED
380 persistent_remove INIT_NOT_INSTALLED
381 persistent_remove INIT_ENABLED
382 persistent_remove INIT_DISABLED
383 persistent_remove XINETD_INSTALLED
384 persistent_remove XINETD_NOT_INSTALLED
385 persistent_remove XINETD_ENABLED
386 persistent_remove XINETD_DISABLED
387
388 persistent_remove INIT_PROVIDES
389
390 if [[ $INIT ]] || [[ $BOTH ]] ; then
391 service_store INIT_INSTALLED "$new_init_inst"
392 service_store INIT_NOT_INSTALLED "$new_init_ninst"
393 service_store INIT_ENABLED "$new_init_enab"
394 service_store INIT_DISABLED "$new_init_disab"
395 fi
396
397 if [[ $XINETD ]] || [[ $BOTH ]] ; then
398 service_store XINETD_INSTALLED "$new_xinetd_inst"
399 service_store XINETD_NOT_INSTALLED "$new_xinetd_ninst"
400 service_store XINETD_ENABLED "$new_xinetd_enab"
401 service_store XINETD_DISABLED "$new_xinetd_disab"
402 fi
403
404 if [[ $new_init_provides ]] ; then
405 service_store INIT_PROVIDES "$new_init_provides"
406 fi
407
408 if [[ $XINETD_INSTALLED ]] ; then
409 suggest_depends xinetd "" "" "for $XINETD_INSTALLED"
410 fi
411 }
412
413
414 #---------------------------------------------------------------------
415 ## Determines what the best default answer should be then gives the
416 ## user a menu of neither, init, xinetd, or both to choose from.
417 ## This is for the case of a service being provided by either init or xinetd
418 ##
419 ## @param service name
420 ## @param return variable to put answer in
421 ## @param list to look in for a default of yes to xinetd
422 ## @param list to look in for a default of no to xinetd
423 ## @param list to look in for a default of yes to init
424 ## @param list to look in for a default of no to init
425 ## @param default for xinetd if not found in either of the xinetd lists
426 ## @param default for init if not found in either of the init lists
427 ##
428 ## @return nothing of importance, returns through a pointer
429 ## @stdout a menu sans question, the caller needs to present the question
430 #---------------------------------------------------------------------
431 function dual_service_query() {
432 local service=$1
433 local returnvar=$2
434 local XY=$3
435 local XN=$4
436 local IY=$5
437 local IN=$6
438 local xinetd_default=$7
439 local init_default=$8
440
441 [[ $xinetd_default == off ]] && xinetd_default=n
442 [[ $xinetd_default == on ]] && xinetd_default=y
443 [[ $init_default == off ]] && init_default=n
444 [[ $init_default == on ]] && init_default=y
445
446 if list_find $service $XY ; then
447 xinetd_default=y
448 elif list_find $service $XN ; then
449 xinetd_default=n
450 fi
451
452 if list_find $service $IY ; then
453 init_default=y
454 elif list_find $service $IN ; then
455 init_default=n
456 fi
457
458 if [[ $init_default == y ]] && [[ $xinetd_default == y ]] ; then
459 default=both
460 elif [[ $xinetd_default == y ]] ; then
461 default=xinetd
462 elif [[ $init_default == y ]] ; then
463 default=init
464 else
465 default=neither
466 fi
467 select_list $returnvar $default neither init xinetd both
468 }
469
470
471 #---------------------------------------------------------------------
472 ## Determines what the best default answer should be then asks the
473 ## user given question and adds the service to one of two lists
474 ## @param service name
475 ## @param question to ask
476 ## @param list to look in for a default of yes
477 ## @param list to look in for a default of no
478 ## @param default if not found in either of the above two lists
479 ## @param store in this list if the answer is yes
480 ## @param store in this list if the answer is no
481 ## @return true if yes false if no
482 ## @stdout a query supplied by the caller
483 #---------------------------------------------------------------------
484 function service_query() {
485 local service=$1
486 local question=$2
487 local L1=$3
488 local L2=$4
489 local real_default=$5
490 local yes_list=$6
491 local no_list=$7
492
493 local default
494 if list_find $service $L1 ; then
495 default=y
496 elif list_find $service $L2 ; then
497 default=n
498 else
499 [[ $real_default == off ]] && real_default=n
500 [[ $real_default == on ]] && real_default=y
501 default=$real_default
502 fi
503
504 if query "$question" $default ; then
505 list_add $yes_list $service
506 true
507 else
508 list_add $no_list $service
509 false
510 fi
511 }
512
513 #---------------------------------------------------------------------
514 ## Internal wrapper around the task of adding a persistent variable
515 ## then storing something in it, or unsetting whatever used to be in it
516 #---------------------------------------------------------------------
517 function service_store() {
518 local VARNAME=$1
519 local list=$2
520 persistent_add $VARNAME
521 if [[ $list ]] ; then
522 eval $VARNAME=\"$list\"
523 else
524 unset $VARNAME
525 fi
526 }
527
528
529 #---------------------------------------------------------------------
530 ## Installs the scripts selected from query_services
531 #---------------------------------------------------------------------
532 function install_xinetd() {
533 if [[ $XINETD_INSTALLED ]] ; then
534 local install_dir=$INSTALL_ROOT/etc/xinetd.d
535 mkdir -p $install_dir
536 pushd "$SCRIPT_DIRECTORY/xinetd.d" >/dev/null
537
538 # install and enable
539 for FILE in $XINETD_INSTALLED; do
540 if ! test -e $FILE ; then
541 message "${PROBLEM_COLOR}Xinetd script $FILE doesnt exist," \
542 "but was selected, this may be a sorcery bug${DEFAULT_COLOR}"
543 continue
544 fi
545 if list_find $FILE $XINETD_ENABLED; then
546 message "Installing and enabling xinetd script $FILE to $install_dir"
547 install_xinetd_sub $FILE no $install_dir
548 elif list_find $FILE $XINETD_DISABLED; then
549 message "Installing and disabling xinetd script $FILE to $install_dir"
550 install_xinetd_sub $FILE yes $install_dir
551 else
552 message "${PROBLEM_COLOR}Xinetd script $FILE is in installed list" \
553 "but wasnt enabled or disabled, this may be a sorcery bug" \
554 "${DEFAULT_COLOR}"
555 fi
556 done
557 popd >/dev/null
558 fi
559 }
560
561 #---------------------------------------------------------------------
562 ## Does the dirty work involved in installing an xinetd script
563 ## this includes setting the disabled field appropriately and
564 ## not trampling on pre-existing files by default
565 #---------------------------------------------------------------------
566 function install_xinetd_sub() {
567 local file=$1
568 local bfile
569 smgl_basename "$1" bfile
570 local state=$2
571 local install_dir=$3
572 local tmp_file=$TMP_DIR/$bfile
573 local inst_file=$install_dir/$bfile
574 install -g root -o root $file $tmp_file
575
576 set_xinetd_state $tmp_file $state
577
578 # FIXME use install_config_file?
579 if test -e $inst_file &&
580 ! grep -v disable $inst_file|diff - $file &>/dev/null ; then
581 message "${QUERY_COLOR}$inst_file differs from the default $file," \
582 "what would you like to do?${DEFAULT_COLOR}"
583 select_list choice "ignore" "ignore" "overwrite" "overwrite/backup"
584 case $choice in
585 "overwrite/backup")
586 local backup=$inst_file.$(date +'%Y%m%d%H%M')
587 mv $inst_file $backup
588 # disable the backup
589 set_xinetd_state $backup yes
590 cp $tmp_file $inst_file ;;
591 overwrite) cp $tmp_file $inst_file ;;
592 esac
593 else
594 cp $tmp_file $inst_file
595 fi
596 }
597
598 #---------------------------------------------------------------------
599 ## Handles the logic of enabling or disabling of an xinetd script
600 #---------------------------------------------------------------------
601 function set_xinetd_state() {
602 local file=$1
603 local state=$2
604 if grep -q "\s*disable" $file ; then
605 sedit "s/disable\s*=.*/disable = $state/" $file
606 else
607 sedit "s/}/disable = $state\n}/" $file
608 fi
609 }
610
611
612 #---------------------------------------------------------------------
613 ## Copies any init.d files from the SCRIPT_DIRECTORY to the /etc/init.d.
614 ## Hopefully saving the old one if it exists and only setting the
615 ## executable bit if the user specified that the init.d script should be
616 ## started at bootup.
617 #---------------------------------------------------------------------
618 function install_initd() {
619 if [[ $INIT_INSTALLED ]] ; then
620 local install_dir=$INSTALL_ROOT/etc/init.d
621 mkdir -p $install_dir
622 pushd "$SCRIPT_DIRECTORY/init.d" >/dev/null
623
624 # install and enable
625 for FILE in $INIT_INSTALLED; do
626 message "${QUERY_COLOR}installing $FILE${DEFAULT_COLOR}"
627 if ! test -e $FILE ; then
628 message "${PROBLEM_COLOR}Init script $FILE doesnt exist," \
629 "but was selected, this may be a sorcery bug${DEFAULT_COLOR}"
630 continue
631 fi
632 if list_find $FILE $INIT_ENABLED; then
633 init_install enabled $FILE
634 elif list_find $FILE $INIT_DISABLED; then
635 init_install disabled $FILE
636 else
637 message "${PROBLEM_COLOR}Init script $FILE is in installed list" \
638 "but wasnt enabled or disabled, this may be a sorcery bug" \
639 "${DEFAULT_COLOR}"
640 fi
641 done
642 popd >/dev/null
643 fi
644 }
645
646
647 #---------------------------------------------------------------------
648 ## Gets the cast lock for us and ensures that we've waited for all
649 ## solo/non-solo casts to complete
650 #---------------------------------------------------------------------
651 function acquire_cast_lock() {
652 # locking - blocks normal spells if a solo cast is running,
653 # solo casts if any cast is running
654 message "${MESSAGE_COLOR}Waiting for any${DEFAULT_COLOR}${FILE_COLOR}" \
655 "Solo${DEFAULT_COLOR} ${MESSAGE_COLOR}casts to complete..." \
656 "${DEFAULT_COLOR}"
657 lock_resources "solo" "cast"
658 if test -f $SOLO && grep -q "^$SPELL$" $SOLO ||
659 [ -f $SCRIPT_DIRECTORY/SOLO ]
660 then #SOLO spell
661 message -n "${MESSAGE_COLOR}Waiting for${DEFAULT_COLOR}" \
662 "${SPELL_COLOR}all other${DEFAULT_COLOR} ${MESSAGE_COLOR}spells to" \
663 "complete...${DEFAULT_COLOR}"
664 excllock_resources "cast" "$SPELL"
665 else
666 message -n "${MESSAGE_COLOR}Waiting for any other casts of" \
667 "${DEFAULT_COLOR}${SPELL_COLOR}$SPELL${DEFAULT_COLOR}" \
668 "${MESSAGE_COLOR}to complete...${DEFAULT_COLOR}"
669 lock_resources "cast" "$SPELL"
670 unlock_resources "solo" "cast"
671 fi
672 message " done."
673 }
674
675 #---------------------------------------------------------------------
676 ## Takes the compile log and stuffs it into
677 ## our compile log directory.
678 #---------------------------------------------------------------------
679 function create_compile_log() {
680 local tmp_log=$C_LOG.2
681
682 message "${MESSAGE_COLOR}Creating compile log" \
683 "${FILE_COLOR}$COMPILE_LOGS/$SPELL-$VERSION$EXTENSION" \
684 "${DEFAULT_COLOR}"
685 if [[ "$STORE_CONF_LOG" == on ]] && test -e $SOURCE_DIRECTORY/config.log; then
686 echo "---config.log---" >> $C_LOG
687 cat $SOURCE_DIRECTORY/config.log >> $C_LOG
688 fi
689
690 # remove any nplicated lines (happens due to all the redirection we do)
691 uniq $C_LOG > $tmp_log
692 mv $tmp_log $C_LOG
693
694 # install the compile log
695 if [ -z "$EXTENSION" ]; then
696 cp $C_LOG $COMPILE_LOGS/$SPELL-$VERSION
697 else
698 $COMPRESSBIN -c $C_LOG > "$COMPILE_LOGS/$SPELL-$VERSION$EXTENSION"
699 fi
700
701 # install the castfs log
702 if [[ $STAGED_INSTALL == on ]] ; then
703 message "${MESSAGE_COLOR}Creating castfs debug log" \
704 "${FILE_COLOR}$COMPILE_LOGS/$SPELL-$VERSION.castfs.dbglog$EXTENSION" \
705 "${DEFAULT_COLOR}"
706 if [ -z "$EXTENSION" ]
707 then
708 cp $CASTFS_DBGLOG $COMPILE_LOGS/$SPELL-$VERSION.castfs.dbglog
709 else
710 $COMPRESSBIN -c $CASTFS_DBGLOG > "$COMPILE_LOGS/$SPELL-$VERSION.castfs.dbglog$EXTENSION"
711 fi
712 rm -f $CASTFS_DBGLOG
713 fi
714 }
715
716
717 #---------------------------------------------------------------------
718 ## Prompts the user to view the compile log
719 ## and deletes the temporary files too
720 #---------------------------------------------------------------------
721 function view_compile_log() {
722
723 debug "libcast" "In view_compile_log, C_LOG=$C_LOG"
724 report $C_LOG "Compile log"
725 }
726
727 #---------------------------------------------------------------------
728 ## Report that something got installed, and possibly display the report
729 ## Pawns the work off to <@function var.lib.sorcery.modules.libsorcery,report>
730 ## @Globals INST_LOG
731 #---------------------------------------------------------------------
732 function report_install() {
733
734 debug "libcast" "In report_install, INST_LOG=$INST_LOG"
735 report $INST_LOG "Install log"
736
737 }
738
739 #---------------------------------------------------------------------
740 ## @TODO This function is dumb. It should be fixed.
741 ## @param download log file name
742 #---------------------------------------------------------------------
743 function show_download_progress() {
744 [[ $SCREEN_NAME ]] && return
745 local download_log=$1
746
747 if [[ -e $download_log ]] && [[ -z $SILENT ]]; then
748 local line_count
749 line_count_old=${line_count_old:-0}
750
751 line_count=$(wc -l < $download_log)
752
753 if [[ $line_count != $line_count_old ]]; then
754 let line_count_old++
755 sed -n ${line_count_old},${line_count}p $download_log
756 line_count_old=$line_count
757 fi
758 fi
759 }
760
761 #---------------------------------------------------------------------
762 ## Shows download progress. Waits for the download to start, and shows
763 ## the progress until the download is done.
764 ## Pawn most of the display out to <@function show_download_progress>
765 ## @TODO fix the old style ad-hoc IPC
766 ## @param Spell to show the download progress for
767 #---------------------------------------------------------------------
768 function show_downloading() {
769
770 local SPELL=$1
771 local download_log=$(get_spell_dl_log $SPELL)
772 local line_count_old
773 debug "cast" "Started show_downloading() on $SPELL from $download_log"
774
775 # poke around waiting for downloading to start
776 while ! [[ -e $download_log ]]
777 do
778 sleep 1
779 done
780
781 # isn't this out of band ipc great?
782 until [ -f "${download_log}.done" ] ; do
783 show_download_progress $download_log
784 sleep 1
785 done
786
787 show_download_progress $download_log
788 debug "libcast" "Out of show_downloading"
789 }
790
791 #---------------------------------------------------------------------
792 ## Gets the filename of the download log file
793 ## @param Spell
794 ## @Stdout file name
795 #---------------------------------------------------------------------
796 function get_spell_dl_log() {
797 echo "$TMP_DIR/download.$1"
798 }
799
800 #---------------------------------------------------------------------
801 ## @License
802 ##
803 ## This software is free software; you can redistribute it and/or modify
804 ## it under the terms of the GNU General Public License as published by
805 ## the Free Software Foundation; either version 2 of the License, or
806 ## (at your option) any later version.
807 ##
808 ## This software is distributed in the hope that it will be useful,
809 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
810 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
811 ## GNU General Public License for more details.
812 ##
813 ## You should have received a copy of the GNU General Public License
814 ## along with this software; if not, write to the Free Software
815 ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
816 ##
817 #---------------------------------------------------------------------