/usr/sbin/confmeld
1 #!/bin/bash
2 #---------------------------------------------------------------------
3 ## @Synopsis merge the config files located in the config stage directory to the system.
4 ## @Copyright Other additions/corrections Copyright 2002 by the Source Mage Team
5 ## Script to install staged config files.
6 #---------------------------------------------------------------------
7
8 #-----
9 ## Help... hmm... I wonder what it does...
10 #-----
11 function help">help">help()
12 {
13 cat << EOF
14 Melds the staged config files from $CONFIG_STAGE_DIRECTORY
15
16 Examples:
17 confmeld
18 confmeld -l
19 confmeld nano
20 confmeld /etc/sysconfig/facilities
21
22 Optional Parameters:
23 -h, --help will just print this help">help">help
24 -l, --list will just list all the spells and their staged configs
25 -c, --list-configs will just list all the staged configs
26 -s, --list-spells will just list all the spells with staged configs
27 -q, --no-column don't column the output
28 -f, --force <action> always use do <action> when merging
29
30 where <action> can be one of:
31 discard-new do nothing
32 discard-old trash the old config and install over it
33 use-old leave the old config in its place and backup the new one
34 use-new backup the old config and install the new one in its place
35
36 Optional arguments:
37 You can invoke confmeld with a spell name or a staged config as an argument.
38 Confmeld will then work only on that argument.
39
40 EOF
41 exit 1
42 }
43
44 #--------------------------------------------------------------------
45 ## List all the configs in the config stage root
46 ##
47 ## @stdout a list of all configs in the config stage root
48 #--------------------------------------------------------------------
49 function all_config_files()
50 {
51 find $CONFIG_STAGE_DIRECTORY -type f
52 }
53
54 #--------------------------------------------------------------------
55 ## List all uniq config *filenames* in the config stage directory
56 ##
57 ## @stdout a list of all uniq configs in the stage directory
58 #--------------------------------------------------------------------
59 function all_uniq_config_files()
60 {
61 all_config_files |
62 sed "s#^$CONFIG_STAGE_DIRECTORY/[^/]*/[^/]*##" |
63 sort -u
64 }
65
66 #--------------------------------------------------------------------
67 ## list all spells that have staged configs
68 ##
69 ## @stdout list of spells that have staged configs
70 #--------------------------------------------------------------------
71 function all_spells_with_staged_configs()
72 {
73 all_config_files |
74 sed "s#$CONFIG_STAGE_DIRECTORY/*##g" |
75 cut -s -d/ -f1 | uniq
76 }
77
78 #-----
79 ## override column so that we can pass -q to not columnate. Adapted from gaze
80 #-----
81 function maybe_column">maybe_column() {
82 if [[ $USE_COLUMN == no ]]; then
83 cat
84 else
85 column "$@"
86 fi
87 }
88
89 #--------------------------------------------------------------------
90 ## nicely list all spells that have staged configs and exit
91 ##
92 ## @stdout list of spells that have staged configs
93 #--------------------------------------------------------------------
94 function list_spells_with_staged_configs()
95 {
96 local spells=$(all_spells_with_staged_configs)
97
98 if [[ -n $spells ]]; then
99 message "${MESSAGE_COLOR}Spells with staged configuration files:$SPELL_COLOR"
100 echo "$spells" | maybe_column">maybe_column
101 message "$DEFAULT_COLOR"
102 fi
103 exit 0
104 }
105
106 #--------------------------------------------------------------------
107 ## nicely list all staged configs and exit
108 ##
109 ## @stdout list of staged configs
110 #--------------------------------------------------------------------
111 function list_staged_configs()
112 {
113 local configs=$(all_uniq_config_files)
114
115 if [[ -n $configs ]]; then
116 message "${MESSAGE_COLOR}Staged configuration files:$FILE_COLOR"
117 echo "$configs" | maybe_column">maybe_column
118 message "$DEFAULT_COLOR"
119 fi
120 exit 0
121 }
122
123 #--------------------------------------------------------------------
124 ## nicely list all spells and their staged configs
125 ##
126 ## @stdout list of spells and their staged configs
127 #--------------------------------------------------------------------
128 function list_all()
129 {
130 local spell config
131 for spell in $(all_spells_with_staged_configs); do
132 message "${SPELL_COLOR}$spell:$FILE_COLOR"
133 all_config_files |
134 sed -n "s,^$CONFIG_STAGE_DIRECTORY/$spell/[^/]*,,p" |
135 maybe_column">maybe_column
136 message "$DEFAULT_COLOR"
137 done
138 exit 0
139 }
140
141 #--------------------------------------------------------------------
142 ## parses the path to get specific information about the config file
143 ##
144 ## @param config file path
145 ## @param upvar for spell name
146 ## @param upvar for spell success time
147 ## @param upvar for actual path to file
148 #--------------------------------------------------------------------
149 function parse_stage_config_path()
150 {
151 local file=$1
152 local __tmp __spell __sdate __path
153 __tmp=$(echo $file | sed "s#^$CONFIG_STAGE_DIRECTORY/##")
154 __spell=$(echo $__tmp | cut -d/ -f1)
155 __sdate=$(echo $__tmp | cut -d/ -f2)
156 __path=$(echo $__tmp | cut -d/ -f3-)
157 eval "$2=\"$__spell\""
158 eval "$3=\"$__sdate\""
159 eval "$4=\"$__path\""
160 }
161
162 #--------------------------------------------------------------------
163 ## Override the merging menu and always use a preset action
164 ##
165 ## @param action
166 #--------------------------------------------------------------------
167 function override_changed_config_menu()
168 {
169
170 case $1 in
171 discard-new) DEFAULT_CHANGED_CONFIG_ACTION=3 ;;
172 discard-old) DEFAULT_CHANGED_CONFIG_ACTION=0 ;;
173 use-old) DEFAULT_CHANGED_CONFIG_ACTION=2 ;;
174 use-new) DEFAULT_CHANGED_CONFIG_ACTION=1 ;;
175 *) error_message "${PROBLEM_COLOR}Bad default merge action!$DEFAULT_COLOR"
176 help">help">help ;;
177 esac
178 PROMPT_DELAY=0
179
180 }
181
182 #--------------------------------------------------------------------
183 ## Final check for removing empty spell directories, so the stage dir
184 ## is left clean
185 #--------------------------------------------------------------------
186 function final_cleanup()
187 {
188 find $CONFIG_STAGE_DIRECTORY -mindepth 1 -maxdepth 2 -type d -empty -delete
189 }
190
191 #--------------------------------------------------------------------
192 ## merge only the passed file
193 ##
194 ## @param config
195 #--------------------------------------------------------------------
196 function merge_single_file()
197 {
198 local file=$1 spell sdate target nice_date
199
200 parse_stage_config_path $file spell sdate target &&
201 if [[ -f $file && $target ]]
202 then
203 # make the $sdate human readable
204 # date -d can't use the whole original, so we have to do it in steps
205 nice_date=$(date -d ${sdate:0:8} "+%a %d %b %Y")
206 nice_date="$nice_date $(date -d ${sdate:8:4} "+%X %Z")"
207 message "${SPELL_COLOR}$spell$DEFAULT_COLOR cast on $nice_date has config"
208 message "${FILE_COLOR}$file$DEFAULT_COLOR"
209 message "to be merged with $FILE_COLOR/$target${DEFAULT_COLOR}\n"
210 tablet_set_spell $spell &&
211 install_config_file $file $INSTALL_ROOT/$target
212 recursive_config_stage_cleanup $file $spell
213 echo -e "\n"
214 fi
215 }
216
217 #--------------------------------------------------------------------
218 ## merge only the passed files or spells
219 ##
220 ## @param spell/config
221 ## @param ...
222 #--------------------------------------------------------------------
223 function confmeld_partial()
224 {
225 local thing config configs rc=0
226
227 for thing in "$@"; do
228 if codex_does_spell_exist $thing &> /dev/null; then
229 # we got a spell
230 configs=$(find $CONFIG_STAGE_DIRECTORY/$thing -type f)
231 else
232 # we got a config or three
233 configs=$(find $CONFIG_STAGE_DIRECTORY -type f -wholename "*$thing")
234 if [[ -z $configs ]]; then
235 error_message "${PROBLEM_COLOR}No such spell or config:$DEFAULT_COLOR $thing"
236 rc=1
237 break
238 fi
239 fi
240 for config in $configs; do
241 merge_single_file "$config"
242 done
243 done
244 final_cleanup
245
246 exit $rc
247 }
248
249 #--------------------------------------------------------------------
250 ## merge all the staged configs
251 #--------------------------------------------------------------------
252 function confmeld_all()
253 {
254 local spell
255
256 for file in $(all_config_files)
257 do
258 merge_single_file "$file"
259 done
260
261 final_cleanup
262 }
263
264 function process_parameters">process_parameters">process_parameters()
265 {
266 local subroutine arguments
267 local mode=$1
268 shift
269
270 while [[ -n $1 ]]; do
271 if [[ ${1:0:1} == "-" ]]; then
272 case "$1" in
273 --help|-h) help">help">help ;;
274 --no-column|-q) USE_COLUMN=no ;;
275 --list-configs|-c) subroutine=list_staged_configs ;;
276 --list-spells|-s) subroutine=list_spells_with_staged_configs ;;
277 --list|-l) subroutine=list_all ;;
278 --force|-f) subroutine="override_changed_config_menu $2"
279 shift ;;
280 *) help">help">help ;;
281 esac
282 else
283 arguments="$1 $arguments"
284 fi
285 shift
286 done
287 [[ $mode == check-only ]] && return 0
288 $subroutine
289
290 [[ $arguments ]] && confmeld_partial $arguments
291 }
292
293 #--------------------------------------------------------------------
294 ## Main
295 ##
296 ## If there's no arguments get all the config files and start installing
297 ## them to the system using install_config_file
298 #--------------------------------------------------------------------
299 function main">main">main">main">main()
300 {
301 local target spell sdate
302 local last_spell=""
303 local last_sdate=""
304
305 [[ -d $CONFIG_STAGE_DIRECTORY ]] || mkdir -p $CONFIG_STAGE_DIRECTORY
306
307 process_parameters">process_parameters">process_parameters normal "$@"
308
309 confmeld_all
310 }
311
312
313 . /etc/sorcery/config
314 if [ "$UID" -gt 0 ]; then
315 # validate the parameters before su-ing, since we may still drop out
316 process_parameters">process_parameters">process_parameters check-only "$@"
317
318 echo "Enter the root password, please."
319 exec su -c "confmeld $@" root
320 else
321 STAGED_INSTALL="off"
322 main">main">main">main">main "$@"
323 fi
324
325 #---------------------------------------------------------------------
326 ##=back
327 ##
328 ##=head1 LICENSE
329 ##
330 ## This software is free software; you can redistribute it and/or modify
331 ## it under the terms of the GNU General Public License as published by
332 ## the Free Software Foundation; either version 2 of the License, or
333 ## (at your option) any later version.
334 ##
335 ## This software is distributed in the hope that it will be useful,
336 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
337 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
338 ## GNU General Public License for more details.
339 ##
340 ## You should have received a copy of the GNU General Public License
341 ## along with this software; if not, write to the Free Software
342 ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
343 ##
344 #---------------------------------------------------------------------