#!/usr/bin/env sh
#
# Caveats:
# - checks with textprocessing assuming that system language is English.
#   - maybe check last return status instead?
# - Do we need to set awk to which awk becomes available or is awk
#   always available as just awk?
#
# Dedicated to the Public Domain.
# SPDX-License-Identifier: 0BSD

progname=${0##*/}

statusmsg()
{
    echo "    $@"
}

infomsg()
{
    statusmsg "INFO:    $@"
}

warningmsg()
{
    statusmsg "WARNING: $@"
}

errormsg()
{
    statusmsg "ERROR:   $@"
}

linemsg()
{
    statusmsg "========================================="
}

errmsg=''

# Check if shell supports builtin 'type'.
if test -z "$errmsg"; then
    if ! (eval 'type type') >/dev/null 2>&1
    then
        errmsg='Shell does not support type builtin'
        exit 1
    fi
fi

os_check()
{
    OS=`uname -s 2>/dev/null`
    infomsg "OS             : $OS"
    REL=`uname -r 2>/dev/null`
    infomsg "OS RELEASE     : $REL"
    HW=`uname -m 2>/dev/null`
    infomsg "HARDWARE       : $HW"
}

# We shouldn't use awk to test for awk... but if
# awk isn't there it can't be found.
awk_check()
{
    if test -z "`type awk | awk '/not found/'`"; then
        infomsg    "awk            : Found"
    else
        warningmsg "awk            : Not found!"
        exit 1
    fi
}

gcc_check()
{
    if test -z "`type gcc | awk '/not found/' 2>/dev/null`"; then
        VERS=`gcc --version 2>/dev/null | head -n 1`
        infomsg "gcc            : $VERS"
    elif test -n "`gcc 2>&1 | tail -1 | awk '{print $1}'`"; then
        VERS=`gcc --version 2>/dev/null | head -n 1`
        infomsg "gcc             : $VERS"
    else
        warningmsg "gcc            : Not Found";
    fi
}

cc_check()
{
    if test -z "`type cc | awk '/not found/' 2>/dev/null`"; then
        VERS=`cc --version 2>/dev/null | head -n 1`
        infomsg "cc             : $VERS"
    else
        warningmsg "cc             : Not Found";
    fi
}

cplusplus_check()
{
    if test -z "`type c++ | awk '/not found/' 2>/dev/null`"; then
        VERS=`c++ --version 2>/dev/null | head -n 1`
        infomsg "c++            : $VERS"
    else
        warningmsg "c++            : Not Found";
    fi
}

clang_check()
{
    TEST=`type clang | awk '/not found/' 2>/dev/null`
    if test -z "$TEST"; then
        VERS=`clang --version 2>/dev/null | head -n 1`
        infomsg "clang          : $VERS"
    elif test -n "`clang 2>&1 | tail -1 | awk '{print $1}'`"; then
        VERS=`clang --version 2>/dev/null | head -n 1`
        infomsg "clang          : $VERS"
    else
        warningmsg "clang          : Not Found";
    fi
}

clangplusplus_check()
{
    TEST=`type clang++ | awk '/not found/' 2>/dev/null`
    if test -n "$TEST"; then
        VERS=`clang++ --version 2>/dev/null | head -n 1`
        infomsg "clang++        : $VERS"
    elif test -n "`clang++ 2>&1 | tail -1 | awk '{print $1}'`"; then
        VERS=`clang++ --version 2>/dev/null | head -n 1`
        infomsg "clang++        : $VERS"
    else
        warningmsg "clang++        : Not Found";
    fi
}

gmake_check()
{
    TEST=`type gmake | awk '/not found/'  2>/dev/null`
    if test -z "$TEST" ; then
        VER=$(gmake --version 2>/dev/null | awk '/GNU Make/ {print $3}')
        infomsg "gmake          : $VER"
    else
        TEST=`make --version 2>/dev/null`
        if test -n "$TEST"; then
	        VER=$(make --version 2>/dev/null | awk '/GNU Make/ {print $3}')
            infomsg "gmake        : $VER"
        else
	        warningmsg "gmake         : Not Found"
        fi
    fi
}

# Applies at least for NetBSD make. This test is a little awkward,
# we should probably grep the output of 'make -dA'. nbmake identifies,
# NetBSD make from NetBSD (nbmake is portable, external) does not identify.
make_check()
{
    TEST=`type make | awk '/not found/' 2>/dev/null`
    if test -z "$TEST"; then
        VER=$(make --version 2>/dev/null | awk '// {print $0}')
        if test -z "$VER"; then
            infomsg    "make           : Found"
        else
            warningmsg "make           : Not Found (unexpected result)"
        fi
    fi
}

autoconf_check()
{
    TEST=`type autoconf | awk '/not found/' 2>/dev/null`
    if test -z "$TEST"; then
        autoconf --version |\
            head -n 1 |\
            awk '{\
	if (length($4) == 0) {\
		print "    INFO:    autoconf       : "$3\
	} else {\
		print "    INFO:    autoconf       : "$4\
	}}'
    else
        warningmsg "autoconf       : Not Found"
    fi
}

automake_check()
{
    TEST=`type automake | awk '/not found/' 2>/dev/null`
    if test -z "$TEST"; then
        VER=`automake --version 2>/dev/null | head -n 1 | awk '{print $4}'`
        infomsg "automake       : $VER"
    else
        warningmsg "automake       : Not Found"
    fi
}

# TODO: More libtool variants.
libtool_check()
{
    TEST=`type libtoolize | awk '/not found/' 2>/dev/null`
    if test -z "$TEST"; then
        VER=`libtoolize --version 2>/dev/null | head -n 1 | awk '{print $4}'`
        infomsg "libtool        : $VER"
    else
        warningmsg "libtool        : Not Found"
    fi
}

libextractor_check()
{
    TEST=`type extract | awk '/not found/' 2>/dev/null`
    if test -z "$TEST"; then
        TEST=`strings $(type extract | awk '{print $NF}') | awk '/EXTRACTOR_extract/' 2>/dev/null`
        if test -n "$TEST"; then
           VER=`extract -v 2>/dev/null | awk '{gsub("v",""); print $NF}'`
           infomsg "libextractor   : $VER"
        else
            warningmsg "libextractor   : Not Found"
        fi
    fi
}

gnunet_version_check()
{
    # historical, should not be matched
    T08=`type gnunetd | awk '/not found/' 2>/dev/null`
    if test -z "$T08"; then
        VER08=`gnunetd -v | awk '{if(/0.8/) { gsub("v",""); print $2}}'`
        infomsg "GNUnet 0.8     : Not Found (good)"
    # else
    #    warningmsg "GNUnet 0.8     : $VER08 (may conflict!)"
    fi
    TEST=`type gnunet-arm | awk '/not found/' 2>/dev/null`
    if test -z "$TEST"; then
        gnunet-arm --version |\
            awk '{\
	if (/not found/) {\
		print "    INFO:    GNUnet         : Not found"\
    } else if (/[0-9]/) {\
        gsub("v",""); print "    INFO:    GNUnet         : "$2\
	} else {\
		print "    INFO:    GNUnet         : Test failed"\
	}}'
    else
        warningmsg "GNUnet         : Not Found"
    fi
}

gitcommit_check()
{
    TEST=$(type git | awk '/not found/' 2> /dev/null)
    if test -z "$TEST"; then
        VER=$(git rev-parse HEAD)
        infomsg "git commit     : $VER"
    else
        warningmsg "git commit      : Not a git checkout"
    fi
}

gcrypt_check()
{
    TEST=`type libgcrypt-config | awk '/not found/' 2> /dev/null`
    if test -z "$TEST"; then
        VER=`libgcrypt-config --version 2> /dev/null`
        infomsg "libgcrypt      : $VER"
    else
        warningmsg "libgcrypt      : Not Found"
    fi
}

mysql_check()
{
    TEST=`type mysql_config | awk '/not found/' 2> /dev/null`
    if test -z "$TEST"; then
        VER=`mysql_config --version 2> /dev/null`
        infomsg "mysql          : $VER"
    else
        infomsg "mysql          : Not Found"
    fi
}

pkgconf_check()
{
    TEST=`type pkgconf | awk '/not found/' 2> /dev/null`
    if test -z "$TEST"; then
        pkgconf --version 2> /dev/null | awk '{print "    INFO:    pkgconf        : "$1}'
    else
        infomsg "pkgconf        : Not Found"
    fi
    TEST=`type pkg-config | awk '/not found/' 2> /dev/null`
    if test -z "$TEST"; then
        VER=`pkg-config --version 2> /dev/null | awk '{print $1}'`
        infomsg "pkg-config     : $VER"
    else
        infomsg "pkg-config     : Not Found"
    fi
}

glib2_check()
{
    TEST=`type pkg-config | awk '/not found/' 2> /dev/null`
    if test -z "$TEST"; then
        VER=`pkg-config --modversion glib-2.0 2> /dev/null | awk '{print $1}'`
        infomsg "glib2          : $VER"
    else
        infomsg "glib2          : Not Found"
    fi
}

gtk_check()
{
    TEST=`type pkg-config | awk '/not found/' 2> /dev/null`
    if test -z "$TEST"; then
        VER=`pkg-config --modversion gtk+-2.0 2> /dev/null | awk '{print $1}'`
        if test -n "$VER"; then
            infomsg "GTK2           : $VER"
        else
            infomsg "GTK2           : Not found"
        fi
    else
        infomsg "GTK2           : Not Found"
    fi

    if test -z "$TEST"; then
        VER=`pkg-config --modversion gtk+-3.0 2> /dev/null | awk '{print $1}'`
        if test -n "$VER"; then
            infomsg "GTK3           : $VER"
        else
            infomsg "GTK3           : Not found"
        fi
    else
        infomsg "GTK3           : Not Found"
    fi

    if test -z "$TEST"; then
        VER=`pkg-config --modversion gtk+-4.0 2> /dev/null | awk '{print $1}'`
        if test -z "$VER"; then
            infomsg "GTK4           : $VER"
        else
            infomsg "GTK4           : Not found"
        fi
    else
        infomsg "GTK4           : Not Found"
    fi
}

gmp_check()
{
    TEST=`type dpkg | awk '/not found/' 2> /dev/null`
    if test -z "$TEST"; then
        LINES=`dpkg -s libgmp-dev | grep Version | wc -l 2> /dev/null`
        if test "$LINES" = "1"
        then
            VERSION=`dpkg -s libgmp-dev | grep Version | awk '{print $2}'`
            infomsg "GMP            : libgmp-dev-$VERSION.deb"
        else
            errormsg "GMP            : dpkg: libgmp-dev not installed"
        fi
    else
        TEST=`type rpm | awk '/not found/' 2> /dev/null`
        if test -z "$TEST"; then
            rpm -q gmp | sed -e "s/gmp-//" 2> /dev/null | \
                infomsg "GMP            : $1.rpm"
        else
            infomsg "GMP            : Test not available"
        fi
        TEST=$(type pkg_info | awk '/not found/' 2> /dev/null)
        if test -z "$TEST"; then
            VER=$(pkg_info -e gmp)
            infomsg "GMP            : $VER"
        else
            infomsg "GMP            : Test not available"
        fi
    fi
}

libunistring_check()
{
    TEST=`type dpkg | awk '/not found/' 2> /dev/null`
    if test -z "$TEST"; then
        LINES=`dpkg -s libunistring-dev | awk '/Version/' | wc -l`
        if test "$LINES" = "1"
        then
            VERSION=`dpkg -s libunistring-dev | awk '/Version/ {print $2}'`
            infomsg "libunistring   : libunistring3-dev-$VERSION.deb"
        else
            errormsg "libunistring   : dpkg: libunistring3-dev not installed"
        fi
    else
        TEST=`type rpm | awk '/not found/' 2> /dev/null`
        if test -z "$TEST"; then
            rpm -q unistring | sed -e "s/unistring-//" 2> /dev/null | \
                awk '{print "libunistring   : "$1.rpm}'
        else
            infomsg "libunistring   : Test not available"
        fi
        TEST=$(type pkg_info | awk '/not found/' 2> /dev/null)
        if test -z "$TEST"; then
            VER=$(pkg_info -e libunistring)
            infomsg "libunistring   : $VER"
        else
            infomsg "libunistring   : Test not available"
        fi
    fi
}

gnugettext_check()
{
    TEST=`type gettext | awk '/not found/'`
    if test -z "$TEST"; then
        if test -n "$(gettext --version 2>&1 | awk '/unknown option/')"; then
            infomsg "GNU gettext    : Not found"
        else
            VER=`gettext --version | awk '/GNU gettext/ {print $4}'`
            infomsg "GNU gettext    : $VER"
        fi
    fi
}

gettext_check()
{
    if test -z "`type getext | awk '/not found/'`"; then
        infomsg "gettext        : Found"
    else
        infomsg "gettext        : Not Found"
    fi
}

gnurl_curl_check()
{
    TESTCURL=`type curl-config | awk '/not found/' 2> /dev/null`
    if test -z "$TESTCURL"; then
        VER=`curl-config --version 2> /dev/null | awk '{print $NF}'`
        infomsg "libcurl        : $VER"
    else
        infomsg "libcurl        : Not found"
    fi

    TESTGNURL=`type gnurl-config | awk '/not found/' 2> /dev/null`
    if test -z "$TESTGNURL"; then
        VER=`gnurl-config --version 2>&1 /dev/null | awk '{print $NF}'`
        infomsg "libgnurl       : $VER"
    else
        infomsg "libgnurl       : Not found"
    fi

    if test -z "$TESTCURL" -a "$TESTGNURL"; then
        warningmsg "libgnurl or libcurl       : Not found"
    fi
}

libmicrohttpd_check()
{
    TMPFILE="bugreport-test_lmhd.c"
    cat - >$TMPFILE <<EOF
#include <microhttpd.h>
#include <stdio.h>
int main()
{
  fprintf (stdout, "%X\n", MHD_VERSION);
  return 0;
}
EOF
    if test -x `type gcc | awk '{print $NF}'`; then
        gcc $CPPFLAGS $CFLAGS -o "$TMPFILE".bin "$TMPFILE"
        VER=`./"$TMPFILE".bin`
    elif test -x `type cc | awk '{print $NF}'`; then
        cc $CPPFLAGS $CFLAGS -o $TMPFILE.bin $TMPFILE
        VER=`./$TMPFILE.bin`
    else
        VER="Not found"
    fi
    infomsg "libmicrohttpd  : $VER"
    rm -f $TMPFILE.c $TMPFILE $TMPFILE.bin
}

glpk_check()
{
    TMPFILE="bugreport-glpk_check.c"
    cat - >$TMPFILE <<EOF
#include <glpk.h>
#include <stdio.h>
int main()
{
  fprintf (stdout, "%u.%u\n", GLP_MAJOR_VERSION, GLP_MINOR_VERSION);
  return 0;
}
EOF
    if test -x `type gcc | awk '{print $NF}'`; then
        gcc $CPPFLAGS $CFLAGS -o "$TMPFILE".bin $TMPFILE
        VER=`./$TMPFILE.bin`
    elif test -x `type cc | awk '{print $NF}'`; then
        cc $CPPFLAGS $CFLAGS -o "$TMPFILE".bin $TMPFILE
        VER=`./"$TMPFILE".bin`
    else
        VER="Not found"
    fi
    infomsg "GNU GLPK       : $VER"
    rm -f $TMPFILE.c $TMPFILE $TMPFILE.bin
}

gnutls_check()
{
    TMPFILE="bugreport-gnutls_check.c"
    cat - >$TMPFILE <<EOF
#include <gnutls/gnutls.h>
#include <stdio.h>
int main()
{
  fprintf (stdout, "%s\n", GNUTLS_VERSION);
  return 0;
}
EOF
    if test -x `type gcc | awk '{print $NF}'`; then
        gcc $CPPFLAGS $CFLAGS -o "$TMPFILE".bin $TMPFILE
        VER=`./"$TMPFILE".bin`
    elif test -x `type cc | awk '{print $NF}'`; then
        cc $CPPFLAGS $CFLAGS -o "$TMPFILE".bin $TMPFILE
        VER=`./"$TMPFILE".bin`
    else
        VER="Not found"
    fi
    infomsg "GnuTLS         : $VER"
    rm -f $TMPFILE.c $TMPFILE $TMPFILE.bin
}

main()
{
    if test -n "$1" -a "$1" = "-h" -o "$1" = "--help"; then
        echo "Usage: ${progname} [-h]"
        echo "If CPPFLAGS and LDFLAGS are unset, try:"
        echo "CPPFLAGS='-I/usr/pkg/include' LDFLAGS='-L/usr/pkg/lib' ${progname}"
        return 0
    fi
    infomsg "${progname} 0.11.0"
    infomsg
    infomsg "Please submit the following"
    infomsg "information with your bug report:"
    linemsg
    os_check
    awk_check
    gcc_check
    cc_check
    cplusplus_check
    clang_check
    clangplusplus_check
    make_check
    gmake_check
    autoconf_check
    automake_check
    libtool_check
    libextractor_check
    gnunet_version_check
    gitcommit_check
    gcrypt_check
    mysql_check
    pkgconf_check
    glib2_check
    gtk_check
    gmp_check
    libunistring_check
    gnugettext_check
    gettext_check
    gnurl_curl_check
    libmicrohttpd_check
    glpk_check
    gnutls_check
    linemsg
    infomsg "Bug report saved in ./my_gnunet_bugreport.log"
}

main "$@" 2>&1 | tee "my_gnunet_bugreport.log"
