epm-sh-functions 22.4 KB
Newer Older
Vitaly Lipatov's avatar
Vitaly Lipatov committed
1 2
#!/bin/sh
#
3 4
# Copyright (C) 2012, 2014  Etersoft
# Copyright (C) 2012, 2014  Vitaly Lipatov <lav@etersoft.ru>
Vitaly Lipatov's avatar
Vitaly Lipatov committed
5
#
6 7 8
# 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
Vitaly Lipatov's avatar
Vitaly Lipatov committed
9 10 11 12 13
# (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
14
# GNU Affero General Public License for more details.
Vitaly Lipatov's avatar
Vitaly Lipatov committed
15
#
16 17
# 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/>.
Vitaly Lipatov's avatar
Vitaly Lipatov committed
18 19
#

20
# copied from /etc/init.d/outformat (ALT Linux)
21

22

23
# FIXME on Android: FIX ME! implement ttyname_r() bionic/libc/bionic/stubs.c:366
24 25
inputisatty()
{
26 27 28
    # check stdin
    #tty -s 2>/dev/null
    test -t 0
29 30
}

31 32
isatty()
{
33 34
    # check stdout
    test -t 1
35 36 37 38
}

isatty2()
{
39 40
    # check stderr
    test -t 2
41 42
}

43 44
check_tty()
{
45
    isatty2 || return
46

47 48 49
    # Set a sane TERM required for tput
    [ -n "$TERM" ] || TERM=dumb
    export TERM
50

51
    check_core_commands
52

53 54 55 56 57
    # grep -E from busybox may not --color
    # grep -E from MacOS print help to stderr
    if grep -E --help 2>&1 | grep -q -- "--color" ; then
        export EGREPCOLOR="--color"
    fi
58

59 60 61 62
    is_command tput || return
    # FreeBSD does not support tput -S
    echo | a= tput -S >/dev/null 2>/dev/null || return
    USETTY="tput -S"
63 64
}

65 66 67 68
: ${BLACK:=0} ${RED:=1} ${GREEN:=2} ${YELLOW:=3} ${BLUE:=4} ${MAGENTA:=5} ${CYAN:=6} ${WHITE:=7}

set_boldcolor()
{
69 70 71 72 73
    [ -n "$USETTY" ] || return
    {
        echo bold
        echo setaf $1
    } | $USETTY
74 75
}

76 77
set_color()
{
78 79 80 81
    [ -n "$USETTY" ] || return
    {
        echo setaf $1
    } | $USETTY
82 83
}

84 85
restore_color()
{
86 87 88 89 90
    [ -n "$USETTY" ] || return
    {
        echo op; # set Original color Pair.
        echo sgr0; # turn off all special graphics mode (bold in our case).
    } | $USETTY
91 92
}

Vitaly Lipatov's avatar
Vitaly Lipatov committed
93 94
echover()
{
Vitaly Lipatov's avatar
Vitaly Lipatov committed
95
    [ -z "$verbose" ] && return
96
    echo "$*" >&2
Vitaly Lipatov's avatar
Vitaly Lipatov committed
97 98
}

99 100 101
# echo string without EOL
echon()
{
102 103
    # default /bin/sh on MacOS does not recognize -n
    echo -n "$*" 2>/dev/null || a= /bin/echo -n "$*"
104 105 106
}


Vitaly Lipatov's avatar
Vitaly Lipatov committed
107
# Print command line and run command line
108
showcmd()
Vitaly Lipatov's avatar
Vitaly Lipatov committed
109
{
110 111 112 113 114 115 116
    if [ -z "$quiet" ] ; then
        set_boldcolor $GREEN
        local PROMTSIG="\$"
        is_root && PROMTSIG="#"
        echo " $PROMTSIG $*"
        restore_color
    fi >&2
117 118
}

119 120 121
# Print command
echocmd()
{
122 123 124 125 126
    set_boldcolor $GREEN
    local PROMTSIG="\$"
    is_root && PROMTSIG="#"
    echo -n "$PROMTSIG $*"
    restore_color
127 128
}

129 130 131
# Print command line and run command line
docmd()
{
132 133
    showcmd "$*$EXTRA_SHOWDOCMD"
    "$@"
Vitaly Lipatov's avatar
Vitaly Lipatov committed
134 135
}

136
# Run every arg with docmd
137 138
docmd_foreach()
{
139 140 141 142 143 144 145
    local cmd pkg
    cmd="$1"
    #showcmd "$@"
    shift
    for pkg in "$@" ; do
        docmd $cmd $pkg
    done
146 147
}

148 149 150
# run command line with SUDO
sudorun()
{
151 152 153 154 155 156
    set_sudo
    if [ -z "$SUDO" ] ; then
        "$@"
        return
    fi
    $SUDO "$@"
157 158
}

159
# Print command line and run command line with SUDO
160
sudocmd()
161
{
162 163 164
    set_sudo
    [ -n "$SUDO" ] && showcmd "$SUDO $*" || showcmd "$*"
    sudorun "$@"
165 166
}

167
# Run every arg with sudocmd
168
# Returns on any error
169 170
sudocmd_foreach()
{
171 172 173 174 175 176 177 178
    local cmd pkg
    cmd="$1"
    #showcmd "$@"
    shift
    for pkg in "$@" ; do
        # don't quote $cmd here: it can be a command with an args
        sudocmd $cmd $pkg || return
    done
179 180
}

181 182 183
# print full path to files
make_filepath()
{
184 185 186 187 188 189
    local i
    for i in "$@" ; do
        [ -f "$i" ] || continue
        echo "$i" | grep -q "/" && echo "$i" && continue
        echo "./$i"
    done
190 191
}

192 193
get_firstarg()
{
194
    echon "$1"
195 196 197 198
}

get_lastarg()
{
199 200 201
    local lastarg
    eval "lastarg=\${$#}"
    echon "$lastarg"
202 203
}

204 205 206
# TODO: see etersoft-build-utils/tests/test_isnumber.sh
isnumber()
{
207
    echo "$*" | filter_strip_spaces | grep -q "^[0-9]\+$"
208 209
}

Vitaly Lipatov's avatar
Vitaly Lipatov committed
210 211
# copied from strings
# CHECKME: the same like estrlist has ?
Vitaly Lipatov's avatar
Vitaly Lipatov committed
212
# Note: used grep -E! write '[0-9]+(first|two)', not '[0-9]\+...'
Vitaly Lipatov's avatar
Vitaly Lipatov committed
213 214
rhas()
{
215
    echo "$1" | grep -E -q -- "$2"
Vitaly Lipatov's avatar
Vitaly Lipatov committed
216 217
}

218 219 220 221 222 223 224 225 226 227 228 229 230
# bash specific
startwith()
{
    # rhas "$1" "^$2"
    [[ "$1" = ${2}* ]]
}

is_abs_path()
{
    #echo "$1" | grep -q "^/"
    startwith "$1" "/"
}

Vitaly Lipatov's avatar
Vitaly Lipatov committed
231 232 233 234
# copied from strings
is_dirpath()
{
    [ "$1" = "." ] && return $?
235 236
    # rhas "$1" "/"
    startwith "$1" "/"
Vitaly Lipatov's avatar
Vitaly Lipatov committed
237 238
}

239

Vitaly Lipatov's avatar
Vitaly Lipatov committed
240 241 242 243 244 245 246 247 248 249 250 251 252
filter_strip_spaces()
{
        # possible use just
        #xargs echo
        sed -e "s| \+| |g" | \
                sed -e "s|^ ||" | sed -e "s| \$||"
}

strip_spaces()
{
        echo "$*" | filter_strip_spaces
}

253 254 255 256 257 258

# https://superuser.com/questions/422459/substitution-in-text-file-without-regular-expressions
# http://stackoverflow.com/a/2705678/120999
# use for subst complex string with symbols treating as regexp
sed_escape()
{
259
    echo "$*" | sed -e 's/[]()$*.^|[]/\\&/g'
260 261 262
}


263 264 265
# param true false
subst_option()
{
266
    eval "[ -n \"\$$1\" ]" && echo "$2" || echo "$3"
267 268
}

269 270 271
store_output()
{
    # use make_temp_file from etersoft-build-utils
272
    RC_STDOUT="$(mktemp)" || fatal
273
    remove_on_exit $RC_STDOUT
274 275
    local CMDSTATUS=$RC_STDOUT.pipestatus
    echo 1 >$CMDSTATUS
276
    #RC_STDERR=$(mktemp)
277
    ( LC_ALL=C $@ 2>&1 ; echo $? >$CMDSTATUS ) | tee $RC_STDOUT
Vitaly Lipatov's avatar
Vitaly Lipatov committed
278
    return "$(cat $CMDSTATUS)"
279
    # bashism
280
    # http://tldp.org/LDP/abs/html/bashver3.html#PIPEFAILREF
281
    #return $PIPESTATUS
282 283
}

284 285 286 287 288 289
showcmd_store_output()
{
    showcmd "$@"
    store_output "$@"
}

290 291
clean_store_output()
{
292
    rm -f $RC_STDOUT $RC_STDOUT.pipestatus
293 294
}

295
# run epm, possible from side repo
296 297
epm()
{
298
    if [ "$EPMMODE" = "pipe" ] ; then
299
        epm_main --inscript "$@"
300
        return
301
    fi
302 303 304

    # run epm again to full initialization
    local bashopt=''
305
    [ -n "$debug" ] && bashopt='-x'
306 307

    $CMDSHELL $bashopt $PROGDIR/$PROGNAME --inscript "$@"
308 309 310 311 312
}

# run $SUDO epm, possible from side repo
sudoepm()
{
313
    [ "$EPMMODE" = "pipe" ] && fatal "Can't use sudo epm call from the piped script"
314

315
    local bashopt=''
316
    [ -n "$debug" ] && bashopt='-x'
317

318
    sudorun $CMDSHELL $bashopt $PROGDIR/$PROGNAME --inscript "$@"
319
}
Vitaly Lipatov's avatar
Vitaly Lipatov committed
320 321 322 323

# Print error message and stop the program
fatal()
{
324
    if [ -z "$TEXTDOMAIN" ] ; then
325 326 327 328
        set_color $RED >&2
        echo -n "ERROR: " >&2
        restore_color >&2
        echo "$*  (you can discuss the epm $EPMVERSION problem in Telegram: https://t.me/useepm)" >&2
329 330 331 332 333
#    else
#        echog "Error in $0: $@" >&2
    fi
#    [ "$TERM" = "screen" ] && echo "(screen detected: waiting ten seconds to exit ...)" >&2 && sleep 10
    exit 1
Vitaly Lipatov's avatar
Vitaly Lipatov committed
334
}
335

336 337 338 339 340 341 342 343 344 345 346 347 348 349 350
# Print debug message
debug()
{
    [ -n "$debug" ] || return
    if [ -z "$TEXTDOMAIN" ] ; then
        set_color $YELLOW >&2
        echo -n "WARNING: " >&2
        restore_color >&2
        echo "$*" >&2
#    else
#        echog "Error in $0: $@" >&2
    fi
}


Vitaly Lipatov's avatar
Vitaly Lipatov committed
351 352 353
# Print warning message
warning()
{
354
    if [ -z "$TEXTDOMAIN" ] ; then
355 356 357 358
        set_color $YELLOW >&2
        echo -n "WARNING: " >&2
        restore_color >&2
        echo "$*" >&2
359 360 361
#    else
#        echog "Error in $0: $@" >&2
    fi
Vitaly Lipatov's avatar
Vitaly Lipatov committed
362 363
}

364 365
info()
{
366
    [ -n "$quiet" ] && return
367

368 369 370 371 372 373 374
    # print message to stderr if stderr forwarded to (a file)
    if isatty2 ; then
        isatty || return 0
        echo "$*"
    else
        echo "$*" >&2
    fi
375 376
}

377 378 379 380 381 382 383 384 385 386 387 388 389

check_su_root()
{
    [ "$BASEDISTRNAME" = "alt" ] || return 0

    is_root || return 0

    echo "$PATH" | grep -q "/usr/sbin" && return 0

    fatal "There is missed /usr/sbin path in PATH. Probably you have used 'su' without '-' to get root access. Use 'esu' or 'su -' command to get root permissions."
}


390 391 392
# if we have not sudo, returns 1 and set SUDO variable to fatal
SUDO_TESTED=''
SUDO_CMD='sudo'
393 394
set_sudo()
{
395 396 397 398 399 400 401 402 403 404 405 406 407 408
    local nofail="$1"

    # cache the result
    [ -n "$SUDO_TESTED" ] && return "$SUDO_TESTED"
    SUDO_TESTED="0"

    SUDO=""
    # skip SUDO if disabled
    [ -n "$EPMNOSUDO" ] && return
    if [ "$DISTRNAME" = "Cygwin" ] || [ "$DISTRNAME" = "Windows" ] ; then
        # skip sudo using on Windows
        return
    fi

409 410
    check_su_root

411 412 413 414 415 416 417
    # if we are root, do not need sudo
    is_root && return

    # start error section
    SUDO_TESTED="1"

    if ! is_command $SUDO_CMD ; then
418
        [ "$nofail" = "nofail" ] || SUDO="fatal 'For this operation run epm under root, or install and tune sudo (http://altlinux.org/sudo)'"
419
        SUDO_TESTED="2"
420 421 422 423 424
        return "$SUDO_TESTED"
    fi

    # if input is a console
    if inputisatty && isatty && isatty2 ; then
425 426 427
        if ! $SUDO_CMD -n true ; then
            info "Please enter sudo user password to use sudo in the current session."
            if ! $SUDO_CMD -l >/dev/null ; then
428
                [ "$nofail" = "nofail" ] || SUDO="fatal 'For this operation run epm under root, or install and tune sudo (http://altlinux.org/sudo)'"
429
                SUDO_TESTED="3"
430 431
                return "$SUDO_TESTED"
            fi
432 433 434 435
        fi
    else
        # use sudo if one is tuned and tuned without password
        if ! $SUDO_CMD -l -n >/dev/null 2>/dev/null ; then
436
            [ "$nofail" = "nofail" ] || SUDO="fatal 'Can't use sudo (only passwordless sudo is supported here). Please run epm under root or check http://altlinux.org/sudo '"
437
            SUDO_TESTED="4"
438 439 440 441 442 443 444 445 446 447
            return "$SUDO_TESTED"
        fi
    fi

    SUDO_TESTED="0"
    # FIXME: does not work: sudo -- VARIABLE=some command
    SUDO="$SUDO_CMD"
    #SUDO="$SUDO_CMD --"
    # check for < 1.7 version which do not support -- (and --help possible too)
    #$SUDO_CMD -h 2>/dev/null | grep -q "  --" || SUDO="$SUDO_CMD"
448

449 450
}

451 452 453
# return TRUE if we can run privileged command
sudo_allowed()
{
454
    set_sudo nofail
455 456
}

457 458
# wait for n seconds (if possible) during executing command
# args: seconds command
459 460
withtimeout()
{
461 462 463 464 465 466 467 468 469
    local TO=$(print_command_path timeout || print_command_path gtimeout)
    if [ -x "$TO" ] ; then
        $TO "$@"
        return
    fi
    fatal "Possible indefinite wait due timeout command is missed"
    # fallback: drop time arg and run without timeout
    #shift
    #"$@"
470 471
}

472 473
set_eatmydata()
{
474 475 476 477 478 479 480 481 482 483 484
    # don't use eatmydata (useless)
    return 0
    # skip if disabled
    [ -n "$EPMNOEATMYDATA" ] && return
    # use if possible
    is_command eatmydata || return
    set_sudo
    # FIXME: check if SUDO already has eatmydata
    [ -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
485 486
}

487 488
# 
__get_package_for_command()
489
{
490 491 492 493 494 495 496 497
    case "$1" in
        equery|revdep-rebuild)
            echo 'gentoolkit'
            ;;
        update-kernel|remove-old-kernels)
            echo 'update-kernel'
            ;;
    esac
498 499
}

500 501 502 503 504 505 506 507 508 509 510 511 512 513 514
# 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
}

515 516 517

confirm_info()
{
518 519 520 521
    info "$*"
    if [ -z "$non_interactive" ] ; then
        confirm "Are you sure? [y/N]" || fatal "Exiting"
    fi
522 523 524 525

}


526 527
is_root()
{
528 529
    local EFFUID="$(id -u)"
    [ "$EFFUID" = "0" ]
530 531
}

532 533
assure_root()
{
534
    is_root || fatal "run me only under root"
535 536
}

537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573
check_su_access()
{
    is_command su && return
    [ ! -f /bin/su ] && warning "/bin/su is missed. Try install su package (http://altlinux.org/su)." && return 1
    local group="$(stat -c '%G' /bin/su)" || fatal
    warning "Check if you are in $group group to have access to su command."
    return 1
}

check_sudo_access()
{
    is_command sudo && return
    local cmd=''
    local i
    for i in /bin/sudo /usr/bin/sudo ; do
        [ -f $i ] && cmd="$i"
    done
    [ ! -f $cmd ] && warning "sudo command is missed. Try install sudo package (http://altlinux.org/sudo)." && return 1
    local group="$(stat -c '%G' $cmd)" || fatal
    warning "Check if you are in $group group to have access to sudo command."
    return 1
}

check_sudo_access_only()
{
    is_command sudo && return
    local cmd=''
    local i
    for i in /bin/sudo /usr/bin/sudo ; do
        [ -f $i ] && cmd="$i"
    done
    [ ! -f $cmd ] && return 1
    local group="$(stat -c '%G' $cmd)" || fatal
    warning "sudo command is presence, but is not accessible for you. Check if you are in $group group to have access to sudo command."
    return 1
}

574 575 576 577 578 579 580 581 582
esu()
{
    if is_root ; then
        if [ -n "$*" ] ; then
            [ -n "$quiet" ] || showcmd "$*"
            exec "$@"
        else
            # just shell
            showcmd "su -"
583
            a= exec su -
584 585 586 587 588 589
        fi
    fi

    set_pm_type


Vitaly Lipatov's avatar
Vitaly Lipatov committed
590 591 592 593 594 595 596
# TODO:
#quote() {
#    for arg in "$@"; do
#        printf '%s\n' "$arg" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/'/"
#    done
#}

597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612
    escape_args()
    {
        local output=''
        while [ -n "$1" ] ; do
            if has_space "$1" ; then
                [ -n "$output" ] && output="$output '$1'" || output="'$1'"
            else
                [ -n "$output" ] && output="$output $1" || output="$1"
            fi
            shift
        done
        echo "$output"
    }

    escaped="$(escape_args "$@")"

613
    check_sudo_access_only
614 615
    # sudo is not accessible, will ask root password
    if ! set_sudo ; then
616
        check_su_access
617 618 619
        #info "Enter root password:"
        if [ -n "$*" ] ; then
            [ -n "$quiet" ] || showcmd "su - -c $escaped"
620
            a= exec su - -c "$escaped"
621 622 623
        else
            # just shell
            showcmd "su -"
624
            a= exec su -
625 626 627
        fi
    fi

628 629
    check_sudo_access

630 631 632 633 634 635 636 637 638 639
    #info "You can be asked about your password:"
    if [ -n "$*" ] ; then
        [ -n "$quiet" ] || showcmd "$SUDO su - -c $escaped"
        $SUDO su - -c "$escaped"
    else
        showcmd "$SUDO su -"
        $SUDO su -
    fi
}

640 641
regexp_subst()
{
642 643 644
    local expression="$1"
    shift
    sed -i -r -e "$expression" "$@"
645 646
}

Vitaly Lipatov's avatar
Vitaly Lipatov committed
647
# TODO: we we can't use epm directly?
648 649
assure_exists()
{
650 651 652
    load_helper epm-assure
    local package="$2"
    [ -n "$package" ] || package="$(__get_package_for_command "$1")"
653 654 655 656 657

    # ask for install: https://bugzilla.altlinux.org/42240
    local ask=''
    [ -n "$non_interactive" ] || ask=1

658
    ( verbose='' direct='' interactive=$ask epm_assure "$1" $package $3 ) || fatal
659 660
}

661 662
assure_exists_erc()
{
663 664 665
    load_helper epm-assure
    local package="erc"
    ( direct='' epm_assure "$package" ) || epm ei erc || fatal "erc is not available to install."
666 667
}

668
# will replaced within disabled_eget in packaged version
Vitaly Lipatov's avatar
Vitaly Lipatov committed
669
eget()
670
{
671 672
    # use internal eget only if exists
    if [ -s $SHAREDIR/tools_eget ] ; then
673
        ( EGET_BACKEND=$eget_backend $CMDSHELL $SHAREDIR/tools_eget "$@" )
674 675 676
        return
    fi
    fatal "Internal error: missed tools_eget"
677

Vitaly Lipatov's avatar
Vitaly Lipatov committed
678
    local EGET
679 680 681 682 683
    # FIXME: we need disable output here, eget can be used for get output
    assure_exists eget eget 3.3 >/dev/null
    # run external command, not the function
    EGET=$(print_command_path eget) || fatal "Missed command eget from installed package eget"
    $EGET "$@"
684 685
}

686

687 688
__epm_assure_7zip()
{
689 690 691 692 693
    # install 7zip in any case (can be used)
    if is_command 7z || is_command 7za || is_command 7zr || is_command 7zz ; then
        :
    else
        epm install p7zip
694
    fi
695 696 697 698 699 700
}

# will replaced within disabled_erc in packaged version
erc()
{

Vitaly Lipatov's avatar
Vitaly Lipatov committed
701
    __epm_assure_7zip
702

703 704
    # use internal eget only if exists
    if [ -s $SHAREDIR/tools_erc ] ; then
705
        $CMDSHELL $SHAREDIR/tools_erc "$@"
706 707 708
        return
    fi
    fatal "Internal error: missed tools_erc"
709

710 711 712
    # FIXME: we need disable output here, ercat can be used for get output
    assure_exists_erc >/dev/null
    # run external command, not the function
713
    local ERC
714 715
    ERC=$(print_command_path erc) || fatal "Missed command erc from installed package erc"
    $ERC "$@"
716 717 718 719 720
}

# will replaced within disabled_ercat in packaged version
ercat()
{
721 722 723
    local ERCAT
    # use internal eget only if exists
    if [ -s $SHAREDIR/tools_ercat ] ; then
724
        $CMDSHELL $SHAREDIR/tools_ercat "$@"
725 726 727
        return
    fi
    fatal "Internal error: missed tools_ercat"
728

729 730 731 732 733
    # FIXME: we need disable output here, ercat can be used for get output
    assure_exists_erc >/dev/null
    # run external command, not the function
    ERCAT=$(print_command_path ercat) || fatal "Missed command ercat from installed package erc"
    $ERCAT "$@"
734 735
}

Vitaly Lipatov's avatar
Vitaly Lipatov committed
736 737
estrlist()
{
738
    if [ -s $SHAREDIR/tools_estrlist ] ; then
739
        $CMDSHELL $SHAREDIR/tools_estrlist "$@"
740 741 742
        return
    fi
    fatal "missed tools_estrlist"
Vitaly Lipatov's avatar
Vitaly Lipatov committed
743 744 745 746
}

onefile_estrlist()
{
747
    internal_tools_estrlist "$@"
Vitaly Lipatov's avatar
Vitaly Lipatov committed
748 749
}

750 751
# will replaced within eget() in packed version
onefile_eget()
Vitaly Lipatov's avatar
Vitaly Lipatov committed
752
{
753 754 755 756 757
    # check for both
    # we really need that cross here,
    is_command curl || assure_exists wget
    is_command wget || assure_exists curl
    internal_tools_eget "$@"
Vitaly Lipatov's avatar
Vitaly Lipatov committed
758 759
}

760
# TODO: improve and drop!
761 762
get_package_type()
{
763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793
    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
            ;;
        *.AppImage)
            echo "AppImage"
            return
            ;;
        *)
Vitaly Lipatov's avatar
Vitaly Lipatov committed
794
            if [ -r "$1" ] && file "$1" | grep -q " ELF " ; then
795 796 797
                echo "ELF"
                return
            fi
798 799
            # print extension by default
            echo "$1" | sed -e 's|.*\.||'
800 801 802
            return 1
            ;;
    esac
803 804 805
}


806
# print options description from HELPCMD/HELPOPT lines in the code
807
# args: section_name, [file with code]
808 809
get_help()
{
810 811 812
    if [ "$0" = "/dev/stdin" ] || [ "$0" = "sh" ] ; then
        return
    fi
813
    local F="$0"
Vitaly Lipatov's avatar
Vitaly Lipatov committed
814 815 816
    if [ -n "$2" ] ; then
        is_dirpath "$2" && F="$2" || F="$(dirname $0)/$2"
    fi
817

818
    cat "$F" | grep -- "# $1" | while read -r n ; do
Vitaly Lipatov's avatar
Vitaly Lipatov committed
819 820 821 822 823 824
        if echo "$n" | grep -q "# $1: PART: " ; then
            echo
            echo "$n" | sed -e "s|# $1: PART: ||"
            continue
        fi
        echo "$n" | grep -q "^ *#" && continue
825 826 827
        opt=`echo $n | sed -e "s|) # $1:.*||g" -e 's|"||g' -e 's@^|@@'`
        desc=`echo $n | sed -e "s|.*) # $1:||g"`
        printf "    %-20s %s\n" "$opt" "$desc"
828 829 830
    done
}

831
set_bigtmpdir()
832
{
833 834 835 836
    # TODO: improve BIGTMPDIR conception
    # https://bugzilla.mozilla.org/show_bug.cgi?id=69938
    # https://refspecs.linuxfoundation.org/FHS_3.0/fhs/ch05s15.html
    # https://geekpeach.net/ru/%D0%BA%D0%B0%D0%BA-systemd-tmpfiles-%D0%BE%D1%87%D0%B8%D1%89%D0%B0%D0%B5%D1%82-tmp-%D0%B8%D0%BB%D0%B8-var-tmp-%D0%B7%D0%B0%D0%BC%D0%B5%D0%BD%D0%B0-tmpwatch-%D0%B2-centos-rhel-7
837
    [ -z "$BIGTMPDIR" ] && [ -d "/var/tmp" ] && BIGTMPDIR="/var/tmp" || BIGTMPDIR="$TMPDIR"
838 839 840 841 842 843 844
    export BIGTMPDIR
}

assure_tmpdir()
{
    if [ -z "$TMPDIR" ] ; then
        export TMPDIR="/tmp"
845
        debug "Your have no TMPDIR defined. Using $TMPDIR as fallback."
846 847
    fi

848 849 850 851
    if [ ! -d "$TMPDIR" ] ; then
        fatal "TMPDIR $TMPDIR does not exist."
    fi

852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870
    if [ ! -w "$TMPDIR" ] ; then
        fatal "TMPDIR $TMPDIR is not writable."
    fi
}

set_distro_info()
{
    assure_tmpdir

    set_bigtmpdir

    # don't run again in subprocesses
    [ -n "$DISTRVENDOR" ] && return 0

    DISTRVENDOR=$PROGDIR/distr_info

    # export pack of variables, see epm print info --print-eepm-env
    [ -n "$verbose" ] && $DISTRVENDOR --print-eepm-env
    eval $($DISTRVENDOR --print-eepm-env | grep -v '^ *#')
871 872 873 874 875
}

# FIXME: detect if not recognized
set_pm_type()
{
876 877
    local CMD
    set_distro_info
878

879
# override package manager detection result
880 881 882 883 884
if [ -n "$EPM_BACKEND" ] ; then
    PMTYPE=$EPM_BACKEND
    return
fi
# obsoleted
885
if [ -n "$FORCEPM" ] ; then
886 887
    PMTYPE=$FORCEPM
    return
888 889
fi

890
}
891

892 893
is_active_systemd()
{
894
    [ "$DISTRCONTROL" = "systemd" ]
895
}
896 897 898

assure_distr()
{
899 900 901
    local TEXT="this option"
    [ -n "$2" ] && TEXT="$2"
    [ "$DISTRNAME" = "$1" ] || fatal "$TEXT supported only for $1 distro"
902
}
903 904 905 906 907

# return delimiter sign in depend of package type
get_pkg_name_delimiter()
{
   local pkgtype="$1"
908
   [ -n "$pkgtype" ] || pkgtype="$PKGFORMAT"
909 910 911 912

   [ "$pkgtype" = "deb" ] && echo "_" && return
   echo "-"
}
913

914
# used via remove_on_exit
915 916
__epm_remove_tmp_files()
{
917
    trap "-" EXIT
918 919
    [ -n "$DEBUG" ] && return 0

920 921
    [ -n "$verbose" ] && info "Removing tmp files on exit ..."

922 923
    if [ -n "$to_clean_tmp_dirs" ] ; then
        echo "$to_clean_tmp_dirs" | while read p ; do
924 925
            [ -n "$verbose" ] && echo "rm -rf '$p'"
            rm -rf "$p" 2>/dev/null
926 927 928 929 930
        done
    fi

    if [ -n "$to_clean_tmp_files" ] ; then
        echo "$to_clean_tmp_files" | while read p ; do
931
            rm $verbose -f "$p" 2>/dev/null
932
        done
933
    fi
934

935 936 937 938
    return 0
}


939 940
remove_on_exit()
{
941 942 943 944
    if [ -z "$set_remove_on_exit" ] ; then
        trap "__epm_remove_tmp_files" EXIT
        set_remove_on_exit=1
    fi
945 946
    while [ -n "$1" ] ; do
        if [ -d "$1" ] ; then
947 948
            to_clean_tmp_dirs="$to_clean_tmp_dirs
$1"
949
        elif [ -f "$1" ] ; then
950 951
            to_clean_tmp_files="$to_clean_tmp_files
$1"
952 953 954 955 956
        fi
        shift
    done
}

957 958 959 960 961
#has_space()
#{
#    estrlist -- has_space "$@"
#}
# use internal implementation for speed
962 963
has_space()
{
964 965 966
        # not for dash:
        [ "$1" != "${1/ //}" ]
        # [ "$(echo "$*" | sed -e "s| ||")" != "$*" ]
967
}
968

969

Vitaly Lipatov's avatar
Vitaly Lipatov committed
970 971
is_url()
{
972
    echo "$1" | grep -q "^[filehtps]*:/"
Vitaly Lipatov's avatar
Vitaly Lipatov committed
973 974
}

975
# print a path to the command if exists in $PATH
976
if a= type -a type 2>/dev/null >/dev/null ; then
977 978
print_command_path()
{
979
    a= type -fpP -- "$1" 2>/dev/null
980
}
981 982 983
elif a= which which 2>/dev/null >/dev/null ; then
    # the best case if we have which command (other ways needs checking)
    # TODO: don't use which at all, it is a binary, not builtin shell command
984 985
print_command_path()
{
986
    a= which -- "$1" 2>/dev/null
987 988 989 990
}
else
print_command_path()
{
991
    a= type "$1" 2>/dev/null | sed -e 's|.* /|/|'
992 993 994 995 996 997 998 999 1000
}
fi

# check if <arg> is a real command
is_command()
{
    print_command_path "$1" >/dev/null
}

1001
# compatibility layer
1002

1003
# add realpath if missed (with -s support)
1004
if ! is_command realpath ; then
1005 1006 1007
realpath()
{
    [ -n "$*" ] || return
1008 1009 1010 1011 1012
    if [ "$1" = "-s" ] ; then
        shift
        echo "$(cd "$(dirname "$1")" && pwd -P)/$(basename "$1")" #"
        return
    fi
1013 1014 1015 1016
    readlink -f "$@"
}
fi

1017

1018 1019 1020 1021 1022
# TODO: use perl if sed -i is not accessible
# sed -i is only supported in GNU sed.
#  sed -i "s/$find/$replace/g" "$@"
#  perl -p -i -e "s/$find/$replace/g" "$@"

1023
# add subst if missed
1024
if ! is_command subst ; then
1025 1026 1027 1028 1029
subst()
{
    sed -i -e "$@"
}
fi
1030 1031 1032

check_core_commands()
{
1033 1034 1035
    #which which >/dev/null || fatal "Can't find which command (which or debianutils package is missed?)"
    is_command grep || fatal "Can't find grep command (coreutils package is missed?)"
    is_command sed || fatal "Can't find sed command (sed package is missed?)"
1036 1037
}