xf.li | 8611891 | 2025-03-19 20:07:27 -0700 | [diff] [blame] | 1 | #!/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 | |
| 22 | set -e |
| 23 | |
| 24 | # admin dir |
| 25 | ad="$OPKG_OFFLINE_ROOT/usr/lib/opkg/alternatives" |
| 26 | |
| 27 | usage() { |
| 28 | echo "update-alternatives: $* |
| 29 | |
| 30 | Usage: 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 | |
| 41 | quit() { |
| 42 | echo "update-alternatives: $*" >&2 |
| 43 | exit 2 |
| 44 | } |
| 45 | |
| 46 | register_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 | |
| 71 | protect_slashes() { |
| 72 | sed -e 's/\//\\\//g' |
| 73 | } |
| 74 | |
| 75 | protect_special_character() { |
| 76 | sed -e 's/\[/\\\[/g' |
| 77 | } |
| 78 | |
| 79 | remove_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 | |
| 91 | add_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 | |
| 103 | find_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 | |
| 137 | do_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 | |
| 156 | do_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 | |
| 176 | while [ $# -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 |
| 197 | done |
| 198 | |
| 199 | usage "at least one of --install or --remove must appear" |
| 200 | |
| 201 | exit 0 |