|
1
|
#!/bin/bash
|
|
2
|
|
|
3
|
#set -x # Set to help debug
|
|
4
|
|
|
5
|
show_usage()
|
|
6
|
{
|
|
7
|
cat <<EOF
|
|
8
|
Usage: $0 [-p<path>] [-fsad] [-u<user>]
|
|
9
|
Where:
|
|
10
|
p = Use specific path instead of current directory
|
|
11
|
f = Override thread-safe dynamically linked version with statically linked patched version containing auto_getch_refresh
|
|
12
|
s = Set system-wide environment instead of just current user
|
|
13
|
a = Handle setup of /etc/apt/sources.list and restore when done (requires sudo)
|
|
14
|
u = Update the given user's .bashrc instead of current running user. Typically for when run under sudo
|
|
15
|
d = Dry run. Just show commands.
|
|
16
|
EOF
|
|
17
|
}
|
|
18
|
|
|
19
|
# True if the variable is already exported, or - for the per-user .bashrc, which we
|
|
20
|
# append to rather than rewrite - already present in the target file.
|
|
21
|
have_var()
|
|
22
|
{
|
|
23
|
[ -n "${!1}" ] && return 0
|
|
24
|
[[ "$system" != true ]] && [ -f "$rc_filename" ] && grep -q "$1" "$rc_filename"
|
|
25
|
}
|
|
26
|
|
|
27
|
# Defaults
|
|
28
|
user=$USER
|
|
29
|
homedir=$HOME
|
|
30
|
|
|
31
|
# process options
|
|
32
|
while getopts "h?p:fsadu:" opt; do
|
|
33
|
case $opt in
|
|
34
|
p ) target_dir=$OPTARG ;;
|
|
35
|
f ) patch_ncurses=true ;;
|
|
36
|
s ) system=true ;;
|
|
37
|
a ) handle_apt=true ;;
|
|
38
|
u ) user=$OPTARG
|
|
39
|
homedir=$(getent passwd "$OPTARG" | cut -d: -f6) ;;
|
|
40
|
d ) dry="echo" ;;
|
|
41
|
h | \
|
|
42
|
\? ) show_usage && exit 1
|
|
43
|
exit 1 ;;
|
|
44
|
esac
|
|
45
|
done
|
|
46
|
shift $(($OPTIND - 1))
|
|
47
|
|
|
48
|
# remove previous install, if any
|
|
49
|
$dry rm -rf ncurses*
|
|
50
|
|
|
51
|
# Learn the OS so that we can handle non-Ubuntu "kind of" gracefully
|
|
52
|
. /etc/os-release
|
|
53
|
codename="$VERSION_CODENAME"
|
|
54
|
case "$codename" in
|
|
55
|
ulyana|ulyssa|uma|una) release="focal" ;; # Linux Mint 20.x
|
|
56
|
vanessa|vera|victoria|virginia) release="jammy" ;; # Linux Mint 21.x
|
|
57
|
wilma|xia|zara|zena) release="noble" ;; # Linux Mint 22.x
|
|
58
|
*) release="$codename" ;;
|
|
59
|
esac
|
|
60
|
if [ "$ID" = "rhel" ]; then
|
|
61
|
is_rhel=true
|
|
62
|
fi
|
|
63
|
|
|
64
|
# get up to date version
|
|
65
|
if [[ "$handle_apt" == true ]]; then
|
|
66
|
apt_backup="" # original file saved under /tmp, restored when done
|
|
67
|
apt_created="" # new file we added, removed when done
|
|
68
|
if [[ -f "/etc/apt/sources.list.d/ubuntu.sources" ]]; then
|
|
69
|
# Deb822 format (Ubuntu 24.04 and newer): widen the Types line to add deb-src
|
|
70
|
apt_backup="/etc/apt/sources.list.d/ubuntu.sources"
|
|
71
|
$dry cp "$apt_backup" /tmp
|
|
72
|
$dry sed -i 's/^Types: deb$/Types: deb deb-src/' "$apt_backup"
|
|
73
|
elif [[ -f "/etc/apt/sources.list.d/official-package-repositories.list" ]]; then
|
|
74
|
# Some Linux distros derive a separate deb-src list from the existing deb entries
|
|
75
|
apt_src="/etc/apt/sources.list.d/official-package-repositories.list"
|
|
76
|
apt_created="/etc/apt/sources.list.d/deb-src.list"
|
|
77
|
if [ -n "$dry" ]; then
|
|
78
|
echo "grep -q '^deb-src' $apt_src ||" \
|
|
79
|
"sed -e 's|^deb |deb-src |' $apt_src >> $apt_created"
|
|
80
|
else
|
|
81
|
grep -q '^deb-src' "$apt_src" || \
|
|
82
|
sed -e 's|^deb |deb-src |' "$apt_src" >> "$apt_created"
|
|
83
|
fi
|
|
84
|
else
|
|
85
|
# Legacy one-line format (Ubuntu 22.04 / 20.04 and earlier)
|
|
86
|
apt_backup="/etc/apt/sources.list"
|
|
87
|
$dry cp "$apt_backup" /tmp
|
|
88
|
if [ -n "$dry" ]; then
|
|
89
|
echo "echo \"deb-src http://archive.ubuntu.com/ubuntu $release main restricted universe multiverse\" >> /etc/apt/sources.list"
|
|
90
|
else
|
|
91
|
echo "deb-src http://archive.ubuntu.com/ubuntu $release main restricted universe multiverse" >> /etc/apt/sources.list
|
|
92
|
fi
|
|
93
|
fi
|
|
94
|
$dry apt-get update
|
|
95
|
fi
|
|
96
|
|
|
97
|
# install ncurses source code for this version
|
|
98
|
if [ -z "$is_rhel" ]; then
|
|
99
|
$dry apt-get -q -y source ncurses
|
|
100
|
src_rc=$?
|
|
101
|
else
|
|
102
|
$dry yum install -y ncurses-devel
|
|
103
|
src_rc=$?
|
|
104
|
fi
|
|
105
|
|
|
106
|
if [[ "$handle_apt" == true ]]; then
|
|
107
|
[ -n "$apt_backup" ] && $dry mv "/tmp/$(basename "$apt_backup")" "$apt_backup"
|
|
108
|
[ -n "$apt_created" ] && $dry rm -f "$apt_created"
|
|
109
|
$dry apt-get update
|
|
110
|
fi
|
|
111
|
|
|
112
|
# check if sources obtained
|
|
113
|
if [ "$src_rc" -ne 0 ] && [ -z "$dry" ]; then
|
|
114
|
echo "+------------------------------------------------------------------------------+"
|
|
115
|
echo "| Unable to get NCURSES source tree! |"
|
|
116
|
echo "| Check the available packages list in /etc/apt/sources.list. |"
|
|
117
|
echo "+------------------------------------------------------------------------------+"
|
|
118
|
exit 1
|
|
119
|
fi
|
|
120
|
|
|
121
|
# patching the source files
|
|
122
|
$dry pushd ncurses-6.* > /dev/null || { echo "Unable to enter NCURSES source directory (ncurses-6.*)!"; exit 1; }
|
|
123
|
if [[ "$patch_ncurses" == true ]]; then
|
|
124
|
# $dry wget https://proj.goldencode.com/downloads/ncurses/ncurses_curses_h_in_v6.4+20240113.patch
|
|
125
|
# $dry wget https://proj.goldencode.com/downloads/ncurses/ncurses_lib_getch_c_v6.4+20240113.patch
|
|
126
|
$dry patch include/curses.h.in ../libncurses_curses_h_in_v6.4+20240113.patch
|
|
127
|
$dry patch ncurses/base/lib_getch.c ../libncurses_lib_getch_c_v6.4+20240113.patch
|
|
128
|
fi
|
|
129
|
|
|
130
|
# configure and build object libraries
|
|
131
|
if [[ "$patch_ncurses" == true ]]; then
|
|
132
|
$dry ./configure --with-termlib CFLAGS='-fPIC -O2' --with-abi-version=6 --disable-widec
|
|
133
|
else
|
|
134
|
$dry ./configure --with-termlib CFLAGS='-fPIC -O2' --with-abi-version=6 --disable-widec --with-pthread --enable-pthreads-eintr
|
|
135
|
fi
|
|
136
|
$dry make
|
|
137
|
make_rc=$?
|
|
138
|
|
|
139
|
# make valid reference to updated ncurses.h
|
|
140
|
$dry cd include
|
|
141
|
$dry ln -s curses.h ncurses.h
|
|
142
|
$dry cd ..
|
|
143
|
|
|
144
|
if [[ "$patch_ncurses" == true ]]; then
|
|
145
|
echo "+------------------------------------------------------------------------------+"
|
|
146
|
echo "| Patched NCURSES libraries update completed. |"
|
|
147
|
else
|
|
148
|
echo "+------------------------------------------------------------------------------+"
|
|
149
|
echo "| Thread-safe NCURSES libraries build completed. |"
|
|
150
|
fi
|
|
151
|
|
|
152
|
# Position minimal files if path is specified
|
|
153
|
if [[ -n "$target_dir" ]]; then
|
|
154
|
$dry mkdir -p "$target_dir"
|
|
155
|
$dry cp -r include "$target_dir"
|
|
156
|
$dry cp -r lib "$target_dir"
|
|
157
|
$dry cd "$target_dir"
|
|
158
|
$dry chown -R "$user:$user" "$target_dir"
|
|
159
|
fi
|
|
160
|
|
|
161
|
# Set up environment variable(s) if they are not set already.
|
|
162
|
# Pick the target file first so we can also skip entries already present in it.
|
|
163
|
if [[ "$system" == true ]]; then
|
|
164
|
rc_filename='/etc/profile.d/10-ncurses.sh'
|
|
165
|
msg="| The environment has been changed! Reboot to activate changes |"
|
|
166
|
mode="644"
|
|
167
|
else
|
|
168
|
rc_filename="${homedir}/.bashrc"
|
|
169
|
msg="| The .bashrc has been changed! Please open new console to activate setup! |"
|
|
170
|
fi
|
|
171
|
|
|
172
|
env_update=""; sudo_update=""
|
|
173
|
if ! have_var NCURSES_FWD_STATIC; then
|
|
174
|
if [[ "$patch_ncurses" == true ]]; then
|
|
175
|
env_update+="# set up patched NCURSES root location"$'\n'
|
|
176
|
else
|
|
177
|
env_update+="# set up thread-safe NCURSES root location"$'\n'
|
|
178
|
fi
|
|
179
|
env_update+="export NCURSES_FWD_STATIC=\"$PWD\""$'\n'
|
|
180
|
sudo_update+="Defaults env_keep += NCURSES_FWD_STATIC"$'\n'
|
|
181
|
fi
|
|
182
|
if ! have_var NCURSES_FWD_PTHREADS && [ "$patch_ncurses" != true ]; then
|
|
183
|
env_update+="# and set up thread-safe NCURSES_FWD_PTHREADS variable"$'\n'
|
|
184
|
env_update+="export NCURSES_FWD_PTHREADS=true"$'\n'
|
|
185
|
sudo_update+="Defaults env_keep += NCURSES_FWD_PTHREADS"$'\n'
|
|
186
|
fi
|
|
187
|
|
|
188
|
if [ -n "$env_update" ]; then
|
|
189
|
if [[ "$system" == true ]]; then
|
|
190
|
# Ensure we are making the only entry in the profile.d script
|
|
191
|
[ -f "$rc_filename" ] && $dry rm -f "$rc_filename"
|
|
192
|
if [ -z "$dry" ]; then
|
|
193
|
tmp_sudoers=$(mktemp)
|
|
194
|
echo -n "$sudo_update" > "$tmp_sudoers"
|
|
195
|
if visudo -cf "$tmp_sudoers"; then
|
|
196
|
install -m 440 "$tmp_sudoers" /etc/sudoers.d/10-ncurses
|
|
197
|
else
|
|
198
|
echo "Generated sudoers snippet failed validation; not installing." >&2
|
|
199
|
fi
|
|
200
|
rm -f "$tmp_sudoers"
|
|
201
|
fi
|
|
202
|
fi
|
|
203
|
if [[ -z "$dry" ]]; then
|
|
204
|
echo '' >> "$rc_filename"
|
|
205
|
echo -n "$env_update" >> "$rc_filename"
|
|
206
|
[[ "$system" == true ]] && chmod "$mode" "$rc_filename"
|
|
207
|
fi
|
|
208
|
echo "| --------------------------- WARNING ! -------------------------------- |"
|
|
209
|
echo "$msg"
|
|
210
|
echo "| --------------------------- WARNING ! -------------------------------- |"
|
|
211
|
fi
|
|
212
|
|
|
213
|
echo "| Please do FULL FWD rebuild to activate the changes. |"
|
|
214
|
echo "+------------------------------------------------------------------------------+"
|
|
215
|
|
|
216
|
# back to the starting directory
|
|
217
|
$dry popd > /dev/null
|
|
218
|
|
|
219
|
# On a successful build, clean up the downloaded source artifacts. The extracted
|
|
220
|
# source tree is only disposable when -p copied the libraries elsewhere; otherwise
|
|
221
|
# NCURSES_FWD_STATIC points into it and it must be kept.
|
|
222
|
if [ "$make_rc" -eq 0 ]; then
|
|
223
|
$dry rm -f ncurses_*.dsc ncurses_*.debian.tar.* ncurses_*.orig.tar.*
|
|
224
|
[ -n "$target_dir" ] && $dry rm -rf ncurses-6.*
|
|
225
|
fi
|