#!/bin/sh # # Copyright (C) 2012, 2014 Etersoft # Copyright (C) 2012, 2014 Vitaly Lipatov <lav@etersoft.ru> # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, 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 Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # # copied from /etc/init.d/outformat (ALT Linux) # FIXME on Android: FIX ME! implement ttyname_r() bionic/libc/bionic/stubs.c:366 inputisatty() { # check stdin tty -s 2>/dev/null } isatty() { # check stdout test -t 1 } isatty2() { # check stderr test -t 2 } check_tty() { isatty2 || return # Set a sane TERM required for tput [ -n "$TERM" ] || TERM=dumb export TERM # egrep from busybox may not --color # egrep from MacOS print help to stderr if grep -E --help 2>&1 | grep -q -- "--color" ; then export EGREPCOLOR="--color" fi which tput >/dev/null 2>/dev/null || return # FreeBSD does not support tput -S echo | tput -S >/dev/null 2>/dev/null || return [ -z "$USETTY" ] || return export USETTY=1 } : ${BLACK:=0} ${RED:=1} ${GREEN:=2} ${YELLOW:=3} ${BLUE:=4} ${MAGENTA:=5} ${CYAN:=6} ${WHITE:=7} set_boldcolor() { [ "$USETTY" = "1" ] || return { echo bold echo setaf $1 } |tput -S } restore_color() { [ "$USETTY" = "1" ] || return { echo op; # set Original color Pair. echo sgr0; # turn off all special graphics mode (bold in our case). } |tput -S } echover() { [ -z "$verbose" ] && return echo "$*" >&2 } # echo string without EOL echon() { # default /bin/sh on MacOS does not recognize -n /bin/echo -n "$*" } # Used DISTRNAME set_target_pkg_env() { [ -n "$DISTRNAME" ] || fatal "Missing DISTRNAME in set_target_pkg_env." PKGFORMAT=$($DISTRVENDOR -p "$DISTRNAME") PKGVENDOR=$($DISTRVENDOR -s "$DISTRNAME") RPMVENDOR=$($DISTRVENDOR -n "$DISTRNAME") } # Print command line and run command line showcmd() { if [ -z "$quiet" ] ; then set_boldcolor $GREEN local PROMTSIG="\$" [ "$EFFUID" = 0 ] && PROMTSIG="#" echo " $PROMTSIG $*" restore_color fi >&2 } # Print command line and run command line docmd() { showcmd "$*$EXTRA_SHOWDOCMD" #FIXME $@ } # Run every arg with docmd docmd_foreach() { local cmd pkg cmd="$1" #showcmd "$@" shift for pkg in "$@" ; do docmd "$cmd" $pkg done } # Print command line and run command line with SUDO sudocmd() { [ -n "$SUDO" ] && showcmd "$SUDO $*" || showcmd "$*" $SUDO $@ } # Run every arg with sudocmd # Returns on any error sudocmd_foreach() { local cmd pkg cmd="$1" #showcmd "$@" shift for pkg in "$@" ; do sudocmd "$cmd" $pkg || return done } # add realpath if missed if ! which realpath 2>/dev/null >/dev/null ; then realpath() { readlink -f "$@" } fi get_firstarg() { echon "$1" } get_lastarg() { local lastarg eval "lastarg=\${$#}" echon "$lastarg" } # TODO: see etersoft-build-utils/tests/test_isnumber.sh isnumber() { echo "$*" | filter_strip_spaces | grep -q "^[0-9]\+$" } filter_strip_spaces() { # possible use just #xargs echo sed -e "s| \+| |g" | \ sed -e "s|^ ||" | sed -e "s| \$||" } strip_spaces() { echo "$*" | filter_strip_spaces } # param true false subst_option() { eval "[ -n \"\$$1\" ]" && echo "$2" || echo "$3" } store_output() { # use make_temp_file from etersoft-build-utils RC_STDOUT=$(mktemp) local CMDSTATUS=$RC_STDOUT.pipestatus echo 1 >$CMDSTATUS #RC_STDERR=$(mktemp) ( $@ 2>&1 ; echo $? >$CMDSTATUS ) | tee $RC_STDOUT return "$(cat $CMDSTATUS)" # bashism # http://tldp.org/LDP/abs/html/bashver3.html#PIPEFAILREF #return $PIPESTATUS } showcmd_store_output() { showcmd "$@" store_output "$@" } clean_store_output() { rm -f $RC_STDOUT $RC_STDOUT.pipestatus } # run epm, possible from side repo epm() { [ -n "$PROGNAME" ] || fatal "Can't use epm call from the piped script" $PROGDIR/$PROGNAME $@ } # Print error message and stop the program fatal() { if [ -z "$TEXTDOMAIN" ] ; then echo "Error: $*" >&2 # else # echog "Error in $0: $@" >&2 fi exit 1 } # Print warning message warning() { if [ -z "$TEXTDOMAIN" ] ; then echo "Warning: $*" >&2 # else # echog "Error in $0: $@" >&2 fi } info() { [ -n "$quiet" ] && return # print message to stderr if stderr forwarded to (a file) if isatty2 ; then isatty || return 0 echo "$*" else echo "$*" >&2 fi } set_sudo() { SUDO="" # skip SUDO if disabled [ -n "$EPMNOSUDO" ] && return if [ "$DISTRNAME" = "Cygwin" ] || [ "$DISTRNAME" = "Windows" ] ; then # skip sudo using on Windows return fi EFFUID=$(id -u) # do not need sudo [ $EFFUID = "0" ] && return # use sudo if possible if which sudo >/dev/null 2>/dev/null ; then SUDO="sudo --" # check for < 1.7 version which do not support -- (and --help possible too) sudo -h 2>/dev/null | grep -q " --" || SUDO="sudo" return fi SUDO="fatal 'Can't find sudo. Please install sudo or run epm under root.'" } # wait for n seconds (if possible) during executing command # args: seconds command withtimeout() { local TO=$(which timeout 2>/dev/null || which gtimeout 2>/dev/null) if [ -x "$TO" ] ; then $TO "$@" return fi # fallback: drop time arg and run without timeout shift "$@" } set_eatmydata() { # skip if disabled [ -n "$EPMNOEATMYDATA" ] && return # use if possible which eatmydata >/dev/null 2>/dev/null || return [ -n "$SUDO" ] && SUDO="$SUDO eatmydata" || SUDO="eatmydata" [ -n "$verbose" ] && info "Uwaga! eatmydata is installed, we will use it for disable all sync operations." return 0 } # __get_package_for_command() { case "$1" in equery|revdep-rebuild) echo 'gentoolkit' ;; update-kernel|remove-old-kernels) echo 'update-kernel' ;; esac } # TODO: confirm() { local response # call with a prompt string or use a default read -r -p "${1:-Are you sure? [y/N]} " response case $response in [yY][eE][sS]|[yY]) true ;; *) false ;; esac } assure_root() { [ "$EFFUID" = 0 ] || fatal "run me only under root" } regexp_subst() { local expression="$1" shift sed -i -r -e "$expression" "$@" } # TODO: we we can't use epm directly? assure_exists() { load_helper epm-assure local package="$2" local textpackage= [ -n "$package" ] || package="$(__get_package_for_command "$1")" [ -n "$3" ] && textpackage=" >= $3" __epm_assure "$1" $package $3 || fatal "Can't assure in '$1' command from $package$textpackage package" } # will replaced within disabled_eget in packaged version eget() { # use internal eget only if exists if [ -s $SHAREDIR/tools_eget ] ; then $SHAREDIR/tools_eget "$@" return fi assure_exists eget # run external command, not the function EGET=$(which eget) || fatal "Missed command eget from installed package eget" $EGET "$@" } # will replaced within eget() in packed version onefile_eget() { assure_exists wget internal_tools_eget "$@" } # TODO: improve and drop! get_package_type() { local i case $1 in *.deb) echo "deb" return ;; *.rpm) echo "rpm" return ;; *.txz) echo "txz" return ;; *.tbz) echo "tbz" return ;; *.exe) echo "exe" return ;; *.msi) echo "msi" return ;; *) #fatal "Don't know type of $1" # return package name for info echo "$1" return 1 ;; esac } # print options description from HELPCMD/HELPOPT lines in the code get_help() { if [ "$0" = "/dev/stdin" ] || [ "$0" = "sh" ] ; then return fi grep -v -- "^#" $0 | grep -- "# $1" | while read -r n ; do opt=$(echo $n | sed -e "s|) # $1:.*||g") desc=$(echo $n | sed -e "s|.*) # $1:||g") printf " %-20s %s\n" $opt "$desc" done } # FIXME: detect if not recognized set_pm_type() { local CMD # Fill for use: PMTYPE, DISTRNAME, DISTRVERSION, PKGFORMAT, PKGVENDOR, RPMVENDOR DISTRVENDOR=$PROGDIR/distr_info [ -n "$DISTRNAME" ] || DISTRNAME=$($DISTRVENDOR -d) || fatal "Can't get distro name." [ -n "$DISTRVERSION" ] || DISTRVERSION=$($DISTRVENDOR -v) set_target_pkg_env # override package manager detection result if [ -n "$FORCEPM" ] ; then PMTYPE=$FORCEPM return fi # TODO: move it in distr_vendor? # FIXME: some problems with multibased distros (Server Edition on CentOS and Desktop Edition on Ubuntu) case $DISTRNAME in ALTLinux) CMD="apt-rpm" #which ds-install 2>/dev/null >/dev/null && CMD=deepsolver-rpm ;; PCLinux) CMD="apt-rpm" ;; Ubuntu|Debian|Mint|AstraLinux|Elbrus) CMD="apt-dpkg" #which aptitude 2>/dev/null >/dev/null && CMD=aptitude-dpkg which snappy 2>/dev/null >/dev/null && CMD=snappy ;; Mandriva|ROSA) CMD="urpm-rpm" ;; FreeBSD|NetBSD|OpenBSD|Solaris) CMD="pkgsrc" which pkg 2>/dev/null >/dev/null && CMD=pkgng ;; Gentoo) CMD="emerge" ;; ArchLinux) CMD="pacman" ;; Fedora|LinuxXP|ASPLinux|CentOS|RHEL|Scientific|GosLinux) CMD="yum-rpm" which dnf 2>/dev/null >/dev/null && test -d /var/lib/dnf/yumdb && CMD=dnf-rpm ;; Slackware) CMD="slackpkg" ;; SUSE|SLED|SLES|Tumbleweed) CMD="zypper-rpm" ;; ForesightLinux|rPathLinux) CMD="conary" ;; Windows) CMD="chocolatey" ;; MacOS) CMD="homebrew" ;; OpenWRT) CMD="ipkg" ;; GNU/Linux/Guix) CMD="guix" ;; Android) CMD="android" ;; Cygwin) CMD="aptcyg" ;; alpine) CMD="apk" ;; TinyCoreLinux) CMD="tce" ;; VoidLinux) CMD="xbps" ;; *) fatal "Have no suitable DISTRNAME $DISTRNAME" ;; esac PMTYPE=$CMD } is_active_systemd() { local a SYSTEMCTL=/bin/systemctl SYSTEMD_CGROUP_DIR=/sys/fs/cgroup/systemd [ -x "$SYSTEMCTL" ] || return [ -d "$SYSTEMD_CGROUP_DIR" ] || return a='' mountpoint -q "$SYSTEMD_CGROUP_DIR" || return readlink /sbin/init | grep -q 'systemd' || return # some hack # shellcheck disable=SC2009 ps ax | grep '[s]ystemd' | grep -q -v 'systemd-udev' }