yast/yast-yast2

View on GitHub
scripts/yast2

Summary

Maintainability
Test Coverage
#!/bin/bash

# File:        /sbin/yast2
# Module:    yast2
# Summary:    Main YaST2 start script
# Authors:    Mathias Kettner <kettner@suse.de>
#        Klaus Kaempf <kkaempf@suse.de>
#        Ludwig Nussel <lnussel@suse.de>
#        Arvin Schnell <aschnell@suse.de>
#
# This script is called when the user just types 'yast2'. It starts
# the qt user interface in case the DISPLAY variable is set and other-
# wise ncurses. It starts then the module 'menu' which implements
# the configuration and administration menu.

# FATE#317637, bsc#877447: In installation system, we call the installer
# script directly and then exit
if [ -f /.instsys.config ]; then
  echo "Starting Installer"
  /usr/lib/YaST2/startup/YaST2.First-Stage
  exit $?
fi

export PATH=/sbin:/usr/sbin:$PATH

# make sure the system ruby is used, bnc#845897
unset GEM_HOME GEM_PATH RUBYLIB RUBYPATH RUBYOPT

# we need input methods for many locales bnc#776567
export QT_IM_MODULE=xim GTK_IM_MODULE=xim

# Do not load libproxy modules (config_kde4 module crashes because of Qt4/Qt5
# clash), empty path causes that the installed modules are not found. Sysconfig
# and envvar extensions are still loaded, /etc/sysconfig/proxy values are still
# used correctly (see bnc#866692 for details).
export PX_MODULE_PATH=""

# allow for a different prefix
# strip the basename off $0, which can be: (bnc#382216, bnc#458385)
# /sbin/yast2, /sbin/yast, yast2 (sh -x yast2 ...), /sbin/yast2 (PATH=/sbin/:...)
shopt -s extglob
mydir=${0%%*(/)[YyZz]a[Ss][Tt]?(2)}
if [[ -z "$mydir" || "$mydir" = /sbin || -n "$TESTING_YAST2" ]]; then
    YAST_PREFIX=/usr
else
    YAST_PREFIX=${mydir%/sbin}
fi

[[ -n "$TESTING_YAST2" ]] && YAST2FUNCS="$(dirname $0)/yast2-funcs" || YAST2FUNCS=$YAST_PREFIX/lib/YaST2/bin/yast2-funcs
# load common script functions
. $YAST2FUNCS


# check that system directories are non-empty - bnc #450643
mount_ok=1
check_mount_ok()
{
    if test -z `ls $1 2>/dev/null | head -n1`; then
        echo "The $1 filesystem is not mounted."
        mount_ok=0
    fi
}
check_mount_ok /proc
check_mount_ok /sys
check_mount_ok /dev
if test $mount_ok -eq 0 -a -z "$TESTING_YAST2"; then
    echo "If you are running in a chroot environment, bind-mount missing filesystems."
    exit 1
fi

exit_code=0

# Accumulated arguments for both the Qt UI and y2cc; currently supported:
# --fullscreen
# --noborder
# well also for gtk and ncurses
# add hints for ui about app name and icon
Y2UI_ARGS="-name YaST2 -icon yast"
GNOME_SHELL="$ybindir/y2controlcenter-gnome"
KDE_SHELL="$ybindir/y2controlcenter"

printhelp()
{
    echo "Usage: $0 [OPTIONS] [MODULE] [module specific parameters]"
    echo
    echo "OPTIONS:"
    echo "    -h, --help    this message"
    echo "    -l, --list    list all available modules"
    echo "    --qt            use the QT graphical user interface"
    echo "    --gtk           use the GTK graphical user interface"
    echo "    --ncurses       use the NCURSES text-mode user interface"
    echo "    -g, --geometry    default window size (qt only)"
    echo "    --noborder      no window manager border for main window"
    echo "    --fullscreen    use full screen"
    echo
}

listmodules()
{
    list=`/bin/ls -1 $YAST_PREFIX/share/applications/YaST2/*.desktop 2>/dev/null`

    if [ -z "$list" ] ; then
    echo "No modules installed"
    else
    echo "Available modules:"
    echo
    grep -h "X-SuSE-YaST-Call=" $list | \
        sed 's|X-SuSE-YaST-Call=\([^ ]\+\)\( .*\)\?|\1|' | \
        sort -u
    fi
}

# Probes for default desktop GUI
probe_desktop_gui()
{
    if [ "$DESKTOP_SESSION" = "gnome" -o \
         "$DESKTOP_SESSION" = "LXDE" -o \
         "$DESKTOP_SESSION" = "xfce" ]; then
    DESKTOP_GUI="gtk"
    elif echo $WINDOWMANAGER | grep -qi "\(gnome\|xfce|lxde\)"; then
    DESKTOP_GUI="gtk"
    else
    DESKTOP_GUI="qt"
    fi
    if [ "$DESKTOP_GUI" = "qt" -a ! -x "$KDE_SHELL" ]; then
    DESKTOP_GUI="gtk"
    fi
    if [ "$DESKTOP_GUI" = "gtk" -a ! -x "$GNOME_SHELL" ]; then
    DESKTOP_GUI="qt"
    fi
}

# Select which control center shell we want to use
select_control_center()
{
    # 'auto' detects desktop
    if [ "$WANTED_SHELL" = "auto" ]; then
    probe_desktop_gui
    WANTED_SHELL=$DESKTOP_GUI
    fi

    # select binary
    y2ccbin=""
    case "$WANTED_SHELL" in
    gtk)
            # gnome control center use different format of arguments (bsc#1058376)
            Y2UI_ARGS="--gtk-name=YaST2 --class=yast"
        y2ccbin="$GNOME_SHELL"
        ;;
    *)
        y2ccbin="$KDE_SHELL"
        ;;
    esac
}

# Select which toolkit we want to use (F#301083)
select_gui_frontend()
{
    if [ "$WANTED_GUI" = "auto" ]; then
    probe_desktop_gui
    WANTED_GUI=qt
    GUI_SELECTION=auto
    fi

    if [ "$WANTED_GUI" = "gtk" ]; then
    if check_qt; then
        SELECTED_GUI=qt
        WANTED_GUI=qt
        if [ "$GUI_SELECTION" != "auto" ]; then
        echo >&2 "The GTK GUI has been retired, falling back to Qt."
        fi
    else
        echo >&2 "The GTK GUI has been retired, falling back to ncurses."
    fi
    elif [ "$WANTED_GUI" = "qt" ]; then
    if check_qt; then
        SELECTED_GUI=qt
    else
        echo >&2 "Qt GUI wanted but not found, falling back to ncurses."
    fi
    elif [ "$SELECTED_GUI" != "gtk" -a "$WANTED_GUI" != "ncurses" ]; then
    echo >&2 "Unknown GUI '$WANTED_GUI', falling back to ncurses."
    fi
}


SNAPPERBIN=/usr/bin/snapper

snapshot_pre()
{
    if [ "$1" != "menu" -a "$1" != "migration" ]; then
    if [ "$USE_SNAPPER" = "yes" -a -x $SNAPPERBIN ] ; then
        SNAPSHOT_NUMBER=`$SNAPPERBIN create --type=pre --cleanup-algorithm=number --print-number --description="yast $1"`
    fi
    fi
}

snapshot_post()
{
    if [ "$1" != "menu" -a "$1" != "migration" ]; then
    if [ "$USE_SNAPPER" = "yes" -a -x $SNAPPERBIN -a "$SNAPSHOT_NUMBER" != '' ] ; then
        $SNAPPERBIN create --type=post --cleanup-algorithm=number --pre-number=$SNAPSHOT_NUMBER
    fi
    fi
}

chef_is_running ()
{
  service chef-client status >/dev/null 2>&1
}

# ask user if he want to continue despite there is chef-client running
# return 0 if user decided to continue
chef_warning_continue ()
{
  $ybindir/y2start other_tools_warning --arg chef "$SELECTED_GUI" $Y2_GEOMETRY $Y2UI_ARGS
}

# Check if chef-client is running and warn user about it (bnc#803358)
# Returns 0 if user confirmed the conflict and wants to exit before starting YaST.
# (check for other tools (like puppet) may be added here)
other_tools_are_conflicting ()
{
  # - no need to check for installation/firstboot, they are started directly with y2start

  if ! chef_is_running; then
    return 1
  fi

  # existing arguments for yast module = CLI mode
  # continue, but print a warning
  if [ -n "$1"  ]; then
    echo "Warning: Chef Client is running. Your changes may be overridden by Chef later." >&2
    return 1
  fi

  if chef_warning_continue; then
    return 1
  fi
  return 0
}

TEMP=`/usr/bin/getopt -o hlg:s:Si --long help,list,kcontrol,geometry:,style:,strings,install,update,remove,fullscreen,noborder,qt,gtk,ncurses \
     -n 'yast2' -- "$@"`

if [ $? != 0 ] ; then echo "Exit." >&2 ; exit 1 ; fi

# Note the quotes around `$TEMP': they are essential!
eval set -- "$TEMP"

while true ; do
    case "$1" in
        -h|--help) if test "$2" = '--' -a -n "$3" ; then CMDLINE_HELP="help" ; else printhelp && exit 0 ; fi ; shift ;;
        -l|--list) listmodules; exit 0 ;;
        -g|--geometry) Y2_GEOMETRY="-geometry $2"; shift 2; ;;
        -i|--install) Y2_INSTALL_PACKAGES=true; Y2_INSTALL_ACTION=install; shift ;;
        --update) Y2_INSTALL_PACKAGES=true; Y2_INSTALL_ACTION=update; shift ;;
        --remove) Y2_INSTALL_PACKAGES=true; Y2_INSTALL_ACTION=remove; shift ;;
                --fullscreen) Y2UI_ARGS="$Y2UI_ARGS --fullscreen"; shift ;;
        --noborder)   Y2UI_ARGS="$Y2UI_ARGS --noborder"  ; shift ;;
        --kcontrol)   Y2UI_ARGS="$Y2UI_ARGS --kcontrol_id YaST" ; shift ;;
        --qt)  export CMDLINE_UI="qt"  ; shift ;;
        --gtk)  export CMDLINE_UI="gtk"  ; shift ;;
        --ncurses)  unset DISPLAY ;  unset WAYLAND_DISPLAY ; shift ;;
        --) shift ; break ;;
        *) echo "Unrecognized option $1" ; exit 1 ;;

            # IMPORTANT: Remember to change that "getopt" call above, too
            # if you change anything here!
    esac
done

# deprecated, drop after SLE12
if [ "$Y2_INSTALL_PACKAGES" = "true" ]; then
    if [ $# -eq 0 ]; then
        echo "DEPRECATED. Use sw_single directly: $0 sw_single" >&2
        export module="sw_single"
    else
        # support passing text files with packages
        # any ycp file support is dropped
        if [[ -f "$1" && ! "$1" == *rpm ]] ; then
          cmd="zypper --non-interactive $Y2_INSTALL_ACTION \`cat \"$1\"\`"
        else
          cmd="zypper --non-interactive $Y2_INSTALL_ACTION $@"
        fi

        echo "DEPRECATED. Use zypper directly: $cmd" >&2

        eval "$cmd"
        exit $?
    fi
else
    # allow module as argument, defaults to "menu"
    export module="${1-menu}"
    shift
fi

# Pass the arguments to client:

if [ -n "$CMDLINE_HELP" ]; then
    set -- $@ help;
fi
ARGS=( )
for i in "$@"; do
  ARGS+=( "--arg" )
  ARGS+=( "$i" )
done
set -- "${ARGS[@]}"

case "`basename $0`" in
    YaST|yast|yast1|zast)
        if [ -z "$CMDLINE_UI" ]; then
            unset DISPLAY;
                        unset WAYLAND_DISPLAY;
        fi
    ;;
esac

if [ "$UID" = 0 ]; then
    echo $$ > /var/run/yast.pid
fi

set_lang_from_sysconfig

# default defaults
WANTED_GUI="auto"
WANTED_SHELL="auto"
DESKTOP_GUI="qt"

# read system settings
if [ -f /etc/sysconfig/yast2 ]; then
    source /etc/sysconfig/yast2
fi
# read user settings
if [ -f "$HOME/.yast2/yast2" ]; then
    source "$HOME/.yast2/yast2"
fi

if [ -n "$CMDLINE_UI" ]; then
    WANTED_GUI="$CMDLINE_UI"
    WANTED_SHELL="$CMDLINE_UI"
fi

# Fallback GUI
SELECTED_GUI=ncurses
# if we have a DISPLAY or WAYLAND_DISPLAY, select a preferred GUI
if [ -n "$DISPLAY" -o -n "$WAYLAND_DISPLAY" ]; then
    select_gui_frontend
    # for wayland only environment, switch qt to use it (bsc#1083907)
    if [ -n "$WAYLAND_DISPLAY" -a -z "$DISPLAY" ]; then
      export QT_QPA_PLATFORM=wayland
    fi
fi

if [ -n "$TESTING_YAST2" ]; then
  SELECTED_GUI="UI"
fi

if [ "$SELECTED_GUI" = "ncurses" ]; then
    if check_ncurses ; then
    TTY=$(/usr/bin/tty)
    TTY=${TTY#/dev/}
    case "$TTY" in
        tty[0-9]|tty[0-9][0-9])
            TTY=console
        ;;
    esac

    # The part below has changed: we don't use 'testutf8' any longer, i.e.
    # don't start YaST in UTF-8 locale by default and don't fix the settings
    # in rxvt*|vt*|xterm*|linux|screen* (trust the locale).
    # See bnc#556555 and bnc#436378.
        if test "$TERM" = "linux" -a "$TTY" = "console" ; then
        case "$LANG" in
        # if it is known that a language doesn't yet work well with ncurses
        # on console use English instead:
        ja*|ko*|zh*)
            if test `locale charmap` = "UTF-8" ; then
            export LANG=en_US.UTF-8
            export LC_CTYPE=en_US.UTF-8
            export LC_ALL=en_US.UTF-8 # just to make sure.
            else
            export LANG=en_US
            export LC_CTYPE=en_US
            export LC_ALL=en_US # just to make sure.
            fi
            ;;
         esac
    fi

    # set color theme, if defined
    if [ -n "$Y2NCURSES_COLOR_THEME" ]; then
        export Y2NCURSES_COLOR_THEME="$Y2NCURSES_COLOR_THEME"
    fi

    else
    rpm -V yast2-core yast2-ncurses yast2-qt yast2-gtk >&2
    echo "Something is wrong with the YaST user interface." >&2
    exit_code=1        # also skips y2start later
    fi
    if [ -n "$DISPLAY" -a ! -t 0 ]; then
    rpm -V yast2-core yast2-ncurses yast2-qt yast2-gtk >&2
    echo "Something is wrong with the YaST user interface, NCurses selected but no terminal available." >&2
    exit_code=1        # also skips y2start later
    fi
elif [ "$SELECTED_GUI" = "qt" ]; then

    set_qt_env

    # find which control center shell we want, if there is none we
    # fall back to the built-in ycp menu
    y2ccbin=""
    if [ $module == "menu" ]; then
    select_control_center
    fi
elif [ "$SELECTED_GUI" = "UI" ]; then
  echo "Testing UI only"
else
    echo >&2 "Internal error, unhandled '$SELECTED_GUI'"
fi

# Used for intergation tests, using libyui YUILoader::loadUI logic instead
# of direct loadPlugin plugin call. When using UI, dummy UI will be created
if [ -n "$Y2TEST" ]; then
  SELECTED_GUI="ui"
  echo "Integration UI tests"
fi

# do it!
# $@ are args for ycp
if [ $module == "menu" -a -x "$y2ccbin" ] ; then
    $y2ccbin $Y2UI_ARGS "$@"
    exit_code=$?
elif test $module != "menu" && other_tools_are_conflicting "$@" ; then
    exit_code=1
else
    # In case YaST has to be restarted, create this file
    # and exit. Script that creates the file should also
    # remove it itself.
    case "$module" in
    # special cases
    menu) REDO_FILE=/var/lib/YaST2/restart_menu ;;
    online_update) REDO_FILE=/var/lib/YaST2/selected_patches.ycp ;;
    # all other cases when YaST has to be restarted
    *) REDO_FILE=/var/lib/YaST2/restart_yast ;;
    esac
    snapshot_pre $module

    # remove the redo file if it already exists before starting the module,
    # avoid possible infinite loop (bsc#842910)
    rm -f "$REDO_FILE"

    #  break out on errors, #343258
    while [ $exit_code = 0 ]; do
    $ybindir/y2start $module "$@" "$SELECTED_GUI" $Y2_GEOMETRY $Y2UI_ARGS
    exit_code=$?
    if [ -z "$REDO_FILE" -o ! -f "$REDO_FILE" ]; then
        break
    fi
    done
    snapshot_post $module

    # check the reboot flag
    if [ -f /var/lib/YaST2/reboot ];then
        rm -f /var/lib/YaST2/reboot
        /sbin/shutdown -r now
    fi
fi

if [ "$UID" = 0 ]; then
    rm -f /var/run/yast.pid
fi

exit $exit_code