/usr/sbin/cast
1 #!/bin/bash
2 #---------------------------------------------------------------------
3 ## @Synopsis cast is the spell installation utility. It can be called by the user or by sorcery
4 ## @Copyright Original version Copyright 2001 by Kyle Sallee
5 ## @Copyright Some parts copyright 2002 Anders Bruun Olsen et al
6 ## @Copyright Other additions/corrections Copyright 2002 by the Source Mage Team
7 ## Script to cast spells.
8 #---------------------------------------------------------------------
9
10 #-----
11 ## Help... hmm... I wonder what it does...
12 #-----
13 function help">help">help() {
14
15 cat << EOF
16
17 Cast installs single or multiple spells
18
19 Example: cast nano hdparm sudo
20 Usage: cast [parameters] [spell]
21
22 Optional Parameters:
23
24 --cflags "flags" Custom CFLAGS
25 --cxxflags "flags" Custom CXXFLAGS
26 --cppflags "flags" Custom CPPFLAGS
27 --ldflags "flags" Custom LDFLAGS
28 --no-opts Turn off setting optimization flags, except
29 for those found in --cflags, --cxxflags,
30 --cppflags and --ldflags.
31
32 -V [on|off] Override \$VOYEUR setting
33
34 -d | --download Force download of sources (overwrite existing
35 files)
36
37 -s Download all given spells before compiling
38 --deps Configure spells and determine dependencies,
39 only cast dependencies, not spells themselves
40
41 -c | --compile Recompile the spells (don't install from cache).
42 -r | --reconfigure Select new dependencies for spells (implies -c)
43
44 -g | --grimoire [...] Use only the specified grimoires for this cast
45 NOTE: If there are any cross-grimoire
46 dependencies on unspecified grimoires they
47 will not work. The target spell will
48 not be found. To avoid this, specify all
49 relevant grimoires to the -g parameter
50 in the order you wish them to be searched.
51
52 -R | --recast-down Recursively recast depended-upon spells, even
53 if they are already installed. You probably
54 also want to pass the -c flag to make sure they
55 are recompiled, not resurrected.
56
57 -B | --recast-up Recursively recast dependent spells. You
58 probably also want to pass the -c flag to make
59 sure they are recompiled, not resurrected.
60
61 -O | --recast-optional [option] If a spell being built has spells which
62 could optionally depend on it, but those
63 dependencies are disabled, ask to recast
64 the dependee. Optional parameter can be
65 option can be one of: "always", "ask-yes",
66 "ask-no", or "ignore"; it defaults to what
67 is set via the sorcery menu. Implies -c.
68
69 -Z | --lazy-updates [option] Perform updates on installed spells that
70 need updates. Optional parameter same as
71 above.
72
73 -b | --force-base-dep Force all spells to depend on basesystem
74
75 --from directory Specify an alternate for $SOURCE_CACHE
76
77 --queue Cast all spells listed in $INSTALL_QUEUE
78
79 EOF
80
81 exit 1
82
83 }
84
85 #---------------------------------------------------------------------
86 ## @Aguments Arguments of cast
87 ## @Globals DEPS_ONLY RECONFIGURE COMPILE
88 ## @Globals FORCE_DOWNLOAD SOURCE_CACHE SILENT SEPARATE
89 ## @Globals INSTALL_QUEUE
90 ##
91 #---------------------------------------------------------------------
92 function process_parameters">process_parameters">process_parameters() {
93
94 local n
95 while [ -n "$1" ]; do
96
97 if echo "" $1 | grep -q "^ -"; then
98
99 case $1 in
100
101 --cflags) export OVERRIDE_CFLAGS="$2"; COMPILE="-c"; shift 2 ;;
102 --cxxflags) export OVERRIDE_CXXFLAGS="$2"; COMPILE="-c"; shift 2 ;;
103 --cppflags) export OVERRIDE_CPPFLAGS="$2"; COMPILE="-c"; shift 2 ;;
104 --ldflags) export OVERRIDE_LDFLAGS="$2"; COMPILE="-c"; shift 2 ;;
105 --no-opts) export NO_OPTIMIZATION_FLAGS=1; COMPILE="-c"; shift 1 ;;
106 -V) export VOYEUR_OVERRIDE="$2"; shift 2 ;;
107 --deps) export DEPS_ONLY="$1"; shift 1 ;;
108 -g|--grimoire*) override_grimoires "$2"; shift 2 ;;
109 -r|--reconfigure) RECONFIGURE="$1"; COMPILE="-c"; shift 1 ;;
110 -R|--recast-down) RECAST_DOWN="$1"; shift 1 ;;
111 -B|--recast-up) RECAST_UP="$1"; shift 1 ;;
112 -O|--recast-optional) get_option "$2" "$DEFAULT_RECAST_OPTIONALS" \
113 RECAST_OPTIONALS n; COMPILE="-c";
114 shift $n ;;
115 -Z|--lazy-updates) get_option "$2" "$DEFAULT_LAZY_DEPENDS_UPDATE" \
116 LAZY_DEPENDS_UPDATES n
117 shift $n ;;
118 -b|--force-base-dep) FORCE_BASESYSTEM_DEPENDS=on; shift 1 ;;
119 -c|--compile) COMPILE="$1"; shift 1 ;;
120 -d|--download) export FORCE_DOWNLOAD="$1"; COMPILE="-c"; shift 1 ;;
121 --from) export SOURCE_CACHE=$2; shift 2 ;;
122 --silent) SILENT="$1"; shift 1 ;;
123 -s) export SEPARATE="$1"; shift 1 ;;
124 --queue) CAST_QUEUE=yes ; COMPILE=$1; shift 1 ;;
125 *) help">help">help ;;
126 esac
127
128 else
129
130 shift
131
132 fi
133
134 done
135
136 }
137
138 #---------------------------------------------------------------------
139 ## @Arguments cast's arguments
140 ## Goes through arguments and prints spells or parameters that are no
141 ## switches rather.
142 #---------------------------------------------------------------------
143 function strip_parameters">strip_parameters() {
144 local x n
145
146 while [ -n "$1" ]; do
147
148 if echo "" $1 | grep -q "^ -"; then
149
150 case $1 in
151
152 --deps) shift 1 ;;
153 --cflags) shift 2 ;;
154 --cxxflags) shift 2 ;;
155 --cppflags) shift 2 ;;
156 --ldflags) shift 2 ;;
157 --no-opts) shift 1 ;;
158 -V) shift 2 ;;
159 -g|--grimoire*) shift 2 ;;
160 -R|--recast-down) shift 1 ;;
161 -B|--recast-up) shift 1 ;;
162 -O|--recast-optional) get_option "$2" "" x n ; shift $n ;;
163 -Z|--lazy-updates) get_option "$2" "" x n ; shift $n ;;
164 -b|--force-base-dep) shift 1 ;;
165 -r|--reconfigure) shift 1 ;;
166 --from) shift 2 ;;
167 --silent) shift 1 ;;
168 -c|--compile) shift 1 ;;
169 -d|--download) shift 1 ;;
170 -s) shift 1 ;;
171 --queue) shift 1 ;;
172 *) shift 1 ;;
173
174 esac
175
176 else
177
178 echo $1
179 shift
180
181 fi
182
183 done
184
185 }
186
187 #---------------------------------------------------------------------
188 ## Look for optional parameter and use default otherwise
189 ## specify via upvar how much to shift parameters
190 #---------------------------------------------------------------------
191 function get_option() {
192 local param=$1
193 local default=$2
194 local answer=$3
195 local up_shift=$4
196 local _answer=$2
197 local _up_shift=1
198 case "$param" in
199 always|ask-yes|ask-no|ignore) _answer=$param; _up_shift=2 ;;
200 *) _answer=$default ;;
201 esac
202 upvar "$answer" "$_answer"
203 upvar "$up_shift" "$_up_shift"
204 }
205
206 #---------------------------------------------------------------------
207 ## Cast a single spell. When this function is called, all dependencies
208 ## have been taken care of and we are allowed to cast this.
209 ## @Globals SPELL
210 #---------------------------------------------------------------------
211 function cast_spell() { (
212
213 debug "cast" "Casting spell [$SPELL]"
214 set_term_title "Casting spell [$SPELL]"
215
216 run_details
217 load_build_api || return 1
218
219 dispel_conflicts $SPELL || return 1
220
221 # show_downloading tail -f's (essentially) the download log as it
222 # comes in, or if downloading is complete, cats the download log, in
223 # either case it blocks until downloading is complete by the presence of
224 # a ${download_log}.done file. If SEPARATE is set, then all downloading
225 # is done first, so there is no need to wait for it to complete.
226 if [[ ! $SEPARATE ]] ; then
227 show_downloading $SPELL
228 fi
229
230 verify_sources || return 1
231
232 # wait for solo casts, to finish and ensure that others can't
233 acquire_cast_lock
234
235 # all this needs to reorganized and stuff...later
236
237 export IW_LOG="$TMP_DIR/$SPELL.iw"
238
239 #some minor discussion occured about having this, i'll leave it out for now
240 activity_log "cast" "$SPELL" "$VERSION" "start"
241
242 # must declare OPTS before sourcing config
243 local OPTS
244 export OPTS
245 run_spell_config
246
247 libtrack_init
248
249 local spell_depends spell_sub_depends
250 get_uncommitted_depends_file $SPELL spell_depends
251 test -e $spell_depends &&
252 OPTS="$OPTS $(get_depends_options $spell_depends $SPELL)"
253
254 get_uncommitted_sub_depends_file $SPELL spell_sub_depends
255 test -e $spell_sub_depends &&
256 local PROCESSED_SUB_DEPENDS=$(cut -f3 -d: $spell_sub_depends|tr '\n' ' ')
257
258 # HACK for bug 2910 and 10546
259 local saved_lc_all=$LC_ALL
260 export LC_ALL=C
261
262 export DISTCC_DIR="$SOURCE_DIRECTORY/.distcc"
263
264 # this will run through the whole build process
265 run_build_spell">run_build_spell
266 rc=$?
267
268 # HACK for bug 2910 and 10546
269 if [[ -n ${saved_lc_all} ]] ; then
270 export LC_ALL=$saved_lc_all
271 else
272 unset LC_ALL
273 fi
274
275 # This is the home for anything and everything we do
276 # when a phase4 succeeds or fails, no more spreading things out
277 # into multiple functions.
278
279 cd /
280
281 # hooks back out to the build_api to do whatever needs to be done
282 if [ $rc == 0 ] ; then
283 run_spell_success
284 else
285 run_spell_failure $rc
286 fi
287
288
289 unlock_resources "cast" "$SPELL"
290 #It's OK to try to release a lock you don't have
291 unlock_resources "solo" "cast"
292
293 return $rc
294
295 ) }
296
297 ##Removed *_solo functions, Duff 2002/11/01
298
299 #---------------------------------------------------------------------
300 ## @Globals SPELLS
301 ## @Stdout User information ("Collating dependencies")
302 ## @Globals SPELL DEPS_ONLY
303 ##
304 ## Do dependency resolution. Takes the spells in the $SPELLS variable
305 ## and resolves them. A superset list is created called $SPELLS_TO_CAST
306 #---------------------------------------------------------------------
307 function pass_one() {
308 # This pass does configuration and dependency identification.
309 debug "cast" "Starting pass_one()"
310
311 echo -n "Computing previously installed dependencies..."
312 compute_installed_depends "dep_f_hash"
313 echo
314 compute_uninstalled_depends "to_cast" "back_hash" "bad_spells" $SPELLS
315
316 SPELLS_TO_CAST=$(hash_get_table_fields "to_cast"|tr '\n' ' ')
317
318 SPELLS="$SPELLS ${BONUS_SPELLS[*]}"
319
320 # special case of no spell making it through dependency resolution
321 # or if DEPS_ONLY is set, there arent any dependent spells to cast
322 if [ -z "$SPELLS_TO_CAST" ] ; then
323 local cannot_cast=$(hash_get_table_fields "bad_spells")
324 message "${PROBLEM_COLOR}No spells to cast!${DEFAULT_COLOR}"
325 message "${MESSAGE_COLOR}Cannot cast these spells:${DEFAULT_COLOR}"
326 message "---------------------------$PROBLEM_COLOR"
327
328 local failure_reason_log=$CAST_BACKUPDIR/failure_reason_log
329 local spell
330 for spell in $cannot_cast; do
331 grep -s "^$spell " $failure_reason_log ||
332 message "$spell"
333 done | sort -u | column
334 rm -f $failure_reason_log
335
336 message "${DEFAULT_COLOR}"
337 exit 1
338 fi
339
340 # if only doing the deps, find the dependencies and make them the
341 # SPELLS list, then recompute the full list of spells that needs to be cast
342 if [[ "$DEPS_ONLY" ]] ; then
343 local dep_spell
344 SPELLS=$(
345 for spell in $SPELLS; do
346 local dep_spells
347 hash_get_ref to_cast $spell dep_spells
348 for dep_spell in $dep_spells; do
349 spell_ok $dep_spell || echo $dep_spell
350 done
351 done|sort -u)
352 spells=( $SPELLS )
353 hash_reset deps_only
354 hash_reset looked_at
355 for ((i=0;$i<${#spells[@]}; i++)); do
356 if [[ "${spells[$i]}" ]] &&
357 ! [[ $(hash_get looked_at "${spells[$i]}") ]] ; then
358 hash_put looked_at "${spells[$i]}" done
359 if ! spell_ok ${spells[$i]}; then
360 hash_put deps_only ${spells[$i]} done
361 hash_get_ref to_cast "${spells[$i]}" new_spells
362 fi
363 spells=( ${spells[@]} $new_spells )
364 unset new_spells
365 fi
366 done
367 SPELLS_TO_CAST=$(hash_get_table_fields "deps_only"|tr '\n' ' ')
368 hash_reset deps_only
369 hash_reset looked_at
370 if [ -z "$SPELLS_TO_CAST" ] ; then
371 local parents=$(hash_get_table_fields "to_cast")
372 message "${PROBLEM_COLOR}No spells to cast!${DEFAULT_COLOR}"
373 message "${MESSAGE_COLOR}None of the spells have dependencies" \
374 "to cast:${DEFAULT_COLOR}"
375 message "---------------------------"
376 message "${PROBLEM_COLOR}${parents}" | tr '[:blank:]' '\n' | sort | column
377 message "${DEFAULT_COLOR}"
378 exit 1
379 fi
380 fi
381
382 message "${MESSAGE_COLOR}Collating dependencies...${DEFAULT_COLOR}"
383
384 # have new depends overwrite existing ones
385 for i in $SPELLS_TO_CAST; do
386 local dependencies
387 hash_get_ref to_cast $i dependencies
388 hash_put dep_f_hash $i "$dependencies"
389 done
390
391 debug "cast" "pass_one, done with SPELLS=$SPELLS"
392
393 }
394
395
396 #---------------------------------------------------------------------
397 ## @Arguments Spells to be cast
398 ## @Stdout the "Spells are to be cast" message.
399 ## @Stdin User interface, y or n
400 ## @Globals SEPARATE
401 ## Asks whether you want to cast the listed spells or not.
402 ## Returns if not.
403 ## Then it starts pass three and four by calling make.
404 ## Depending on SEPARATE it starts pass three in the background
405 ## or not.
406 #---------------------------------------------------------------------
407 function pass_two() {
408 # This pass downloads required sources.
409 # And starts the make process
410 debug "cast" "Starting pass_two()"
411
412 unset_details
413
414 message "${MESSAGE_COLOR}Spells are to be cast:${DEFAULT_COLOR}"
415 message "---------------------------"
416 message "${SPELL_COLOR}${SPELLS_TO_CAST}" | tr '[:blank:]' '\n' | column
417 message "${DEFAULT_COLOR}"
418
419 if ! query "Do you want to cast these spells?" "y" ; then
420 message "Ok, quitting cast. Figure out what you want."
421 # conflicts are already registered, but they weren't removed, so don't show them
422 :> $CONFLICT_LIST
423 return 1
424 fi
425
426 echo
427
428 rm -f $TMP_DIR/pass_three.done # don't return until this file exists
429 MINUS_K=yes
430 if [[ $SEPARATE ]] ; then
431 ( CAST_PASS="three"
432 depengine_entry_point "$SPELLS" "$SPELLS_TO_CAST"
433 if [[ $SCREEN_NAME ]] ; then
434 screen_notify "$SCREEN_NAME" "Done downloading"
435 screen_kill_window "$SCREEN_NAME" $SCREEN_SUMMON_WIN
436 fi
437 touch $TMP_DIR/pass_three.done
438 )
439 else
440 ( CAST_PASS="three"
441 trap "exit 1" INT TERM # this keep a rather nasty message
442 # from appearing if we get killed
443 depengine_entry_point "$SPELLS" "$SPELLS_TO_CAST"
444 if [[ $SCREEN_NAME ]] ; then
445 screen_notify "$SCREEN_NAME" "Done downloading"
446 screen_kill_window "$SCREEN_NAME" $SCREEN_SUMMON_WIN
447 fi
448 touch $TMP_DIR/pass_three.done &>/dev/null
449 ) &
450 fi
451
452 debug "cast" "Starting stage four make."
453
454 (
455 CAST_PASS="four"
456 depengine_entry_point "$SPELLS" "$SPELLS_TO_CAST"
457 touch $TMP_DIR/pass_four.done
458 )
459
460
461 # pass three might not finish, give it a short amount of time to complete
462 # in case its near the end of a download or something, if after a minute
463 # it doesn't finish just kill everything off.
464 # in 1.14 this may be improved, see bug 8763
465 local i
466 let i=0
467 if ! test -e $TMP_DIR/pass_three.done; then
468 message "Download pass has not completed yet, pausing momentarily"
469 fi
470 while ! test -e $TMP_DIR/pass_three.done; do
471 sleep 5
472 let i+=5
473 if [[ $i -gt 60 ]] ; then
474 message "Download pass did not finish, killing it off."
475 # this is rather violent, but job control in bash lame and theres
476 # no other way to kill everything off effectively :-(
477 ps x|grep $TMP_DIR|awk '{print $1}'|grep -v $$|xargs kill &>/dev/null
478 echo -n .; sleep 1
479 ps x|grep $TMP_DIR|awk '{print $1}'|grep -v $$|xargs kill &>/dev/null
480 echo -n .; sleep 1
481 ps x|grep $TMP_DIR|awk '{print $1}'|grep -v $$|xargs kill -9 &>/dev/null
482 echo -n .; sleep 1
483 echo
484 break
485 fi
486 done
487
488 }
489
490 #---------------------------------------------------------------------
491 ## @param spellname
492 ## @Globals SPELL
493 ## Sets SPELL to the spellname and calls summon_spell with spellname
494 ## as argument. This is equivalent to calling summon, but without the
495 ## overhead.
496 ## (Is being called by make)
497 ## If in screen mode it also execs a tail to the summon window
498 #---------------------------------------------------------------------
499 function pass_three() {
500 debug "cast" "pass_three - $*"
501 unset CAST_PASS
502 trap "exit 1" INT TERM
503 local SPELL=$1
504
505 # download_log is removed with it's .done in libcast
506 local download_log=$(get_spell_dl_log $SPELL)
507
508 if [[ $SCREEN_NAME ]] && [ ! -p $TMP_DIR/download.fifo ] ; then
509 # Create the summon window
510 mkfifo $TMP_DIR/download.fifo
511 # Neither tail not cat work properly on FIFOs so a while loop will
512 # have to be used
513 screen_new_window "$SCREEN_NAME" $SCREEN_SUMMON_WIN "Summon $SPELL" \
514 /bin/bash -c 'while : ; do
515 read LINE && echo $LINE || sleep 0.1 ;
516 done < '$TMP_DIR/download.fifo
517 sleep 0.1
518 fi
519 if [[ $SCREEN_NAME ]] ; then
520 # A summon window is already up, just change the name
521 screen_name_window "$SCREEN_NAME" $SCREEN_SUMMON_WIN "Summon $SPELL"
522 # symlink the d/l log to the fifo
523 ln -s $TMP_DIR/download.fifo $download_log
524 else
525 # normal non-screen cast, create a normal file
526 touch $download_log
527 fi
528
529 # check if this is being resurrected and if so, don't summon
530 # this will go away when resurrect support and dependency resolution merge
531 if ! [[ $COMPILE ]] ; then
532 VERSION=$(codex_set_current_spell_by_name $SPELL &> /dev/null;echo $VERSION)
533 if [[ $VERSION ]] && can_resurrect $SPELL $VERSION &> /dev/null ; then
534 # The 2>/dev/null is necessary because the dir may not exist
535 echo "pass_three thought that $SPELL was being resurrected" \
536 > $download_log 2>/dev/null
537 # touch the 'log' file just in case the spell disagreed so cast doesnt
538 # hang forever
539 touch ${download_log}.done &>/dev/null
540 return
541 fi
542 fi
543
544 if [[ $SEPARATE ]] ; then
545 summon_spell "$SPELL" &> "$download_log"
546 else
547 lock_file $download_log
548 summon_spell "$SPELL" &> "$download_log"
549 unlock_file $download_log
550 fi
551
552 # This is to notify show_downloading/cast_spell that it is done with
553 # this source
554 touch "${download_log}.done"
555 }
556
557 #---------------------------------------------------------------------
558 ## @param spellname
559 ## @Globals SPELL COMPILE
560 ## Sets SPELL to spellname.
561 ## Calls trigger "pre_cast"
562 ## If COMPILE is not set, the spell doesn't need an update and it can
563 ## be resurrected (can_resurrect SPELL) it calls resurrect with SPELL.
564 ## Otherwise it calls cast_spell.
565 ## If resurrect or cast_spell returned 0 it calls trigger "cast"
566 ## (Is being called by make)
567 #---------------------------------------------------------------------
568 function pass_four() {
569
570 debug "cast" "pass_four - $*"
571 local do_resurrect=no
572 local VERSION
573 unset CAST_PASS
574 SPELL=$1
575
576 trigger "pre_cast"
577
578 if ! [[ $COMPILE ]] ; then
579 # hacky way to get the latest version
580 VERSION=$(codex_set_current_spell_by_name $SPELL &> /dev/null;echo $VERSION)
581 if [[ ! $VERSION ]] ; then
582 message "Can't find spell version for some reason, is $SPELL a spell?"
583 else
584 can_resurrect $SPELL $VERSION &> /dev/null &&
585 ! does_spell_need_update $SPELL &> /dev/null &&
586 do_resurrect=yes
587 fi
588 fi
589
590 # this is a hacky way to tell what version we're updating from
591 # if any, we can use it to find md5 logs for installing config type
592 # files, it mostly is here for libresurrect.real_install_config_file
593 local OLD_SPELL_VERSION=$(installed_version $SPELL)
594
595 local rc
596 if [[ "$do_resurrect" == "yes" ]] ; then
597 resurrect_spell $SPELL $VERSION
598 rc=$?
599 # this is here for safety in case resurrect bails out somewhere
600 # we didnt expect it to
601 unlock_resources "libgrimoire" "install"
602 unlock_resources "cast" "$SPELL"
603 unlock_resources "solo" "cast"
604 else
605 cast_spell $*
606 rc=$?
607 fi
608
609 return $rc
610 }
611
612
613 #---------------------------------------------------------------------
614 ## @Globals SUCCESS_LIST FAILED_LIST CHECK_TRIGGERS_SUCCESS
615 ## CHECK_TRIGGERS_FAILURE
616 ## Does report generation.
617 #---------------------------------------------------------------------
618 function pass_five() {
619
620 debug "cast" "Function : pass_five"
621 local rc=0
622 local notice_log=$TMP_DIR/notice_log
623
624 if [[ -s $notice_log ]]; then
625 message "$DEFAULT_COLOR"
626 message "${MESSAGE_COLOR}Spell notices are repeated below:"
627 message "-----------------------------------------------$DEFAULT_COLOR"
628 cp $notice_log $CAST_BACKUPDIR
629 if (( $(wc -l < $notice_log) > 40 )); then
630 cat - $notice_log > $notice_log.2 <<< "Spell notices are repeated below:"
631 mv $notice_log.2 $notice_log
632 timeout_pager $notice_log
633 else
634 cat $notice_log
635 fi
636 message "These notices are backed up to $CAST_BACKUPDIR/notice_log ."
637 message "$DEFAULT_COLOR"
638 fi
639
640 # must exist or we get problems with checks here.
641 touch $SUCCESS_LIST
642 touch $FAILED_LIST
643 touch $CHECK_TRIGGERS_SUCCESS
644 touch $CHECK_TRIGGERS_FAILURE
645 touch $CONFLICT_LIST
646
647 debug "pass_five" "SUCCESS LIST is : `cat $SUCCESS_LIST 2>/dev/null`"
648 debug "pass_five" "FAILED LIST is : `cat $FAILED_LIST 2>/dev/null`"
649 debug "pass_five" "CONFLICT LIST is : `cat $CONFLICT_LIST 2>/dev/null`"
650 debug "pass_five" "CHECK_TRIGGERS_SUCCESS is : `cat $CHECK_TRIGGERS_SUCCESS 2>/dev/null`"
651 debug "pass_five" "bad_spells is : `hash_get_table_fields bad_spells`"
652 debug "pass_five" "to_cast is : `hash_get_table_fields to_cast`"
653
654 if [ -s $SUCCESS_LIST ] ; then
655
656 message "${MESSAGE_COLOR}Finished processing install requests."
657 message ""
658 message "Spells installed successfully:"
659 message "------------------------------${SPELL_COLOR}"
660
661 for item in `cat $SUCCESS_LIST 2>/dev/null`; do
662 message "$item"
663 done | sort | column
664
665 set_term_title "Casting successful."
666 message "${DEFAULT_COLOR}"
667
668 fi
669
670 if [ -s $CHECK_TRIGGERS_SUCCESS ] ; then
671 message "${DEFAULT_COLOR}"
672 message "${MESSAGE_COLOR}Spells that had a check_self trigger succeed:"
673 message "---------------------------------------------${SPELL_COLOR}"
674 for item in `cat $CHECK_TRIGGERS_SUCCESS 2>/dev/null`; do
675 message "$item"
676 done | sort | column
677 message "${DEFAULT_COLOR}"
678 fi
679
680 if [ -s $CHECK_TRIGGERS_FAILURE ] ; then
681 message "${DEFAULT_COLOR}"
682 message "${MESSAGE_COLOR}Spells that had a check_self trigger fail:"
683 message "------------------------------------------${SPELL_COLOR}"
684 for item in `cat $CHECK_TRIGGERS_FAILURE 2>/dev/null`; do
685 message "$item"
686 done | sort | column
687 message "${DEFAULT_COLOR}"
688 fi
689
690 local NOT_CAST
691 NOT_CAST=$( { hash_get_table_fields to_cast
692 hash_get_table_fields bad_spells
693 cat $SUCCESS_LIST $FAILED_LIST $CHECK_TRIGGERS_SUCCESS
694 } | sort | uniq -u ) # all not caught otherwise
695 if [[ "$NOT_CAST" ]] ;then
696 message "${DEFAULT_COLOR}" #being paranoid
697 message "${MESSAGE_COLOR}Spells that have been dropped:"
698 message "------------------------------${QUERY_COLOR}"
699 message "$NOT_CAST" | sort | column
700 message "${DEFAULT_COLOR}"
701 fi
702
703 if [ -s $CONFLICT_LIST ] ; then
704 message "${DEFAULT_COLOR}"
705 message "${MESSAGE_COLOR}Spells that have been removed due to conflicts:"
706 message "-----------------------------------------------${QUERY_COLOR}"
707 for item in $(cut -d" " -f2- $CONFLICT_LIST 2>/dev/null); do
708 message "$item"
709 done | sort | column
710 message "${DEFAULT_COLOR}"
711 fi
712
713 #
714 # To check for failed spells, we only need to see what is remaining in the
715 # install queue.
716 #
717 if [ -s $FAILED_LIST ] ; then
718 local failure_reason_log=$CAST_BACKUPDIR/failure_reason_log
719 message "${DEFAULT_COLOR}"
720 message "${MESSAGE_COLOR}Spells that encountered problems:"
721 message "---------------------------------${PROBLEM_COLOR}"
722
723 while read item; do
724 grep -s "^$item " $failure_reason_log ||
725 message "$item"
726 done < $FAILED_LIST | sort -u | column
727 rm -f $failure_reason_log
728
729 set_term_title "Casting failed."
730 message "${DEFAULT_COLOR}"
731 rc=1
732
733 fi
734
735 if [[ "$CAST_QUEUE" == "yes" ]] ; then
736 if [ -s $INSTALL_QUEUE ] ; then
737 message "${MESSAGE_COLOR}The install queue is not empty, "
738 message "it still contains the following spells: "
739 message "---------------------------------------${PROBLEM_COLOR}"
740 for item in `cat $INSTALL_QUEUE 2>/dev/null`; do
741 message "$item"
742 done | sort | column
743 message "${DEFAULT_COLOR}"
744 rc=1
745 fi
746 fi
747
748 # check if confmeld should be run
749 local spell deferred_list
750 while read spell; do
751 # ignore the date - previously deferred files should be merged too
752 if [[ -d $CONFIG_STAGE_DIRECTORY/$spell ]]; then
753 deferred_list="$spell $deferred_list"
754 fi
755 done < $SUCCESS_LIST
756 if [[ $deferred_list ]]; then
757 message "${MESSAGE_COLOR}Cast deferred installing some configuration files."
758 message "The following spells have new pending updates: "
759 message "----------------------------------------------$SPELL_COLOR"
760 message "$deferred_list" | sort | column
761 message "${MESSAGE_COLOR}Please run confmeld to merge them into your system."
762 message "$DEFAULT_COLOR"
763 fi
764
765 debug "cast" "End of pass_five"
766 return $rc
767 }
768
769 #---------------------------------------------------------------------
770 ## @Arguments Spells to cast
771 ## @Globals CAST_PASS
772 ##
773 ## Starts the passes and sets CAST_PASS accordingly.
774 #---------------------------------------------------------------------
775 function pass_zero() {
776
777 debug "cast" "Starting pass_zero()"
778 debug "pass_zero" "Starting passes 1,2,3,4 with : '$*'"
779 debug "pass_zero" " and with spells : '$SPELLS'"
780 export CAST_PASS="one"; pass_one $* &&
781 export CAST_PASS="two"; pass_two $SPELLS
782 #pass_three and _four are run via pass_two
783 debug "pass_zero" "Starting pass 5 with: '$@'"
784 export CAST_PASS="five"; pass_five "$@"
785
786
787 }
788
789 #---------------------------------------------------------------------
790 ## @STDOUT User information ("Cleaning up as well as I can...")
791 ## That function is being called when the process receives
792 ## SIGINT. It then calls cleanup.
793 #---------------------------------------------------------------------
794 function int_trap()
795 {
796 message "${PROBLEM_COLOR}SIGINT${DEFAULT_COLOR}"
797 message "Cleaning up as well as I can..."
798 cast_cleanup
799 if [[ $SCREEN_NAME ]] ; then
800 message -n "Press a key to exit screen."
801 read -n 1
802 screen_quit "$SCREEN_NAME"
803 fi
804 exit 1
805 }
806
807 #---------------------------------------------------------------------
808 ## Used for cleaning up. Deleting some files and $TMP_DIR.
809 #---------------------------------------------------------------------
810 function cast_cleanup() {
811 $STD_DEBUG
812 cleanup_tmp_dir $TMP_DIR
813 rmdir $CAST_BACKUPDIR 2>/dev/null
814 clean_resources
815 }
816
817 #---------------------------------------------------------------------
818 ## @Arguments arguments of cast
819 ## @Globals CAST_PASS
820 ## @return 0 always
821 ## Starts prameter processing and casts the given spells.
822 ## The list of given spells is being searched for invalid spells
823 ## which are then being reported. Then the passes are being started
824 ## according to CAST_PASS
825 #---------------------------------------------------------------------
826 function main">main">main">main">main() {
827 debug "cast" "main">main">main">main">main() - $*"
828 local T_SPELLS
829 process_parameters">process_parameters">process_parameters "$@"
830
831 if [[ "$CAST_QUEUE" == yes ]] ; then
832
833 touch "$INSTALL_QUEUE"
834 local tfile
835 lock_start_transaction "$INSTALL_QUEUE" tfile
836 grep -Ev '^$' $INSTALL_QUEUE > $tfile
837 lock_commit_transaction "$INSTALL_QUEUE"
838 if [ -s $INSTALL_QUEUE ]; then
839 message -n "${MESSAGE_COLOR}Casting install queue..."
840 message "${DEFAULT_COLOR}"
841
842 # remove possible empty lines from queue.
843 if query "Would you like to review the queue history for each spell?" n ; then
844 sorcery review-queue
845 fi
846
847 SPELLS=$(<$INSTALL_QUEUE)
848 else
849 message "${MESSAGE_COLOR}Install queue is empty${DEFAULT_COLOR}"
850 exit
851 fi
852 else
853 SPELLS=`strip_parameters">strip_parameters "$@"`
854 fi
855
856 if [[ $OVERRIDE_GRIMOIRES ]] ; then
857 codex_set_grimoires $OVERRIDE_GRIMOIRES
858 fi
859
860 for spell in $SPELLS ; do
861 codex_does_spell_exist $spell
862 if [ $? -eq 0 ] ; then
863 T_SPELLS="$T_SPELLS $spell"
864 fi
865 done
866 SPELLS=$T_SPELLS
867
868 if ! [[ $SPELLS ]]; then
869 return 1
870 fi
871
872 case $CAST_PASS in
873 one) pass_one $SPELLS ;; #Never matches
874 two) pass_two $SPELLS ;; #Never matches
875 three) pass_three $SPELLS ;; #d/l sources, Never matches
876 four) pass_four $SPELLS ;; #real casting, Never matches
877 five) pass_five $SPELLS ;; #cast report
878 *) pass_zero $SPELLS ;; #start everything
879 esac
880 local rc=$?
881
882 return $rc
883 }
884
885
886 . /etc/sorcery/config
887 [[ $VOYEUR_OVERRIDE ]] && VOYEUR="$VOYEUR_OVERRIDE"
888 if [ $# -eq 0 ]; then help">help">help | $PAGER
889
890 elif [[ $1 == -h ]] || [[ $1 == --help ]] ; then help">help">help
891 elif [ "$UID" -gt 0 ]; then
892 # validate the parameters before su-ing, since we may still drop out
893 process_parameters">process_parameters">process_parameters "$@"
894
895 echo "Enter the root password, please."
896 PARAMS=$(consolidate_params "$@")
897 exec su -c "cast $PARAMS" root
898
899 elif [ ${0:0:5} != "/tmp/" ]; then
900
901 # Make a nice dir structure to put stuff in, this exits if it fails
902 mk_tmp_dirs backup /tmp/cast
903 export CAST_BACKUPDIR=$TMP_DIR
904 mk_tmp_dirs cast
905 export CAST_TMPDIR=$TMP_DIR
906
907 export SAFE_CAST="$TMP_DIR/casting.safe"
908 export SUCCESS_LIST="$TMP_DIR/success_list"
909 export FAILED_LIST="$TMP_DIR/failed_list"
910 export CONFLICT_LIST="$TMP_DIR/conflict_list"
911 export CHECK_TRIGGERS_SUCCESS="$TMP_DIR/check_trigger_success_list"
912 export CHECK_TRIGGERS_FAILURE="$TMP_DIR/check_trigger_failure_list"
913 lock_file $SAFE_CAST
914
915 # $0 can be bashdb, but we want to copy cast
916 smgl_which cast PATH_TO_CAST
917 cp "$PATH_TO_CAST" $SAFE_CAST
918
919 chmod +x $SAFE_CAST
920 exec bash $SAFE_CAST "$@"
921
922 else
923 export TOP_LEVEL=${TOP_LEVEL:-$SHLVL}
924 if [[ $NICE != "0" ]] ; then
925 renice $NICE -p $$ >/dev/null
926 fi
927
928 # If we are in a screen, weird things happen if we make another screen.
929 # So disable screen mode if we are in a screen aready which wasn't started
930 # by smgl. We also have to make sure this is the top level cast so the SA
931 # won't see the message over and over and over
932 if [[ $TERM == screen ]] &&
933 [[ $TOP_LEVEL == $SHLVL ]] &&
934 [[ $SCREEN == on ]] &&
935 [[ ! $SCREEN_NAME ]]
936 then
937 export SCREEN_OVERRIDE=no
938 message "${MESSAGE_COLOR}Although screen mode is enabled, you already seem to be in a another"
939 message "screen session. Screen-in-screen is disabled."
940 message "Continuing with screen mode off.${DEFAULT_COLOR}"
941 fi
942
943 # Disable screen mode if the appropriate env var is set
944 if [[ $SCREEN_OVERRIDE ]] &&
945 [[ $SCREEN == on ]]
946 then
947 export SCREEN=$SCREEN_OVERRIDE
948 debug "cast" "Turning $SCREEN_OVERRIDE screen mode"
949 fi
950
951 # If screen mode is on, but we aren't in screen, start a new session
952 # Call to screen_start never exits
953 if [[ $SCREEN == on ]] &&
954 [[ $TERM != screen ]]
955 then
956 SCREEN_NAME="ScreenCast $*"
957 export SCREEN_NAME="${SCREEN_NAME:0:64}$(echo $SCREEN_NAME | md5sum)"
958 screen_start "$SCREEN_NAME" "$0" "$@"
959 echo "WTF?? We should not get here. screen_start execs!"
960 exit 1
961 fi
962
963 # If running in screen, screen mode is on, screen was started by us
964 # and finally, it hasn't been initialized yet.
965 if [[ $TERM == screen ]] &&
966 [[ $SCREEN == on ]] &&
967 [[ $SCREEN_NAME ]] &&
968 [[ ! $SCREEN_INITIALIZED ]]
969 then
970 debug "cast" "Initializing screen windows"
971 screen_name_window "$SCREEN_NAME" $SCREEN_MAIN_WIN "Main"
972
973 # Start debugging window if debugging is on and not set to /dev*
974 if [[ $DEBUG ]] &&
975 [[ ${DEBUG#/dev} == $DEBUG ]]
976 then
977 touch $DEBUG
978 screen_new_window "$SCREEN_NAME" $SCREEN_DEBUG_WIN "Debug" \
979 tail -f -n 0 -s 0.1 $DEBUG
980 #screen_unmonitor_window "$SCREEN_NAME" $SCREEN_DEBUG_WIN
981 fi
982
983 screen_switch_window "$SCREEN_NAME" $SCREEN_MAIN_WIN
984 screen_monitor_window "$SCREEN_NAME" $SCREEN_MAIN_WIN
985 screen_quick_intro
986 export SCREEN_INITIALIZED=yes
987 fi
988
989 trap int_trap INT
990 main">main">main">main">main "$@"
991 rc=$?
992 if [ $SHLVL -eq $TOP_LEVEL ] ; then
993 unlock_file $SAFE_CAST
994 cast_cleanup
995 fi
996 if [[ $SCREEN_NAME ]] && [[ $TOP_LEVEL -eq $SHLVL ]] ; then
997 screen_notify "$SCREEN_NAME" "Done casting"
998 message -n "Press enter to exit screen."
999 read
1000 screen_quit "$SCREEN_NAME"
1001 fi
1002 exit $rc
1003 fi
1004
1005 debug "cast" "exiting..."
1006
1007 #---------------------------------------------------------------------
1008 ##=back
1009 ##
1010 ##=head1 LICENSE
1011 ##
1012 ## This software is free software; you can redistribute it and/or modify
1013 ## it under the terms of the GNU General Public License as published by
1014 ## the Free Software Foundation; either version 2 of the License, or
1015 ## (at your option) any later version.
1016 ##
1017 ## This software is distributed in the hope that it will be useful,
1018 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
1019 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1020 ## GNU General Public License for more details.
1021 ##
1022 ## You should have received a copy of the GNU General Public License
1023 ## along with this software; if not, write to the Free Software
1024 ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1025 ##
1026 #---------------------------------------------------------------------