aboutsummaryrefslogtreecommitdiff
path: root/reproduce/software/shell/prep-source.sh
blob: dcdc472bc4802bf6e3b64cf94e1ed602a4372109 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#!/usr/bin/env sh
#
# Necessary corrections in the un-packed source of programs to make them
# portable (for example to not use '/bin/sh').
#
# Usage: Run in top source directory (will work on all files within the
#        directory that it is run in ):
#   ./prep-source.sh /FULL/ADDRESS/TO/DESIRED/BIN
#
# Copyright (C) 2024-2025 Mohammad Akhlaghi <mohammad@akhlaghi.org>
#
# This script is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your
# option) any later version.
#
# This script 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 GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this script.  If not, see <http://www.gnu.org/licenses/>.





# Abort the script in case of an error
set -e




# Read the first argument.
bindir="$1"
if [ x"$bindir" = x ]; then
    printf "$0: no argument (location of the 'bin/' directory "
    printf "containing the 'bash' executable)\n"
    exit 1
elif ! [ -d "$bindir" ]; then
    printf "$0: the directory given as the first argument ('$bindir')"
    printf "does not exist"
fi





# Find all the files that contain the '/bin/sh' string and correct them to
# Maneage's own Bash. We are using 'while read' to read the file names line
# by line. This is necessary to account file names that include the 'SPACE'
# character (happens in CMake for example!).
#
# Note that dates are important in the source directory (files depend on
# each other), so we should read the original date and after making. We are
# also not using GNU SED's '-i' ('--in-place') option because the host OS
# may not have GNU SED.
#
# Actual situation which prompted the addition of this step: a Maneage'd
# project (with GNU Bash 5.1.8 and Readline 8.1.1) was being built on a
# system where '/bin/sh' was GNU Bash 5.2.26 and had Readline 8.2.010. The
# newer version of Bash needed the newer Readline library function(s) that
# were not available in Maneage's Readline library. Therefore, as soon as
# the basic software were built and Maneage entered the creation of
# high-level software (where we completely close-off the host environment),
# Maneage crashed with the following '/bin/sh' error:
#
#   /bin/sh: symbol lookup error: /bin/sh: undefined symbol: rl_trim_arg_from_keyseq
#
# This lead to the discovery that through '/bin/sh' the host operating
# system was leaking into our closed Maneage environment which needs to be
# closed. This needs a source-level correction because '/bin/sh' is
# hard-coded in the source code of almost all programs (their build
# scripts); and in special programs like GNU Make, GNU M4 or CMake it is
# actually hardcoded in the source code (not just build scripts).
if [ -f "$bindir/bash" ]; then shpath="$bindir"/bash
else                           shpath="$bindir"/dash
fi
grep -I -r -e'/bin/sh' $(pwd)/* \
    | sed -e's|:|\t|' \
    | awk 'BEGIN{FS="\t"}{print $1}' \
    | sort \
    | uniq \
    | while read filename; do \
         tmp="$filename".tmp; \
         origtime="$(date -R -r "$filename")"; \
         origperm=$(stat -c '%a' "$filename"); \
         sed -e's|/bin/sh|'"$shpath"'|g' "$filename" > "$tmp"; \
         mv "$tmp" "$filename"; \
         chmod $origperm "$filename"; \
         touch -d"$origtime" "$filename"; \
         echo "Corrected /bin/sh in $filename"; \
      done