3 # Copyright (c) 2000,2004 Matthias S. Benkmann <article AT winterdrache DOT de>
4 # You may do everything with this code except misrepresent its origin.
5 # PROVIDED `AS IS' WITH ABSOLUTELY NO WARRANTY OF ANY KIND!
7 # Copyright (C) 2014 Steve Youngs <steve@steveyoungs.com>
9 # Actually there's not much left of Matt's original script... pretty
10 # much a complete re-write here. :)
12 ### What this is and what it does:
14 # It is a wrapper around the install binary that comes with the
15 # coreutils package. It is designed to catch the most common
16 # problems that pkgusr will face during a package install.
18 # By far, the most common thing this script catches are setuid/gid
19 # installs. What we do is strip the setuid/gid bit off of the --mode
20 # option and then go ahead with the install. So the file is still
21 # installed, there'll be no error, it will just not be setuid/gid.
23 # It also sanitises the --owner and --group options. With the former,
24 # it changes it to the name of the pkgusr, and with the latter it
25 # tests if the group is one of the groups that pkgusr belongs to, and
26 # if it isn't, change the option to the pkgusr's current active group.
28 # It only allows pkgusrs to create directories that don't already
29 # exist. This stops those packages that try to reset permissions on
30 # main system directories.
32 # It optionally suppresses installing anything into /**/share/locale.
33 # See `## locale suppression' below for more details.
35 # ******************************
36 # *** S P E C I A L N O T E ***
37 # ******************************
39 # Whenever this script changes something on the install command line
40 # it is reported in the build logs. Everything is prefixed with
41 # '***' so always grep your logs for that after any and every package
42 # install to see if there is anything you need to take action on.
46 ### Where this differs from Matt's original script:
48 # setuid etc: Matt's script only tested for 4755, 4775, 4711, and
49 # nothing else. This script tests and does something about _ALL_
50 # file mode possibilities, including modes set via symbols instead of
53 # owner/group: Matt simply dropped these options if they were present.
54 # This script tries to keep them if possible by resetting to a safer
55 # alternative. Both names and UIDs/GIDs are supported.
57 # locale directories: Matt's approach was to convert any newly created
58 # directory under /usr/share/locale to an "install" directory. The
59 # problem with that is the directories were not owned by root because
60 # they were set by the pkgusr. That would allow one pkgusr to delete
61 # another's files in that directory.
63 # My approach to locale directories is simple... Just don't install
64 # them. There are three situations where they are needed...
66 # 1. You're multi-lingual and like switching between languages.
67 # 2. English is not your 1st or preferred language. (or you can't
69 # 3. To satisfy glibc's test suite.
71 # For me, #3 is the only one that is relevant. But don't worry,
72 # it is configurable via an environment variable. You can turn on
73 # locale installs either globally or for individual packages. See
74 # `## locale suppression' below and in /etc/pkgusr/bash_profile.
76 # man pages: Matt tried to catch dups going into /usr/share/man/man?/.
77 # I'm not bothering with this as it was too much of a "one-off" type
78 # of occurance to have it scripted.
80 # Running the script as root: Matt allows it, I don't.
84 ## Preserve the original command line.
88 ## Find the real install.
90 for p in $(type -ap install) ; do
91 if [ ! $p -ef $0 ]; then
97 if [ ! -n "$DAISY_CHAIN" ]; then
98 echo 1>&2 '***' Cannot find real ${0##*/} command
102 ## root has no business installing things here!!
103 if [ $UID == 0 ]; then
104 echo 1>&2 '***' $(dirname $0) should not be in root\'s \$PATH
105 echo 1>&2 '***' call '"'$DAISY_CHAIN ${pristinecmd[*]'"' directly
110 # When we change something, note what the original command was in the
114 echo 1>&2 '***' install ${pristinecmd[*]}
118 ## locale suppression
119 # $SUPPRESSLOCALEDIR is set in the pkgusr's environment. It defaults
120 # to `1' (on) which means: DO NOT install locale stuff. To override
121 # it set SUPPRESSLOCALEDIR=0 in the pkgusr's ~/.pkgusrrc.
123 # For me, at least, the only package I turn off the suppression is
124 # glibc, and that is only to satisfy glibc's test suite.
125 if [ ${SUPPRESSLOCALEDIR} -eq 1 ]; then
126 case "${pristinecmd[-1]}" in
128 echo 1>&2 '***' Suppressed locale installation for: ${pristinecmd[-1]}
136 # Only allow the creation of directories that don't already exist.
140 local dir=${myarray[-1]}
142 if [ -d ${dir} ]; then
145 cmdopts="$cmdopts -d"
150 ## Leading directories (install option -D)
151 # The same as for -d, only create if it doesn't exist. But we need
152 # to do a little more this time because if we decide to NOT create
153 # the directory we will need to alter the command line further...
155 # install -Dm755 myprog /usr/bin/myprog
157 # install -m755 myprog /usr/bin
161 local dir=$(dirname ${myarray[-1]})
162 local last=$((${#myarray[*]}-1))
164 if [ -d ${dir} ]; then
166 myarray[${last}]=${dir}
168 set -- "$@" "${myarray[*]}"
170 cmdopts="$cmdopts -D"
176 # If $group is one of the groups we belong to, use it, otherwise set
177 # -g to our currently active group and report it.
184 if [ $group -ge 0 2>/dev/null ]; then
190 for g in ${GRP_LIST}; do
191 if [ $group == "$g" ]; then
197 if [ -z "$GRP_CHAIN" ]; then
199 cmdopts="$cmdopts -g$(id -gn)"
201 cmdopts="$cmdopts -g$group"
207 # Set -u to our username and report if it wasn't already our name.
213 if [ $owner -ge 0 2>/dev/null ]; then
219 if [ $owner != "$MYNAME" ]; then
222 cmdopts="$cmdopts -u$(id -un)"
227 # If the file perms are being set to a 4-digit number they are
228 # trying to do something funky like setuid. In that case, truncate
229 # the 1st digit and set -m to what's left, and report it. If perms
230 # are symbolic, convert them to numerical first.
235 # Convert symbolic permissions to numerical. This works via
236 # side-effect because if $perm is text it causes the if to error
237 # and you come out on the else branch.
238 if [ $perm -ge 0 2>/dev/null ]; then
241 touch /tmp/hack-o-matic-9000
242 chmod $perm /tmp/hack-o-matic-9000
243 p=$(stat --printf "%a" /tmp/hack-o-matic-9000)
244 rm -f /tmp/hack-o-matic-9000
246 # Catch the funky shit
247 if [ $p -gt 999 ]; then
249 cmdopts="$cmdopts -m${p/?/}"
251 cmdopts="$cmdopts -m$p"
256 ## Parse the command line.
257 # All we really care about here is -d, -D, -o, -g, and -m. -c is
258 # silently dropped. Unrecognised options cause the script to exit
259 # with a non-zero return code.
261 # Any other legal options get passed on without alteration.
263 # NOTE: The following long options will most likely cause this script
264 # to fail (hopefully they are obscure enough to not worry about)
266 # --preserve-timestamps (short opt '-p' is OK)
268 # --target-directory (short opt '-t' is OK)
269 # --no-target-directory (short opt '-T' is OK)
272 args=bcCdDpsTvg:m:o:S:t:Z:-:
273 while getopts $args opts; do
278 (backup*) cmdopts="$cmdopts --${OPTARG}" ;;
279 (compare) cmdopts="$cmdopts -C" ;;
281 (group*) group=${OPTARG/group[=[:space:]]/}; _group ;;
282 (mode*) perm=${OPTARG/mode[=[:space:]]/}; _perms ;;
283 (owner*) owner=${OPTARG/owner[=[:space:]]/}; _owner ;;
284 (strip) cmdopts="$cmdopts -s" ;;
285 (suffix*) cmdopts="$cmdopts -S${OPTARG/suffix[=[:space:]]/}" ;;
286 (verbose) cmdopts="$cmdopts -v" ;;
287 (context*) cmdopts="$cmdopts -Z${OPTARG/context[=[:space:]]/}" ;;
288 (help) cmdopts="$cmdopts --help" ;;
289 (version) cmdopts="$cmdopts --version" ;;
290 (*) echo 1>&2 '***' Illegal option -- ${OPTARG}
296 (b) cmdopts="$cmdopts -b" ;;
297 (C) cmdopts="$cmdopts -C" ;;
301 (g) group=${OPTARG}; _group ;;
302 (m) perm=${OPTARG}; _perms ;;
303 (o) owner=${OPTARG}; _owner ;;
304 (p) cmdopts="$cmdopts -p" ;;
305 (s) cmdopts="$cmdopts -s" ;;
306 (S) cmdopts="$cmdopts -S${OPTARG}" ;;
307 (t) cmdopts="$cmdopts -t${OPTARG}" ;;
308 (T) cmdopts="$cmdopts -T" ;;
309 (v) cmdopts="$cmdopts -v" ;;
310 (Z) cmdopts="$cmdopts -Z${OPTARG}" ;;
314 shift $(( $OPTIND - 1 ))
316 # We've done all we can, now lets run install
317 $DAISY_CHAIN "$cmdopts $@" || exit $?