Prepare 1.3.8-rc1
[yaboot.git] / ybin / ybin
1 #! /bin/sh
2
3 ###############################################################################
4 ##
5 ## ybin (YaBoot INstaller) installs/updates the yaboot bootloader.
6 ## Copyright (C) 2000, 2001, 2002 Ethan Benson
7 ##
8 ## This program is free software; you can redistribute it and/or
9 ## modify it under the terms of the GNU General Public License
10 ## as published by the Free Software Foundation; either version 2
11 ## of the License, or (at your option) any later version.
12 ##
13 ## This program is distributed in the hope that it will be useful,
14 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 ## GNU General Public License for more details.
17 ##
18 ## You should have received a copy of the GNU General Public License
19 ## along with this program; if not, write to the Free Software
20 ## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21 ##
22 ###############################################################################
23
24 PATH="/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin"
25 ## allow to run out of /target in boot-floppies
26 if [ -n "$PATH_PREFIX" ] ; then
27     PATH="${PATH}:${PATH_PREFIX}/sbin:${PATH_PREFIX}/bin:${PATH_PREFIX}/usr/sbin:${PATH_PREFIX}/usr/bin:${PATH_PREFIX}/usr/local/sbin:${PATH_PREFIX}/usr/local/bin"
28 fi
29 PRG="${0##*/}"
30 SIGINT="$PRG: Interrupt caught ... exiting"
31 VERSION=1.3.8-rc1
32 DEBUG=0
33 VERBOSE=0
34 TMP="${TMPDIR:-/tmp}"
35 export LC_COLLATE=C
36
37 ## avoid older versions of ofpath shipped in debian boot-floppies etc.
38 if [ -x "${PATH_PREFIX}/usr/sbin/ofpath" ] ; then
39     OFPATH="${PATH_PREFIX}/usr/sbin/ofpath"
40 else
41     OFPATH=ofpath
42 fi
43
44 ## catch signals, clean up junk in /tmp.
45 trap "cleanup" 0
46 trap "exit 129" 1
47 trap "echo 1>&2 $SIGINT ; exit 130" 2
48 trap "exit 131" 3
49 trap "exit 143" 15
50
51 ## allow for non-existent config file, in which case it will be
52 ## generated from command line arguments.
53 if [ -f /etc/yaboot.conf ] ; then
54     CONF=/etc/yaboot.conf
55     bootconf=$CONF
56     ERR=" Error in $CONF:"
57 else
58     CONF=/dev/null
59     bootconf=/dev/null
60 fi
61
62 ## define default configuration
63 boot=unconfigured
64
65 ## allow default to work on packaged and non-packaged yaboot. 
66 ## no default for magicboot since it is not required everywhere.
67 if [ -f /usr/local/lib/yaboot/yaboot ] ; then
68     install=/usr/local/lib/yaboot/yaboot
69 elif [ -f /usr/lib/yaboot/yaboot ] ; then
70     install=/usr/lib/yaboot/yaboot
71 fi
72
73 ## defaults
74 usemount=no
75 if (cat /proc/cpuinfo 2> /dev/null | grep ^machine | grep -q 'CHRP IBM') ; then
76     fstype=raw
77 else
78     fstype=hfs
79 fi
80 hfstype=tbxi
81 hfscreator=UNIX
82 bless=yes
83 protect=no
84 hide=no
85 nonvram=0
86 defaultos=linux
87 brokenosx=no
88 cdrom=no
89 network=no
90 of=no
91 fgcolor=white
92 bgcolor=black
93
94 ## yaboot autoconf defaults
95 label=Linux
96 timeout=40
97 image=/vmlinux
98 partition=3
99 root=/dev/hda3
100 device=hd:
101
102 ## this program behaves differently based on how its called, this
103 ## ensures that nothing nasty happens if someone makes a bogus
104 ## symlink.
105 case "$PRG" in
106     ybin)
107     ;;
108     mkofboot)
109     ;;
110     *)
111     echo 1>&2 "This program must be called as either \`ybin' or \`mkofboot'"
112     exit 1
113     ;;
114 esac
115
116 ## check for printf, use it if possible otherwise fall back on
117 ## unreliable echo -e -n ("SUS" says echo shall support no switches)
118 if [ "$(printf printf_test 2>/dev/null)" = printf_test ] ; then
119     PRINTF=printf
120 else
121     PRINTF="echo -e -n"
122 fi
123
124 ## make fake `id' if its missing, outputs 0 since if its missing we
125 ## are probably running on boot floppies and thus are root.
126 if (command -v id > /dev/null 2>&1) ; then 
127     true
128 else
129     id()
130     {
131     echo 0
132     }
133 fi
134
135 ## --version output
136 version()
137 {
138 echo \
139 "$PRG $VERSION
140 Written by Ethan Benson
141
142 Copyright (C) 2000, 2001, 2002 Ethan Benson
143 This is free software; see the source for copying conditions.  There is NO
144 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
145 }
146
147 ## --help output.
148 usage()
149 {
150 echo \
151 "Usage: $PRG [OPTION]...
152 Update/install bootloader onto a bootstrap partition.
153
154   -b, --boot                 set bootstrap partition device [ -b /dev/hda2 ]
155   -o, --ofboot               set bootstrap partition OpenFirmware device
156                                default: automatically determined [ -o hd:2 ]
157   -i, --install              pathname to the actual bootloader binary
158                                default: /usr/{local/}lib/yaboot/yaboot same as
159                                install= in config file [ -i bootloader_file ]
160   -C, --config               use alternate configuration file (ybin and yaboot)
161                                [ -C config_file ]
162   -m, --magicboot            pathname to a OpenFirmware magicboot (CHRP) script
163       --filesystem           set the filesystem type of the bootstrap partition
164                                available options are hfs, msdos, and raw
165                                [ --filesystem hfs ] default is hfs
166       --nobless              don't bless the root directory, this should only
167                                be used if you are using a MacOS boot partition
168                                as the bootstrap partition (not recommended)
169   -M, --mount                don't use userspace hfsutils to modify the
170                                bootstrap instead try and mount the filesystem
171                                directly.  Note that attributes cannot be set
172                                this way and you will have to manually modify
173                                OpenFirmware to make your system bootable
174       --protect              set the read-only (locked) bit on all bootstrap
175                                files
176       --hide                 set the invisible bit on all bootstrap files
177                                this is useful of you don't want them to be
178                                visible from MacOS.
179       --nonvram              do not update the boot-device variable in nvram.
180       --force                don't ever ask for confirmation
181   -v, --verbose              make $PRG more verbose
182       --debug                print boring junk only useful for debugging
183   -h, --help                 display this help and exit
184   -V, --version              output version information and exit"
185 }
186
187 ## configuration file parsing. FIXME: need a method which can parse
188 ## image= sections.
189 parseconf()
190 {
191 case "$1" in
192     str)
193        v=`grep "^$2[\ ,=]" "$CONF"` ; echo "${v#*=}"
194        ;;
195     flag)
196        grep "^$2\>" "$CONF" > /dev/null && echo 0 || echo 1
197        ;;
198     ck)
199        grep "^$2[\ ,=]" "$CONF" > /dev/null && echo 0 || echo 1
200        ;;
201 esac
202 }
203
204 ## check for existence of a configuration file, and make sure we have
205 ## read permission.
206 confexist()
207 {
208     if [ ! -e "$CONF" ] ; then
209         echo 1>&2 "$PRG: $CONF: No such file or directory"
210         return 1
211     elif [ ! -f "$CONF" ] ; then
212         echo 1>&2 "$PRG: $CONF: Not a regular file"
213         return 1
214     elif [ ! -r "$CONF" ] ; then
215         echo 1>&2 "$PRG: $CONF: Permission denied"
216         return 1
217     else
218         return 0
219     fi
220 }
221
222 ## check to make sure the configuration file is sane and correct.
223 ## maybe this is an insane ammount of error checking, but I want to
224 ## make sure (hopfully) nothing unexpected ever happens.  and i just
225 ## like useful errors from programs.  every error just marks an error
226 ## variable so we give the user as much info as possible before we
227 ## abandon ship.
228 checkconf()
229 {
230     if [ ! -e "$boot" ] ; then
231         echo 1>&2 "$PRG: $boot: No such file or directory"
232         local CONFERR=1
233     elif [ ! -b "$boot" -a ! -f "$boot" ] ; then
234         echo 1>&2 "$PRG: $boot: Not a regular file or block device"
235         local CONFERR=1
236     elif [ ! -w "$boot" -o ! -r "$boot" ] ; then
237         [ -z "$mntpoint" ] && echo 1>&2 "$PRG: $boot: Permission denied"
238         [ -z "$mntpoint" ] && CONFERR=1
239     fi
240
241     if [ ! -e "$install" ] ; then
242         echo 1>&2 "$PRG: $install: No such file or directory"
243         local CONFERR=1
244     elif [ ! -f "$install" ] ; then
245         echo 1>&2 "$PRG: $bootconf: Not a regular file"
246         local CONFERR=1
247     elif [ ! -r "$install" ] ; then
248         echo 1>&2 "$PRG: $install: Permission denied"
249         local CONFERR=1
250     fi
251
252     if [ "$bootconf" = auto ] ; then
253         true
254     elif [ ! -e "$bootconf" ] ; then
255         echo 1>&2 "$PRG: $bootconf: No such file or directory"
256         local CONFERR=1
257     elif [ ! -f "$bootconf" ] ; then
258         echo 1>&2 "$PRG: $bootconf: Not a regular file"
259         local CONFERR=1
260     elif [ ! -r "$bootconf" ] ; then
261         echo 1>&2 "$PRG: $bootconf: Permission denied"
262         local CONFERR=1
263     fi
264
265     if [ -n "$magicboot" ] ; then
266         if [ ! -e "$magicboot" ] ; then
267             echo 1>&2 "$PRG: $magicboot: No such file or directory"
268             local CONFERR=1
269         elif [ ! -f "$magicboot" ] ; then
270             echo 1>&2 "$PRG: $magicboot: Not a regular file"
271             local CONFERR=1
272         elif [ ! -r "$magicboot" ] ; then
273             echo 1>&2 "$PRG: $magicboot: Permission denied"
274             local CONFERR=1
275         fi
276     fi
277
278     case "$fstype" in
279         hfs|msdos|raw)
280          ;;
281         *)
282          if [ "$ARGFS" = 1 ] ; then
283             echo 1>&2 "$PRG: --filesystem must be either \`hfs', \`msdos', or \`raw'"
284          else
285             echo 1>&2 "$PRG:$ERR \`fstype' must be either \`hfs', \`msdos', or \`raw'"
286          fi
287          local CONFERR=1
288          ;;
289     esac
290
291     ## if we are not using HFS filesystems we don't care about HFS
292     ## specific options.
293     if [ "$fstype" = hfs ] ; then
294         if [ `echo ${#hfstype}` != 4 ] ; then
295             if [ "$ARGTP" = 1 ] ; then
296                 echo 1>&2 "$PRG: --type must be 4 characters"
297             else
298                 echo 1>&2 "$PRG:$ERR \`hfstype' must be 4 characters"
299             fi
300             local CONFERR=1
301         fi
302         
303         if [ `echo ${#hfscreator}` != 4 ] ; then
304             if [ "$ARGCT" = 1 ] ; then
305                 echo 1>&2 "$PRG: --creator must be 4 characters"
306             else
307                 echo 1>&2 "$PRG:$ERR \`hfscreator' must be 4 characters"
308             fi
309             local CONFERR=1
310         fi
311     fi
312
313     ## some options are not compatible with fstype=raw
314     if [ "$fstype" = raw ] ; then
315         if [ -n "$mntpoint" ] ; then
316             echo 1>&2 "$PRG:$ERR \`mntpoint' is not compatible with fstype=raw"
317             local CONFERR=1
318         fi
319         if [ "$usemount" = yes ] ; then
320             echo 1>&2 "$PRG:$ERR \`usemount' is not compatible with fstype=raw"
321             local CONFERR=1
322         fi
323         if [ -n "$magicboot" ] ; then
324             echo 1>&2 "$PRG:$ERR \`magicboot' scripts cannot be used with fstype=raw"
325             local CONFERR=1
326         fi
327     fi
328
329     if [ -n "$mntpoint" ] ; then
330         ## standard checks
331         if [ ! -e "$mntpoint" ] ; then
332             echo 1>&2 "$PRG: $mntpoint: No such file or directory"
333             local CONFERR=1
334         elif [ ! -d "$mntpoint" ] ; then
335             echo 1>&2 "$PRG: $mntpoint: Not a directory"
336             local CONFERR=1
337         elif [ ! -w "$mntpoint" -o ! -r "$mntpoint" ] ; then
338             echo 1>&2 "$PRG: $mntpoint: Permission denied"
339             local CONFERR=1
340         elif [ ! -O "$mntpoint" -a `id -u` != 0 ] ; then
341             echo 1>&2 "$PRG: $mntpoint: Permission denied (not owner)"
342             local CONFERR=1
343         fi
344
345         ## make sure no embedded spaces exist
346         echo "$mntpoint" | grep -q [[:space:]]
347         if [ $? = 0 ] ; then
348             echo 1>&2 "$PRG:$ERR \`mntpoint=$mntpoint' contains embedded spaces, don't use lame filenames"
349             local CONFERR=1
350         fi
351
352         ## make sure $mntpoint is on $boot, this matters to nvram updating.
353         if [ "$(v=`df "$mntpoint" 2> /dev/null | grep ^/dev/` ; echo ${v%%[ ]*})" != "$boot" -a -d "$mntpoint" ] ; then
354             echo 1>&2 "$PRG: $mntpoint is not located on $boot"
355             local CONFERR=1
356             ## more then one subdirectory deep is not supported. no sed available on boot floppies ( / -> \ )
357         elif [ "$mntpoint" != "$(v=`df "$mntpoint" 2> /dev/null | grep ^/dev/` ; echo ${v##*[ ]})" ] ; then
358             echo "$(v=`df "$mntpoint" 2>/dev/null | grep ^/dev/`; m=${v##*[ ]}; echo "${mntpoint##*$m/}")" | grep -q /
359             if [ $? = 0 ] ; then
360                 echo 1>&2 "$PRG:$ERR $mntpoint is more then one subdirectory deep from root of $boot"
361                 local CONFERR=1
362             else
363                 OFDIR="$(v=`df "$mntpoint" 2>/dev/null | grep ^/dev/`; m=${v##*[ ]}; echo "${mntpoint##*$m/}")"
364             fi
365         fi
366
367         if [ "$usemount" = no ] ; then
368             echo 1>&2 "$PRG:$ERR \`mntpoint=' requires \`usemount' be set"
369             local CONFERR=1
370         fi
371     fi
372
373     if [ -n "$magicboot" ] ; then
374         ## check for bsd loader
375         if [ -n "$bsd" ] ; then
376             if [ -f /usr/lib/yaboot/ofwboot -a -r /usr/lib/yaboot/ofwboot ] ; then
377                 BSDLOADER="/usr/lib/yaboot/ofwboot"
378             elif [ -f /usr/local/lib/yaboot/ofwboot -a -r /usr/local/lib/yaboot/ofwboot ] ; then
379                 BSDLOADER="/usr/local/lib/yaboot/ofwboot"
380             else
381                 echo 1>&2 "$PRG: /usr/local/lib/yaboot/ofwboot: No such file or directory"
382                 echo 1>&2 "$PRG: With the bsd= option set you must have the bsd boot loader ofwboot"
383                 CONFERR=1
384             fi
385         fi
386
387         ## convert defaultos variable
388         case "$defaultos" in 
389             linux|Linux|GNU|Gnu|gnu)
390                 defaultos=bootyaboot
391                 ;;
392             bootyaboot)
393                 ;;
394             bsd)
395                 defaultos=bootbsd
396                 if [ -z "$bsd" ] ; then
397                     echo 1>&2 "$PRG:$ERR no entry for \`bsd' found, but defaultos is set to \`bsd'"
398                     local CONFERR=1
399                 fi
400                 ;;
401             macos)
402                 defaultos=bootmacos
403                 if [ -z "$macos" ] ; then
404                     echo 1>&2 "$PRG:$ERR no entry for \`macos' found, but defaultos is set to \`macos'"
405                     local CONFERR=1
406                 fi
407                 ;;
408             macosx)
409                 defaultos=bootmacosx
410                 if [ -z "$macosx" ] ; then
411                     echo 1>&2 "$PRG:$ERR no entry for \`macosx' found, but defaultos is set to \`macosx'"
412                     local CONFERR=1
413                 fi
414                 ;;
415             darwin)
416                 defaultos=bootdarwin
417                 if [ -z "$darwin" ] ; then
418                     echo 1>&2 "$PRG:$ERR no entry for \`darwin' found, but defaultos is set to \`darwin'"
419                     local CONFERR=1
420                 fi
421                 ;;
422             *)
423                 echo 1>&2 "$PRG:$ERR \`defaultos' must be either \`linux', \`bsd', \`macos' or \`macosx'"
424                 local CONFERR=1
425                 ;;
426         esac
427     fi
428
429     ## nvsetenv requires /proc
430     if [ ! -f /proc/uptime -a "$nonvram" = 0 ] ; then
431         echo 1>&2 "$PRG: /proc filesystem is not mounted, nvram will not be updated"
432         nonvram=1
433     fi
434
435     if [ "$nonvram" = 0 ] ; then
436         ## see if nvsetenv exists and is executable
437         if (command -v nvsetenv > /dev/null 2>&1) ; then
438             [ -x `command -v nvsetenv` ] || MISSING=1 ; else MISSING=1
439         fi
440
441         if [ "$nonvram" = 0 ] ; then
442             ## if nvsetenv exists see if its the old broken version
443             if [ "$MISSING" != 1 ] ; then
444                 nvsetenv --version > /dev/null 2>&1 || OLD=1
445             else
446                 nonvram=1
447                 echo 1>&2 "$PRG: Warning: \`nvsetenv' could not be found, nvram will not be updated"
448             fi
449
450             if [ "$OLD" = 1 ] ; then
451                 ## i check this myself to avoid misleading error
452                 ## messages. nvsetenv should REALLY support --version.
453                 if [ ! -e /dev/nvram ] ; then
454                     echo 1>&2 "$PRG: /dev/nvram: No such file or directory"
455                     echo 1>&2 "$PRG: Warning: nvram will not be updated"
456                     nonvram=1
457                 elif [ ! -c /dev/nvram ] ; then
458                     echo 1>&2 "$PRG: /dev/nvram: Not a character device"
459                     echo 1>&2 "$PRG: Warning: nvram will not be updated"
460                     nonvram=1
461                 elif [ ! -w /dev/nvram -o ! -r /dev/nvram ] ; then
462                     echo 1>&2 "$PRG: /dev/nvram: Permission denied"
463                     echo 1>&2 "$PRG: Warning: nvram will not be updated"
464                     nonvram=1
465                 else
466                     nonvram=1
467                     echo 1>&2 "$PRG: Warning: Incompatible version of \`nvsetenv', nvram will not be updated"
468                 fi
469             fi
470         fi
471
472         if [ -f "$boot" ] ; then
473             echo 1>&2 "$PRG: $boot is a regular file, disabling nvram updating"
474             nonvram=1
475         fi
476     fi
477
478     ## check for newworld mac. use cat hack due to /proc wierdness.
479     ## do not bail if we are on an OldWorld only warn (very loudly).
480     if [ "$(v=`cat /proc/cpuinfo 2>/dev/null | grep pmac-generation` ; echo ${v##*:})" = NewWorld ] ; then
481         true
482     elif [ "$(v=`cat /proc/cpuinfo 2>/dev/null | grep pmac-generation` ; echo ${v##*:})" = OldWorld ] ; then
483         echo 1>&2
484         echo 1>&2 '@@@@@@@@@@@@@@ WARNING!! WARNING!! WARNING!! @@@@@@@@@@@@@@'
485         echo 1>&2 "$PRG: Warning: This is an OldWorld PowerMac, $boot will **NOT** be bootable on this machine"
486         echo 1>&2 "$PRG: Oldworld PowerMacs need to use the quik bootloader, not yaboot"
487         echo 1>&2 '@@@@@@@@@@@@@@ WARNING!! WARNING!! WARNING!! @@@@@@@@@@@@@@'
488         echo 1>&2
489         [ "$nonvram" = 0 ] && echo 1>&2 "$PRG: OldWorld PowerMac, nvram will not be updated"
490         nonvram=1
491     elif (cat /proc/cpuinfo 2>/dev/null | grep ^motherboard | grep -q AAPL) ; then
492         echo 1>&2
493         echo 1>&2 '@@@@@@@@@@@@@@ WARNING!! WARNING!! WARNING!! @@@@@@@@@@@@@@'
494         echo 1>&2 "$PRG: Warning: This is an OldWorld PowerMac, $boot will **NOT** be bootable on this machine"
495         echo 1>&2 "$PRG: Oldworld PowerMacs need to use the quik bootloader, not yaboot"
496         echo 1>&2 '@@@@@@@@@@@@@@ WARNING!! WARNING!! WARNING!! @@@@@@@@@@@@@@'
497         echo 1>&2
498         [ "$nonvram" = 0 ] && echo 1>&2 "$PRG: OldWorld PowerMac, nvram will not be updated"
499         nonvram=1
500     elif (cat /proc/cpuinfo 2> /dev/null | grep ^machine | grep -q 'CHRP IBM') ; then
501         ## IBM hardware does not need nvram update AFAICT
502         nonvram=1
503         ADDNOTE=yes
504     else
505         #echo 1>&2 "$PRG: Warning: Unknown archetecture, $boot may not be bootable on this machine"
506         [ "$nonvram" = 0 ] && echo 1>&2 "$PRG: Warning: Unknown architecture, nvram will not be updated"
507         nonvram=1
508     fi
509
510     ## convert human readable color values from config to proper color
511     ## codes
512     case "$fgcolor" in
513         black) fgc=0 ;; blue) fgc=1 ;; green) fgc=2 ;; cyan) fgc=3 ;;
514         red) fgc=4 ;; purple) fgc=5 ;; brown) fgc=6 ;; light-gray) fgc=7 ;;
515         dark-gray) fgc=8 ;; light-blue) fgc=9 ;; light-green) fgc=a ;;
516         light-cyan) fgc=b ;; light-red) fgc=c ;; light-purple) fgc=d ;;
517         yellow) fgc=e ;; white) fgc=f ;;
518         *)
519         echo 1>&2 "$PRG:$ERR Invalid fgcolor: \`$fgcolor'"
520         local CONFERR=1
521         ;;
522     esac
523     case "$bgcolor" in
524         black) bgc=0 ;; blue) bgc=1 ;; green) bgc=2 ;; cyan) bgc=3 ;;
525         red) bgc=4 ;; purple) bgc=5 ;; brown) bgc=6 ;; light-gray) bgc=7 ;;
526         dark-gray) bgc=8 ;; light-blue) bgc=9 ;; light-green) bgc=a ;;
527         light-cyan) bgc=b ;; light-red) bgc=c ;; light-purple) bgc=d ;;
528         yellow) bgc=e ;; white) bgc=f ;;
529         *)
530         echo 1>&2 "$PRG:$ERR Invalid bgcolor: \`$bgcolor'"
531         local CONFERR=1
532         ;;
533     esac
534
535     ## if delay is not set use yaboot's timeout
536     if [ -z "$delay" ] ; then
537         delay="$(($timeout / 10))"
538     fi
539
540     if [ "$CONFERR" = 1 ] ; then
541         return 1
542     else
543         return 0
544     fi
545 }
546
547
548 ## if readlink is missing use a kludge
549 if (command -v readlink > /dev/null 2>&1) ; then
550     true
551 else
552     readlink()
553     {
554         local SYMTARGET="$(v=`ls -l "$2" 2>/dev/null` ; echo ${v##*> })"
555         if [ -n "$SYMTARGET" ] ; then
556             echo "$SYMTARGET"
557             return 0
558         else
559             return 1
560         fi
561     }
562 fi
563
564 ## /etc/yaboot.conf with password should not be world readable.
565 permcheck()
566 {
567 if [ -L "$bootconf" ] ; then
568     local realfile="$(readlink -f "$bootconf")" || return 0
569 else
570     local realfile="$bootconf"
571 fi
572
573 ## don't bother if we could not read the symlink
574 [ -z "$realfile" ] && return 0
575 [ ! -f "$realfile" ] && return 0
576
577 ## get permissions, and don't bother checking if we can't
578 local PERM=`v=$(ls -l "$realfile" 2>/dev/null) ; echo ${v%% *}`
579 [ -z "$PERM" ] && return 0
580 [ `echo ${#PERM}` != 10 ] && return 0
581
582 case "$PERM" in
583     -rw-------|-r--------)
584       if [ ! -O "$realfile" -a `id -u` = 0 ] ; then
585          echo 1>&2 "$PRG: Warning: $bootconf is not owned by root"
586       fi
587       ;;
588     -rw-r-----|-r--r-----)
589       if [ ! -O "$realfile" -a `id -u` = 0 ] ; then
590          echo 1>&2 "$PRG: Warning: $bootconf is not owned by root"
591       fi
592       if [ ! -G "$realfile" -a `id -g` = 0 ] ; then
593          echo 1>&2 "$PRG: Warning: $bootconf is not owned by group root"
594       fi
595       ;;
596     -r--r--r--|-rw-r--r--|-rw-rw-r--|-rw-rw-rw-|-rw-rw----)
597       echo 1>&2 "$PRG: Warning: Insecure permissions on $bootconf: $PERM should be -rw-------"
598       ;;
599     *)
600       echo 1>&2 "$PRG: Warning: Incorrect permissions on $bootconf: $PERM should be -rw-------"
601       ;;
602 esac
603 }
604
605 convertpath()
606 {
607     ## figure out bootstrap device OF pathname if user did not supply it.
608     if [ -z "$ofboot" ] ; then
609         [ "$VERBOSE" = 1 ] && echo "$PRG: Finding OpenFirmware device path to \`$boot'..."
610         ofboot="$($OFPATH $boot)"
611         if [ $? != 0 ] ; then
612             echo 1>&2 "$PRG: Unable to find OpenFirmware path for boot=$boot"
613             echo 1>&2 "$PRG: Please add ofboot=<path> where <path> is the OpenFirmware path to $boot to $CONF"
614             local CONVERR=1
615         fi
616         [ "$DEBUG" = 1 ] && echo 1>&2 "$PRG: DEBUG: ofboot set to \`$ofboot'"
617     fi
618
619     ## figure out OF device path for macos/macosx if user supplied a unix device node.
620     if [ -n "$bsd" ] ; then
621         case "$bsd" in
622             /dev/*)
623                 [ "$VERBOSE" = 1 ] && echo "$PRG: Finding OpenFirmware device path to \`$bsd'..."
624                 local sbsd="$bsd"
625                 bsd="$($OFPATH $bsd)"
626                 if [ $? != 0 ] ; then
627                     echo 1>&2 "$PRG: Unable to determine OpenFirmware path for bsd=$sbsd"
628                     echo 1>&2 "$PRG: Try specifying the real OpenFirmware path for bsd=$sbsd in $CONF"
629                     local CONVERR=1
630                 fi
631                 [ "$DEBUG" = 1 ] && echo 1>&2 "$PRG: DEBUG: bsd set to \`$bsd' from \`$sbsd'"
632                 ;;
633             *)
634                 [ "$DEBUG" = 1 ] && echo 1>&2 "$PRG: DEBUG: bsd left alone: \`$bsd'"
635                 ;;
636         esac
637     fi
638
639     if [ -n "$macos" ] ; then
640         case "$macos" in
641             /dev/*)
642                 [ "$VERBOSE" = 1 ] && echo "$PRG: Finding OpenFirmware device path to \`$macos'..."
643                 local smacos="$macos"
644                 macos="$($OFPATH $macos)"
645                 if [ $? != 0 ] ; then
646                     echo 1>&2 "$PRG: Unable to determine OpenFirmware path for macos=$smacos"
647                     echo 1>&2 "$PRG: Try specifying the real OpenFirmware path for macos=$smacos in $CONF"
648                     local CONVERR=1
649                 fi
650                 [ "$DEBUG" = 1 ] && echo 1>&2 "$PRG: DEBUG: macos set to \`$macos' from \`$smacos'"
651                 ;;
652             *)
653                 [ "$DEBUG" = 1 ] && echo 1>&2 "$PRG: DEBUG: macos left alone: \`$macos'"
654                 ;;
655         esac
656     fi
657
658     if [ -n "$macosx" ] ; then
659         case "$macosx" in
660             /dev/*)
661                 [ "$VERBOSE" = 1 ] && echo "$PRG: Finding OpenFirmware device path to \`$macosx'..."
662                 local smacosx="$macosx"
663                 macosx="$($OFPATH $macosx)"
664                 if [ $? != 0 ] ; then
665                     echo 1>&2 "$PRG: Unable to determine OpenFirmware path for macosx=$smacosx"
666                     echo 1>&2 "$PRG: Try specifying the real OpenFirmware path for macosx=$smacosx in $CONF"
667                     local CONVERR=1
668                 fi
669                 [ "$DEBUG" = 1 ] && echo 1>&2 "$PRG: DEBUG: macosx set to \`$macosx' from \`$smacosx'"
670                 ;;
671             *)
672                 [ "$DEBUG" = 1 ] && echo 1>&2 "$PRG: DEBUG: macosx left alone: \`$macosx'"
673                 ;;
674         esac
675     fi
676
677     if [ -n "$darwin" ] ; then
678         case "$darwin" in
679             /dev/*)
680                 [ "$VERBOSE" = 1 ] && echo "$PRG: Finding OpenFirmware device path to \`$darwin'..."
681                 local sdarwin="$darwin"
682                 darwin="$($OFPATH $darwin)"
683                 if [ $? != 0 ] ; then
684                     echo 1>&2 "$PRG: Unable to determine OpenFirmware path for darwin=$sdarwin"
685                     echo 1>&2 "$PRG: Try specifying the real OpenFirmware path for darwin=$sdarwin in $CONF"
686                     local CONVERR=1
687                 fi
688                 [ "$DEBUG" = 1 ] && echo 1>&2 "$PRG: DEBUG: darwin set to \`$darwin' from \`$sdarwin'"
689                 ;;
690             *)
691                 [ "$DEBUG" = 1 ] && echo 1>&2 "$PRG: DEBUG: darwin left alone: \`$darwin'"
692                 ;;
693         esac
694     fi
695
696     if [ "$CONVERR" = 1 ] ; then
697         return 1
698     else
699         return 0
700     fi
701 }
702
703 ## make sure the hfsutils we need are installed and executable.
704 checkhfsutils()
705 {
706     if (command -v hmount > /dev/null 2>&1) ; then
707         [ -x `command -v hmount` ] || FAIL=1 ; else FAIL=1 ; fi
708     if (command -v humount > /dev/null 2>&1) ; then
709         [ -x `command -v humount` ] || FAIL=1 ; else FAIL=1 ; fi
710     if (command -v hcopy > /dev/null 2>&1) ; then
711         [ -x `command -v hcopy` ] || FAIL=1 ; else FAIL=1 ; fi
712     if (command -v hattrib > /dev/null 2>&1) ; then
713         [ -x `command -v hattrib` ] || FAIL=1 ; else FAIL=1 ; fi
714     if (command -v hformat > /dev/null 2>&1) ; then
715         [ -x `command -v hformat` ] || FAIL=1 ; else FAIL=1 ; fi
716
717     if [ "$FAIL" = 1 ] ; then
718         return 1
719     else
720         return 0
721     fi
722 }
723
724 ## This is gross, IBM CHRP OF needs a .note added to the yaboot
725 ## binary, nobody knows whether this note will affect PowerMac OF or
726 ## not (or could in the future). 
727 hack_yaboot()
728 {
729     local YBDIR="${install%/*}"
730     if [ -x "$YBDIR/addnote" ] ; then
731         TMPYABOOT=`mktemp -q "$TMP/yaboot.XXXXXX"`
732         if [ $? != 0 ] ; then
733             echo 1>&2 "$PRG: Could not create temporary file, aborting."
734             return 1
735         else
736             if (cat "$install" > "$TMPYABOOT" 2> /dev/null) ; then
737                 install="$TMPYABOOT"
738             else
739                 echo 1>&2 "$PRG: Could not create temporary file, aborting."
740                 return 1
741             fi
742         fi
743         [ "$DEBUG" = 1 ] && echo "$PRG: Embedding CHRP note section in temp yaboot..."
744         "$YBDIR/addnote" "$install" > /dev/null 2>&1
745         if [ $? != 0 ] ; then
746             echo 1>&2 "$PRG: Could not install note section required by your architecture"
747             return 1
748         fi
749     else
750         echo 1>&2 "$PRG: Your architecture requires $YBDIR/addnote which cannot be found"
751         return 1
752     fi
753     return 0
754 }
755
756 ## install using userspace utilities rather then kernel filesytem
757 ## support.  hfsutils only, mtools not supported.
758 util_install()
759 {
760     ## catch signals, and humount, cleanup done by trap 0.
761     trap "humount $boot ; exit 129" 1
762     trap "echo 1>&2 $SIGINT ; humount $boot ; exit 130" 2
763     trap "humount $boot ; exit 131" 3
764     trap "humount $boot ; exit 143" 15
765
766     ## filenames on bootstrap partition. ofboot hard codes yaboot.
767     local BTFILE=yaboot
768     local CFFILE=yaboot.conf
769
770     ## if there is a magicboot script to install we will give it the
771     ## hfstype (should be "tbxi") and give yaboot type "boot".
772     if [ -n "$magicboot" ] ; then
773         local BTTYPE=boot
774     else
775         local BTTYPE="$hfstype"
776     fi
777
778     if [ -n "$magicboot" ] ; then
779         local WRAP="${magicboot##*/}"
780     fi
781
782     ## set verbose messages here so they don't show temporary file paths
783     local INSTALLFIRST="$PRG: Installing first stage bootstrap $magicboot onto $boot..."
784     local INSTALLPRIMARY="$PRG: Installing primary bootstrap $install onto $boot..."
785
786     ## repoint magicboot as the real first stage loader if using the
787     ## modern automatic generating ofboot.b.
788     if [ -n "$FIRST" ] ; then   
789         magicboot="$FIRST"
790         [ "$DEBUG" = 1 ] && echo 1>&2 "$PRG: DEBUG: set magicboot to $FIRST"
791     fi
792
793     ## gross hack, add note section for IBM CHRP
794     if [ "$ADDNOTE" = yes ] ; then
795         hack_yaboot || return 1
796     fi
797
798     if [ "$fstype" = hfs ] ; then
799         if [ "$protect" = yes ] ; then
800             local LOCK="+l"
801         fi
802         
803         if [ "$hide" = yes ] ; then
804             local INVISIBLE="+i"
805         fi
806
807         ## make sure the device is not mounted as a filesystem before
808         ## we start mucking with it directly.
809         mount | grep "^$boot\>" > /dev/null
810         if [ $? = 0 ] ; then
811             echo 1>&2 "$PRG: $boot appears to be mounted! aborting."
812             return 1
813         fi
814
815         ## hmount is really more of a way to make sure we have a valid HFS
816         ## filesystem before proceding, and hcopy requires it...
817         hmount "$boot" > /dev/null
818         if [ $? != 0 ] ; then
819             echo 1>&2 "$PRG: $boot appears to have never had a bootstrap installed, please run mkofboot"
820             return 1
821         fi
822
823         ## must be explicit with target filename to avoid hfsutils
824         ## braindamage ("_" -> " " filename mangling) also avoid
825         ## ambiguity in the bootstrap partition.
826         if [ -n "$magicboot" ] ; then
827             [ "$VERBOSE" = 1 ] && echo "$INSTALLFIRST"
828             hcopy -r "$magicboot" :ofboot.b
829             if [ $? != 0 ] ; then
830                echo 1>&2 "$PRG: An error occured while writing to $boot"
831                return 1
832             fi
833         fi
834
835         [ "$VERBOSE" = 1 ] && echo "$INSTALLPRIMARY"
836         hcopy -r "$install" :"$BTFILE"
837         if [ $? != 0 ] ; then
838             echo 1>&2 "$PRG: An error occured while writing to $boot"
839             return 1
840         fi
841
842         [ "$VERBOSE" = 1 ] && echo "$PRG: Installing $bootconf onto $boot..."
843         hcopy -r "$bootconf" :"$CFFILE"
844         if [ $? != 0 ] ; then
845             echo 1>&2 "$PRG: An error occured while writing to $boot"
846             return 1
847         fi
848
849         if [ -n "$BSDLOADER" ] ; then
850             [ "$VERBOSE" = 1 ] && echo "$PRG: Installing $BSDLOADER onto $boot..."
851             hcopy -r "$BSDLOADER" :ofwboot
852             if [ $? != 0 ] ; then
853                 echo 1>&2 "$PRG: An error occured while writing to $boot"
854                 return 1
855             fi
856         fi
857
858         ## set all file's attributes, if a magicboot script exists it
859         ## gets the configured hfstype instead of yaboot (should be
860         ## "tbxi") so it gets booted by OF.
861         if [ -n "$magicboot" ] ; then
862             [ "$VERBOSE" = 1 ] && echo "$PRG: Setting attributes on $WRAP..."
863             hattrib -t "$hfstype" -c "$hfscreator" $INVISIBLE $LOCK :ofboot.b
864             if [ $? != 0 ] ; then
865                 echo 1>&2 "$PRG: Warning: error setting attributes on $WRAP"
866                 echo 1>&2 "$PRG: This is probably bad but we'll ignore it."
867             fi
868         fi
869
870         [ "$VERBOSE" = 1 ] && echo "$PRG: Setting attributes on $BTFILE..."
871         hattrib -t "$BTTYPE" -c "$hfscreator" $INVISIBLE $LOCK :"$BTFILE"
872         if [ $? != 0 ] ; then
873             echo 1>&2 "$PRG: Warning: error setting attributes on $BTFILE"
874             echo 1>&2 "$PRG: This is probably bad but we'll ignore it"
875         fi
876
877         [ "$VERBOSE" = 1 ] && echo "$PRG: Setting attributes on $CFFILE..."
878         hattrib -t "conf" -c "$hfscreator" $INVISIBLE $LOCK :"$CFFILE"
879         if [ $? != 0 ] ; then
880             echo 1>&2 "$PRG: Warning: error setting attributes on $CFFILE"
881             echo 1>&2 "$PRG: This is probably unimportant so we'll ignore it"
882         fi
883
884         if [ -n "$BSDLOADER" ] ; then
885             [ "$VERBOSE" = 1 ] && echo "$PRG: Setting attributes on ofwboot..."
886             hattrib -t "bsdb" -c "$hfscreator" $INVISIBLE $LOCK :ofwboot
887             if [ $? != 0 ] ; then
888                 echo 1>&2 "$PRG: Warning: error setting attributes on ofwboot"
889                 echo 1>&2 "$PRG: This is probably unimportant so we'll ignore it"
890             fi
891         fi
892
893         ## bless the root directory so OF will find the boot file
894         if [ "$bless" = yes ] ; then
895             [ "$VERBOSE" = 1 ] && echo "$PRG: Blessing $boot with Holy Penguin Pee..."
896             hattrib -b :
897             if [ $? != 0 ] ; then
898                 echo 1>&2 "$PRG: Warning: error blessing $boot"
899                 echo 1>&2 "$PRG: This is probably bad but we'll ignore it"
900             fi
901         fi
902
903         ## clean up the ~/.hcwd file hmount creates
904         humount "$boot" > /dev/null
905         sync ; sync
906
907         ## use explicit filename if we don't bless.
908         if [ "$bless" = yes ] ; then
909             local OFFILE='\\:tbxi'
910         else
911             if [ -n "$magicboot" ] ; then
912                 local OFFILE=ofboot.b
913             else
914                 local OFFILE="$BTFILE"
915             fi
916         fi
917
918         ## update the boot-device variable in OF nvram.
919         if [ "$nonvram" = 0 ] ; then
920             [ "$VERBOSE" = 1 ] && echo "$PRG: Updating OpenFirmware boot-device variable in nvram..."
921             [ "$DEBUG" = 1 ] && echo 1>&2 "$PRG: DEBUG: boot-device=${ofboot},${OFFILE}"
922             nvsetenv boot-device "${ofboot},${OFFILE}"
923             if [ $? != 0 ] ; then
924                 echo 1>&2 "$PRG: An error occured while updating nvram, we'll ignore it"
925             fi
926         fi
927
928     else
929         echo 1>&2 "$PRG: mtools support is not implemented"
930         echo 1>&2 "$PRG: Use --mount or add \`usemount' to $CONF"
931         return 1
932     fi
933
934     return 0
935 }
936
937 ## used by mnt_install so mntpoint= can be supported in a cleaner way.
938 mnt()
939 {
940     ## we can even create bootstrap filesystem images directly if you
941     ## ever wanted too.
942     if [ -f "$boot" ] ; then
943         local loop=",loop"
944     fi
945
946     if [ -e "$TMP/bootstrap.$$" ] ; then
947         echo 1>&2 "$PRG: $TMP/bootstrap.$$ exists, aborting."
948         return 1
949     fi
950
951     mkdir -m 700 "$TMP/bootstrap.$$"
952     if [ $? != 0 ] ; then
953         echo 1>&2 "$PRG: Could not create mountpoint directory, aborting."
954         return 1
955     fi
956
957     mount | grep "^$boot\>" > /dev/null
958     if [ $? = 0 ] ; then
959         echo 1>&2 "$PRG: $boot appears to be mounted! aborting."
960         return 1
961     fi
962
963     [ "$VERBOSE" = 1 ] && echo "$PRG: Mounting $boot..."
964     mount -t "$fstype" -o rw,umask=077$loop "$boot" "$TMP/bootstrap.$$"
965     if [ $? != 0 ] ; then
966         echo 1>&2 "$PRG: An error occured mounting $boot"
967         return 1
968     fi
969
970     ## catch signals, set here to avoid umounting something we did not
971     ## mount. cleanup done by trap 0.
972     trap "umount $boot ; exit 129" 1
973     trap "echo 1>&2 $SIGINT ; umount $boot ; exit 130" 2
974     trap "umount $boot ; exit 131" 3
975     trap "umount $boot ; exit 143" 15
976
977     TARGET="$TMP/bootstrap.$$"
978     return 0
979 }
980
981 ## umnt funtion which checks whether we mounted anything or not, for
982 ## mntpoint= this makes the code below cleaner IMO.
983 umnt()
984 {
985     if [ -z "$mntpoint" ] ; then
986         [ "$1" = failure ] && echo 1>&2 "$PRG: Attempting to umount $boot..."
987         umount "$2"
988         if [ $? != 0 ] ; then
989             echo 1>&2 "$PRG: umount of $boot failed!"
990             return 1
991         else
992             [ "$1" = failure ] && echo 1>&2 "$PRG: umount successfull"
993             return 0
994         fi
995     else
996         return 0
997     fi
998 }
999
1000 ## Use kernel filesytem drivers to mount the bootstrap partition like
1001 ## any other filesystem and copy the files there with standard un*x
1002 ## utilities.
1003 mnt_install()
1004 {
1005     local BTFILE=yaboot
1006   
1007     ## msdosfs is broken, yaboot may not support this filename.
1008     if [ "$fstype" = msdos ] ; then
1009         local CFFILE=yaboot.cnf
1010     else
1011         local CFFILE=yaboot.conf
1012     fi
1013
1014     if [ -n "$magicboot" ] ; then
1015         local WRAP="${magicboot##*/}"
1016     fi
1017
1018     ## set verbose messages here so they don't show temporary file paths
1019     local INSTALLFIRST="$PRG: Installing first stage bootstrap $magicboot onto $boot..."
1020     local INSTALLPRIMARY="$PRG: Installing primary bootstrap $install onto $boot..."
1021
1022     ## repoint magicboot as the real first stage loader if using the
1023     ## modern automatic generating ofboot.b.
1024     if [ -n "$FIRST" ] ; then
1025         magicboot="$FIRST"
1026         [ "$DEBUG" = 1 ] && echo 1>&2 "$PRG: DEBUG: set magicboot to $FIRST"
1027     fi
1028
1029     ## gross hack, add note section for IBM CHRP
1030     if [ "$ADDNOTE" = yes ] ; then
1031         hack_yaboot || return 1
1032     fi
1033
1034     ## call mnt() function to take care of mounting filesystem if needed
1035     if [ -z "$mntpoint" ] ; then
1036         mnt || return 1
1037     else
1038         TARGET="$mntpoint"
1039     fi
1040
1041     ## this is probably insecure on modern filesystems, but i think
1042     ## safe on crippled hfs/dosfs. user should ensure mntpoint= is safe.
1043     if [ -n "$magicboot" ] ; then
1044         [ "$VERBOSE" = 1 ] && echo "$INSTALLFIRST"
1045         cp -f "$magicboot" "$TARGET/ofboot.b"
1046         if [ $? != 0 ] ; then
1047             echo 1>&2 "$PRG: An error occured while writing to $boot"
1048             umnt failure "$TARGET"
1049             return 1
1050         fi
1051     fi
1052
1053     [ "$VERBOSE" = 1 ] && echo "$INSTALLPRIMARY"
1054     cp -f "$install" "$TARGET/$BTFILE"
1055     if [ $? != 0 ] ; then
1056         echo 1>&2 "$PRG: An error occured while writing to $boot"
1057         umnt failure "$TARGET"
1058         return 1
1059     fi
1060
1061     [ "$VERBOSE" = 1 ] && echo "$PRG: Installing $bootconf onto $boot..."
1062     cp -f "$bootconf" "$TARGET/$CFFILE"
1063     if [ $? != 0 ] ; then
1064         echo 1>&2 "$PRG: An error occured while writing to $boot"
1065         umnt failure "$TARGET"
1066         return 1
1067     fi
1068
1069     if [ -n "$BSDLOADER" ] ; then
1070         [ "$VERBOSE" = 1 ] && echo "$PRG: Installing $BSDLOADER onto $boot..."
1071         cp -f "$BSDLOADER" "$TARGET/ofwboot"
1072         if [ $? != 0 ] ; then
1073             echo 1>&2 "$PRG: An error occured while writing to $boot"
1074             umnt failure "$TARGET"
1075             return 1
1076         fi
1077     fi
1078
1079     if [ "$protect" = yes ] ; then
1080         [ "$VERBOSE" = 1 ] && echo "$PRG: Setting read-only attributes..."
1081         chmod a-w "$TARGET/$BTFILE"
1082         chmod a-w "$TARGET/$CFFILE"
1083         if [ -n "$magicboot" ] ; then
1084             chmod a-w "$TARGET/ofboot.b"
1085         fi
1086         if [ -n "$BSDLOADER" ] ; then
1087             chmod a-w "$TARGET/ofwboot"
1088         fi
1089     fi
1090
1091     sync ; sync
1092     umnt success "$TARGET" || return 1
1093
1094     ## make variable with a \ to avoid shell fsckage.  ugly ugly ugly.
1095     local BS='\'
1096     if [ -n "$magicboot" ] ; then
1097         [ -n "$OFDIR" ] && OFDIR="${BS}${OFDIR}${BS}"
1098         local OFFILE="${OFDIR}ofboot.b"
1099     else
1100         [ -n "$OFDIR" ] && OFDIR="${BS}${OFDIR}${BS}"
1101         local OFFILE="${OFDIR}${BTFILE}"
1102     fi
1103
1104     ## update the boot-device variable in OF nvram.
1105     if [ "$nonvram" = 0 ] ; then
1106         [ "$VERBOSE" = 1 ] && echo "$PRG: Updating OpenFirmware boot-device variable in nvram..."
1107         [ "$DEBUG" = 1 ] && echo 1>&2 "$PRG: DEBUG: boot-device=${ofboot},${OFFILE}"
1108         nvsetenv boot-device "${ofboot},${OFFILE}"
1109         if [ $? != 0 ] ; then
1110             echo 1>&2 "$PRG: An error occured while updating nvram, we'll ignore it"
1111         fi
1112     else
1113         echo 1>&2 "$PRG: Warning: You must manually configure OpenFirmware to boot."
1114     fi
1115
1116     return 0
1117 }
1118
1119 ## raw installation, for IBM RS/6000 hardware, yaboot is dded to the
1120 ## bootstrap partition. 
1121 raw_install()
1122 {
1123     ## make sure the device is not mounted as a filesystem before
1124     ## we start mucking with it directly.
1125     mount | grep "^$boot\>" > /dev/null
1126     if [ $? = 0 ] ; then
1127         echo 1>&2 "$PRG: $boot appears to be mounted! aborting."
1128         return 1
1129     fi
1130
1131     ## set verbosity message before munging the yaboot pathname
1132     local INSTALLPRIMARY="$PRG: Installing primary bootstrap $install onto $boot..."
1133
1134     ## gross hack, add note section for IBM CHRP
1135     if [ "$ADDNOTE" = yes ] ; then
1136         hack_yaboot || return 1
1137     fi
1138
1139     [ "$VERBOSE" = 1 ] && echo "$INSTALLPRIMARY"
1140     dd if=/dev/zero of="$boot" bs=512 count=1600 > /dev/null 2>&1
1141     dd if="$install" of="$boot" bs=512 > /dev/null 2>&1
1142     if [ $? != 0 ] ; then
1143         echo 1>&2 "$PRG: Installation failed."
1144         return 1
1145     fi
1146     sync ; sync
1147     [ "$VERBOSE" = 1 ] && echo "$PRG: Installation successful"
1148 }
1149
1150 ## make sure the first stage ofboot generator is compatible.
1151 checkfirststage()
1152 {
1153     grep -q "^#%ybinscript-" "$magicboot" 2> /dev/null
1154     if [ "$?" = 0 ] ; then
1155         local magic=`grep "^#%ybinscript-" "$magicboot"`
1156         local ver="${magic##*-}"
1157         if [ "$ver" = "1.1" ] ; then
1158             FIRSTSTG=compat
1159             return 0
1160         else
1161             echo 1>&2 "$PRG: Incompatible version of first stage loader $magicboot.  aborting..."
1162             return 1
1163         fi
1164     else
1165         FIRSTSTG=old
1166         return 0
1167     fi
1168 }
1169
1170 ## build the first stage loader.
1171 mkfirststage()
1172 {
1173     ## must have 7 backslashes to == \\ printf + shell = bizarre... or,
1174     ## make special variable to contain a \ (need \\ to make \) to work
1175     ## around echo -e -n brokeness.
1176     local BS='\\'
1177     local OS=1
1178
1179     ## deal with mntpoint=
1180     [ -n "$OFDIR" ] && local OFDIR="${BS}${OFDIR}${BS}"
1181
1182     ## some misguided people insist on installing OSX on
1183     ## HorribleFileSystem+ instead of UFS, as a result MacOS deblesses
1184     ## OSX, making it unbootable. if apple localizes the filesystem hierarchy again screw it.
1185     [ "$brokenosx" = yes ] && local OSXBOOT="${BS}System${BS}Library${BS}CoreServices${BS}BootX"
1186     [ "$brokenosx" = no ] && local OSXBOOT="${BS}${BS}:tbxi"
1187
1188     ## assign variables for configured menu options.
1189     [ "$usemount" = no -a "$bless" = yes ] && local YB="yaboot GNU l $ofboot ,${BS}${BS}yaboot"
1190     [ "$usemount" = yes -o "$bless" = no ] && local YB="yaboot GNU l $ofboot ,${OFDIR}yaboot"
1191     [ -n "$bsd" ] && OS="$(($OS + 1))" && local BSD="ybsd BSD b $ofboot ,${BS}${BS}ofwboot/$bsd"
1192     [ -n "$macos" ] && OS="$(($OS + 1))" && local MAC="macos MacOS m $macos ,${BS}${BS}:tbxi"
1193     [ -n "$macosx" ] && OS="$(($OS + 1))" && local MX="macosx MacOSX x $macosx ,${OSXBOOT}"
1194     [ -n "$darwin" ] && OS="$(($OS + 1))" && local DW="darwin Darwin d $darwin ,${BS}${BS}:tbxi"
1195     [ "$cdrom" = yes ] && OS="$(($OS + 1))" && local CD="cd CDROM c cd: ,${BS}${BS}:tbxi"
1196     [ "$network" = yes ] && OS="$(($OS + 1))" && local NET="net Network n enet: 0"
1197     [ "$of" = yes ] && OS="$(($OS + 1))" && local OF="of OpenFirmware o quit now"
1198     [ "$DEBUG" = 1 ] && echo 1>&2 "$PRG: DEBUG: OS=$OS"
1199
1200     ## call ofboot,
1201     ## Usage: OS-count defaultos timeout fgc bgc osname oslabel oskey osdev osfile ...
1202     [ "$DEBUG" = 1 ] && $PRINTF 1>&2 "$PRG: DEBUG: /bin/sh $magicboot $OS $defaultos $delay $fbc $bgc $YB $BSD $MAC $MX $DW $CD $NET $OF\n"
1203     FIRST="$(/bin/sh "$magicboot" "$OS" "$defaultos" "$delay" $fgc $bgc ${YB} ${BSD} ${MAC} ${MX} ${DW} ${CD} ${NET} ${OF})" || return 1
1204
1205     return 0
1206 }
1207
1208 ## mkofboot function.
1209 mkoffs()
1210 {
1211     mount | grep "^$boot\>" > /dev/null
1212     if [ $? = 0 ] ; then
1213         echo 1>&2 "$PRG: $boot appears to be mounted! aborting."
1214         return 1
1215     fi
1216
1217     case "$fstype" in
1218         hfs)
1219             [ "$VERBOSE" = 1 ] && echo "$PRG: Creating HFS filesystem on $boot..."
1220             if (command -v dd > /dev/null 2>&1) ; then
1221                 dd if=/dev/zero of="$boot" bs=512 count=1600 > /dev/null 2>&1
1222             fi
1223             hformat -l bootstrap "$boot" > /dev/null
1224             if [ $? != 0 ] ; then
1225                 echo 1>&2 "$PRG: HFS filesystem creation failed!"
1226                 return 1
1227             fi
1228             humount "$boot" ## otherwise we might get confused.
1229             return 0
1230             ;;
1231         msdos)
1232             if (command -v mkdosfs > /dev/null 2>&1) ; then
1233                 [ -x `command -v mkdosfs` ] || FAIL=1 ; else FAIL=1 ; fi
1234                 if [ "$FAIL" = 1 ] ; then
1235                     echo 1>&2 "$PRG: mkdosfs is not installed or cannot be found"
1236                     return 1
1237                 fi
1238
1239             [ "$VERBOSE" = 1 ] && echo "$PRG: Creating DOS filesystem on $boot..."
1240             if (command -v dd > /dev/null 2>&1) ; then
1241                 dd if=/dev/zero of="$boot" bs=512 count=1600 > /dev/null 2>&1
1242             fi  
1243             mkdosfs -n bootstrap "$boot" > /dev/null
1244             if [ $? != 0 ] ; then
1245                 echo 1>&2 "$PRG: DOS filesystem creation failed!"
1246                 return 1
1247             fi
1248             return 0
1249             ;;
1250     esac
1251 }
1252
1253 confirm()
1254 {
1255     if [ "$FORCE" = yes ] ; then
1256         return 0
1257     else
1258         echo 1>&2
1259         [ "$fstype" = raw ] && $PRINTF 1>&2 "$PRG: Overwrite contents of $boot with $install? [y/N] "
1260         [ "$fstype" != raw ] && $PRINTF 1>&2 "$PRG: Create $fstype filesystem on $boot? [y/N] "
1261         read ans
1262         case "$ans" in
1263             y|Y)
1264                 return 0
1265                 ;;
1266             *)
1267                 echo 1>&2 "$PRG: Abort."
1268                 return 2
1269                 ;;
1270         esac
1271     fi
1272 }
1273
1274 ## for fstype=raw check if an ELF binary has already been dded.
1275 luserck()
1276 {
1277     if [ "$(dd if="$boot" bs=1 skip=1 count=3 2>/dev/null)" = ELF ] ; then
1278         return 0
1279     else
1280         echo 1>&2 "$PRG: This partition has never had yaboot installed before, please run mkofboot"
1281         return 1
1282     fi
1283 }
1284
1285 mkconf()
1286 {
1287 ## defaults for this are defined at the beginning of the script with
1288 ## other variables.
1289
1290 echo \
1291 "## yaboot configuration file generated by ybin $VERSION
1292
1293 device=$device
1294 timeout=$timeout
1295
1296 image=$image
1297         label=$label
1298         partition=$partition
1299         root=$root
1300         read-only
1301 " > "$TMPCONF" || return 1
1302
1303 [ "$DEBUG" = 1 ] && $PRINTF 1>&2 "\nDEBUG: autoconf:\n----\n" && cat "$TMPCONF" 1>&2 && echo 1>&2 "----"
1304 return 0
1305 }
1306
1307 ## take out the trash.
1308 cleanup()
1309 {
1310     if [ -n "$TMPCONF" ] ; then rm -f "$TMPCONF" ; fi
1311     if [ -n "$FIRST" ] ; then rm -f "$FIRST" ; fi
1312     if [ -n "$TMPYABOOT" ] ; then rm -f "$TMPYABOOT" ; fi
1313     if [ -d "$TMP/bootstrap.$$" -a "$usemount" = yes ] ; then rmdir "$TMP/bootstrap.$$" ; fi
1314     return 0
1315 }
1316
1317 ##########
1318 ## Main ##
1319 ##########
1320
1321 ## absurdly bloated case statement to parse command line options.
1322 if [ $# != 0 ] ; then
1323     while true ; do
1324         case "$1" in 
1325             -V|--version)
1326                 version
1327                 exit 0
1328                 ;;
1329             -h|--help)
1330                 usage
1331                 exit 0
1332                 ;;
1333             --debug)
1334                 DEBUG=1
1335                 shift
1336                 ;;
1337             -v|--verbose)
1338                 VERBOSE=1
1339                 shift
1340                 ;;
1341             -f|--force)
1342                 FORCE=yes
1343                 shift
1344                 ;;
1345             -b|--boot)
1346                 if [ -n "$2" ] ; then
1347                     boot="$2"
1348                     ARGBT=1
1349                     shift 2
1350                 else
1351                     echo 1>&2 "$PRG: option requires an argument $1"
1352                     echo 1>&2 "Try \`$PRG --help' for more information."
1353                     exit 1
1354                 fi
1355                 ;;
1356             -o|--ofboot)
1357                 if [ -n "$2" ] ; then
1358                     ofboot="$2"
1359                     ARGOB=1
1360                     shift 2
1361                 else
1362                     echo 1>&2 "$PRG: option requires an argument $1"
1363                     echo 1>&2 "Try \`$PRG --help' for more information."
1364                     exit 1
1365                 fi
1366                 ;;
1367             -i|--install)
1368                 if [ -n "$2" ] ; then
1369                     install="$2"
1370                     ARGBF=1
1371                     shift 2
1372                 else
1373                     echo 1>&2 "$PRG: option requires an argument $1"
1374                     echo 1>&2 "Try \`$PRG --help' for more information."
1375                     exit 1
1376                 fi
1377                 ;;
1378             -C|--config)
1379                 if [ -n "$2" ] ; then
1380                     CONF="$2"
1381                     bootconf="$2"
1382                     ERR=" Error in $CONF:"
1383                     shift 2
1384                 else
1385                     echo 1>&2 "$PRG: option requires an argument $1"
1386                     echo 1>&2 "Try \`$PRG --help' for more information."
1387                     exit 1
1388                 fi
1389                 ;;
1390             -m|--magicboot)
1391                 if [ -n "$2" ] ; then
1392                     magicboot="$2"
1393                     ARGWP=1
1394                     shift 2
1395                 else
1396                     echo 1>&2 "$PRG: option requires an argument $1"
1397                     echo 1>&2 "Try \`$PRG --help' for more information."
1398                     exit 1
1399                 fi
1400                 ;;
1401             --filesystem)
1402                 if [ -n "$2" ] ; then
1403                     fstype="$2"
1404                     ARGFS=1
1405                     shift 2
1406                 else
1407                     echo 1>&2 "$PRG: option requires an argument $1"
1408                     echo 1>&2 "Try \`$PRG --help' for more information."
1409                     exit 1
1410                 fi
1411                 ;;
1412             --nobless)
1413                 bless=no
1414                 ARGBS=1
1415                 shift
1416                 ;;
1417             -M|--mount)
1418                 usemount=yes
1419                 ARGMT=1
1420                 shift
1421                 ;;
1422             --protect)
1423                 protect=yes
1424                 ARGPT=1
1425                 shift
1426                 ;;
1427             --hide)
1428                 hide=yes
1429                 ARGHD=1
1430                 shift
1431                 ;;
1432             --nonvram)
1433                 nonvram=1
1434                 ARGNV=1
1435                 shift
1436                 ;;
1437             --device)
1438                 if [ -n "$2" ] ; then
1439                     device="$2"
1440                     bootconf=auto
1441                     echo 1>&2 "$PRG: WARNING: Deprecated option --device"
1442                     shift 2
1443                 else
1444                     echo 1>&2 "$PRG: option requires an argument $1"
1445                     echo 1>&2 "Try \`$PRG --help' for more information."
1446                     exit 1
1447                 fi
1448                 ;;
1449             --timeout)
1450                 if [ -n "$2" ] ; then
1451                     timeout="$2"
1452                     bootconf=auto
1453                     echo 1>&2 "$PRG: WARNING: Deprecated option --device"
1454                     shift 2
1455                 else
1456                     echo 1>&2 "$PRG: option requires an argument $1"
1457                     echo 1>&2 "Try \`$PRG --help' for more information."
1458                     exit 1
1459                 fi
1460                 ;;
1461             --image)
1462                 if [ -n "$2" ] ; then
1463                     image="$2"
1464                     bootconf=auto
1465                     echo 1>&2 "$PRG: WARNING: Deprecated option --device"
1466                     shift 2
1467                 else
1468                     echo 1>&2 "$PRG: option requires an argument $1"
1469                     echo 1>&2 "Try \`$PRG --help' for more information."
1470                     exit 1
1471                 fi
1472                 ;;
1473             --label)
1474                 if [ -n "$2" ] ; then
1475                     label="$2"
1476                     bootconf=auto
1477                     echo 1>&2 "$PRG: WARNING: Deprecated option --device"
1478                     shift 2
1479                 else
1480                     echo 1>&2 "$PRG: option requires an argument $1"
1481                     echo 1>&2 "Try \`$PRG --help' for more information."
1482                     exit 1
1483                 fi
1484                 ;;
1485             --partition)
1486                 if [ -n "$2" ] ; then
1487                     partition="$2"
1488                     bootconf=auto
1489                     echo 1>&2 "$PRG: WARNING: Deprecated option --device"
1490                     shift 2
1491                 else
1492                     echo 1>&2 "$PRG: option requires an argument $1"
1493                     echo 1>&2 "Try \`$PRG --help' for more information."
1494                     exit 1
1495                 fi
1496                 ;;
1497             --root)
1498                 if [ -n "$2" ] ; then
1499                     root="$2"
1500                     bootconf=auto
1501                     echo 1>&2 "$PRG: WARNING: Deprecated option --device"
1502                     shift 2
1503                 else
1504                     echo 1>&2 "$PRG: option requires an argument $1"
1505                     echo 1>&2 "Try \`$PRG --help' for more information."
1506                     exit 1
1507                 fi
1508                 ;;
1509             "")
1510                 break
1511                 ;;
1512             *)
1513                 echo 1>&2 "$PRG: unrecognized option \`$1'"
1514                 echo 1>&2 "Try \`$PRG --help' for more information."
1515                 exit 1
1516                 ;;
1517         esac
1518     done
1519 fi
1520
1521 ## check that specified config file exists, unless its /dev/null in
1522 ## which case we assume all options are done on the command line.
1523 if [ "$CONF" = /dev/null ] ; then
1524     true
1525 else
1526     confexist || exit 1
1527 fi
1528
1529 ## if there is no config file use the automatic generation to make a
1530 ## generic yaboot.conf. do this before the confcheck to avoid wierd errors.
1531 if [ "$bootconf" = /dev/null ] ; then
1532     if (command -v yabootconfig > /dev/null 2>&1) ; then
1533         echo 1>&2 "$PRG: Warning: no /etc/yaboot.conf, running yabootconfig to make one"
1534         yabootconfig --noinstall --quiet
1535         if [ $? != 0 ] ; then
1536             echo 1>&2 "$PRG: yabootconfig failed, please supply a valid /etc/yaboot.conf"
1537             echo 1>&2 "$PRG: You may also use $PRG's --boot, --image, --partition, and --device switches"
1538             echo 1>&2 "$PRG: These switches will cause $PRG to generate a basic yaboot.conf on the fly"
1539             exit 1
1540         else
1541             CONF=/etc/yaboot.conf
1542             bootconf=$CONF
1543             ERR=" Error in $CONF:"
1544             confexist || exit 1
1545         fi
1546     fi
1547 fi
1548
1549 ## Checks if each option was defined on the command line, and if so
1550 ## don't read it from the configuration file. this avoids
1551 ## configuration options from being set null, as well as command line
1552 ## options from being clobbered.
1553 [ "$ARGBT" != 1 -a $(parseconf ck boot) = 0 ] && boot=`parseconf str boot`
1554 [ "$ARGOB" != 1 -a $(parseconf ck ofboot) = 0 ] && ofboot=`parseconf str ofboot`
1555 [ "$ARGBF" != 1 -a $(parseconf ck install) = 0 ] && install=`parseconf str install`
1556 [ "$ARGWP" != 1 -a $(parseconf ck magicboot) = 0 ] && magicboot=`parseconf str magicboot`
1557 [ "$ARGMT" != 1 -a $(parseconf flag usemount) = 0 ] && usemount=yes
1558 [ "$ARGFS" != 1 -a $(parseconf ck fstype) = 0 ] && fstype=`parseconf str fstype`
1559 [ "$ARGBS" != 1 -a $(parseconf flag nobless) = 0 ] && bless=no
1560 [ "$ARGPT" != 1 -a $(parseconf flag protect) = 0 ] && protect=yes
1561 [ "$ARGHD" != 1 -a $(parseconf flag hide) = 0 ] && hide=yes
1562 [ "$ARGNV" != 1 -a $(parseconf flag nonvram) = 0 ] && nonvram=1
1563 [ $(parseconf ck hfstype) = 0 ] && hfstype=`parseconf str hfstype`
1564 [ $(parseconf ck hfscreator) = 0 ] && hfscreator=`parseconf str hfscreator`
1565 [ $(parseconf ck mntpoint) = 0 ] && mntpoint=`parseconf str mntpoint`
1566 [ $(parseconf ck delay) = 0 ] && delay=`parseconf str delay`
1567 [ $(parseconf ck timeout) = 0 ] && timeout=`parseconf str timeout`
1568 [ $(parseconf ck bsd) = 0 ] && bsd=`parseconf str bsd`
1569 [ $(parseconf ck macos) = 0 ] && macos=`parseconf str macos`
1570 [ $(parseconf ck macosx) = 0 ] && macosx=`parseconf str macosx`
1571 [ $(parseconf ck darwin) = 0 ] && darwin=`parseconf str darwin`
1572 [ $(parseconf ck defaultos) = 0 ] && defaultos=`parseconf str defaultos`
1573 [ $(parseconf ck fgcolor) = 0 ] && fgcolor=`parseconf str fgcolor`
1574 [ $(parseconf ck bgcolor) = 0 ] && bgcolor=`parseconf str bgcolor`
1575 [ $(parseconf ck icon) = 0 ] && export YBINOFICON=`parseconf str icon`
1576 [ $(parseconf flag enablecdboot) = 0 ] && cdrom=yes
1577 [ $(parseconf flag enablenetboot) = 0 ] && network=yes
1578 [ $(parseconf flag enableofboot) = 0 ] && of=yes
1579 [ $(parseconf flag brokenosx) = 0 ] && brokenosx=yes
1580
1581 ## ffs!! rtfm! foad!
1582 if [ "$boot" = unconfigured ] ; then
1583     echo 1>&2 "$PRG: You must specify the device for the bootstrap partition. (ie: boot=/dev/hdaX)"
1584     echo 1>&2 "$PRG: Try \`$PRG --help' for more information."
1585     exit 1
1586 fi
1587
1588 ## if there is still no config file use the automatic generation to make a
1589 ## generic yaboot.conf. do this before the confcheck to avoid wierd errors.
1590 if [ "$bootconf" = /dev/null ] ; then
1591     echo 1>&2 "$PRG: Warning: no yaboot.conf, using generic configuration."
1592     bootconf=auto
1593 fi
1594
1595 ## mntpoint is incompatible with mkofboot.
1596 if [ "$PRG" = mkofboot -a -n "$mntpoint" ] ; then
1597     echo 1>&2 "$PRG: Cannot be used with \`mntpoint='"
1598     exit 1
1599 fi
1600
1601 ## validate configuration for sanity.
1602 checkconf || exit 1
1603
1604 ## check that we can use ofpath, its only needed for magicboot script
1605 ## building and nvram updates.
1606 if [ -n "$magicboot" -o "$nonvram" = 0 ] ; then
1607     if [ -z "$ofboot" -o -n "$macos" -o -n "$macosx" -o -n "$darwin" ] ; then
1608         if (command -v ofpath > /dev/null 2>&1) ; then
1609             [ -x `command -v ofpath` ]
1610             if [ $? != 0 ] ; then
1611                 echo 1>&2 "$PRG: ofpath could not be found, aborting."
1612                 exit 1
1613             fi
1614         else
1615             echo 1>&2 "$PRG: ofpath could not be found, aborting."
1616             exit 1
1617         fi
1618     fi
1619 fi
1620
1621 ## if password is set in yaboot.conf make sure permissions on that
1622 ## file are safe, warn if not.
1623 if (grep -q '^[[:space:]]*password[[:space:]]*=' "$bootconf" > /dev/null 2>&1) ; then
1624     permcheck
1625 fi
1626
1627 ## check if we are root if needed.
1628 if [ "$usemount" = yes -a -z "$mntpoint" ] ; then
1629     if [ `id -u` != 0 ] ; then
1630         echo 1>&2 "$PRG: \`usemount' requires root privileges, go away."
1631         exit 1
1632     fi
1633 fi
1634
1635 if [ "$fstype" = hfs ] ; then
1636     checkhfsutils
1637     if [ $? != 0 ] ; then
1638         echo 1>&2 "$PRG: hfsutils is not installed or cannot be found"
1639         echo 1>&2 "$PRG: Try --mount if `uname -sr` supports HFS"
1640         exit 1
1641     fi
1642 fi
1643
1644 ## convert unix device nodes to OpenFirmware pathnames
1645 if [ -n "$magicboot" -o "$nonvram" = 0 ] ; then
1646     convertpath || exit 1
1647 fi
1648
1649 ## yaboot.conf autogeneration. MUST have secure mktemp to
1650 ## avoid race conditions. Debian's mktemp qualifies.
1651 if [ "$bootconf" = auto ] ; then
1652     TMPCONF=`mktemp -q "$TMP/$PRG.XXXXXX"`
1653     if [ $? != 0 ] ; then
1654         echo 1>&2 "$PRG: Could not create temporary file, aborting."
1655         exit 1
1656     fi
1657
1658     mkconf
1659     if [ $? != 0 ] ; then
1660         echo 1>&2 "$PRG: An error occured generating yaboot.conf, aborting."
1661         exit 1
1662     fi
1663
1664     bootconf="$TMPCONF"
1665 fi
1666
1667 if [ -n "$magicboot" ] ; then
1668     checkfirststage || exit 1
1669     if [ "$FIRSTSTG" = compat ] ; then
1670         mkfirststage
1671         if [ $? != 0 ] ; then
1672             echo 1>&2 "$PRG: An error occured while building first stage loader.  aborting..."
1673             exit 1
1674         fi
1675     fi
1676 fi
1677
1678 case "$PRG" in
1679     ybin)
1680         case "$usemount" in
1681             no)
1682                 if [ "$fstype" = raw ] ; then
1683                     luserck || exit 1
1684                     raw_install || exit 1
1685                 else
1686                     util_install || exit 1
1687                 fi
1688                 exit 0
1689                 ;;
1690             yes)
1691                 mnt_install || exit 1
1692                 exit 0
1693                 ;;
1694         esac
1695         ;;
1696     mkofboot)
1697         case "$usemount" in
1698             no)
1699                 ## its not nice to erase the partition and then bail!
1700                 if [ "$fstype" = msdos ] ; then
1701                     echo 1>&2 "$PRG: mtools support is not implemented"
1702                     echo 1>&2 "$PRG: Use --mount or add \`usemount' to $CONF"
1703                     exit 1
1704                 fi
1705                 confirm || exit 2
1706                 if [ "$fstype" = raw ] ; then
1707                     raw_install || exit 1
1708                 else
1709                     mkoffs || exit 1
1710                     util_install || exit 1
1711                 fi
1712                 [ "$VERBOSE" = 1 ] && echo "$PRG: Installation complete."
1713                 exit 0
1714                 ;;
1715             yes)
1716                 confirm || exit 2
1717                 mkoffs || exit 1
1718                 mnt_install || exit 1
1719                 [ "$VERBOSE" = 1 ] && echo "$PRG: Installation complete."
1720                 exit 0
1721                 ;;
1722         esac
1723         ;;
1724 esac
1725
1726 exit 0