libopkg: implement lightweight package listing logic
[oweals/opkg-lede.git] / utils / update-alternatives.in
1 #!/bin/sh
2 # update-alternatives
3 #
4 # Copyright (C) 2001 Carl D. Worth
5 #
6 # This program was inspired by the Debian update-alternatives program
7 # which is Copyright (C) 1995 Ian Jackson. This version of
8 # update-alternatives is command-line compatible with Debian's for a
9 # subset of the options, (only --install, --remove, and --help)
10 #
11 # This program is free software; you can redistribute it and/or modify
12 # it under the terms of the GNU General Public License as published by
13 # the Free Software Foundation; either version 2, or (at your option)
14 # any later version.
15 #
16 # This program is distributed in the hope that it will be useful,
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 # GNU General Public License for more details.
20
21 set -e
22
23 # admin dir
24 ad="$OPKG_OFFLINE_ROOT@opkglibdir@/opkg/alternatives"
25
26 usage() {
27         echo "update-alternatives: $*
28
29 Usage: update-alternatives --install <link> <name> <path> <priority>
30        update-alternatives --remove <name> <path>
31        update-alternatives --help
32 <link> is the link pointing to the provided path (ie. /usr/bin/foo).
33 <name> is the name in $ad/alternatives (ie. foo)
34 <path> is the name referred to (ie. /usr/bin/foo-extra-spiffy)
35 <priority> is an integer; options with higher numbers are chosen.
36 " >&2
37         exit 2
38 }
39
40 quit() {
41         echo "update-alternatives: $*" >&2
42         exit 2
43 }
44
45 register_alt() {
46         [ $# -lt 2 ] && return 1
47         local name="$1"
48         local link="$2"
49
50         if [ ! -d $ad ]; then
51                 mkdir -p $ad
52         fi
53
54         if [ -e "$ad/$name" ]; then
55                 local olink=`head -n 1 $ad/$name`
56                 if [ "$link" != "$olink" ]; then
57                         echo "update-alternatives: Error: cannot register alternative $name to $link since it is already registered to $olink" >&2
58                         return 1
59                 fi
60         else
61                 echo "$link" > "$ad/$name"
62         fi
63
64         return 0
65 }
66
67 protect_slashes() {
68         sed -e 's/\//\\\//g'
69 }
70
71 remove_alt() {
72         [ $# -lt 2 ] && return 1
73         local name="$1"
74         local path="$2"
75         
76         [ ! -f $ad/$name ] && return 0
77
78         path=`echo $path | protect_slashes`
79         sed -ne "/^$path\>.*/!p" $ad/$name > $ad/$name.new
80         mv $ad/$name.new $ad/$name
81 }
82
83 add_alt() {
84         [ $# -lt 3 ] && return 1
85         local name="$1"
86         local path="$2"
87         local priority="$3"
88         remove_alt $name $path
89         echo "$path $priority" >> $ad/$name
90 }
91
92 find_best_alt() {
93         [ $# -lt 1 ] && return 1
94         [ ! -f $ad/$name ] && return 0
95
96         link=$OPKG_OFFLINE_ROOT/`head -n 1 $ad/$name`
97
98         prio=`sed -ne "1!p" $ad/$name | sed -e "s/\(.*\) \(.*\)/\2 \1/g" | sort -nr | head -n 1 | sed 's/ [^ ]*$//'`
99         if [ -z "$prio" ]; then
100                 echo "update-alternatives: removing $link as no more alternatives exist for it"
101                 rm $ad/$name
102                 if [ -L $link ]; then
103                         rm $link
104                 fi
105                 return 0
106         fi
107
108         ## Find last line with highest priority.
109         path=`grep "${prio}$" $ad/$name | tail -n 1 | sed 's/ [^ ]*$//'`
110
111         if [ ! -e $link -o -L $link ]; then
112                 local link_dir=`dirname $link`
113                 if [ ! -d $link_dir ]; then
114                         mkdir -p $link_dir
115                 fi
116                 if [ -h $link -a -d $link ]; then
117                         # If $link exists and the target is a directory,
118                         # 'ln -sf $path $link' doesn't replace the link to
119                         # that directory, it creates new link inside.
120                         echo "update-alternatives: Removing $link".
121                         rm -f $link
122                 fi
123                 ln -sf $path $link
124                 echo "update-alternatives: Linking $link to $path"
125         else
126                 echo "update-alternatives: Error: not linking $link to $path since $link exists and is not a link"
127                 return 1
128         fi
129
130         return 0
131 }
132
133 do_install() {
134         if [ $# -lt 4 ]; then
135                 usage "--install needs <link> <name> <path> <priority>"
136         fi
137         local link="$1"
138         local name="$2"
139         local path="$3"
140         local priority="$4"
141
142         path=`echo $path | sed 's|/\+|/|g'`
143
144         # This is a bad hack, but I haven't thought of a cleaner solution yet...
145         [ -n "$OPKG_OFFLINE_ROOT" ] && path=`echo $path | sed "s|^$OPKG_OFFLINE_ROOT/*|/|"`
146
147         register_alt $name $link
148         add_alt $name $path $priority
149         find_best_alt $name
150 }
151
152 do_remove() {
153        if [ $# -lt 2 ]; then
154                 usage "--remove needs <name> <path>"
155         fi      
156         local name="$1"
157         local path="$2"
158
159         path=`echo $path | sed 's|/\+|/|g'`
160
161         # This is a bad hack, but I haven't thought of a cleaner solution yet...
162         [ -n "$OPKG_OFFLINE_ROOT" ] && path=`echo $path | sed "s|^$OPKG_OFFLINE_ROOT/*|/|"`
163
164         remove_alt $name $path
165         find_best_alt $name
166 }
167
168 ###
169 # update-alternatives "main"
170 ###
171
172 while [ $# -gt 0 ]; do
173         arg="$1"
174         shift
175
176         case $arg in
177         --help)
178                 usage "help:"
179                 exit 0
180                 ;;
181         --install)
182                 do_install $*
183                 exit $?
184                 ;;
185         --remove)
186                 do_remove $*
187                 exit $?
188                 ;;
189         *)
190                 usage "unknown argument \`$arg'"
191                 ;;
192         esac
193 done
194
195 usage "at least one of --install or --remove must appear"
196
197 exit 0