Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 17 additions & 6 deletions core/core.func
Original file line number Diff line number Diff line change
Expand Up @@ -718,12 +718,13 @@ arch_check() {
echo -e "${TAB}If you try it, please report the outcome - success or failure:"
echo -e "${TAB}${BGN}https://github.com/community-scripts/ProxmoxVED/issues${CL}"
echo ""
if [[ ! -t 0 ]]; then
local arm64_src
if ! arm64_src="$(_cs_stdin_source)"; then
msg_error "Not running interactively - refusing to guess on arm64. Set var_arm64=yes to override."
sleep 2
exit 106
fi
read -r -p "${TAB}Continue anyway? (y/N): " arm64_prompt </dev/tty
read -r -p "${TAB}Continue anyway? (y/N): " arm64_prompt <"$arm64_src"
if [[ "${arm64_prompt,,}" =~ ^(y|yes)$ ]]; then
msg_ok "Continuing on arm64 - thanks for testing"
return 0
Expand Down Expand Up @@ -1640,6 +1641,17 @@ show_missing_values_warning() {
return 0
}

# Where to read an answer from, or failure when nobody can answer. Incus has no /dev/tty.
_cs_stdin_source() {
if : 2>/dev/null </dev/tty; then
printf '/dev/tty'
elif [[ -t 0 || "${CS_STDIN_OK:-0}" == "1" ]]; then
printf '/dev/stdin'
else
return 1
fi
}

# ------------------------------------------------------------------------------
# prompt_confirm()
#
Expand Down Expand Up @@ -1693,9 +1705,8 @@ prompt_confirm() {
fi
fi

# Check if running in a TTY
if [[ ! -t 0 ]]; then
# Not a TTY, use default
local prompt_src
if ! prompt_src="$(_cs_stdin_source)"; then
if [[ "$default" == "y" ]]; then
return 0
else
Expand All @@ -1706,7 +1717,7 @@ prompt_confirm() {
# Interactive prompt with timeout
echo -en "${YW}${message} ${hint} (auto-${default} in ${timeout}s): ${CL}"

if read -t "$timeout" -r response </dev/tty; then
if read -t "$timeout" -r response <"$prompt_src"; then
# User provided input
response="${response,,}" # lowercase
case "$response" in
Expand Down
51 changes: 39 additions & 12 deletions incus/backend.func
Original file line number Diff line number Diff line change
Expand Up @@ -1054,23 +1054,15 @@ INNEREOF" >>"${LOGFILE:-$INCUS_BUILD_LOG}" 2>&1 || { msg_error "Failed to push f
_install_script="$(_cs_fetch_text "install/${var_install}.sh")"
_run_env="$(_incus_build_install_env)"
_run_env+=$'\nsource /dev/stdin <<<"$(cat /tmp/incus-functions)"'
_run_env+=$'\n'"$(_incus_prompt_shim)"

# Deliberately NO pty here. Forcing one with `incus exec -t` looks like the
# fix for install scripts that prompt, but apt saves and restores stdin's
# terminal attributes around every dpkg call: on that pty tcsetattr returned
# EIO ("Setting in Stop via TCSAFLUSH for stdin failed"), killing the shell
# mid-install. It died before silent() could record anything, so the run was
# reported as a success against an empty container.
# No pty on purpose: under `incus exec -t` apt's tcsetattr fails with EIO and kills the shell.
set +Eeuo pipefail
trap - ERR
# stdin from /dev/null: without a pty `read -p` prints no prompt at all, so a
# script that asks a question waited on input nobody could see or answer.
# The trailing touch is a completion sentinel: all 552 install scripts run to
# cleanup_lxc/customize and none exits early, so the marker appears if and
# only if the script reached its end.
# The trailing touch is a completion sentinel: no install script exits early.
incus exec "${CT_NAME}" -- bash -c "${_run_env}
${_install_script}
touch /root/.install-${SESSION_ID}.done" </dev/null 2>&1 |
touch /root/.install-${SESSION_ID}.done" 2>&1 |
tee >(sed -u 's/.*\r//' >>"${LOGFILE:-$INCUS_BUILD_LOG}")
# PIPESTATUS, not $?: the line above turns pipefail off, so $? is tee's
# status - always 0. Every non-zero exit from the container was discarded
Expand Down Expand Up @@ -1403,9 +1395,44 @@ export REPO_SOURCE='${REPO_SOURCE:-}'
export REPO_SLUG='${REPO_SLUG:-}'
export TELEMETRY_PLATFORM='incus'
export CS_ANIMATION_OK='$([ -t 1 ] && echo 1 || echo 0)'
export CS_STDIN_OK='$([ -t 0 ] && echo 1 || echo 0)'
EOF
}

# bash shows a `read -p` prompt only on a terminal, so without a pty the question was invisible.
_incus_prompt_shim() {
cat <<'SHIMEOF'
read() {
local -a _args=()
local _prompt="" _flags
while (($#)); do
if [[ "$1" == -*p && "$1" != --* && $# -ge 2 ]]; then
_flags="${1%p}"
[[ "$_flags" != "-" ]] && _args+=("$_flags")
_prompt="$2"
shift 2
continue
fi
_args+=("$1")
shift
done
[[ -n "$_prompt" ]] || {
builtin read "${_args[@]}"
return
}
printf '%s' "$_prompt" >&2
if [[ "${CS_STDIN_OK:-0}" != "1" ]]; then
printf '%s\n' "(no input available - using the default)" >&2
return 0
fi
builtin read "${_args[@]}" || {
printf '\n' >&2
return 0
}
}
SHIMEOF
}

incus_build_container() {
_incus_sync_from_pve_settings
_incus_prepare_install_exports
Expand Down
9 changes: 4 additions & 5 deletions lxc/install.func
Original file line number Diff line number Diff line change
Expand Up @@ -589,12 +589,11 @@ pkg_update() {
else
msg_warn "Find Debian mirrors at: https://www.debian.org/mirror/list"
fi
# Only ask when there is someone to answer. Headless, /dev/tty does not
# exist, the read fails instantly, custom_mirror stays empty and the
# `continue` below spins the loop forever instead of prompting. Falling
# through leaves apt_ok=false, which the caller reports properly.
# Only ask when there is someone to answer: otherwise the loop spins forever.
local mirror_src
while ! is_unattended; do
read -rp " Enter a mirror hostname (or 'skip' to abort): " custom_mirror </dev/tty || break
mirror_src="$(_cs_stdin_source)" || break
read -rp " Enter a mirror hostname (or 'skip' to abort): " custom_mirror <"$mirror_src" || break
[[ -z "$custom_mirror" ]] && continue
[[ "$custom_mirror" == "skip" ]] && break
[[ ! "$custom_mirror" =~ ^[a-zA-Z0-9._-]+$ ]] && {
Expand Down
1 change: 1 addition & 0 deletions ui/API.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ _cs_run_os_section
_cs_run_update
_cs_runtime_cache_dir
_cs_scripts_ref_line
_cs_stdin_source
_dev_step_end
_dev_step_key
_dev_step_start
Expand Down
Loading