epm-sh-functions 21.6 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
}

# copied from strings
is_dirpath()
{
    [ "$1" = "." ] && return $?
    rhas "$1" "/"
}

Vitaly Lipatov's avatar
Vitaly Lipatov committed
225 226 227 228 229 230 231 232 233 234 235 236 237
filter_strip_spaces()
{
        # possible use just
        #xargs echo
        sed -e "s| \+| |g" | \
                sed -e "s|^ ||" | sed -e "s| \$||"
}

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

238 239 240 241 242 243

# 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()
{
244
    echo "$*" | sed -e 's/[]()$*.^|[]/\\&/g'
245 246 247
}


248 249 250
# param true false
subst_option()
{
251
    eval "[ -n \"\$$1\" ]" && echo "$2" || echo "$3"
252 253
}

254 255 256
store_output()
{
    # use make_temp_file from etersoft-build-utils
257
    RC_STDOUT="$(mktemp)" || fatal
258
    remove_on_exit $RC_STDOUT
259 260
    local CMDSTATUS=$RC_STDOUT.pipestatus
    echo 1 >$CMDSTATUS
261
    #RC_STDERR=$(mktemp)
262
    ( LANG=C $@ 2>&1 ; echo $? >$CMDSTATUS ) | tee $RC_STDOUT
Vitaly Lipatov's avatar
Vitaly Lipatov committed
263
    return "$(cat $CMDSTATUS)"
264
    # bashism
265
    # http://tldp.org/LDP/abs/html/bashver3.html#PIPEFAILREF
266
    #return $PIPESTATUS
267 268
}

269 270 271 272 273 274
showcmd_store_output()
{
    showcmd "$@"
    store_output "$@"
}

275 276
clean_store_output()
{
277
    rm -f $RC_STDOUT $RC_STDOUT.pipestatus
278 279
}

280
# run epm, possible from side repo
281 282
epm()
{
283
    if [ "$EPMMODE" = "pipe" ] ; then
284
        epm_main --inscript "$@"
285
        return
286
    fi
287 288 289

    # run epm again to full initialization
    local bashopt=''
290
    [ -n "$debug" ] && bashopt='-x'
291 292

    $CMDSHELL $bashopt $PROGDIR/$PROGNAME --inscript "$@"
293 294 295 296 297
}

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

300
    local bashopt=''
301
    [ -n "$debug" ] && bashopt='-x'
302

303
    sudorun $CMDSHELL $bashopt $PROGDIR/$PROGNAME --inscript "$@"
304
}
Vitaly Lipatov's avatar
Vitaly Lipatov committed
305 306 307 308

# Print error message and stop the program
fatal()
{
309
    if [ -z "$TEXTDOMAIN" ] ; then
310 311 312 313
        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
314 315 316 317 318
#    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
319
}
320

321 322 323 324 325 326 327 328 329 330 331 332 333 334 335
# 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
336 337 338
# Print warning message
warning()
{
339
    if [ -z "$TEXTDOMAIN" ] ; then
340 341 342 343
        set_color $YELLOW >&2
        echo -n "WARNING: " >&2
        restore_color >&2
        echo "$*" >&2
344 345 346
#    else
#        echog "Error in $0: $@" >&2
    fi
Vitaly Lipatov's avatar
Vitaly Lipatov committed
347 348
}

349 350
info()
{
351
    [ -n "$quiet" ] && return
352

353 354 355 356 357 358 359
    # print message to stderr if stderr forwarded to (a file)
    if isatty2 ; then
        isatty || return 0
        echo "$*"
    else
        echo "$*" >&2
    fi
360 361
}

362 363 364
# if we have not sudo, returns 1 and set SUDO variable to fatal
SUDO_TESTED=''
SUDO_CMD='sudo'
365 366
set_sudo()
{
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387
    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

    # if we are root, do not need sudo
    is_root && return

    # start error section
    SUDO_TESTED="1"

    if ! is_command $SUDO_CMD ; then
388
        [ "$nofail" = "nofail" ] || SUDO="fatal 'For this operation run epm under root, or install and tune sudo (http://altlinux.org/sudo)'"
389
        SUDO_TESTED="2"
390 391 392 393 394
        return "$SUDO_TESTED"
    fi

    # if input is a console
    if inputisatty && isatty && isatty2 ; then
395 396 397
        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
398
                [ "$nofail" = "nofail" ] || SUDO="fatal 'For this operation run epm under root, or install and tune sudo (http://altlinux.org/sudo)'"
399
                SUDO_TESTED="3"
400 401
                return "$SUDO_TESTED"
            fi
402 403 404 405
        fi
    else
        # use sudo if one is tuned and tuned without password
        if ! $SUDO_CMD -l -n >/dev/null 2>/dev/null ; then
406
            [ "$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 '"
407
            SUDO_TESTED="4"
408 409 410 411 412 413 414 415 416 417
            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"
418

419 420
}

421 422 423
# return TRUE if we can run privileged command
sudo_allowed()
{
424
    set_sudo nofail
425 426
}

427 428
# wait for n seconds (if possible) during executing command
# args: seconds command
429 430
withtimeout()
{
431 432 433 434 435 436 437 438 439
    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
    #"$@"
440 441
}

442 443
set_eatmydata()
{
444 445 446 447 448 449 450 451 452 453 454
    # 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
455 456
}

457 458
# 
__get_package_for_command()
459
{
460 461 462 463 464 465 466 467
    case "$1" in
        equery|revdep-rebuild)
            echo 'gentoolkit'
            ;;
        update-kernel|remove-old-kernels)
            echo 'update-kernel'
            ;;
    esac
468 469
}

470 471 472 473 474 475 476 477 478 479 480 481 482 483 484
# 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
}

485 486 487

confirm_info()
{
488 489 490 491
    info "$*"
    if [ -z "$non_interactive" ] ; then
        confirm "Are you sure? [y/N]" || fatal "Exiting"
    fi
492 493 494 495

}


496 497
is_root()
{
498 499
    local EFFUID="$(id -u)"
    [ "$EFFUID" = "0" ]
500 501
}

502 503
assure_root()
{
504
    is_root || fatal "run me only under root"
505 506
}

507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543
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
}

544 545 546 547 548 549 550 551 552
esu()
{
    if is_root ; then
        if [ -n "$*" ] ; then
            [ -n "$quiet" ] || showcmd "$*"
            exec "$@"
        else
            # just shell
            showcmd "su -"
553
            a= exec su -
554 555 556 557 558 559
        fi
    fi

    set_pm_type


Vitaly Lipatov's avatar
Vitaly Lipatov committed
560 561 562 563 564 565 566
# TODO:
#quote() {
#    for arg in "$@"; do
#        printf '%s\n' "$arg" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/'/"
#    done
#}

567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582
    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 "$@")"

583
    check_sudo_access_only
584 585
    # sudo is not accessible, will ask root password
    if ! set_sudo ; then
586
        check_su_access
587 588 589
        #info "Enter root password:"
        if [ -n "$*" ] ; then
            [ -n "$quiet" ] || showcmd "su - -c $escaped"
590
            a= exec su - -c "$escaped"
591 592 593
        else
            # just shell
            showcmd "su -"
594
            a= exec su -
595 596 597
        fi
    fi

598 599
    check_sudo_access

600 601 602 603 604 605 606 607 608 609
    #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
}

610 611
regexp_subst()
{
612 613 614
    local expression="$1"
    shift
    sed -i -r -e "$expression" "$@"
615 616
}

Vitaly Lipatov's avatar
Vitaly Lipatov committed
617
# TODO: we we can't use epm directly?
618 619
assure_exists()
{
620 621 622
    load_helper epm-assure
    local package="$2"
    [ -n "$package" ] || package="$(__get_package_for_command "$1")"
623 624 625 626 627

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

628
    ( direct='' interactive=$ask epm_assure "$1" $package $3 ) || fatal
629 630
}

631 632
assure_exists_erc()
{
633 634 635
    load_helper epm-assure
    local package="erc"
    ( direct='' epm_assure "$package" ) || epm ei erc || fatal "erc is not available to install."
636 637
}

638
# will replaced within disabled_eget in packaged version
Vitaly Lipatov's avatar
Vitaly Lipatov committed
639
eget()
640
{
641 642
    # use internal eget only if exists
    if [ -s $SHAREDIR/tools_eget ] ; then
643
        ( EGET_BACKEND=$eget_backend $CMDSHELL $SHAREDIR/tools_eget "$@" )
644 645 646
        return
    fi
    fatal "Internal error: missed tools_eget"
647

Vitaly Lipatov's avatar
Vitaly Lipatov committed
648
    local EGET
649 650 651 652 653
    # 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 "$@"
654 655
}

656

657 658
__epm_assure_7zip()
{
659 660 661 662 663
    # 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
664
    fi
665 666 667 668 669 670
}

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

Vitaly Lipatov's avatar
Vitaly Lipatov committed
671
    __epm_assure_7zip
672

673 674
    # use internal eget only if exists
    if [ -s $SHAREDIR/tools_erc ] ; then
675
        $CMDSHELL $SHAREDIR/tools_erc "$@"
676 677 678
        return
    fi
    fatal "Internal error: missed tools_erc"
679

680 681 682
    # FIXME: we need disable output here, ercat can be used for get output
    assure_exists_erc >/dev/null
    # run external command, not the function
683
    local ERC
684 685
    ERC=$(print_command_path erc) || fatal "Missed command erc from installed package erc"
    $ERC "$@"
686 687 688 689 690
}

# will replaced within disabled_ercat in packaged version
ercat()
{
691 692 693
    local ERCAT
    # use internal eget only if exists
    if [ -s $SHAREDIR/tools_ercat ] ; then
694
        $CMDSHELL $SHAREDIR/tools_ercat "$@"
695 696 697
        return
    fi
    fatal "Internal error: missed tools_ercat"
698

699 700 701 702 703
    # 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 "$@"
704 705
}

Vitaly Lipatov's avatar
Vitaly Lipatov committed
706 707
estrlist()
{
708
    if [ -s $SHAREDIR/tools_estrlist ] ; then
709
        $CMDSHELL $SHAREDIR/tools_estrlist "$@"
710 711 712
        return
    fi
    fatal "missed tools_estrlist"
Vitaly Lipatov's avatar
Vitaly Lipatov committed
713 714 715 716
}

onefile_estrlist()
{
717
    internal_tools_estrlist "$@"
Vitaly Lipatov's avatar
Vitaly Lipatov committed
718 719
}

720 721
# will replaced within eget() in packed version
onefile_eget()
Vitaly Lipatov's avatar
Vitaly Lipatov committed
722
{
723 724 725 726 727
    # 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
728 729
}

730
# TODO: improve and drop!
731 732
get_package_type()
{
733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763
    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
            ;;
        *)
764 765
            # print extension by default
            echo "$1" | sed -e 's|.*\.||'
766 767 768
            return 1
            ;;
    esac
769 770 771
}


772
# print options description from HELPCMD/HELPOPT lines in the code
773
# args: section_name, [file with code]
774 775
get_help()
{
776 777 778
    if [ "$0" = "/dev/stdin" ] || [ "$0" = "sh" ] ; then
        return
    fi
779
    local F="$0"
Vitaly Lipatov's avatar
Vitaly Lipatov committed
780 781 782
    if [ -n "$2" ] ; then
        is_dirpath "$2" && F="$2" || F="$(dirname $0)/$2"
    fi
783

784
    cat "$F" | grep -- "# $1" | while read -r n ; do
Vitaly Lipatov's avatar
Vitaly Lipatov committed
785 786 787 788 789 790
        if echo "$n" | grep -q "# $1: PART: " ; then
            echo
            echo "$n" | sed -e "s|# $1: PART: ||"
            continue
        fi
        echo "$n" | grep -q "^ *#" && continue
791 792 793
        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"
794 795 796
    done
}

797
set_bigtmpdir()
798
{
799 800 801 802
    # 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
803
    [ -n "$BIGTMPDIR" ] || [ -d "/var/tmp" ] && BIGTMPDIR="/var/tmp" || BIGTMPDIR="$TMPDIR"
804 805 806 807 808 809 810
    export BIGTMPDIR
}

assure_tmpdir()
{
    if [ -z "$TMPDIR" ] ; then
        export TMPDIR="/tmp"
Vitaly Lipatov's avatar
Vitaly Lipatov committed
811
        warning "Your have no TMPDIR defined. Using $TMPDIR as fallback."
812 813
    fi

814 815 816 817
    if [ ! -d "$TMPDIR" ] ; then
        fatal "TMPDIR $TMPDIR does not exist."
    fi

818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837
    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 DISTRVENDOR

    # export pack of variables, see epm print info --print-eepm-env
    [ -n "$verbose" ] && $DISTRVENDOR --print-eepm-env
    eval $($DISTRVENDOR --print-eepm-env | grep -v '^ *#')
838 839 840 841 842
}

# FIXME: detect if not recognized
set_pm_type()
{
843 844
    local CMD
    set_distro_info
845

846
# override package manager detection result
847 848 849 850 851
if [ -n "$EPM_BACKEND" ] ; then
    PMTYPE=$EPM_BACKEND
    return
fi
# obsoleted
852
if [ -n "$FORCEPM" ] ; then
853 854
    PMTYPE=$FORCEPM
    return
855 856
fi

857
}
858

859 860
is_active_systemd()
{
861
    [ "$DISTRCONTROL" = "systemd" ]
862
}
863 864 865

assure_distr()
{
866 867 868
    local TEXT="this option"
    [ -n "$2" ] && TEXT="$2"
    [ "$DISTRNAME" = "$1" ] || fatal "$TEXT supported only for $1 distro"
869
}
870 871 872 873 874

# return delimiter sign in depend of package type
get_pkg_name_delimiter()
{
   local pkgtype="$1"
875
   [ -n "$pkgtype" ] || pkgtype="$PKGFORMAT"
876 877 878 879

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

881
# used via remove_on_exit
882 883
__epm_remove_tmp_files()
{
884
    trap "-" EXIT
885 886
    [ -n "$DEBUG" ] && return 0

887 888
    [ -n "$verbose" ] && info "Removing tmp files on exit ..."

889 890
    if [ -n "$to_clean_tmp_dirs" ] ; then
        echo "$to_clean_tmp_dirs" | while read p ; do
891
            rm $verbose -rf "$p" 2>/dev/null
892 893 894 895 896
        done
    fi

    if [ -n "$to_clean_tmp_files" ] ; then
        echo "$to_clean_tmp_files" | while read p ; do
897
            rm $verbose -f "$p" 2>/dev/null
898
        done
899
    fi
900

901 902 903 904
    return 0
}


905 906
remove_on_exit()
{
907 908 909 910
    if [ -z "$set_remove_on_exit" ] ; then
        trap "__epm_remove_tmp_files" EXIT
        set_remove_on_exit=1
    fi
911 912
    while [ -n "$1" ] ; do
        if [ -d "$1" ] ; then
913 914
            to_clean_tmp_dirs="$to_clean_tmp_dirs
$1"
915
        elif [ -f "$1" ] ; then
916 917
            to_clean_tmp_files="$to_clean_tmp_files
$1"
918 919 920 921 922
        fi
        shift
    done
}

923 924 925 926 927
#has_space()
#{
#    estrlist -- has_space "$@"
#}
# use internal implementation for speed
928 929
has_space()
{
930 931 932
        # not for dash:
        [ "$1" != "${1/ //}" ]
        # [ "$(echo "$*" | sed -e "s| ||")" != "$*" ]
933
}
934

935

Vitaly Lipatov's avatar
Vitaly Lipatov committed
936 937
is_url()
{
938
    echo "$1" | grep -q "^[filehtps]*:/"
Vitaly Lipatov's avatar
Vitaly Lipatov committed
939 940
}

941
# print a path to the command if exists in $PATH
942
if a= which which 2>/dev/null >/dev/null ; then
943 944 945 946
    # the best case if we have which command (other ways needs checking)
    # TODO: don't use which at all, it is binary, not builtin shell command
print_command_path()
{
947
    a= which -- "$1" 2>/dev/null
948
}
949
elif a= type -a type 2>/dev/null >/dev/null ; then
950 951
print_command_path()
{
952
    a= type -fpP -- "$1" 2>/dev/null
953 954 955 956
}
else
print_command_path()
{
957
    a= type "$1" 2>/dev/null | sed -e 's|.* /|/|'
958 959 960 961 962 963 964 965 966
}
fi

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

967
# compatibility layer
968

969
# add realpath if missed
970
if ! is_command realpath ; then
971 972 973 974 975 976 977
realpath()
{
    [ -n "$*" ] || return
    readlink -f "$@"
}
fi

978

979 980 981 982 983
# 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" "$@"

984
# add subst if missed
985
if ! is_command subst ; then
986 987 988 989 990
subst()
{
    sed -i -e "$@"
}
fi
991 992


993

994 995
check_core_commands()
{
996 997 998
    #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?)"
999 1000
}