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