aboutsummaryrefslogtreecommitdiff
path: root/installworld_oldk
blob: 4eb4c479da46aa7adc797b2ca8099d2254ab2092 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
#!/bin/sh
# -------+---------+---------+---------+---------+---------+---------+---------+
# Copyright (c) 2004  - Garance Alistair Drosehn <gad@FreeBSD.org>.
#
# All rights reserved.
#
#  Redistribution and use in source and binary forms, with or without
#  modification, are permitted provided that the following conditions
#  are met:
#  1. Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer.
#  2. Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
#
#  THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
#  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
#  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
#  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
#  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
#  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
#  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
#  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
#  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
#  SUCH DAMAGE.
#
# -------+---------+---------+---------+---------+---------+---------+---------+
# $FreeBSD$
# -------+---------+---------+---------+---------+---------+---------+---------+
#
#   This script does a 'make installworld' using the *old* versions of all
# commands to do the work.  It expects that the new kernel has been installed,
# but that the system has not been rebooted (and is thus still running on the
# previous kernel).  This is useful when a major incompatible change is made,
# and you want to do an installworld that uses NFS-mounted directories for
# /usr/src and /usr/obj.  This script was written for the change to
# 64-bit time_t on FreeBSD/Sparc64, but it is not specific to that.
#
#   IMPORTANT: This script does require that you are NOT YET running on
# the new kernel that matches the 'world' that you want to install.
#
# -------+---------+---------+---------+---------+---------+---------+---------+

#   This script expects that it will be run from /usr/src, or an
#   equivalent (perhaps NFS-mounted) directory.
if [ -f MAINTAINERS -a -f UPDATING -a -f Makefile -a -f Makefile.inc1 ] ; then
    SOURCE_BWDIR="`make -V .OBJDIR`"
else
    echo "This script must be run from /usr/src!  (or equivalent)"
    exit 1
fi

DOMAKE=
DOMINI=
SETMINPATH=
SYMLINKS=
VERBOSE=
BADOPT=
while test $# != 0
do
    case "$1" in
    -M)   SETMINPATH=yes ;;
    -N)   DOMINI=no ;;
    -S)   echo "-S (symlinks) is ignored in installworld_oldk." ;;
    -Y)   DOMINI=yes ;;
    -y)   DOMAKE=yes ;;
    -n)   DOMAKE=no ;;
    -v)   VERBOSE=yes ;;
    *)    echo "Invalid option: $1" ; BADOPT=yes ;;
    esac
    shift 1
done
if [ -n "$BADOPT" ] ; then
    exit 1
fi

echo "* + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - *"
echo "*  This script expects that a 'make installkernel' has already"
echo "*  been done, but that the system is still running the previous"
echo "*  kernel.  Ie, that you have not rebooted."
echo "*"
echo "*  Also note that this only does a PARTIAL installworld.  You"
echo "*  will still have to do a full installworld after rebooting."
echo "* + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - *"
echo ""

#   See if the user wants us to create a mini-/bin inside of the
#   newly-installed kernel.  These executables would only be used
#   *after* booting into the new kernel, so we want the new-world
#   versions of all files.
#   XXX - This is a idea which could be useful in many situations, but
#	it really should be implemented as an official make-target.
#	It would be particularly nice to make this a statically-linked
#	(and crunchgen-ed) collection of programs...
if [ -z "${DOMINI}" -a -z "${DOMAKE}" ] ; then
    echo "Do you want a mini-/bin in that newly-installed /boot/kernel? "
    read -p "(y/n) ? "  DOMINI remline
    echo " "
elif [ -z "${DOMINI}" ] ; then
    DOMINI="${DOMAKE}"
fi
if [ -n "`echo /y/yes/okay/ok/ | grep -i \"/${DOMINI}/\"`" ] ; then
    KERNBINDIR=/boot/kernel/bin
    if [ -e ${KERNBINDIR} ] ; then
        rm -Rf ${KERNBINDIR}
    fi
    mkdir -p ${KERNBINDIR}
    #   Much of this is done in a subshell, so values of DESTDIR, etc,
    #   will only be in effect for this section of the script.
    (
    DESTDIR=${KERNBINDIR}
    BINDIR=""
    NOINFO=YES
    NOMAN=YES
    export BINDIR DESTDIR NOINFO NOMAN
    MFLAG=
    for wantdir in bin/chflags bin/chmod bin/cp bin/ls bin/mkdir bin/mv bin/sh \
                   sbin/ifconfig sbin/mount sbin/mount_nfs sbin/reboot \
                   usr.bin/find usr.bin/xargs ; do
	if [ -n "$VERBOSE" ] ; then
	    echo ".. Installing ${wantdir} to mini-/bin"
	fi
        (cd ${wantdir} && make ${MFLAG} install >/dev/null )
	if [ $? -ne 0 ] ; then
	    echo "** Error while in ${wantdir} doing 'make install'"
	    echo "**       for DESTDIR=${KERNBINDIR}" 
	    exit 1
	fi
    done
    echo "Done building ${KERNBINDIR}"
    echo
    ) || exit 1
fi

#   Start out with no PATH at all.
PATH=

#   Where all the binaries should be coming from.
OW_BIN="/bin"
OW_SBIN="/sbin"
OW_UBIN="/usr/bin"
OW_USBIN="/usr/sbin"
OW_GUBIN="/usr/bin"

MKTEMPCMD=/usr/bin/mktemp

#   I intentionally prefer to have a shorter name here...  We just need a
#   unique name, we're not likely to be under attack during installworld!
TMPHOLD=`"${MKTEMPCMD}" -q -d ${TMPDIR:-/tmp}/install-oldk.XXX`
if [ $? -ne 0 ] ; then
    echo "** Unable to create temp program-holding directory"
    exit 1
fi

#   Set the most-restrictive value for PATH that the user is willing to
#   shoot for.  The more restrictive we are here, the more likely we
#   will catch all references to "unexpected" executables.
PATH=${TMPHOLD}:/sbin:/bin:/usr/sbin:/usr/bin
if [ -n "$SETMINPATH" ] ; then
    PATH=${TMPHOLD}
fi

#   Find the most-appropriate version of key commands for this script.
#   XXX - It would be nice if we could reliably find the exact kernel that
#	we booted up with, and check for the optional mini-/bin in it.
COPYCMD=/missing/cp
for chkexec in "/rescue/cp" /bin/cp ; do
    if [ -f "${chkexec}" ] ; then
        COPYCMD="${chkexec} -p"
        break
    fi
done
LINKCMD=/missing/ln
for chkexec in "/rescue/ln" /bin/ln ; do
    if [ -f "${chkexec}" ] ; then
        LINKCMD="${chkexec}"
        break
    fi
done
COPYINFO="Copying"

copy_exec () {
    srcdir="$1"
    cmdname="$2"
    alsoln="$3"
    srcfile="${srcdir}/${cmdname}"
    resfile="/rescue/${cmdname}"

    if [ -f "${resfile}" -a -x "${resfile}" ] ; then
        if [ -n "$VERBOSE" ] ; then
	    echo ".. Linking ${TMPHOLD}/RESCUE to ${cmdname}"
	fi
	${LINKCMD} "${TMPHOLD}/RESCUE" "${TMPHOLD}/${cmdname}"
	if [ $? -ne 0 ] ; then
	    echo "** Error Linking '${cmdname}'"
	    exit 1
	fi
    elif [ -f "${srcfile}" -a -x "${srcfile}" ] ; then
        if [ -n "$VERBOSE" ] ; then
	    echo ".. ${COPYINFO} ${srcfile}"
	fi
	${COPYCMD} "${srcfile}" "${TMPHOLD}"
	if [ $? -ne 0 ] ; then
	    echo "** Error ${COPYINFO} '${srcfile}'"
	    exit 1
	fi
    else
        echo "** Cannot find ${cmdname} in /rescue or ${srcdir}?"
        exit 1
    fi

    if [ -n "${alsoln}" ] ; then
	if [ -n "$VERBOSE" ] ; then
	    echo ".. Linking '${cmdname}' as '${alsoln}' "
	fi
	${LINKCMD} "${TMPHOLD}/${cmdname}" "${TMPHOLD}/${alsoln}"
	if [ $? -ne 0 ] ; then
	    echo "** Error Linking '${cmdname}'"
	    exit 1
	fi
    fi
}

# The programs listed in the following `do' loop are all the same programs
# that the standard 'installworld' target wants to make copies of, except
# that this has special-cases for `awk', `[', and `egrep'.  This script
# also adds the commands `cp', `install', `id' and `which', because those
# are also *used* by the standard `make installworld' target, although
# that target doesn't bother to make copies of those programs.  The `sleep'
# command is also added, but only because it is used in this script.  And
# `script' is included just because it can be useful when testing this script.
#
# Note that this means there will be two copies made of these files
# (because the 'make installworld' target is still going to copy them a
# second time).

#   Do the `cp' command first, because this script does so much with it.
#   This is done as a special case, because it's the initial program
#   from /rescue (if /rescue exists).
chkfile="/rescue/cp"
if [ -f "${chkfile}" -a -x "${chkfile}" ] ; then
    if [ -n "$VERBOSE" ] ; then
        echo ".. Copying ${chkfile} to 'RESCUE'"
    fi
    ${COPYCMD} "${chkfile}" "${TMPHOLD}/RESCUE"
fi
copy_exec "${OW_BIN}" cp

#   Do the `ln' command as the second one, for similar reasons.
copy_exec "${OW_BIN}" ln

#   Awk is also called 'nawk'
copy_exec "${OW_UBIN}" nawk awk

#   The `install' comand is not a special case in this script,
#   but it is in the installworld_newk script.
copy_exec "${OW_UBIN}" install

#   Worried about the extra disk space that this script uses up in /tmp?  Well,
#   just specify the -S option, and this script will create symlinks instead of
#   copying the files.  Note that the original files might be NFS-mounted, and
#   /tmp might be a memory-based file system, so the `installworld' might go
#   much faster when copies are done here instead of symlinks.
if [ -n "$SYMLINKS" ] ; then
    echo "The -S (symlinks) option is ignored in installworld_oldk"
    # COPYINFO="Linking to"
    # COPYCMD="ln -s"
    # LINKCMD="ln -s"
fi

for prog in cap_mkdb cat chflags chmod chown date \
            echo       find grep    make mkdir mtree mv \
            pwd_mkdb rm sed sh sysctl test true uname wc zic \
            hostname id ls sleep script umount which xargs
do
    gotmatch=
    for chkdir in "${OW_BIN}" "${OW_SBIN}" "${OW_UBIN}" "${OW_USBIN}"
    do
        if [ -f "${chkdir}/${prog}" -a -x "${chkdir}/${prog}" ] ; then
            gotmatch=yes
            copy_exec "${chkdir}" "${prog}"
            if [ $? -ne 0 ] ; then
                exit 1
            fi
            break
        fi
    done
    if [ -z "$gotmatch" ] ; then
        echo "** Did not find '${prog}' ?"
    fi
done

#   Special case to handle '[', which we know is the same as 'test'
if [ -x ${TMPHOLD}/test ] ; then
    if [ -n "$VERBOSE" ] ; then
        echo ".. Linking 'test' as '[' "
    fi
    ${LINKCMD} ${TMPHOLD}/test ${TMPHOLD}/[
fi
#   Special case for 'egrep', which is the same as 'grep'
if [ -x ${TMPHOLD}/grep ] ; then
    if [ -n "$VERBOSE" ] ; then
        echo ".. Linking 'grep' as 'egrep' "
    fi
    ${LINKCMD} ${TMPHOLD}/grep ${TMPHOLD}/egrep
fi

#   Have to duplicate the standard makefile, to make a few changes.

#   First find the setting of PATH.  Insert a line in front of that
#   which uses the (undocumented) .SHELL feature to get 'make' to
#   use the newer version of /bin/sh that we just made a copy of.
#   Then alter the PATH setting so that all make targets check our
#   directory of copied files first.  If '-M' was given, then have
#   a PATH setting that looks ONLY at our copied files.
#    
#   XXX - the .SHELL feature did NOT seem to work the way that I
#	wanted it to, but that is not a problem for now.  It can
#	be looked into at some later date...
nawk '/^PATH=/ { \
	    print "#   Try to get the make cmd to use an alternate /bin/sh." ; \
	    print ".SHELL : name=sh path=" TDIR "/sh"  ; \
	    print "" ; \
	    if (WANTMIN == "yes") \
	        sub(/^PATH *=[ \t]*.*/, "PATH=\t" TDIR ); \
	    else \
	        sub(/^PATH *=[ \t]*/, "PATH=\t" TDIR ":"); \
	    } \
      /-f Makefile.inc1/ { \
	    sub(/Makefile.inc1/, TDIR "/Makefile.inc1" ); \
	    } \
      { print $0 }' \
    "TDIR=${TMPHOLD}" "WANTMIN=${SETMINPATH}" Makefile > ${TMPHOLD}/Makefile

#   In the case of this script, we want the new libraries to be the
#   *last* things that are installed (since we will be running some
#   programs which expect the present libraries).  However, we do
#   still have the problem that 'make' explicitly uses /bin/sh, so
#   the install of 'bin' must be delayed to after those libraries.
#   [Someone recently committed a total restructuring of Makefile.inc1,
#   so the following  has to be setup such that it works with either
#   formats.  That's why it seems to be doing everything twice.]
nawk 'BEGIN { GOTSBIN = 0; } \
      /^# Put initial settings/ { \
	    print "#   Try to get the make cmd to use an alternate /bin/sh." ; \
	    print ".SHELL : name=sh path=" TDIR "/sh"  ; \
	    print "" ; \
	    } \
      /^SUBDIR=[\t ]*share\/info .*bin/ { \
	    print "#   Try to get the make cmd to use an alternate /bin/sh." ; \
	    print ".SHELL : name=sh path=" TDIR "/sh"  ; \
	    print "" ; \
	    } \
      /exists\(.*\/sbin\)/ { \
	    if (GOTSBIN == 0) { \
		GOTSBIN = 1;
		print "" ; \
		print "#   For installworld_oldk processing, forget" ; \
		print "#   all the subdirectories before sbin..."; \
		print "SUBDIR=" ; \
	        } \
	    } \
      /^SUBDIR\+=sbin/ { \
	    if (GOTSBIN == 0) { \
		GOTSBIN = 1;
		print "" ; \
		print "#   For installworld_oldk processing, forget" ; \
		print "#   all the subdirectories before sbin..."; \
		print "SUBDIR=" ; \
	        } \
	    } \
      /^# These are last, since it is/ { \
	    print "#   These dirs are done last for installworld_oldk." ; \
	    print ".if exists(${.CURDIR}/lib)" ; \
	    print "SUBDIR+= lib" ; \
	    print ".endif" ; \
	    print ".if exists(${.CURDIR}/libexec)" ; \
	    print "SUBDIR+= libexec"; \
	    print ".endif"; \
	    print ".if exists(${.CURDIR}/bin)" ; \
	    print "SUBDIR+= bin"; \
	    print ".endif"; \
	    } \
      /-f Makefile.inc1/ { \
	    sub(/Makefile.inc1/, TDIR "/Makefile.inc1" ); \
	    } \
     { print $0 } \
     END    { \
	    if (GOTSBIN == 0) { \
	        print "ERROR: No \"sbin\" match in Makefile.inc1" > "/dev/stderr"; \
	        } \
	    }' \
    "TDIR=${TMPHOLD}" Makefile.inc1 > "${TMPHOLD}/Makefile.inc1"

echo ""
echo "The key programs needed by 'make installworld' have been copied."
if [ -n "$VERBOSE" ] ; then
    ls -C ${TMPHOLD}
    echo ""
fi

# XXX - Add some "do-nothing" settings so that we won't clobber any
#	more than we need to.  I wish we could avoid having to set
#	them as environment variables, particularly for the case
#	where the user chooses to type in all the commands.  The
#	more a user has to type, the more chances for a typo...
NO_FORTRAN=yes
NO_RESCUE=yes
NOGAMES=yes
NOINFO=yes
NOMAN=yes
NOSHARE=yes
export NO_FORTRAN NO_RESCUE NOGAMES NOINFO NOMAN NOSHARE

#   The sparc64_installcheck will want this in the environment.
NEWSPARC_TIMETYPE=__int64_t
export NEWSPARC_TIMETYPE

# See if the user wants us to go ahead with 'installworld',
#     or just tell them what steps they need to do.
if [ -z "${DOMAKE}" ] ; then
    echo "Do you want to proceed with the abridged 'installworld'? "
    read -p "(y/n) ? "  DOMAKE remline
    echo " "
fi
if [ -n "`echo /y/yes/okay/ok/ | grep -i \"/${DOMAKE}/\"`" ] ; then
    echo "Okay then, this script has set:"
    echo "    NO_FORTRAN NO_RESCUE NOGAMES NOINFO NOMAN NOSHARE"
    echo "and:"
    echo "    NEWSPARC_TIMETYPE=__int64_t"
    echo "    PATH=${PATH}"
    echo "and will now execute the command:"
    echo "    make -f ${TMPHOLD}/Makefile installworld"
    sleep 4
    make -f ${TMPHOLD}/Makefile installworld
else
    echo "When you are ready to continue, enter the commands:"
    echo "    NO_FORTRAN=yes"
    echo "    NO_RESCUE=yes"
    echo "    NOGAMES=yes"
    echo "    NOINFO=yes"
    echo "    NOMAN=yes"
    echo "    NOSHARE=yes"
    echo "    export NO_FORTRAN NO_RESCUE NOGAMES NOINFO NOMAN NOSHARE"
    echo "    NEWSPARC_TIMETYPE=__int64_t"
    echo "    export NEWSPARC_TIMETYPE"
    echo "and:"
    echo "    PATH=${PATH}"
    echo "or:"
    echo "    PATH=${TMPHOLD}:\${PATH}"
    echo "and:"
    echo "    make -f ${TMPHOLD}/Makefile installworld"
fi