• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/bin/sh -e
2
3# The only purpose of the above shebang is to orient shellcheck right.
4# To make CI scripts maintenance simpler, copies of this file in the
5# libpcap, tcpdump and tcpslice git repositories should be identical.
6# Please mind that Solaris /bin/sh before 11 does not support the $()
7# command substitution syntax, hence the "-e SC2006" flag in Makefile.
8
9# A poor man's mktemp(1) for OSes that don't have one (e.g. AIX 7, Solaris 9).
10mktempdir_diy() {
11    while true; do
12        # /bin/sh implements $RANDOM in AIX 7, but not in Solaris before 11,
13        # thus use dd and od instead.
14        mktempdir_diy_suffix=`dd if=/dev/urandom bs=4 count=1 2>/dev/null | od -t x -A n | head -1 | tr -d '\t '`
15        [ -z "$mktempdir_diy_suffix" ] && return 1
16        mktempdir_diy_path="${TMPDIR:-/tmp}/${1:?}.${mktempdir_diy_suffix}"
17        # "test -e" would be more appropriate, but it is not available in
18        # Solaris /bin/sh before 11.
19        if [ ! -d "$mktempdir_diy_path" ]; then
20            mkdir "$mktempdir_diy_path"
21            chmod go= "$mktempdir_diy_path"
22            echo "$mktempdir_diy_path"
23            break
24        fi
25        # Try again (very unlikely, just in case).
26    done
27}
28
29mktempdir() {
30    mktempdir_prefix=${1:-tmp}
31    case `os_id` in
32    Darwin-*|FreeBSD-*|NetBSD-*)
33        # In these operating systems mktemp(1) always appends an implicit
34        # ".XXXXXXXX" suffix to the requested template when creating a
35        # temporary directory.
36        mktemp -d -t "$mktempdir_prefix"
37        ;;
38    SunOS-5.10|SunOS-5.11)
39        # Although the suffix is optional, specify it for consistent results.
40        mktemp -d -t "${mktempdir_prefix}.XXXXXXXX"
41        ;;
42    SunOS-*|AIX-*)
43        mktempdir_diy "$mktempdir_prefix"
44        ;;
45    *)
46        # At least Haiku, Linux and OpenBSD implementations require explicit
47        # trailing X'es in the template, so make it the same suffix as above.
48        # XXX - is MSYS2 GNU-based, so that it would be like Linux?
49        mktemp -d -t "${mktempdir_prefix}.XXXXXXXX"
50        ;;
51    esac
52}
53
54print_sysinfo() {
55    uname -a
56    printf 'OS identification: '
57    os_id
58    date
59}
60
61# Try to make the current C compiler print its version information (usually
62# multi-line) to stdout.
63cc_version_nocache() {
64    : "${CC:?}"
65    case `basename "$CC"` in
66    gcc*|egcc*|clang*|tcc*)
67        # GCC and Clang recognize --version, print to stdout and exit with 0.
68        "$CC" --version
69        ;;
70    xl*)
71        # XL C 12.1 and 13.1 recognize "-qversion", print to stdout and exit
72        # with 0. XL C 12.1 on an unknown command-line flag displays its man
73        # page and waits.
74        # XL C 16.1 recognizes "-qversion" and "--version", prints to stdout
75        # and exits with 0. Community Edition also prints a banner to stderr.
76        "$CC" -qversion 2>/dev/null
77        ;;
78    sun*)
79        # Sun compilers recognize -V, print to stderr and exit with an error.
80        "$CC" -V 2>&1 || :
81        ;;
82    cc)
83        case `os_id` in
84        SunOS-*)
85            # Most likely Sun C.
86            "$CC" -V 2>&1 || :
87            ;;
88        Darwin-*)
89            # Most likely Clang.
90            "$CC" --version
91            ;;
92        Linux-*|FreeBSD-*|NetBSD-*|OpenBSD-*)
93            # Most likely Clang or GCC.
94            "$CC" --version
95            ;;
96        esac
97        ;;
98    cl)
99        # Visual Studio's compiler doesn't have a "print the compiler
100        # version" option, but we can get version information by
101        # running it with no options, sending its standard error to
102        # the standard output, and throwing out the usage message;
103        # as we have MSYS2, we can just "head" it out.
104        #
105        # XXX - does it exit with an error?
106        "$CC" 2>&1 | head -2
107        ;;
108    *)
109        "$CC" --version || "$CC" -V || :
110        ;;
111    esac
112}
113
114cc_version() {
115    echo "${cc_version_cached:=`cc_version_nocache`}"
116}
117
118print_cc_version() {
119    cc_version
120    printf 'Compiler identification: '
121    cc_id
122}
123
124# For the current C compiler try to print a short and uniform identification
125# string (such as "gcc-9.3.0") that is convenient to use in a case statement.
126cc_id_nocache() {
127    cc_id_firstline=`cc_version | head -1`
128    : "${cc_id_firstline:?}"
129
130    cc_id_guessed=`echo "$cc_id_firstline" | sed 's/^.*clang version \([0-9\.]*\).*$/clang-\1/'`
131    if [ "$cc_id_firstline" != "$cc_id_guessed" ]; then
132        echo "$cc_id_guessed"
133        return
134    fi
135
136    cc_id_guessed=`echo "$cc_id_firstline" | sed 's/^IBM XL C.*, V\([0-9\.]*\).*$/xlc-\1/'`
137    if [ "$cc_id_firstline" != "$cc_id_guessed" ]; then
138        echo "$cc_id_guessed"
139        return
140    fi
141
142    cc_id_guessed=`echo "$cc_id_firstline" | sed 's/^.* Sun C \([0-9\.]*\) .*$/suncc-\1/'`
143    if [ "$cc_id_firstline" != "$cc_id_guessed" ]; then
144        echo "$cc_id_guessed"
145        return
146    fi
147
148    cc_id_guessed=`echo "$cc_id_firstline" | sed 's/^Microsoft (R) C\/C++ Optimizing Compiler Version \([0-9\.]*\) .*$/msvc-\1/'`
149    if [ "$cc_id_firstline" != "$cc_id_guessed" ]; then
150        echo "$cc_id_guessed"
151        return
152    fi
153
154    # Examples of installed packages:
155    # "tcc version 0.9.27 (x86_64 Linux)"
156    # "tcc version 0.9.27 2023-07-05 mob@5b28165 (x86_64 OpenBSD)"
157    # Example of a development version:
158    # "tcc version 0.9.28rc 2024-04-28 mob@0aca8611 (x86_64 Linux)"
159    cc_id_guessed=`echo "$cc_id_firstline" | sed 's/^.*tcc version \([0-9\.rc]*\).*$/tcc-\1/'`
160    if [ "$cc_id_firstline" != "$cc_id_guessed" ]; then
161        echo "$cc_id_guessed"
162        return
163    fi
164
165    # OpenBSD default GCC:
166    # "gcc (GCC) 4.2.1 20070719"
167    # RedHat GCC:
168    # "gcc (GCC) 8.3.1 20190223 (Red Hat 8.3.1-2)"
169    # "gcc (GCC) 10.3.1 20210422 (Red Hat 10.3.1-1)"
170    # other GCC packages:
171    # "sparc-sun-solaris2.9-gcc (GCC) 4.2.0 (gccfss)"
172    # "gcc (GCC) 5.5.0"
173    # "gcc (nb4 20200810) 7.5.0"
174    # "gcc (OpenIndiana 7.5.0-il-0) 7.5.0"
175    # "gcc (Debian 8.3.0-6) 8.3.0"
176    # "gcc (Raspbian 8.3.0-6+rpi1) 8.3.0"
177    # "egcc (GCC) 8.4.0"
178    # "gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0"
179    # "gcc (FreeBSD Ports Collection) 10.3.0"
180    cc_id_guessed=`echo "$cc_id_firstline" | sed 's/^.* (.*) \([0-9\.]*\).*$/gcc-\1/'`
181    if [ "$cc_id_firstline" != "$cc_id_guessed" ]; then
182        echo "$cc_id_guessed"
183        return
184    fi
185}
186
187cc_id() {
188    echo "${cc_id_cached:=`cc_id_nocache`}"
189}
190
191# Call this function each time CC has changed.
192discard_cc_cache() {
193    cc_version_cached=
194    cc_id_cached=
195}
196
197# For the current C compiler try to print CFLAGS value that tells to treat
198# warnings as errors.
199cc_werr_cflags() {
200    case `cc_id` in
201    gcc-*|clang-*|tcc-*)
202        echo '-Werror'
203        ;;
204    xlc-*)
205        # XL C 12.1 and 13.1 recognize "-qhalt=w". XL C 16.1 recognizes that
206        # and "-Werror".
207        echo '-qhalt=w'
208        ;;
209    suncc-*)
210        # GCC and Clang print an identification for every warning, which is
211        # useful for root cause analysis and bug fixing.  Sun C does not do it
212        # by default, but an additional option makes the style more consistent.
213        echo '-errwarn=%all -errtags=yes'
214        ;;
215    msvc-*)
216        # XXX - what?
217        echo ''
218        ;;
219    esac
220}
221
222# Tell whether "gcc" is a symlink to Clang (this is the case on macOS).
223gcc_is_clang_in_disguise() {
224    case `cc_id`/`basename "${CC:?}"` in
225    clang-*/gcc)
226        return 0
227        ;;
228    esac
229    return 1
230}
231
232os_id() {
233    # OS does not change between builds or in the middle of a build, so it is
234    # fine to cache uname output.
235    : "${os_id_sysname:=`uname -s`}"
236    printf '%s-' "$os_id_sysname"
237    : "${os_id_release:=`uname -r`}"
238    case "$os_id_sysname" in
239    AIX)
240        : "${os_id_version:=`uname -v`}"
241        echo "${os_id_version}.${os_id_release}"
242        ;;
243    Darwin|GNU|OpenBSD|SunOS)
244        echo "$os_id_release"
245        ;;
246    FreeBSD|NetBSD|Linux)
247        # Meaningful version is usually the substring before the first dash.
248        # Or the first underscore.
249        echo "$os_id_release" | sed 's/^\([0-9\.]*\).*$/\1/'
250        ;;
251    Haiku)
252        # The complete version is a substring before the first space, e.g.:
253        # * "hrevNNNNN" for a release without updates, e.g. hrev56578 for
254        #   R1/beta4, also for a clean build of master branch;
255        # * "hrevNNNNN+MM" for a release with updates;
256        # * "hrevNNNNN-MM" for a build of a branch that is ahead of the master
257        #   branch;
258        # * "hrevNNNNN_MMMM_KK" for a CI build of a Gerrit review;
259        # * something else for a build of a working copy with the changes not
260        #   yet committed.
261        # With this system it is not clear which version components would be
262        # meaningful to relate with the build result, so let's return the
263        # complete version and leave any interpretation to the user.
264        : "${os_id_version:=`uname -v`}"
265        echo "$os_id_version" | sed -E 's/^(hrev[^ ]+).+$/\1/'
266        ;;
267    MSYS*)
268        # uname -s produces "MSYS_NT-{NT version?}-{build?}
269        # uname -r produces MSYS2 version?
270        echo "$os_id_version", MSYS "$os_id_release"
271        ;;
272    *)
273        echo 'UNKNOWN'
274        ;;
275    esac
276}
277
278increment() {
279    # No arithmetic expansion in Solaris /bin/sh before 11.
280    # shellcheck disable=SC2003
281    expr "${1:?}" + 1
282}
283
284# Display text in magenta.
285echo_magenta() {
286    # ANSI magenta, the imploded text, ANSI reset, newline.
287    printf '\033[35;1m%s\033[0m\n' "$*"
288}
289
290# Run a command after displaying it.
291run_after_echo() {
292    : "${1:?}" # Require at least one argument.
293    printf '$ %s\n' "$*"
294    "$@"
295}
296
297print_so_deps() {
298    case `os_id` in
299    Darwin-*)
300        run_after_echo otool -L "${1:?}"
301        ;;
302    Haiku-*)
303        run_after_echo objdump -p "${1:?}"
304        ;;
305    MSYS*)
306        run_after_echo dumpbin /dependents "${1:?}"
307        ;;
308    *)
309        run_after_echo ldd "${1:?}"
310        ;;
311    esac
312}
313
314# Beware that setting MATRIX_DEBUG for tcpdump or tcpslice will produce A LOT
315# of additional output there and in any nested libpcap builds. Multiplied by
316# the matrix size, the full output log size might exceed limits of some CI
317# systems (as it had previously happened with Travis CI). Use with caution on
318# a reduced matrix.
319handle_matrix_debug() {
320    [ "$MATRIX_DEBUG" != yes ] && return
321    echo '$ cat Makefile [...]'
322    sed '/^# DO NOT DELETE THIS LINE -- mkdep uses it.$/q' <Makefile
323    run_after_echo cat config.h
324    [ "$CMAKE" = yes ] || run_after_echo cat config.log
325}
326
327purge_directory() {
328    if [ "`os_id`" = SunOS-5.11 ]; then
329        # In Solaris 11 /bin/sh the pathname expansion of "*" always includes
330        # "." and "..", so the straightforward rm would always fail.
331        (
332            cd "${1:?}"
333            for pd_each in *; do
334                if [ "$pd_each" != . ] && [ "$pd_each" != .. ]; then
335                    rm -rf "$pd_each"
336                fi
337            done
338        )
339    else
340        rm -rf "${1:?}"/*
341    fi
342}
343
344# vi: set tabstop=4 softtabstop=0 expandtab shiftwidth=4 smarttab autoindent :
345