1 |
#!/bin/sh |
2 |
|
3 |
# The umask setting makes everything we do group writable, which is a requirement for stuff |
4 |
# we leave in the VO software area. If we didn't, only the original user would be able to |
5 |
# modify or remove these files. |
6 |
umask 002 |
7 |
|
8 |
# This is the location to fetch pkgsrc.tar.gz from. It's a fast mirror. |
9 |
#pkgsrc_url=ftp://ftp.nl.netbsd.org/pub/NetBSD/packages/pkgsrc.tar.gz |
10 |
pkgsrc_url=http://poc.vl-e.nl/pkgsrc/pkgsrc.tar.gz |
11 |
|
12 |
|
13 |
# bunch stdout and stderr together |
14 |
exec 2>&1 |
15 |
|
16 |
# Parse the command-line options. Right now only two options are supported: |
17 |
# -u update the pkgsrc instance (which is normally skipped because it could take a long time) |
18 |
# -h print help |
19 |
# -v explicitly set the VO (normally this is found by inspecting the proxy) |
20 |
|
21 |
printhelp() { |
22 |
cat <<EOF |
23 |
usage: pkgsrc-cmd.sh [-u] [-v vo] [-h] <command> [arguments] |
24 |
|
25 |
Options: |
26 |
-u force update of the pkgsrc installation |
27 |
-v explicitly set VO (use if not recognised automatically) |
28 |
-h print this help |
29 |
-d print debug output |
30 |
|
31 |
Commands: |
32 |
init Set up pkgsrc for the first time |
33 |
check Check the pkgsrc installation |
34 |
install [ pkg ... ] Install the given packages |
35 |
remove [ pkg ... ] Remove the given packages |
36 |
update [ pkg ... ] Update the given packages |
37 |
version print version information |
38 |
|
39 |
EOF |
40 |
|
41 |
} |
42 |
|
43 |
# should we update pkgsrc itself? |
44 |
update=0 |
45 |
# what is the VO? |
46 |
vo= |
47 |
printhelp=0 |
48 |
debugging=0 |
49 |
bmakedebug= |
50 |
while getopts udhv: opt; do |
51 |
case $opt in |
52 |
u) |
53 |
update=1 |
54 |
;; |
55 |
v) vo=$OPTARG |
56 |
;; |
57 |
h) printhelp |
58 |
exit 0; |
59 |
;; |
60 |
d) debugging=1 ; bmakedebug="-d cmvx" ;; |
61 |
?) printhelp |
62 |
exit 1; |
63 |
;; |
64 |
esac |
65 |
done |
66 |
shift $(($OPTIND - 1)) |
67 |
|
68 |
# the debug function prints output if debugging==1 |
69 |
debug() { |
70 |
test $debugging -eq 1 && echo debug: "$@" >&2 |
71 |
} |
72 |
|
73 |
# the log function prints output with a timestamp |
74 |
log() { |
75 |
ts=`date "+%b %e %H:%M:%S %Z"` |
76 |
echo "$ts $@" |
77 |
} |
78 |
|
79 |
# A similar function to produce an error message and exit |
80 |
error() { |
81 |
log "ERROR: $@" |
82 |
exit 1 |
83 |
} |
84 |
|
85 |
# infer VO from the proxy if not set |
86 |
if [ -z $vo ]; then |
87 |
debug "VO not set, looking at proxy" |
88 |
vo=`voms-proxy-info -vo` |
89 |
if [ $? -ne 0 ]; then |
90 |
error "Could not get VO with voms-proxy-info; try -v <vo>." |
91 |
fi |
92 |
debug "VO set from proxy: '$vo'" |
93 |
else |
94 |
debug "VO set on command line: '$vo'" |
95 |
fi |
96 |
|
97 |
log "Started pkgsrc-cmd.sh. VO=$vo, debugging=$debugging" |
98 |
|
99 |
# We need an indirection to set the directory of the VO specific software area |
100 |
vo_sw_dir_var=VO_`echo $vo | tr a-z. A-Z.`_SW_DIR |
101 |
eval vo_sw_dir=\$$vo_sw_dir_var |
102 |
|
103 |
debug "VO software area looked for in environment variable: $vo_sw_dir_var" |
104 |
debug "set vo_sw_dir to $vo_sw_dir" |
105 |
|
106 |
PKGSRC_LOCATION=$vo_sw_dir/pkgsrc |
107 |
PKG_PREFIX=$vo_sw_dir/pkg |
108 |
PATH=$PKG_PREFIX/bin:$PKG_PREFIX/sbin:$PATH |
109 |
export PATH PKG_PREFIX PKGSRC_LOCATION |
110 |
|
111 |
debug "PATH set to: $PATH" |
112 |
|
113 |
log "Running on host: $HOSTNAME" |
114 |
log "Site name: $SITE_NAME" |
115 |
log "command: $0 $@" |
116 |
|
117 |
# This sanity check makes sure we are allowed to write to the software area. |
118 |
# This check should be done before init, install, delete or any other operation |
119 |
# that writes data, but not for operations that only read data. |
120 |
# Also, we need to prevent simultaneous conflicting write operations, so we set |
121 |
# a lock file at this point. We should remove the lockfile at the end, but |
122 |
# if that fails we'll check whether it has become 'stale', which means older than |
123 |
# half an hour. |
124 |
get_write_lock() { |
125 |
log "Checking if the vo software area is writable." |
126 |
if [ -z $vo_sw_dir ] ; then |
127 |
error "\$$vo_sw_dir_var not set." |
128 |
fi |
129 |
|
130 |
if [ ! -w $vo_sw_dir ] ; then |
131 |
error "\$$vo_sw_dir_var ($vo_sw_dir) is not writable. (Check your proxy: are you the VO software manager?)" |
132 |
fi |
133 |
log "$vo_sw_dir writable OK." |
134 |
# now do the lockfile shuffle |
135 |
lockfile=$vo_sw_dir/pkgsrc-lock |
136 |
log "checking lockfile $lockfile" |
137 |
if [ -f $lockfile ]; then |
138 |
log "lockfile exists." |
139 |
ls -l $lockfile |
140 |
if [ ! -z `find $lockfile -mmin -30 2> /dev/null` ]; then |
141 |
log "lockfile is still fresh." |
142 |
return 1 |
143 |
else |
144 |
log "removing stale lockfile (older than 30 minutes)" |
145 |
rm -f $lockfile |
146 |
fi |
147 |
else |
148 |
log "no lockfile found. Setting lock" |
149 |
fi |
150 |
# At this point, we've concluded we should try and set the lockfile. |
151 |
# be careful to avoid race conditions (although rare). |
152 |
log "attempting to get lock." |
153 |
a=`mktemp $vo_sw_dir/pkgsrc-lock.XXXXXXXXXX` || error "mktemp failed" |
154 |
ln $a $lockfile |
155 |
if [ $? -ne 0 ]; then |
156 |
log "failed to obtain lock" |
157 |
rm $a |
158 |
return 1 |
159 |
fi |
160 |
log "lock set" |
161 |
rm $a |
162 |
unset a |
163 |
trap "rm -f $lockfile" INT TERM EXIT |
164 |
return 0 |
165 |
} |
166 |
|
167 |
check_installation() { |
168 |
debug "Test if $PKGSRC_LOCATION exists" |
169 |
if [ ! -d $PKGSRC_LOCATION ]; then |
170 |
error "pkgsrc seems not to be installed; run <init> first." |
171 |
fi |
172 |
for i in pkg_admin pkg_create pkg_info ; do |
173 |
if [ ! -x $PKG_PREFIX/sbin/$i ]; then |
174 |
error "$PKG_PREFIX/sbin/$i is missing. Run <init> first." |
175 |
fi |
176 |
done |
177 |
|
178 |
# check the vulnerabilities databases and run an audit |
179 |
debug "fetching vulnerabilities and auditing system" |
180 |
pkg_admin fetch-pkg-vulnerabilities |
181 |
pkg_admin audit |
182 |
} |
183 |
|
184 |
|
185 |
# fetch the pkgsrc tarball if necessary |
186 |
get_pkgsrc() { |
187 |
if [ ! -r $PKGSRC_LOCATION/pkgsrc.tar.gz ]; then |
188 |
log "$PKGSRC_LOCATION/pkgsrc.tar.gz is not found, downloading for the first time" |
189 |
elif [ -z `find $PKGSRC_LOCATION/pkgsrc.tar.gz -mtime -30` ]; then |
190 |
log "$PKGSRC_LOCATION/pkgsrc.tar.gz is older than 30 days, fetching new version" |
191 |
else |
192 |
log "$PKGSRC_LOCATION/pkgsrc.tar.gz is found and fresh." |
193 |
ls -l $PKGSRC_LOCATION/pkgsrc.tar.gz |
194 |
log "unpacking tarball in `pwd`" |
195 |
tar xfz $PKGSRC_LOCATION/pkgsrc.tar.gz |
196 |
log "unpacking tarball done." |
197 |
return 0 |
198 |
fi |
199 |
|
200 |
# fetch from fast mirror |
201 |
log "Fetching pkgsrc.tar.gz from $pkgsrc_url" |
202 |
mkdir -p $PKGSRC_LOCATION |
203 |
wget --no-verbose -O $PKGSRC_LOCATION/pkgsrc.tar.gz $pkgsrc_url |
204 |
if [ $? -ne 0 ]; then |
205 |
error "Fetching pkgsrc.tar.gz from $pkgsrc_url failed." |
206 |
fi |
207 |
log "$pkgsrc_url saved as $PKGSRC_LOCATION/pkgsrc.tar.gz" |
208 |
log "unpacking tarball in `pwd`" |
209 |
tar xfz $PKGSRC_LOCATION/pkgsrc.tar.gz |
210 |
log "unpacking tarball done." |
211 |
|
212 |
} |
213 |
|
214 |
|
215 |
# The command functions. One of these functions will be called from |
216 |
# the case...esac switch later on. |
217 |
|
218 |
do_init() { |
219 |
log "Starting init." |
220 |
get_pkgsrc |
221 |
|
222 |
log "Creating temporary work directory for bootstrapping" |
223 |
workdir=`mktemp -d -t pkgsrc-bootstrap.XXXXXXXX`/work |
224 |
|
225 |
if [ $? -ne 0 ]; then |
226 |
error "failed to create temporary working directory" |
227 |
fi |
228 |
|
229 |
log bootstrapping: pkgsrc/bootstrap/bootstrap --prefix $PKG_PREFIX --unprivileged --workdir $workdir |
230 |
pkgsrc/bootstrap/bootstrap --prefix $PKG_PREFIX --unprivileged --workdir $workdir |
231 |
if [ $? -ne 0 ]; then |
232 |
error "Bootstrapping pkgsrc failed" |
233 |
fi |
234 |
|
235 |
# set ALLOW_VULNERABLE_PACKAGES |
236 |
tmpcnf=`mktemp` |
237 |
sed '/^.endif/ iALLOW_VULNERABLE_PACKAGES=yes' $PKG_PREFIX/etc/mk.conf > $tmpcnf |
238 |
mv $tmpcnf $PKG_PREFIX/etc/mk.conf |
239 |
|
240 |
# Make sure that fetching is going to work. The pkgsrc provided tnftp requires |
241 |
# libtermcap-devel, which is not commonly found on systems; although pkgsrc also |
242 |
# provides ncurses, which could work just fine, fetching the ncurses sources requires |
243 |
# tnftp, which means a circular dependency. |
244 |
# So we check if the system has wget installed, which is almost always the case, and |
245 |
# configure pkgsrc to use wget as an alternative method of fetching sources. |
246 |
log "trying to build net/tnftp" |
247 |
( cd pkgsrc/net/tnftp && bmake ${bmakedebug} install && bmake clean && bmake clean-depends ) |
248 |
if [ $? -ne 0 ] ; then |
249 |
log "failed building net/tnftp." |
250 |
log "trying alternatives." |
251 |
if [ -x /usr/bin/wget ] ; then |
252 |
log "/usr/bin/wget found. Setting configuration in $PKG_PREFIX/etc/mk.conf" |
253 |
tmpcnf=`mktemp` || exit "failed to create temporary file" |
254 |
sed '/^.endif/ iPREFER_PKGSRC=termcap\ |
255 |
FETCH_USING= custom\ |
256 |
FETCH_CMD= /usr/bin/wget\ |
257 |
FETCH_BEFORE_ARGS= ${PASSIVE_FETCH:D--passive-ftp}\ |
258 |
FETCH_AFTER_ARGS= # empty\ |
259 |
FETCH_RESUME_ARGS= -c\ |
260 |
FETCH_OUTPUT_ARGS= -O' $PKG_PREFIX/etc/mk.conf > $tmpcnf |
261 |
mv $tmpcnf $PKG_PREFIX/etc/mk.conf |
262 |
elif [ -x /usr/bin/curl ] ; then |
263 |
log "/usr/bin/curl found. Setting configuration in $PKG_PREFIX/etc/mk.conf" |
264 |
tmpcnf=`mktemp` || exit "failed to create temporary file" |
265 |
sed '/^.endif/ iPREFER_PKGSRC=termcap\ |
266 |
FETCH_USING= custom\ |
267 |
FETCH_CMD= /usr/bin/curl |
268 |
FETCH_BEFORE_ARGS= ${PASSIVE_FETCH:D--ftp-pasv} |
269 |
FETCH_AFTER_ARGS= -O # must be here to honor -o option |
270 |
FETCH_RESUME_ARGS= -C - |
271 |
FETCH_OUTPUT_ARGS= -o' $PKG_PREFIX/etc/mk.conf > $tmpcnf |
272 |
mv $tmpcnf $PKG_PREFIX/etc/mk.conf |
273 |
else |
274 |
exit "could not find wget or curl, giving up" |
275 |
fi |
276 |
else |
277 |
log "building net/tnftp succeeded" |
278 |
fi |
279 |
|
280 |
log "installation OK. Init is done." |
281 |
|
282 |
|
283 |
} |
284 |
|
285 |
# In case you ever feel the need to start over, this operation will trash the entire installation |
286 |
# |
287 |
do_clear() { |
288 |
log "Starting Clear" |
289 |
if [ -f $PKGSRC_LOCATION/pkgsrc.tar.gz ]; then |
290 |
log "deleting $PKGSRC_LOCATION/pkgsrc.tar.gz" |
291 |
rm -f $PKGSRC_LOCATION/pkgsrc.tar.gz |
292 |
fi |
293 |
if [ -d $PKG_PREFIX ]; then |
294 |
log "Removing $PKG_PREFIX" |
295 |
rm -rf $PKG_PREFIX/* |
296 |
fi |
297 |
log "Done with Clear" |
298 |
} |
299 |
|
300 |
do_check() { |
301 |
log "Starting check; output goes to status.txt" |
302 |
exec 3> status.txt |
303 |
{ |
304 |
echo "Site: $SITE_NAME" |
305 |
echo |
306 |
echo "Environment:" |
307 |
env |
308 |
echo |
309 |
echo "Installed RPMS:" |
310 |
rpm -qa |
311 |
echo |
312 |
echo "Our VO: $vo" |
313 |
echo "VO Software area set in variable \$$vo_sw_dir_var = $vo_sw_dir" |
314 |
} >&3 |
315 |
|
316 |
if [ -z $vo_sw_dir ] ; then |
317 |
echo "\$$vo_sw_dir_var not set. Contact the site administrator." |
318 |
# do we need to go on at all at this point? |
319 |
echo "It's impossible to install pkgsrc at this site until this is fixed." |
320 |
return |
321 |
fi |
322 |
if [ ! -w $vo_sw_dir ] ; then |
323 |
echo "$vo_sw_dir) is not writable, check your proxy (are you the VO software manager?)." |
324 |
ls -ld $vo_sw_dir |
325 |
echo "I am: " |
326 |
id -a |
327 |
fi |
328 |
# test the pkgsrc installation |
329 |
echo >&3 |
330 |
echo "Pkgsrc installation" >&3 |
331 |
echo "PKGSRC_LOCATION=$PKGSRC_LOCATION" >&3 |
332 |
if [ ! -d $PKGSRC_LOCATION ]; then |
333 |
echo "pkgsrc seems not to be installed." |
334 |
elif [ ! -f $PKGSRC_LOCATION/pkgsrc.tar.gz ]; then |
335 |
echo "$PKGSRC_LOCATION/pkgsrc.tar.gz not found" |
336 |
else |
337 |
echo "pkgsrc.tar.gz:" >&3 |
338 |
ls -l $PKGSRC_LOCATION/pkgsrc.tar.gz >&3 |
339 |
fi |
340 |
echo "PKG_PREFIX=$PKG_PREFIX" >&3 |
341 |
if [ ! -d $PKG_PREFIX ]; then |
342 |
echo "$PKG_PREFIX does not exist. Need to bootstrap." |
343 |
else |
344 |
for i in pkg_admin pkg_create pkg_info ; do |
345 |
filecheck=$PKG_PREFIX/sbin/$i |
346 |
echo -n "Checking for $filecheck..." |
347 |
if [ ! -x $filecheck ]; then |
348 |
echo "missing" |
349 |
else |
350 |
echo OK |
351 |
fi |
352 |
done |
353 |
fi |
354 |
echo "Configuration: $PKG_PREFIX/etc/mk.conf" >&3 |
355 |
cat $PKG_PREFIX/etc/mk.conf >&3 |
356 |
|
357 |
echo "End of Configuration file" >&3 |
358 |
|
359 |
# check the vulnerabilities databases and run an audit |
360 |
log "fetching vulnerabilities and auditing system" |
361 |
pkg_admin fetch-pkg-vulnerabilities |
362 |
{ |
363 |
echo "Audit:" |
364 |
pkg_admin audit |
365 |
echo "End audit:" |
366 |
echo |
367 |
echo "Installed packages:" |
368 |
pkg_info -a |
369 |
echo "End of installed packages" |
370 |
} >&3 |
371 |
|
372 |
# if lintpkgsrc is installed, run it. |
373 |
if [ -x $PKG_PREFIX/bin/lintpkgsrc ]; then |
374 |
debug "running lintpkgsrc -i" |
375 |
{ |
376 |
echo "lintpkgsrc -i" |
377 |
$PKG_PREFIX/bin/lintpkgsrc -i |
378 |
echo "end of lintpkgsrc" |
379 |
echo |
380 |
} >&3 |
381 |
else |
382 |
log "Skipping lintpkgsrc; install pkgtools/lintpkgsrc to include this test" |
383 |
fi |
384 |
log "Check done." |
385 |
return |
386 |
} |
387 |
|
388 |
do_install() { |
389 |
get_pkgsrc |
390 |
# install the packages in $@. |
391 |
for i in "$@" ; do |
392 |
if [ ! -d pkgsrc/$i ]; then |
393 |
echo "WARNING: unknown package $i" >&2 |
394 |
continue |
395 |
fi |
396 |
( cd pkgsrc/$i && bmake ${bmakedebug} install && bmake clean && bmake clean-depends ) |
397 |
if [ $? -ne 0 ] ; then |
398 |
error "bmake failed on $i" |
399 |
fi |
400 |
done |
401 |
|
402 |
} |
403 |
|
404 |
do_remove() { |
405 |
check_installation |
406 |
# delete the given packages |
407 |
pkg_delete "$@" |
408 |
} |
409 |
|
410 |
do_update() { |
411 |
get_pkgsrc |
412 |
for i in "$@" ; do |
413 |
if [ ! -d pkgsrc/$i ]; then |
414 |
echo "WARNING: unknown package $i" >&2 |
415 |
continue |
416 |
fi |
417 |
( cd pkgsrc/$i && bmake update && bmake clean && bmake clean-depends ) |
418 |
done |
419 |
|
420 |
} |
421 |
|
422 |
do_version() { |
423 |
log "version() not implemented." |
424 |
return 0 |
425 |
} |
426 |
|
427 |
|
428 |
# all operations need to write to the software area in some way or other, so we |
429 |
# might as well try to get the write lock here and get it out of the way |
430 |
get_write_lock || exit 1 |
431 |
|
432 |
|
433 |
# Parse the command-line arguments. Current understood commands are: |
434 |
# |
435 |
# init - set up pkgsrc for the first time |
436 |
# check - check the pkgsrc setup |
437 |
# install <packages> - install the given packages |
438 |
# remove <package> - remove the given packages |
439 |
# update - update the packages |
440 |
# version - display version information |
441 |
|
442 |
if [ $# -gt 0 ] ; then |
443 |
case $1 in |
444 |
init) do_init ;; |
445 |
reinit) do_clear && do_init ;; |
446 |
check) do_check ;; |
447 |
install) shift; do_install "$@" ;; |
448 |
remove) shift; do_remove "$@" ;; |
449 |
update) do_update "$@" ;; |
450 |
version) do_version ;; |
451 |
*) |
452 |
log "ERROR: unknown command given: $1" >&2 |
453 |
printhelp |
454 |
exit 1 |
455 |
;; |
456 |
esac |
457 |
shift |
458 |
else |
459 |
log "No command given. Stop." |
460 |
printhelp |
461 |
exit 1 |
462 |
fi |
463 |
|
464 |
log "Script ends." |