From 81e6aa9d3c6459776af60160ad6199f868714d0d Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Tue, 23 Jul 2013 23:29:15 -0500 Subject: [PATCH] Update: numerous changes, features, and bugfixes I had worked on a number of changes after a while and then forgot about them. I do not remember the exact nature of every change. The external dependency has been moved into kit as kit-core to make it easier for other distributions to install and utilize kit. --- sources/kit | 482 ++++++++++++++++++++++ sources/kit-core | 244 ++++++++++++ sources/kit-distribution | 85 ++++ sources/kit-dynamic | 542 +++++++++++++++++++++++++ sources/kit-fss | 83 ++++ sources/kit-log | 53 +++ sources/kit-message | 129 ++++++ sources/kit-operation | 43 ++ sources/kit-operation-access | 170 ++++++++ sources/kit-operation-attribute | 170 ++++++++ sources/kit-operation-directory | 112 ++++++ sources/kit-operation-file | 156 ++++++++ sources/kit-operation-group | 100 +++++ sources/kit-operation-if | 116 ++++++ sources/kit-operation-library | 140 +++++++ sources/kit-operation-mode | 169 ++++++++ sources/kit-operation-path | 97 +++++ sources/kit-operation-shell | 32 ++ sources/kit-operation-strip | 100 +++++ sources/kit-operation-version | 131 ++++++ sources/kit-package | 863 ++++++++++++++++++++++++++++++++++++++++ sources/kit-permission | 65 +++ sources/kit-procedure | 36 ++ sources/kit-read | 6 + sources/kit-reserved | 305 ++++++++++++++ sources/kit-rule | 301 ++++++++++++++ sources/sh/kit-core | 244 ++++++++++++ 27 files changed, 4974 insertions(+) create mode 100755 sources/kit create mode 100755 sources/kit-core create mode 100755 sources/kit-distribution create mode 100755 sources/kit-dynamic create mode 100755 sources/kit-fss create mode 100755 sources/kit-log create mode 100755 sources/kit-message create mode 100755 sources/kit-operation create mode 100755 sources/kit-operation-access create mode 100755 sources/kit-operation-attribute create mode 100755 sources/kit-operation-directory create mode 100755 sources/kit-operation-file create mode 100755 sources/kit-operation-group create mode 100755 sources/kit-operation-if create mode 100755 sources/kit-operation-library create mode 100755 sources/kit-operation-mode create mode 100755 sources/kit-operation-path create mode 100755 sources/kit-operation-shell create mode 100755 sources/kit-operation-strip create mode 100755 sources/kit-operation-version create mode 100755 sources/kit-package create mode 100755 sources/kit-permission create mode 100755 sources/kit-procedure create mode 100755 sources/kit-read create mode 100755 sources/kit-reserved create mode 100755 sources/kit-rule create mode 100755 sources/sh/kit-core diff --git a/sources/kit b/sources/kit new file mode 100755 index 0000000..5bb2b9d --- /dev/null +++ b/sources/kit @@ -0,0 +1,482 @@ +#!/bin/bash +# Programmer: Kevin Day +# License: lgplv2 +# See: https://www.kevux.org/ or https://primary.kevux/ +# Dependencies: bash uniq sort sed grep fss_basic_read fss_extended_read fss_basic_list_read fss_basic_write fss_extended_write fss_basic_list_write fss_return_code rm rmdir cp ln strip chown chmod chgrp chattr chacl find git touch mknod gcc as file line + +# TODO: for security purposes, when doing compilation, add a variable that defines a users to su as during compilation of sources. +# said user account must have access to all appropriate cache paths. +# consider creating this as an operation called 'safe' (a variant of the 'shell' command), such as: safe ./configure + +main() { + public_name="Kevux Package Manager" + system_name=kit + version=0.4.x + + # control variables + local do_help= + local do_cleanup=y + local kit_operation= + local path_original=$PWD + local search_target= # FIXME: what was this for again? + local action= + local verbose= + local self=global + local parent= + + # global variable management + local reserved_variables= + local reserved= + + # dynamic variable management + local dynamic_variables= + local dynamic_data= + local dynamic_total= + local dynamic= + + # permission variable management + local permission_variables= + local permission_data= + local permission_total= + local permission= + + # path & system variables + local system_settings_path=/etc/kit/ + local system_data_path=/share/kit/ + local system_cache_path=/home/kit/ + local system_versions_path=${system_settings_path}versions/ + local system_settings_file=system.settings + local system_permissions_file=system.permissions + local system_environment_file=environment.settings + local system_settings_name=main + local installation_base= + + # remote variables + local remote_url_web=https://packages.kevux/ + local remote_url_git=git://packages.kevux:3/ + local remote_branch=master + local remote_tag= + local remote_depth="--depth 1" + + # distribution variables + local distribution=turtle + local distribution_version=0.9 + local distribution_flavor=core + local distribution_path=distribution/${distribution}/${distribution_version}/ + local distribution_base=$system_cache_path$distribution_path$distribution_flavor/ + local distribution_settings_path=${distribution_base}settings/ + local distribution_settings_file=system.settings + local distribution_environment_file=environment.settings + local distribution_permissions_file=system.permissions + + # targets variables + local targets= + local targets_path=packages/ + local targets_extension=package + local targets_type=source + local targets_what= + local targets_huh= + local targets_oh= + + # log variables + local logs_path=${system_cache_path}logs/ + local logs_file=main.log + + # resume variables + local resume_path=${system_cache_path}resume/ + local resume_execution= + + # other variables + local strip=yes + local i= + + + while [[ $count -lt $main_size ]] ; do + i=${main_input[$count]} + + if [[ $grab_next == "" ]] ; then + if [[ $i == "-h" || $i == "--help" ]] ; then + do_help=y + elif [[ $i == "+n" || $i == "++no_color" ]] ; then + do_color=none + elif [[ $i == "+l" || $i == "++light" ]] ; then + do_color=light + elif [[ $i == "+v" || $i == "++version" ]] ; then + do_help=v + elif [[ $i == "-v" || $i == "--verbose" ]] ; then + verbose=y + elif [[ $i == "-u" || $i == "--url" ]] ; then + grab_next=url + elif [[ $i == "-d" || $i == "--distribution" ]] ; then + grab_next=distribution + elif [[ $i == "-t" || $i == "--target" ]] ; then + grab_next=target + elif [[ $i == "-c" || $i == "--cache" ]] ; then + grab_next=cache + elif [[ $i == "-r" || $i == "--resume" ]] ; then + resume_execution=yes + elif [[ $i == "-s" || $i == "--settings" ]] ; then + grab_next=settings + elif [[ $i == "-a" || $i == "--action" ]] ; then + grab_next=action + elif [[ $i == "-b" || $i == "--installation_base" ]] ; then + grab_next=installation_base + elif [[ $i == "+c" || $i == "++cleanup" ]] ; then + do_cleanup=n + elif [[ $kit_operation == "" ]] ; then + kit_operation="$i" + else + targets="$targets$i " + fi + else + if [[ $grab_next == "url" ]] ; then + if [[ $i == "git" || $i == "web" ]] ; then + grab_next="url $i" + else + kit_message_error_no_log "Unrecognized option '${c_notice}$i${c_error}' for the ${c_notice}url${c_error} parameter." + cleanup_before_exit + exit -1 + fi + + let count=$count+1 + continue + elif [[ $grab_next == "url git" ]] ; then + remote_url_git="$i" + elif [[ $grab_next == "url web" ]] ; then + remote_url_web="$i" + elif [[ $grab_next == "distribution" ]] ; then + if [[ $i == "name" || $i == "version" || $i == "flavor" || $i == "branch" ]] ; then + grab_next="distribution $i" + else + kit_message_error_no_log "Unrecognized option '${c_notice}$i${c_error}' for the ${c_notice}distribution${c_error} parameter." + cleanup_before_exit + exit -1 + fi + + let count++ + continue + elif [[ $grab_next == "distribution name" ]] ; then + distribution="$i" + distribution_path=distribution/${distribution}/${distribution_version}/ + distribution_base=$system_cache_path$distribution_path$distribution_flavor/ + distribution_settings_path=${distribution_base}settings/ + elif [[ $grab_next == "distribution version" ]] ; then + distribution_version="$i" + distribution_path=distribution/${distribution}/${distribution_version}/ + distribution_base=$system_cache_path$distribution_path$distribution_flavor/ + distribution_settings_path=${distribution_base}settings/ + elif [[ $grab_next == "distribution flavor" ]] ; then + distribution_flavor="$i" + distribution_base=$system_cache_path$distribution_path$distribution_flavor/ + distribution_settings_path=${distribution_base}settings/ + elif [[ $grab_next == "distribution branch" ]] ; then + remote_branch="$i" + elif [[ $grab_next == "target" ]] ; then + if [[ $i == "type" || $i == "what" || $i == "huh" || $i == "oh" ]] ; then + grab_next="target $i" + else + kit_message_error_no_log "Unrecognized option '${c_notice}$i${c_error}' for the ${c_notice}package${c_error} parameter." + cleanup_before_exit + exit -1 + fi + + let count=$count+1 + continue + elif [[ $grab_next == "target type" ]] ; then + targets_type="$i" + elif [[ $grab_next == "target what" ]] ; then + targets_what="$targets_what$i " + multiple="yes" + elif [[ $grab_next == "target huh" ]] ; then + targets_huh="$targets_huh$i " + elif [[ $grab_next == "target oh" ]] ; then + if [[ $(kit_core_is_empty $targets_oh) == "" ]] ; then + targets_oh="$i" + else + kit_message_warning_no_log "For simplicity purposes, the current design only allows one 'oh' to be specified, the additional oh '${c_notice}$i${c_error}' is being ignored." + sleep 6 + fi + elif [[ $grab_next == "cache" ]] ; then + system_cache_path=$(echo "$i" | sed -e 's|/*$|/|') + resume_path="${system_cache_path}resume/" + logs="${system_cache_path}logs/" + elif [[ $grab_next == "settings" ]] ; then + system_settings_path=$(echo "$i" | sed -e 's|/*$|/|') + system_versions_path="${system_settings_path}versions/" + elif [[ $grab_next == "action" ]] ; then + action="$i" + elif [[ $grab_next == "installation_base" ]] ; then + installation_base=$(echo "$i" | sed -e 's|/*$|/|') + fi + + grab_next= + fi + + let count++ + done + + + kit_core_handle_colors + + + if [[ $do_help != "" ]] ; then + if [[ $do_help == "v" ]] ; then + echo $the_version + else + kit_message_help + fi + + return + fi + + + if [[ $(kit_core_is_empty $kit_operation ) == "" ]] ; then + kit_message_help + return + fi + + if [[ $(kit_core_is_empty $targets_what ) == "" ]] ; then + targets_what=runtime + fi + + if [[ $(kit_core_is_empty $distribution_base ) == "" ]] ; then + distribution_base=$system_cache_path$distribution_path$distribution_flavor/ + fi + + if [[ ! -d $logs_path ]] ; then + mkdir -p $logs_path + fi + + if [[ ! -d $system_cache_path$distribution_path ]] ; then + mkdir -p $system_cache_path$distribution_path + fi + + if [[ ! -d $resume_path ]] ; then + mkdir -p $resume_path + fi + + + # TODO: come up with a cleanup function that cleans & deletes data, such as distribution repositories, logs, or other cached/temporary data + # TODO: come up with a list of all of the other possible options, like revert, and figure out if and how they are to be implemented + case $kit_operation in + "distribution") + # TODO: execution a series of procedures and packages accodring to a given distribution + kit_message_warning_no_log "'$c_notice$kit_operation$c_warning' is currently not implemented." + cleanup_before_exit + exit -1 + ;; + "procedure") + targets_path=procedures/ + targets_extension=procedure + ;; + "install") ;; + "alter") + if [[ $action == "" ]] ; then + action=upgrade + elif [[ $action != "upgrade" && $action != "downgrade" && $action != "force" ]] ; then + kit_message_error_no_log "The action '$c_notice$action$c_error' is not valid for the operation '$c_notice$kit_operation$c_error'." + cleanup_before_exit + exit -1 + fi + ;; + "uninstall") + kit_message_warning_no_log "'$c_notice$kit_operation$c_warning' is currently not implemented." + cleanup_before_exit + exit -1 + ;; + "update") ;; + "reset") ;; + #"revert") ;; # TODO: figure out if it is possible and practical to perform revert operations + *) + kit_message_error_no_log "'$c_notice$kit_operation$c_error' is not a valid operation." + cleanup_before_exit + exit -1 + ;; + esac + + if [[ $kit_operation == "install" || $kit_operation == "alter" || $kit_operation == "uninstall" ]] ; then + if [[ $targets == "" ]] ; then + kit_message_error_no_log "$kit_operation ${c_notice}what${c_error}? Please specify a package." + cleanup_before_exit + exit -1 + fi + fi + + if [[ $(echo "$url" | grep -s -o '^http://') != "" || $(echo "$url" | grep -s -o '^https://') != "" ]] ; then + remote_depth= + fi + + + kit_reserved_register + kit_distribution_load + + + kit_log_section + + if [[ $targets != "" ]] ; then + kit_log_message message "Processing the targets: $targets" + fi + + + # load specific settings + if [[ -f $system_settings ]] ; then + # load optional 'strip' setting + if [[ $(fss_basic_list_read $system_settings_path$system_settings_file -t -n $system_settings_name) -gt 0 ]] ; then + if [[ $(fss_basic_list_read $system_settings_path$system_settings_file -n $system_settings_name | fss_basic_read -t -n strip) -gt 0 ]] ; then + kit_log_message load global "strip" "fss_basic_list_read $system_settings_path$system_settings_file -c 0 -n $system_settings_name | fss_basic_read -c 0 -n strip" + strip=$(fss_basic_list_read $system_settings_path$system_settings_file -c 0 -n $system_settings_name | fss_basic_read -c 0 -n strip) + + if [[ $strip != "yes" && $strip != "explicit" && $strip != "implicit" && $strip != "no" ]] ; then + kit_message_warning_no_log "The optional strip setting '$c_notice$strip$c_warning', defined in '$c_notice$system_settings_name$c_warning' of '$c_notice$system_settings_path$system_settings_file$c_warning' is invalid and should be either yes, explicit, implicit, or no, now defaulting to yes." + strip=yes + sleep 6 + fi + fi + fi + + # attempt to load installation base path if it was not specified by a parameter + if [[ $(kit_core_is_empty $installation_base) == "" ]] ; then + if [[ $(fss_basic_list_read $system_settings_path$system_settings_file -t -n installation_base) -gt 0 ]] ; then + if [[ $(fss_basic_list_read $system_settings_path$system_settings_file -n installation_base | fss_extended_read -t -n installation_base) -gt 0 ]] ; then + kit_log_message load global "installation_base" "fss_basic_list_read $system_settings_path$system_settings_file -c 0 -n installation_base | fss_extended_read -c 0 -s 0 -n installation_base" + installation_base=$(fss_basic_list_read $system_settings_path$system_settings_file -c 0 -n installation_base | fss_extended_read -c 0 -s 0 -n installation_base) + fi + fi + fi + fi + + + # TODO: if "what", "huh", and "oh" options are present, only allow one target to be specified OR find a way to allow multiple targets at the same time + # process targets + for i in $targets ; do + if [[ -f $distribution_base$targets_path$i.$targets_extension || $kit_operation == "reset" || $kit_operation == "update" ]] ; then + if [[ $targets_extension == "package" ]] ; then + kit_package "$i" "$distribution_base$targets_path" "$i.$targets_extension" + elif [[ $targets_extension == "procedure" ]] ; then + kit_procedure "$i" "$distribution_base$targets_path" "$i.$targets_extension" + fi + else + kit_message_warning_no_log "Could not find target '$c_notice$i$c_warning' at the path '$c_notice$distribution_base$targets_path$i.$targets_extension${c_warning}'" + fi + done + + + cleanup_before_exit +} + +cleanup_before_exit() { + local i= + cd $path_original + + if [[ $do_cleanup != "y" ]] ; then + return + fi + + if [[ $(kit_core_is_empty $distribution_base) != "" ]] ; then + if [[ -d $distribution_base$targets_path ]] ; then + rmdir --ignore-fail-on-non-empty $distribution_base$targets_path + fi + + if [[ -d $distribution_base ]] ; then + rmdir --ignore-fail-on-non-empty $distribution_base + fi + fi + + if [[ $(kit_core_is_empty $distribution) != "" ]] ; then + if [[ $(kit_core_is_empty $distribution_version) != "" ]] ; then + if [[ -d ${system_cache_path}distribution/${distribution}/${distribution_version}/ ]] ; then + rmdir --ignore-fail-on-non-empty ${system_cache_path}distribution/${distribution}/${distribution_version}/ + fi + fi + + if [[ -d ${system_cache_path}distribution/${distribution}/ ]] ; then + rmdir --ignore-fail-on-non-empty ${system_cache_path}distribution/${distribution}/ + fi + fi + + if [[ -d ${system_cache_path}distribution/ ]] ; then + rmdir --ignore-fail-on-non-empty ${system_cache_path}distribution/ + fi +} + +cleanup_main() { + kit_core_unset + + kit_fss_unset + kit_message_unset + kit_log_unset + kit_reserved_unset + kit_dynamic_unset + kit_permission_unset + kit_distribution_unset + kit_package_unset + kit_procedure_unset + kit_rule_unset + + kit_operation_unset + kit_operation_access_unset + kit_operation_attribute_unset + kit_operation_directory_unset + kit_operation_file_unset + kit_operation_group_unset + kit_operation_library_unset + kit_operation_mode_unset + kit_operation_path_unset + kit_operation_shell_unset + kit_operation_strip_unset + kit_operation_version_unset + kit_operation_if_unset + + unset cleanup_before_exit + unset main +} + + +OLD_PATH=$PATH +# PATH=_SCRIPT_LIBRARY_PREFIX_:$PATH + +source $(type -p kit-core) +source $(type -p kit-fss) +source $(type -p kit-message) +source $(type -p kit-log) +source $(type -p kit-reserved) +source $(type -p kit-dynamic) +source $(type -p kit-permission) +source $(type -p kit-distribution) +source $(type -p kit-package) +source $(type -p kit-procedure) +source $(type -p kit-operation) +source $(type -p kit-operation-access) +source $(type -p kit-operation-attribute) +source $(type -p kit-operation-directory) +source $(type -p kit-operation-file) +source $(type -p kit-operation-group) +source $(type -p kit-operation-library) +source $(type -p kit-operation-mode) +source $(type -p kit-operation-path) +source $(type -p kit-operation-shell) +source $(type -p kit-operation-strip) +source $(type -p kit-operation-version) +source $(type -p kit-operation-if) +source $(type -p kit-rule) +PATH=$OLD_PATH +unset OLD_PATH + +# populate main_input variable +main_input= +main_size=$# +c1=0 +c2= + +while [[ $c1 -lt $main_size ]] ; do + let c2=$c1+1 + main_input[$c1]=${!c2} + let c1=$c1+1 +done + +unset c1 c2 + +# execute the program +kit_core_main_execute=main +kit_core_main +cleanup_main diff --git a/sources/kit-core b/sources/kit-core new file mode 100755 index 0000000..30aa5c6 --- /dev/null +++ b/sources/kit-core @@ -0,0 +1,244 @@ +#!/bin/bash +# License: lgpl v2 + +kit_core_unset(){ + unset kit_core_main_execute + unset kit_core_main + unset kit_core_prepare_input + unset kit_core_handle_colors + unset kit_core_help_title + unset kit_core_help_options + unset kit_core_error + unset kit_core_warning + unset kit_core_is_empty + unset kit_core_unset + unset kit_core_to_lower + unset kit_core_to_upper + unset kit_core_alpha_numeric + unset kit_core_directory_ending + unset kit_core_get_random +} + +kit_core_main(){ + local public_name= + local system_name= + local called_name= + local version= + local the_operation= + local grab_next= + local do_color=normal + local do_help= + local i= + local count= + + if [[ $# -gt 0 ]] ; then + local main_input= + local main_size=$# + + while [[ $count -lt $main_size ]] ; do + let i=$count+1 + main_input[$count]=${!i} + let count=$count+1 + done + + i= + count=0 + fi + + local c_reset="\\033[0m" + local c_title="\\033[1;33m" + local c_error="\\033[1;31m" + local c_warning="\\033[0;33m" + local c_highlight="\\033[1;32m" + local c_notice="\\033[0;01m" + local c_important="\\033[0;32m" + local c_subtle="\\033[1;30m" + local c_prefix="\\" + + $kit_core_main_execute +} + +kit_core_handle_colors(){ + if [[ $do_color == "light" ]] ; then + c_error="\\033[1;31m" + c_warning="\\033[0;31m" + c_title="\\033[1;34m" + c_highlight="\\033[0;34m" + c_notice="\\033[0;01m" + c_important="\\033[0;35m" + elif [[ $do_color == "none" ]] ; then + c_reset= + c_title= + c_error= + c_warning= + c_highlight= + c_notice= + c_important= + c_subtle= + c_prefix= + fi +} + +kit_core_help_title(){ + echo + echo -e "${c_title}$public_name$c_reset" + echo -e " ${c_notice}Version $version$c_reset" + echo +} + +kit_core_help_options(){ + echo -e "${c_highlight}Options:$c_reset" + echo -e " -${c_important}h${c_reset}, --${c_important}help${c_reset} Print this help screen" + echo -e " +${c_important}l${c_reset}, ++${c_important}light${c_reset} Use color modes that show up better on light backgrounds" + echo -e " +${c_important}n${c_reset}, ++${c_important}no_color${c_reset} Do not use color" + echo -e " +${c_important}v${c_reset}, ++${c_important}version${c_reset} Print the version number of this program" + echo +} + +kit_core_error(){ + echo -e "${c_error}ERROR: $*$c_reset" +} + +kit_core_warning(){ + echo -e "${c_warning}WARNING: $*$c_reset" +} + +kit_core_is_empty(){ + if [[ $(echo $1 | sed -e "s|[[:space:]]||g") != "" ]] ; then + echo -n n + fi +} + +kit_core_to_lower(){ + echo -n $(echo $* | sed -e 's/\(.*\)/\L\1/') +} + +kit_core_to_upper(){ + echo -n $(echo $* | sed -e 's/\(.*\)/\U\1/') +} + +kit_core_alpha_numeric(){ + echo -n $(echo $* | sed -e 's|[[:punct:][:space:][:cntrl:]]*||g') +} + +kit_core_directory_ending(){ + echo -n $(echo $i | sed -e 's|/*$|/|') +} + +standard_datetimestamp(){ + echo -n $(date +%Y-%m-%dT%H:%M:%S%z) +} + +standard_datetimestamp_safe(){ + echo -n $(date +%Y_%m_%d-%H_%M_%S%z) +} + +kit_core_get_random(){ + local method=$1 + local minimum=$2 + local maximum=$3 + local current=0 + local goal=$[ ( $RANDOM % $maximum ) ] + local number= + + if [[ $goal -lt $minimum ]] ; then + let goal=$minimum + fi + + while [[ $current -lt $goal ]] ; do + if [[ $method == "numeric" ]] ; then + number=$[ ( $RANDOM % 10 ) ] + elif [[ $method == "alphanumeric" ]] ; then + number=$[ ( $RANDOM % 62 ) ] + elif [[ $method == "all" ]] ; then + number=$[ ( $RANDOM % 89 ) ] + fi + + case $number in + "10") echo -n "A";; + "11") echo -n "B";; + "12") echo -n "C";; + "13") echo -n "D";; + "14") echo -n "E";; + "15") echo -n "F";; + "16") echo -n "G";; + "17") echo -n "H";; + "18") echo -n "I";; + "19") echo -n "J";; + "20") echo -n "K";; + "21") echo -n "L";; + "22") echo -n "M";; + "23") echo -n "N";; + "24") echo -n "O";; + "25") echo -n "P";; + "26") echo -n "Q";; + "27") echo -n "R";; + "28") echo -n "S";; + "29") echo -n "T";; + "30") echo -n "U";; + "31") echo -n "V";; + "32") echo -n "W";; + "33") echo -n "X";; + "34") echo -n "Y";; + "35") echo -n "Z";; + "36") echo -n "a";; + "37") echo -n "b";; + "38") echo -n "c";; + "39") echo -n "d";; + "40") echo -n "e";; + "41") echo -n "f";; + "42") echo -n "g";; + "43") echo -n "h";; + "44") echo -n "i";; + "45") echo -n "j";; + "46") echo -n "k";; + "47") echo -n "l";; + "48") echo -n "m";; + "49") echo -n "n";; + "50") echo -n "o";; + "51") echo -n "p";; + "52") echo -n "q";; + "53") echo -n "r";; + "54") echo -n "s";; + "55") echo -n "t";; + "56") echo -n "u";; + "57") echo -n "v";; + "58") echo -n "w";; + "59") echo -n "x";; + "60") echo -n "y";; + "61") echo -n "z";; + "62") echo -n "~";; + "63") echo -n "!";; + "64") echo -n "@";; + "65") echo -n "#";; + "66") echo -n "$";; + "67") echo -n "%";; + "68") echo -n "^";; + "69") echo -n "&";; + "70") echo -n "*";; + "71") echo -n "(";; + "72") echo -n ")";; + "73") echo -n "-";; + "74") echo -n "+";; + "75") echo -n "\`";; + "76") echo -n "\"";; + "77") echo -n "'";; + "78") echo -n "{";; + "79") echo -n "}";; + "80") echo -n "[";; + "81") echo -n "]";; + "82") echo -n "|";; + "83") echo -n "\\";; + "84") echo -n ";";; + "85") echo -n ">";; + "86") echo -n "<";; + "87") echo -n ",";; + "88") echo -n ".";; + "87") echo -n "=";; + "88") echo -n "_";; + *) echo -n $number;; + esac + + let current=$current+1 + done +} diff --git a/sources/kit-distribution b/sources/kit-distribution new file mode 100755 index 0000000..737042b --- /dev/null +++ b/sources/kit-distribution @@ -0,0 +1,85 @@ +#!/bin/bash +# provides functions for processing and execution of distribution files. + +kit_distribution_unset() { + unset kit_distribution_load +} + +kit_distribution_load() { + local i=0 + + kit_log_message + kit_log_message message "obtaining and reading data for distribution '$distribution', version '$distribution_version', flavor '$distribution_flavor'" + + if [[ ! -d $system_cache_path ]] ; then + kit_message_shell "mkdir -p $system_cache_path" + mkdir -p $system_cache_path + + if [[ $? -ne 0 ]] ; then + kit_message_error "Failed to create the directory '$c_notice$system_cache_path$c_error'" + cleanup_before_exit + return + fi + fi + + if [[ ! -d $distribution_base ]] ; then + kit_message_shell "git clone --progress $remote_depth -q -o $remote_branch -n $remote_url_git$distribution_path$distribution_flavor $distribution_base" + git clone --progress $remote_depth -q -o $remote_branch -n $remote_url_git$distribution_path$distribution_flavor $distribution_base + + if [[ $? -ne 0 || ! -d $distribution_base ]] ; then + kit_message_error "Failed to clone '$c_notice$remote_url_git$distribution_path$distribution_flavor$c_error' with branch of '$c_notice$remote_branch$c_error' to '$c_notice$distribution_base$c_error'" + exit -1 + fi + + kit_message_shell "cd $distribution_base" + cd $distribution_base + + if [[ $? -ne 0 ]] ; then + kit_message_error "Failed to change to the directory '$c_notice$distribution_base$c_error'$c_reset" + cleanup_before_exit + exit -1 + fi + + kit_message_shell "git checkout" + git checkout + + if [[ $? -ne 0 ]] ; then + kit_message_error "Failed to checkout repository at '${c_notice}$distribution_base$c_error'" + cleanup_before_exit + exit -1 + fi + else + kit_message_shell "cd $distribution_base" + cd $distribution_base + + if [[ $? -ne 0 ]] ; then + kit_message_error "Failed to change to the directory '$c_notice$distribution_base$c_error'$c_reset" + cleanup_before_exit + exit -1 + fi + fi + + if [[ $kit_operation == "update" && $(kit_core_is_empty $targets) == "" ]] ; then + kit_message_shell "git pull --quiet --progress" + git pull --quiet --progress + + if [[ $? -ne 0 ]] ; then + kit_message_error "Failed to update repository at '${c_notice}$distribution_base$c_error'$c_reset" + cleanup_before_exit + exit -1 + fi + + echo -e "${c_highlight}The branch '${c_notice}$remote_branch$c_highlight' and flavor '${c_notice}$distribution_flavor$c_highlight' for the distribution '${c_notice}$distribution$c_highlight' has been updated.$c_reset" + elif [[ $kit_operation == "reset" && $(kit_core_is_empty $targets) == "" ]] ; then + kit_message_shell "git reset --hard --quiet" + git reset --hard --quiet + + if [[ $? -ne 0 ]] ; then + kit_message_error "Failed to reset repository at '${c_notice}$distribution_base$c_error'$c_reset" + cleanup_before_exit + exit -1 + fi + + kit_message_highlight "The branch '${c_notice}$remote_branch$c_highlight' and flavor '${c_notice}$distribution_flavor$c_highlight' for the distribution '${c_notice}$distribution$c_highlight' has been reset." + fi +} diff --git a/sources/kit-dynamic b/sources/kit-dynamic new file mode 100755 index 0000000..0a5f07a --- /dev/null +++ b/sources/kit-dynamic @@ -0,0 +1,542 @@ +#!/bin/bash +# provides functions for reading and writing dynamic variables. + +kit_dynamic_unset() { + unset kit_dynamic_error + unset kit_dynamic_is + unset kit_dynamic_set + unset kit_dynamic_get + unset kit_dynamic_required_load_names + unset kit_dynamic_process + unset kit_dynamic_process_inline + unset kit_dynamic_optional_load_names + unset kit_dynamic_inline_load_names + unset kit_dynamic_inline_resume + unset kit_dynamic_strategy_prepare + unset kit_dynamic_strategy_load + unset kit_dynamic_sanitize + unset kit_dynamic_safe_expand +} + +kit_dynamic_error() { + kit_message_error "$*" + + cleanup_before_exit + exit -6 +} + +kit_dynamic_is() { + local name=$1 + + echo -n $(echo $dynamic_variables | grep -s -o "\<$name=[[:digit:]]*\>" | sed -e "s|$name=||") +} + +kit_dynamic_set() { + local name=$1 + local value=$2 + local position= + + position=$(kit_dynamic_is $name) + + if [[ $position == "" ]] ; then + if [[ $dynamic_total == "" ]] ; then + dynamic_total=0 + fi + dynamic_data[$dynamic_total]=$value + dynamic_variables="${dynamic_variables}$name=$dynamic_total " + let dynamic_total++ + else + dynamic_data[$position]=$value + fi + + kit_log_message save dynamic "$name" "$value" +} + +kit_dynamic_get() { + local name=$1 + local name_custom=$2 + local position= + local file= + local list= + + if [[ $name == "" ]] ; then + dynamic= + return + fi + + if [[ $(kit_core_is_empty $name_custom) == "" ]] ; then + name_custom=$name + fi + + dynamic= + position=$(kit_dynamic_is "$name") + + # loading priority is: memory (dynamic_data), system settings, and then distribution settings. + if [[ $position != "" && $position -ge 0 ]] ; then + dynamic=${dynamic_data[$position]} + + kit_log_message load dynamic "$name" "$dynamic" + else + for file in "$system_settings_path$system_settings_file" "$distribution_settings_path$distribution_settings_file" ; do + if [[ -f $file ]] ; then + for list in "$name_custom" "$system_settings_name" ; do + + if [[ $(fss_basic_list_read -n $list -t $file) -gt 0 && $(fss_basic_list_read -c 0 -n $list $file | fss_basic_read -t -n $name) -gt 0 ]] ; then + kit_log_message load dynamic "$name" "fss_basic_list_read -c 0 -n $list $file | fss_basic_read -c 0 -n $name" + dynamic=$(fss_basic_list_read -c 0 -n $list $file | fss_basic_read -c 0 -n $name) + kit_dynamic_set "$name" "$dynamic" + return + fi + done + fi + done + fi +} + +kit_dynamic_required_load_names() { + local path=$1 + local file=$2 + + dynamic_required= + + if [[ -f $path$file ]] ; then + dynamic_required=$(grep -s -o '\[\[[[:alnum:]_]*]]' $path$file | sort | uniq | sed -e 's|^\[\[||g' -e 's|]]$||g') + fi +} + +kit_dynamic_process() { + local type=$1 + local path=$2 + local file=$3 + local name_custom=$4 + local name= + local variable= + local dynamic= + local position= + local reserved= + local answer= + local sanitized= + local variables= + local processed= + local expanded= + local dynamic_inline= + + if [[ $type == "required" ]] ; then + variables=$dynamic_required + elif [[ $type == "optional" ]] ; then + variables=$dynamic_optional + elif [[ $type == "inline" ]] ; then + kit_dynamic_inline_load_names + variables="$dynamic_inline" + name_custom=$2 + else + return + fi + + while [[ $variables != "" ]] ; do + + for name in $variables ; do + if [[ $type == "required" ]] ; then + variable="[[$name]]" + elif [[ $type == "optional" ]] ; then + variable="[<$name>]" + elif [[ $type == "inline" ]] ; then + variable="[{$name}]" + + # process variables only once, strip recursive names (preventing infinite recursion) + if [[ $(echo "$processed" | grep -s -o "\<$name\>") != "" ]] ; then + line=$(echo -n "$line" | sed -e "s|\[{$name}]||g") + continue; + fi + fi + + position=$(kit_reserved_is $name) + kit_dynamic_strategy_load $name + + if [[ $position == "global" || $(echo "$parent" | grep -s -o "\<$position\>") != "" || $position == $self ]] ; then + kit_reserved_get "$name" + + if [[ $strategy_length -gt 0 ]] ; then + kit_dynamic_sanitize "$name" "$reserved" + + if [[ $? -eq 0 ]] ; then + if [[ $type == "required" ]] ; then + sed -i -e "s|\[\[$name]]|$sanitized|g" $path$file + elif [[ $type == "optional" ]] ; then + sed -i -e "s|\[<$name>]|$sanitized|g" $path$file + elif [[ $type == "inline" ]] ; then + line=$(echo -n "$line" | sed -e "s|\[{$name}]||g") + processed="$processed$name " + fi + else + if [[ $strategy_type == "list" ]] ; then + kit_dynamic_error "'$c_notice$reserved$c_error' is not a valid choice for '$c_notice$name$c_error'$c_reset" + fi + fi + else + if [[ $type == "required" ]] ; then + sed -i -e "s|\[\[$name]]|$reserved|g" $path$file + elif [[ $type == "optional" ]] ; then + sed -i -e "s|\[<$name>]|$reserved|g" $path$file + elif [[ $type == "inline" ]] ; then + line=$(echo -n "$line" | sed -e "s|\[{$name}]|$reserved|g") + processed="$processed$name " + fi + fi + else + kit_dynamic_get "$name" "$name_custom" + position=$(kit_dynamic_is $name) + + if [[ $(kit_core_is_empty $position) == "" ]] ; then + if [[ $type == "required" ]] ; then + answer= + + while [[ $answer == "" ]] ; do + echo + echo -e "Define the value for the variable $c_notice$name$c_reset (required)." + echo -n "# " + read answer + + if [[ $strategy_length -gt 0 ]] ; then + kit_dynamic_sanitize "$name" "$answer" + + if [[ $? -eq 0 ]] ; then + answer=$sanitized + break; + else + if [[ $strategy_type == "list" ]] ; then + kit_message_error "'$c_notice$answer$c_error' is not a valid choice for '$c_notice$name$c_error'$c_reset" + fi + + answer= + fi + fi + done + + kit_dynamic_set "$name" "$answer" + sed -i -e "s|\[\[$name]]|$answer|g" $path$file + elif [[ $type == "optional" ]] ; then + sed -i -e "s|\[<$name>]||g" $path$file + elif [[ $type == "inline" ]] ; then + line=$(echo -n "$line" | sed -e "s|\[{$name}]||g") + processed="$processed$name " + fi + else + if [[ $strategy_length -gt 0 ]] ; then + kit_dynamic_sanitize "$name" "$dynamic" + + if [[ $? -eq 0 ]] ; then + if [[ $type == "required" ]] ; then + sed -i -e "s|\[\[$name]]|$sanitized|g" $path$file + elif [[ $type == "optional" ]] ; then + sed -i -e "s|\[<$name>]|$sanitized|g" $path$file + elif [[ $type == "inline" ]] ; then + line=$(echo -n "$line" | sed -e "s|\[{$name}]|$sanitized|g") + processed="$processed$name " + fi + else + if [[ $strategy_type == "list" ]] ; then + kit_dynamic_error "'$c_notice$dynamic$c_error' is not a valid choice for '$c_notice$name$c_error'$c_reset" + fi + fi + else + if [[ $type == "required" ]] ; then + sed -i -e "s|\[\[$name]]|$dynamic|g" $path$file + elif [[ $type == "optional" ]] ; then + sed -i -e "s|\[<$name>]|$dynamic|g" $path$file + elif [[ $type == "inline" ]] ; then + line=$(echo -n "$line" | sed -e "s|\[{$name}]|$dynamic|g") + processed="$processed$name " + fi + fi + fi + fi + done + + + # allow a limited form of recursion on inline variables + if [[ $type == "inline" ]] ; then + kit_dynamic_inline_load_names + variables=$dynamic_inline + else + variables= + fi + done +} + +kit_dynamic_optional_load_names() { + local path=$1 + local file=$2 + + dynamic_optional= + + if [[ -f $path$file ]] ; then + dynamic_optional=$(grep -s -o '\[<[[:alnum:]_]*>]' $path$file | sort | uniq | sed -e 's|^\[<||g' -e 's|>]$||g') + fi +} + +kit_dynamic_inline_load_names() { + dynamic_inline=$(echo -n "$line" | grep -s -o '\[{[[:alnum:]_]*}]' | sort | uniq | sed -e 's|^\[{||g' -e 's|}]$||g') +} + +kit_dynamic_inline_resume() { + local name= + local count= + local total= + local position= + local data= + + if [[ ! -f $resume_path$resume_file ]] ; then + kit_message_log warning "Failed to load the resume file '$c_notice$resume_path$resume_file$c_error', it does not exist" + return + fi + + total=$(fss_extended_read -n variable -t $resume_path$resume_file) + + if [[ $(kit_fss_has_error) != "" ]] ; then + kit_dynamic_error "Failed to load the resume file '$c_notice$resume_path$resume_file$c_error'" + fi + + if [[ $(kit_core_is_empty $total) == "" ]] ; then + return + fi + + let count=0 + + while [[ $count -lt $total ]] ; do + name=$(fss_extended_read -n variable -s 0 -c 0 $resume_path$resume_file) + + if [[ $(echo "$inline_variables" | grep -s -o "\[{$name}]") != "" ]] ; then + data=$(fss_extended_read -n variable -s 1 -c 0 $resume_path$resume_file) + + if [[ $? -ne 0 ]] ; then + kit_dynamic_error "While loading the inline variable resume data for '$c_notice$name$c_error' from '$c_notice$resume_path$resume_file$c_error'" + fi + + position=$(kit_reserved_is $name) + + if [[ $position == "global" || $position == $parent || $position == $self ]] ; then + eval $name=\$data + else + kit_dynamic_set $name "$data" + fi + fi + + let count++ + done +} + +kit_dynamic_strategy_prepare() { + if [[ ! -f $strategy_path$strategy_file ]] ; then + kit_message_shell "fss_basic_list_read $system_cache_path$rule_path_base$rule_path_rule$rule_file -n variables > $strategy_path$strategy_file" + fss_basic_list_read $system_cache_path$rule_path_base$rule_path_rule$rule_file -n variables > $strategy_path$strategy_file + + if [[ $(kit_fss_has_error) != "" ]] ; then + kit_rule_error "Failed to generate '$c_notice$strategy_path$strategy_file$c_error' from '${c_notice}variable$c_error' of the file '$c_notice$system_cache_path$rule_path_base$rule_path_rule$rule_file$c_error'" + fi + fi + + kit_log_message load strategy_names "fss_extended_read -o $strategy_path$strategy_file" + strategy_names=$(fss_extended_read -o $strategy_path$strategy_file) + + if [[ $(kit_fss_has_error) != "" ]] ; then + kit_dynamic_error "Failed to load the strategy names from '$c_notice$strategy_path$strategy_file$c_error'" + fi +} + +kit_dynamic_strategy_load() { + local name=$1 + local c=0 + + strategy_length= + strategy_data= + + kit_log_message load strategy_length "fss_extended_read -n $name -c 0 -t $strategy_path$strategy_file" + strategy_length=$(fss_extended_read -n $name -c 0 -t $strategy_path$strategy_file) + + if [[ $(kit_fss_has_error) != "" ]] ; then + kit_dynamic_error "Failed to read the '$c_notice$name${c_error}' strategy data length from '$c_notice$strategy_path$strategy_file$c_error'" + fi + + if [[ $(kit_core_is_empty $strategy_length) == "" || $strategy_length -eq 0 ]] ; then + return + fi + + while [[ $c -lt $strategy_length ]] ; do + kit_log_message load "strategy_data[$c]" "fss_extended_read -n $name -c 0 -s $c $strategy_path$strategy_file" + strategy_data[$c]=$(fss_extended_read -n $name -c 0 -s $c $strategy_path$strategy_file) + + if [[ $(kit_fss_has_error) != "" ]] ; then + kit_dynamic_error "Failed to read parameter '$c_notice$c${c_error}' of the '$c_notice$name${c_error}' strategy data from '$c_notice$strategy_path$strategy_file$c_error'" + fi + + let c++ + done +} + +kit_dynamic_sanitize() { + local variable=$1 + local data=$2 + local strategy_type= + local c= + + sanitized= + + if [[ ! $strategy_length -gt 0 ]] ; then + return 0 + fi + + strategy_type=${strategy_data[0]} + + if [[ $strategy_type == "directory" ]] ; then + sanitized=$(echo -n ${strategy_data[1]} | sed -e 's|/*$|/|' -e 's|^/+|/|') + + return 0 + elif [[ $strategy_type == "list" ]] ; then + if [[ $strategy_length -eq 1 ]] ; then + return 1 + fi + + let c=1 + + while [[ $c -lt $strategy_length ]] ; do + if [[ ${strategy_data[$c]} == $data ]] ; then + sanitized=$data + return 0 + fi + + let c++ + done + fi + + return 1 +} + +kit_dynamic_safe_expand() { + local v=$1 + local o= + local format= + local c1=0 + local t1= + local c2=0 + local t2= + local safe= + local part= + + expanded= + + if [[ $type == "inline" ]] ; then + kit_operation_format "$operation" + + if [[ $format == "fss_basic" || $(kit_core_is_empty $line) == "" ]] ; then + line=$(echo "$line" | sed -e "s|\[<$name>]|$v|g") + + if [[ $? -ne 0 ]] ; then + kit_dynamic_error "Failed to convert inline variable from '${c_notice}[<$name>]${c_error}' to '$c_notice$v$c_error'" + fi + + return + fi + + t1=$(echo "object $line" | fss_extended_read -c 0 -t -n object) + + if [[ ! $t1 -gt 0 ]] ; then + return + fi + + while [[ $c1 -lt $t1 ]] ; do + part=$(fss_extended_read -c 0 -s $c1) + + if [[ $(fss_has_error) != "" ]] ; then + kit_dynamic_error "Failed to load inline variable data at position '$c_notice$c1${c_error}' for expansion" + fi + + part=$(echo "$part" | sed -e "s|\[{$name}]|$v|g") + + if [[ $? -ne 0 ]] ; then + kit_dynamic_error "Failed to convert inline variable from '${c_notice}[{$name}]${c_error}' to '$c_notice$v$c_error'" + fi + + safe=$(fss_extended_write -s -p "$part") + + if [[ $(fss_has_error) != "" ]] ; then + kit_dynamic_error "Failed to sanitize the converted inline variable part '$c_notice$part${c_error}'" + fi + + expanded="$expanded$safe " + + let c1++ + done + + line=$expanded + return + fi + + t2=$(fss_extended_read -t $path$file) + + if [[ ! $t2 -gt 0 ]] ; then + return + fi + + while [[ $c2 -lt $t2 ]] ; do + o=$(fss_extended_read -c $c2 -o $path$file) + kit_operation_format "$o" + + # FIXME: these sed commands will potentially fail if the resume file has any non-fss valid lines, FSS read and write functions need to support literal/exact line detection in addition to the usual relative line numbering. + if [[ $format == "fss_basic" ]] ; then + if [[ $type == "required" ]] ; then + sed -i -e "${c2}s|\[\[$name]]|$v|g" $path$file + + if [[ $? -ne 0 ]] ; then + kit_dynamic_error "Failed to convert required variable from '${c_notice}[[$name]]${c_error}' to '$c_notice$v$c_error' at line '$c_notice$c2${c_error}' of '$c_notice$path$file${c_error}'" + fi + elif [[ $type == "optional" ]] ; then + sed -i -e "${c2}s|\[<$name>]|$v|g" $path$file + + if [[ $? -ne 0 ]] ; then + kit_dynamic_error "Failed to convert optional variable from '${c_notice}[<$name>]${c_error}' to '$c_notice$v$c_error' at line '$c_notice$c2${c_error}' of '$c_notice$path$file${c_error}'" + fi + fi + elif [[ $format == "fss_extended" ]] ; then + # FIXME: looks like a bug in fss_*_read where -c 0 -t does not give the total for extended content of that line.., for now grab the object name and use it with -n to get the total + t1=$(fss_extended_read -c $c2 -t -n $o $path$file) + c1=0 + + if [[ ! $t1 -gt 0 ]] ; then + return + fi + + while [[ $c1 -lt $t1 ]] ; do + part=$(fss_extended_read -c $c2 -s $c1 $path$file) + + if [[ $(fss_has_error) != "" ]] ; then + kit_dynamic_error "Failed to load $type variable data at position '$c_notice$c1${c_error}' of line '$c_notice$c2${c_error}' of '$c_notice$path$file${c_error}' for expansion" + fi + + if [[ $type == "required" ]] ; then + part=$(echo "$part" | sed -e "s|\[\[$name]]|$v|g") + elif [[ $type == "optional" ]] ; then + part=$(echo "$part" | sed -e "s|\[<$name>]|$v|g") + fi + + if [[ $? -ne 0 ]] ; then + kit_dynamic_error "Failed to convert $type variable from '${c_notice}[{$name}]${c_error}' of line '$c_notice$c2${c_error}' of '$c_notice$path$file${c_error}' to '$c_notice$v$c_error'" + fi + + safe=$(fss_extended_write -s -p "$part") + + if [[ $(fss_has_error) != "" ]] ; then + kit_dynamic_error "Failed to sanitize the converted $type variable part '$c_notice$part${c_error}' of line '$c_notice$c2${c_error}' of '$c_notice$path$file${c_error}'" + fi + + expanded="$expanded$safe " + + let c1++ + done + + sed -i -e "${c2}s|^.*$|$expanded|g" $path$file + fi + + let c2++ + done +} diff --git a/sources/kit-fss b/sources/kit-fss new file mode 100755 index 0000000..7cb1262 --- /dev/null +++ b/sources/kit-fss @@ -0,0 +1,83 @@ +#!/bin/bash +# provides functions for reading and writing in fss format. + +kit_fss_unset() { + unset kit_kit_has_fss_error + unset kit_fss_exit_on_error + unset kit_fss_read + unset kit_fss_read_path +} + + +kit_fss_has_error() { + local code=$? + + fss_return_code -e $code + + if [[ $? -eq 1 ]] ; then + echo -n $code + fi +} + +kit_fss_exit_on_error() { + local return_code=$1 + local message=$2 + + if [[ $(kit_fss_has_error $return_code) != "" ]] ; then + kit_message_error "$message" + cleanup_before_exit + exit -1 + fi +} + +kit_fss_read() { + local file=$1 + local variable=$2 + local list=$3 + local name=$4 + local count=$5 + local select=$6 + local data= + + if [[ $(kit_core_is_empty $file) == "" || $(kit_core_is_empty $variable) == "" || $(kit_core_is_empty $list) == "" || $(kit_core_is_empty $count) == "" ]] ;then + kit_fss_exit_on_error $? "Invalid arguments passed to the '${c_notice}kit_fss_read$c_error' function while trying to process the file '$c_notice$file$c_error'" + elif [[ $name == "" ]] ; then + kit_log_message load variable "$variable" "fss_basic_list_read $file -n $list | fss_extended_read -o" + data=$(fss_basic_list_read $file -n $list | fss_extended_read -o) + elif [[ $select == "" ]] ; then + kit_log_message load variable "$variable" "fss_basic_list_read $file -n $list | fss_basic_read -c $count -n $name" + data=$(fss_basic_list_read $file -n $list | fss_basic_read -c $count -n $name) + else + kit_log_message load variable "$variable" "fss_basic_list_read $file -n $list | fss_extended_read -c $count -s $select -n $name" + data=$(fss_basic_list_read $file -n $list | fss_extended_read -c $count -s $select -n $name) + fi + + kit_fss_exit_on_error $? "Failed to read '$c_notice${list}:$name${c_error}' data from '$c_notice$file$c_error'" + eval $variable=\$data +} + +kit_fss_read_path() { + local file=$1 + local variable=$2 + local list=$3 + local name=$4 + local count=$5 + local select=$6 + local data= + + if [[ $(kit_core_is_empty $file) == "" || $(kit_core_is_empty $variable) == "" || $(kit_core_is_empty $list) == "" || $(kit_core_is_empty $count) == "" ]] ;then + kit_fss_exit_on_error $? "Invalid arguments passed to the '${c_notice}kit_fss_read_path$c_error' function while trying to process the file '$c_notice$file$c_error'" + elif [[ $name == "" ]] ; then + kit_log_message load variable "$variable" "fss_basic_list_read $file -n $list | fss_extended_read -o | sed -e 's|/*$|/|'" + data=$(fss_basic_list_read $file -n $list | fss_extended_read -o | sed -e 's|/*$|/|') + elif [[ $select == "" ]] ; then + kit_log_message load variable "$variable" "fss_basic_list_read $file -n $list | fss_basic_read -c $count -n $name | sed -e 's|/*$|/|'" + data=$(fss_basic_list_read $file -n $list | fss_basic_read -c $count -n $name | sed -e 's|/*$|/|') + else + kit_log_message load variable "$variable" "fss_basic_list_read $file -n $list | fss_extended_read -c $count -s $select -n $name | sed -e 's|/*$|/|'" + data=$(fss_basic_list_read $file -n $list | fss_extended_read -c $count -s $select -n $name | sed -e 's|/*$|/|') + fi + + kit_fss_exit_on_error $? "Failed to read '$c_notice${list}:$name${c_error}' data from '$c_notice$file$c_error'" + eval $variable=\$data +} diff --git a/sources/kit-log b/sources/kit-log new file mode 100755 index 0000000..5b2ce21 --- /dev/null +++ b/sources/kit-log @@ -0,0 +1,53 @@ +#!/bin/bash +# provides log generation functions. + +kit_log_unset() { + unset kit_log_section + unset kit_log_message + unset kit_log_message_raw +} + +kit_log_section() { + if [[ ! -f $logs_path$logs_file ]] ; then + echo -e "# fss-0002\n" >> $logs_path$logs_file + fi + + echo >> $logs_path$logs_file + echo "$(standard_datetimestamp_safe):" >> $logs_path$logs_file +} + +kit_log_message() { + local count=2 + local total=$# + local string= + + if [[ ! -f $logs_path$logs_file ]] ; then + kit_log_section + fi + + if [[ $total -eq 0 ]] ; then + echo >> $logs_path$logs_file + else + string=$(fss_extended_write -s -o "$1") + echo -n " $string" >> $logs_path$logs_file + + while [[ $count -le $total ]] ; do + string=$(fss_extended_write -p -s "${!count}") + echo -n "$string" >> $logs_path$logs_file + + let count++ + done + + echo >> $logs_path$logs_file + fi +} + +kit_log_message_raw() { + local total=$# + + if [[ $total -eq 0 ]] ; then + echo >> $logs_path$logs_file + else + echo " $arguments" >> $logs_path$logs_file + fi +} diff --git a/sources/kit-message b/sources/kit-message new file mode 100755 index 0000000..560b129 --- /dev/null +++ b/sources/kit-message @@ -0,0 +1,129 @@ +#!/bin/bash +# provides functions for presenting errors to the screen and logging them. + +kit_message_unset() { + unset kit_message_log + unset kit_message_error + unset kit_message_warning + unset kit_message_highlight + unset kit_message_important + unset kit_message_shell + unset kit_message_operation + unset kit_message + unset kit_message_error_no_log + unset kit_message_warning_no_log + unset kit_message_highlight_no_log + unset kit_message_important_no_log + unset kit_message_help +} + +kit_message_log() { + kit_log_message $1 "$(echo ${@:2} | sed -e 's|\\033\[[[:digit:]];[[:digit:]]*m||g' -e 's|\\033\[[[:digit:]]*m||g')" +} + +kit_message_error() { + echo -e "${c_error}ERROR: $*$c_reset" + + kit_message_log error "$*" +} + +kit_message_warning() { + echo -e "${c_warning}WARNING: $*$c_reset" + + kit_message_log warning "$*" +} + +kit_message_highlight() { + echo -e "$c_highlight$*$c_reset" + + kit_message_log message "$*" +} + +kit_message_important() { + echo -e "$c_important$*$c_reset" + + kit_message_log message "$*" +} + +kit_message_shell() { + if [[ $verbose == "y" ]] ; then + echo -e "$c_important$*$c_reset" + fi + + kit_message_log shell "$*" +} + +kit_message_operation() { + kit_message_log operation "$*" +} + +kit_message() { + echo -e "$*" + + kit_message_log message "$*" +} + +kit_message_error_no_log() { + echo -e "${c_error}ERROR: $*$c_reset" +} + +kit_message_warning_no_log() { + echo -e "${c_warning}WARNING: $*$c_reset" +} + +kit_message_highlight_no_log() { + echo -e "$c_highlight$*$c_reset" +} + +kit_message_important_no_log() { + echo -e "$c_important$*$c_reset" +} + +kit_message_help() { + kit_core_help_title + echo -e "$c_highlight$system_name$c_reset $c_notice<${c_reset}operations$c_notice>$c_reset $c_notice[${c_reset}targets$c_notice]$c_reset $c_notice[${c_reset}options$c_notice]$c_reset" + echo -e " ${c_important}install${c_reset} Add a new package to the system" + echo -e " ${c_important}procedure${c_reset} Process a procedure on the system" + echo -e " ${c_important}alter${c_reset} Upgrade/Downgrade/Reinstall an existing target on the system" + echo -e " ${c_important}uninstall${c_reset} Remove a package from the system" + echo -e " ${c_important}update${c_reset} Obtain the latest information for a given repository" + echo -e " ${c_important}reset${c_reset} Forcibly reset all local changes made to a given repository" + echo + kit_core_help_options + echo -e " -${c_important}u${c_reset}, --${c_important}url${c_reset} Alter url-specific options" + echo -e " -${c_important}d${c_reset}, --${c_important}distribution${c_reset} Alter distribution-specific options" + echo -e " -${c_important}t${c_reset}, --${c_important}target${c_reset} Alter target-specific options" + echo -e " -${c_important}c${c_reset}, --${c_important}cache${c_reset} Local cache directory (i.e: /home/kit/)" + echo -e " -${c_important}r${c_reset}, --${c_important}resume${c_reset} Resume from a previous instance" + echo -e " -${c_important}a${c_reset}, --${c_important}action${c_reset} Specify a specific action, see below" + echo -e " -${c_important}s${c_reset}, --${c_important}settings${c_reset} Change the settings path (i.e: /etc/kit)" + echo -e " -${c_important}v${c_reset}, --${c_important}verbose${c_reset} Display additional information while running" + echo -e " -${c_important}b${c_reset}, --${c_important}installation_base${c_reset} Override the base path of the system" + echo -e " +${c_important}c${c_reset}, ++${c_important}cleanup${c_reset} Do not delete files after execution" + echo + echo -e "${c_highlight}Url Options:$c_reset" + echo -e " ${c_important}git${c_reset} Entire remote repository url (i.e: git://packages.kevux/)" + echo -e " ${c_important}web${c_reset} Entire remote web url (i.e: https://packages.kevux/)" + echo + echo -e "${c_highlight}Distribution Options:$c_reset" + echo -e " ${c_important}name${c_reset} Distribution name (i.e: turtle)" + echo -e " ${c_important}version${c_reset} Distribution version (i.e: 0.9)" + echo -e " ${c_important}flavor${c_reset} Distribution flavor (i.e: core)" + echo -e " ${c_important}branch${c_reset} Distribution flavor branch (i.e: master)" + echo + echo -e "${c_highlight}Target Options:$c_reset" + echo -e " ${c_important}type${c_reset} Specify a type of a target to operate on (i.e: source)" + echo -e " ${c_important}what${c_reset} Specify a group of parts of a target to operate on (i.e: runtime)" + echo -e " ${c_important}huh${c_reset} What part of the target to operate on (i.e: kernel)" + echo -e " ${c_important}oh${c_reset} What sub-part of the target to operate on (i.e: main)" + echo + echo -e "${c_highlight}Action Options for Alter Command:$c_reset" # TODO: consider making these actions available to the procedure operation + echo -e " ${c_important}upgrade${c_reset} Only install the package if it is an newer version (default)" + echo -e " ${c_important}downgrade${c_reset} Only install the package if it is an older version" + echo -e " ${c_important}force${c_reset} Always install the package" + echo + echo -e "${c_highlight}Types of Targets:$c_reset" + echo -e " ${c_important}package${c_reset} Something that can be added, altered, or removed" + echo -e " ${c_important}procedure${c_reset} A series of operations to perform" + echo +} diff --git a/sources/kit-operation b/sources/kit-operation new file mode 100755 index 0000000..3ca7f64 --- /dev/null +++ b/sources/kit-operation @@ -0,0 +1,43 @@ +#!/bin/bash +# This contains all functions shared between the different kit operation scripts. + +kit_operation_unset() { + unset kit_operation_error + unset kit_operation_message + unset kit_operation_format +} + +kit_operation_error() { + if [[ $(kit_core_is_empty $operation) != "" ]] ; then + kit_message_error_no_log "Operation $c_notice$operation$c_error on line #$c_notice$line_number$c_error from '$c_notice$resume_rule_path$resume_rule_file$c_error':$c_reset\n ${c_error}$line" + fi + + kit_message_error "$*" + + cleanup_before_exit + exit -5 +} + +kit_operation_warning() { + if [[ $(kit_core_is_empty $operation) != "" ]] ; then + kit_message_warning_no_log "Operation $c_notice$operation$c_warning on line #$c_notice$line_number$c_warning from '$c_notice$resume_rule_path$resume_rule_file$c_warning':$c_reset\n ${c_warning}$line" + fi + + kit_message_warning "$*" +} + +kit_operation_message() { + kit_log_message message "Now processing line #$line_number of $resume_rule_path$resume_rule_file, $operation operation" + + kit_message_operation "$operation" "$line" +} + +kit_operation_format() { + local operation=$1 + + format=fss_extended + + if [[ $operation == "shell" ]] ; then + format=fss_basic + fi +} diff --git a/sources/kit-operation-access b/sources/kit-operation-access new file mode 100755 index 0000000..bf85ec4 --- /dev/null +++ b/sources/kit-operation-access @@ -0,0 +1,170 @@ +#!/bin/bash +# the access operation saves the access control list variable settings so that the access permission may be applied in subsequent file, directory, or library operations. +# with this operation, file and directory permissions are store in separate variables and only get applied for their appropriate type. +# +# arguments +# type: +# - this designates what category the permission belongs under. +# - can be one of the following: file, directory, both. +# name: +# - this is name used to represent the permission. +# - this is a reference to the actual permissions in the appropriate settings.permissions file either on the local system settings or in the distribution settings. + +kit_operation_access_unset() { + unset kit_operation_access_apply + unset kit_operation_access_resume + unset kit_operation_access +} + +kit_operation_access_apply() { + local type=$1 + local filepath=$2 + local recursive=$(echo "${@:3}" | grep -s -o "\") + local dereference=$(echo "${@:3}" | grep -s -o "\") + local permission= + local filepaths= + local i= + + if [[ $type == "file" ]] ; then + if [[ $permission_access_file == "none" ]] ; then + return + fi + + get_permissions_data access_file "$permission_access_file" + + if [[ $(kit_core_is_empty $permission) == "" ]] ; then + return + fi + + if [[ $(kit_core_is_empty $recursive) == "" ]] ; then + kit_message_shell "chacl $permission $filepath" + chacl $permission $filepath + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Failed to set access '$c_notice$permission$c_error' on the file '$c_notice$filepath$c_error'" + fi + else + kit_message_shell "chacl -R $permission $filepath" + chacl -R $permission $filepath + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Failed to set access '$c_notice$permission$c_error' on the files at '$c_notice$filepath$c_error'" + fi + fi + elif [[ $type == "directory" ]] ; then + if [[ $permission_access_directory == "none" ]] ; then + return + fi + + get_permissions_data access_directory "$permission_access_directory" + + if [[ $(kit_core_is_empty $permission) == "" ]] ; then + return + fi + + if [[ $(kit_core_is_empty $recursive) == "" ]] ; then + kit_message_shell "chacl $permission $filepath" + chacl $permission $filepath + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Failed to set access '$c_notice$permission$c_error' on the directory '$c_notice$filepath$c_error'" + fi + else + kit_message_shell "chacl -R $permission $filepath" + chacl -R $permission $filepath + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Failed to set access '$c_notice$permission$c_error' on the files at '$c_notice$filepath$c_error'" + fi + fi + elif [[ $type == "both" ]] ; then + if [[ $permission_access_file != "none" ]] ; then + get_permissions_data access_file "$permission_access_file" + + if [[ $(kit_core_is_empty $permission) != "" ]] ; then + filepaths=$(find $filepath -type f) + + for i in $filepaths ; do + kit_message_shell "chacl $permission $i" + chacl $permission $i + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Failed to set access '$c_notice$permission$c_error' on the file '$c_notice$i$c_error'" + fi + done + fi + fi + + if [[ $permission_access_directory != "none" ]] ; then + get_permissions_data access_directory "$permission_access_directory" + + if [[ $(kit_core_is_empty $permission) != "" ]] ; then + filepaths=$(find $filepath -type d) + + for i in $filepaths ; do + kit_message_shell "chacl $permission $i" + chacl $permission $i + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Failed to set access '$c_notice$permission$c_error' on the directory '$c_notice$i$c_error'" + fi + done + fi + fi + fi +} + +kit_operation_access_resume() { + local name= + local line= + + if [[ $(fss_basic_read -t -n permission_access_directory $resume_path$resume_file) -gt 0 ]] ; then + line=$(fss_basic_read -n permission_access_directory -c 0 $resume_path$resume_file) + + if [[ $(kit_fss_has_error) != "" ]] ; then + kit_operation_error "Error while processing the access data '${c_notice}permission_access_directory$c_error' from the resume file '$c_notice$resume_path$resume_file$c_error', cannot resume" + fi + + permission_access_directory=$line + fi + + if [[ $(fss_basic_read -t -n permission_access_file $resume_path$resume_file) -gt 0 ]] ; then + line=$(fss_basic_read -n permission_access_file -c 0 $resume_path$resume_file) + + if [[ $(kit_fss_has_error) != "" ]] ; then + kit_operation_error "Error while processing the access data '${c_notice}permission_access_file$c_error' from the resume file '$c_notice$resume_path$resume_file$c_error', cannot resume" + fi + + permission_access_file=$line + fi +} + +kit_operation_access() { + local type= + local name= + + # operation controls + local parent=$parent-$self + local self=operation + + kit_operation_message + + type=$(echo object $line | fss_extended_read -c 0 -s 0) + name=$(echo object $line | fss_extended_read -c 0 -s 1) + + if [[ $type != "file" && $type != "directory" && $type != "both" ]] ; then + kit_operation_error "For the '$c_notice$operation$c_error' operation, the '${c_notice}type$c_error' parameter can only be one of: file, directory, or both" + fi + + if [[ $(kit_core_is_empty $name) == "" ]] ; then + kit_operation_error "The '${c_notice}name$c_error' parameter for the '$c_notice$operation$c_error' operation is missing" + fi + + if [[ $type == "directory" || $type == "both" ]] ; then + permission_access_directory=$name + fi + + if [[ $type == "file" || $type == "both" ]] ; then + permission_access_file=$name + fi +} diff --git a/sources/kit-operation-attribute b/sources/kit-operation-attribute new file mode 100755 index 0000000..fdac298 --- /dev/null +++ b/sources/kit-operation-attribute @@ -0,0 +1,170 @@ +#!/bin/bash +# the attribute operation saves the attribute variable settings so that the file attributes may be applied in subsequent file, directory, or library operations. +# with this operation, file and directory permissions are store in separate variables and only get applied for their appropriate type. +# +# arguments +# type: +# - this designates what category the permission belongs under. +# - can be one of the following: file, directory, both. +# name: +# - this is name used to represent the permission. +# - this is a reference to the actual permissions in the appropriate settings.permissions file either on the local system settings or in the distribution settings. + +kit_operation_attribute_unset() { + unset kit_operation_attribute_apply + unset kit_operation_attribute_resume + unset kit_operation_attribute +} + +kit_operation_attribute_apply() { + local type=$1 + local filepath=$2 + local recursive=$(echo "${@:3}" | grep -s -o "\") + local dereference=$(echo "${@:3}" | grep -s -o "\") + local permission= + local filepaths= + local i= + + if [[ $type == "file" ]] ; then + if [[ $permission_attribute_file == "none" ]] ; then + return + fi + + kit_permission_get attr_file "$permission_attribute_file" + + if [[ $(kit_core_is_empty $permission) == "" ]] ; then + return + fi + + if [[ $(kit_core_is_empty $recursive) == "" ]] ; then + kit_message_shell "chattr $permission $filepath" + chattr $permission $filepath + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Failed to set attributes '$c_notice$permission$c_error' on the file '$c_notice$filepath$c_error'" + fi + else + kit_message_shell "chattr -R $permission $filepath" + chattr -R $permission $filepath + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Failed to set attributes '$c_notice$permission$c_error' on the files at '$c_notice$filepath$c_error'" + fi + fi + elif [[ $type == "directory" ]] ; then + if [[ $permission_attribute_directory == "none" ]] ; then + return + fi + + kit_permission_get attr_directory "$permission_attribute_directory" + + if [[ $(kit_core_is_empty $permission) == "" ]] ; then + return + fi + + if [[ $(kit_core_is_empty $recursive) == "" ]] ; then + kit_message_shell "chattr $permission $filepath" + chattr $permission $filepath + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Failed to set attributes '$c_notice$permission$c_error' on the directory '$c_notice$filepath$c_error'" + fi + else + kit_message_shell "chattr -R $permission $filepath" + chattr -R $permission $filepath + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Failed to set attributes '$c_notice$permission$c_error' on the files at '$c_notice$filepath$c_error'" + fi + fi + elif [[ $type == "both" ]] ; then + if [[ $permission_attribute_file != "none" ]] ; then + kit_permission_get attr_file "$permission_attribute_file" + + if [[ $(kit_core_is_empty $permission) != "" ]] ; then + filepaths=$(find $filepath -type f) + + for i in $filepaths ; do + kit_message_shell "chattr $permission $i" + chattr $permission $i + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Failed to set attributes '$c_notice$permission$c_error' on the file '$c_notice$i$c_error'" + fi + done + fi + fi + + if [[ $permission_attribute_directory != "none" ]] ; then + kit_permission_get attr_directory "$permission_attribute_directory" + + if [[ $(kit_core_is_empty $permission) != "" ]] ; then + filepaths=$(find $filepath -type d) + + for i in $filepaths ; do + kit_message_shell "chattr $permission $i" + chattr $permission $i + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Failed to set attributes '$c_notice$permission$c_error' on the directory '$c_notice$i$c_error'" + fi + done + fi + fi + fi +} + +kit_operation_attribute_resume() { + local name= + local line= + + if [[ $(fss_basic_read -t -n permission_attribute_directory $resume_path$resume_file) -gt 0 ]] ; then + line=$(fss_basic_read -n permission_attribute_directory -c 0 $resume_path$resume_file) + + if [[ $(kit_fss_has_error) != "" ]] ; then + kit_operation_error "Error while processing the attribute data '${c_notice}permission_attribute_directory$c_error' from the resume file '$c_notice$resume_path$resume_file$c_error', cannot resume" + fi + + permission_attribute_directory=$line + fi + + if [[ $(fss_basic_read -t -n permission_attribute_file $resume_path$resume_file) -gt 0 ]] ; then + line=$(fss_basic_read -n permission_attribute_file -c 0 $resume_path$resume_file) + + if [[ $(kit_fss_has_error) != "" ]] ; then + kit_operation_error "Error while processing the attribute data '${c_notice}permission_attribute_file$c_error' from the resume file '$c_notice$resume_path$resume_file$c_error', cannot resume" + fi + + permission_attribute_file=$line + fi +} + +kit_operation_attribute() { + local type= + local name= + + # operation controls + local parent=$parent-$self + local self=operation + + kit_operation_message + + type=$(echo object $line | fss_extended_read -c 0 -s 0) + name=$(echo object $line | fss_extended_read -c 0 -s 1) + + if [[ $type != "file" && $type != "directory" && $type != "both" ]] ; then + kit_operation_error "For the '$c_notice$operation$c_error' operation, the '${c_notice}type$c_error' parameter can only be one of: file, directory, or both" + fi + + if [[ $(kit_core_is_empty $name) == "" ]] ; then + kit_operation_error "The '${c_notice}name$c_error' parameter for the '$c_notice$operation$c_error' operation is missing" + fi + + if [[ $type == "directory" || $type == "both" ]] ; then + permission_attribute_directory=$name + fi + + if [[ $type == "file" || $type == "both" ]] ; then + permission_attribute_file=$name + fi +} diff --git a/sources/kit-operation-directory b/sources/kit-operation-directory new file mode 100755 index 0000000..6fa23ea --- /dev/null +++ b/sources/kit-operation-directory @@ -0,0 +1,112 @@ +#!/bin/bash +# There are different variants of the file operation: directory, directory_dereference. +# +# Operation 'directory': +# - Installs a file without any special considerations. +# - This will install symbolic links as symbolic links. +# +# Operation 'directory_dereference': +# - Installs a directory, but dereferences all symbolic links, so symbolic links do not get copied and instead the actual files get copied. +# +# Arguments: +# name: +# - the name of the directory to install. +# - this is the name the directory is installed as. +# destination: +# - the directory name in which the directory will be installed to. +# source (conditionally optional): +# - if omitted, then the directory is created an not copied. +# - can only be ommitted for directory operation. +# - this is either the source directory or source file. +# - if it is a directory, then the file name is derived from the name argument above. +# source_name (optional): +# - The name of the directory in the source path if the name the directory is installed as is different than it is copied from. + +kit_operation_directory_unset() { + unset kit_operation_directory +} + +kit_operation_directory() { + local name= + local destination= + local source= + local source_name= + local library_source= + local library_medium= + local filepath= + local dereference= + + # operation controls + local parent=$parent-$self + local self=operation + + kit_operation_message + + name=$(echo object $line | fss_extended_read -c 0 -s 0) + destination=$(echo object $line | fss_extended_read -c 0 -s 1) + source=$(echo object $line | fss_extended_read -c 0 -s 2) + source_name=$(echo object $line | fss_extended_read -c 0 -s 3) + + if [[ $(kit_core_is_empty $name) == "" ]] ; then + kit_operation_error "Missing file name" + fi + + if [[ $(kit_core_is_empty $destination) == "" ]] ; then + kit_operation_error "Missing destination path" + fi + + destination=$(echo $destination | sed -e 's|/*$|/|' -e 's|/*$|/|') + + if [[ $operation == "directory_dereference" ]] ; then + dereference="dereference" + fi + + if [[ $(kit_core_is_empty $source) == "" ]] ; then + if [[ ! -f $installation_base$destination$name ]] ; then + kit_message_shell "mkdir -p $installation_base$destination$name" + mkdir -p $installation_base$destination$name + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Failed to create the directory '$c_notice$installation_base$destination$name$c_error'" + fi + + kit_operation_attribute_apply directory "$installation_base$destination$name" $dereference + kit_operation_group_apply "$installation_base$destination$name" $dereference + kit_operation_mode_apply directory "$installation_base$destination$name" $dereference + #kit_operation_access_apply directory "$installation_base$destination$name" $dereference + fi + else + source=$(echo $source | sed -e 's|/*$|/|' -e 's|/*$|/|') + + if [[ $(kit_core_is_empty $source_name) == "" ]] ; then + filepath=$source + else + filepath=$source$source_name + fi + + if [[ ! -d $filepath ]] ; then + kit_operation_error "Directory path '$c_notice$filepath$c_error' is not a valid directory" + fi + + kit_operation_attribute_apply both "$installation_base$filepath" $dereference + kit_operation_group_apply "$installation_base$filepath" $dereference + kit_operation_mode_apply both "$installation_base$filepath" $dereference + #kit_operation_access_apply both "$installation_base$filepath" $dereference + + if [[ $operation == "directory" ]] ; then + kit_message_shell "cp -faR $filepath $installation_base$destination$name" + cp -faR $filepath $installation_base$destination$name + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Failed to install the directory '$c_notice$filepath$c_error' to '$c_notice$installation_base$destination$name$c_error'" + fi + elif [[ $operation == "directory_dereference" ]] ; then + kit_message_shell "cp -faLR $filepath $installation_base$destination$name" + cp -faLR $filepath $installation_base$destination$name + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Failed to install the directory '$c_notice$filepath$c_error' to '$c_notice$installation_base$destination$name$c_error'" + fi + fi + fi +} diff --git a/sources/kit-operation-file b/sources/kit-operation-file new file mode 100755 index 0000000..3fd76a1 --- /dev/null +++ b/sources/kit-operation-file @@ -0,0 +1,156 @@ +#!/bin/bash +# There are different variants of the file operation: file, file_dereference, file_safe, file_new, file_new_dereference, executable, executable_dereference, and executable_safe. +# +# Operation 'file': +# - Installs a file without any special considerations. +# - This will install symbolic links as symbolic links. +# +# Operation 'file_new': +# - Identical to operation file, except files are only copied if a file does not already exist at the destination path. +# +# Operation 'file_dereference': +# - Installs a file, but dereferences all symbolic links, so symbolic links do not get copied and instead the actual files get copied. +# +# Operation 'file_new_dereference': +# - Identical to operation file_dereference, except files are only copied if a file does not already exist at the destination path. +# +# Operation 'file_safe': +# - Installs a file, but a backup is made. +# - This must and only should be used for files that are being used by the installer. +# - This prevents the installer from crashing when the installer or files used by the installer get replaced during the runtime of the installer. +# +# Operations 'executable', 'executable_dereference', 'executable_safe': +# - These are identical to the file equivalents, except they conditionally get stripped. +# +# Arguments: +# name: +# - the name of the file to install. +# - this is the name the file is installed as. +# destination: +# - the directory name in which the file will be installed to. +# source (conditionally optional): +# - if omitted, then the file is created and not copied. +# - can only be ommitted for file operation. +# - this is either the source directory or source file. +# - if it is a directory, then the file name is derived from the name argument above. + +kit_operation_file_unset() { + unset kit_operation_file +} + +kit_operation_file() { + local name= + local destination= + local source= + local library_source= + local library_medium= + local filepath= + local dereference= + + # operation controls + local parent=$parent-$self + local self=operation + + kit_operation_message + + name=$(echo object $line | fss_extended_read -c 0 -s 0) + destination=$(echo object $line | fss_extended_read -c 0 -s 1) + source=$(echo object $line | fss_extended_read -c 0 -s 2) + + if [[ $(kit_core_is_empty $name) == "" ]] ; then + kit_operation_error "Missing file name" + fi + + if [[ $(kit_core_is_empty $destination) == "" ]] ; then + kit_operation_error "Missing destination path" + fi + + destination=$(echo $destination | sed -e 's|/*$|/|' -e 's|/*$|/|') + + if [[ ! -d $destination ]] ; then + kit_operation_error "Destination path '$c_notice$destination$c_error' is not a valid directory" + fi + + if [[ $operation == "file_dereference" || $operation == "executable_dereference" ]] ; then + dereference="dereference" + fi + + if [[ $(kit_core_is_empty $source) == "" ]] ; then + if [[ $operation == "file_dereference" || $operation == "file_new_dereference" || $operation == "file_safe" || $operation == "executable" || $operation == "executable_dereference" || $operation == "executable_safe" ]] ; then + kit_operation_error "Cannot use the '$c_notice$operation$c_error' operation without specifying a source file" + fi + + if [[ ! -f $installation_base$destination$name ]] ; then + kit_message_shell "touch $installation_base$destination$name" + touch $installation_base$destination$name + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Failed to create the file '$c_notice$installation_base$destination$name$c_error'" + fi + + kit_operation_attribute_apply file "$installation_base$destination$name" $dereference + kit_operation_group_apply "$installation_base$destination$name" $dereference + kit_operation_mode_apply file "$installation_base$destination$name" $dereference + #kit_operation_access_apply file "$installation_base$destination$name" $dereference + fi + else + if [[ -d $source ]] ; then + source=$(echo $source | sed -e 's|/*$|/|' -e 's|/*$|/|') + filepath=$source$name + else + filepath=$source + fi + + if [[ ! -f $filepath ]] ; then + kit_operation_error "Source path '$c_notice$filepath$c_error' is not a valid filepath" + fi + + # do nothing if file already exists for *_new commands + if [[ $operation == "file_new" || $operation == "file_new_dereference" ]] ; then + if [[ -f "$installation_base$destination$name" ]] ; then + return + fi + fi + + if [[ $operation == "executable" || $operation == "executable_dereference" || $operation == "executable_safe" ]] ; then + kit_operation_strip_apply executable "$filepath" + fi + + kit_operation_attribute_apply file "$installation_base$filepath" $dereference + kit_operation_group_apply "$installation_base$filepath" $dereference + kit_operation_mode_apply file "$installation_base$filepath" $dereference + #kit_operation_access_apply both "$installation_base$filepath" $dereference + + if [[ $operation == "file" || $operation == "file_new" || $operation == "executable" ]] ; then + kit_message_shell "cp -fa $filepath $installation_base$destination$name" + cp -fa $filepath $installation_base$destination$name + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Failed to install the file '$c_notice$filepath$c_error' to '$c_notice$installation_base$destination$name$c_error'" + fi + elif [[ $operation == "file_dereference" || $operation == "file_new_dereference" || $operation == "executable_dereference" ]] ; then + kit_message_shell "cp -faLf $filepath $installation_base$destination$name" + cp -faLf $filepath $installation_base$destination$name + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Failed to install the file '$c_notice$filepath$c_error' to '$c_notice$installation_base$destination$name$c_error'" + fi + elif [[ $operation == "file_safe" || $operation == "executable_safe" ]] ; then + kit_message_shell "cp -fa --backup=simple --suffix=~ $filepath $installation_base$destination$name" + cp -fa --backup=simple --suffix=~ $filepath $installation_base$destination$name + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Failed to install the file '$c_notice$filepath$c_error' to '$c_notice$installation_base$destination$name$c_error'" + fi + + if [[ -f $installation_base$part2$part1${part3}~ ]] ; then + kit_message_shell "rm -f $installation_base$destination$name~" + rm -f $installation_base$destination$name~ + + if [[ $? -ne 0 ]] ; then + kit_operation_warning "Failed to remove the backup file '$c_notice$installation_base$destination$name~$c_error'" + fi + fi + fi + fi +} diff --git a/sources/kit-operation-group b/sources/kit-operation-group new file mode 100755 index 0000000..7c1e166 --- /dev/null +++ b/sources/kit-operation-group @@ -0,0 +1,100 @@ +#!/bin/bash +# the group operation saves the group variable settings so that the group may be applied in subsequent file, directory, or library operations. +# +# arguments +# type: +# - this designates what category the permission belongs under. +# - this is a reference to the list object name in the appropriate settings.permissions file either on the local system settings or in the distribution settings. +# name: +# - this is name used to represent the permission. +# - this is a reference to the actual permissions in the appropriate settings.permissions file either on the local system settings or in the distribution settings. + +kit_operation_group_unset() { + unset kit_operation_group_apply + unset kit_operation_group_resume + unset kit_operation_group +} + +kit_operation_group_apply() { + local filepath=$1 + local recursive=$(echo "${@:2}" | grep -s -o "\") + local dereference=$(echo "${@:2}" | grep -s -o "\") + local permission= + + if [[ $permission_group_type == "none" ]] ; then + return + fi + + kit_permission_get "$permission_group_type" "$permission_group_name" + + if [[ $(kit_core_is_empty $permission) == "" ]] ; then + return + fi + + if [[ $(kit_core_is_empty $recursive) == "" ]] ; then + kit_message_shell "chgrp $permission $filepath" + chgrp $permission $filepath + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Failed to set group '$c_notice$permission$c_error' on the file '$c_notice$filepath$c_error'" + fi + else + kit_message_shell "chgrp -R $permission $filepath" + chgrp -R $permission $filepath + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Failed to set group '$c_notice$permission$c_error' on the files at '$c_notice$filepath$c_error'" + fi + fi +} + +kit_operation_group_resume() { + local name= + local line= + + if [[ $(fss_basic_read -t -n permission_group_type $resume_path$resume_file) -gt 0 ]] ; then + line=$(fss_basic_read -n permission_group_type -c 0 $resume_path$resume_file) + + if [[ $(kit_fss_has_error) != "" ]] ; then + kit_operation_error "Error while processing the group data '${c_notice}permission_group_type$c_error' from the resume file '$c_notice$resume_path$resume_file$c_error', cannot resume" + fi + + permission_group_type=$line + fi + + if [[ $(fss_basic_read -t -n permission_group_name $resume_path$resume_file) -gt 0 ]] ; then + line=$(fss_basic_read -n permission_group_name -c 0 $resume_path$resume_file) + + if [[ $(kit_fss_has_error) != "" ]] ; then + kit_operation_error "Error while processing the group data '${c_notice}permission_group_name$c_error' from the resume file '$c_notice$resume_path$resume_file$c_error', cannot resume" + fi + + permission_group_name=$line + fi +} + +kit_operation_group() { + local type= + local name= + + # operation controls + local parent=$parent-$self + local self=operation + + kit_operation_message + + type=$(echo object $line | fss_extended_read -c 0 -s 0) + name=$(echo object $line | fss_extended_read -c 0 -s 1) + + + if [[ $(kit_core_is_empty $type) == "" ]] ; then + kit_operation_error "The '${c_notice}type$c_error' parameter for the '$c_notice$operation$c_error' operation is missing" + fi + + if [[ $(kit_core_is_empty $name) == "" ]] ; then + kit_operation_error "The '${c_notice}name$c_error' parameter for the '$c_notice$operation$c_error' operation is missing" + fi + + permission_group_type=$type + permission_group_name=$name +} diff --git a/sources/kit-operation-if b/sources/kit-operation-if new file mode 100755 index 0000000..68d1cef --- /dev/null +++ b/sources/kit-operation-if @@ -0,0 +1,116 @@ +#!/bin/bash +# the if operation performs simple/primitive tests and executes (or not) operations in its block. +# supplies non-complex and non-nested if conditions with blocks of operations that will only be executed when the condition succeeds. +# +# type values: +# - is: perform a comparison against the value of some variable. +# - like: perform comparison against the value of some variable, using regex. TODO: pcre? grep? +# - end: terminate an if block. +# +# arguments +# type: +# - this is the type of if condition +# name: +# - if the type is 'compare', then this represents the unexpanded variable name. +# - not used for 'end' type. +# value: +# - the value or regex to compare against. +# - not used for 'end' type. + +kit_operation_if_unset() { + unset kit_operation_if_resume + unset kit_operation_if +} + +kit_operation_if_resume() { + local type= + local condition= + + if [[ $(fss_basic_read -t -n if_condition $resume_path$resume_file) -gt 0 ]] ; then + condition=$(fss_basic_read -n if_condition -c 0 $resume_path$resume_file) + + if [[ $(kit_fss_has_error) != "" ]] ; then + kit_operation_error "Error while processing the if data '${c_notice}if_condition$c_error' from the resume file '$c_notice$resume_path$resume_file$c_error', cannot resume" + fi + + if_condition=$condition + fi +} + +kit_operation_if() { + local type= + local name= + local l_value= + local r_value= + local safe_object= + local safe_content= + local position= + + # operation controls + local parent=$parent-$self + local self=operation + + kit_operation_message + + # TODO: if if_condition is already set, present error then return + + type=$(echo object $line | fss_extended_read -c 0 -s 0) + name=$(echo object $line | fss_extended_read -c 0 -s 1) + r_value=$(echo object $line | fss_extended_read -c 0 -s 2) + + if [[ $(kit_core_is_empty $type) == "" ]] ; then + kit_operation_error "The '${c_notice}type$c_error' parameter for the '$c_notice$operation$c_error' operation is missing" + fi + + if [[ $type == "is" ]] ; then + if [[ $(kit_core_is_empty $name) == "" ]] ; then + kit_operation_error "The '${c_notice}name$c_error' parameter for the '$c_notice$operation$c_error' operation is missing" + fi + + position=$(kit_reserved_is $name) + + if [[ $(kit_core_is_empty $position) == "" ]] ; then + position=$(kit_dynamic_is $name) + + if [[ $(kit_core_is_empty $position) == "" ]] ; then + position=$(kit_permission_is $name) + + if [[ $(kit_core_is_empty $position) == "" ]] ; then + l_value= + # TODO: if variable does not exist, print error and return. + else + kit_permission_get $name + l_value=$reserved + fi + else + kit_dynamic_get $name + l_value=$reserved + fi + # TODO: also check for non-reserved variables. + else + kit_reserved_get $name + l_value=$reserved + fi + + if [[ $l_value == $r_value ]] ; then + if_condition=true + else + if_condition=false + fi + + sed -i -e '/^[[:space:]]*if_condition\>[[:space:]]*/d' $resume_path$resume_file + + safe_object=$(fss_extended_write -s -o "if_condition") + safe_content=$(fss_extended_write -s -p "$if_condition") + echo "$safe_object$safe_content" >> $resume_path$resume_file + + # TODO: implement $type == "like" + #elif [[ $type == "like" ]] ; then + elif [[ $type == "end" ]] ; then + sed -i -e '/^[[:space:]]*if_condition\>[[:space:]]*/d' $resume_path$resume_file + + if_condition= + else + kit_operation_error "'$c_notice$type$c_error' is not a supported value for the '${c_notice}type$c_error' parameter for the '$c_notice$operation$c_error' operation" + fi +} diff --git a/sources/kit-operation-library b/sources/kit-operation-library new file mode 100755 index 0000000..ae51d9d --- /dev/null +++ b/sources/kit-operation-library @@ -0,0 +1,140 @@ +#!/bin/bash +# the library operation installs a library file. +# while installing, it handles stripping, settings permissions, and even symbolic linkage for shared libraries. +# +# arguments: +# type: +# - the type of the library to install, can be: static, dynamic, or binutils +# - binutils: the non-standard dynamic library that is common amongst a handfull of the older GNU projects. +# - dynamic: standard shared library, produces 3 files, for eample: libexample.so, libexample.so.1, libexample.so.1.0.0. +# - static: standard static library, ends in .a, for example: libexample.a. +# - module: a dynamic library whose naming system is commonly used for dynamic loaded modules, for example: example.so. +# name: +# - the name of the library, without extensions, such as 'libexample' (as opposed to 'libexample.so' or 'libexample.a'). +# - this is the name the library is installed as. +# destination: +# - this is the destination path. +# - this must be a directory and not a file. +# source: +# - this is either the source directory or source file. +# - if it is a directory, then the file name is derived from the name argument above. +# + +kit_operation_library_unset() { + unset kit_operation_library +} + +kit_operation_library() { + local type= + local name= + local destination= + local source= + local library_source= + local library_medium= + + # operation controls + local parent=$parent-$self + local self=operation + + kit_operation_message + + type=$(echo object $line | fss_extended_read -c 0 -s 0) + name=$(echo object $line | fss_extended_read -c 0 -s 1) + destination=$(echo object $line | fss_extended_read -c 0 -s 2) + source=$(echo object $line | fss_extended_read -c 0 -s 3) + + if [[ $type != "static" && $type != "dynamic" && $type != "module" && $type != "binutils" ]] ; then + kit_operation_error "Invalid type, must be one of: static, dynamic, module, or binutils" + fi + + if [[ $(kit_core_is_empty $name) == "" ]] ; then + kit_operation_error "Missing library name" + fi + + if [[ $(kit_core_is_empty $destination) == "" ]] ; then + kit_operation_error "Missing destination path" + fi + + if [[ $(kit_core_is_empty $source) == "" ]] ; then + kit_operation_error "Missing source path" + fi + + destination=$(echo $destination | sed -e 's|/*$|/|' -e 's|/*$|/|') + source=$(echo $source | sed -e 's|/*$|/|' -e 's|/*$|/|') + + if [[ ! -d $destination ]] ; then + kit_operation_error "Destination path '$c_notice$destination$c_error' is not a valid directory" + fi + + if [[ ! -d $source ]] ; then + kit_operation_error "Source path '$c_notice$source$c_error' is not a valid directory" + fi + + if [[ $type == "static" ]] ; then + library_source="${name}.a" + elif [[ $type == "dynamic" ]] ; then + library_source=$(find $source -maxdepth 1 -name "${name}.so*" -type f | line) + + if [[ $(kit_core_is_empty $library_source) == "" ]] ; then + kit_operation_error "Failed to find the library '$c_notice$source${name}.so$c_error'" + fi + + library_medium=$(echo $library_source | grep -s -o "${name}\.so\.[^.]*") + library_source=$(echo $library_source | grep -s -o "${name}\.so\..*$") + elif [[ $type == "module" ]] ; then + library_source="${name}.so" + + if [[ ! -f $source$library_source ]] ; then + kit_operation_error "Failed to find the library '$c_notice$source$library_source$c_error'" + fi + elif [[ $type == "binutils" ]] ; then + library_source=$(find $source -maxdepth 1 -name "${name}-${package_version}.so" -type f | line) + + if [[ $(kit_core_is_empty $library_source) == "" ]] ; then + kit_operation_error "Failed to find the library '$c_notice$source${name}-${package_version}.so$c_error'" + fi + + library_source="${name}-${package_version}.so" + fi + + kit_operation_strip_apply library "$source$library_source" + kit_operation_attribute_apply file "$source$library_source" + kit_operation_group_apply "$source$library_source" + kit_operation_mode_apply file "$source$library_source" + #kit_operation_access_apply file "$source$library_source" + + kit_message_shell "cp --backup=simple --suffix=~ -a $source$library_source $installation_base$destination" + cp --backup=simple --suffix=~ -a $source$library_source $installation_base$destination + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Failed to copy the library '$c_notice$source$library_source$c_error' to '$c_notice$installation_base$destination$c_error'" + fi + + if [[ -f $installation_base$destination${library_source}~ ]] ; then + kit_message_shell "rm -f $installation_base$destination${library_source}~" + rm -f $installation_base$destination${library_source}~ + fi + + if [[ $type == "dynamic" ]] ; then + kit_message_shell "ln -sf $library_source $installation_base$destination${library_medium}" + ln -sf $library_source $installation_base$destination${library_medium} + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Failed to create a symbolic link of '$c_notice$library_medium$c_error' to '$c_notice$library_source$c_error' at the path '$c_notice$installation_base$destination$c_error'" + fi + + kit_message_shell "ln -sf $library_medium $installation_base$destination${name}.so" + ln -sf $library_medium $installation_base$destination${name}.so + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Failed to create a symbolic link of '$c_notice${name}.so$c_error' to '$c_notice$library_medium$c_error' at the path '$c_notice$installation_base$destination$c_error'" + fi + elif [[ $type == "binutils" ]] ; then + kit_message_shell "ln -sf $library_source $installation_base$destination${name}.so" + ln -sf $library_source $installation_base$destination${name}.so + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Failed to create a symbolic link of '$c_notice${name}.so$c_error' to '$c_notice$library_source$c_error' at the path '$c_notice$installation_base$destination$c_error'" + fi + fi +} diff --git a/sources/kit-operation-mode b/sources/kit-operation-mode new file mode 100755 index 0000000..bb14b64 --- /dev/null +++ b/sources/kit-operation-mode @@ -0,0 +1,169 @@ +#!/bin/bash +# the mode operation saves the mode variable settings so that the file mode may be applied in subsequent file, directory, or library operations. +# with this operation, file and directory permissions are store in separate variables and only get applied for their appropriate type. +# +# arguments +# type: +# - this designates what category the permission belongs under. +# - can be one of the following: file, directory, both. +# name: +# - this is name used to represent the permission. +# - this is a reference to the actual permissions in the appropriate settings.permissions file either on the local system settings or in the distribution settings. + +kit_operation_mode_unset() { + unset kit_operation_mode_apply + unset kit_operation_mode_resume + unset kit_operation_mode +} + +kit_operation_mode_apply() { + local type=$1 + local filepath=$2 + local recursive=$3 + local permission= + local filepaths= + local i= + + if [[ $type == "file" ]] ; then + if [[ $permission_mode_file == "none" ]] ; then + return + fi + + kit_permission_get mode_file "$permission_mode_file" + + if [[ $(kit_core_is_empty $permission) == "" ]] ; then + return + fi + + if [[ $(kit_core_is_empty $recursive) == "" ]] ; then + kit_message_shell "chmod $permission $filepath" + chmod $permission $filepath + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Failed to set mode '$c_notice$permission$c_error' on the file '$c_notice$filepath$c_error'" + fi + else + kit_message_shell "chmod -R $permission $filepath" + chmod -R $permission $filepath + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Failed to set mode '$c_notice$permission$c_error' on the files at '$c_notice$filepath$c_error'" + fi + fi + elif [[ $type == "directory" ]] ; then + if [[ $permission_mode_directory == "none" ]] ; then + return + fi + + kit_permission_get mode_directory "$permission_mode_directory" + + if [[ $(kit_core_is_empty $permission) == "" ]] ; then + return + fi + + if [[ $(kit_core_is_empty $recursive) == "" ]] ; then + kit_message_shell "chmod $permission $filepath" + chmod $permission $filepath + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Failed to set mode '$c_notice$permission$c_error' on the directory '$c_notice$filepath$c_error'" + fi + else + kit_message_shell "chmod -R $permission $filepath" + chmod -R $permission $filepath + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Failed to set mode '$c_notice$permission$c_error' on the files at '$c_notice$filepath$c_error'" + fi + fi + elif [[ $type == "both" ]] ; then + if [[ $permission_mode_file != "none" ]] ; then + kit_permission_get mode_file "$permission_mode_file" + + if [[ $(kit_core_is_empty $permission) != "" ]] ; then + filepaths=$(find $filepath -type f) + + for i in $filepaths ; do + kit_message_shell "chmod $permission $i" + chmod $permission $i + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Failed to set mode '$c_notice$permission$c_error' on the file '$c_notice$i$c_error'" + fi + done + fi + fi + + if [[ $permission_mode_directory != "none" ]] ; then + kit_permission_get mode_directory "$permission_mode_directory" + + if [[ $(kit_core_is_empty $permission) != "" ]] ; then + filepaths=$(find $filepath -type d) + + for i in $filepaths ; do + kit_message_shell "chmod $permission $i" + chmod $permission $i + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Failed to set mode '$c_notice$permission$c_error' on the directory '$c_notice$i$c_error'" + fi + done + fi + fi + fi +} + +kit_operation_mode_resume() { + local name= + local line= + + if [[ $(fss_basic_read -t -n permission_mode_directory $resume_path$resume_file) -gt 0 ]] ; then + line=$(fss_basic_read -n permission_mode_directory -c 0 $resume_path$resume_file) + + if [[ $(kit_fss_has_error) != "" ]] ; then + kit_operation_error "Error while processing the mode data '${c_notice}permission_mode_directory$c_error' from the resume file '$c_notice$resume_path$resume_file$c_error', cannot resume" + fi + + permission_mode_directory=$line + fi + + if [[ $(fss_basic_read -t -n permission_mode_file $resume_path$resume_file) -gt 0 ]] ; then + line=$(fss_basic_read -n permission_mode_file -c 0 $resume_path$resume_file) + + if [[ $(kit_fss_has_error) != "" ]] ; then + kit_operation_error "Error while processing the mode data '${c_notice}permission_mode_file$c_error' from the resume file '$c_notice$resume_path$resume_file$c_error', cannot resume" + fi + + permission_mode_file=$line + fi +} + +kit_operation_mode() { + local type= + local name= + + # operation controls + local parent=$parent-$self + local self=operation + + kit_operation_message + + type=$(echo object $line | fss_extended_read -c 0 -s 0) + name=$(echo object $line | fss_extended_read -c 0 -s 1) + + if [[ $type != "file" && $type != "directory" && $type != "both" ]] ; then + kit_operation_error "For the '$c_notice$operation$c_error' operation, the '${c_notice}type$c_error' parameter can only be one of: file, directory, or both" + fi + + if [[ $(kit_core_is_empty $name) == "" ]] ; then + kit_operation_error "The '${c_notice}name$c_error' parameter for the '$c_notice$operation$c_error' operation is missing" + fi + + if [[ $type == "directory" || $type == "both" ]] ; then + permission_mode_directory=$name + fi + + if [[ $type == "file" || $type == "both" ]] ; then + permission_mode_file=$name + fi +} diff --git a/sources/kit-operation-path b/sources/kit-operation-path new file mode 100755 index 0000000..6b49442 --- /dev/null +++ b/sources/kit-operation-path @@ -0,0 +1,97 @@ +#!/bin/bash +# the path operation is used to perform a directory change operation while processing a script. +# this is better than doing cd directly because if the script is every stopped and resumed later, this state will be reset. +# the path operation is always relative to the source or binary directory. +# +# arguments: +# path (optional): +# - when defined, this is the path to change to, previous path will be reset. +# +# if no arguments are specified, then the resume path is reset and directory is changed to the original source or binary directory. + +kit_operation_path_unset() { + unset kit_operation_path + unset kit_operation_path_resume +} + +kit_operation_path() { + local part= + local temporary= + + # operation controls + local parent=$parent-$self + local self=operation + + kit_operation_message + + part=$(echo object $line | fss_extended_read -c 0 -s 0) + + if [[ $(kit_fss_has_error) != "" ]] ; then + kit_operation_error "Failed to process the '$c_notice$operation$c_error' operation data" + fi + + if [[ $(kit_core_is_empty $part) == "" ]] ; then + if [[ $(kit_core_is_empty $path_previous) == "" ]] ; then + kit_operation_error "The original path is not properly defined, cannot reset path" + fi + + kit_message_shell "cd $path_previous" + cd $path_previous + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Failed to go to the path '$c_notice$path_previous$c_error', cannot reset path" + fi + + sed -i -e '/^[[:space:]]*path_original\>[[:space:]]*/d' $resume_path$resume_file + sed -i -e '/^[[:space:]]*path_current\>[[:space:]]*/d' $resume_path$resume_file + + path_current=$PWD + else + if [[ ! -d $part ]] ; then + kit_operation_error "The path '$c_notice$part$c_error' is not a valid directory" + fi + + kit_message_shell "cd $path_previous" + cd "$path_previous" + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Failed to go to the path '$c_notice$path_previous$c_error', cannot reset path" + fi + + sed -i -e '/^[[:space:]]*path_original\>[[:space:]]*/d' $resume_path$resume_file + temporary=$(fss_extended_write -s -p "$path_previous") + echo "$(fss_extended_write -s -o path_original)$temporary" >> $resume_path$resume_file + + kit_message_shell "cd $part" + cd $part + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Failed to go to the path '$c_notice$part$c_error'" + fi + + path_current=$PWD + temporary=$(fss_extended_write -s -p "$path_current") + + sed -i -e '/^[[:space:]]*path_current\>[[:space:]]*/d' $resume_path$resume_file + echo "$(fss_extended_write -s -o path_current)$temporary" >> $resume_path$resume_file + fi +} + +kit_operation_path_resume() { + path_current=$path_previous + + if [[ $(fss_extended_read -n path_current -t $resume_path$resume_file) -gt 0 ]] ; then + path_current=$(fss_extended_read -n path_current -c 0 -s 0 $resume_path$resume_file) + + if [[ $(kit_fss_has_error) != "" || ! -d $path_current ]] ; then + kit_operation_error "The current path '$c_notice$path_current$c_error' as specified in the resume file '$c_notice$resume_path$resume_file$c_error' is not a valid directory, cannot resume" + fi + + kit_message_shell "cd $path_current" + cd $path_current + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Failed to go to the path '$c_notice$path_current$c_error', cannot resume" + fi + fi +} diff --git a/sources/kit-operation-shell b/sources/kit-operation-shell new file mode 100755 index 0000000..80e7bd4 --- /dev/null +++ b/sources/kit-operation-shell @@ -0,0 +1,32 @@ +#!/bin/bash +# this performs a shell command. +# a shell command is a powerful and very flexible operation, but is also potentially dangereous. +# whenever there is a non-shell operation equivalent, it is safer and better to use those instead. +# +# future versions will have a shell_safe operation that will execute the specified command as a non-root user, reducing the risks of this operation. +# +# unlike all of the previous commands, the shell command uses fss-0000 (basic) format, which does not accept individual arguments, but instead takes the entire content as is. + +kit_operation_shell_unset() { + unset kit_operation_shell +} + +kit_operation_shell() { + + # operation controls + local parent=$parent-$self + local self=operation + + kit_operation_message + + if [[ $(kit_core_is_empty $line) == "" ]] ; then + kit_operation_error "No shell command given" + fi + + kit_message_shell "$line" + eval $line + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Something went wrong while executing the shell command" + fi +} diff --git a/sources/kit-operation-strip b/sources/kit-operation-strip new file mode 100755 index 0000000..67b944a --- /dev/null +++ b/sources/kit-operation-strip @@ -0,0 +1,100 @@ +#!/bin/bash +# the strip operation removes debugging information from executables and libraries. +# the executable and library operations already perform strips, so this is only needed if strip is explicitly needed. +# +# arguments: +# filetype: +# - the type of file to strip, either executable or library. +# filepath/directory: +# - if this is a filepath, then strip will be performed on the specified file. +# - if this is a directory, then strip will be performed on all binaries (executables & libraries) within the specified folder (not recursively). +# +# variables: +# strip: +# - "yes" (default): all strip commands will be performed. +# - "explicit": only strip commands given by this operation will be performed. +# - "implicit": only automatic strip commands will be performed (aka: the strip operation does nothing). +# - "no": no strip commands will be performed (aka: the strip operation does nothing). + +kit_operation_strip_unset() { + unset kit_operation_strip + unset kit_operation_strip_apply +} + +kit_operation_strip() { + local filetype= + local filepath= + + # operation controls + local parent=$parent-$self + local self=operation + + kit_operation_message + + filetype=$(echo object $line | fss_extended_read -c 0 -s 0) + filepath=$(echo object $line | fss_extended_read -c 0 -s 1) + + kit_operation_strip_apply "$filetype" "$filepath" +} + +kit_operation_strip_apply() { + local filetype=$1 + local filepath=$2 + + local i= + local files= + + if [[ $strip == "yes" || $strip == "explicit" ]] ; then + if [[ $filetype != "executable" && $filetype != "library" ]] ; then + kit_operation_error "The strip filetype parameter '$c_notice$filetype$c_error' is invalid, must be either: executable or library" + fi + + if [[ -d $filepath ]] ; then + if [[ $filetype == "executable" ]] ; then + files=$(find $filepath -maxdepth 1 -type f) + + for i in $files ; do + if [[ $(file -L -b $i | grep -s -o '\') != "" ]] ; then + kit_message_shell "strip --strip-debug $i" + strip --strip-debug $i + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Failed to strip the executable '$c_notice$i$c_error'" + fi + fi + done + elif [[ $filetype == "library" ]] ; then + files=$(find $filepath -maxdepth 1 -type f) + + for i in $files ; do + if [[ $(file -L -b $i | grep -s -o '\') != "" || $(file -L -b $i | grep -s -o '\') != "" ]] ; then + kit_message_shell "strip --strip-debug $i" + strip --strip-debug $i + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Failed to strip the library '$c_notice$i$c_error'" + fi + fi + done + fi + elif [[ -f $filepath ]] ; then + if [[ $filetype == "executable" ]] ; then + if [[ $(file -L -b $filepath | grep -s -o '\') != "" ]] ; then + kit_message_shell "strip --strip-debug $filepath" + strip --strip-debug $filepath + else + kit_operation_error "Cannot strip '$c_notice$filepath$c_error' because it is not an executable" + fi + elif [[ $filetype == "library" ]] ; then + if [[ $(file -L -b $filepath | grep -s -o '\') != "" || $(file -L -b $filepath | grep -s -o '\') != "" ]] ; then + kit_message_shell "strip --strip-debug $filepath" + strip --strip-debug $filepath + else + kit_operation_error "Cannot strip '$c_notice$filepath$c_error' because it is not a library" + fi + fi + else + kit_operation_error "The strip filepath or directory '$c_notice$filepath$c_error' is invalid" + fi + fi +} diff --git a/sources/kit-operation-version b/sources/kit-operation-version new file mode 100755 index 0000000..6010b01 --- /dev/null +++ b/sources/kit-operation-version @@ -0,0 +1,131 @@ +#!/bin/bash +# this provides an operation to obtain or set the version number for a particular package. +# +# arguments: +# type: +# - this is the version type to specify. +# - must be one of the following: major, minor, or micro. +# command: +# - this is the method in which to obtain or define the version. +# - must be one of the following: shell or set. +# data: +# - when the command is 'set', this is the version number. +# - when command is 'shell', this is the shell command to perform to obtain the version number. + +kit_operation_version_unset() { + unset kit_operation_version + unset kit_operation_version_resume +} + +kit_operation_version() { + local type= + local command= + local data= + local version= + local temporary= + + # operation controls + local parent=$parent-$self + local self=operation + + kit_operation_message + + type=$(echo object $line | fss_extended_read -c 0 -s 0) + command=$(echo object $line | fss_extended_read -c 0 -s 1) + data=$(echo object $line | fss_extended_read -c 0 -s 2) + + if [[ $type != "major" && $type != "minor" && $type != "micro" ]] ; then + kit_operation_error "Invalid version type '$c_notice$type$c_error'" + fi + + if [[ $command != "shell" && $command != "set" ]] ; then + kit_operation_error "Invalid version command '$c_notice$command$c_error', must be one of the following: set or shell" + fi + + if [[ $command == "set" ]] ; then + version=$data + elif [[ $command == "shell" ]] ; then + if [[ $(kit_core_is_empty $data) == "" ]] ; then + kit_operation_error "For the '$c_notice$command$c_error' command, the actual command was not supplied." + fi + + kit_message_shell "$data" + version=$(eval $data) + + if [[ $? -ne 0 ]] ; then + kit_operation_error "Something went wrong while executing the shell command for the version operation" + fi + fi + + if [[ $type == "major" ]] ; then + kit_reserved_set about_version_major "$version" + elif [[ $type == "minor" ]] ; then + kit_reserved_set about_version_minor "$version" + elif [[ $type == "micro" ]] ; then + kit_reserved_set about_version_micro "$version" + fi + + # the version information has changed so reset the package version information + if [[ $about_version_major != "" ]] ; then + if [[ $about_version_minor != "" ]] ; then + if [[ $about_version_micro != "" ]] ; then + package_version=${about_version_major}.${about_version_minor}.${about_version_micro} + else + package_version=${about_version_major}.${about_version_minor} + fi + else + package_version=${about_version_major} + fi + fi + + kit_message_log message "The package_version number is now: '$package_version'" + + sed -i -e '/^[[:space:]]*about_version_major\>[[:space:]]*/d' $resume_path$resume_file + sed -i -e '/^[[:space:]]*about_version_micro\>[[:space:]]*/d' $resume_path$resume_file + sed -i -e '/^[[:space:]]*about_version_minor\>[[:space:]]*/d' $resume_path$resume_file + + temporary=$(fss_extended_write -s -p "$about_version_major") + echo "$(fss_extended_write -s -o about_version_major)$temporary" >> $resume_path$resume_file + temporary=$(fss_extended_write -s -p "$about_version_minor") + echo "$(fss_extended_write -s -o about_version_minor)$temporary" >> $resume_path$resume_file + temporary=$(fss_extended_write -s -p "$about_version_micro") + echo "$(fss_extended_write -s -o about_version_micro)$temporary" >> $resume_path$resume_file +} + +kit_operation_version_resume() { + local type= + local version= + + for type in about_version_major about_version_minor about_version_micro ; do + if [[ $(fss_extended_read -n $type -t $resume_path$resume_file) -gt 0 ]] ; then + version=$(fss_extended_read -n $type -c 0 -s 0 $resume_path$resume_file) + + if [[ $(kit_fss_has_error) != "" ]] ; then + kit_operation_error "Failed to load '$c_notice$type$c_error' from the file '$c_notice$resume_path$resume_file$c_error'" + fi + + + if [[ $type == "about_version_major" ]] ; then + kit_reserved_set about_version_major "$version" + elif [[ $type == "about_version_minor" ]] ; then + kit_reserved_set about_version_minor "$version" + elif [[ $type == "about_version_micro" ]] ; then + kit_reserved_set about_version_micro "$version" + fi + fi + done + + + # the version information may have changed so reset the package version information + if [[ $about_version_major != "" ]] ; then + if [[ $about_version_minor != "" ]] ; then + if [[ $about_version_micro != "" ]] ; then + package_version=${about_version_major}.${about_version_minor}.${about_version_micro} + else + package_version=${about_version_major}.${about_version_minor} + fi + else + package_version=${about_version_major} + fi + fi +} diff --git a/sources/kit-package b/sources/kit-package new file mode 100755 index 0000000..ed4bdf5 --- /dev/null +++ b/sources/kit-package @@ -0,0 +1,863 @@ +#!/bin/bash +# provides functions for processing and execution of package files. + +kit_package_unset() { + unset kit_package_read + unset kit_package_read_path + unset kit_package_error + unset kit_package_repository_load_rules + unset kit_package_repository_load_premade + unset kit_package_repository_load_source + unset kit_package_repository_load_binary + unset kit_package_repository_load_data + unset kit_package_version_check + unset kit_package_version_save + unset kit_package + unset kit_package_individual +} + +kit_package_read() { + kit_fss_read $package_path$package_file "$1" "$2" "$3" "$4" "$5" +} + +kit_package_read_path() { + kit_fss_read_path $package_path$package_file "$1" "$2" "$3" "$4" "$5" +} + +kit_package_error() { + kit_message_error "While processing the package '$c_notice$package$c_error', '$c_notice$package_what$c_error', '$c_notice$package_huh$c_error', '$c_notice$package_oh$c_error', '$c_notice$package_type$c_error' for the '$c_notice$distribution $distribution_version $distribution_flavor$c_error' distribution." + + if [[ $(kit_core_is_empty $*) != "" ]] ; then + kit_message_error "$*" + fi + + if [[ $self == "package" ]] ; then + cleanup_before_exit + exit -2 + fi +} + +kit_package_repository_load_rules() { + local path=$package_path_url$package_repository$package_path_rules + local operation=$1 + local previous_path=$PWD + + if [[ ! -d "$system_cache_path$path" ]] ; then + # note: this is also the "load" operation, which only does something when $system_cache_path$path does not exist. + kit_message_shell "git clone $remote_depth -q -n -o $rule_branch $package_url$path $system_cache_path$path" + git clone -q -n -o $rule_branch $package_url$path $system_cache_path$path + + if [[ $? -ne 0 || ! -d $system_cache_path$path ]] ; then + kit_package_error "Failed to clone '$c_notice$package_url$path$c_error' with branch of '$c_notice$rule_branch$c_error' to '$c_notice$system_cache_path$path$c_error'" + fi + + kit_message_shell "cd $system_cache_path$path" + cd $system_cache_path$path + + if [[ $? -ne 0 ]] ; then + kit_package_error "Failed to change to the directory '$c_notice$system_cache_path$path$c_error'" + fi + + kit_message_shell "git checkout" + git checkout + + if [[ $? -ne 0 ]] ; then + kit_package_error "Failed to checkout rules repository at '$c_notice$system_cache_path$path$c_error' for package '$c_notice$package$c_error'" + fi + + if [[ $rule_revision != "HEAD" ]] ; then + kit_message_shell "git reset --hard --quiet $rule_revision" + git reset --hard --quiet $rule_revision + + if [[ $? -ne 0 ]] ; then + kit_package_error "Failed to reset rules repository at '$c_notice$system_cache_path$path$c_error' to '$c_notice$rule_revision$c_error' for package '$c_notice$package$c_error'" + fi + fi + elif [[ $operation == "update" ]] ; then + kit_message_shell "cd $system_cache_path$path" + cd $system_cache_path$path + + if [[ $? -ne 0 ]] ; then + kit_package_error "Failed to change to the directory '$c_notice$system_cache_path$path$c_error'" + fi + + kit_message_shell "git fetch --quiet" + git fetch --quiet + + if [[ $? -ne 0 ]] ; then + kit_package_error "Failed to fetch rules repository at '$c_notice$system_cache_path$path$c_error' for package '$c_notice$package$c_error'" + fi + + kit_message_shell "git pull --quiet --progress" + git pull --quiet --progress + + if [[ $? -ne 0 ]] ; then + kit_package_error "Failed to update rules repository at '$c_notice$system_cache_path$path$c_error' for package '$c_notice$package$c_error'" + fi + elif [[ $operation == "reset" ]] ; then + kit_message_shell "cd $system_cache_path$path" + cd $system_cache_path$path + + if [[ $? -ne 0 ]] ; then + kit_package_error "Failed to change to the directory '$c_notice$system_cache_path$path$c_error'" + fi + + if [[ $rule_revision == "HEAD" ]] ; then + kit_message_shell "git reset --hard --quiet" + git reset --hard --quiet + + if [[ $? -ne 0 ]] ; then + kit_package_error "Failed to reset rules repository at '$c_notice$system_cache_path$path$c_error' for package '$c_notice$package$c_error'" + fi + else + kit_message_shell "git reset --hard --quiet $rule_revision" + git reset --hard --quiet $rule_revision + + if [[ $? -ne 0 ]] ; then + kit_package_error "Failed to reset rules repository at '$c_notice$system_cache_path$path$c_error' to '$c_notice$rule_revision$c_error' for package '$c_notice$package$c_error'" + fi + fi + fi + + if [[ $operation == "update" ]] ; then + kit_message_highlight "The '${c_notice}rules$c_highlight' repository for the package '${c_notice}$package$c_highlight' has been updated." + elif [[ $operation == "reset" ]] ; then + kit_message_highlight "The '${c_notice}rules$c_highlight' repository for the package '${c_notice}$package$c_highlight' has been reset." + fi + + kit_message_shell "cd $previous_path" + cd $previous_path +} + +kit_package_repository_load_premade() { + local path=$package_path_url$package_repository$package_path_premade + local operation=$1 + local previous_path=$PWD + + # note: whether or not premade files exist is determined by the rules in question, therefore this can only update and reset rules if the directories already exist + if [[ ! -d $system_cache_path$path ]] ; then + return + elif [[ $operation == "update" ]] ; then + kit_message_shell "cd $system_cache_path$path" + cd $system_cache_path$path + + if [[ $? -ne 0 ]] ; then + kit_package_error "Failed to change to the directory '$c_notice$system_cache_path$path$c_error'" + fi + + kit_message_shell "git fetch --quiet" + git fetch --quiet + + if [[ $? -ne 0 ]] ; then + kit_package_error "Failed to fetch premade repository at '$c_notice$system_cache_path$path$c_error' for package '$c_notice$package$c_error'" + fi + + kit_message_shell "git pull --quiet --progress" + git pull --quiet --progress + + if [[ $? -ne 0 ]] ; then + kit_package_error "Failed to update premade repository at '$c_notice$system_cache_path$path$c_error' for package '$c_notice$package$c_error'" + fi + elif [[ $operation == "reset" ]] ; then + kit_message_shell "cd $system_cache_path$path" + cd $system_cache_path$path + + if [[ $? -ne 0 ]] ; then + kit_package_error "Failed to change to the directory '$c_notice$system_cache_path$path$c_error'" + fi + + if [[ $premade_revision == "HEAD" ]] ; then + kit_message_shell "git reset --hard --quiet" + git reset --hard --quiet + + if [[ $? -ne 0 ]] ; then + kit_package_error "Failed to reset premade repository at '$c_notice$system_cache_path$path$c_error' for package '$c_notice$package$c_error'" + fi + else + kit_message_shell "git reset --hard --quiet $premade_revision" + git reset --hard --quiet $premade_revision + + if [[ $? -ne 0 ]] ; then + kit_package_error "Failed to reset premade repository at '$c_notice$system_cache_path$path$c_error' to '$c_notice$premade_revision$c_error' for package '$c_notice$package$c_error'" + fi + fi + fi + + if [[ $operation == "update" ]] ; then + kit_message_highlight "The '${c_notice}premade$c_highlight' repository for the package '${c_notice}$package$c_highlight' has been updated." + elif [[ $operation == "reset" ]] ; then + kit_message_highlight "The '${c_notice}premade$c_highlight' repository for the package '${c_notice}$package$c_highlight' has been reset." + fi + + kit_message_shell "cd $previous_path" + cd $previous_path + + if [[ $? -ne 0 ]] ; then + kit_package_error "Failed to change to the directory '$c_notice$previous_path$c_error'" + fi +} + +kit_package_repository_load_source() { + local path=$package_path_url$package_repository$package_major_minor_path$package_path_source + local operation=$1 + local previous_path=$PWD + + if [[ ! -d $system_cache_path$path ]] ; then + # note: this is also the "load" operation, which only does something when $system_cache_path$path does not exist. + kit_message_shell "git clone $remote_depth -q -n -o $source_branch $package_url$path $system_cache_path$path" + git clone -q -n -o $source_branch $package_url$path $system_cache_path$path + + if [[ $? -ne 0 || ! -d $system_cache_path$path ]] ; then + kit_package_error "Failed to clone '$c_notice$package_url$path$c_error' with branch of '$c_notice$source_branch$c_error' to '$c_notice$system_cache_path$path$c_error'" + fi + + kit_message_shell "cd $system_cache_path$path" + cd $system_cache_path$path + + if [[ $? -ne 0 ]] ; then + kit_package_error "Failed to change to the directory '$c_notice$system_cache_path$path$c_error'" + fi + + kit_message_shell "git checkout" + git checkout + + if [[ $? -ne 0 ]] ; then + kit_package_error "Failed to checkout source repository at '$c_notice$system_cache_path$path$c_error' for package '$c_notice$package$c_error'" + fi + + if [[ $source_revision != "HEAD" ]] ; then + kit_message_shell "git reset --hard --quiet $source_revision" + git reset --hard --quiet $source_revision + + if [[ $? -ne 0 ]] ; then + kit_package_error "Failed to reset source repository at '$c_notice$system_cache_path$path$c_error' to '$c_notice$source_revision$c_error' for package '$c_notice$package$c_error'" + fi + fi + elif [[ $operation == "update" ]] ; then + kit_message_shell "cd $system_cache_path$path" + cd $system_cache_path$path + + if [[ $? -ne 0 ]] ; then + kit_package_error "Failed to change to the directory '$c_notice$system_cache_path$path$c_error'" + fi + + kit_message_shell "git fetch --quiet" + git fetch --quiet + + if [[ $? -ne 0 ]] ; then + kit_package_error "Failed to fetch source repository at '$c_notice$system_cache_path$path$c_error' for package '$c_notice$package$c_error'" + fi + + kit_message_shell "git pull --quiet --progress" + git pull --quiet --progress + + if [[ $? -ne 0 ]] ; then + kit_package_error "Failed to update source repository at '$c_notice$system_cache_path$path$c_error' for package '$c_notice$package$c_error'" + fi + elif [[ $operation == "reset" ]] ; then + kit_message_shell "cd $system_cache_path$path" + cd $system_cache_path$path + + if [[ $? -ne 0 ]] ; then + kit_package_error "Failed to change to the directory '$c_notice$system_cache_path$path$c_error'" + fi + + if [[ $source_revision == "HEAD" ]] ; then + kit_message_shell "git reset --hard --quiet" + git reset --hard --quiet + + if [[ $? -ne 0 ]] ; then + kit_package_error "Failed to reset sources repository at '$c_notice$system_cache_path$path$c_error' for package '$c_notice$package$c_error'" + fi + else + kit_message_shell "git reset --hard --quiet $source_revision" + git reset --hard --quiet $source_revision + + if [[ $? -ne 0 ]] ; then + kit_package_error "Failed to reset sources repository at '$c_notice$system_cache_path$path$c_error' to '$c_notice$source_revision$c_error' for package '$c_notice$package$c_error'" + fi + fi + fi + + if [[ $operation == "update" ]] ; then + kit_message_highlight "The '${c_notice}source$c_highlight' repository for the package '${c_notice}$package$c_highlight' has been updated." + elif [[ $operation == "reset" ]] ; then + kit_message_highlight "The '${c_notice}source$c_highlight' repository for the package '${c_notice}$package$c_highlight' has been reset." + fi + + kit_message_shell "cd $previous_path" + cd $previous_path + + if [[ $? -ne 0 ]] ; then + kit_package_error "Failed to change to the directory '$c_notice$previous_path$c_error'" + fi +} + +kit_package_repository_load_binary() { + local path=$package_path_url$package_repository$package_major_minor_path$package_path_binary + + # TODO +} + +kit_package_repository_load_data() { + local path=$package_path_url$package_repository$package_path_data + + # TODO +} + +kit_package_version_check() { + local path=$system_versions_path + local file=${package}.version + local version_string= + local version_raw= + local version_major= + local version_minor= + local version_micro= + local version_what= + local version_huh= + local c=0 + local t= + local c2= + local t2= + local w= + local h= + + version_difference=new + + if [[ ! -f $path$file ]] ; then + return + fi + + t=$(fss_basic_list_read -n version -t $path$file) + + if [[ $(kit_fss_has_error) != "" ]] ; then + kit_package_error "Failed to read '${c_notice}version${c_error}' data from '$c_notice$path$file$c_error'" + fi + + while [[ $c -lt $t ]] ; do + kit_fss_read "$path$file" version_string version string $c + kit_fss_read "$path$file" version_raw version raw $c + kit_fss_read "$path$file" version_major version major $c + kit_fss_read "$path$file" version_minor version minor $c + kit_fss_read "$path$file" version_micro version micro $c + + t2=$(fss_basic_list_read -n "${version_string}-$version_raw" -t $path$file) + + if [[ $(kit_fss_has_error) != "" ]] ; then + kit_package_error "Failed to read '${c_notice}${version_string}-$version_raw${c_error}' data from '$c_notice$path$file$c_error'" + fi + + if [[ $t2 -gt 0 ]] ; then + let c2=0 + t2=$(fss_basic_list_read -n ${version_string}-$version_raw $path$file | fss_extended_read -t) + + if [[ $(kit_fss_has_error) != "" ]] ; then + kit_package_error "Failed to read '${c_notice}${version_string}-$version_raw${c_error}' data from '$c_notice$path$file$c_error'" + fi + + while [[ $c2 -lt $t2 ]] ; do + w=$(fss_basic_list_read -n ${version_string}-$version_raw $path$file | fss_extended_read -c $c2 -o) + + if [[ $(kit_fss_has_error) != "" ]] ; then + kit_package_error "Failed to read '${c_notice}${version_string}-$version_raw${c_error}' data from '$c_notice$path$file$c_error'" + fi + + h=$(fss_basic_list_read -n ${version_string}-$version_raw $path$file | fss_extended_read -c $c2 -s 0) + + if [[ $(kit_fss_has_error) != "" ]] ; then + kit_package_error "Failed to read '${c_notice}${version_string}-$version_raw${c_error}' data from '$c_notice$path$file$c_error'" + fi + + if [[ $package_what == $w && $package_huh == $h ]] ; then + if [[ $version_major -lt $about_version_major ]] ; then + version_difference="newer" + return; + elif [[ $version_major -eq $about_version_major ]] ; then + if [[ $version_minor == "x" || $about_version_minor == "x" ]] ; then + version_difference="x" + return + elif [[ $(kit_core_is_empty $version_minor) != "" ]] ; then + if [[ $(kit_core_is_empty $about_version_minor) != "" ]] ; then + version_difference="same" + return + fi + + version_difference="unknown" + return + else + if [[ $(kit_core_is_empty $version_minor) != "" ]] ; then + if [[ $version_micro == "x" || $about_version_micro == "x" ]] ; then + version_difference="x" + return + elif [[ $(kit_core_is_empty $about_version_micro) != "" ]] ; then + version_difference="same" + return + fi + + version_difference="unknown" + return + elif [[ $version_micro -lt $about_version_micro ]] ; then + version_difference="newer" + return; + elif [[ $version_micro -eq $about_version_micro ]] ; then + version_difference="same" + return; + else + version_difference="older" + return; + fi + fi + else + version="older" + return; + fi + fi + done + fi + + let c++ + done +} + +kit_package_version_save() { + + # control variables + local list_name=${package_version}-$package_version_raw + + # converted version information variables + local safe_version_string=$(fss_extended_write -s -p "$package_version") + local safe_version_raw=$(fss_extended_write -s -p "$package_version_raw") + local safe_version_major=$(fss_extended_write -s -p "$about_version_major") + local safe_version_minor=$(fss_extended_write -s -p "$about_version_minor") + local safe_version_micro=$(fss_extended_write -s -p "$about_version_micro") + local safe_version_name=$(fss_basic_list_write -s -o "$list_name") + local safe_version_what=$(fss_extended_write -s -o "$package_what") + local safe_version_huh=$(fss_extended_write -s -p "$package_huh") + local safe_version_oh=$(fss_extended_write -s -p "$package_oh") + + + # TODO: add support for multiple version files and objects + + # create new version information + echo -e "# fss-0002\n" > $system_versions_path${package}.version + + echo >> $system_versions_path${package}.version + echo "$(fss_basic_list_write -s -o version)" >> $system_versions_path${package}.version + echo " $(fss_extended_write -s -o string)$safe_version_string" >> $system_versions_path${package}.version + echo " $(fss_extended_write -s -o raw)$safe_version_raw" >> $system_versions_path${package}.version + echo " $(fss_extended_write -s -o major)$safe_version_major" >> $system_versions_path${package}.version + echo " $(fss_extended_write -s -o minor)$safe_version_minor" >> $system_versions_path${package}.version + echo " $(fss_extended_write -s -o micro)$safe_version_micro" >> $system_versions_path${package}.version + echo >> $system_versions_path${package}.version + + echo >> $system_versions_path${package}.version + echo "$safe_version_name" >> $system_versions_path${package}.version + echo " $safe_version_what$safe_version_huh$safe_version_oh" >> $system_versions_path${package}.version + echo >> $system_versions_path${package}.version +} + +kit_package_individual() { + + # package variables + local package_what=$1 + local package_huh=$2 + local package_oh=$3 + local package_version_raw= + + # control variables + local version_difference= + local previous_path=$PWD + local parent=package + + # other variables + local skip= + + + # TODO: add support for other operations, such as uninstall + # load all appropriate repositories + if [[ $kit_operation == "install" || ( $kit_operation == "alter" && $action != "force" ) ]] ; then + kit_package_version_check + + # TODO: also keep in mind that some of the options here might require comparing the git revisions to see if the packages are actually the same (this is expensive) + if [[ $kit_operation == "install" ]] ; then + if [[ $version_difference != "new" ]] ; then + kit_message_warning "Skipping '${c_notice}$package_what$c_error' '${c_notice}$package_huh$c_error' '${c_notice}$package_oh$c_error' of package '${c_notice}$package$c_error' because the package is already installed, try the alter operation instead." + skip="yes" + fi + elif [[ $kit_operation == "alter" ]] ; then + if [[ $action == "upgrade" ]] ; then + if [[ $version_difference != "newer" && $version_difference != "x" ]] ; then + kit_message_warning "Skipping '${c_notice}$package_what$c_error' '${c_notice}$package_huh$c_error' '${c_notice}$package_oh$c_error' of package '${c_notice}$package$c_error' because the package is already installed, try the alter operation instead." + skip="yes" + fi + elif [[ $action == "downgrade" ]] ; then + if [[ $version_difference != "older" && $version_difference != "x" ]] ; then + kit_message_warning "Skipping '${c_notice}$package_what$c_error' '${c_notice}$package_huh$c_error' '${c_notice}$package_oh$c_error' of package '${c_notice}$package$c_error' because the package is already installed, try the alter operation instead." + skip="yes" + fi + fi + fi + fi + + if [[ $skip == "yes" ]] ; then + # TODO: do any cleanup operations here + return + fi + + kit_package_repository_load_rules + + if [[ $package_type == "source" ]] ; then + kit_package_repository_load_source + kit_package_repository_load_premade + + # TODO: at this point, if version_difference=="x" on an alter command attempt a git revision version test + + # TODO: now begin processing the rules + kit_message_shell "cd $package_path_base$package_major_minor_path$package_path_source" + cd $package_path_base$package_major_minor_path$package_path_source + + if [[ $source_revision == "HEAD" ]] ; then + package_version_raw=$(git log -1 --format="%h") + else + package_version_raw=$source_revision + fi + elif [[ $package_type == "binary" ]] ; then + kit_package_repository_load_binary + kit_package_repository_load_data + + # TODO: at this point, if version_difference=="x" on an alter command attempt a git revision version test + + # TODO: now begin processing the rules + kit_message_shell "cd $package_path_base$package_major_minor_path$package_path_binary" + cd $package_path_base$package_major_minor_path$package_path_binary + + if [[ $binary_revision == "HEAD" ]] ; then + package_version_raw=$(git log -1 --format="%h") + else + package_version_raw=$binary_revision + fi + fi + + # process the rules for a given package + kit_rule "$package" "$package_what" "$package_huh" "$package_oh" "$package_type" "$package_url" "$package_path_url$package_repository" "$package_path_rules" "$package_path_premade" + + kit_message_highlight "'$c_notice$package_what$c_highlight', '$c_notice$package_huh$c_highlight', '$c_notice$package_oh$c_highlight' of the package '$c_notice$package$c_highlight' has been processed" + + kit_message_shell "cd $previous_path" + cd $previous_path + + + # save version information after install + if [[ $kit_operation == "install" || $kit_operation == "alter" ]] ; then + kit_package_version_save + #elif [[ $kit_operation == "uninstall" ]] ; then + # TODO: remove the appropriate "who" (that is, package_what, package_huh, and package_oh) and if there are no who's left, then remove the version file entirely + fi + + + # do cleanup + if [[ $do_cleanup == "y" ]] ; then + if [[ $package_type == "source" ]] ; then + if [[ -d "$package_path_base$package_path_premade" ]] ; then + rm -Rf "$package_path_base$package_path_premade" + fi + + if [[ -d "$package_path_base$package_major_minor_path$package_path_source" ]] ; then + rm -Rf "$package_path_base$package_major_minor_path$package_path_source" + rmdir --ignore-fail-on-non-empty "$package_path_base$package_major_minor_path" + fi + fi + + if [[ -d "$package_path_base" ]] ; then + rmdir --ignore-fail-on-non-empty "$package_path_base" + fi + + if [[ -d "$system_cache_path$package_path_url" ]] ; then + rmdir --ignore-fail-on-non-empty "$system_cache_path$package_path_url" + fi + fi +} + +kit_package() { + + # package variables + local package=$1 + local package_path=$2 + local package_file=$3 + local package_type=$targets_type + local package_what=$targets_what + local package_huh=$targets_huh + local package_oh=$targets_oh + local package_settings_name="package-$package" + local package_path_url=package/ + local package_path_rules=rules/ + local package_path_source=source/ + local package_path_premade=premade/ + local package_path_binary=binary/ + local package_path_data=data/ + local package_path_base= + local package_url= + local package_repository= + local package_major_minor_path= + local package_version= + local package_version_raw= + local package_version_file=${package}.version + + # package properties + local about_name= + local about_description= + local about_version_major= + local about_version_minor= + local about_version_micro= + local about_categories= + local about_flags= + + local rule_branch= + local rule_revision= + local source_branch= + local source_revision= + local binary_branch= + local binary_revision= + local data_branch= + local data_revision= + local premade_branch= + local premade_revision= + + # control variables + local self=package + local source= + + local logs_file=$package.log + local resume_file=$kit_operation-$package.resume + + # other variables + local w= + local h= + local o= + local c= + local t= + local p1= + local p2= + local p3= + + + kit_log_section + kit_log_message message "obtaining and reading data for the package '$package'" + + + if [[ ! -f $package_path$package_file ]] ; then + kit_package_error "Failed to find the file '${c_notice}$package_path$package_file$c_error'" + fi + + # ensure that the package resume file exists + if [[ ! -f $resume_path$resume_file || $resume_execution != "yes" ]] ; then + echo -e "# fss-0001\n" > $resume_path$resume_file + fi + + + # about: + kit_package_read about_name about name 0 + kit_package_read about_description about description 0 + kit_package_read about_version_major about version 0 0 + kit_package_read about_version_minor about version 0 1 + kit_package_read about_version_micro about version 0 2 + kit_package_read about_categories about categories 0 + kit_package_read about_flags about flags 0 + + if [[ $about_version_major != "" ]] ; then + if [[ $about_version_minor != "" ]] ; then + if [[ $about_version_micro != "" ]] ; then + package_version=${about_version_major}.${about_version_minor}.${about_version_micro} + package_major_minor_path=${about_version_major}.${about_version_minor}/ + else + package_version=${about_version_major}.${about_version_minor} + package_major_minor_path=$package_version/ + fi + else + package_version=${about_version_major} + package_major_minor_path=$package_version/ + fi + fi + + + # from: + kit_package_read_path package_url from url 0 + kit_package_read_path package_repository from repository 0 + + package_path_base=$system_cache_path$package_path_url$package_repository + + + # revisions: + kit_package_read rule_branch revisions rule 0 0 + kit_package_read rule_revision revisions rule 0 1 + kit_package_read source_branch revisions source 0 0 + kit_package_read source_revision revisions source 0 1 + kit_package_read binary_branch revisions binary 0 0 + kit_package_read binary_revision revisions binary 0 1 + kit_package_read data_branch revisions data 0 0 + kit_package_read data_revision revisions data 0 1 + kit_package_read premade_branch revisions premade 0 0 + kit_package_read premade_revision revisions premade 0 1 + + # assign defaults repositories in the event data is missing + if [[ $(kit_core_is_empty $rule_branch) == "" ]] ; then + rule_branch=master + fi + + if [[ $(kit_core_is_empty $rule_revision) == "" ]] ; then + rule_revision=HEAD + fi + + if [[ $(kit_core_is_empty $source_branch) == "" ]] ; then + source_branch=master + fi + + if [[ $(kit_core_is_empty $source_revision) == "" ]] ; then + source_revision=HEAD + fi + + if [[ $(kit_core_is_empty $binary_branch) == "" ]] ; then + binary_branch=master + fi + + if [[ $(kit_core_is_empty $binary_revision) == "" ]] ; then + binary_revision=HEAD + fi + + if [[ $(kit_core_is_empty $data_branch) == "" ]] ; then + data_branch=master + fi + + if [[ $(kit_core_is_empty $data_revision) == "" ]] ; then + data_revision=HEAD + fi + + if [[ $(kit_core_is_empty $premade_branch) == "" ]] ; then + premade_branch=master + fi + + if [[ $(kit_core_is_empty $premade_revision) == "" ]] ; then + premade_revision=HEAD + fi + + + + # $package_what: + if [[ ! $(fss_basic_list_read -n $package_what -t $package_path$package_file) -ge 1 ]] ; then + kit_package_error "The list '${c_notice}$package_what${c_error}' is not defined in file '${c_notice}$package_path$package_file${c_error}'" + fi + + if [[ $(kit_core_is_empty $(fss_basic_list_read -n $package_what -c 0 $package_path$package_file)) == "" ]] ; then + kit_package_error "The list '${c_notice}$package_what${c_error}' in file '${c_notice}$package_path$package_file${c_error}' is empty" + fi + + if [[ $(kit_core_is_empty $package_huh) == "" ]] ; then + package_huh=$(fss_basic_list_read -n $package_what -c 0 $package_path$package_file | fss_extended_read -o | sort | uniq) + + if [[ $(kit_fss_has_error) != "" ]] ; then + kit_package_error "Failed to read '${c_notice}${version_string}-$version_raw${c_error}' data from '$c_notice$path$file$c_error'" + fi + fi + + if [[ $(kit_core_is_empty $package_oh) == "" ]] ; then + package_oh="object " + + for h in $package_huh ; do + package_oh="${package_oh}$(fss_basic_list_read -n $package_what -c 0 $package_path$package_file | fss_extended_read -n $h -c 0 -s 0) " + done + else + o= + + for h in $package_huh ; do + o="${o}$package_oh " + done + + package_oh="object $o" + fi + + + # TODO: requirements: or dependencies: + + + # perform update on individual packages if they have been downloaded already, otherwise skip them. + if [[ $kit_operation == "update" || $kit_operation == "reset" ]] ; then + kit_package_repository_load_rules "$kit_operation" + + if [[ $package_type == "source" ]] ; then + kit_package_repository_load_source "$kit_operation" + kit_package_repository_load_premade "$kit_operation" + elif [[ $package_type == "binary" ]] ; then + kit_package_repository_load_binary "$kit_operation" + kit_package_repository_load_data "$kit_operation" + fi + + # always remove resume file on proper exit + if [[ -f $resume_path$resume_file ]] ; then + rm -f $resume_path$resume_file + fi + + return + fi + + + # operate on individual package parts (what + huh + oh) + for w in $package_what ; do + let c=0 + p1=$(fss_extended_write -p -s "$w" | sed -e 's|[[:space:]]*$||') + + for h in $package_huh ; do + o=$(echo "$package_oh" | fss_extended_read -c 0 -s $c) + p2=$(fss_extended_write -p -s "$h" | sed -e 's|[[:space:]]*$||') + p3=$(fss_extended_write -p -s "$o" | sed -e 's|[[:space:]]*$||') + + if [[ ! -f "$resume_path$resume_file" || $(fss_basic_read -n processed $resume_path$resume_file | grep -s -o "^[[:space:]]*$p1[[:space:]]*$p2[[:space:]]*$p3[[:space:]]*$") == "" ]] ; then + kit_package_individual $w $h $o + echo "$(fss_extended_write -s processed)$p1 $p2 $p3" >> "$resume_path$resume_file" + fi + + let c++ + done + done + + + # do cleanup + + # always remove resume file on proper exit + if [[ -f $resume_path$resume_file ]] ; then + rm -f $resume_path$resume_file + fi + + if [[ $do_cleanup == "y" ]] ; then + # TODO: implement locking so that files don't get deleted until there are no instances left + if [[ -d $package_path_base$package_path_rules ]] ; then + rm -Rf $package_path_base$package_path_rules + fi + + if [[ $package_type == "source" ]] ; then + if [[ -d $package_path_base$package_major_minor_path$package_path_source ]] ; then + rm -Rf $package_path_base$package_major_minor_path$package_path_source + fi + + if [[ -d $package_path_base$package_path_premade ]] ; then + rm -Rf $package_path_base$package_path_premade + fi + elif [[ $package_type == "binary" ]] ; then + if [[ -d $package_path_base$package_major_minor_path$package_path_binary ]] ; then + rm -Rf $package_path_base$package_major_minor_path$package_path_binary + fi + + # TODO: should data be stored under the directory $package_major_minor_path ? + if [[ -d $package_path_base$package_path_data ]] ; then + rm -Rf $package_path_base$package_path_data + fi + fi + + if [[ -d $package_path_base ]] ; then + rmdir --ignore-fail-on-non-empty $package_path_base + fi + + if [[ -d $system_cache_path$package_path_url ]] ; then + rmdir --ignore-fail-on-non-empty $system_cache_path$package_path_url + fi + fi +} diff --git a/sources/kit-permission b/sources/kit-permission new file mode 100755 index 0000000..a8bc266 --- /dev/null +++ b/sources/kit-permission @@ -0,0 +1,65 @@ +#!/bin/bash +# provides functions for reading and writing permission variables. + +kit_permission_unset() { + unset kit_permission_is + unset kit_permission_set + unset kit_permission_get +} + +kit_permission_is() { + local name=$2 + local list=$1 + + echo -n $(echo -n $permission_variables | grep -s -o "\<${list}_$name=[[:digit:]]*\>" | sed -e "s|$name=||") +} + +kit_permission_set() { + local name=$2 + local value=$3 + local position= + local list=$1 + + position=$(kit_permission_is $list $name) + + if [[ $position == "" ]] ; then + permission_data[$permission_total]=$value + permission_variables="${permission_variables}${list}_$name=$permission_total " + let permission_total++ + else + permission_data[$position]=$value + fi + + kit_log_message save permission "${list}_$name" "$value" +} + +kit_permission_get() { + local name=$2 + local position= + local file= + local list=$1 + + if [[ $name == "" ]] ; then + permission= + return + fi + + permission= + position=$(kit_permission_is $name) + + # loading priority is: memory (permission_data), system settings, and then distribution settings. + if [[ $position != "" && $position -ge 0 ]] ; then + permission=${permission_data[$position]} + else + for file in "$system_settings_path$system_permissions_file" "$distribution_settings_path$distribution_permissions_file" ; do + if [[ -f $file ]] ; then + if [[ $(fss_basic_list_read -n $list -t $file) -gt 0 && $(fss_basic_list_read -c 0 -n $list $file | fss_basic_read -t -n $name) -gt 0 ]] ; then + kit_log_message load permission "${list}_$name" "fss_basic_list_read -c 0 -n $list $file | fss_basic_read -c 0 -n $name" + permission=$(fss_basic_list_read -c 0 -n $list $file | fss_basic_read -c 0 -n $name) + kit_permission_set "$list" "$name" "$permission" + return + fi + fi + done + fi +} diff --git a/sources/kit-procedure b/sources/kit-procedure new file mode 100755 index 0000000..a4753d6 --- /dev/null +++ b/sources/kit-procedure @@ -0,0 +1,36 @@ +#!/bin/bash +# provides functions for processing and execution of procedure files. +# TODO: this is incomplete. + +kit_procedure_unset() { + unset kit_procedure_error + unset kit_procedure +} + +kit_procedure_error() { + kit_message_error "While processing the procedure '$c_notice$procedure$c_error', '$c_notice$procedure_what$c_error', '$c_notice$procedure_huh$c_error', '$c_notice$procedure_oh$c_error', '$c_notice$procedure_type$c_error' for the '$c_notice$distribution $distribution_version $distribution_flavor$c_error' distribution." + + if [[ $(kit_core_is_empty $*) != "" ]] ; then + kit_message_error "$*" + fi + + if [[ $self == "procedure" ]] ; then + cleanup_before_exit + exit -3 + fi +} + +kit_procedure() { + + # procedure variables + local procedure=$1 + local procedure_path=$2 + local procedure_file=$3 + local procedure_type=$targets_type + local procedure_what=$targets_what + local procedure_huh=$targets_huh + local procedure_oh=$tarets_oh + + # TODO + echo "TODO" +} diff --git a/sources/kit-read b/sources/kit-read new file mode 100755 index 0000000..1ab6395 --- /dev/null +++ b/sources/kit-read @@ -0,0 +1,6 @@ +#!/bin/bash +# ??? what was I doing here? is this deprecated? + +#kit_read_unset() { +# unset kit_read_line +#} diff --git a/sources/kit-reserved b/sources/kit-reserved new file mode 100755 index 0000000..9b8f1aa --- /dev/null +++ b/sources/kit-reserved @@ -0,0 +1,305 @@ +#!/bin/bash +# provides functions for reading and writing reserved variables. + +kit_reserved_unset() { + unset kit_reserved_is + unset kit_reserved_get + unset kit_reserved_set + unset kit_reserved_register +} + +kit_reserved_is() { + local name=$1 + + echo -n $(echo "$reserved_variables" | grep -s -o "\<$name=[[:alpha:]]*\>" | sed -e "s|$name=||") +} + +kit_reserved_set() { + local name=$1 + local value=$2 + local position= + + position=$(kit_reserved_is $name) + + if [[ $(kit_core_is_empty $position) == "" ]] ; then + return + fi + + if [[ $position == "global" ]] ; then + case $name in + "system_settings_path") system_settings_path=$value;; + "system_data_path") system_data_path=$value;; + "system_cache_path") system_cache_path=$value;; + "system_versions_path") system_versions_path=$value;; + "system_settings_file") system_settings_file=$value;; + "system_permissions_file") system_permissions_file=$value;; + "system_environment_file") system_environment_file=$value;; + "system_settings_name") system_settings_name=$value;; + "installation_base") installation_base=$value;; + "remote_url_web") remote_url_web=$value;; + "remote_url_git") remote_url_git=$value;; + "remote_branch") remote_branch=$value;; + "remote_tag") remote_tag=$value;; + "remote_depth") remote_depth=$value;; + "distribution") distribution=$value;; + "distribution_version") distribution_version=$value;; + "distribution_flavor") distribution_flavor=$value;; + "distribution_path") distribution_path=$value;; + "distribution_base") distribution_base=$value;; + "distribution_settings") distribution_settings=$value;; + "distribution_environment") distribution_environment=$value;; + "distribution_permissions") distribution_permissions=$value;; + "targets") targets=$value;; + "targets_path") targets_path=$value;; + "targets_extension") targets_extension=$value;; + "targets_type") targets_type=$value;; + "targets_what") targets_what=$value;; + "targets_huh") targets_huh=$value;; + "targets_oh") targets_oh=$value;; + esac + + kit_log_message save reserved "$name" "$value" + return + elif [[ $self == "global" ]] ; then + return; + fi + + if [[ $position == "package" && ( $self == "package" || $(echo "$parent" | grep -s -o '\') != "" ) ]] ; then + case $name in + "package") package=$value;; + "package_type") package_type=$value;; + "package_what") package_what=$value;; + "package_huh") package_huh=$value;; + "package_oh") package_oh=$value;; + "package_settings_name") package_settings_name=$value;; + "package_path_url") package_path_url=$value;; + "package_path_rules") package_path_rules=$value;; + "package_path_source") package_path_source=$value;; + "package_path_premade") package_path_premade=$value;; + "package_path_binary") package_path_binary=$value;; + "package_path_data") package_path_data=$value;; + "package_path_base") package_path_base=$value;; + "package_url") package_url=$value;; + "package_repository") package_repository=$value;; + "package_major_minor_path") package_major_minor_path=$value;; + "package_version") package_version=$value;; + "package_version_raw") package_version_raw=$value;; + "package_version_file") package_version_file=$value;; + "about_name") about_name=$value;; + "about_description") about_description=$value;; + "about_version_major") about_version_major=$value;; + "about_version_minor") about_version_minor=$value;; + "about_version_micro") about_version_micro=$value;; + "about_categories") about_categories=$value;; + "about_flags") about_flags=$value;; + "rule_branch") rule_branch=$value;; + "rule_revision") rule_revision=$value;; + "source_branch") source_branch=$value;; + "source_revision") source_revision=$value;; + "binary_branch") binary_branch=$value;; + "binary_revision") binary_revision=$value;; + "data_branch") data_branch=$value;; + "data_revision") data_revision=$value;; + esac + + kit_log_message save reserved "$name" "$value" + return + elif [[ $self == "package" ]] ; then + return; + fi + + # TODO: add support for procedure here + + if [[ $position == "rule" && ( $self == "rule" || $(echo "$parent" | grep -s -o '\') != "" ) ]] ; then + case $name in + "rule_what") rule_what=$value;; + "rule_huh") rule_huh=$value;; + "rule_oh") rule_oh=$value;; + "rule_type") rule_type=$value;; + "about_from") about_from=$value;; + "about_copyright") about_copyright=$value;; + "about_flags") about_flags=$value;; + "premade_path") premade_path=$value;; + "if_condition") if_condition=$value;; + esac + + kit_log_message save reserved "$name" "$value" + return + elif [[ $self == "rule" ]] ; then + return; + fi +} + +kit_reserved_get() { + local name=$1 + local position= + local file= + local list= + + reserved= + position=$(kit_reserved_is $name) + + if [[ $(kit_core_is_empty $position) == "" ]] ; then + return + fi + + if [[ $position == "global" ]] ; then + case $name in + "system_settings_path") reserved=$system_settings_path;; + "system_data_path") reserved=$system_data_path;; + "system_cache_path") reserved=$system_cache_path;; + "system_versions_path") reserved=$system_versions_path;; + "system_settings_file") reserved=$system_settings_file;; + "system_permissions_file") reserved=$system_permissions_file;; + "system_environment_file") reserved=$system_environment_file;; + "system_settings_name") reserved=$system_settings_name;; + "installation_base") reserved=$installation_base;; + "remote_url_web") reserved=$remote_url_web;; + "remote_url_git") reserved=$remote_url_git;; + "remote_branch") reserved=$remote_branch;; + "remote_tag") reserved=$remote_tag;; + "remote_depth") reserved=$remote_depth;; + "distribution") reserved=$distribution;; + "distribution_version") reserved=$distribution_version;; + "distribution_flavor") reserved=$distribution_flavor;; + "distribution_path") reserved=$distribution_path;; + "distribution_base") reserved=$distribution_base;; + "distribution_settings") reserved=$distribution_settings;; + "distribution_environment") reserved=$distribution_environment;; + "distribution_permissions") reserved=$distribution_permissions;; + "targets") reserved=$targets;; + "targets_path") reserved=$targets_path;; + "targets_extension") reserved=$targets_extension;; + "targets_type") reserved=$targets_type;; + "targets_what") reserved=$targets_what;; + "targets_huh") reserved=$targets_huh;; + "targets_oh") reserved=$targets_oh;; + esac + + kit_log_message load reserved "$name" "$reserved" + return + elif [[ $self == "global" ]] ; then + return; + fi + + if [[ $position == "package" && ( $self == "package" || $(echo "$parent" | grep -s -o '\') != "" ) ]] ; then + case $name in + "package") reserved=$package;; + "package_path") reserved=$package_path;; + "package_file") reserved=$package_file;; + "package_type") reserved=$package_type;; + "package_what") reserved=$package_what;; + "package_huh") reserved=$package_huh;; + "package_oh") reserved=$package_oh;; + "package_settings_name") reserved=$package_settings_name;; + "package_path_url") reserved=$package_path_url;; + "package_path_rules") reserved=$package_path_rules;; + "package_path_source") reserved=$package_path_source;; + "package_path_premade") reserved=$package_path_premade;; + "package_path_binary") reserved=$package_path_binary;; + "package_path_data") reserved=$package_path_data;; + "package_path_base") reserved=$package_path_base;; + "package_url") reserved=$package_url;; + "package_repository") reserved=$package_repository;; + "package_major_minor_path") reserved=$package_major_minor_path;; + "package_version") reserved=$package_version;; + "package_version_raw") reserved=$package_version_raw;; + "package_version_file") reserved=$package_version_file;; + "about_name") reserved=$about_name;; + "about_description") reserved=$about_description;; + "about_version_major") reserved=$about_version_major;; + "about_version_minor") reserved=$about_version_minor;; + "about_version_micro") reserved=$about_version_micro;; + "about_categories") reserved=$about_categories;; + "about_flags") reserved=$about_flags;; + "rule_branch") reserved=$rule_branch;; + "rule_revision") reserved=$rule_revision;; + "source_branch") reserved=$source_branch;; + "source_revision") reserved=$source_revision;; + "binary_branch") reserved=$binary_branch;; + "binary_revision") reserved=$binary_revision;; + "data_branch") reserved=$data_branch;; + "data_revision") reserved=$data_revision;; + esac + + kit_log_message load reserved "$name" "$reserved" + return + elif [[ $self == "package" ]] ; then + return; + fi + + # TODO: add support for procedure here + + if [[ $position == "rule" && ( $self == "rule" || $(echo "$parent" | grep -s -o '\') != "" ) ]] ; then + case $name in + "rule_what") reserved=$rule_what;; + "rule_huh") reserved=$rule_huh;; + "rule_oh") reserved=$rule_oh;; + "rule_type") reserved=$rule_type;; + "about_from") reserved=$about_from;; + "about_copyright") reserved=$about_copyright;; + "about_flags") reserved=$about_flags;; + "premade_path") reserved=$premade_path;; + "if_condition") reserved=$if_condition;; + esac + + kit_log_message load reserved "$name" "$reserved" + return + elif [[ $self == "rule" ]] ; then + return; + fi +} + +kit_reserved_register() { + local name= + + + # register global reserved variables + for name in system_settings_path system_data_path system_cache_path system_versions_path system_settings_file system_permissions_file system_environment_file system_settings_name installation_base ; do + reserved_variables="${reserved_variables}$name=global " + done + + for name in remote_url_web remote_url_git remote_branch remote_tag remote_depth ; do + reserved_variables="${reserved_variables}$name=global " + done + + for name in distribution distribution_version distribution_flavor distribution_path distribution_base distribution_settings_path distribution_settings_file distribution_environment_file distribution_permissions_file ; do + reserved_variables="${reserved_variables}$name=global " + done + + for name in targets targets_path targets_extension targets_type targets_what targets_huh targets_oh ; do + reserved_variables="${reserved_variables}$name=global " + done + + + # register package reserved variables + for name in package package_type package_what package_huh package_oh package_settings_name package_path_url package_path_rules package_path_source package_path_premade package_path_binary package_path_data package_path_base package_url package_repository package_major_minor_path package_version package_version_raw package_version_file ; do + reserved_variables="${reserved_variables}$name=package " + done + + for name in about_name about_description about_version_major about_version_minor about_version_micro about_categories about_flags ; do + reserved_variables="${reserved_variables}$name=package " + done + + for name in rule_branch rule_revision source_branch source_revision binary_branch binary_revision data_branch data_revision ; do + reserved_variables="${reserved_variables}$name=package " + done + + + # register procedure reserved variables + # TODO + + + # register rule reserved variables + for name in rule_what rule_huh rule_oh rule_type ; do + reserved_variables="${reserved_variables}$name=rule " + done + + for name in about_from about_copyright about_flags ; do + reserved_variables="${reserved_variables}$name=rule " + done + + for name in premade_path if_condition; do + reserved_variables="${reserved_variables}$name=rule " + done +} diff --git a/sources/kit-rule b/sources/kit-rule new file mode 100755 index 0000000..dac6133 --- /dev/null +++ b/sources/kit-rule @@ -0,0 +1,301 @@ +#!/bin/bash +# provides functions for processing and execution of rule files. + +kit_rule_unset() { + unset kit_rule_read + unset kit_rule_read_path + unset kit_rule_error + unset kit_rule_repository_load_premade + unset kit_rule +} + +kit_rule_read() { + kit_fss_read $system_cache_path$rule_path_base$rule_path_rule$rule_file "$1" "$2" "$3" "$4" "$5" +} + +kit_rule_read_path() { + kit_fss_read_path $system_cache_path$rule_path_base$rule_path_rule$rule_file "$1" "$2" "$3" "$4" "$5" +} + +kit_rule_error() { + if [[ $parent == "package" ]] ; then + kit_package_error + elif [[ $parent == "procedure" ]] ; then + kit_procedure_error + fi + + if [[ $operation != "" ]] ; then + kit_message_error "While processing rule line '$c_notice$line_number$c_error', operation '$c_notice$operation$c_error)." + fi + + if [[ $(kit_core_is_empty $*) != "" ]] ; then + kit_message_error "$*" + fi + + if [[ $self == "rule" ]] ; then + cleanup_before_exit + exit -4 + fi +} + +kit_rule_repository_load_premade() { + local previous_path=$PWD + + if [[ ! -d $premade_path ]] ; then + kit_message_shell "git clone $remote_depth -q -n -o $premade_branch $rule_url$rule_path_base$rule_path_premade $premade_path" + git clone $remote_depth -q -n -o $premade_branch $rule_url$rule_path_base$rule_path_premade $premade_path + + if [[ $? -ne 0 || ! -d $premade_path ]] ; then + kit_rule_error "Failed to clone '$c_notice$rule_path_base$rule_path_premade$c_error' with branch of '$c_notice$premade_branch$c_error' to '$c_notice$premade_path$c_error'" + fi + + kit_message_shell "cd $premade_path" + cd $premade_path + + if [[ $? -ne 0 ]] ; then + kit_rule_error "Failed to change to the directory '$c_notice$premade_path$c_error'" + fi + + kit_message_shell "git checkout" + git checkout + + if [[ $premade_revision != "HEAD" ]] ; then + kit_message_shell "git reset --hard --quiet $premade_revision" + git reset --hard --quiet $premade_revision + + if [[ $? -ne 0 ]] ; then + kit_package_error "Failed to reset premade repository at '$c_notice$premade_path$c_error' to '$c_notice$premade_revision$c_error' for package '$c_notice$package$c_error'" + fi + fi + fi + + kit_message_shell "cd $previous_path" + cd $previous_path + + if [[ $? -ne 0 ]] ; then + kit_rule_error "Failed to change to the directory '$c_notice$previous_path$c_error'" + fi +} + +kit_rule() { + + # passed variables + local rule=$1 + local rule_what=$2 + local rule_huh=$3 + local rule_oh=$4 + local rule_type=$5 + + # rule variables + local about_from= + local about_copyright= + local about_flags="$about_flags " + + # permission variables + local permission_group_type= + local permission_group_name= + local permission_mode_directory=none + local permission_mode_file=none + local permission_attribute_directory=none + local permission_attribute_file=none + local permission_access_directory=none + local permission_access_file=none + + # control variables + local self=rule + local operation= + local line_number= + local line= + local data= + local requires= + + local path_previous=$PWD + local path_current=$PWD + local rule_url=$6 + local rule_path_base=$7 + local rule_path_rule=$8 + local rule_path_premade=$9 + local rule_file=$rule_oh.rule + + local premade_path= + + local strategy_path=$resume_path + local strategy_file=$kit_operation-$rule-$rule_what-$rule_huh-$rule_oh.variables + + local resume_file=$kit_operation-$rule-$rule_what-$rule_huh-$rule_oh.resume + local resume_rule_path=$resume_path + local resume_rule_file=$kit_operation-$rule-$rule_what-$rule_huh-$rule_oh.rule + + local if_condition= + + # dynamic variable management + local dynamic_optional= + local dynamic_required= + + # strategy data management + local strategy_data= + local strategy_length= + local strategy_names= + + # strategy data management + local inline_data= + local inline_length= + local inline_names= + + # other variables + local c= + local t= + local total= + local temporary= + + + if [[ ! -f $system_cache_path$rule_path_base$rule_path_rule$rule_file ]] ; then + kit_rule_error "Failed to find the rules file '$c_notice$system_cache_path$rule_path_base$rule_path_rule$rule_file$c_error'" + fi + + + kit_log_section + kit_log_message message "now ${kit_operation}ing '$rule' '$rule_what' '$rule_huh' '$rule_oh' from $rule_type" + + + # ensure that the rule resume file exists + if [[ ! -f $resume_path$resume_file || $resume_execution != "yes" ]] ; then + echo -e "# fss-0001\n" > $resume_path$resume_file + fi + + + # about: + data=$about_flags + kit_rule_read about_from about from 0 + kit_rule_read about_copyright about copyright 0 + kit_rule_read about_flags about flags 0 + about_flags="$about_flags$data " + data= + + if [[ $(echo "$about_flags" | grep -s -o '\') != "" ]] ; then + premade_path="$system_cache_path$rule_path_base$rule_path_premade" + kit_rule_repository_load_premade + fi + + + # provides: + kit_rule_read provides provides + + + # requires: + kit_rule_read requires requires + + + # generate and preprocess the strategy list + kit_dynamic_strategy_prepare + + + if [[ ! -f $resume_rule_path$resume_rule_file ]] ; then + resume_execution= + fi + + # perform resume if requested + if [[ $resume_execution == "yes" ]] ; then + kit_log_message message "now resuming '$resume_rule_path$resume_rule_file' using '$resume_path$resume_file'" + + # load resume line + c=$(fss_extended_read -n line -c 0 -s 0 $resume_path$resume_file) + + if [[ $(kit_fss_has_error) != "" ]] ; then + kit_rule_error "Failed to read '$c_notice$resume_path$resume_file$c_error', cannot resume" + fi + + if [[ $c -ge 0 ]] ; then + let line_number=$c+1 + + # process all custom operations that provide resume functions + kit_operation_mode_resume + kit_operation_group_resume + kit_operation_attribute_resume + kit_operation_access_resume + + kit_operation_path_resume + kit_operation_version_resume + + kit_dynamic_inline_resume + else + resume_execution= + fi + fi + + if [[ $resume_execution != "yes" ]] ; then + # $rule_type: + if [[ ! $(fss_basic_list_read $system_cache_path$rule_path_base$rule_path_rule$rule_file -t -n $rule_type) -gt 0 ]] ; then + kit_rule_error "There is no target type of '$c_notice$rule_type$c_error' defined in the file '$c_notice$system_cache_path$rule_path_base$rule_path_rule$rule_file$c_error'" + fi + + kit_message_shell "fss_basic_list_read $system_cache_path$rule_path_base$rule_path_rule$rule_file -n $rule_type > $resume_rule_path$resume_rule_file" + fss_basic_list_read $system_cache_path$rule_path_base$rule_path_rule$rule_file -n $rule_type > $resume_rule_path$resume_rule_file + + if [[ $(kit_fss_has_error) != "" ]] ; then + kit_rule_error "Failed to generate '$c_notice$resume_rule_path$resume_rule_file$c_error' from '$c_notice$rule_type$c_error' of the file '$c_notice$system_cache_path$rule_path_base$rule_path_rule$rule_file$c_error'" + fi + + kit_dynamic_required_load_names "$resume_rule_path" "$resume_rule_file" + kit_dynamic_optional_load_names "$resume_rule_path" "$resume_rule_file" + + kit_dynamic_process required "$resume_rule_path" "$resume_rule_file" "$parent-$rule" + kit_dynamic_process optional "$resume_rule_path" "$resume_rule_file" "$parent-$rule" + + let c=0 + fi + + # begin processing the generated rules file + total=$(fss_basic_read -t $resume_rule_path$resume_rule_file) + + if [[ $(kit_fss_has_error) != "" || $(kit_core_is_empty $total) == "" ]] ; then + kit_rule_error "Failed to load the generated rules file '$c_notice$resume_rule_path$resume_rule_file$c_error'" + fi + + while [[ $c -lt $total ]] ; do + operation=$(fss_basic_read -c $c -o $resume_rule_path$resume_rule_file) + line=$(fss_basic_read -c $c $resume_rule_path$resume_rule_file) + let line_number=$c+1 + + sed -i -e '/^[[:space:]]*line\>/d' $resume_path$resume_file + temporary=$(fss_extended_write -s -p "$c") + echo "$(fss_extended_write -s -o line)$temporary" >> $resume_path$resume_file + + kit_dynamic_process inline "$parent-$rule" + + case $operation in + "shell") kit_operation_shell ;; + "version") kit_operation_version ;; + "attribute") kit_operation_attribute ;; + "mode") kit_operation_mode ;; + "group") kit_operation_group ;; + "access") kit_operation_access ;; + "directory" | "directory_dereference") kit_operation_directory ;; + "file" | "file_dereference" | "file_safe" | "file_new" | "file_new_dereference" | "executable" | "executable_dereference" | "executable_safe") kit_operation_file ;; + "library") kit_operation_library ;; + "strip") kit_operation_strip ;; + "path") kit_operation_path ;; + *) kit_message_warning "No such operation called '$c_notice$operation$c_reset'" + esac + + let c++ + done + + + # do cleanup + + # always remove resume file on proper exit + if [[ -f $resume_path$resume_file ]] ; then + rm -f $resume_path$resume_file + fi + + if [[ $do_cleanup == "y" ]] ; then + if [[ -f $strategy_path$strategy_file ]] ; then + rm -f $strategy_path$strategy_file + fi + + if [[ -f $resume_rule_path$resume_rule_file ]] ; then + rm -f $resume_rule_path$resume_rule_file + fi + fi +} diff --git a/sources/sh/kit-core b/sources/sh/kit-core new file mode 100755 index 0000000..75c23bc --- /dev/null +++ b/sources/sh/kit-core @@ -0,0 +1,244 @@ +#!/bin/bash +# License: lgpl v2 + +standard_unset(){ + unset standard_main_execute + unset standard_main + unset standard_prepare_input + unset standard_handle_colors + unset standard_help_title + unset standard_help_options + unset standard_error + unset standard_warning + unset standard_is_empty + unset standard_unset + unset standard_to_lower + unset standard_to_upper + unset standard_alpha_numeric + unset standard_directory_ending + unset standard_get_random +} + +standard_main(){ + local public_name= + local system_name= + local called_name= + local version= + local the_operation= + local grab_next= + local do_color=normal + local do_help= + local i= + local count= + + if [[ $# -gt 0 ]] ; then + local main_input= + local main_size=$# + + while [[ $count -lt $main_size ]] ; do + let i=$count+1 + main_input[$count]=${!i} + let count=$count+1 + done + + i= + count=0 + fi + + local c_reset="\\033[0m" + local c_title="\\033[1;33m" + local c_error="\\033[1;31m" + local c_warning="\\033[0;33m" + local c_highlight="\\033[1;32m" + local c_notice="\\033[0;01m" + local c_important="\\033[0;32m" + local c_subtle="\\033[1;30m" + local c_prefix="\\" + + $standard_main_execute +} + +standard_handle_colors(){ + if [[ $do_color == "light" ]] ; then + c_error="\\033[1;31m" + c_warning="\\033[0;31m" + c_title="\\033[1;34m" + c_highlight="\\033[0;34m" + c_notice="\\033[0;01m" + c_important="\\033[0;35m" + elif [[ $do_color == "none" ]] ; then + c_reset= + c_title= + c_error= + c_warning= + c_highlight= + c_notice= + c_important= + c_subtle= + c_prefix= + fi +} + +standard_help_title(){ + echo + echo -e "${c_title}$public_name$c_reset" + echo -e " ${c_notice}Version $version$c_reset" + echo +} + +standard_help_options(){ + echo -e "${c_highlight}Options:$c_reset" + echo -e " -${c_important}h${c_reset}, --${c_important}help${c_reset} Print this help screen" + echo -e " +${c_important}l${c_reset}, ++${c_important}light${c_reset} Use color modes that show up better on light backgrounds" + echo -e " +${c_important}n${c_reset}, ++${c_important}no_color${c_reset} Do not use color" + echo -e " +${c_important}v${c_reset}, ++${c_important}version${c_reset} Print the version number of this program" + echo +} + +standard_error(){ + echo -e "${c_error}ERROR: $*$c_reset" +} + +standard_warning(){ + echo -e "${c_warning}WARNING: $*$c_reset" +} + +standard_is_empty(){ + if [[ $(echo $1 | sed -e "s|[[:space:]]||g") != "" ]] ; then + echo -n n + fi +} + +standard_to_lower(){ + echo -n $(echo $* | sed -e 's/\(.*\)/\L\1/') +} + +standard_to_upper(){ + echo -n $(echo $* | sed -e 's/\(.*\)/\U\1/') +} + +standard_alpha_numeric(){ + echo -n $(echo $* | sed -e 's|[[:punct:][:space:][:cntrl:]]*||g') +} + +standard_directory_ending(){ + echo -n $(echo $i | sed -e 's|/*$|/|') +} + +standard_datetimestamp(){ + echo -n $(date +%Y-%m-%dT%H:%M:%S%z) +} + +standard_datetimestamp_safe(){ + echo -n $(date +%Y_%m_%d-%H_%M_%S%z) +} + +standard_get_random(){ + local method=$1 + local minimum=$2 + local maximum=$3 + local current=0 + local goal=$[ ( $RANDOM % $maximum ) ] + local number= + + if [[ $goal -lt $minimum ]] ; then + let goal=$minimum + fi + + while [[ $current -lt $goal ]] ; do + if [[ $method == "numeric" ]] ; then + number=$[ ( $RANDOM % 10 ) ] + elif [[ $method == "alphanumeric" ]] ; then + number=$[ ( $RANDOM % 62 ) ] + elif [[ $method == "all" ]] ; then + number=$[ ( $RANDOM % 89 ) ] + fi + + case $number in + "10") echo -n "A";; + "11") echo -n "B";; + "12") echo -n "C";; + "13") echo -n "D";; + "14") echo -n "E";; + "15") echo -n "F";; + "16") echo -n "G";; + "17") echo -n "H";; + "18") echo -n "I";; + "19") echo -n "J";; + "20") echo -n "K";; + "21") echo -n "L";; + "22") echo -n "M";; + "23") echo -n "N";; + "24") echo -n "O";; + "25") echo -n "P";; + "26") echo -n "Q";; + "27") echo -n "R";; + "28") echo -n "S";; + "29") echo -n "T";; + "30") echo -n "U";; + "31") echo -n "V";; + "32") echo -n "W";; + "33") echo -n "X";; + "34") echo -n "Y";; + "35") echo -n "Z";; + "36") echo -n "a";; + "37") echo -n "b";; + "38") echo -n "c";; + "39") echo -n "d";; + "40") echo -n "e";; + "41") echo -n "f";; + "42") echo -n "g";; + "43") echo -n "h";; + "44") echo -n "i";; + "45") echo -n "j";; + "46") echo -n "k";; + "47") echo -n "l";; + "48") echo -n "m";; + "49") echo -n "n";; + "50") echo -n "o";; + "51") echo -n "p";; + "52") echo -n "q";; + "53") echo -n "r";; + "54") echo -n "s";; + "55") echo -n "t";; + "56") echo -n "u";; + "57") echo -n "v";; + "58") echo -n "w";; + "59") echo -n "x";; + "60") echo -n "y";; + "61") echo -n "z";; + "62") echo -n "~";; + "63") echo -n "!";; + "64") echo -n "@";; + "65") echo -n "#";; + "66") echo -n "$";; + "67") echo -n "%";; + "68") echo -n "^";; + "69") echo -n "&";; + "70") echo -n "*";; + "71") echo -n "(";; + "72") echo -n ")";; + "73") echo -n "-";; + "74") echo -n "+";; + "75") echo -n "\`";; + "76") echo -n "\"";; + "77") echo -n "'";; + "78") echo -n "{";; + "79") echo -n "}";; + "80") echo -n "[";; + "81") echo -n "]";; + "82") echo -n "|";; + "83") echo -n "\\";; + "84") echo -n ";";; + "85") echo -n ">";; + "86") echo -n "<";; + "87") echo -n ",";; + "88") echo -n ".";; + "87") echo -n "=";; + "88") echo -n "_";; + *) echo -n $number;; + esac + + let current=$current+1 + done +} -- 1.8.3.1