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