commit e06434573e053df429578c9784b6ba87196068d3 Author: Fincer Date: Tue Aug 14 20:47:24 2018 +0300 Initial commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..b192ede --- /dev/null +++ b/README.md @@ -0,0 +1,21 @@ +# Arch Linux tools +Various command line tools for Arch Linux + +## About + +This repository has various practical developer/sysadmin-oriented tools to Arch Linux. + +---------------------- + +### Contents + +- **tools/getsource.sh** + - What: Retrieve necessary build time files, such as PKGBUILD + patches, from remote Arch/AUR package repositories + - As you execute this script, it asks for the package name on remote repository. Be exact. Default name is the name of your current working directory. + - The script downloads the files to the current working directory. + +---------------------- + +## License + +This repository uses GPLv3 license. Please see [LICENSE](https://github.com/Fincer/archlinux-tools/blob/master/LICENSE) files for details. diff --git a/bash.custom b/bash.custom new file mode 100644 index 0000000..3bd61f6 --- /dev/null +++ b/bash.custom @@ -0,0 +1,840 @@ +#!/bin/bash + +# Global bash customization settings +# Copyright (C) 2018 Pekka Helenius +# +# This program 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 program 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 program. If not, see . + +############################################################################## +# In order to use this file, replace the following line in /etc/bash.bashrc file: + +# PS1="[\\u@\\h \\W]\\$ " +# +# with +# +# [[ -f /etc/bash.custom ]] && . /etc/bash.custom || PS1="[\\u@\\h \\W]\\$ " + +# Insert/Install this file into /etc folder. + +# After that, you can change bash settings globally by editing /etc/bash.custom file + +############################################################################## +# Check https://www.cyberciti.biz/tips/howto-linux-unix-bash-shell-setup-prompt.html for more settings + +####################################### + +# Use server environment settings? Main switch. +# Use only if you implement this solution to a server environment +# You don't need this feature for client/local computers + +ENABLE_SERVER_ENV=no + +####################################### + +# APPLIES ONLY IF SERVER ENVIRONMENT ENABLED + +# Retrieve time zone information for every user connected with a SSH client +# Based on a look up for local GeoIP database +# If timezone can't be defined, use UTC time as a fallback value +# Timezone information can be overwritten by exporting TZ variable with +# desirable value as the user in the user-specific $HOME/.bashrc file +# +# This method doesn't require any environment variables delivered via SSH +# connection by a client +# This method doesn't require any modifications to /etc/ssh/sshd_config file. +# +ENABLE_SSH_TIMEZONE=yes + +####################################### + +# APPLIES ONLY IF SERVER ENVIRONMENT ENABLED + +# If server environment is enabled +if [[ $ENABLE_SERVER_ENV == "yes" ]]; then + + if [[ $ENABLE_SSH_TIMEZONE == "yes" ]]; then + + if [[ $(export -p | grep SSH_TTY) ]]; then + . $(which ssh_timezone) + fi + fi +fi + +############################################################################## +# Hook to bash's STDERR output so that it will be printed as red for all users +export LD_PRELOAD="/usr/\$LIB/libstderred.so${LD_PRELOAD:+:$LD_PRELOAD}" + +############################################################################## +# COLOR TABLE +# These are available colors +# Expand if you wish + +# Full color table available by executing 'tputcolors' command + +# To get equal color values here, use command 'tput setaf | hexdump -c' + +# By default, blank TTY sessions have TERM=linux, which has limitation of 8 possible colors when +# tput is used. On many graphical environments, TERM=xterm-256color is used instead, expanding +# all possible colors to 256. +# Because colors defined in this bash file rely on 256 color support, we must +# export TERM=xterm-256color in all opened shell sessions, including blank TTYs. +# +# Setting raw color values, which are disabled below, does not work well with +# slash \$ escaped 'bash_foldercolor' function (defined below) +# +# You get count of supported colors with 'tput colors' command +# +export TERM=xterm-256color + +bash_red=$(tput setaf 196) +bash_pink=$(tput setaf 211) +bash_green=$(tput setaf 46) +bash_yellow=$(tput setaf 226) +bash_light_yellow=$(tput setaf 229) +bash_gold=$(tput setaf 184) +bash_orange=$(tput setaf 172) +bash_blue=$(tput setaf 27) +bash_light_blue=$(tput setaf 33) +bash_magenta=$(tput setaf 201) +bash_cyan=$(tput setaf 51) +bash_turquoise=$(tput setaf 86) +bash_grey=$(tput setaf 250) +bash_white=$(tput setaf 255) + +bash_color_default=$(tput sgr0) + +#bash_red="\033[38;5;196m" +#bash_pink="\033[38;5;211" +#bash_green="\033[38;5;46m" +#bash_yellow="\033[38;5;226m" +#bash_light_yellow="\033[38;5;229m" +#bash_gold="\033[38;5;184m" +#bash_orange="\033[38;5;172m" +#bash_blue="\033[38;5;27m" +#bash_light_blue="\033[38;5;33m" +#bash_magenta="\033[38;5;201m" +#bash_cyan="\033[38;5;51m" +#bash_turquoise="\033[38;5;86m" +#bash_grey="\033[38;5;250m" +#bash_white="\033[38;5;255m" + +#bash_color_default="\033[0m" + +############################################################################## +# COLOR TABLE CHECK FUNCTION + +bash_colorstring() { + + case $1 in + red) + printf "\x01%s\x02" "${bash_red}" + ;; + pink) + printf "\x01%s\x02" "${bash_pink}" + ;; + green) + printf "\x01%s\x02" "${bash_green}" + ;; + yellow) + printf "\x01%s\x02" "${bash_yellow}" + ;; + light_yellow) + printf "\x01%s\x02" "${bash_light_yellow}" + ;; + gold) + printf "\x01%s\x02" "${bash_gold}" + ;; + orange) + printf "\x01%s\x02" "${bash_orange}" + ;; + blue) + printf "\x01%s\x02" "${bash_blue}" + ;; + light_blue) + printf "\x01%s\x02" "${bash_light_blue}" + ;; + magenta|purple) + printf "\x01%s\x02" "${bash_magenta}" + ;; + cyan) + printf "\x01%s\x02" "${bash_cyan}" + ;; + turquoise) + printf "\x01%s\x02" "${bash_turquoise}" + ;; + grey) + printf "\x01%s\x02" "${bash_grey}" + ;; + white) + printf "\x01%s\x02" "${bash_white}" + ;; + default|*) + printf "\x01%s\x02" "${bash_color_default}" + esac +} + +############################################################################## + +# Original PS1 variable value +#PS1='[\u@\h \W]\$ ' + +####################################### + +# APPLIES ONLY IF SERVER ENVIRONMENT ENABLED + +# Different command prompt for local (server) logins? +# Distinguish from SSH logins +# This string does not have any colors for now +# Applies only to tty sessions (sessions without X desktop) + +BASH_PS1_DIFFERENT_LOCAL=yes +BASH_PS1_LOCAL='[\u: \W ]\$ ' + +####################################### +# This is an override switch for all color settings +BASH_PS1_SHOW_COLORS=yes + +####################################### +# Start and ending symbols for command prompt + +BASH_PS1_START="[" +BASH_PS1_START_COLORS=no +BASH_PS1_START_COLOR=$(bash_colorstring default) + +BASH_PS1_END=" ]" +BASH_PS1_END_COLORS=no +BASH_PS1_END_COLOR=$(bash_colorstring default) + +####################################### +# Override command prompt string? +BASH_PS1_SYNTAX_OVERRIDE=no +BASH_PS1_SYNTAX_OVERRIDESTR='[\u@\h \W]\$ ' + +####################################### +# Use colors for users? +# Group 'sudo' members are considered as sysadmins. + +BASH_USER_COLORS=yes +BASH_SYSADMIN_COLOR=$(bash_colorstring yellow) +BASH_USER_COLOR=$(bash_colorstring default) +BASH_ROOT_COLOR=$(bash_colorstring red) + +####################################### +# Use different color for folders owned by the user and some other color for other folders? +BASH_FOLDER_COLORS=yes +BASH_USER_FOLDER_COLOR=$(bash_colorstring green) +BASH_NOTOWNED_FOLDER_COLOR=$(bash_colorstring red) + +####################################### +# Colors for ls command? +BASH_LS_COLORS=yes + +####################################### +# Show the name of this computer? +BASH_SHOW_HOSTNAME=no + +# User and hostname separator settings +BASH_HOSTNAME_SEP="@" +BASH_HOSTNAME_SEP_COLORS=no +BASH_HOSTNAME_SEP_COLOR=$(bash_colorstring gold) + +# Use color for hostname? +BASH_HOSTNAME_COLORS=yes +BASH_HOSTNAME_COLOR=$(bash_colorstring blue) + +####################################### +# Hostname/user and folder separator settings + +BASH_FOLDER_SEP=":" +BASH_FOLDER_SEP_COLORS=no +BASH_FOLDER_SEP_COLOR=$(bash_colorstring default) + +####################################### +# Suffix symbol settings + +BASH_SUFFIX_SYMBOL="$ " +BASH_SUFFIX_SYMBOL_ROOT="# " +BASH_SUFFIX_COLORS=no +BASH_SUFFIX_COLOR=$(bash_colorstring default) + +############################################################################## +# Timestamp + +# Show timestamp in the command prompt? +BASH_SHOW_TIMESTAMP=yes + +# Example: 26/02/2018 21:33:19 +# "\D{%d/%m/%Y} \t" + +# Example: 26/02/2018 +# "\D{%d/%m/%Y}" + +# Example: 21:33:19 +# "\t" + +BASH_TIMESTAMP_FORMAT=" \! | \D{%d/%m/%Y} \t" +BASH_TIMESTAMP_COLORS=no +BASH_TIMESTAMP_COLOR=$(bash_colorstring default) + +####################################### +# Return codes after command execution + +# Show command return code in bash? +USE_RETCODE=yes +# Print human readable text strings for each code? +RETCODE_HUMAN=no +# Use colors in error codes? +RETCODE_COLORS=yes + +if [[ $USE_RETCODE == "yes" ]]; then + + function RETCODE() { + + local RET=$? + + case $RET in + 0) + local RETC=$(bash_colorstring green) + local RETH="ok" + ;; + 1) + local RETC=$(bash_colorstring red) + local RETH="error" + ;; + 2) + local RETC=$(bash_colorstring orange) + local RETH="misuse of shell builtin" + ;; + 127) + local RETC=$(bash_colorstring orange) + local RETH="not found" + ;; + 128) + local RETC=$(bash_colorstring red) + local RETH="invalid exit argument" + ;; + 130) + local RETC=$(bash_colorstring purple) + local RETH="aborted" + ;; + *) + local RETC=$(bash_colorstring yellow) + local RETH="undefined exit code" + ;; + esac + + if [[ $RETCODE_COLORS == "no" ]]; then + RETC=$(bash_colorstring default) + fi + + if [[ $RETCODE_HUMAN == "yes" ]]; then + printf "Return code: ${RETC}$RET - $RETH$(bash_colorstring default)\n" + else + printf "Return code: ${RETC}$RET$(bash_colorstring default)\n" + fi + + } + PROMPT_COMMAND=RETCODE +fi + +############################################################################## +# Set up ls command colors +# +if [[ $BASH_PS1_SHOW_COLORS == "yes" ]]; then + + if [[ $BASH_LS_COLORS == "yes" ]]; then + eval "$(dircolors -b /etc/dircolors)" + alias ls='ls --color=auto' + fi +fi + +####################################### +# Set up starting and ending symbols +# +if [[ $BASH_PS1_START_COLORS == "yes" ]]; then + BASH_PS1_START_INSERT="${BASH_PS1_START_COLOR}${BASH_PS1_START}$(bash_colorstring default)" +else + BASH_PS1_START_INSERT="${BASH_PS1_START}" +fi + +if [[ $BASH_PS1_END_COLORS == "yes" ]]; then + BASH_PS1_END_INSERT="${BASH_PS1_END_COLOR}${BASH_PS1_END}$(bash_colorstring default)" +else + BASH_PS1_END_INSERT="${BASH_PS1_END}" +fi + +####################################### +# Set up folder-specific colors +# +bash_foldercolor() { + # Change color if we are not owner of the current dir + # For root we always use green color + # + if [[ $BASH_FOLDER_COLORS == "yes" ]]; then + if [[ $(stat -c %u "$PWD") -eq $(id -u) ]] || [[ $(id -u) -eq 0 ]]; then + # Green color + printf "%s" "${BASH_USER_FOLDER_COLOR}" + else + # Red color + printf "%s" "${BASH_NOTOWNED_FOLDER_COLOR}" + fi + else + # White color // reset attributes + printf "%s" "$(bash_colorstring default)" + fi +} + +####################################### +# Set up user-specific colors +# +bash_usercolor() { + + if [[ $BASH_USER_COLORS == "yes" ]] ;then + + if [[ $(id -u) == 0 ]]; then + printf "%s" "${BASH_ROOT_COLOR}" + elif [[ $(groups | grep -o sudo) ]]; then + printf "%s" "${BASH_SYSADMIN_COLOR}" + else + printf "%s" "${BASH_USER_COLOR}" + fi + else + printf "%s" "$(bash_colorstring default)" + fi +} + +####################################### +# Set up computer hostname +# +bash_hostname() { + if [[ $BASH_SHOW_HOSTNAME == "yes" ]]; then + + if [[ $BASH_HOSTNAME_SEP_COLORS == "yes" ]]; then + BASH_HOSTNAME_SEP_INSERT="${BASH_HOSTNAME_SEP_COLOR}${BASH_HOSTNAME_SEP}$(bash_colorstring default)" + else + BASH_HOSTNAME_SEP_INSERT="${BASH_HOSTNAME_SEP}" + fi + + if [[ $BASH_HOSTNAME_COLORS == "yes" ]]; then + printf "%s" "\u$(bash_colorstring default)${BASH_HOSTNAME_SEP_INSERT}${BASH_HOSTNAME_COLOR}\h$(bash_colorstring default)" + else + printf "%s" "\u$(bash_colorstring default)${BASH_HOSTNAME_SEP_INSERT}\h" + fi + else + printf "%s" "\u$(bash_colorstring default)" + fi +} + +####################################### +# Set up folder separator +# +bash_folder_separator() { + if [[ $BASH_FOLDER_SEP_COLORS == "yes" ]] && [[ $BASH_SHOW_HOSTNAME == "yes" ]]; then + printf "%s" "${BASH_FOLDER_SEP_COLOR}${BASH_FOLDER_SEP}$(bash_colorstring default)" + else + printf "%s" "${BASH_FOLDER_SEP}" + fi +} + +####################################### +# Set up timestamp +# +bash_timestamp() { + if [[ $BASH_SHOW_TIMESTAMP == "yes" ]]; then + if [[ $BASH_TIMESTAMP_COLORS == "yes" ]]; then + printf "%s" "${BASH_TIMESTAMP_COLOR}${BASH_TIMESTAMP_FORMAT}$(bash_colorstring default) - " + else + printf "%s" "${BASH_TIMESTAMP_FORMAT} - " + fi + else + printf "" + fi +} + +####################################### +# Set up suffix symbol +# +bash_suffixsymbol() { + + if [[ $(id -u) -eq 0 ]]; then + BASH_SUFFIX=${BASH_SUFFIX_SYMBOL_ROOT} + else + BASH_SUFFIX=${BASH_SUFFIX_SYMBOL} + fi + + if [[ $BASH_SUFFIX_COLORS == "yes" ]]; then + printf "%s" "${BASH_SUFFIX_COLOR}${BASH_SUFFIX}$(bash_colorstring default)" + else + printf "%s" "${BASH_SUFFIX}" + fi +} + +####################################### +# Export command prompt string +# +if [[ $BASH_PS1_SHOW_COLORS != "yes" ]]; then + + BASH_PS1_START_COLORS=$(bash_colorstring default) + BASH_PS1_END_COLORS=$(bash_colorstring default) + + BASH_USER_COLOR=$(bash_colorstring default) + BASH_ROOT_COLOR=$(bash_colorstring default) + + BASH_USER_FOLDER_COLOR=$(bash_colorstring default) + BASH_NOTOWNED_FOLDER_COLOR=$(bash_colorstring default) + + BASH_HOSTNAME_COLOR=$(bash_colorstring default) + + BASH_SUFFIX_COLOR=$(bash_colorstring default) + + BASH_TIMESTAMP_COLOR=$(bash_colorstring default) +fi + +ps1_syntax() { + # Default string + export PS1="$BASH_PS1_START_INSERT$(bash_timestamp)$(bash_usercolor)$(bash_hostname)$(bash_folder_separator) \$(bash_foldercolor)\W$(bash_colorstring default)$BASH_PS1_END_INSERT$(bash_suffixsymbol)" +} + +if [[ $BASH_PS1_SYNTAX_OVERRIDE == "no" ]]; then + + # If we want to use different PS1 variable for local logins... + if [[ $BASH_PS1_DIFFERENT_LOCAL == "yes" ]] && [[ $ENABLE_SERVER_ENV == "yes" ]]; then + + # Check if we are local login... + # Returns 0 (true) if we are, otherwise 1 (false) + if [[ ! $(export -p | grep SSH_TTY) ]]; then + export PS1=${BASH_PS1_LOCAL} + else + ps1_syntax + fi + else + ps1_syntax + fi + +elif [[ $BASH_PS1_SYNTAX_OVERRIDE == "yes" ]]; then + + # User override string + export PS1=${BASH_PS1_SYNTAX_OVERRIDESTR} + +else + + # Fallback string + export PS1='[\u@\h \W]\$ ' +fi + +############################################################################## +# Common messages for sudo checks +# + +# Ask password every time for sudo commands? +SUDO_ASKPASS=yes + +# Separator +function INFO_SEP() { + # http://wiki.bash-hackers.org/snipplets/print_horizontal_line#a_line_across_the_entire_width_of_the_terminal + printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +} + +# Default information printed to user +INFO_MSG="\ +$(bash_colorstring orange)\ +Privileged permissions required\ +$(bash_colorstring default)\ +" +# +# If any of the following messages is printed by a command, +# then try the command with sudo prefix +ERROR_MSGS="\ +Permission denied|\ +Operation not permitted|\ +you cannot perform this operation unless you are root|\ +You may not view or modify password information for root\ +" + +####################################### +# Check if the current user belongs to sudo +# or is root +# +sudocheck() { + + if [[ $UID -ne 0 ]]; then + + if [[ ! $(printf $(groups | grep sudo &> /dev/null)$?) -eq 0 ]]; then + printf "Current user does not have sufficient permissions and does not belong to 'sudo' group.\n" + return 1 + else + + if [[ $SUDO_ASKPASS == "yes" ]]; then + sudo -k + fi + + return 0 + fi + else + return 0 + fi + +} + +####################################### +# Execute with sudo if no permissions +# to execute a command otherwise +# +# NOTE: This does not work for nano or cd commands +# +trap 'sudoperms' ERR + +function sudoperms() { + + # Previous command (ERR) always returns value 1 which is not + # we don't want if the following sudo command succeeds + # + unset PROMPT_COMMAND + + local CMD="${BASH_COMMAND}" + local i=0 + + # WORKAROUND + # rm command has an interactive prompt where + # it asks for confirmation for file deletion + # However, interactive prompt does not work + # very well here, thus we hook --force/-f + # option to the original rm command + # + if [[ "${CMD}" =~ ^rm[[:space:]] ]]; then + CMD=$(printf "${CMD}" | sed -E 's/^rm/rm -f/') + fi + + while [[ $i < 1 ]]; do + + if [[ $(${CMD} 2>&1 > /dev/null | grep -E "${ERROR_MSGS}") ]]; then + printf "${INFO_MSG}\n" + sudocheck + if [[ $? -eq 0 ]]; then + INFO_SEP + + # Execute the failed command with sudo and get its return code + sudo bash -c "${CMD}" && RETCODE + fi + fi + + let i++ + done + +} + +####################################### +# If nano doesn't have correct permissions, use sudo +# automatically for it +# +sudonano() { + + # Prevent file names having spaces to be splitted up to + # multiple arguments by setting local IFS variable to be + # a newline instead of space + # + local IFS=$'\n' + + # Get all input arguments into a new array + local i=0 + for arg in "${@}"; do + ARGS[$i]="${arg}" + let i++ + done + + # If the first argument is not -h or --help, apply other arguments, too + # + if [[ "${1}" != "-h" ]] || [[ "${1}" != "--help" ]]; then + # If the last input argument is a file, delete + # it from the existing ARGS array + # and put it into a new variable FILE . + # Check owner of the file + # + # If no input file is given, treat + # all arguments as options for nano editor + # + if [[ -f "${ARGS[-1]}" ]]; then + + # Get full file path (e.g. if user types just + # name of a file in the current folder) + local FILE=$(readlink -f "${ARGS[-1]}") + + # Set single quotes around the file name with full path + # This is just for stat command below + # + local FILE=$(printf "${FILE}" | sed "s/\(.*\)\r/'\1'/g") + local OWNER=$(stat -c %u "${FILE}") + + # Remove filename from the arguments list since it + # is not actually an argument we want to supply to + # nano. We need to treat the filename in a special + # way unlike other arguments + # + unset 'ARGS[${#ARGS[@]}-1]' + + # Add escape prefixes to every whitespace we have + # in the filename because single quotes are + # not well preserved when supplying filename + # to nano command + # + if [[ "${FILE}" =~ [[:space:]] ]]; then + FILE=$(printf "${FILE}" | sed 's/ /\\ /g') + fi + + # If arguments were given, put them before + # the filename. If no arguments were given, + # just supply the filename to nano command + # + if [[ -n ${ARGS[*]} ]]; then + local OPTIONS="${ARGS[*]} ${FILE}" + else + local OPTIONS="${FILE}" + fi + else + local OPTIONS="${ARGS[*]}" + fi + else + local OPTIONS="${1}" + fi + + if [[ $UID -ne 0 ]]; then + if [[ -v OWNER ]]; then + if [[ $OWNER -ne $UID ]]; then + printf "${INFO_MSG}\n" + sudocheck + if [[ $? -eq 0 ]]; then + INFO_SEP + sudo nano ${OPTIONS} + fi + else + nano ${OPTIONS} + fi + else + nano ${OPTIONS} + fi + else + nano ${OPTIONS} + fi + + # In a case of failure (e.g. return code 1) + # we want to get the real code number + # That's why we call RETCODE function + # which returns the right value for + # the previous command + # + RETCODE + + # We need to unset PROMPT_COMMAND variable + # after RETCODE function execution + # Otherwise we get false-positive + # return value (return code 0) for + # the previous command, no matter + # whether it succeeded or failed + # + unset PROMPT_COMMAND + +} + +if [[ $(printf $(which nano &> /dev/null)$?) -eq 0 ]]; then + alias nano='sudonano' +fi + +####################################### +# If find doesn't have correct permissions, use sudo +# automatically for it +# +: ' +sudofind() { + + if [[ ! "${1}" =~ ^-{1,2}[a-z]* ]]; then + if [[ ! -d "${1}" ]]; then + printf "$(bash_colorstring red)Error:$(bash_colorstring default) ${1}: No such directory\n" + return 1 + fi + else + find "${1}" + fi + + if [[ $UID -ne 0 ]]; then + + local i=0 + for arg in "${@}"; do + if [[ $arg =~ [[:space:]] ]]; then + arg=\"$arg\" + fi + local ARGS[$i]="${arg}" + let i++ + done + + local DIRPATH="${ARGS[0]}" + local OWNER_STR=$(stat -c %U "${DIRPATH}") + local USER_STR=$(id -un $UID) + + if [[ $OWNER_STR == $USER_STR ]]; then + find "${ARGS[*]}" + else + sudo SUDOARGS="${ARGS[*]}" -u $OWNER_STR bash -c 'find "${SUDOARGS}"' + fi + else + find "${ARGS[*]}" + fi + +} + +alias find='sudofind' +' + +####################################### +# If we don't have access to a directory, check dir owner +# and access the folder as that user with sudo +# +sudocd() { + + if [[ -d "${1}" ]]; then + + if [[ $UID -ne 0 ]]; then + + if [[ $(stat -c %u "${1}") -ne $UID ]]; then + + local PERMS=$(stat -c %A "${1}") + + if [[ $(echo "${PERMS:9:1}") == "x" ]]; then + cd "${1}" + else + + printf "${INFO_MSG}\n" + sudocheck + if [[ $? -eq 0 ]]; then + INFO_SEP + local OWNER=$(stat -c %U "${1}") + printf "Opening $OWNER shell environment\n" + sudo GODIR="${1}" -u $OWNER bash -c 'cd "${GODIR}"; $SHELL' + fi + fi + else + cd "${1}" + fi + else + cd "${1}" + fi + elif [[ -z "${1}" ]]; then + cd "${HOME}" + else + printf "$(bash_colorstring red)Error:$(bash_colorstring default) No such directory\n" + return 1 + fi + +} + +alias cd='sudocd' diff --git a/tools/LS_COLORS b/tools/LS_COLORS new file mode 100644 index 0000000..564e852 --- /dev/null +++ b/tools/LS_COLORS @@ -0,0 +1,708 @@ +# LS_COLORS +# Maintainers: Magnus Woldrich , +# Ryan Delaney OpenGPG: 0D98863B4E1D07B6 +# URL: https://github.com/trapd00r/LS_COLORS +# Version: 0.254 +# Updated: Tue Mar 29 21:25:30 AEST 2016 +# +# This is a collection of extension:color mappings, suitable to use as your +# LS_COLORS environment variable. Most of them use the extended color map, +# described in the ECMA-48 document; in other words, you'll need a terminal +# with capabilities of displaying 256 colors. +# +# As of this writing, around 300 different filetypes/extensions is supported. +# That's indeed a lot of extensions, but there's a lot more! Therefore I need +# your help. +# +# Fork this project on github, add the extensions you are missing, and send me +# a pull request. +# +# For files that usually ends up next to each other, like html, css and js, +# try to pick colors that fit nicely together. Filetypes with multiple +# possible extensions, like htm and html, should have the same color. + +# This program 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 Perl Artistic License for more details. +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the Perl Artistic License as published by the Perl Foundation, +# either version 1.0 of the License, or (at your option) any later version. +# +# You should have received a copy of the Perl Artistic License along +# with this program. If not, see . + +# core {{{1 +BLK 38;5;68 +CAPABILITY 38;5;17 +CHR 38;5;113;1 +DIR 38;5;30 +DOOR 38;5;127 +EXEC 38;5;208;1 +FIFO 38;5;126 +FILE 0 +LINK target +MULTIHARDLINK 38;5;222;1 +# "NORMAL don't reset the bold attribute - +# https://github.com/trapd00r/LS_COLORS/issues/11 +#NORMAL 38;5;254 +NORMAL 0 +ORPHAN 48;5;196;38;5;232;1 +OTHER_WRITABLE 38;5;220;1 +SETGID 48;5;3;38;5;0 +SETUID 38;5;220;1;3;100;1 +SOCK 38;5;197 +STICKY 38;5;86;48;5;234 +STICKY_OTHER_WRITABLE 48;5;235;38;5;139;3 + +*LS_COLORS 48;5;89;38;5;197;1;3;4;7 # :-) +# }}} +# documents {{{1 +*README 38;5;220;1 +*README.rst 38;5;220;1 +*LICENSE 38;5;220;1 +*COPYING 38;5;220;1 +*INSTALL 38;5;220;1 +*COPYRIGHT 38;5;220;1 +*AUTHORS 38;5;220;1 +*HISTORY 38;5;220;1 +*CONTRIBUTORS 38;5;220;1 +*PATENTS 38;5;220;1 +*VERSION 38;5;220;1 +*NOTICE 38;5;220;1 +*CHANGES 38;5;220;1 +.log 38;5;190 +# plain-text {{{2 +.txt 38;5;253 +# markup {{{2 +.etx 38;5;184 +.info 38;5;184 +.markdown 38;5;184 +.md 38;5;184 +.mkd 38;5;184 +.nfo 38;5;184 +.pod 38;5;184 +.rst 38;5;184 +.tex 38;5;184 +.textile 38;5;184 +# key-value, non-relational data {{{2 +.json 38;5;178 +.msg 38;5;178 +.pgn 38;5;178 +.rss 38;5;178 +.xml 38;5;178 +.yaml 38;5;178 +.yml 38;5;178 +.RData 38;5;178 +.rdata 38;5;178 +# }}} +# binary {{{2 +.cbr 38;5;141 +.cbz 38;5;141 +.chm 38;5;141 +.djvu 38;5;141 +.pdf 38;5;141 +.PDF 38;5;141 +# words {{{3 +.docm 38;5;111;4 +.doc 38;5;111 +.docx 38;5;111 +.eps 38;5;111 +.ps 38;5;111 +.odb 38;5;111 +.odt 38;5;111 +.rtf 38;5;111 +# presentation {{{3 +.odp 38;5;166 +.pps 38;5;166 +.ppt 38;5;166 +.pptx 38;5;166 +# Powerpoint show +.ppts 38;5;166 +# Powerpoint with enabled macros +.pptxm 38;5;166;4 +# Powerpoint show with enabled macros +.pptsm 38;5;166;4 +# spreadsheet {{{3 +.csv 38;5;78 +# Open document spreadsheet +.ods 38;5;112 +.xla 38;5;76 +# Excel spreadsheet +.xls 38;5;112 +.xlsx 38;5;112 +# Excel spreadsheet with macros +.xlsxm 38;5;112;4 +# Excel module +.xltm 38;5;73;4 +.xltx 38;5;73 +# }}} +# }}} +# configs {{{2 +*cfg 1 +*conf 1 +*rc 1 +.ini 1 +.plist 1 +# vim +.viminfo 1 +# cisco VPN client configuration +.pcf 1 +# adobe photoshop proof settings file +.psf 1 +# }}} +# }}} +# code {{{1 +# version control {{{2 +.git 38;5;197 +.gitignore 38;5;240 +.gitattributes 38;5;240 +.gitmodules 38;5;240 + +# shell {{{2 +.awk 38;5;172 +.bash 38;5;172 +.bat 38;5;172 +.BAT 38;5;172 +.sed 38;5;172 +.sh 38;5;172 +.zsh 38;5;172 +.vim 38;5;172 + +# interpreted {{{2 +.ahk 38;5;41 +# python +.py 38;5;41 +# perl +.pl 38;5;208 +.PL 38;5;160 +.t 38;5;114 +# sql +.msql 38;5;222 +.mysql 38;5;222 +.pgsql 38;5;222 +.sql 38;5;222 +# Tool Command Language +.tcl 38;5;64;1 +# R language +.r 38;5;49 +.R 38;5;49 +# GrADS script +.gs 38;5;81 + +# compiled {{{2 +# +# assembly language +.asm 38;5;81 +# LISP +.cl 38;5;81 +.lisp 38;5;81 +# lua +.lua 38;5;81 +# Moonscript +.moon 38;5;81 +# C +.c 38;5;81 +.C 38;5;81 +.h 38;5;110 +.H 38;5;110 +.tcc 38;5;110 +# C++ +.c++ 38;5;81 +.h++ 38;5;110 +.hpp 38;5;110 +.hxx 38;5;110 +.ii 38;5;110 +# method file for Objective C +.M 38;5;110 +.m 38;5;110 +# Csharp +.cc 38;5;81 +.cs 38;5;81 +.cp 38;5;81 +.cpp 38;5;81 +.cxx 38;5;81 +# Crystal +.cr 38;5;81 +# Google golang +.go 38;5;81 +# fortran +.f 38;5;81 +.for 38;5;81 +.ftn 38;5;81 +# pascal +.s 38;5;110 +.S 38;5;110 +# Rust +.rs 38;5;81 +# Swift +.swift 38;5;219 +# ? +.sx 38;5;81 +# interface file in GHC - https://github.com/trapd00r/LS_COLORS/pull/9 +.hi 38;5;110 +# haskell +.hs 38;5;81 +.lhs 38;5;81 + +# binaries {{{2 +# compiled apps for interpreted languages +.pyc 38;5;240 +# }}} +# html {{{2 +.css 38;5;125;1 +.less 38;5;125;1 +.sass 38;5;125;1 +.scss 38;5;125;1 +.htm 38;5;125;1 +.html 38;5;125;1 +.jhtm 38;5;125;1 +.mht 38;5;125;1 +.eml 38;5;125;1 +.mustache 38;5;125;1 +# }}} +# java {{{2 +.coffee 38;5;074;1 +.java 38;5;074;1 +.js 38;5;074;1 +.jsm 38;5;074;1 +.jsm 38;5;074;1 +.jsp 38;5;074;1 +# }}} +# php {{{2 +.php 38;5;81 +# CakePHP view scripts and helpers +.ctp 38;5;81 +# Twig template engine +.twig 38;5;81 +# }}} +# vb/a {{{2 +.vb 38;5;81 +.vba 38;5;81 +.vbs 38;5;81 +# 2}}} +# Build stuff {{{2 +*Dockerfile 38;5;155 +.dockerignore 38;5;240 +*Makefile 38;5;155 +*MANIFEST 38;5;243 +*pm_to_blib 38;5;240 +# automake +.am 38;5;242 +.in 38;5;242 +.hin 38;5;242 +.scan 38;5;242 +.m4 38;5;242 +.old 38;5;242 +.out 38;5;242 +.SKIP 38;5;244 +# }}} +# patch files {{{2 +.diff 48;5;197;38;5;232 +.patch 48;5;197;38;5;232;1 +#}}} +# graphics {{{1 +.bmp 38;5;97 +.tiff 38;5;97 +.tif 38;5;97 +.TIFF 38;5;97 +.cdr 38;5;97 +.gif 38;5;97 +.ico 38;5;97 +.jpeg 38;5;97 +.JPG 38;5;97 +.jpg 38;5;97 +.nth 38;5;97 +.png 38;5;97 +.psd 38;5;97 +.xpm 38;5;97 +# }}} +# vector {{{1 +.ai 38;5;99 +.eps 38;5;99 +.epsf 38;5;99 +.drw 38;5;99 +.ps 38;5;99 +.svg 38;5;99 +# }}} +# video {{{1 +.avi 38;5;114 +.divx 38;5;114 +.IFO 38;5;114 +.m2v 38;5;114 +.m4v 38;5;114 +.mkv 38;5;114 +.MOV 38;5;114 +.mov 38;5;114 +.mp4 38;5;114 +.mpeg 38;5;114 +.mpg 38;5;114 +.ogm 38;5;114 +.rmvb 38;5;114 +.sample 38;5;114 +.wmv 38;5;114 + # mobile/streaming {{{2 +.3g2 38;5;115 +.3gp 38;5;115 +.gp3 38;5;115 +.webm 38;5;115 +.gp4 38;5;115 +.asf 38;5;115 +.flv 38;5;115 +.ts 38;5;115 +.ogv 38;5;115 +.f4v 38;5;115 + # }}} + # lossless {{{2 +.VOB 38;5;115;1 +.vob 38;5;115;1 +# }}} +# audio {{{1 +.3ga 38;5;137;1 +.S3M 38;5;137;1 +.aac 38;5;137;1 +.au 38;5;137;1 +.dat 38;5;137;1 +.dts 38;5;137;1 +.fcm 38;5;137;1 +.m4a 38;5;137;1 +.mid 38;5;137;1 +.midi 38;5;137;1 +.mod 38;5;137;1 +.mp3 38;5;137;1 +.mp4a 38;5;137;1 +.oga 38;5;137;1 +.ogg 38;5;137;1 +.opus 38;5;137;1 +.s3m 38;5;137;1 +.sid 38;5;137;1 +.wma 38;5;137;1 +# lossless +.ape 38;5;136;1 +.aiff 38;5;136;1 +.cda 38;5;136;1 +.flac 38;5;136;1 +.alac 38;5;136;1 +.midi 38;5;136;1 +.pcm 38;5;136;1 +.wav 38;5;136;1 +.wv 38;5;136;1 +.wvc 38;5;136;1 + +# }}} +# fonts {{{1 +.afm 38;5;66 +.fon 38;5;66 +.fnt 38;5;66 +.pfb 38;5;66 +.pfm 38;5;66 +.ttf 38;5;66 +.otf 38;5;66 +# postscript fonts +.PFA 38;5;66 +.pfa 38;5;66 +# }}} +# archives {{{1 +.7z 38;5;40 +.a 38;5;40 +.arj 38;5;40 +.bz2 38;5;40 +.cpio 38;5;40 +.gz 38;5;40 +.lrz 38;5;40 +.lz 38;5;40 +.lzma 38;5;40 +.lzo 38;5;40 +.rar 38;5;40 +.s7z 38;5;40 +.sz 38;5;40 +.tar 38;5;40 +.tgz 38;5;40 +.xz 38;5;40 +.z 38;5;40 +.Z 38;5;40 +.zip 38;5;40 +.zipx 38;5;40 +.zoo 38;5;40 +.zpaq 38;5;40 +.zz 38;5;40 + # packaged apps {{{2 +.apk 38;5;215 +.deb 38;5;215 +.rpm 38;5;215 +.jad 38;5;215 +.jar 38;5;215 +.cab 38;5;215 +.pak 38;5;215 +.pk3 38;5;215 +.vdf 38;5;215 +.vpk 38;5;215 +.bsp 38;5;215 +.dmg 38;5;215 + # }}} + # segments from 0 to three digits after first extension letter {{{2 +.r[0-9]{0,2} 38;5;239 +.zx[0-9]{0,2} 38;5;239 +.z[0-9]{0,2} 38;5;239 +# partial files +.part 38;5;239 + # }}} +# partition images {{{2 +.dmg 38;5;124 +.iso 38;5;124 +.bin 38;5;124 +.nrg 38;5;124 +.qcow 38;5;124 +.sparseimage 38;5;124 +.toast 38;5;124 +.vcd 38;5;124 +.vmdk 38;5;124 +# }}} +# databases {{{2 +.accdb 38;5;60 +.accde 38;5;60 +.accdr 38;5;60 +.accdt 38;5;60 +.db 38;5;60 +.fmp12 38;5;60 +.fp7 38;5;60 +.localstorage 38;5;60 +.mdb 38;5;60 +.mde 38;5;60 +.sqlite 38;5;60 +.typelib 38;5;60 +# NetCDF database +.nc 38;5;60 +# }}} +# tempfiles {{{1 +# undo files +.pacnew 38;5;33 +.un~ 38;5;241 +.orig 38;5;241 +# backups +.BUP 38;5;241 +.bak 38;5;241 +.o 38;5;241 # *nix Object file (shared libraries, core dumps etc) +.rlib 38;5;241 # Static rust library +# temporary files +.swp 38;5;244 +.swo 38;5;244 +.tmp 38;5;244 +.sassc 38;5;244 +# state files +.pid 38;5;248 +.state 38;5;248 +*lockfile 38;5;248 +# error logs +.err 38;5;160;1 +.error 38;5;160;1 +.stderr 38;5;160;1 +# state dumps +.dump 38;5;241 +.stackdump 38;5;241 +.zcompdump 38;5;241 +.zwc 38;5;241 +# tcpdump, network traffic capture +.pcap 38;5;29 +.cap 38;5;29 +.dmp 38;5;29 +# macOS +.DS_Store 38;5;239 +.localized 38;5;239 +.CFUserTextEncoding 38;5;239 +# }}} +# hosts {{{1 +# /etc/hosts.{deny,allow} +.allow 38;5;112 +.deny 38;5;196 +# }}} +# systemd {{{1 +# http://www.freedesktop.org/software/systemd/man/systemd.unit.html +.service 38;5;45 +*@.service 38;5;45 +.socket 38;5;45 +.swap 38;5;45 +.device 38;5;45 +.mount 38;5;45 +.automount 38;5;45 +.target 38;5;45 +.path 38;5;45 +.timer 38;5;45 +.snapshot 38;5;45 +# }}} +# metadata {{{1 +.application 38;5;116 +.cue 38;5;116 +.description 38;5;116 +.directory 38;5;116 +.m3u 38;5;116 +.m3u8 38;5;116 +.md5 38;5;116 +.properties 38;5;116 +.sfv 38;5;116 +.srt 38;5;116 +.theme 38;5;116 +.torrent 38;5;116 +.urlview 38;5;116 +# }}} +# encrypted data {{{1 +.asc 38;5;192;3 +.bfe 38;5;192;3 +.enc 38;5;192;3 +.gpg 38;5;192;3 +.signature 38;5;192;3 +.sig 38;5;192;3 +.p12 38;5;192;3 +.pem 38;5;192;3 +.pgp 38;5;192;3 +.asc 38;5;192;3 +.enc 38;5;192;3 +.sig 38;5;192;3 +# 1}}} +# emulators {{{1 +.32x 38;5;213 +.cdi 38;5;213 +.fm2 38;5;213 +.rom 38;5;213 +.sav 38;5;213 +.st 38;5;213 + # atari +.a00 38;5;213 +.a52 38;5;213 +.A64 38;5;213 +.a64 38;5;213 +.a78 38;5;213 +.adf 38;5;213 +.atr 38;5;213 + # nintendo +.gb 38;5;213 +.gba 38;5;213 +.gbc 38;5;213 +.gel 38;5;213 +.gg 38;5;213 +.ggl 38;5;213 +.ipk 38;5;213 # Nintendo (DS Packed Images) +.j64 38;5;213 +.nds 38;5;213 +.nes 38;5;213 + # Sega +.sms 38;5;213 +# }}} +# unsorted {{{1 +# +# Portable Object Translation for GNU Gettext +.pot 38;5;7 +# CAD files for printed circuit boards +.pcb 38;5;7 +# groff (rendering app for texinfo) +.mm 38;5;7 +# perldoc +.pod 38;5;7 +# GIMP brush +.gbr 38;5;7 +# printer spool file +.spl 38;5;7 +# GIMP project file +.scm 38;5;7 +# RStudio project file +.Rproj 38;5;11 +# Nokia Symbian OS files +.sis 38;5;7 + +.1p 38;5;7 +.3p 38;5;7 +.cnc 38;5;7 +.def 38;5;7 +.ex 38;5;7 +.example 38;5;7 +.feature 38;5;7 +.ger 38;5;7 +.map 38;5;7 +.mf 38;5;7 +.mfasl 38;5;7 +.mi 38;5;7 +.mtx 38;5;7 +.pc 38;5;7 +.pi 38;5;7 +.plt 38;5;7 +.pm 38;5;7 +.rb 38;5;7 +.rdf 38;5;7 +.rst 38;5;7 +.ru 38;5;7 +.sch 38;5;7 +.sty 38;5;7 +.sug 38;5;7 +.t 38;5;7 +.tdy 38;5;7 +.tfm 38;5;7 +.tfnt 38;5;7 +.tg 38;5;7 +.vcard 38;5;7 +.vcf 38;5;7 +.xln 38;5;7 +# AppCode files +.iml 38;5;166 +# Xcode files +.xcconfig 1 +.entitlements 1 +.strings 1 +.storyboard 38;5;196 +.xcsettings 1 +.xib 38;5;208 +# }}} +# termcap {{{1 +TERM ansi +TERM color-xterm +TERM con132x25 +TERM con132x30 +TERM con132x43 +TERM con132x60 +TERM con80x25 +TERM con80x28 +TERM con80x30 +TERM con80x43 +TERM con80x50 +TERM con80x60 +TERM cons25 +TERM console +TERM cygwin +TERM dtterm +TERM Eterm +TERM eterm-color +TERM gnome +TERM gnome-256color +TERM jfbterm +TERM konsole +TERM kterm +TERM linux +TERM linux-c +TERM mach-color +TERM mlterm +TERM putty +TERM rxvt +TERM rxvt-256color +TERM rxvt-cygwin +TERM rxvt-cygwin-native +TERM rxvt-unicode +TERM rxvt-unicode-256color +TERM rxvt-unicode256 +TERM screen +TERM screen-256color +TERM screen-256color-bce +TERM screen-bce +TERM screen-w +TERM screen.linux +TERM screen.rxvt +TERM terminator +TERM vt100 +TERM xterm +TERM xterm-16color +TERM xterm-256color +TERM xterm-88color +TERM xterm-color +TERM xterm-debian +# }}} + + +# vim: ft=dircolors:fdm=marker:et:sw=2: diff --git a/tools/PKGBUILD b/tools/PKGBUILD new file mode 100644 index 0000000..6feea43 --- /dev/null +++ b/tools/PKGBUILD @@ -0,0 +1,118 @@ +# Maintainer: Pekka Helenius + +# Do we include server-specific files such as SSH timezone settings? +server_environment=false + +if [[ $server_environment == "true" ]]; then + pkgname=archtools-server + pkgdesc="Useful scripts for Arch Linux (server)" + conflicts=(archtools) +else + pkgname=archtools + pkgdesc="Useful scripts for Arch Linux" + conflicts=(archtools-server) +fi + +pkgver=0.1 +pkgrel=1 +url="https://github.com/Fincer/archtools" +arch=(any) +license=(GPL) +depends=(coreutils bash grep sed +pacman # listpkg.sh, bininfo.sh, pkginfo.sh, buildpkg.sh, installlocal.sh, missinglibs.sh, nowner.sh, findpkg.sh, pkgdeps.sh, pkgstr.sh, risks.sh, showpkg.sh +perl # findpkg.sh, genmac.sh +wget # getsource.sh +file # nowner.sh +which iputils 9base package-query # pkgdeps.sh (9base = read command) #mimetype TODO get rid of this dependency +tar xz bzip2 unrar gzip unzip p7zip cabextract #extract.sh +arch-audit bc # risks.sh +glibc # missinglibs.sh +util-linux # killprocess.sh (kill command) +stderred # bash.custom +) +makedepends=(git) +source=( +tputcolors.sh +extract.sh +findmatch.sh +findpkg.sh +genmac.sh +getsource.sh # TODO: More implementation needed. See the file for details +nowner.sh # TODO: More implementation needed. See the file for details +pkgdeps.sh # TODO: More implementation needed. See the file for details +pkgstr.sh +archrisks.sh +showpkg.sh +deltmpfiles.sh +missinglibs.sh +installlocal.sh +buildpkg.sh +pkginfo.sh +bininfo.sh +listpkg.sh +killprocess.sh +rmpkgfiles.sh +specialchars.sh +bash.custom +https://raw.github.com/trapd00r/LS_COLORS/master/LS_COLORS) + +if [[ $server_environment == "true" ]]; then + # for ssh_timezone.sh + depends+=(geoip2-database mmdblookup systemd openssh bind-tools) + source+=(ssh_timezone.sh) +fi + +sha256sums=('623b794a8a537649cc434b496dbf1f018aeea99f57f11d0719f80e495ca438b6' + '568dba0eb0dfe1875980484fe473bbbd4397bdc04622f6177992ee75ca1b065f' + 'ed4e06ceb5aff36ea66ce9de74f5ff2236ab2f92a9419d79d6fefe5a1b013859' + 'a3cf8e77af8a49935c3e9a579354f761ab7ca8c2f94760012b9e23a196307f8f' + '047bbe110d75a6e44f427675134c0594bc413efd57ca16836ff1acd607601c10' + 'a56c4e7b99078da4324c425fe4da5dc7c10c55d7fac62c8d23a86cfcf4abae0e' + '4b1015e10c0f4e4e9e0dd64533aea1ffe914f3ce6760bf6293f056b4069a4f37' + '67d5627b20ec75d94cb89f9f193daa8a8018d1453d387e0306c0032f5a9b6b30' + '88e37be0de270d023712d4bae852c54292541ca5510d09c5a1316fa5958f117c' + 'abc140033891cc4564d71e8487f6cd1e54add761417cc772652542daf7352f44' + '8b76a175d7cc767519d1e3519d1fd874cc19cc529e08a27138948f8a1907ac6a' + '6886176293cb3ed131dd83e2ca3aa15f70c559e265534e195fa8848f2d02f659' + 'ef4574de79c82d52a2cfb57cbf19419362ab702471bd71620e5893f426d150e2' + 'ac761aa82d3a369a3f5335ad8f38af6cd00181cacf24737080e6d6ed6fff1b18' + '63a7b50faba7963584519f2800205d853cc02d6386362c9efd9f61154e4c9ddb' + 'aa0b96ff9f1ff51e1ea3634fa7e17cbffa565c5b2db79ed75bd6aeeb9de9a723' + 'fc87bd14c0638cd3c803143c371946efe2c96a87d72d2c144fbaf29a815294d3' + '4baf8c7d1032cafb8535dc4d53c42b7e7f2da6839bde791c31104a3f67eb845b' + 'e179f9b18d6869558a97530101502ae6b445d3ef430e2e4359d015f214292093' + '1aae9db8652179e18691fd51c687ab393672f380084e8777145572a5699bf5cf' + '594453fefd07471e4aa167c486c77fbf589c5ee838cb0f33d3b5399fabff5ee6' + '40fd211e7b4a21ca61be81a809ee47f58adc6cd220218a20a0c7e65e1534c6ca') + +package() { + mkdir -p "$pkgdir"/{usr/bin,etc} + + #cp -R "$srcdir"/"$pkgname"/*.sh "$pkgdir"/usr/bin/ + install -m644 "$srcdir"/LS_COLORS "$pkgdir"/etc/dircolors + install -m644 "$srcdir"/bash.custom "$pkgdir"/etc/bash.custom + + for sh in ./*.sh; do + install -m755 $sh "$pkgdir"/usr/bin/ + #chmod u=rwx,g=rx,o=rx $sh + mv "$pkgdir"/usr/bin/$sh $(echo "$pkgdir"/usr/bin/$sh | sed 's/\.sh//') + done + + + msg2 ' + + In /etc/bash.bashrc file, replace line + + PS1="[\\u@\\h \\W]\\$ " + + with + + [[ -f /etc/bash.custom ]] && . /etc/bash.custom || PS1="[\\u@\\h \\W]\\$ " + + After that, you can change bash settings globally by editing /etc/bash.custom file + ' + + #msg2 "You can change bash settings globally by editing /etc/bash.custom file" + +} + diff --git a/tools/archrisks.sh b/tools/archrisks.sh new file mode 100755 index 0000000..000a98b --- /dev/null +++ b/tools/archrisks.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# archrisks - Security information tool for Arch Linux +# Copyright (C) 2018 Pekka Helenius +# +# This program 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 program 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 program. If not, see . + +###################################################################################################################### + +if [[ ! $(id -u) -eq 0 ]]; then + echo -e "\nThis command requires root privileges.\n" + exit +fi + +echo "Security report date: $(date '+%d-%m-%Y, %X') (TZ: $(timedatectl status | grep "Time zone:" | awk '{print $3}'))" + +red=$'\33[91m' +orange=$'\033[38;5;208m' +yellow=$'\033[93m' +green=$'\033[92m' +reset=$'\033[0m' + +PROVIDER="security.archlinux.org" + +# pacman, pacaur or yaourt. Please make sure all parameters used in this script are accepted by PKGMGR +PKGMGR="pacman" + +INTERNET_TEST=$(ping -c 1 $PROVIDER 2>&1 | grep -c "Name or service not known") + +if [[ ! $INTERNET_TEST -eq 0 ]]; then + echo -e "\nCan't connect to $PROVIDER. Please check your internet connection and try again.\n" +else + + echo -e "\nSynchronizing package databases with $PKGMGR\n" + $PKGMGR -Syy || return + + if [[ ! $(which arch-audit | wc -l) -eq 1 ]]; then + echo -e "\nCouldn't find Arch Linux security utility (arch-audit). Please make sure it's installed.\n" + else + + CNT=0 + PRSCNT=0 + + # Internal Field Separator. This variable determines how Bash recognizes fields, or word boundaries, when it interprets character strings. + IFS=$'\n' + + for i in $(arch-audit); do + PACKAGENAME=$(echo "$i" | awk -F ' ' '{print $2}') + RISKLEVEL=$(echo "$i" | grep -oE "Low|Medium|High|Critical") + RISKSCOUNT=$(echo "$i" | awk -F 'CVE' '{print NF-1}') + + RISKS[$CNT]="$PACKAGENAME $RISKLEVEL $RISKSCOUNT" + + let CNT++ + done + + echo -e "\e[1m" + printf "%-25s%-20s%-15s%-25s%s\n" "Package" "Security issues" "Risk level" "Version status" "Description" + echo -e "\e[0m" + + for RISK_PARSED in $(echo "${RISKS[*]}"); do + + # Package in question + col1=$(echo "$RISK_PARSED" | awk -F ' ' '{print $1}') + + # Security issues detected + col2=$(echo "$RISK_PARSED" | awk -F ' ' '{print $3}') + + #Critical, High, Medium or Low risk + col3=$(echo "$RISK_PARSED" | awk -F ' ' '{print $2}' | sed 's/Critical/0/g; s/High/1/g; s/Medium/2/g; s/Low/3/g') + + col5=$($PKGMGR -Qi $col1 |grep -i description | awk -F ": " '{print $2}') + maxchars=35 + + if [[ $(echo $col5 | wc -m) -gt $maxchars ]]; then + col5=$(echo "$(echo $col5 | cut -c 1-$maxchars)...") + fi + + #pkgurl=$(pacaur -Qi $col1 |grep URL | awk -F ": " '{print $2}') + + versioncheck() { + + parsedver() { + + TRIMMED=$(echo $1 | sed 's/[:.-]/./g') + + if [[ $TRIMMED =~ [A-Za-z] ]]; then + + PKGVERCHARS=$(echo $TRIMMED | sed 's/[^a-zA-Z]//g') + + CHARNUM=0 + for char in $PKGVERCHARS; do + charnum=$(echo {a..z} | sed 's/ //g' | grep -b -o $char | awk 'BEGIN {FS=":"}{print $1}') + REP[$CHARNUM]="s/$char/$charnum/g;" + let CHARNUM++ + done + + for seds in "${REP[*]}"; do + SEDSTR=$seds + done + + echo $TRIMMED | sed "$SEDSTR" + + else + echo $TRIMMED + fi + } + + SYSVER=$($PKGMGR -Q $1 | awk -F ' ' '{print $2}') + REPOVER=$($PKGMGR -Si $1 | grep "Version.*:" | awk -F ' ' '{print $3}') + + VERARRAY1=$(parsedver $SYSVER) + VERARRAY2=$(parsedver $REPOVER) + + #Count of version elements (0 18 2 1 contains 4 numbers, for example) + firstvernums=$(echo $VERARRAY1 | awk -F '.' '{print split($0, a)}') + lastvernums=$(echo $VERARRAY2 | awk -F '.' '{print split($0, a)}') + + # Count of comparable version elements (maximum) + # We compare this much of elements, not more + if [[ $lastvernums -lt $firstvernums ]]; then + comparables=$lastvernums + else + comparables=$firstvernums + fi + + # If all numbers are same, we don't analyze them more deeply. + if [[ $VERARRAY1 == $VERARRAY2 ]]; then + col4="${green}Package is updated" + else + + s=1 + while [ $s -le $comparables ]; do + + check1=$(echo -e $VERARRAY1 | awk -v var=$s -F '.' '{print $var}') + check2=$(echo -e $VERARRAY2 | awk -v var=$s -F '.' '{print $var}') + + if [[ $check2 -gt $check1 ]]; then + # Repo number is greater + col4="${yellow}Update available" + break + + elif [[ $check2 -lt $check1 ]]; then + # System number is greater + col4="${reset}Newer package installed" + break + fi + + let s++ + done + fi + } + + versioncheck $col1 + + RISKENTRIES[$PRSCNT]=$(printf "%s|%s|%s|%s|%s\n" "$col1" "$col2" "$col3" "$col4" "$col5") + + let PRSCNT++ + + done + + i=0 + for line in $(echo "${RISKENTRIES[*]}" | sort -t'|' -k3); do + + if [[ $(echo "$line" | awk -F '|' '{print $3}') -eq 0 ]]; then + alertclr="${red}" + IMPT="Critical" + + elif [[ $(echo "$line" | awk -F '|' '{print $3}') -eq 1 ]]; then + alertclr="${orange}" + IMPT="High" + + elif [[ $(echo "$line" | awk -F '|' '{print $3}') -eq 2 ]]; then + alertclr="${yellow}" + IMPT="Medium" + + elif [[ $(echo "$line" | awk -F '|' '{print $3}') -eq 3 ]]; then + alertclr="${green}" + IMPT="Low" + fi + + SECCOUNT=$(echo "$line" | awk -F '|' '{print $2}') + + if [[ $SECCOUNT -lt 5 ]]; then + secclr="${green}" + elif [[ $SECCOUNT -ge 5 ]] && [[ $SECCOUNT -lt 10 ]]; then + secclr="${yellow}" + elif [[ $SECCOUNT -ge 10 ]] && [[ $SECCOUNT -lt 20 ]]; then + secclr="${orange}" + elif [[ $SECCOUNT -ge 20 ]]; then + secclr="${red}" + fi + + secsum[$i]=$SECCOUNT + + echo "$line" | awk -F '|' -v clr1="${alertclr}" -v clr2="${secclr}" -v rs="${reset}" -v var="${IMPT}" '{printf "%-25s%s%-20s%s%-15s%-30s%s%s\n",$1,clr2,$2,clr1,var,$4,rs,$5}' + + let i++ + done + + secsums_total=$(echo $(printf "%d+" ${secsum[@]})0 | bc) + + echo -e "\nTotal:" + printf "%-25s%s\n\n" "$CNT" "$secsums_total" + fi +fi diff --git a/tools/bininfo.sh b/tools/bininfo.sh new file mode 100755 index 0000000..ec0a66b --- /dev/null +++ b/tools/bininfo.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +##################################### +# Show information about executable on Arch Linux +BIN=$(which $1) +echo -e "$BIN\n$(pacman -Qo $BIN)" diff --git a/tools/buildpkg.sh b/tools/buildpkg.sh new file mode 100755 index 0000000..73d7065 --- /dev/null +++ b/tools/buildpkg.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +############################# +# Build local package in PKGBUILD directory on Arch Linux +# +if [ ! -e ./PKGBUILD ]; then #We check whether PKGBUILD file exists. If no, then... + echo -e "No PKGBUILD file found!\n" + return 1 +else + rm -Rf ./{src,pkg} #This doesn't mean they really exist + updpkgsums + makepkg -f +fi diff --git a/tools/deltmpfiles.sh b/tools/deltmpfiles.sh new file mode 100755 index 0000000..f981b6a --- /dev/null +++ b/tools/deltmpfiles.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +########################################################### +# Delete current temporary files + +#All tmp files currently being used +TMP_USED=$(lsof +D /tmp/ | awk '{print $9," "}' | sort -u | tail -n+3 | sed 's/[ \t]*$//') + +#All tmp files +TMP_ALL=$(find /tmp/ -type s -print -o -type f -print | sort -u | sed 's/[ \t]*$//') + +#Get all tmp files/symlinks/etc which are not being used at the moment +# Exclude /tmp/.X11-unix/X0 from the list +# +TMP_NOTUSED=$(comm -23 <(echo "$TMP_ALL") <(echo "$TMP_USED") | sed 's/\/tmp\/.X11-unix\/X0//g; /^\s*$/d') + +echo "$TMP_NOTUSED" | while read line; do echo "Deleting file $line" && sudo rm $line ; done diff --git a/tools/extract.sh b/tools/extract.sh new file mode 100755 index 0000000..2e644c4 --- /dev/null +++ b/tools/extract.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +########################################################### +#Extract wide range of various archive types +if [ -z "$1" ]; then + # display usage if no parameters given + echo "Usage: extract ." + echo " extract [path/file_name_2.ext] [path/file_name_3.ext]" + return 1 +else + for n in $@ + do + if [ -f "$n" ] ; then + case "${n%,}" in + *.tar.bz2|*.tar.gz|*.tar.xz|*.tbz2|*.tgz|*.txz|*.tar) + tar xvf "$n" ;; + *.lzma) unlzma ./"$n" ;; + *.bz2) bunzip2 ./"$n" ;; + *.rar) unrar x -ad ./"$n" ;; + *.gz) gunzip ./"$n" ;; + *.zip) unzip ./"$n" ;; + *.z) uncompress ./"$n" ;; + *.7z|*.arj|*.cab|*.chm|*.deb|*.dmg|*.iso|*.lzh|*.msi|*.rpm|*.udf|*.wim|*.xar) + 7z x ./"$n" ;; + *.xz) unxz ./"$n" ;; + *.exe) cabextract ./"$n" ;; + *) + echo "extract: '$n' - unknown archive method" + return 1 + ;; + esac + else + echo "'$n' - file does not exist" + return 1 + fi + done +fi diff --git a/tools/findmatch.sh b/tools/findmatch.sh new file mode 100755 index 0000000..71b7c90 --- /dev/null +++ b/tools/findmatch.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +########################################################### +# Grep/List matching strings in a specific folder + +if [ -z "$1" ]; then + $1=/ #If folder not specified, then we use root folder as a starting path +fi + +if [ -z "$2" ]; then #If string not defined, then... + # display usage if no string is given + echo "Usage: findmatch " + return 1 +else + ls $1 |grep -i "$2" +fi diff --git a/tools/findpkg.sh b/tools/findpkg.sh new file mode 100755 index 0000000..d050669 --- /dev/null +++ b/tools/findpkg.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +################################################## +# Search package in online repositories + +if [ -z "$1" ] ; then + echo "Usage: findpkg " + return 1 +else +# +# pacman: find packages which include/refer to user input string $1 by using online repositories. Verbose order +# +# Sort the output: +# 1) sed: remove first 9 lines +# 2) sed: remove everything before the first slash in every other line (package names), including the slash itself +# 3) sed: remove version number strings in every other line (all numbers after the first space after package names +# 4) sed: remove bracket mark ) from every other line +# 5) perl: colorize the output: every other line with bold blue ( \033[1:34m ) and the other after that with dim yellow ( \033[0;33m ). Starting from the first output line (sorted by sed in the first step) +# 6) sed: colorize all '[installed]' strings with bold red ( [ \033[1;31m ) +# 7) echo: normalize bash text (reset colors with \e[0m) +# NOTE: \e and \033 mean the same thing. +# NOTE: More bash colors here: http://misc.flogisoft.com/bash/tip_colors_and_formatting +# + + pacman -Ssv $1 | sed -e '1,9d' | sed -e '1~2s/^.*\///' -e '1~2s/ .*[0-9]//g' -e '1~2s/)//g' | perl -pe '$_ = "\033[1;34m$_\033[0;33m" if($. % 2)' | sed ''/\\[installed\\]/s//$(printf "\033[1;31m\\[installed\\]")/'' +fi +echo -e '\e[0m' diff --git a/tools/genmac.sh b/tools/genmac.sh new file mode 100755 index 0000000..3982d50 --- /dev/null +++ b/tools/genmac.sh @@ -0,0 +1,156 @@ +#!/bin/bash + +# Randomize MAC Address +trap ctrl_c INT + +function ctrl_c() { + echo -e "\nAborting.\n" + return +} + +random_mac() { + MAC=$(printf '%02x' $((0x$(od /dev/urandom -N1 -t x1 -An | cut -c 2-) & 0xFE | 0x02)); od /dev/urandom -N5 -t x1 -An | sed 's/ /:/g') +} + +insert_mac() { + echo -e "\nChanging MAC address information (root permission required).\n" + + sudo sed -i "/\[Link\]/!b;n;cMACAddress=$MAC" /etc/systemd/network/00-default.link + echo -e "MAC address changed from '$MAC_OLD' to '$MAC' for interface '$MAC_DEVICE'.\n\nPlease restart this interface to apply the changes.\n\nTo restore original MAC address, either delete configuration file '/etc/systemd/network/$linkname' or set real MAC address manually into it.\n" + return 0 +} + +geninsert_mac() { + + gennew_mac() { + + while true; do + unset response + read -r -p "Generate a new MAC address? [Y/n] " response + + if [[ $(echo $response | sed 's/ //g') =~ ^([yY][eE][sS]|[yY])$ ]]; then + random_mac + newname_mac + else + echo -e "\nKeeping old MAC address configuration.\n" + return + fi + done + } + + newname_mac() { + unset response + read -r -p "New MAC address for '$MAC_DEVICE' will be '$MAC'. Accept? [Y/n] " response + + if [[ $(echo $response | sed 's/ //g') =~ ^([yY][eE][sS]|[yY])$ ]]; then + insert_mac + else + gennew_mac + fi + } + newname_mac +} + +gen_mac() { + + real_mac() { + + AVAILABLE_MACS=$(ip -br link show | sed '/LOOPBACK/d' | awk '{print NR"\t"$1"\t"$3"\t"$2}') + + IFS=$'\n' + + echo -e "\nAvailable network interfaces with their MAC addresses are:\n\n${AVAILABLE_MACS[*]}" + + echo -e "\nPlease select the interface which MAC address you want to spoof of\n" + read -r -p "Selection [number]: " number + + if [[ ! $number =~ ^[0-9]+$ ]]; then + echo -e "\nInvalid input value. Aborting.\n" + return 1 + fi + + for INTERFACE in $(echo -e "${AVAILABLE_MACS[*]}"); do + + intf_num=$(echo $INTERFACE | awk '{print $1}') + + if [[ $number -eq $intf_num ]]; then + MAC_REAL=$(echo $INTERFACE | awk '{print $3}') + MAC_DEVICE=$(echo $INTERFACE | awk '{print $2}') + break + fi + done + unset IFS + + if [[ $MAC_REAL == "" ]]; then + echo -e "\nNot a valid MAC address found for interface number $number. Aborting.\n" + return 1 + fi + + } + + real_mac + + PREV_CONF=$(grep -Ril "$MAC_REAL" /etc/systemd/network/) + + if [[ ! $(echo $PREV_CONF | wc -w) -eq 0 ]]; then + echo -e "\nUsing existing configuration file for interface '$MAC_DEVICE':\n$PREV_CONF\n" + linkname=$(basename $PREV_CONF) + MAC_OLD=$(awk -F= '/\[Link\]/{getline; print $2}' $PREV_CONF) + else + MAC_OLD=$MAC_REAL + echo -e "\nPrevious configuration file not found. Creating it (root permission required).\n" + read -r -p "Configuration file name? (must follow syntax: 00-default.link, 41-default.link, 98-default.link etc.): " linkname + + if [[ $linkname =~ ^[0-9][0-9]-default.link ]]; then + + if [[ ! $(sudo -n true) ]]; then + sudo echo "" + fi + + echo -e "[Match]\nMACAddress=$MAC_REAL\n\n[Link]\nMACAddress=$MAC_REAL\nNamePolicy=kernel database onboard slot path" \ + | sudo tee /etc/systemd/network/$linkname > /dev/null + + echo -e "Created new configuration file: /etc/systemd/network/$linkname\n" + else + echo -e "\nInvalid file name given. Aborting.\n" + return 1 + fi + fi + + unset response + echo -e "Either randomly generated or manually specified MAC address can be used.\n" + read -r -p "Do you want to use randomly generated MAC address? [Y/n] " response + + if [[ $(echo $response | sed 's/ //g') =~ ^([yY][eE][sS]|[yY])$ ]]; then + random_mac + geninsert_mac + else + + if [[ $(echo $response | sed 's/ //g') =~ ^([nN][oO]|[nN])$ ]]; then + read -r -p "Please type a new MAC address (Syntax is e.g. aa:bb:33:zz:f0:4a): " MAC + maxtries=5 + while [[ $maxtries -gt 0 ]]; do + + case "$MAC" in + [[:xdigit:]][[:xdigit:]]:[[:xdigit:]][[:xdigit:]]:[[:xdigit:]][[:xdigit:]]:[[:xdigit:]][[:xdigit:]]:[[:xdigit:]][[:xdigit:]]:[[:xdigit:]][[:xdigit:]]) + insert_mac + ;; + esac + unset MAC + read -r -p "Invalid MAC address given. Please type again ($maxtries tries left): " MAC + let maxtries-- + done + else + echo -e "\nInvalid answer. Aborting.\n" + fi + fi +} + +echo -e "\nWARNING: Changing MAC address WILL DISRUPT connections to any network device using MAC-based authentication methods. These devices may include configured routers, WiFi hotspots etc. Remember to write down the new MAC address, and make sure you are authorized to configure the MAC address to all affected network devices if needed.\n" +read -r -p "You are going to spoof a MAC address of a network interface of this computer. Are you sure? [Y/n] " response + +if [[ $(echo $response | sed 's/ //g') =~ ^([yY][eE][sS]|[yY])$ ]]; then + gen_mac +else + echo -e "\nKeeping old MAC address configuration.\n" +fi diff --git a/tools/getsource.sh b/tools/getsource.sh new file mode 100755 index 0000000..3d8016c --- /dev/null +++ b/tools/getsource.sh @@ -0,0 +1,157 @@ +#!/bin/bash + +# getsource - Get build files for Arch/AUR packages on Arch Linux +# Copyright (C) 2018 Pekka Helenius +# +# This program 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 program 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 program. If not, see . + +########################################################### + +# TODO: Add support for wider range of processor architectures (below) +# TODO: Add directory support (getsource wine ~/winesource) +# TODO: create subdir for source files automatically to the current main dir + +########################################################### + +ARCH_DOMAINURL="https://git.archlinux.org" +ARCH_GITBASES=('packages.git' 'community.git') + +AUR_DOMAINURL="https://aur.archlinux.org" +AUR_GITBASES=('aur.git') + +CURDIR=$(pwd | awk '{print $NF}' FS=/) + +if [[ -n "$1" ]]; then + CURDIR="$1" +else + read -r -p "Source package name? [Default: $CURDIR] " response + if [[ -n $response ]]; then + CURDIR=$response + fi +fi + +################################## + +function check_database() { + for GITBASE in ${2}; do + + if [[ "$1" != "$AUR_DOMAINURL" ]]; then + BASEURL="$1/svntogit/$GITBASE/tree/trunk?h=packages/$CURDIR" + DOMAINURL=$ARCH_DOMAINURL + else + BASEURL="$1/cgit/$GITBASE/snapshot/$CURDIR.tar.gz" + DOMAINURL=$AUR_DOMAINURL + fi + + wget -q -T 5 "$BASEURL" -o - + if [[ $? -eq 0 ]]; then + wget -q "$BASEURL" + if [[ "$1" != "$AUR_DOMAINURL" ]]; then + mv ./trunk?h=packages%2F$CURDIR ./baseurl.html + else + tar xf "$CURDIR.tar.gz" + fi + break + fi + done + + if [[ ! -f ./baseurl.html ]]; then + return 1 + fi +} + +################################## + +function arch_repos_deepscan() { + + ARCH_DATABASES=(core extra community community-testing) + + for ARCH_DB in ${ARCH_DATABASES[*]}; do + + ARCH_DB_URL="https://www.archlinux.org/packages/$ARCH_DB/x86_64/$CURDIR" + + wget -q -T 5 "$ARCH_DB_URL" -o - + if [[ $? -eq 0 ]]; then + wget -q "$ARCH_DB_URL" + mv ./$CURDIR ./baseurl_2.html + break + fi + + done + + if [[ -f baseurl_2.html ]]; then + echo -e "Selecting another package name:\n" + CURDIR=$(grep "Source Files" baseurl_2.html | sed "s/.*href=[\"'].*packages\///g; s/[\"'].*//g") + echo -e "Package name is $CURDIR" + rm baseurl_2.html + check_database "$ARCH_DOMAINURL" "${ARCH_GITBASES[*]}" + arch_dl_files + else + echo -e "\nCouldn't find package $CURDIR\n" + exit 1 + fi + +} + +################################## + +function arch_dl_files() { + if [[ -f baseurl.html ]]; then + FILELIST=$(cat baseurl.html | grep -E "ls-mode" | sed "s/.*href=[\"']//g; s/[\"']>plain.*//g") + + for file in $FILELIST; do + if [[ ! -f $file ]]; then + # Wget only if file doesn't exist + wget -q $DOMAINURL/$file + mv $(echo "$file" | sed 's/.*trunk//g; s/\///1' | sed 's/\//%2F/g') $(echo $file | sed 's/.*trunk//g; s/?.*//g; s/\///g') + fi + done + rm baseurl.html + echo -e "\nSource files for $CURDIR downloaded\n" + + elif [[ -f "$CURDIR.tar.gz" ]]; then + mv ./$CURDIR/* ./ + rm -Rf {"$CURDIR.tar.gz",$CURDIR} + echo -e "\nSource files for $CURDIR downloaded\n" + else + arch_repos_deepscan + fi +} + +################################## + +check_database "$ARCH_DOMAINURL" "${ARCH_GITBASES[*]}" + +if [[ ! $? -eq 0 ]]; then + check_database "$AUR_DOMAINURL" "${AUR_GITBASES[*]}" +fi + +arch_dl_files + +################################## + +# Check if we are raspberry pi (ARM 7) or not +if [[ $(cat /proc/cpuinfo | grep -i armv7 -m1 | wc -l) -eq 1 ]]; then + if [[ -f PKGBUILD ]]; then + cat PKGBUILD | grep arch= | grep -E "any|armv7h" > /dev/null + if [[ $? -ne 0 ]]; then + sed -i "s/arch=.*/arch=('any')/" PKGBUILD + echo -e "Modified architecture in PKGBUILD to 'any'\n" + fi + fi +fi + +################################## + +rm -Rf ./{,*trunk*} 2>/dev/null diff --git a/tools/installlocal.sh b/tools/installlocal.sh new file mode 100755 index 0000000..21a7eec --- /dev/null +++ b/tools/installlocal.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +############################################## +# Install locally build program on Arch Linux + +if [ -e ./PKGBUILD ]; then #We check whether PKGBUILD file exists. If yes, then... + PACKAGE_NAME=$(cat ./PKGBUILD | grep "pkgname=" | sed -e 's/pkgname=//g') #get package name from PKGBUILD + PACKAGE=$(echo $PACKAGE_NAME*.pkg.tar.xz) #package name + * + suffix + + if [ -e $PACKAGE ]; then # If package has been compiled, then... + sudo pacman -U $PACKAGE # ...install the package. + fi +else + return 1 +fi diff --git a/tools/killprocess.sh b/tools/killprocess.sh new file mode 100755 index 0000000..9f52df5 --- /dev/null +++ b/tools/killprocess.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +# NOT MADE BY ME! + +########################################################### +# Kill a process by name +ps aux | grep $1 > /dev/null +mypid=$(pidof $1) +if [ "$mypid" != "" ]; then + kill -9 $(pidof $1) + if [[ "$?" == "0" ]]; then + echo "PID $mypid ($1) killed." + fi +else + echo "None killed." +fi diff --git a/tools/listpkg.sh b/tools/listpkg.sh new file mode 100755 index 0000000..5142866 --- /dev/null +++ b/tools/listpkg.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +########################################################### +# Show packages named as on Arch Linux +pacman -Q | grep "$1" | cut -d' ' -f1 diff --git a/tools/missinglibs.sh b/tools/missinglibs.sh new file mode 100755 index 0000000..d90bbd7 --- /dev/null +++ b/tools/missinglibs.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +########################################################### +# Missing package libraries + +ldd $(mimetype $(pacman -Ql "${1}") | grep -iE "x\-sharedlib|x\-executable" | sed 's/\:.*//g') | grep -i "not found" diff --git a/tools/nowner.sh b/tools/nowner.sh new file mode 100755 index 0000000..75d1236 --- /dev/null +++ b/tools/nowner.sh @@ -0,0 +1,328 @@ +#!/bin/bash + +# nowner - Find orphan files on various Linux distributions +# Copyright (C) 2018 Pekka Helenius +# +# This program 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 program 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 program. If not, see . + +########################################################### + +bash_yellow=$'\033[93m' +bash_red=$'\033[91m' +bash_color_default=$'\033[0m' + +########################################################### + +#Useful for additional commands: + +# TODO: Look for .old .bak ~ .pacnew and such files (maybe separate command or not??) + +#find /usr/share -maxdepth 1 -type d -exec stat --format "%n: %U" {} \; | grep fincer + +########################################################### +# Check for command dependencies + +if [[ $(which --help 2>/dev/null) ]] && [[ $(echo --help 2>/dev/null) ]]; then + + COMMANDS=(who awk getent printenv sed file stat id date find tee chown timedatectl hostname) + + a=0 + for command in ${COMMANDS[@]}; do + if [[ ! $(which $command 2>/dev/null) ]]; then + COMMANDS_NOTFOUND[$a]=$command + let a++ + fi + done + + if [[ -n $COMMANDS_NOTFOUND ]]; then + echo -e "\n${bash_red}Error:${bash_color_default} The following commands could not be found: ${COMMANDS_NOTFOUND[*]}\nAborting\ņ" + exit 1 + fi +else + exit 1 +fi + +########################################################### +# Retrieve our Linux distribution and set the correct +# package manager for this command + +# Get our Linux distribution +DISTRO=$(cat /etc/os-release | sed -n '/PRETTY_NAME/p' | grep -o '".*"' | sed -e 's/"//g' -e s/'([^)]*)'/''/g -e 's/ .*//' -e 's/[ \t]*$//') + +function check_pkgmgr() { + + if [[ ! $(which $1 2>/dev/null) ]]; then + echo -e "\n${bash_red}Error:${bash_color_default} Package manager ($1) could not be found\nAborting\ņ" + exit 1 + fi +} + +############################## + +# Arch Linux +if [[ $DISTRO == "Arch" ]]; then + check_pkgmgr pacman + function PKGMGR_CMD() { pacman -Qo "$1" &>/dev/null || echo "error" | wc -l ; } +fi + +# Debian, Ubuntu +if [[ $DISTRO == "Ubuntu" ]] || [[ $DISTRO == "Debian" ]]; then + check_pkgmgr dpkg + function PKGMGR_CMD() { dpkg -S "$1" &>/dev/null || echo "no path found matching pattern" | wc -l ; } +fi + +# CentOS +# TODO + +# Fedora +# TODO + +# RedHat +# TODO + +# OpenSUSE +# TODO + +########################################################### +# List files and directories which are not owned by any package in the system +echo -e "\nSearch for files & folders which are not owned by any installed package.\n" + +# Avoid storing log files into root home +REAL_USER=$(who am i | awk '{print $1}') +REAL_USER_HOME=$(getent passwd $REAL_USER | cut -d: -f6) + +if [[ $# -eq 0 ]]; then + read -r -p "Folder path: " BASEDIR + #Substitute $ symbol from environmental variables for printenv input + if [[ $BASEDIR == *"$"* ]]; then + BASEDIR=$(echo $(printenv $(echo ${BASEDIR} | sed 's/\$//g'))) + fi +else + BASEDIR=$1 +fi + +if [[ ! $(file --mime-type "${BASEDIR}" | grep "inode/directory" | wc -l) -eq 1 ]]; then + echo "${bash_red}Error:${bash_color_default} Use full folder path as an input value!" +elif [[ $# -gt 1 ]]; then + echo "${bash_red}Error:${bash_color_default} Only one argument accepted!" +else + + echo -e "Search depth:\n1 = "${BASEDIR}"\n2 = "${BASEDIR}" & subfolders\n3 = "${BASEDIR}", subfolders & 2 folder levels below\n4 = no limit\n" + read -r -p "Which depth value you prefer? [Default: 1] " response + + case $response in + 1) + depth="-maxdepth 1 " + depthstr="${BASEDIR}" + DEPTH_NUM=1 + ;; + 2) + depth="-maxdepth 2 " + depthstr="${BASEDIR} and subfolders" + DEPTH_NUM=2 + ;; + 3) + depth="-maxdepth 3 " + depthstr="${BASEDIR}, subfolders and 2 folder levels below" + DEPTH_NUM=3 + ;; + 4) + depth="" + depthstr="${BASEDIR} and all subfolders" + DEPTH_NUM=4 + ;; + *) + echo -e "\nUsing default value [1]" + depth="-maxdepth 1 " + depthstr="${BASEDIR}" + DEPTH_NUM=1 + esac + + unset response + +############################## + + BASEDIR_OWNER=$(stat --format "%u" "${BASEDIR}") + + if [[ $BASEDIR_OWNER -eq 0 ]] && [[ $(id -u) -ne 0 ]]; then + echo -e "\n${bash_yellow}Warning:${bash_color_default} the main folder '${BASEDIR}' is owned by root. Some files or directories may be inaccessible. Please consider running this command with root privileges.\n" + + read -r -p "Continue? [Y/n] " response + if [[ $(echo $response | sed 's/ //g') =~ ^([nN][oO]|[nN])$ ]]; then + echo -e "\nAborting\n" + exit 0 + fi + + elif [[ $BASEDIR_OWNER -ne $(id -u $REAL_USER) ]] && [[ $BASEDIR_OWNER -ne 0 ]]; then + echo -e "\n${bash_yellow}Warning:${bash_color_default} the main folder belongs to local user '$(id -un $BASEDIR_OWNER)'. Some files or directories may be inaccessible\n" + fi + +############################## + + BASEDIR_UNDERLINE="$(echo ${BASEDIR} | sed 's/\//_/g')" + LOGFILE="$REAL_USER_HOME/nowner-${BASEDIR_UNDERLINE}-depth-${DEPTH_NUM}_$(date +%Y-%m-%d).log" + + # Delete log file if the command is interrupted + # Define function del_log here, after we have defined $LOGFILE + # + # Interrupt signal must be trapped after $LOGFILE and before any further commands + # That's why it is located here and not at the end or at the start of this script + # + del_log() { rm $LOGFILE ; exit 0 ; } + trap 'del_log' INT + + read -r -p "Save results to a file? [Y/n] " response + if [[ $(echo $response | sed 's/ //g') =~ ^([yY][eE][sS]|[yY])$ ]]; then + echo -e "Scan results will be saved in '$LOGFILE'" + TO_FILE=1 + else + TO_FILE=0 + fi + +############################## + + echo -e "\nSearching unowned files & folders in $depthstr\n" + +############################## + + function data_counter() { + i=0 + n=1 + ARRAY=("$@") + COUNT=${#ARRAY[@]} + + for scan_data in "${ARRAY[@]}"; do + + echo -ne "Scanning $data_name $n ($(( 100*$n/$COUNT ))%) of all $type ($COUNT) in $depthstr\r" + + if [[ $(PKGMGR_CMD $scan_data) -eq 1 ]]; then + DATA_ARRAY[$i]="$(( $i + 1 )) - ${scan_data}" + let i++ + fi + let n++ + + done + +############### + + function results() { + + if [[ $i -gt 0 ]]; then + echo -e "\nThe following $i of $COUNT $type is not owned by any installed package in $depthstr:\n" + IFS=$'\n' + echo -e "${DATA_ARRAY[*]}\n" + unset IFS + unset DATA_ARRAY + elif [[ "$COUNT" -eq 0 ]]; then + echo -e "\nCouldn't find any $type in the target path $depthstr. Consider using greater depth value.\n" + else + echo -e "\nAll $type are owned by system packages in $depthstr" + fi + } + + if [[ $TO_FILE -eq 1 ]]; then + results | tee -a $LOGFILE + echo "" + else + results + echo "" + fi + + } + +############################## + + function data_check() { + + DATASET=$(find "${BASEDIR}" ${depth} ${1} 2>/dev/null) + + IFS=$'\n' + datacnt=0 + for DATA in ${DATASET}; do + + # Do read permission check for files/folders unless we are root + # + if [[ $(id -u) -ne 0 ]]; then + + echo -e "Checking for $2 permissions. Please wait\n" + + DATA_OWNER=$(stat --format "%u" "${DATA}") + DATA_OWNER_HUMAN=$(stat --format "%U" "${DATA}") + + # If the current user (which this command is executed by) is not the owner of folder/file + # By performing this check we can distinguish whether the user + # belongs to the owner class or "others" class + # and therefore we can perform check for "read" bit + # for "others" if needed + # + if [[ $(id -u) -ne $DATA_OWNER ]]; then + + # If read bit is defined for "others" + if [[ $(stat --format "%A" "${DATA}" | cut -c 8) == "r" ]]; then + VALID_DATASET[$datacnt]="${DATA}" + let datacnt++ + else + echo -e "${bash_yellow}Warning:${bash_color_default} $data_name '${DATA}' (owned by $DATA_OWNER_HUMAN) is not readable. Skipping it\n" + fi + + # We assume that the file/dir owner has read permission for this specific file/folder + # + else #elif [[ $(id -u $REAL_USER) -eq $DATA_OWNER ]]; then + VALID_DATASET[$datacnt]="${DATA}" + let datacnt++ + fi + else + VALID_DATASET[$datacnt]="${DATA}" + let datacnt++ + fi + done + unset IFS + unset datacnt + data_counter "${VALID_DATASET[@]}" + unset VALID_DATASET + } + +############################## + + function folders() { + type="folders" + data_name="folder" + find_type="-mindepth 1 -type d" + data_check "${find_type}" $data_name + } + + function files() { + type="files" + data_name="file" + find_type="-type f" + data_check "${find_type}" $data_name + } + +############################## + + if [[ $TO_FILE -eq 1 ]]; then + echo -e "Log timestamp: $(date '+%d-%m-%Y, %X') (TZ: $(timedatectl status | grep "Time zone:" | awk '{print $3}'))\nComputer: $(hostname)\nScanning Depth: $depthstr" >> $LOGFILE + fi + + folders + files + + if [[ $TO_FILE -eq 1 ]]; then + chown $REAL_USER $LOGFILE + echo -e "Scan complete. Results have been saved in '$LOGFILE'\n" + else + echo -e "Scan complete\n" + fi + +fi diff --git a/tools/pkgdeps.sh b/tools/pkgdeps.sh new file mode 100755 index 0000000..c9fc9c6 --- /dev/null +++ b/tools/pkgdeps.sh @@ -0,0 +1,463 @@ +#!/bin/bash + +# Shared library & executable dependency finder for Linux +# Copyright (C) 2018 Pekka Helenius +# +# This program 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 program 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 program. If not, see . + +###################################################################################################################### + +# TODO print stored dependency packages as red if errors encountered +# TODO check packages themselves, too (not only their dependencies...) +# TODO + +# BUG : +# +# Optional dependencies for linux : +# +# crda: to set the correct wireless channels of your country +# +# Required dependencies for linux : +# +# coreutils Found libraries/executables: 102 +# grep: Unmatched [ or [^ +# grep: Invalid regular expression + +# TODO +# Depends on: libtinfo.so.6 Provided by: +# ei anna oikeaa tulosta... + +# TODO +#Error: octopi not found. Skipping. +# Lisää tähän "do you mean...?...logiikka + +# ------------------------------------------- +# BUG +# Ignore rules.d folder since it gives permission denied error + +# ------------------------------------------- +# BUG + +#1/1 (100%) - ncurses + +#Required dependencies for ncurses : + +# glibc Found libraries/executables: 302 +#ldd: warning: you do not have execution permission for `/usr/lib/libcursesw.so' +#error: failed to find 'dynamic' in PATH: No such file or directory +#ldd: warning: you do not have execution permission for `/usr/lib/libform.so' +#error: failed to find 'dynamic' in PATH: No such file or directory +#ldd: warning: you do not have execution permission for `/usr/lib/libmenu.so' +#error: failed to find 'dynamic' in PATH: No such file or directory +#ldd: warning: you do not have execution permission for `/usr/lib/libncurses++.so' +#error: failed to find 'dynamic' in PATH: No such file or directory +# gcc-libs-multilib Found libraries/executables: 17 + +# ------------------------------------------- +# BUG + +# When using command 'pkgdeps wine-git', the following error occurs: + +#... +# lib32-libsm Found libraries/executables: 1 +#error: failed to find 'dynamic' in PATH: No such file or directory +#error: failed to find 'dynamic' in PATH: No such file or directory + +###################################################################################################################### +# Look for missing library files for installed packages + +red=$'\33[91m' +orange=$'\033[38;5;208m' +yellow=$'\033[93m' +green=$'\033[92m' +blue=$'\033[94m' +bold=$'\033[1m' +reset=$'\033[0m' + +COMMANDS=(sudo pacman date ping package-query) +for com in $COMMANDS; do + if [[ ! $(which $com |grep "which: no $com in" | wc -w) -eq 0 ]]; then + echo -e "\nCommand $com not found. Can't run the script.\n" + return + fi +done + +echo -e "\n${bold}Dependency tracker - Find broken executables & libraries${reset}" + +if [[ $# -eq 1 ]]; then + pacman -Q $1 2> /dev/null #|| echo 'something' # TODO silent normal output! + if [[ $? -eq 1 ]]; then + seterror=1 + else + seterror=0 + fi +else + seterror=0 +fi + +function checkconnection() { + PROVIDER="luna.archlinux.org" + INTERNET_TEST=$(ping -c 1 $PROVIDER 2>&1 | grep -c "Name or service not known") + + if [[ ! $INTERNET_TEST -eq 0 ]]; then + echo -e "\n${red}Error:${reset} Can't connect to $PROVIDER. Please check your internet connection.\n" + else + echo -e "\nUpdating file databases with pacman (root required)\n" + sudo pacman -Fy + fi +} + +LOGFILE=/var/log/pacman.log + +if [[ -f $LOGFILE ]] && [[ $seterror -ne 1 ]]; then + LASTRUN=$(date --date="$(awk '/pacman -Fy/ {a=$0} END{print a}' $LOGFILE | awk -F'[][]' '{print $2}')" +"%s") + + if [[ $? -ne 0 ]]; then + echo -e " ${red}Error:${reset} Can't parse the latest 'pacman -Fy' date value from pacman log file $LOGFILE! Skipping database update.\n" + else + + if [[ $(echo $LASTRUN | wc -w) -eq 1 ]]; then + + CURTIME=$(date +"%s") + LASTUPDATE=$(( ($CURTIME - $LASTRUN)/60 )) + TIME_THRESHOLD=180 # 3 hours + + if [[ $LASTUPDATE -ge $TIME_THRESHOLD ]]; then + echo -e "\nPackage databases updated $LASTUPDATE minutes ago.\n" # TODO minutes....hours...days...ago... + + read -r -p "Do you want to update databases now? [y/N] " dbupdate + if [[ $(echo $dbupdate | sed 's/ //g') =~ ^([yY][eE][sS]|[yY])$ ]]; then + checkconnection + else + echo -e "\nSkipping database update.\n" + fi + else + echo -e "\nPackage databases are updated.\n" + fi + else + echo -e "\nPrevious database update timestamp not found. Updating...\n" + checkconnection + fi + fi +elif [[ ! -f $LOGFILE ]]; then + echo -e "\n ${red}Error:${reset} Pacman log file not found.\n" +fi + +pkgcount=$# +curpkgcount=1 +typeset -A CHECKEDLIST +# Loop through all input arguments (package names) +for p in $(echo "${@}"); do # TODO show how many dependencies this package has if more than 1 + + LOCALDIRS=("/usr/lib" "/usr/bin" "/usr/lib/" "/opt/") + + w=0 + for dir in $(pacman -Ql $p 2> /dev/null | awk '{print $2}'); do + if [[ -d $dir ]]; then + MAINPKGDIRS[$w]="${dir}" + let w++ + fi + done + + echo -e "----------------------------------------" + echo -e "\n$curpkgcount/$pkgcount ($((100*$curpkgcount/$pkgcount))%) - ${orange}$p${reset}" + + # Check that the input package can actually be found + if [[ $(pacman -Qi $p &>/dev/null || echo "was not found" | wc -l) -eq 1 ]]; then + echo -e "\n ${red}Error:${reset} ${orange}$p${reset} not found. Skipping.\n" + else + + # Parse dependencies of the selected package to a string list + PKGDEPS=$(pacman -Qi $p | grep "Depends On" | sed 's/.*: //g; s/ / /g') + + #Parse optional dependencies + PKGDEPS_OPT=$(pacman -Qi $p | grep "Optional Deps" | sed 's/.*\s: //; s/ / /') + + # Loop for each package ([@] means array value X) + # We circumvent a pacman bug/issue here + # pacman does a hard fixed listing for packages, meaning it doesn't recognize "provides" option + # This is mainly a problem of git package versions + # + if [[ $PKGDEPS_OPT != "None" ]]; then + echo -e "\nOptional dependencies for ${orange}$p${reset} :\n\n $PKGDEPS_OPT" + fi + + if [[ $PKGDEPS != "None" ]]; then + echo -e "\nRequired dependencies for ${orange}$p${reset} :\n" # TODO go even one step deeper with these! + for i in $(echo "${PKGDEPS[@]}"); do + + function parseversion() { + pattern="[<=>]" + if [[ $i =~ $pattern ]]; then + i=$(echo $i | awk -F'[<=>]' '{print $1}') + # TODO do version check here as done in 'risks' function? + #i_ver=$(echo $i | awk -F'[<=>]' '{print $3}') + #return $pkgname $pkgver + #else + #return $i + fi + } + + parseversion + # Error (package was not found) + if [[ $(pacman -Qi $i &>/dev/null || echo "was not found" | wc -l) -eq 1 ]]; then + + # Get name of the package which provides the dependency + ALTDEP=$(pacman -Qi | grep -iE "Name|Provides" | grep $i | grep "Name" | sed 's/.*: //') + + o=0 + for altdep in $ALTDEP; do + ALTDEPS[$o]=$altdep + let o++ + done + + function deepscan() { + MAINPKGFILES=$(pacman -Ql $p | awk '{print $2}') + for mainpkgfile in $MAINPKGFILES; do + if [[ $(mimetype "${mainpkgfile}" | grep -iE "x\-sharedlib|x\-executable" | wc -l) -eq 1 ]]; then + for deepscan in $(ldd "${mainpkgfile}" | awk '{print $3}' | sed '/^\s*$/d'); do + OWNER_DEEPSCAN=$(pacman -Qo $deepscan | awk '{print $5}') + for item in "${ALTDEPS[@]}"; do + if [[ $OWNER_DEEPSCAN == "$item" ]]; then + i=$OWNER_DEEPSCAN + return 0 + fi + done + done + fi + done + return 1 + } + deepscan + if [[ $? -eq 1 ]]; then + #Get 'provides' from arch package database + FETCHEDPKGS=$(package-query --qprovides "$i" -Q -f "%n") + k=0 + for fetch in $FETCHEDPKGS; do + if [[ ! $(pacman -Q $fetch &>/dev/null || echo "was not found" | wc -l) -eq 1 ]]; then + i="$fetch" + break + # TODO show here the true 'depends on' stuff, not just 'provided by' package? bash <-> sh conversion for example + else + echo -e " ${yellow}Warning:${reset} Dependency '$i' not found and not recognized as a provided package" + i="notfound" + NOTFOUNDS[$k]=$i + let k++ + fi + done + fi + fi + + if [[ $i != "notfound" ]] && [[ -z ${CHECKEDLIST[$i]} ]]; then + + FILES=$(pacman -Ql $i | awk '{print $2}') + x=0 + printf " %-30s%s\r" "$i" "Searching libraries/executables" + for mimefile in $FILES; do + if [[ $(mimetype "${mimefile}" | grep -iE "x\-sharedlib|x\-executable" | wc -l) -eq 1 ]]; then + MIMEFILES[$x]="${mimefile}" + let x++ + printf " %-30s%s\r" "$i" "Found libraries/executables: $x " #Yes, the trailing space is meant to be here + fi + done + + if [[ $x -gt 0 ]]; then + CHECKEDLIST[$i]=$(printf " %-30s%s\n" "$i" "Found libraries/executables: $x") + else + CHECKEDLIST[$i]=$(printf " %-30s%s\n" "$i" "No libraries/executables") + fi + + # Replace the current line (100 characters) with empty space and fill it with checkedlist value + echo -e "\r$(for ((i = 0; i < 100; i++)); do echo -n ' '; done)\r${CHECKEDLIST[$i]}" + + # Go through all listed library & executable files + for n in $(echo "${MIMEFILES[@]}"); do + + # Get count of all matching lines for a file. If no errors, this should return 1 + # Enable bash debugging with set -x and run it in subshell (otherwise we need to use set +x to disable debugging) + # As debugging output is considered as STDERR (not default STDOUT), we pipe it with |& + # Suppress ldd warning messages ("you have no permission") as they are not relevant here and delete empty lines + + LDDCMDCNT=$( (set -x; ldd $n |grep -i "not found") |& grep -E "$n|=> not found" | sed 's/.*warning.*//g; /^\s*$/d' | wc -l) + + # Get all lines for a file. If no errors, this should return only "++ ldd " + LDDCMD=$( (set -x; ldd $n |grep -i "not found") |& grep -E "$n" | sed 's/.*warning.*//g; /^\s*$/d') + LDDCMD_FILE=$(echo "$LDDCMD " | sed 's/++ ldd //g') + + # Basename doesn't accept empty/null parameters + if [[ ! -z "${LDDCMD_FILE// }" ]]; then + LDDCMD_FILE_BASENAME=$(basename $LDDCMD_FILE) # | sed "s/[-0-9.]*$//" + fi + + # If we have match for "not found" messages, print the output + if [[ $LDDCMDCNT -gt 1 ]]; then + LIBNOTFOUND=true + function checklocaldirs() { + unset PKG + for filepkgdir in $1; do + #echo "Search dir is $filepkgdir Search term is $2" + findfile=$(find "$filepkgdir" -maxdepth 1 -type f -iname "*$2*") + + if [[ -f $findfile ]]; then + PKG="$(pacman -Qo $findfile | awk '{print $5 " " $6}')" + return + fi + done + } + + function checkrepopkgs() { + unset PKG + unset NIPKG + REPOPKGS=$(pacman -Fs $1 | sed '2~2d' | awk -F '[/ ]' '{print $2}') + if [[ ! -z $REPOPKGS ]]; then + c=0 + for repopkg in $REPOPKGS; do + t=0 + for repopkgfile in $(pacman -Fl "$repopkg" | awk '{print "/"$2}'); do + if [[ -f $repopkgfile ]]; then + REPOPKGFILES[$t]="$repopkgfile" + let t++ + fi + done + + if [ ! "${#REPOPKGFILES[@]}" -eq 0 ]; then + for matchrepofile in "${REPOPKGFILES[@]}"; do + if [[ "${matchrepofile}" == "${2}" ]]; then + PKG=$repopkg + return + # else + # if [[ $(pacman -Qo $matchrepofile | grep -o "owned by" | wc -w) -eq 2 ]] + # PKG=$(echo "${REPOPKGS[*]}?" | tr '\n' ',' | sed 's/\,*$//g') + # #return + fi + done + unset REPOPKGFILES + else + #echo "do we get here $repopkg" + if [[ $(pacman -Q $repopkg &>/dev/null || echo "was not found" | wc -l) -eq 1 ]]; then + NIPKG[$c]="$repopkg" + let c++ + fi + #PKG="${red}N/A${reset}" + fi + done + #PKG="${red}N/A${reset}" + else + PKG="${red}N/A${reset}" + fi + } + + checkrepopkgs $LDDCMD_FILE_BASENAME $LDDCMD_FILE + # MAINPKG=$PKG + #REPOPKG=$(pacman -Fs $(echo $n | awk '{print $NF}' FS=/) | sed '1!d' | awk -F '[/ ]' '{print $2}') + + #if [[ -z ${PKG} ]]; then + # PKG="${red}N/A${reset}" + # fi + + NOTFOUNDFILES=$( (set -x; ldd $n |grep -i "not found") |& grep -E "=> not found" | sed 's/ => not found//g; s/\s//g' | tr '\n' ' ' | sed 's/.*warning.*//g; /^\s*$/d') + + printf "\n %s %s\n" "${red}=>${reset} Missing or broken dependencies for" "${yellow}$LDDCMD_FILE${reset}" + printf " %-38s%s\n" " Owned by system package:" "$(pacman -Qo $n | sed 's/.* by //g')" + # if [[ ! $MAINPKG == *"N/A"* ]] || [[ ! -z "${NIPKG}" ]]; then + # printf " %-38s%s\n" " Provided by..." + # if [[ ! $MAINPKG == *"N/A"* ]]; then + # printf " %-38s%s\n" " ...installed repo package(s):" "$MAINPKG" + # fi + if [[ ! -z "${NIPKG}" ]]; then + printf " %-38s%s\n" " Provided by package(s):" "${NIPKG[*]}" + # printf " %-38s%s\n" " ...non-installed repo package(s):" "${NIPKG[*]}" + fi + # fi + printf "\n" + + # Set up a new array for r variables (libary files) and store printf output there. + # This is just so that we don't need to check these library files again but instead + # we can use a stored value. This is just to speed up processing. + # TODO does this really work? + r_count=0 + typeset -A RLIST + for r in $(echo ${NOTFOUNDFILES[@]}); do + + if [[ ! ${RLIST[$r_count]} ]]; then + checklocaldirs "${MAINPKGDIRS[*]}" $r #$r_basename + if [[ -z ${PKG} ]]; then + checklocaldirs "${LOCALDIRS[*]}" $r #$r_basename + fi + LIBPKG=$PKG + RLIST[$r_count]=$(printf " %-47s%-30s%s\n" " ${red}Depends on${reset}:" "$r" "${blue}Provided by${reset}: $LIBPKG") + fi + + echo "${RLIST[$r_count]}" + + #unset MAINPKG + #unset PKG + #r_basename=$(echo $r | sed "s/[-0-9.]*$//") # libicui18n.so.58.4 -> libicui18n.so + #unset PKG + #if [[ -z ${PKG} ]]; then + # checkrepopkgs $r_basename + #if [[ -z ${PKG} ]]; then + # PKG="${red}N/A${reset}" + #fi + # fi + + #check_main $r_basename + #checkrepopkgs $r_basename $r + + # if [[ -z ${PKG} ]]; then + # PKG="N/A" + # fi + # for r_providers in $(pacman -Fs $r_basename | sed '2~2d' | awk -F '[/ ]' '{print $2}'); do + # TODO + + #LIBPKG[0]=$(pacman -Fs $(echo $r | awk '{print $NF}' FS=/) | sed '1!d' | awk -F '[/ ]' '{print $2}') + #LIBPKG=$(pacman -Fs $(echo $r | awk '{print $NF}' FS=/) | sed '1!d' | awk -F '[/ ]' '{print $2}') + #LIBPKG=$(pacman -Fs $r | sed '1!d' | awk -F '[/ ]' '{print $2}') + #if [[ "${#LIBPKG[@]}" -eq 0 ]]; then + + #if [[ $(echo $LIBPKG | wc -w) -eq 0 ]]; then + # LIBPKG="N/A" + #fi + + #printf " %-47s%-30s%s\n" " ${red}Depends on${reset}:" "$r" "${blue}Provided by${reset}: $LIBPKG" + + #unset LIBPKG + #unset PKG + #unset MAINPKG + let r_count++ + done + unset RLIST + + fi + done + unset MIMEFILES #Unset MIMEFILES array for the next dependency check + else + printf '%s\n' "${CHECKEDLIST[$i]}" + fi + done + else + echo -e "\n No dependencies for this package." + fi + + if [[ ! -z "${NOTFOUNDS}" ]] || [[ $LIBNOTFOUND != true ]]; then + echo -e "\n ${green}=>${reset} Dependencies checked. All ${green}OK${reset}.\n" + else + echo -e "\n ${red}=>${reset} Dependency problems discovered. See above messages for details.\n" + fi + unset NOTFOUNDS + unset LIBNOTFOUND + + fi +let curpkgcount++ +done diff --git a/tools/pkginfo.sh b/tools/pkginfo.sh new file mode 100755 index 0000000..00856cc --- /dev/null +++ b/tools/pkginfo.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +################################# +# Gather some package information with pacman on Arch Linux + +FILETHRESHOLD=100 + +if [[ $2 == "local" ]]; then + pacman -Qi $1 + if [[ $3 == "files" ]]; then + if [[ $(pacman -Ql $1 | wc -l) -gt $FILETHRESHOLD ]]; then + echo "Package $1 has $(pacman -Ql $1 | wc -l) files/dirs" + sleep 3 + pacman -Ql $1 | less + fi + fi +elif [[ $2 == "remote" ]]; then + pacman -Si $1 + if [[ $3 == "files" ]]; then + if [[ $(pacman -Ql $1 | wc -l) -gt $FILETHRESHOLD ]]; then + echo "Package $1 has $(pacman -Ql $1 | wc -l) files/dirs" + sleep 3 + pacman -Ql $1 | less + fi + fi +else + echo -e "Input: sh pkginfo.sh [local/remote] [files]\n" +fi diff --git a/tools/pkgstr.sh b/tools/pkgstr.sh new file mode 100755 index 0000000..5154a9b --- /dev/null +++ b/tools/pkgstr.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +########################################################### +# Search a text pattern inside package files +read -r -p "Enter search pattern: " TEXT + +if [[ -z $TEXT ]]; then + echo -e "\nInvalid input\n" + exit +else + + for p in $(echo "${@}"); do + + echo -e " \033[1m\033[92m=>\033[39m\033[0m Files of package '$p' containing pattern '$TEXT':\n" + + for i in $(pacman -Ql $p | awk -F ' ' '{print $NF}' | sed '/\/*.*\/$/d'); do + sudo grep -Ril "$TEXT" $i + done + done +fi diff --git a/tools/rmpkgfiles.sh b/tools/rmpkgfiles.sh new file mode 100755 index 0000000..072c9bc --- /dev/null +++ b/tools/rmpkgfiles.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +################################ +# Remove build-time files after program compilation on Arch Linux +# +if [ ! -e ./PKGBUILD ] && [ ! -d ./{src,pkg} ]; then #We check whether PKGBUILD file and src,pkg directories exist. If no, then... + echo -e "Nothing to be removed\n" + exit +else + rm -Rf ./{src,pkg,packages,community,*tar.xz} #tar.xz file may or may not exist +fi diff --git a/tools/showpkg.sh b/tools/showpkg.sh new file mode 100755 index 0000000..cb09254 --- /dev/null +++ b/tools/showpkg.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +########################################################### +# Show specific package, installed and available version +echo "" +PKGMGR="pacman" + +for p in $(echo "${@}"); do + + INSTALLDATE=$($PKGMGR -Qi $p | grep "Install Date" | awk -F ': ' '{print $2}') + NEWDATE=$($PKGMGR -Si $p | grep "Build Date" | awk -F ': ' '{print $2}') + echo "Installed: $($PKGMGR -Q $p) ($INSTALLDATE)" + echo $($PKGMGR -Si $p | grep -E "Version.*:|Build Date.*:" | awk -F ': ' '{print $2}') | awk -v pkg=$p -F ' ' '{print "Available: " pkg " " $1 " ("substr($0,length($1)+1)")"}' | sed 's/( /(/g' + echo "" + #echo -e "Available: $p $($PKGMGR -Si $p | grep "Version.*:" | awk -F ' ' '{print $3}')\n" +done diff --git a/tools/specialchars.sh b/tools/specialchars.sh new file mode 100644 index 0000000..f433582 --- /dev/null +++ b/tools/specialchars.sh @@ -0,0 +1,14 @@ +#!/bin/bash +special=$'`!@#$%^&*()-_+={}|[]\\;\':",.<>?/ ' +for ((i=0; i < ${#special}; i++)); do + char="${special:i:1}" + printf -v q_char '%q' "$char" + if [[ "$char" != "$q_char" ]]; then + printf 'Yes - character %s needs to be escaped\n' "$char" + else + printf 'No - character %s does not need to be escaped\n' "$char" + fi +done | sort + +# Author: codeforester +# https://stackoverflow.com/questions/15783701/which-characters-need-to-be-escaped-in-bash-how-do-we-know-it/44581064#44581064 diff --git a/tools/ssh_timezone.sh b/tools/ssh_timezone.sh new file mode 100644 index 0000000..578d301 --- /dev/null +++ b/tools/ssh_timezone.sh @@ -0,0 +1,76 @@ +#!/bin/bash + +# SSH timezone - Retrieve timezone information for SSH users +# Copyright (C) 2018 Pekka Helenius +# +# This program 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 program 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 program. If not, see . + +############################################################################## + +# This script is meant to be used as a part of provided 'bash.custom' file + +############################################################################## + +REQ_PKGS=(geoip2-database mmdblookup systemd openssh bind-tools) + +for pkg in ${REQ_PKGS[*]}; do + if [[ ! $(pacman -Q | grep $pkg) ]]; then + echo -e "\nMissing package $pkg\n" + kill -INT $$ + fi +done + +GEOIP2_DATABASE="/usr/share/GeoIP/GeoLite2-City.mmdb" + +if [[ ! -f $GEOIP2_DATABASE ]]; then + + # GeoIP2 database file couldn't be found + kill -INT $$ + +fi + +# If SSH_CONNECTION variable is defined +if [[ $(export -p | grep -o SSH_CONNECTION) ]]; then + + # Get IP address of the user + RUSER_IP=$(echo $SSH_CONNECTION | awk '{print $1}') + + # If SSH IP is local, try to get public IP. + if [[ $RUSER_IP =~ ^192\.168\. ]] || [[ $RUSER_IP =~ ^10\. ]] || [[ $USER_IP =~ ^172\.{16..31}\. ]]; then + + RUSER_WAN_IP=$(dig +short +time=8 +tries=1 myip.opendns.com @resolver1.opendns.com 2>/dev/null) + + # If OpenDNS hostname can't be resolved, use local IP as a fallback + if [[ $(echo $RUSER_WAN_IP | wc -w) -eq 0 ]]; then + RUSER_WAN_IP=$RUSER_IP + fi + else + + # WAN IP is used IP + RUSER_WAN_IP=$RUSER_IP + fi +else + + # Couldn't find IP address from SSH_CONNECTION variable + kill -INT $$ +fi + +TZ=$(mmdblookup -f $GEOIP2_DATABASE -i $RUSER_WAN_IP location 2>/dev/null | awk '/time_zone/ {getline; print $0}' | awk -F '"' '{print $2}') + +# If TZ is empty, then use server default time zone setting as a default value +if [[ $(echo $TZ | wc -w) -eq 0 ]]; then + export TZ=$(timedatectl | sed '/Time zone:/!d' | awk '{print $3}') +else + export TZ +fi diff --git a/tools/tputcolors.sh b/tools/tputcolors.sh new file mode 100644 index 0000000..2050f77 --- /dev/null +++ b/tools/tputcolors.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +# Source: https://unix.stackexchange.com/questions/269077/tput-setaf-color-table-how-to-determine-color-codes + +# Author: user79743 + +color(){ + for c; do + printf '\e[48;5;%dm%03d' $c $c + done + printf '\e[0m \n' +} + +IFS=$' \t\n' +color {0..15} +for ((i=0;i<6;i++)); do + color $(seq $((i*36+16)) $((i*36+51))) +done +color {232..255}