| #!/bin/sh |
| # SPDX-License-Identifier: GPL-2.0-or-later |
| # update-alternatives |
| # |
| # Copyright (C) 2001 Carl D. Worth |
| # |
| # This program was inspired by the Debian update-alternatives program |
| # which is Copyright (C) 1995 Ian Jackson. This version of |
| # update-alternatives is command-line compatible with Debian's for a |
| # subset of the options, (only --install, --remove, and --help) |
| # |
| # This program is free software; you can redistribute it and/or modify |
| # it under the terms of the GNU General Public License as published by |
| # the Free Software Foundation; either version 2, or (at your option) |
| # any later version. |
| # |
| # This program is distributed in the hope that it will be useful, |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| # GNU General Public License for more details. |
| |
| set -e |
| |
| # admin dir |
| ad="$OPKG_OFFLINE_ROOT/usr/lib/opkg/alternatives" |
| |
| usage() { |
| echo "update-alternatives: $* |
| |
| Usage: update-alternatives --install <link> <name> <path> <priority> |
| update-alternatives --remove <name> <path> |
| update-alternatives --help |
| <link> is the link pointing to the provided path (ie. /usr/bin/foo). |
| <name> is the name in $ad/alternatives (ie. foo) |
| <path> is the name referred to (ie. /usr/bin/foo-extra-spiffy) |
| <priority> is an integer; options with higher numbers are chosen. |
| " >&2 |
| exit 2 |
| } |
| |
| quit() { |
| echo "update-alternatives: $*" >&2 |
| exit 2 |
| } |
| |
| register_alt() { |
| [ $# -lt 2 ] && return 1 |
| local name="$1" |
| local link="$2" |
| |
| if [ ! -d $ad ]; then |
| mkdir -p $ad |
| fi |
| |
| if [ -e "$ad/$name" ]; then |
| local olink=`head -n 1 $ad/$name` |
| if [ "$link" != "$olink" ]; then |
| echo "update-alternatives: renaming $name link from $olink to $link" |
| local link_str=`echo $link | protect_slashes` |
| sed -e "1s/.*/$link_str/" $ad/$name > $ad/$name.new |
| mv $ad/$name.new $ad/$name |
| mv $OPKG_OFFLINE_ROOT$olink $OPKG_OFFLINE_ROOT$link |
| fi |
| else |
| echo "$link" > "$ad/$name" |
| fi |
| |
| return 0 |
| } |
| |
| protect_slashes() { |
| sed -e 's/\//\\\//g' |
| } |
| |
| protect_special_character() { |
| sed -e 's/\[/\\\[/g' |
| } |
| |
| remove_alt() { |
| [ $# -lt 2 ] && return 1 |
| local name="$1" |
| local path="$2" |
| |
| [ ! -f $ad/$name ] && return 0 |
| |
| path=`echo $path | protect_slashes | protect_special_character` |
| sed -ne "/^$path\s.*/!p" $ad/$name > $ad/$name.new |
| mv $ad/$name.new $ad/$name |
| } |
| |
| add_alt() { |
| [ $# -lt 3 ] && return 1 |
| local name="$1" |
| local path="$2" |
| local priority="$3" |
| remove_alt $name $path |
| if grep -qw "$priority" $ad/$name; then |
| echo "Warn: update-alternatives: $name has multiple providers with the same priority, please check $ad/$name for details" |
| fi |
| echo "$path $priority" >> $ad/$name |
| } |
| |
| find_best_alt() { |
| [ $# -lt 1 ] && return 1 |
| [ ! -f $ad/$name ] && return 0 |
| |
| link=$OPKG_OFFLINE_ROOT`head -n 1 $ad/$name` |
| |
| prio=`sed -ne "1!p" $ad/$name | sed -e "s/\(.*\) \(.*\)/\2 \1/g" | sort -nr | head -n 1 | sed 's/ [^ ]*$//'` |
| if [ -z "$prio" ]; then |
| echo "update-alternatives: removing $link as no more alternatives exist for it" |
| rm $ad/$name |
| if [ -L $link ]; then |
| rm $link |
| fi |
| return 0 |
| fi |
| |
| ## Find last line with highest priority. |
| path=`grep "${prio}$" $ad/$name | tail -n 1 | sed 's/ [^ ]*$//'` |
| |
| if [ ! -e $link -o -L $link ]; then |
| local link_dir=`dirname $link` |
| if [ ! -d $link_dir ]; then |
| mkdir -p $link_dir |
| fi |
| ln -snf $path $link |
| echo "update-alternatives: Linking $link to $path" |
| else |
| echo "update-alternatives: Error: not linking $link to $path since $link exists and is not a link" |
| return 1 |
| fi |
| |
| return 0 |
| } |
| |
| do_install() { |
| if [ $# -lt 4 ]; then |
| usage "--install needs <link> <name> <path> <priority>" |
| fi |
| local link="$1" |
| local name="$2" |
| local path="$3" |
| local priority="$4" |
| |
| path=`echo $path | sed 's|/\+|/|g'` |
| |
| # This is a bad hack, but I haven't thought of a cleaner solution yet... |
| [ -n "$OPKG_OFFLINE_ROOT" ] && path=`echo $path | sed "s|^$OPKG_OFFLINE_ROOT/*|/|"` |
| |
| register_alt $name $link |
| add_alt $name $path $priority |
| find_best_alt $name |
| } |
| |
| do_remove() { |
| if [ $# -lt 2 ]; then |
| usage "--remove needs <name> <path>" |
| fi |
| local name="$1" |
| local path="$2" |
| |
| path=`echo $path | sed 's|/\+|/|g'` |
| |
| # This is a bad hack, but I haven't thought of a cleaner solution yet... |
| [ -n "$OPKG_OFFLINE_ROOT" ] && path=`echo $path | sed "s|^$OPKG_OFFLINE_ROOT/*|/|"` |
| |
| remove_alt $name $path |
| find_best_alt $name |
| } |
| |
| ### |
| # update-alternatives "main" |
| ### |
| |
| while [ $# -gt 0 ]; do |
| arg="$1" |
| shift |
| |
| case $arg in |
| --help) |
| usage "help:" |
| exit 0 |
| ;; |
| --install) |
| do_install $* |
| exit $? |
| ;; |
| --remove) |
| do_remove $* |
| exit $? |
| ;; |
| *) |
| usage "unknown argument \`$arg'" |
| ;; |
| esac |
| done |
| |
| usage "at least one of --install or --remove must appear" |
| |
| exit 0 |