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