source: CLFS3/master.sh@ c0b307c

2.3 2.3.x 2.4 ablfs ablfs-more legacy new_features trunk
Last change on this file since c0b307c was 4fef116, checked in by George Boudreau <georgeb@…>, 18 years ago

Corrections to CLFS-embedded build of custom_files

  • Property mode set to 100644
File size: 19.8 KB
Line 
1#!/bin/bash
2# $Id$
3
4###################################
5### FUNCTIONS ###
6###################################
7
8
9#----------------------------#
10host_prep_Makefiles() { # Initialization of the system
11#----------------------------#
12 local CLFS_HOST
13
14 echo "${tab_}${GREEN}Processing... ${L_arrow}host prep files ( SETUP ) ${R_arrow}"
15
16 # defined here, only for ease of reading
17 CLFS_HOST="$(echo $MACHTYPE | sed "s/$(echo $MACHTYPE | cut -d- -f2)/cross/")"
18(
19cat << EOF
20
21025-addinguser:
22 @\$(call echo_message, Building)
23 @if [ ! -d /home/\$(LUSER) ]; then \\
24 groupadd \$(LGROUP); \\
25 useradd -s /bin/bash -g \$(LGROUP) -m -k /dev/null \$(LUSER); \\
26 else \\
27 touch luser-exist; \\
28 fi;
29 @touch \$@ && \\
30 echo " "\$(BOLD)Target \$(BLUE)\$@ \$(BOLD)OK && \\
31 echo --------------------------------------------------------------------------------\$(WHITE)
32
33026-settingenvironment: 025-addinguser
34 @\$(call echo_message, Building)
35 @if [ -f /home/\$(LUSER)/.bashrc -a ! -f /home/\$(LUSER)/.bashrc.XXX ]; then \\
36 mv /home/\$(LUSER)/.bashrc /home/\$(LUSER)/.bashrc.XXX; \\
37 fi;
38 @if [ -f /home/\$(LUSER)/.bash_profile -a ! -f /home/\$(LUSER)/.bash_profile.XXX ]; then \\
39 mv /home/\$(LUSER)/.bash_profile /home/\$(LUSER)/.bash_profile.XXX; \\
40 fi;
41 @echo "set +h" > /home/\$(LUSER)/.bashrc && \\
42 echo "umask 022" >> /home/\$(LUSER)/.bashrc && \\
43 echo "CLFS=\$(MOUNT_PT)" >> /home/\$(LUSER)/.bashrc && \\
44 echo "LC_ALL=POSIX" >> /home/\$(LUSER)/.bashrc && \\
45 echo "PATH=\$(MOUNT_PT)/cross-tools/bin:/bin:/usr/bin" >> /home/\$(LUSER)/.bashrc && \\
46 echo "export CLFS LC_ALL PATH" >> /home/\$(LUSER)/.bashrc && \\
47 echo "" >> /home/\$(LUSER)/.bashrc && \\
48 echo "unset CFLAGS" >> /home/\$(LUSER)/.bashrc && \\
49 echo "unset CXXFLAGS" >> /home/\$(LUSER)/.bashrc && \\
50 echo "" >> /home/\$(LUSER)/.bashrc && \\
51 echo "export CLFS_HOST=\"${CLFS_HOST}\"" >> /home/\$(LUSER)/.bashrc && \\
52 echo "export CLFS_TARGET=\"${TARGET}\"" >> /home/\$(LUSER)/.bashrc && \\
53 echo "export CLFS_MIPS_LEVEL=\"${MIPS_LEVEL}\"" >> /home/\$(LUSER)/.bashrc && \\
54 echo "export BUILD=\"${ABI}\"" >> /home/\$(LUSER)/.bashrc && \\
55 echo "source $JHALFSDIR/envars" >> /home/\$(LUSER)/.bashrc
56 @chown \$(LUSER):\$(LGROUP) /home/\$(LUSER)/.bashrc && \\
57 touch envars && \\
58 chown \$(LUSER):\$(LGROUP) envars
59 @touch \$@ && \\
60 echo " "\$(BOLD)Target \$(BLUE)\$@ \$(BOLD)OK && \\
61 echo --------------------------------------------------------------------------------\$(WHITE)
62
63027-create-directories: 026-settingenvironment
64 @\$(call echo_message, Building)
65
66 @mkdir -p \$(MOUNT_PT)/{bin,boot,dev,{etc/,}opt,home,lib,mnt}
67 @mkdir -p \$(MOUNT_PT)/{proc,media/{floppy,cdrom},sbin,srv,sys}
68 @mkdir -p \$(MOUNT_PT)/var/{lock,log,mail,run,spool}
69 @mkdir -p \$(MOUNT_PT)/var/{opt,cache,lib/{misc,locate},local}
70 @install -d -m 0750 \$(MOUNT_PT)/root
71 @install -d -m 1777 \$(MOUNT_PT){/var,}/tmp
72 @mkdir -p \$(MOUNT_PT)/usr/{,local/}{bin,include,lib,sbin,src}
73 @mkdir -p \$(MOUNT_PT)/usr/{,local/}share/{doc,info,locale,man}
74 @mkdir -p \$(MOUNT_PT)/usr/{,local/}share/{misc,terminfo,zoneinfo}
75 @mkdir -p \$(MOUNT_PT)/usr/{,local/}share/man/man{1,2,3,4,5,6,7,8}
76 @for dir in \$(MOUNT_PT)/usr{,/local}; do \\
77 ln -s share/{man,doc,info} \$\$dir ; \\
78 done
79
80 @touch \$@ && \\
81 echo " "\$(BOLD)Target \$(BLUE)\$@ \$(BOLD)OK && \\
82 echo --------------------------------------------------------------------------------\$(WHITE)
83
84028-creating-sysfile: 027-create-directories
85 @\$(call echo_message, Building)
86
87 @touch \$(MOUNT_PT)/etc/mtab
88 @echo "root::0:0:root:/root:/bin/ash" >> \$(MOUNT_PT)/etc/passwd
89 @echo "root:x:0:" >> \$(MOUNT_PT)/etc/group
90 @echo "bin:x:1:" >> \$(MOUNT_PT)/etc/group
91 @echo "sys:x:2:" >> \$(MOUNT_PT)/etc/group
92 @echo "kmem:x:3" >> \$(MOUNT_PT)/etc/group
93 @echo "tty:x:4:" >> \$(MOUNT_PT)/etc/group
94 @echo "tape:x:5:" >> \$(MOUNT_PT)/etc/group
95 @echo "daemon:x:6:" >> \$(MOUNT_PT)/etc/group
96 @echo "floppy:x:7:" >> \$(MOUNT_PT)/etc/group
97 @echo "disk:x:8:" >> \$(MOUNT_PT)/etc/group
98 @echo "lp:x:9:" >> \$(MOUNT_PT)/etc/group
99 @echo "dialout:x:10:" >> \$(MOUNT_PT)/etc/group
100 @echo "audio:x:11:" >> \$(MOUNT_PT)/etc/group
101 @echo "video:x:12:" >> \$(MOUNT_PT)/etc/group
102 @echo "utmp:x:13:" >> \$(MOUNT_PT)/etc/group
103 @echo "usb:x:14:" >> \$(MOUNT_PT)/etc/group
104 @echo "cdrom:x:15:" >> \$(MOUNT_PT)/etc/group
105
106 @touch \$(MOUNT_PT)/var/run/utmp \$(MOUNT_PT)/var/log/{btmp,lastlog,wtmp}
107 @chmod 664 \$(MOUNT_PT)/var/run/utmp \$(MOUNT_PT)/var/log/lastlog
108 @chown -R \$(LUSER) \$(MOUNT_PT) && \\
109 chmod -R a+wt \$(MOUNT_PT)/\$(SCRIPT_ROOT)
110
111 @touch \$@ && \\
112 echo " "\$(BOLD)Target \$(BLUE)\$@ \$(BOLD)OK && \\
113 echo --------------------------------------------------------------------------------\$(WHITE)
114
115EOF
116) >> $MKFILE.tmp
117
118 host_prep=" 025-addinguser 026-settingenvironment 027-create-directories 028-creating-sysfile"
119}
120
121#-----------------------------#
122systemprep_Makefiles() { #
123#-----------------------------#
124 echo "${tab_}${GREEN}Processing... ${L_arrow}system prep tools ( LUSER ) ${R_arrow}"
125
126 for file in systemprep/* ; do
127 # Keep the script file name
128 this_script=`basename $file`
129
130 # Set the dependency for the first target.
131 if [ -z $PREV ] ; then PREV=028-creating-sysfile ; fi
132
133 # First append each name of the script files to a list (this will become
134 # the names of the targets in the Makefile)
135 cross_tools="$cross_tools $this_script"
136
137 # Grab the name of the target (minus the -headers or -cross in the case of gcc
138 # and binutils in chapter 5)
139 name=`echo $this_script | sed -e 's@[0-9]\{3\}-@@'`
140
141 pkg_tarball=$(get_package_tarball_name $name)
142 #--------------------------------------------------------------------#
143 # >>>>>>>> START BUILDING A Makefile ENTRY <<<<<<<< #
144 #--------------------------------------------------------------------#
145 #
146 # Drop in the name of the target on a new line, and the previous target
147 # as a dependency. Also call the echo_message function.
148 LUSER_wrt_target "${this_script}" "$PREV"
149 #
150 # If $pkg_tarball isn't empty, we've got a package...
151 if [ "$pkg_tarball" != "" ] ; then
152 LUSER_wrt_unpack "$pkg_tarball"
153 fi
154 #
155 LUSER_wrt_RunAsUser "${file}"
156 #
157 [[ "$pkg_tarball" != "" ]] && LUSER_RemoveBuildDirs "${name}"
158 #
159 # Include a touch of the target name so make can check if it's already been made.
160 wrt_touch
161 #
162 #--------------------------------------------------------------------#
163 # >>>>>>>> END OF Makefile ENTRY <<<<<<<< #
164 #--------------------------------------------------------------------#
165 #
166 # Keep the script file name for Makefile dependencies.
167 PREV=$this_script
168
169 done # for file in ....
170}
171
172
173#-----------------------------#
174cross_tools_Makefiles() { #
175#-----------------------------#
176 echo "${tab_}${GREEN}Processing... ${L_arrow}cross tools ( LUSER ) ${R_arrow}"
177
178 for file in cross-tools/* ; do
179 # Keep the script file name
180 this_script=`basename $file`
181 #
182 # Skip this script...
183 # NOTE.. the book indicated you only needed to install groff or file if the host
184 # had older versions. The packages would be installed in the target directory
185 # and not the host.
186 case $this_script in
187 *cflags* | *variables* | *abi | *toolchain*) # work done in host_prep_Makefiles
188 continue ;;
189 *) ;;
190 esac
191
192 #
193 # Set the dependency for the first target.
194 if [ -z $PREV ] ; then PREV=028-creating-sysfile ; fi
195
196 # First append each name of the script files to a list (this will become
197 # the names of the targets in the Makefile)
198 cross_tools="$cross_tools $this_script"
199
200 # Grab the name of the target (minus the -headers or -cross in the case of gcc
201 # and binutils in chapter 5)
202 name=`echo $this_script | sed -e 's@[0-9]\{3\}-@@' \
203 -e 's@-static@@' \
204 -e 's@-final@@' \
205 -e 's@-64@@' \
206 -e 's@-n32@@'`
207 case $name in
208 uclibc*) name="uClibc" ;;
209 esac
210 pkg_tarball=$(get_package_tarball_name $name)
211 #--------------------------------------------------------------------#
212 # >>>>>>>> START BUILDING A Makefile ENTRY <<<<<<<< #
213 #--------------------------------------------------------------------#
214 #
215 # Drop in the name of the target on a new line, and the previous target
216 # as a dependency. Also call the echo_message function.
217 LUSER_wrt_target "${this_script}" "$PREV"
218 #
219 # If $pkg_tarball isn't empty, we've got a package...
220 if [ "$pkg_tarball" != "" ] ; then
221 LUSER_wrt_unpack "$pkg_tarball"
222 # If using optimizations, write the instructions
223 [[ "$OPTIMIZE" != "0" ]] && wrt_optimize "$name" && wrt_makeflags "$name"
224 fi
225 #
226 LUSER_wrt_RunAsUser "${file}"
227 #
228 [[ "$pkg_tarball" != "" ]] && LUSER_RemoveBuildDirs "${name}"
229 #
230 # Include a touch of the target name so make can check if it's already been made.
231 wrt_touch
232 #
233 #--------------------------------------------------------------------#
234 # >>>>>>>> END OF Makefile ENTRY <<<<<<<< #
235 #--------------------------------------------------------------------#
236 #
237 # Keep the script file name for Makefile dependencies.
238 PREV=$this_script
239
240 done # for file in ....
241}
242
243
244
245#-----------------------------#
246final_system_Makefiles() { #
247#-----------------------------#
248 echo "${tab_}${GREEN}Processing... ${L_arrow}final system ( LUSER ) ${R_arrow}"
249
250 for file in final-system/* ; do
251 # Keep the script file name
252 this_script=`basename $file`
253
254 # Test if the stripping phase must be skipped.
255 # Skip alsp temp-perl for iterative runs
256 case $this_script in
257 *stripping*) [[ "$STRIP" = "n" ]] && continue ;;
258 esac
259
260 # Grab the name of the target, strip id number, XXX-script
261 name=`echo $this_script | sed -e 's@[0-9]\{3\}-@@' \
262 -e 's@temp-@@' \
263 -e 's@-64bit@@' \
264 -e 's@-64@@' \
265 -e 's@64@@' \
266 -e 's@n32@@'`
267
268 # Find the version of the command files, if it corresponds with the building of
269 # a specific package.
270 pkg_tarball=$(get_package_tarball_name $name)
271
272 # Append each name of the script files to a list (this will become
273 # the names of the targets in the Makefile
274 basicsystem="$basicsystem ${this_script}"
275
276 #--------------------------------------------------------------------#
277 # >>>>>>>> START BUILDING A Makefile ENTRY <<<<<<<< #
278 #--------------------------------------------------------------------#
279 #
280 # Drop in the name of the target on a new line, and the previous target
281 # as a dependency. Also call the echo_message function.
282 LUSER_wrt_target "${this_script}" "$PREV"
283 #
284 # If $pkg_tarball isn't empty, we've got a package...
285 if [ "$pkg_tarball" != "" ] ; then
286 LUSER_wrt_unpack "$pkg_tarball"
287 # If using optimizations, write the instructions
288 [[ "$OPTIMIZE" != "0" ]] && wrt_optimize "$name" && wrt_makeflags "$name"
289 fi
290 #
291 LUSER_wrt_RunAsUser "${file}"
292 #
293 [[ "$pkg_tarball" != "" ]] && LUSER_RemoveBuildDirs "${name}"
294 #
295 # Include a touch of the target name so make can check if it's already been made.
296 wrt_touch
297 #
298 #--------------------------------------------------------------------#
299 # >>>>>>>> END OF Makefile ENTRY <<<<<<<< #
300 #--------------------------------------------------------------------#
301 #
302 # Keep the script file name for Makefile dependencies.
303 PREV=${this_script}
304 done # for file in final-system/* ...
305}
306
307
308
309#-----------------------------#
310bootscripts_Makefiles() { #
311#-----------------------------#
312 echo "${tab_}${GREEN}Processing... ${L_arrow}bootscripts ( LUSER ) ${R_arrow}"
313
314 for file in bootscripts/* ; do
315 # Keep the script file name
316 this_script=`basename $file`
317
318 case $this_script in
319 *console*) continue ;; # Use the files that came with the bootscripts
320 *network*) continue ;; # Manually create these files
321 *) ;;
322 esac
323
324 # First append each name of the script files to a list (this will become
325 # the names of the targets in the Makefile
326 bootscripttools="$bootscripttools $this_script"
327
328 # Grab the name of the target, strip id number, XXX-script
329 name=`echo $this_script | sed -e 's@[0-9]\{3\}-@@'\
330 -e 's@-64bit@@' \
331 -e 's@-64@@' \
332 -e 's@64@@' \
333 -e 's@n32@@'`
334 case $name in
335 *bootscripts*) name=clfs-embedded-bootscripts ;;
336 esac
337
338 pkg_tarball=$(get_package_tarball_name $name)
339
340 #--------------------------------------------------------------------#
341 # >>>>>>>> START BUILDING A Makefile ENTRY <<<<<<<< #
342 #--------------------------------------------------------------------#
343 #
344 # Drop in the name of the target on a new line, and the previous target
345 # as a dependency. Also call the echo_message function.
346 LUSER_wrt_target "${this_script}" "$PREV"
347 #
348 # If $pkg_tarball isn't empty, we've got a package...
349 [[ "$pkg_tarball" != "" ]] && LUSER_wrt_unpack "$pkg_tarball"
350 #
351 LUSER_wrt_RunAsUser "${file}"
352 #
353 [[ "$pkg_tarball" != "" ]] && LUSER_RemoveBuildDirs "${name}"
354 #
355 # Include a touch of the target name so make can check if it's already been made.
356 wrt_touch
357 #
358 #--------------------------------------------------------------------#
359 # >>>>>>>> END OF Makefile ENTRY <<<<<<<< #
360 #--------------------------------------------------------------------#
361 #
362 # Keep the script file name for Makefile dependencies.
363 PREV=$this_script
364
365 done # for file in bootscripts/* ...
366
367}
368
369
370#-----------------------------#
371bootable_Makefiles() { #
372#-----------------------------#
373 echo "${tab_}${GREEN}Processing... ${L_arrow}make bootable ( LUSER ) ${R_arrow}"
374
375 for file in bootable/* ; do
376 # Keep the script file name
377 this_script=`basename $file`
378
379 # A little housekeeping on the scripts
380 case $this_script in
381 *grub | *aboot | *colo | *silo | *arcload | *lilo | *reboot* ) continue ;;
382 *fstab) [[ ! -z ${FSTAB} ]] && cp ${FSTAB} $BUILDDIR/sources/fstab ;;
383 *kernel) # if there is no kernel config file do not build the kernel
384 [[ -z $CONFIG ]] && continue
385 # Copy the config file to /sources with a standardized name
386 cp $CONFIG $BUILDDIR/sources/kernel-config
387 ;;
388 esac
389 #
390 # First append each name of the script files to a list (this will become
391 # the names of the targets in the Makefile
392 # NOTE: new makfile format forces the last script, *chowning, into a separate
393 # phase.
394 case ${this_script} in
395 *chowning) chowning=${this_script} ;;
396 *) bootable="$bootable $this_script" ;;
397 esac
398 #
399 # Grab the name of the target, strip id number and misc words.
400 name=`echo $this_script | sed -e 's@[0-9]\{3\}-@@' -e 's@-build@@' `
401 case $this_script in
402 *kernel*) name=linux
403 ;;
404 esac
405
406 pkg_tarball=$(get_package_tarball_name $name)
407
408 #--------------------------------------------------------------------#
409 # >>>>>>>> START BUILDING A Makefile ENTRY <<<<<<<< #
410 #--------------------------------------------------------------------#
411 #
412 # Drop in the name of the target on a new line, and the previous target
413 # as a dependency. Also call the echo_message function.
414 LUSER_wrt_target "${this_script}" "$PREV"
415 #
416 # If $pkg_tarball isn't empty, we've got a package...
417 [[ "$pkg_tarball" != "" ]] && LUSER_wrt_unpack "$pkg_tarball"
418 #
419 # Select a script execution method
420 case $this_script in
421 *fstab*) if [[ -n "$FSTAB" ]]; then
422 LUSER_wrt_CopyFstab
423 else
424 LUSER_wrt_RunAsUser "${file}"
425 fi
426 ;;
427 *chowning) wrt_RunAsRoot "${file}"
428 ;;
429 *) LUSER_wrt_RunAsUser "${file}"
430 ;;
431 esac
432 #
433 # Housekeeping...remove any build directory(ies) except if the package build fails.
434 [[ "$pkg_tarball" != "" ]] && LUSER_RemoveBuildDirs "${name}"
435 #
436 # Include a touch of the target name so make can check if it's already been made.
437 wrt_touch
438 #
439 #--------------------------------------------------------------------#
440 # >>>>>>>> END OF Makefile ENTRY <<<<<<<< #
441 #--------------------------------------------------------------------#
442 #
443 # Keep the script file name for Makefile dependencies.
444 PREV=$this_script
445
446 done
447
448}
449
450
451#-----------------------------#
452build_Makefile() { # Construct a Makefile from the book scripts
453#-----------------------------#
454 echo "Creating Makefile... ${BOLD}START${OFF}"
455
456 cd $JHALFSDIR/${PROGNAME}-commands
457 # Start with a clean Makefile.tmp file
458 >$MKFILE.tmp
459
460 host_prep_Makefiles
461 [[ "${PLATFORM% -*}" = "WRT" ]] && systemprep_Makefiles # $cross_tools
462 cross_tools_Makefiles # $cross_tools
463 final_system_Makefiles # $basicsystem
464 bootscripts_Makefiles # $bootscripttools
465 bootable_Makefiles # $bootable
466 # Add the CUSTOM_TOOLS targets, if needed
467 [[ "$CUSTOM_TOOLS" = "y" ]] && wrt_CustomTools_target
468
469 # Add a header, some variables and include the function file
470 # to the top of the real Makefile.
471 wrt_Makefile_header
472
473 # Drop in the main target 'all:' and the chapter targets with each sub-target
474 # as a dependency.
475(
476cat << EOF
477
478all: ck_UID mk_SETUP mk_LUSER create-sbu_du-report mk_CUSTOM_TOOLS mk_ROOT
479 @sudo make restore-luser-env
480 @sudo make do-housekeeping
481 @\$(call echo_finished,$VERSION)
482
483ck_UID:
484 @if [ \`id -u\` = "0" ]; then \\
485 echo "--------------------------------------------------"; \\
486 echo "You cannot run this makefile from the root account"; \\
487 echo "--------------------------------------------------"; \\
488 exit 1; \\
489 fi
490
491mk_SETUP:
492 @\$(call echo_SU_request)
493 @sudo make SETUP
494 @touch \$@
495
496mk_LUSER: mk_SETUP
497 @\$(call echo_SULUSER_request)
498 @(sudo \$(SU_LUSER) "source .bashrc && cd \$(MOUNT_PT)/\$(SCRIPT_ROOT) && make LUSER" )
499 @touch \$@
500
501mk_CUSTOM_TOOLS: create-sbu_du-report
502 \$(call echo_PHASE,Building CUSTOM_TOOLS);
503 @if [ "\$(ADD_CUSTOM_TOOLS)" = "y" ]; then \\
504 (sudo \$(SU_LUSER) "mkdir -p $BUILDDIR$TRACKING_DIR"); \\
505 (sudo \$(SU_LUSER) "source .bashrc && cd \$(MOUNT_PT)/\$(SCRIPT_ROOT) && make CUSTOM_TOOLS"); \\
506 fi;
507 @touch \$@
508
509mk_ROOT:
510 @\$(call echo_SU_request)
511 @echo "$VERSION-embedded - jhalfs build" > clfs-release && \\
512 sudo mv clfs-release \$(MOUNT_PT)/etc
513 @sudo make ROOT
514 @touch \$@
515
516
517SETUP: $host_prep
518LUSER: $cross_tools $basicsystem $bootscripttools $bootable
519CUSTOM_TOOLS: $custom_list
520ROOT: $chowning
521
522
523create-sbu_du-report: mk_LUSER
524 @\$(call echo_message, Building)
525 @if [ "\$(ADD_REPORT)" = "y" ]; then \\
526 ./create-sbu_du-report.sh logs $VERSION; \\
527 \$(call echo_report,$VERSION-SBU_DU-$(date --iso-8601).report); \\
528 fi;
529 @touch \$@
530
531restore-luser-env:
532 @\$(call echo_message, Building)
533 @if [ -f /home/\$(LUSER)/.bashrc.XXX ]; then \\
534 mv -f /home/\$(LUSER)/.bashrc.XXX /home/\$(LUSER)/.bashrc; \\
535 fi;
536 @if [ -f /home/\$(LUSER)/.bash_profile.XXX ]; then \\
537 mv /home/\$(LUSER)/.bash_profile.XXX /home/\$(LUSER)/.bash_profile; \\
538 fi;
539 @chown \$(LUSER):\$(LGROUP) /home/\$(LUSER)/.bash* && \\
540 touch \$@ && \\
541 echo " "\$(BOLD)Target \$(BLUE)\$@ \$(BOLD)OK && \\
542 echo --------------------------------------------------------------------------------\$(WHITE)
543
544do-housekeeping:
545 @-if [ ! -f luser-exist ]; then \\
546 userdel \$(LUSER); \\
547 rm -rf /home/\$(LUSER); \\
548 fi;
549
550EOF
551) >> $MKFILE
552
553 # Bring over the items from the Makefile.tmp
554 cat $MKFILE.tmp >> $MKFILE
555 rm $MKFILE.tmp
556 echo "Creating Makefile... ${BOLD}DONE${OFF}"
557
558}
559
Note: See TracBrowser for help on using the repository browser.