lynis/include/helper_show

448 lines
21 KiB
Plaintext
Raw Normal View History

2016-04-07 16:24:38 +02:00
#!/bin/sh
#################################################################################
#
# Lynis
# ------------------
#
# Copyright 2007-2013, Michael Boelen
2018-01-11 09:50:26 +01:00
# Copyright 2007-2018, CISOfy
2016-04-07 16:24:38 +02:00
#
# Website : https://cisofy.com
# Blog : http://linux-audit.com
# GitHub : https://github.com/CISOfy/lynis
#
# Lynis comes with ABSOLUTELY NO WARRANTY. This is free software, and you are
# welcome to redistribute it under the terms of the GNU General Public License.
# See LICENSE file for usage of this software.
#
######################################################################
#
# Helper program to share details
#
######################################################################
#
# How to use:
# ------------
# Run: lynis show <option>
#
######################################################################
2017-02-05 21:08:08 +01:00
COMMANDS="audit configure show update upload-only"
HELPERS="audit configure show update"
2018-08-27 14:25:59 +02:00
OPTIONS="--auditor\n--cronjob (--cron)\n--debug\n--developer\n--help (-h)\n--license-key\n--log-file\n--manpage (--man)\n--no-colors\n--no-log\n--pentest\n--profile\n--plugin-dir\n--quick (-Q)\n--quiet (-q)\n--report-file\n--reverse-colors\n--skip-plugins\n--tests\n--tests-from-category\n--tests-from-group\n--upload\n--verbose\n--version (-V)\n--wait\n--warnings-only"
2016-10-16 15:23:47 +02:00
SHOW_ARGS="categories changelog commands dbdir details environment groups help hostids includedir language license logfile man options os pidfile plugindir profiles release releasedate report settings tests version workdir"
SHOW_HELP="lynis show ${BROWN}categories${NORMAL} (display test categories)
lynis show ${BROWN}changelog${NORMAL} ${GRAY}[version]${NORMAL} (release details)
lynis show ${BROWN}commands${NORMAL} (all available commands)
lynis show ${BROWN}dbdir${NORMAL} (database directory)
2016-08-26 14:08:24 +02:00
lynis show ${BROWN}details${NORMAL} (display test details from log file)
2016-10-16 15:23:47 +02:00
lynis show ${BROWN}environment${NORMAL} (hardware, virtual machine, or container type)
lynis show ${BROWN}groups${NORMAL} (test groups)
lynis show ${BROWN}help${NORMAL} (detailed information about arguments)
lynis show ${BROWN}hostids${NORMAL} (unique IDs for this system)
lynis show ${BROWN}includedir${NORMAL} (include directory for tests and functions)
lynis show ${BROWN}language${NORMAL} (configured or detected language)
lynis show ${BROWN}license${NORMAL} (license details)
lynis show ${BROWN}logfile${NORMAL} (location of logfile)
lynis show ${BROWN}man${NORMAL} (show help)
lynis show ${BROWN}options${NORMAL} (available flags and options)
lynis show ${BROWN}os${NORMAL} (operating system and version)
lynis show ${BROWN}pidfile${NORMAL} (active file to stored process ID)
lynis show ${BROWN}plugindir${NORMAL} (directory with plugins)
lynis show ${BROWN}profiles${NORMAL} (discovered profiles)
lynis show ${BROWN}release${NORMAL} (version)
lynis show ${BROWN}releasedate${NORMAL} (date of release)
lynis show ${BROWN}report${NORMAL} (location of report data)
lynis show ${BROWN}settings${NORMAL} (display configured settings, ${WHITE}options:${NORMAL} ${CYAN}--brief --nocolors${NORMAL})
lynis show ${BROWN}tests${NORMAL} ${GRAY}[test]${NORMAL} (display information about one or more tests)
lynis show ${BROWN}tests skipped${NORMAL} (which tests to skip according profile)
lynis show ${BROWN}version${NORMAL} (${PROGRAM_NAME} version)
lynis show ${BROWN}workdir${NORMAL} (work directory)"
2016-04-12 21:59:23 +02:00
AUDIT_ARGS="( dockerfile | system )"
AUDIT_HELP="
2016-05-14 17:42:33 +02:00
${WHITE}lynis audit <target>${NORMAL}
2016-04-12 21:59:23 +02:00
2016-05-14 17:42:33 +02:00
${CYAN}audit dockerfile ${BROWN}<file>${NORMAL}
2016-04-12 21:59:23 +02:00
2016-05-14 17:42:33 +02:00
Perform security audit on a Docker build file
${GRAY}Example:${NORMAL}
lynis audit dockerfile Dockerfile
2016-04-12 21:59:23 +02:00
2016-05-14 17:42:33 +02:00
${CYAN}audit system ${GRAY}[options]${NORMAL}
Perform security system audit
${GRAY}Examples:${NORMAL}
lynis audit system
lynis audit system --cronjob
lynis audit system --profile developer.prf
lynis audit system --quick
${CYAN}audit system remote ${BROWN}<target> ${GRAY}[options]${NORMAL}
Perform security system audit on a remote target
${GRAY}Examples:${NORMAL}
lynis audit system remote 192.168.1.100
lynis audit system remote 192.168.1.100 --no-colors
2016-04-12 21:59:23 +02:00
"
2016-04-07 16:24:38 +02:00
UPDATE_ARGS="check info"
2016-05-14 17:42:33 +02:00
UPDATE_HELP="
${CYAN}update info${NORMAL}
Check version information
"
2016-04-07 16:24:38 +02:00
2016-10-13 20:15:00 +02:00
UPLOAD_ONLY_HELP="
${CYAN}update-only${NORMAL}
Perform just a data upload
"
SHOW_SETTINGS_ARGS="--brief --configured-only --nocolors"
SHOW_TESTS_ARGS="skipped"
2016-04-07 16:24:38 +02:00
COMMANDS_AUDIT_SYSTEM_USAGE="Usage: lynis audit system"
COMMANDS_AUDIT_SYSTEM_FUNCTION="Function: performs a security audit of the system"
if [ $# -gt 0 ]; then
case $1 in
"categories")
ViewCategories
;;
"changelog")
# Allow providing a version
if [ $# -gt 1 ]; then
shift; SEARCH_VERSION="$1"
fi
PROGRAM_NAME_LOWER=$( echo ${PROGRAM_NAME} | tr '[:upper:]' '[:lower:]')
CHANGELOG_PATHS="/usr/share/doc/${PROGRAM_NAME} /usr/share/doc/${PROGRAM_NAME}-${PROGRAM_VERSION} /usr/share/doc/${PROGRAM_NAME_LOWER} ."
CHANGELOG=""
if [ -z "${SEARCH_VERSION}" ]; then SEARCH_VERSION="${PROGRAM_VERSION}"; fi
STARTED=0
for FILEPATH in ${CHANGELOG_PATHS}; do
if [ -f ${FILEPATH}/CHANGELOG.md ]; then
CHANGELOG="${FILEPATH}/CHANGELOG.md"
# Check also for gzipped changelog
elif [ -f ${FILEPATH}/changelog.gz ]; then
A bunch of Solaris compatibility tweaks (#367) * Work around Solaris' /bin/sh not being POSIX. If /usr/xpg4/bin/sh is present, we are (definitely?) on Solaris or a derivative, and /bin/sh cannot be trusted to support POSIX, but /usr/xpg4/bin/sh can be. Exec it right away. * Work around Solaris 'which' command oddity. Solaris' (at least) 'which' command outputs not-found errors to STDOUT instead of STDERR. This makes "did we get any output from which" checks insufficient; piping to grep -v the "no foo in ..." message should work. Note that this patch set includes all such uses of which that I could find, including ones that should never be reached on Solaris (i.e. only executed on some other OS) just for consistency. * Improved alternate-sh exec to avoid looping. * Solaris' /usr/ucb/echo supports -n. * Check for the best hash type that openssl supports. When using openssl to generate hashes, do not assume it supports sha256; try that, then sha1, then give up and use md5. * Solaris does not support sed -i; use a tempfile. * Use the full path for modinfo. When running as non-root, /usr/sbin/ might not be in PATH. include/tests_accounting already calls modinfo by full path, but include/tests_kernel did not. * Solaris find does not support -maxdepth. This mirrors the logic already in tests_homedirs. * Use PSBINARY instead of ps. * Work around Solaris' date not supporting +%s. Printing nawk's srand value is a bizarre but apparently once popular workaround for there being no normal userland command to print UNIX epoch seconds. A perl one-liner is the other common approach, but nawk may be more reliably present on Solaris than perl. * Revert to using sha1 for HOSTID. * Whitespace cleanup for openssl hash tests.
2017-03-08 17:24:24 +01:00
ZCAT=$(which zcat 2> /dev/null | grep -v "no [^ ]* in ")
if [ ! -z "${ZCAT}" ]; then
CreateTempFile
CHANGELOG="${TEMP_FILE}"
LogText "Result: found gzipped changelog in ${FILEPATH}"
LogText "Action: Creating temporary file to store text"
${ZCAT} ${FILEPATH}/changelog.gz > ${CHANGELOG}
else
DisplayError "Could not find zcat utility to use on gzipped changelog"
fi
fi
if [ ! -z "${CHANGELOG}" ]; then LogText "Result: found changelog file: ${CHANGELOG}"; break; fi
done
if [ ! -z "${CHANGELOG}" ]; then
SEARCH=$(egrep "^${PROGRAM_NAME} ${SEARCH_VERSION}" ${CHANGELOG})
if [ $? -eq 0 ]; then
2016-07-30 13:48:22 +02:00
while read -r LINE; do
if [ ${STARTED} -eq 0 ]; then
SEARCH=$(echo ${LINE} | egrep "^${PROGRAM_NAME} ${SEARCH_VERSION}")
if [ $? -eq 0 ]; then STARTED=1; ${ECHOCMD} "${BOLD}${LINE}${NORMAL}"; fi
else
# Stop if we find the next Lynis version
SEARCH=$(echo ${LINE} | egrep "^${PROGRAM_NAME} [0-9]\.[0-9]\.[0-9]")
if [ $? -eq 0 ]; then
break
else
${ECHOCMD} "${LINE}"
fi
fi
done < ${CHANGELOG}
else
DisplayError "Could not find this version in the changelog"
${ECHOCMD} ""
${ECHOCMD} "${HEADER}Usage:${NORMAL}"
${ECHOCMD} "$0 lynis show changelog [version]"
${ECHOCMD} ""
${ECHOCMD} "${HEADER}${PROGRAM_NAME} versions:${NORMAL}"
SEARCH=$(egrep "^Lynis [0-9]\.[0-9]\.[0-9] " ${CHANGELOG} | awk '{print $2}' | sort -n)
${ECHOCMD} ${SEARCH}
ExitFatal
fi
else
DisplayError "Could not find the changelog file (searched in ${CHANGELOG_PATHS})"
ExitFatal
fi
;;
2016-04-07 16:24:38 +02:00
"commands")
if [ $# -eq 1 ]; then
2016-05-14 17:42:33 +02:00
${ECHOCMD} "\n${WHITE}Commands:${NORMAL}"
for ITEM in ${COMMANDS}; do
${ECHOCMD} "lynis ${CYAN}${ITEM}${NORMAL}"
2016-04-12 21:59:23 +02:00
done
2016-05-14 17:42:33 +02:00
${ECHOCMD} ""
else
2016-04-07 16:24:38 +02:00
shift
if [ $# -eq 1 ]; then
2016-05-03 13:16:11 +02:00
case $1 in
2016-05-14 17:42:33 +02:00
"audit") ${ECHOCMD} "${AUDIT_HELP}" ;;
"show") ${ECHOCMD} "${SHOW_HELP}" ;;
"update") ${ECHOCMD} "No help available yet" ;;
*) DisplayError "Unknown argument for 'commands'"
2016-05-03 13:16:11 +02:00
esac
else
2016-05-03 13:16:11 +02:00
shift
case $1 in
"dockerfile")
2016-05-14 17:42:33 +02:00
${ECHOCMD} "Usage: lynis audit dockerfile <file>"
2016-05-03 13:16:11 +02:00
;;
"system")
2016-05-14 17:42:33 +02:00
${ECHOCMD} "${COMMANDS_AUDIT_SYSTEM_USAGE}\n${COMMANDS_AUDIT_SYSTEM_FUNCTION}\n"
2016-05-03 13:16:11 +02:00
;;
*)
DisplayError "Unknown argument '$1' for commands"
2016-05-03 13:16:11 +02:00
;;
esac
2016-04-07 16:24:38 +02:00
fi
fi
;;
"dbdir")
${ECHOCMD} "${DBDIR}"
;;
"details")
if [ -z "${LOGFILE}" ]; then DisplayError "Could not find log file to parse"; fi
if [ $# -eq 1 ]; then
2018-08-27 14:51:28 +02:00
DisplayError "This command needs a test ID (e.g. CORE-1000) to search for. This command is used after a scan (lynis audit system). Run 'lynis show tests' to see all available tests."
else
shift
if [ $# -eq 1 ]; then
TESTID="$1"
awk -v search="Performing test ID $TESTID" '$0 ~ search {++f;p=1}p&&f==1;/===---/{p=0}' ${LOGFILE}
fi
fi
;;
2016-10-16 15:23:47 +02:00
"environment")
if [ -z "${CONTAINER_TYPE}" ]; then
${ECHOCMD} "container=0"
else
${ECHOCMD} "container=1"
${ECHOCMD} "container-type=${CONTAINER_TYPE}"
fi
if [ ${ISVIRTUALMACHINE} -eq 1 ]; then
${ECHOCMD} "virtual-machine=1"
${ECHOCMD} "virtual-machine-type=${VMTYPE}"
else
${ECHOCMD} "hardware=1"
${ECHOCMD} "virtual-machine=0"
fi
;;
"groups")
ViewGroups
;;
"help" | "--help" | "-h")
2016-04-07 16:24:38 +02:00
if [ $# -eq 1 ]; then
2016-05-14 17:42:33 +02:00
${ECHOCMD} "${PROGRAM_NAME} ${PROGRAM_VERSION} - Help"
${ECHOCMD} "=========================="
${ECHOCMD} ""
${ECHOCMD} "${WHITE}Commands${NORMAL}:"
for ITEM in ${COMMANDS}; do
${ECHOCMD} "${CYAN}${ITEM}${NORMAL}"
2016-04-12 21:59:23 +02:00
done
2016-05-14 17:42:33 +02:00
${ECHOCMD} ""
${ECHOCMD} "Use 'lynis show help ${CYAN}<command>${NORMAL}' to see details"
2016-05-14 17:42:33 +02:00
${ECHOCMD} ""; ${ECHOCMD} ""
${ECHOCMD} "${WHITE}Options${NORMAL}:\n${GRAY}${OPTIONS}${NORMAL}"
else
2016-04-07 16:24:38 +02:00
shift
case $1 in
2016-05-14 17:42:33 +02:00
"audit") ${ECHOCMD} "${AUDIT_HELP}" ;;
"show") ${ECHOCMD} "${SHOW_HELP}" ;;
"update") ${ECHOCMD} "${UPDATE_HELP}" ;;
2016-10-13 20:15:00 +02:00
"upload-only") ${ECHOCMD} "${UPLOAD_ONLY_HELP}" ;;
2016-05-14 17:42:33 +02:00
"?") ${ECHOCMD} "${SHOW_ARGS}" ;;
2016-10-13 20:15:00 +02:00
*) ${ECHOCMD} "Unknown argument provided for lynis show help" ;;
2016-04-07 16:24:38 +02:00
esac
fi
;;
"helpers") for ITEM in ${HELPERS}; do ${ECHOCMD} ${ITEM}; done ;;
"hostids" | "hostid")
${ECHOCMD} "hostid=${HOSTID}"
${ECHOCMD} "hostid2=${HOSTID2}"
2016-10-16 15:23:47 +02:00
${ECHOCMD} "machineid=${MACHINEID}"
;;
"includedir")
${ECHOCMD} "${INCLUDEDIR}"
;;
"language") ${ECHOCMD} "${LANGUAGE}" ;;
2016-05-14 17:42:33 +02:00
"license") ${ECHOCMD} "${PROGRAM_LICENSE}" ;;
"logfile") ${ECHOCMD} "${LOGFILE}" ;;
2016-05-14 17:42:33 +02:00
"man") ${ECHOCMD} "Use ./lynis --man or man lynis" ;;
"options") ${ECHOCMD} "${OPTIONS}" ;;
"os")
${ECHOCMD} "OS=${OS}"
${ECHOCMD} "OS_NAME=${OS_NAME}"
${ECHOCMD} "OS_FULLNAME=${OS_FULLNAME}"
${ECHOCMD} "OS_VERSION=${OS_VERSION}"
;;
2016-05-14 17:42:33 +02:00
"pidfile") ${ECHOCMD} "${PIDFILE}" ;;
"profile" | "profiles") for ITEM in ${PROFILES}; do ${ECHOCMD} ${ITEM}; done ;;
"profiledir") ${ECHOCMD} "${PROFILEDIR}" ;;
2016-05-14 17:42:33 +02:00
"plugindir") ${ECHOCMD} "${PLUGINDIR}" ;;
"release") ${ECHOCMD} "${PROGRAM_VERSION}-${PROGRAM_RELEASE_TYPE}" ;;
2016-05-14 17:42:33 +02:00
"releasedate") ${ECHOCMD} "${PROGRAM_RELEASE_DATE}" ;;
"report") ${ECHOCMD} "${REPORTFILE}" ;;
"settings")
BRIEF_OUTPUT=0
COLORED_OUTPUT=1
CONFIGURED_ONLY_OUTPUT=0
while [ $# -gt 1 ]; do
shift
case $1 in
"--brief" | "--br") BRIEF_OUTPUT=1 ;;
"--configured-only" | "--co") CONFIGURED_ONLY_OUTPUT=1 ;;
"--nocolors" | "--no-colors" | "--nc") COLORED_OUTPUT=0; COLORS=0 ;;
*)
${ECHOCMD} "${RED}Error${NORMAL}: Invalid argument provided to 'lynis show settings'\n\n"
${ECHOCMD} "Suggestions:"
for ITEM in ${SHOW_SETTINGS_ARGS}; do ${ECHOCMD} "lynis show settings ${ITEM}"; done
ExitFatal
;;
esac
done
if [ ${COLORED_OUTPUT} -eq 0 ]; then RemoveColors; fi
# Sort all settings and display them
SETTINGS=$(sort ${SETTINGS_FILE} | sed 's/ /:space:/g')
for LINE in ${SETTINGS}; do
SETTING=$(echo ${LINE} | awk -F';' '{print $1}')
VALUE=$(echo ${LINE} | awk -F';' '{print $2}')
DESCRIPTION=$(echo ${LINE} | awk -F';' '{print $3}' | sed 's/:space:/ /g')
if [ -z "${VALUE}" -a ${CONFIGURED_ONLY_OUTPUT} -eq 0 ]; then VALUE="${GRAY}[not configured]${NORMAL}"; fi
if [ ! -z "${VALUE}" ]; then
if [ ${BRIEF_OUTPUT} -eq 0 ]; then ${ECHOCMD} "${GRAY}# ${DESCRIPTION}${NORMAL}"; fi
${ECHOCMD} "${WHITE}${SETTING}${NORMAL}=${CYAN}${VALUE}${NORMAL}"
if [ ${BRIEF_OUTPUT} -eq 0 ]; then ${ECHOCMD} ""; fi
fi
done
if [ ${BRIEF_OUTPUT} -eq 0 -a ${CONFIGURED_ONLY_OUTPUT} -eq 0 -a ${COLORED_OUTPUT} -eq 1 ]; then
if [ ${COLORS} -eq 1 ]; then
${ECHOCMD} "# Add --brief to hide descriptions, --configured-only to show configured items only, or --nocolors to remove colors"
else
${ECHOCMD} "# Add --brief to hide descriptions, --configured-only to show configured items only"
fi
fi
;;
"tests")
if [ $# -gt 1 ]; then
shift
case $1 in
"skipped")
if [ -z "${SKIP_TESTS}" ]; then
${ECHOCMD} "# ${CYAN}No tests are skipped (according profile)${NORMAL}"
else
${ECHOCMD} "# Skipped tests (according profile)"
${ECHOCMD} "${SKIP_TESTS}"
fi
;;
*)
if [ -f ${DBDIR}/tests.db ]; then
SEARCH="$1"
FIND=$(grep "^${SEARCH}" ${DBDIR}/tests.db | sed "s/ /:space:/g")
if [ -z "${FIND}" ]; then
${ECHOCMD} "${WARNING}Error${NORMAL}: ${BOLD}Could not find this test in the database${NORMAL}\n\n"
ExitFatal
else
for ITEM in ${FIND}; do
TEST_DESCRIPTION=$(echo ${ITEM} | sed "s/:space:/ /g" | awk -F: '{print $6}')
TEST=$(echo ${ITEM} | awk -F: '{print $1}')
TEST_TYPE=$(echo ${ITEM} | awk -F: '{print $2}')
TEST_CATEGORY=$(echo ${ITEM} | awk -F: '{print $3}')
TEST_GROUP=$(echo ${ITEM} | awk -F: '{print $4}')
TEST_OS=$(echo ${ITEM} | awk -F: '{print $5}')
TEST_SKIPPED=0
${ECHOCMD} "${CYAN}${TEST}${NORMAL}"
${ECHOCMD} "==================================="
${ECHOCMD} ""
${ECHOCMD} "${WHITE}Type:${NORMAL} ${TEST_TYPE}"
${ECHOCMD} ""
${ECHOCMD} "${WHITE}Description:${NORMAL}"
${ECHOCMD} "${TEST_DESCRIPTION}"
${ECHOCMD} ""
${ECHOCMD} "${WHITE}Category:${NORMAL} ${TEST_CATEGORY}, ${WHITE}Group:${NORMAL} ${TEST_GROUP}"
${ECHOCMD} ""
${ECHOCMD} "${WHITE}Test Execution:${NORMAL}"
if [ "${TEST_OS}" = "" ]; then
${ECHOCMD} " Operating System: ${GREEN}Yes${NORMAL} (all systems)"
elif [ "${TEST_OS}" = "${OS}" ]; then
${ECHOCMD} " Operating System: ${GREEN}Yes${NORMAL} (${TEST_OS} only)"
else
${ECHOCMD} " Operating System: ${RED}No${NORMAL} (${TEST_OS} only)"
TEST_SKIPPED=1
fi
if [ -z "${SKIP_TESTS}" ]; then
${ECHOCMD} " Profile: ${GREEN}Yes${NORMAL} (not configured)"
else
FIND=$(echo ${SKIP_TESTS} | egrep "${TEST}")
if [ -z "${FIND}" ]; then
${ECHOCMD} " Profile: ${GREEN}Yes${NORMAL} (test not marked to be skipped)"
else
${ECHOCMD} " Profile: ${RED}No${NORMAL} (marked test as to be skipped)"
TEST_SKIPPED=1
fi
fi
if [ ${TEST_SKIPPED} -eq 1 ]; then ${ECHOCMD} ""; ${ECHOCMD} " This test will NOT be performed on this system"; fi
${ECHOCMD} ""
${ECHOCMD} ""
done
fi
else
ShowError "Can not find tests database"
${ECHOCMD} "The changelog might not be installed on your system. Details can be found at ${PROGRAM_SOURCE}."
ExitFatal
fi
;;
esac
else
if [ -f ${DBDIR}/tests.db ]; then
${ECHOCMD} "# Test OS Description"
${ECHOCMD} "# ======================================================================================"
awk -F: '{ if ($1 !~ /^#/) printf("%-10s %-10s %s (%s)\n",$1,$5,$6,$3)}' ${DBDIR}/tests.db
else
ShowError "Can not find tests database"
${ECHOCMD} "The changelog might not be installed on your system. Details can be found at ${PROGRAM_SOURCE}."
ExitFatal
fi
fi
;;
"version") ${ECHOCMD} "${PROGRAM_VERSION}" ;;
"workdir") ${ECHOCMD} "${WORKDIR}" ;;
2016-05-14 17:42:33 +02:00
"?") ${ECHOCMD} "${SHOW_ARGS}" ;;
*) ${ECHOCMD} "Unknown argument '${RED}$1${NORMAL}' for lynis show" ;;
2016-04-07 16:24:38 +02:00
esac
else
2016-05-14 17:42:33 +02:00
${ECHOCMD} "\n ${WHITE}Provide an additional argument${NORMAL}\n\n"
for ITEM in ${SHOW_ARGS}; do
${ECHOCMD} " lynis show ${BROWN}${ITEM}${NORMAL}"
2016-04-07 16:24:38 +02:00
done
2016-05-14 17:42:33 +02:00
${ECHOCMD} "\n"
2018-08-27 14:51:28 +02:00
${ECHOCMD} ""
${ECHOCMD} "Extended help about the show command can be provided with: $0 show commands show"
2016-04-07 16:24:38 +02:00
fi
ExitClean
# More additions:
# - categories
# - workdir
2016-04-07 16:24:38 +02:00
# The End