1258066Sjhb#!/bin/sh
2258066Sjhb#
3283927Sjhb# Copyright (c) 2013 Hudson River Trading LLC
4258066Sjhb# Written by: John H. Baldwin <jhb@FreeBSD.org>
5258066Sjhb# All rights reserved.
6258066Sjhb#
7258066Sjhb# Redistribution and use in source and binary forms, with or without
8258066Sjhb# modification, are permitted provided that the following conditions
9258066Sjhb# are met:
10258066Sjhb# 1. Redistributions of source code must retain the above copyright
11258066Sjhb#    notice, this list of conditions and the following disclaimer.
12258066Sjhb# 2. Redistributions in binary form must reproduce the above copyright
13258066Sjhb#    notice, this list of conditions and the following disclaimer in the
14258066Sjhb#    documentation and/or other materials provided with the distribution.
15258066Sjhb#
16258066Sjhb# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17258066Sjhb# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18258066Sjhb# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19258066Sjhb# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20258066Sjhb# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21258066Sjhb# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22258066Sjhb# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23258066Sjhb# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24258066Sjhb# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25258066Sjhb# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26258066Sjhb# SUCH DAMAGE.
27258066Sjhb#
28258066Sjhb# $FreeBSD$
29258066Sjhb
30258066Sjhb# Regression tests for the pre-world (-p) mode 
31258066Sjhb
32263221SjmmvFAILED=no
33258066SjhbWORKDIR=work
34258066Sjhb
35258066Sjhbusage()
36258066Sjhb{
37258066Sjhb	echo "Usage: preworld.sh [-s script] [-w workdir]"
38258066Sjhb	exit 1
39258066Sjhb}
40258066Sjhb
41258066Sjhb# Allow the user to specify an alternate work directory or script.
42258066SjhbCOMMAND=etcupdate
43258066Sjhbwhile getopts "s:w:" option; do
44258066Sjhb	case $option in
45258066Sjhb		s)
46258066Sjhb			COMMAND="sh $OPTARG"
47258066Sjhb			;;
48258066Sjhb		w)
49258066Sjhb			WORKDIR=$OPTARG
50258066Sjhb			;;
51258066Sjhb		*)
52258066Sjhb			echo
53258066Sjhb			usage
54258066Sjhb			;;
55258066Sjhb	esac
56258066Sjhbdone
57258066Sjhbshift $((OPTIND - 1))
58258066Sjhbif [ $# -ne 0 ]; then
59258066Sjhb	usage
60258066Sjhbfi
61258066Sjhb
62258066SjhbCONFLICTS=$WORKDIR/conflicts
63258066SjhbSRC=$WORKDIR/src
64258066SjhbOLD=$WORKDIR/current
65258066SjhbTEST=$WORKDIR/test
66258066Sjhb
67258066Sjhbbuild_trees()
68258066Sjhb{
69258066Sjhb
70259134Sjhb	# Populate trees with pre-world files and additional files
71258066Sjhb	# that should not be touched.
72258066Sjhb
73258066Sjhb	rm -rf $SRC $OLD $TEST $CONFLICTS
74258066Sjhb
75258066Sjhb	# Create the "old" source tree as the starting point
76258066Sjhb	mkdir -p $OLD/etc
77258066Sjhb	cat >> $OLD/etc/master.passwd <<EOF
78258066Sjhb#
79258066Sjhbroot::0:0::0:0:Charlie &:/root:/bin/csh
80258066Sjhbtoor:*:0:0::0:0:Bourne-again Superuser:/root:
81258066Sjhbdaemon:*:1:1::0:0:Owner of many system processes:/root:/usr/sbin/nologin
82258066Sjhboperator:*:2:5::0:0:System &:/:/usr/sbin/nologin
83258066Sjhb_dhcp:*:65:65::0:0:dhcp programs:/var/empty:/usr/sbin/nologin
84258066Sjhbuucp:*:66:66::0:0:UUCP pseudo-user:/var/spool/uucppublic:/usr/local/libexec/uucp/uucico
85258066Sjhbpop:*:68:6::0:0:Post Office Owner:/nonexistent:/usr/sbin/nologin
86258066Sjhbwww:*:80:80::0:0:World Wide Web Owner:/nonexistent:/usr/sbin/nologin
87258066Sjhbhast:*:845:845::0:0:HAST unprivileged user:/var/empty:/usr/sbin/nologin
88258066Sjhbnobody:*:65534:65534::0:0:Unprivileged user:/nonexistent:/usr/sbin/nologin
89258066SjhbEOF
90258066Sjhb	cat >> $OLD/etc/group <<EOF
91258066Sjhb#
92258066Sjhbwheel:*:0:root
93258066Sjhbdaemon:*:1:
94258066Sjhbkmem:*:2:
95258066Sjhbsys:*:3:
96258066Sjhbtty:*:4:
97258066Sjhboperator:*:5:root
98258066Sjhb_dhcp:*:65:
99258066Sjhbuucp:*:66:
100258066Sjhbdialer:*:68:
101258066Sjhbnetwork:*:69:
102258066Sjhbwww:*:80:
103258066Sjhbhast:*:845:
104258066Sjhbnogroup:*:65533:
105258066Sjhbnobody:*:65534:
106258066SjhbEOF
107258066Sjhb	cat >> $OLD/etc/inetd.conf <<EOF
108258066Sjhb# Yet another file
109258066SjhbEOF
110258066Sjhb
111258066Sjhb	# Copy the "old" source tree to the test tree and make local
112258066Sjhb	# modifications.
113258066Sjhb	cp -R $OLD $TEST
114258066Sjhb	sed -I "" -e 's/root::/root:<rpass>:/' $TEST/etc/master.passwd
115258066Sjhb	cat >> $TEST/etc/master.passwd <<EOF
116258066Sjhbjohn:<password>:1001:1001::0:0:John Baldwin:/home/john:/bin/tcsh
117258066Sjhbmessagebus:*:556:556::0:0:D-BUS Daemon User:/nonexistent:/usr/sbin/nologin
118258066Sjhbpolkit:*:562:562::0:0:PolicyKit User:/nonexistent:/usr/sbin/nologin
119258066Sjhbhaldaemon:*:560:560::0:0:HAL Daemon User:/nonexistent:/usr/sbin/nologin
120258066SjhbEOF
121258066Sjhb	awk '/wheel/ { printf "%s,john\n", $0; next } // { print }' \
122258066Sjhb	    $OLD/etc/group > $TEST/etc/group
123258066Sjhb	cat >> $TEST/etc/group <<EOF
124258066Sjhbjohn:*:1001:
125258066Sjhbmessagebus:*:556:
126258066Sjhbpolkit:*:562:
127258066Sjhbhaldaemon:*:560:
128258066SjhbEOF
129258066Sjhb	rm $TEST/etc/inetd.conf
130259134Sjhb	touch $TEST/etc/localtime
131258066Sjhb
132258066Sjhb	# Copy the "old" source tree to the new source tree and
133258066Sjhb	# make upstream modifications.
134258066Sjhb	cp -R $OLD $SRC
135258066Sjhb	sed -I "" -e '/:80:/i\
136258066Sjhbauditdistd:*:78:77::0:0:Auditdistd unprivileged user:/var/empty:/usr/sbin/nologin' \
137258066Sjhb	    $SRC/etc/master.passwd
138258066Sjhb	sed -I "" -e '/:80:/i\
139258066Sjhbaudit:*:77:' \
140258066Sjhb	    $SRC/etc/group
141258066Sjhb	cat >> $SRC/etc/inetd.conf <<EOF
142258066Sjhb# Making this larger
143258066SjhbEOF
144258066Sjhb}
145258066Sjhb
146258066Sjhb# $1 - relative path to file that should be missing from TEST
147258066Sjhbmissing()
148258066Sjhb{
149258066Sjhb	if [ -e $TEST/$1 -o -L $TEST/$1 ]; then
150258066Sjhb		echo "File $1 should be missing"
151263221Sjmmv		FAILED=yes
152258066Sjhb	fi
153258066Sjhb}
154258066Sjhb
155258066Sjhb# $1 - relative path to file that should be present in TEST
156258066Sjhbpresent()
157258066Sjhb{
158258066Sjhb	if ! [ -e $TEST/$1 -o -L $TEST/$1 ]; then
159258066Sjhb		echo "File $1 should be present"
160263221Sjmmv		FAILED=yes
161258066Sjhb	fi
162258066Sjhb}
163258066Sjhb
164258066Sjhb# $1 - relative path to regular file that should be present in TEST
165258066Sjhb# $2 - optional string that should match file contents
166258066Sjhb# $3 - optional MD5 of the flie contents, overrides $2 if present
167258066Sjhbfile()
168258066Sjhb{
169258066Sjhb	local contents sum
170258066Sjhb
171258066Sjhb	if ! [ -f $TEST/$1 ]; then
172258066Sjhb		echo "File $1 should be a regular file"
173263221Sjmmv		FAILED=yes
174258066Sjhb	elif [ $# -eq 2 ]; then
175258066Sjhb		contents=`cat $TEST/$1`
176258066Sjhb		if [ "$contents" != "$2" ]; then
177258066Sjhb			echo "File $1 has wrong contents"
178263221Sjmmv			FAILED=yes
179258066Sjhb		fi
180258066Sjhb	elif [ $# -eq 3 ]; then
181258066Sjhb		sum=`md5 -q $TEST/$1`
182258066Sjhb		if [ "$sum" != "$3" ]; then
183258066Sjhb			echo "File $1 has wrong contents"
184263221Sjmmv			FAILED=yes
185258066Sjhb		fi
186258066Sjhb	fi
187258066Sjhb}
188258066Sjhb
189258066Sjhb# $1 - relative path to a regular file that should have a conflict
190258066Sjhb# $2 - optional MD5 of the conflict file contents
191258066Sjhbconflict()
192258066Sjhb{
193258066Sjhb	local sum
194258066Sjhb
195258066Sjhb	if ! [ -f $CONFLICTS/$1 ]; then
196258066Sjhb		echo "File $1 missing conflict"
197263221Sjmmv		FAILED=yes
198258066Sjhb	elif [ $# -gt 1 ]; then
199258066Sjhb		sum=`md5 -q $CONFLICTS/$1`
200258066Sjhb		if [ "$sum" != "$2" ]; then
201258066Sjhb			echo "Conflict $1 has wrong contents"
202263221Sjmmv			FAILED=yes
203258066Sjhb		fi
204258066Sjhb	fi
205258066Sjhb}
206258066Sjhb
207258066Sjhbcheck_trees()
208258066Sjhb{
209258066Sjhb
210258066Sjhb	echo "Checking tree for correct results:"
211258066Sjhb
212258066Sjhb	file /etc/master.passwd "" 1385366e8b424d33d59b7d8a2bdb15d3
213258066Sjhb	file /etc/group "" 21273f845f6ec0cda9188c4ddac9ed47
214258066Sjhb	missing /etc/inetd.conf
215258066Sjhb
216258066Sjhb	# These should be auto-generated by pwd_mkdb
217258066Sjhb	file /etc/passwd "" 9831537874bdc99adccaa2b0293248a1
218258066Sjhb	file /etc/pwd.db
219258066Sjhb	file /etc/spwd.db
220258066Sjhb}
221258066Sjhb
222258066Sjhbif [ `id -u` -ne 0 ]; then
223258066Sjhb	echo "must be root"
224263221Sjmmv	exit 0
225258066Sjhbfi
226258066Sjhb
227258066Sjhbif [ -r /etc/etcupdate.conf ]; then
228258066Sjhb	echo "WARNING: /etc/etcupdate.conf settings may break some tests."
229258066Sjhbfi
230258066Sjhb
231258066Sjhbbuild_trees
232258066Sjhb
233258066Sjhb$COMMAND -np -s $SRC -d $WORKDIR -D $TEST > $WORKDIR/testn.out
234258066Sjhb
235258066Sjhbcat > $WORKDIR/correct.out <<EOF
236258066Sjhb  M /etc/group
237258066Sjhb  M /etc/master.passwd
238258066SjhbEOF
239258066Sjhb
240258066Sjhbecho "Differences for -n:"
241263221Sjmmvdiff -u -L "correct" $WORKDIR/correct.out -L "test" $WORKDIR/testn.out \
242263221Sjmmv    || FAILED=yes
243258066Sjhb
244258066Sjhb$COMMAND -p -s $SRC -d $WORKDIR -D $TEST > $WORKDIR/test.out
245258066Sjhb
246258066Sjhbecho "Differences for real:"
247263221Sjmmvdiff -u -L "correct" $WORKDIR/correct.out -L "test" $WORKDIR/test.out \
248263221Sjmmv    || FAILED=yes
249258066Sjhb
250258066Sjhbcheck_trees
251263221Sjmmv
252263221Sjmmv[ "${FAILED}" = no ]
253