From c534ea1c7906a3de3b9ab1aa18e30b9129494f82 Mon Sep 17 00:00:00 2001 From: Michael Wesemann Date: Mon, 10 Aug 2026 16:12:09 +0200 Subject: [PATCH] initial commit [141.14.140.180,mike] --- .gitignore | 10 + README | 46 + extra.setup | 39 + extra/config/btop/btop.conf | 218 +++ extra/config/eza/theme.yml | 123 ++ extra/config/lsd/colors.yaml | 39 + extra/config/lsd/config.yaml | 150 ++ .../config/yazi/flavors/mwx.yazi/flavor.toml | 185 +++ .../yazi/flavors/mwx.yazi/flavor.toml.bak | 159 +++ extra/config/yazi/keymap.toml | 4 + extra/config/yazi/package.toml | 5 + extra/config/yazi/theme.toml | 2 + extra/config/yazi/yazi.toml | 3 + extra/omp.json | 133 ++ extra/zshrc | 27 + files/authorized_keys | 3 + files/csh.cshrc | 49 + files/default.jcf | 83 ++ files/dx | 95 ++ files/gx | 20 + files/gy | 51 + files/joerc | 99 ++ files/joerc4 | 104 ++ files/locale | 1 + files/mbackup | 573 ++++++++ files/mgsh | 525 +++++++ files/mybackup | 195 +++ files/myuser | 43 + files/psmem | 611 ++++++++ files/rc.local.debian | 3 + files/rc.local.ubuntu | 6 + files/rt | 289 ++++ files/telemetry | 43 + files/timesyncd.conf | 26 + files/zshrc | 96 ++ go.setup | 25 + perlmodules/MD5-1.7/Changes | 83 ++ perlmodules/MD5-1.7/MANIFEST | 13 + perlmodules/MD5-1.7/MD5.pm | 263 ++++ perlmodules/MD5-1.7/MD5.xs | 101 ++ perlmodules/MD5-1.7/Makefile.PL | 13 + perlmodules/MD5-1.7/Makefile.old | 1027 ++++++++++++++ perlmodules/MD5-1.7/README | 42 + perlmodules/MD5-1.7/examples/mddriver.pl | 69 + perlmodules/MD5-1.7/examples/twdigest.pl | 35 + perlmodules/MD5-1.7/global.h | 49 + perlmodules/MD5-1.7/md5.h | 36 + perlmodules/MD5-1.7/md5c.c | 351 +++++ perlmodules/MD5-1.7/test.pl | 154 +++ perlmodules/MD5-1.7/typemap | 3 + perlmodules/mwx-1.21/Changes | 6 + perlmodules/mwx-1.21/MANIFEST | 6 + perlmodules/mwx-1.21/Makefile.PL | 17 + perlmodules/mwx-1.21/Makefile.old | 864 ++++++++++++ perlmodules/mwx-1.21/README | 35 + perlmodules/mwx-1.21/mwx.pm | 281 ++++ perlmodules/mwx-1.21/test.pl | 45 + restic.config.enc | 6 + restic.setup | 117 ++ setup.debian1x | 114 ++ setup.phpini | 60 + setup.rpi | 34 + setup.ssh | 24 + setup.ubuntu2x | 58 + telemetry.setup | 28 + upd | 1227 +++++++++++++++++ 66 files changed, 9244 insertions(+) create mode 100644 .gitignore create mode 100644 README create mode 100755 extra.setup create mode 100644 extra/config/btop/btop.conf create mode 100644 extra/config/eza/theme.yml create mode 100644 extra/config/lsd/colors.yaml create mode 100644 extra/config/lsd/config.yaml create mode 100644 extra/config/yazi/flavors/mwx.yazi/flavor.toml create mode 100644 extra/config/yazi/flavors/mwx.yazi/flavor.toml.bak create mode 100644 extra/config/yazi/keymap.toml create mode 100644 extra/config/yazi/package.toml create mode 100644 extra/config/yazi/theme.toml create mode 100644 extra/config/yazi/yazi.toml create mode 100644 extra/omp.json create mode 100644 extra/zshrc create mode 100644 files/authorized_keys create mode 100644 files/csh.cshrc create mode 100644 files/default.jcf create mode 100755 files/dx create mode 100755 files/gx create mode 100755 files/gy create mode 100755 files/joerc create mode 100755 files/joerc4 create mode 100644 files/locale create mode 100755 files/mbackup create mode 100755 files/mgsh create mode 100755 files/mybackup create mode 100755 files/myuser create mode 100755 files/psmem create mode 100644 files/rc.local.debian create mode 100644 files/rc.local.ubuntu create mode 100755 files/rt create mode 100755 files/telemetry create mode 100644 files/timesyncd.conf create mode 100644 files/zshrc create mode 100755 go.setup create mode 100644 perlmodules/MD5-1.7/Changes create mode 100644 perlmodules/MD5-1.7/MANIFEST create mode 100644 perlmodules/MD5-1.7/MD5.pm create mode 100644 perlmodules/MD5-1.7/MD5.xs create mode 100644 perlmodules/MD5-1.7/Makefile.PL create mode 100644 perlmodules/MD5-1.7/Makefile.old create mode 100644 perlmodules/MD5-1.7/README create mode 100644 perlmodules/MD5-1.7/examples/mddriver.pl create mode 100644 perlmodules/MD5-1.7/examples/twdigest.pl create mode 100644 perlmodules/MD5-1.7/global.h create mode 100644 perlmodules/MD5-1.7/md5.h create mode 100644 perlmodules/MD5-1.7/md5c.c create mode 100644 perlmodules/MD5-1.7/test.pl create mode 100644 perlmodules/MD5-1.7/typemap create mode 100644 perlmodules/mwx-1.21/Changes create mode 100644 perlmodules/mwx-1.21/MANIFEST create mode 100644 perlmodules/mwx-1.21/Makefile.PL create mode 100644 perlmodules/mwx-1.21/Makefile.old create mode 100644 perlmodules/mwx-1.21/README create mode 100644 perlmodules/mwx-1.21/mwx.pm create mode 100644 perlmodules/mwx-1.21/test.pl create mode 100644 restic.config.enc create mode 100755 restic.setup create mode 100755 setup.debian1x create mode 100755 setup.phpini create mode 100755 setup.rpi create mode 100755 setup.ssh create mode 100755 setup.ubuntu2x create mode 100755 telemetry.setup create mode 100755 upd diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3a5465c --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +.DS_Store +.AppleDouble +.LSOverride +._* +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.mgshrc diff --git a/README b/README new file mode 100644 index 0000000..7e4853f --- /dev/null +++ b/README @@ -0,0 +1,46 @@ + +-------------------- Debian 10/11/12 -------------------- +# su - +# apt install git; git clone https://git.fhi.mpg.de/mike/linuxsetup +# cd ~/linuxsetup; ./setup.ssh +relogin as root +# cd ~/linuxsetup; ./setup.debian1x +# cd ~/linuxsetup; ./telemetry.setup + +-------------------- Raspberry Pi OS -------------------- +# sudo passwd root +# su - +# apt install git; git clone https://git.fhi.mpg.de/mike/linuxsetup +# cd ~/linuxsetup; ./setup.ssh +relogin as root +# cd ~/linuxsetup; ./setup.debian1x +# cd ~/linuxsetup; ./telemetry.setup + +-------------------- Ubuntu 18/20/22 -------------------- +# sudo passwd root +# su - +# git clone https://git.fhi.mpg.de/mike/linuxsetup +# cd ~/linuxsetup; ./setup.ssh +relogin as root +# cd ~/linuxsetup; ./setup.ubuntu2x +# cd ~/linuxsetup; ./telemetry.setup + +-------------------- restic backup -------------------- +decrypt restic conf (password: quo...): +# openssl enc -a -d -aes-256-cbc -salt -pbkdf2 -iter 1000000 -in restic.config.enc +# ./restic.setup +# rt backup +check crontab + +-------------------- mariadb -------------------- +# apt install mariadb-server +MariaDB> ALTER USER root@localhost IDENTIFIED VIA mysql_native_password USING PASSWORD("eizohphu"); +# mybackup -a +# myuser + +-------------------- go -------------------- +# wget https://go.dev/dl/go1.25.4.linux-arm64.tar.gz +# rm -rf /db/go && tar -C /db -xzf go1.25.4.linux-arm64.tar.gz +export PATH=/db/go/bin:$PATH +export CGO_ENABLED=0 + diff --git a/extra.setup b/extra.setup new file mode 100755 index 0000000..8bb6265 --- /dev/null +++ b/extra.setup @@ -0,0 +1,39 @@ +#!/usr/bin/perl +######################################################################################## extra setup (mwx'2025) +use Config; + +$HOME=$ENV{"HOME"}; + + + +if ($Config{archname}=~/^darwin/) { + if ($Config{myuname}=~/arm64/) { + system("brew install eza"); + } +} else { + system("./upd https://github.com/eza-community/eza -i /db/bin") + +} + +system("mkdir -p $HOME/.config"); +system("cp -r extra/config/eza $HOME/.config"); + +system("./upd https://github.com/sxyazi/yazi -i /db/bin") + + +system("mkdir -p $HOME/.config"); +system("cp -r extra/config/yazi $HOME/.config"); + + +system("curl -s https://ohmyposh.dev/install.sh | bash -s -- -d /db/bin"); +system("mkdir -p /db/etc"); +system("cp extra/omp.json /db/etc/"); + + +system("git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf"); +system("~/.fzf/install"); + +system("cp -r extra/zshrc $HOME/.zshrc"); + + +########################################################################################################### END diff --git a/extra/config/btop/btop.conf b/extra/config/btop/btop.conf new file mode 100644 index 0000000..0c431b9 --- /dev/null +++ b/extra/config/btop/btop.conf @@ -0,0 +1,218 @@ +#? Config file for btop v. 1.4.0 + +#* Name of a btop++/bpytop/bashtop formatted ".theme" file, "Default" and "TTY" for builtin themes. +#* Themes should be placed in "../share/btop/themes" relative to binary or "$HOME/.config/btop/themes" +color_theme = "Default" + +#* If the theme set background should be shown, set to False if you want terminal background transparency. +theme_background = False + +#* Sets if 24-bit truecolor should be used, will convert 24-bit colors to 256 color (6x6x6 color cube) if false. +truecolor = True + +#* Set to true to force tty mode regardless if a real tty has been detected or not. +#* Will force 16-color mode and TTY theme, set all graph symbols to "tty" and swap out other non tty friendly symbols. +force_tty = False + +#* Define presets for the layout of the boxes. Preset 0 is always all boxes shown with default settings. Max 9 presets. +#* Format: "box_name:P:G,box_name:P:G" P=(0 or 1) for alternate positions, G=graph symbol to use for box. +#* Use whitespace " " as separator between different presets. +#* Example: "cpu:0:default,mem:0:tty,proc:1:default cpu:0:braille,proc:0:tty" +presets = "cpu:1:default,proc:0:default cpu:0:default,mem:0:default,net:0:default cpu:0:block,net:0:tty" + +#* Set to True to enable "h,j,k,l,g,G" keys for directional control in lists. +#* Conflicting keys for h:"help" and k:"kill" is accessible while holding shift. +vim_keys = False + +#* Rounded corners on boxes, is ignored if TTY mode is ON. +rounded_corners = True + +#* Default symbols to use for graph creation, "braille", "block" or "tty". +#* "braille" offers the highest resolution but might not be included in all fonts. +#* "block" has half the resolution of braille but uses more common characters. +#* "tty" uses only 3 different symbols but will work with most fonts and should work in a real TTY. +#* Note that "tty" only has half the horizontal resolution of the other two, so will show a shorter historical view. +graph_symbol = "braille" + +# Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty". +graph_symbol_cpu = "default" + +# Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty". +graph_symbol_mem = "default" + +# Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty". +graph_symbol_net = "default" + +# Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty". +graph_symbol_proc = "default" + +#* Manually set which boxes to show. Available values are "cpu mem net proc" and "gpu0" through "gpu5", separate values with whitespace. +shown_boxes = "cpu mem net proc" + +#* Update time in milliseconds, recommended 2000 ms or above for better sample times for graphs. +update_ms = 500 + +#* Processes sorting, "pid" "program" "arguments" "threads" "user" "memory" "cpu lazy" "cpu direct", +#* "cpu lazy" sorts top process over time (easier to follow), "cpu direct" updates top process directly. +proc_sorting = "cpu lazy" + +#* Reverse sorting order, True or False. +proc_reversed = False + +#* Show processes as a tree. +proc_tree = False + +#* Use the cpu graph colors in the process list. +proc_colors = True + +#* Use a darkening gradient in the process list. +proc_gradient = True + +#* If process cpu usage should be of the core it's running on or usage of the total available cpu power. +proc_per_core = True + +#* Show process memory as bytes instead of percent. +proc_mem_bytes = True + +#* Show cpu graph for each process. +proc_cpu_graphs = True + +#* Use /proc/[pid]/smaps for memory information in the process info box (very slow but more accurate) +proc_info_smaps = False + +#* Show proc box on left side of screen instead of right. +proc_left = False + +#* (Linux) Filter processes tied to the Linux kernel(similar behavior to htop). +proc_filter_kernel = False + +#* In tree-view, always accumulate child process resources in the parent process. +proc_aggregate = False + +#* Sets the CPU stat shown in upper half of the CPU graph, "total" is always available. +#* Select from a list of detected attributes from the options menu. +cpu_graph_upper = "Auto" + +#* Sets the CPU stat shown in lower half of the CPU graph, "total" is always available. +#* Select from a list of detected attributes from the options menu. +cpu_graph_lower = "Auto" + +#* Toggles if the lower CPU graph should be inverted. +cpu_invert_lower = True + +#* Set to True to completely disable the lower CPU graph. +cpu_single_graph = False + +#* Show cpu box at bottom of screen instead of top. +cpu_bottom = False + +#* Shows the system uptime in the CPU box. +show_uptime = True + +#* Show cpu temperature. +check_temp = True + +#* Which sensor to use for cpu temperature, use options menu to select from list of available sensors. +cpu_sensor = "Auto" + +#* Show temperatures for cpu cores also if check_temp is True and sensors has been found. +show_coretemp = True + +#* Set a custom mapping between core and coretemp, can be needed on certain cpus to get correct temperature for correct core. +#* Use lm-sensors or similar to see which cores are reporting temperatures on your machine. +#* Format "x:y" x=core with wrong temp, y=core with correct temp, use space as separator between multiple entries. +#* Example: "4:0 5:1 6:3" +cpu_core_map = "" + +#* Which temperature scale to use, available values: "celsius", "fahrenheit", "kelvin" and "rankine". +temp_scale = "celsius" + +#* Use base 10 for bits/bytes sizes, KB = 1000 instead of KiB = 1024. +base_10_sizes = False + +#* Show CPU frequency. +show_cpu_freq = True + +#* Draw a clock at top of screen, formatting according to strftime, empty string to disable. +#* Special formatting: /host = hostname | /user = username | /uptime = system uptime +clock_format = "%X" + +#* Update main ui in background when menus are showing, set this to false if the menus is flickering too much for comfort. +background_update = True + +#* Custom cpu model name, empty string to disable. +custom_cpu_name = "" + +#* Optional filter for shown disks, should be full path of a mountpoint, separate multiple values with whitespace " ". +#* Begin line with "exclude=" to change to exclude filter, otherwise defaults to "most include" filter. Example: disks_filter="exclude=/boot /home/user". +disks_filter = "" + +#* Show graphs instead of meters for memory values. +mem_graphs = True + +#* Show mem box below net box instead of above. +mem_below_net = False + +#* Count ZFS ARC in cached and available memory. +zfs_arc_cached = True + +#* If swap memory should be shown in memory box. +show_swap = True + +#* Show swap as a disk, ignores show_swap value above, inserts itself after first disk. +swap_disk = True + +#* If mem box should be split to also show disks info. +show_disks = True + +#* Filter out non physical disks. Set this to False to include network disks, RAM disks and similar. +only_physical = True + +#* Read disks list from /etc/fstab. This also disables only_physical. +use_fstab = True + +#* Setting this to True will hide all datasets, and only show ZFS pools. (IO stats will be calculated per-pool) +zfs_hide_datasets = False + +#* Set to true to show available disk space for privileged users. +disk_free_priv = False + +#* Toggles if io activity % (disk busy time) should be shown in regular disk usage view. +show_io_stat = True + +#* Toggles io mode for disks, showing big graphs for disk read/write speeds. +io_mode = False + +#* Set to True to show combined read/write io graphs in io mode. +io_graph_combined = False + +#* Set the top speed for the io graphs in MiB/s (100 by default), use format "mountpoint:speed" separate disks with whitespace " ". +#* Example: "/mnt/media:100 /:20 /boot:1". +io_graph_speeds = "" + +#* Set fixed values for network graphs in Mebibits. Is only used if net_auto is also set to False. +net_download = 100 + +net_upload = 100 + +#* Use network graphs auto rescaling mode, ignores any values set above and rescales down to 10 Kibibytes at the lowest. +net_auto = False + +#* Sync the auto scaling for download and upload to whichever currently has the highest scale. +net_sync = False + +#* Starts with the Network Interface specified here. +net_iface = "" + +#* Show battery stats in top right if battery is present. +show_battery = True + +#* Which battery to use if multiple are present. "Auto" for auto detection. +selected_battery = "Auto" + +#* Show power stats of battery next to charge indicator. +show_battery_watts = True + +#* Set loglevel for "~/.config/btop/btop.log" levels are: "ERROR" "WARNING" "INFO" "DEBUG". +#* The level set includes all lower levels, i.e. "DEBUG" will show all logging info. +log_level = "WARNING" diff --git a/extra/config/eza/theme.yml b/extra/config/eza/theme.yml new file mode 100644 index 0000000..5787a96 --- /dev/null +++ b/extra/config/eza/theme.yml @@ -0,0 +1,123 @@ +# eza theme — Palette aus coltest.go +# +# white #F0F0EA pink #F5B2F7 +# yellow #F9E2AF violet #CBA6F7 +# orange #FAB387 grey #AAAABB +# red #F38BA8 dark #777788 +# green #94E2D5 darker #444455 +# blue #B4BEFE +# +# Ort: ~/.config/eza/theme.yml (oder $EZA_CONFIG_DIR/theme.yml) +# Getestet mit eza 0.23.5. + +colourful: true + +filekinds: + normal: {foreground: "#F0F0EA"} # white + directory: {foreground: "#B4BEFE", is_bold: true} # blue + symlink: {foreground: "#F5B2F7", is_underline: false} # pink + pipe: {foreground: "#CBA6F7"} # violet + block_device: {foreground: "#FAB387"} # orange + char_device: {foreground: "#F9E2AF"} # yellow + socket: {foreground: "#F5B2F7", is_bold: true} # pink + special: {foreground: "#CBA6F7"} # violet + executable: {foreground: "#94E2D5", is_bold: true} # green + mount_point: {foreground: "#B4BEFE", is_underline: false} + +perms: + user_read: {foreground: "#94E2D5"} # green + user_write: {foreground: "#F9E2AF"} # yellow + user_execute_file: {foreground: "#F38BA8", is_underline: false} # red + user_execute_other: {foreground: "#F38BA8", is_underline: false} # red + group_read: {foreground: "#94E2D5"} + group_write: {foreground: "#F9E2AF"} + group_execute: {foreground: "#F38BA8", is_underline: false} + other_read: {foreground: "#94E2D5"} + other_write: {foreground: "#F9E2AF"} + other_execute: {foreground: "#F38BA8", is_underline: false} + special_user_file: {foreground: "#F5B2F7", is_underline: false} # pink — setuid + special_other: {foreground: "#F5B2F7", is_underline: false} # pink + attribute: {foreground: "#777788"} # dark — @ / xattr + +size: + number_byte: {foreground: "#94E2D5"} # green + number_kilo: {foreground: "#94E2D5"} + number_mega: {foreground: "#F9E2AF"} # yellow + number_giga: {foreground: "#FAB387"} # orange + number_huge: {foreground: "#F38BA8"} # red + unit_byte: {foreground: "#94E2D5"} + unit_kilo: {foreground: "#94E2D5"} + unit_mega: {foreground: "#F9E2AF"} + unit_giga: {foreground: "#FAB387"} + unit_huge: {foreground: "#F38BA8"} + major: {foreground: "#CBA6F7"} # violet — Device-Nummern + minor: {foreground: "#F5B2F7"} # pink + +users: + user_you: {foreground: "#F0F0EA"} # white + user_root: {foreground: "#F38BA8"} # red + user_other: {foreground: "#AAAABB"} # grey + group_yours: {foreground: "#AAAABB"} # grey + group_other: {foreground: "#777788"} # dark + group_root: {foreground: "#F38BA8"} # red + +links: + normal: {foreground: "#F5B2F7"} # pink + multi_link_file: {foreground: "#CBA6F7"} # violet + +git: + new: {foreground: "#94E2D5"} # green + modified: {foreground: "#F9E2AF"} # yellow + deleted: {foreground: "#F38BA8"} # red + renamed: {foreground: "#CBA6F7"} # violet + typechange: {foreground: "#FAB387"} # orange + ignored: {foreground: "#444455"} # darker + conflicted: {foreground: "#F5B2F7"} # pink + +git_repo: + branch_main: {foreground: "#94E2D5"} # green + branch_other: {foreground: "#CBA6F7"} # violet + git_clean: {foreground: "#94E2D5"} # green + git_dirty: {foreground: "#F9E2AF"} # yellow + +security_context: + none: {foreground: "#777788"} # dark + selinux: + colon: {foreground: "#444455"} + user: {foreground: "#B4BEFE"} + role: {foreground: "#CBA6F7"} + typ: {foreground: "#F5B2F7"} + range: {foreground: "#F9E2AF"} + +file_type: + image: {foreground: "#CBA6F7"} # violet + video: {foreground: "#F5B2F7"} # pink + music: {foreground: "#94E2D5"} # green + lossless: {foreground: "#94E2D5"} # green + crypto: {foreground: "#F38BA8"} # red + document: {foreground: "#F0F0EA"} # white + compressed: {foreground: "#FAB387"} # orange + temp: {foreground: "#444455"} # darker + compiled: {foreground: "#AAAABB"} # grey + build: {foreground: "#F9E2AF", is_underline: false} # yellow — README, Makefile, … + source: {foreground: "#B4BEFE"} # blue + +punctuation: {foreground: "#444455"} # darker — die - in rwx +date: {foreground: "#B4BEFE"} # blue +inode: {foreground: "#F5B2F7"} # pink +blocks: {foreground: "#777788"} # dark +header: {foreground: "#AAAABB", is_underline: false} # grey +octal: {foreground: "#777788"} # dark +flags: {foreground: "#FAB387"} # orange +symlink_path: {foreground: "#CBA6F7", is_underline: false} # violet +control_char: {foreground: "#F38BA8"} # red +broken_symlink: {foreground: "#F38BA8", is_underline: false} # red +broken_path_overlay: {foreground: "#F38BA8", is_underline: false} + +# Eigene Regeln pro Dateiname / Endung — das, was lsd nicht kann: +# +# filenames: +# Makefile: {filename: {foreground: "#F38BA8", is_bold: true}} +# extensions: +# go: {filename: {foreground: "#94E2D5"}} +# md: {filename: {foreground: "#B4BEFE"}} diff --git a/extra/config/lsd/colors.yaml b/extra/config/lsd/colors.yaml new file mode 100644 index 0000000..d8a8251 --- /dev/null +++ b/extra/config/lsd/colors.yaml @@ -0,0 +1,39 @@ +user: 230 +group: 187 +permission: + read: green + write: yellow + exec: red + exec-sticky: 5 + no-access: 245 + octal: 6 + acl: dark_cyan + context: cyan +date: + hour-old: 159 + day-old: 158 + older: 157 +size: + none: 245 + small: 229 + medium: 216 + large: 172 +inode: + valid: 219 + invalid: 245 +links: + valid: 13 + invalid: 245 +tree-edge: 245 +git-status: + default: 245 + unmodified: 245 + ignored: 245 + new-in-index: green + new-in-workdir: green + typechange: yellow + deleted: red + renamed: green + modified: yellow + conflicted: red + \ No newline at end of file diff --git a/extra/config/lsd/config.yaml b/extra/config/lsd/config.yaml new file mode 100644 index 0000000..1727180 --- /dev/null +++ b/extra/config/lsd/config.yaml @@ -0,0 +1,150 @@ +# == Classic == +# This is a shorthand to override some of the options to be backwards compatible +# with `ls`. It affects the "color"->"when", "sorting"->"dir-grouping", "date" +# and "icons"->"when" options. +# Possible values: false, true +classic: false + +# == Blocks == +# This specifies the columns and their order when using the long and the tree +# layout. +# Possible values: permission, user, group, context, size, date, name, inode, links, git +blocks: + - permission + - user + - date + - size + - git + - name + + +# == Color == +# This has various color options. (Will be expanded in the future.) +color: + # When to colorize the output. + # When "classic" is set, this is set to "never". + # Possible values: never, auto, always + when: auto + # How to colorize the output. + # When "classic" is set, this is set to "no-color". + # Possible values: default, custom + # When "custom" is set, lsd will look in the config directory for `colors.yaml`. + theme: custom + +# == Date == +# This specifies the date format for the date column. The freeform format +# accepts a strftime like string. +# When "classic" is set, this is set to "date". +# Possible values: date, locale, relative, '+' +# `date_format` will be a `strftime` formatted value. e.g. `date: '+%d %b %y %X'` will give you a date like this: 17 Jun 21 20:14:55 +date: date + +# == Dereference == +# Whether to dereference symbolic links. +# Possible values: false, true +dereference: false + +# == Display == +# What items to display. Do not specify this for the default behavior. +# Possible values: all, almost-all, directory-only +# display: all + +# == Icons == +icons: + # When to use icons. + # When "classic" is set, this is set to "never". + # Possible values: always, auto, never + when: auto + # Which icon theme to use. + # Possible values: fancy, unicode + theme: fancy + # Separator between icon and the name + # Default to 1 space + separator: " " + +# == Ignore Globs == +# A list of globs to ignore when listing. +# ignore-globs: +# - .git + +# == Indicators == +# Whether to add indicator characters to certain listed files. +# Possible values: false, true +indicators: false + +# == Layout == +# Which layout to use. "oneline" might be a bit confusing here and should be +# called "one-per-line". It might be changed in the future. +# Possible values: grid, tree, oneline +layout: grid + +# == Recursion == +recursion: + # Whether to enable recursion. + # Possible values: false, true + enabled: false + # How deep the recursion should go. This has to be a positive integer. Leave + # it unspecified for (virtually) infinite. + # depth: 3 + +# == Size == +# Specifies the format of the size column. +# Possible values: default, short, bytes +size: default + +# == Permission == +# Specify the format of the permission column +# Possible value: rwx, octal, attributes (windows only), disable +# permission: octal + +# == Sorting == +sorting: + # Specify what to sort by. + # Possible values: extension, name, time, size, version + column: name + # Whether to reverse the sorting. + # Possible values: false, true + reverse: false + # Whether to group directories together and where. + # When "classic" is set, this is set to "none". + # Possible values: first, last, none + dir-grouping: none + +# == No Symlink == +# Whether to omit showing symlink targets +# Possible values: false, true +no-symlink: false + +# == Total size == +# Whether to display the total size of directories. +# Possible values: false, true +total-size: false + +# == Hyperlink == +# Attach hyperlink to filenames +# Possible values: always, auto, never +hyperlink: never + +# == Symlink arrow == +# Specifies how the symlink arrow display, chars in both ascii and utf8 +symlink-arrow: ⇒ + +# == Header == +# Whether to display block headers. +# Possible values: false, true +header: false + +# == Literal == +# Whether to show quotes on filenames. +# Possible values: false, true +literal: false + +# == Truncate owner == +# How to truncate the username and group names for a file if they exceed a certain +# number of characters. +truncate-owner: + # Number of characters to keep. By default, no truncation is done (empty value). + after: + # String to be appended to a name if truncated. + marker: "" + \ No newline at end of file diff --git a/extra/config/yazi/flavors/mwx.yazi/flavor.toml b/extra/config/yazi/flavors/mwx.yazi/flavor.toml new file mode 100644 index 0000000..d0da728 --- /dev/null +++ b/extra/config/yazi/flavors/mwx.yazi/flavor.toml @@ -0,0 +1,185 @@ +# yazi flavor "mwx" — Palette aus coltest.go +# +# white #F0F0EA pink #F5B2F7 +# yellow #F9E2AF violet #CBA6F7 +# orange #FAB387 grey #AAAABB +# red #F38BA8 dark #777788 +# green #94E2D5 darker #444455 +# blue #B4BEFE +# +# Schema: yazi 26.2.2 — [mgr] (früher [manager]), [tabs] (früher tab_* in +# [manager]), [cmp] (früher [completion]), [indicator] (früher hovered/ +# preview_hovered). Alte Sektionsnamen werden von yazi still ignoriert. + +[mgr] +cwd = { fg = "#94E2D5" } + +# Find +find_keyword = { fg = "#F9E2AF", bold = true, italic = true } +find_position = { fg = "#F5B2F7", bg = "reset", bold = true, italic = true } + +# Symlink-Ziel +symlink_target = { fg = "#777788" } + +# Marker +marker_copied = { fg = "#94E2D5", bg = "#94E2D5" } +marker_cut = { fg = "#F38BA8", bg = "#F38BA8" } +marker_marked = { fg = "#CBA6F7", bg = "#CBA6F7" } +marker_selected = { fg = "#FAB387", bg = "#FAB387" } + +# Count +count_copied = { fg = "#444455", bg = "#94E2D5" } +count_cut = { fg = "#444455", bg = "#F38BA8" } +count_selected = { fg = "#444455", bg = "#FAB387" } + +# Border +border_symbol = "│" +border_style = { fg = "#B4BEFE" } + + +[indicator] +# current = die ganze Cursor-Zeile (ersetzt das alte "hovered") +parent = { fg = "#F0F0EA", bg = "#444455" } +current = { fg = "#444455", bg = "#B4BEFE", bold = true } +preview = { fg = "#AAAABB", bg = "#444455" } + + +[tabs] +active = { fg = "#444455", bg = "#B4BEFE", bold = true } +inactive = { fg = "#B4BEFE", bg = "#444455" } + + +[mode] +normal_main = { fg = "#444455", bg = "#B4BEFE", bold = true } +normal_alt = { fg = "#B4BEFE", bg = "#444455" } + +# Select mode +select_main = { fg = "#444455", bg = "#94E2D5", bold = true } +select_alt = { fg = "#94E2D5", bg = "#444455" } + +# Unset mode +unset_main = { fg = "#444455", bg = "#AAAABB", bold = true } +unset_alt = { fg = "#AAAABB", bg = "#444455" } + + +[status] +# Permissions — wie in lsd/eza: read grün, write gelb, exec rot +perm_sep = { fg = "#777788" } +perm_type = { fg = "#B4BEFE" } +perm_read = { fg = "#94E2D5" } +perm_write = { fg = "#F9E2AF" } +perm_exec = { fg = "#F38BA8" } + +# Progress +progress_label = { fg = "#F0F0EA", bold = true } +progress_normal = { fg = "#B4BEFE", bg = "#444455" } +progress_error = { fg = "#F38BA8", bg = "#444455" } + + +[pick] +border = { fg = "#B4BEFE" } +active = { fg = "#F5B2F7", bold = true } +inactive = {} + + +[input] +border = { fg = "#B4BEFE" } +title = {} +value = {} +selected = { reversed = true } + + +[cmp] +border = { fg = "#B4BEFE" } + + +[tasks] +border = { fg = "#B4BEFE" } +title = {} +hovered = { fg = "#F5B2F7", bold = true } + + +[which] +mask = { bg = "#444455" } +cand = { fg = "#94E2D5" } +rest = { fg = "#777788" } +desc = { fg = "#F5B2F7" } +separator = " " +separator_style = { fg = "#777788" } + + +[help] +on = { fg = "#94E2D5" } +run = { fg = "#F5B2F7" } +hovered = { reversed = true, bold = true } +footer = { fg = "#444455", bg = "#F0F0EA" } + + +[spot] +border = { fg = "#B4BEFE" } +title = { fg = "#B4BEFE" } +tbl_col = { fg = "#94E2D5" } +tbl_cell = { fg = "#F5B2F7", bg = "#444455" } + + +[notify] +title_info = { fg = "#94E2D5" } +title_warn = { fg = "#F9E2AF" } +title_error = { fg = "#F38BA8" } + + +[filetype] +rules = [ + # Bilder + { mime = "image/*", fg = "#FAB387" }, + + # Audio / Video + { mime = "{audio,video}/*", fg = "#FAB387" }, + + # Archive + { mime = "application/{zip,rar,7z*,tar,gzip}", fg = "#F9E2AF" }, + { mime = "application/{xz,zstd,bzip*,lzma,compress}", fg = "#F9E2AF" }, + { mime = "application/{archive,cpio,arj,xar,ms-cab*}", fg = "#F9E2AF" }, + + # Kaputte Links + { url = "*", is = "orphan", fg = "#777788", crossed = true }, + + # Symlinks + { url = "*", is = "link", fg = "#F5B2F7" }, + { url = "*/", is = "link", fg = "#CBA6F7" }, + + # Ausführbar + { url = "*", is = "exec", fg = "#F38BA8" }, + + # Sprachen + { url = "*.{c,c++,cake,cats,cc,cl,cp,cpp,cs}", fg = "#94E2D5" }, + { url = "*.{cshtml,css,csx,cxx,emacs,go}", fg = "#94E2D5" }, + { url = "*.{h,h++,hh,hpp,hs,hxx,idc,inl,ipp,ipynb}", fg = "#94E2D5" }, + { url = "*.{java,jl,js,json}", fg = "#94E2D5" }, + { url = "*.{ksh,l,lisp,lsp,lua,m}", fg = "#94E2D5" }, + { url = "*.{php,pl,ps1,py,ron}", fg = "#94E2D5" }, + { url = "*.{sass,sh,tcc,tpp}", fg = "#94E2D5" }, + { url = "*.{vbs,w,}", fg = "#94E2D5" }, + { url = "*.{sh,bash,zsh,fish}", fg = "#94E2D5" }, + { url = "*.{el,elc}", fg = "#94E2D5" }, + + # Config / Patches + { url = "*.{cfg,conf,yaml,yml,toml,inc}", fg = "#F9E2AF" }, + { url = "*.{diff,patch,matlab,ron}", fg = "#F9E2AF" }, + + # Markup + { url = "*.{jinja,markdown,md,mkd,mkdn,mkdown,tex}", fg = "#B4BEFE" }, + { url = "*.{htm,html,xhtml,xml}", fg = "#B4BEFE" }, + { url = "*.{org}", fg = "#CBA6F7" }, + + # Dokumente + { url = "*.{pdf,txt,rtf}", fg = "#AAAABB" }, + { url = "*.{doc,docx,xls,xlsx,ppt,pptx}", fg = "#AAAABB" }, + + # Virtuelles Dateisystem + { mime = "vfs/{absent,stale}", fg = "#777788" }, + + # Fallback + { url = "*", fg = "#F0F0EA" }, + { url = "*/", fg = "#B4BEFE" }, +] diff --git a/extra/config/yazi/flavors/mwx.yazi/flavor.toml.bak b/extra/config/yazi/flavors/mwx.yazi/flavor.toml.bak new file mode 100644 index 0000000..f0b7929 --- /dev/null +++ b/extra/config/yazi/flavors/mwx.yazi/flavor.toml.bak @@ -0,0 +1,159 @@ +[manager] +cwd = { fg = "#00d1e9" } + +# Hovered +hovered = { fg = "#ffffff", bg = "#66ccff" } +preview_hovered = { underline = true } + +# Find +find_keyword = { fg = "#ffde57", bold = true, italic = true, underline = true } +find_position = { fg = "#e45c9c", bg = "reset", bold = true, italic = true } + +# Marker +marker_copied = { fg = "#6ae073", bg = "#6ae073" } +marker_cut = { fg = "#ff6e64", bg = "#ff6e64" } +marker_marked = { fg = "#00d1e9", bg = "#00d1e9" } +marker_selected = { fg = "#ffde57", bg = "#ffde57" } + +# Tab +tab_active = { reversed = true } +tab_inactive = {} +tab_width = 1 + +# Count +count_copied = { fg = "#222327", bg = "#6ae073" } +count_cut = { fg = "#222327", bg = "#ff6e64" } +count_selected = { fg = "#222327", bg = "#ffde57" } + +# Border +border_symbol = "│" +border_style = { fg = "#66ccff" } + + +[mode] +normal_main = { fg = "#222327", bg = "#66ccff", bold = true } +normal_alt = { fg = "#66ccff", bg = "#393939" } + +# Select mode +select_main = { fg = "#222327", bg = "#6ae073", bold = true } +select_alt = { fg = "#6ae073", bg = "#393939" } + +# Unset mode +unset_main = { fg = "#222327", bg = "#f2cdcd", bold = true } +unset_alt = { fg = "#f2cdcd", bg = "#393939" } + + +[status] +separator_open = "" +separator_close = "" + +# Progress +progress_label = { fg = "#ffffff", bold = true } +progress_normal = { fg = "#66ccff", bg = "#45475a" } +progress_error = { fg = "#ff6e64", bg = "#45475a" } + +# Permissions +perm_sep = { fg = "#8c8c8c" } +perm_type = { fg = "#66ccff" } +perm_read = { fg = "#ffde57" } +perm_write = { fg = "#ff6e64" } +perm_exec = { fg = "#6ae073" } + + +[pick] +border = { fg = "#66ccff" } +active = { fg = "#e45c9c", bold = true } +inactive = {} + + +[input] +border = { fg = "#0000ff" } +title = {} +value = {} +selected = { reversed = true } + + +[completion] +border = { fg = "#66ccff" } + + +[tasks] +border = { fg = "#66ccff" } +title = {} +hovered = { fg = "#e45c9c", underline = true } + + +[which] +mask = { bg = "#393939" } +cand = { fg = "#00d1e9" } +rest = { fg = "#8c8c8c" } +desc = { fg = "#e45c9c" } +separator = "  " +separator_style = { fg = "#585b70" } + + +[help] +on = { fg = "#00d1e9" } +run = { fg = "#e45c9c" } +hovered = { reversed = true, bold = true } +footer = { fg = "#393939", bg = "#eaead7" } + + +[notify] +title_info = { fg = "#6ae073" } +title_warn = { fg = "#ffde57" } +title_error = { fg = "#ff6e64" } + + +[filetype] +rules = [ + # Images + { mime = "image/*", fg = "#ffb350" }, + + # Media + { mime = "{audio,video}/*", fg = "#ffb350" }, + + # Archives + { mime = "application/{zip,rar,7z*,tar,gzip}", fg = "#ffde57" }, + { mime = "application/{xz,zstd,bzip*,lzma,compress}", fg = "#ffde57" }, + { mime = "application/{archive,cpio,arj,xar,ms-cab*}", fg = "#ffde57" }, + + # Broken links + { name = "*", is = "orphan", fg = "#8c8c8c", crossed = true }, + + # Symlinks files + { name = "*", is = "link", fg = "#e45c9c" }, + { name = "*/", is = "link", fg = "#66ffcc" }, + + # Executables + { name = "*", is = "exec", fg = "#ff6e64" }, + + # Languages + { name = "*.{c,c++,cake,cats,cc,cl,cp,cpp,cs}", fg = "#6ae073" }, + { name = "*.{cshtml,css,csx,cxx,emacs,go}", fg = "#6ae073" }, + { name = "*.{h,h++,hh,hpp,hs,hxx,idc,inl,ipp,ipynb}", fg = "#6ae073" }, + { name = "*.{java,jl,js,json}", fg = "#6ae073" }, + { name = "*.{ksh,l,lisp,lsp,lua,m}", fg = "#6ae073" }, + { name = "*.{php,pl,ps1,py,ron}", fg = "#6ae073" }, + { name = "*.{sass,sh,tcc,tpp}", fg = "#6ae073" }, + { name = "*.{vbs,w,}", fg = "#6ae073" }, + { name = "*.{sh,bash,zsh,fish}", fg = "#6ae073" }, + + { name = "*.{cfg,conf,yaml,yml,toml,inc}", fg = "#ffde57" }, + { name = "*.{diff,patch,matlab,ron}", fg = "#ffde57" }, + + { name = "*.{jinja,markdown,md,mkd,mkdn,mkdown,tex}", fg = "#00d1e9" }, + { name = "*.{htm,html,xhtml,xml}", fg = "#00d1e9" }, + + # Emacs + { name = "*.{el,elc}", fg = "#6ae073" }, + { name = "*.{org}", fg = "#cd7bf6" }, + + # Documents + { name = "*.{pdf,txt,rtf}", fg = "#9999ff" }, + { name = "*.{pdf,doc,docx,xls,xlsx,ppt,pptx}", fg = "#9999ff" }, + + # Fallback + { name = "*", fg = "#eaead7" }, + { name = "*/", fg = "#66ccff" } +] diff --git a/extra/config/yazi/keymap.toml b/extra/config/yazi/keymap.toml new file mode 100644 index 0000000..f672852 --- /dev/null +++ b/extra/config/yazi/keymap.toml @@ -0,0 +1,4 @@ +[[manager.prepend_keymap]] +on = "t" +run = "plugin max-preview" +desc = "Maximize or restore preview" diff --git a/extra/config/yazi/package.toml b/extra/config/yazi/package.toml new file mode 100644 index 0000000..9091919 --- /dev/null +++ b/extra/config/yazi/package.toml @@ -0,0 +1,5 @@ +[plugin] +deps = [] + +[flavor] +deps = [] diff --git a/extra/config/yazi/theme.toml b/extra/config/yazi/theme.toml new file mode 100644 index 0000000..022029c --- /dev/null +++ b/extra/config/yazi/theme.toml @@ -0,0 +1,2 @@ +[flavor] +dark = "mwx" diff --git a/extra/config/yazi/yazi.toml b/extra/config/yazi/yazi.toml new file mode 100644 index 0000000..0f4ae9e --- /dev/null +++ b/extra/config/yazi/yazi.toml @@ -0,0 +1,3 @@ +[mgr] +# [parent, current, preview] — Default ist [1, 4, 3] +ratio = [1, 1, 3] diff --git a/extra/omp.json b/extra/omp.json new file mode 100644 index 0000000..a531603 --- /dev/null +++ b/extra/omp.json @@ -0,0 +1,133 @@ +{ + "palette": { + "white": "#F0F0EA", + "yellow": "#F9E2AF", + "orange": "#FAB387", + "red": "#F38BA8", + "green": "#94E2D5", + "blue": "#B4BEFE", + "pink": "#F5B2F7", + "violet": "#CBA6F7", + "grey": "#AAAABB", + "dark": "#777788", + "darker": "#444455" + }, + "var": { + "sep": "<#ffffff>・" + }, + "blocks": [ + { + "alignment": "left", + "newline": false, + "segments": [ + { + "foreground_templates": ["{{if .SSHSession }}p:violet{{else}}p:green{{ end }}"], + "style": "diamond", + "template": "{{.HostName}}{{.Var.sep}}{{.OS}}{{.Var.sep}}{{.Shell}}", + "type": "session" + },{ + "foreground": "p:orange", + "style": "diamond", + "template": "{{.Var.sep}}{{.SHLVL}}/{{.PromptCount}}", + "type": "session" + }, + { + "foreground_templates": ["{{if .Root }}p:red{{else}}p:green{{ end }}"], + "leading_diamond": "", + "style": "diamond", + "template": "{{.Var.sep}}{{.UserName}}", + "type": "session" + }, + + { + "foreground": "p:green", + "foreground_templates": ["{{ if gt .Code 0 }}p:red{{ end }}"], + "leading_diamond": "", + "style": "diamond", + "template": "{{.Var.sep}}{{.Code}}", + "type": "session" + }, + { + "foreground": "p:yellow", + "properties": { + "branch_icon": "", + "fetch_stash_count": true, + "fetch_status": true, + "fetch_upstream_icon": true, + "fetch_worktree_count": true + }, + "style": "diamond", + "template": "{{.Var.sep}}{{ .HEAD }} {{ .StashCount }}", + "trailing_diamond": "", + "type": "git" + }, + { + "type": "go", + "style": "plain", + "foreground": "p:blue", + "template": "{{.Var.sep}}GO {{ .Full }} " + } + ], + "type": "prompt" + }, + { + "alignment": "right", + "segments": [ + { + "foreground": "p:blue", + "properties": { + "time_format": "Mon, 15:04" + }, + "style": "diamond", + "template": "{{ .CurrentDate | date .Format }}{{.Var.sep}}", + "type": "time" + }, + { + "foreground": "#94ffa2", + "style": "diamond", + "template": "{{ round .PhysicalPercentUsed .Precision }}%{{.Var.sep}}{{ round .Load15 .Precision }}", + "properties": { + "precision": 1 + }, + "type": "sysinfo" + }, + { + "type": "battery", + "style": "plain", + "foreground": "#FFFFFF", + "background": "", + "foreground_templates": [ + "{{ if lt .Percentage 20 }}p:red{{ end }}", + "{{ if lt .Percentage 50 }}p:yellow{{ end }}", + "p:blue" + ], + "template": "{{if not .Error}}{{.Var.sep}}{{.Percentage}}%{{end}} " + } + + ], + "type": "prompt" + }, + { + "alignment": "left", + "newline": true, + "segments": [ + { + "properties": { + "always_enabled": true + }, + "style": "plain", + "template": "{{.PWD}} <#66ffcc>>{{if .Root }}>{{end}} ", + "type": "status" + } + ], + "type": "prompt" + } + ], + "console_title_template": "{{.UserName}}@{{.HostName}} {{.Shell}} in {{.PWD}}", + + "transient_prompt": { + "background": "transparent", + "template": "<#cc99ff>> " + }, + "version": 3 +} diff --git a/extra/zshrc b/extra/zshrc new file mode 100644 index 0000000..744e972 --- /dev/null +++ b/extra/zshrc @@ -0,0 +1,27 @@ +alias tsc='timeshift --yes --create --comments' +alias tsr='timeshift --yes --restore' +alias tsd='timeshift --yes --delete' +alias tsl='timeshift --list' + +eval "$(oh-my-posh init zsh --config /db/etc/omp.json )" + +[ -f ~/.fzf.zsh ] && source ~/.fzf.zsh + +alias y yazi +alias f fzf + + +alias ll='eza --icons auto -la' +alias ls='eza --icons auto -a' +alias lt='eza --icons auto -la -s changed' +alias lx='eza --icons auto --tree -la' + +export FZF_DEFAULT_OPTS=$FZF_DEFAULT_OPTS' + --color=fg:#AAAABB,bg:#252528,hl:#F5B2F7 + --color=fg+:#F0F0EA,bg+:#444455,hl+:#F5B2F7 + --color=info:#94E2D5,prompt:#F38BA8,pointer:#CBA6F7 + --color=marker:#94E2D5,spinner:#CBA6F7,header:#AAAABB + --color=query:#F0F0EA,disabled:#777788,gutter:#252528 + --color=border:#444455,separator:#444455,scrollbar:#777788 + --color=label:#AAAABB,preview-fg:#F0F0EA,preview-bg:#252528' + \ No newline at end of file diff --git a/files/authorized_keys b/files/authorized_keys new file mode 100644 index 0000000..d4a4609 --- /dev/null +++ b/files/authorized_keys @@ -0,0 +1,3 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC9kb7R4qAqRdPw90zxM9dg68bnskdgqAZLSaogAKSpcvsmVNDgz5XKAr22hg25VrhJdE4S8ptvAyDT3n18yYmqv0Bht7t/uHWUd+pzJHy5d763nII7ukQtKBZdLaLEqSGD1XkyOTj21MZiiCaNurU6pqbcx3mlfVGtH0SdBCs8Nz6tYVUC/jCn202LM5tmHakLgYBvU4QPb6nfNMGKvNVjxUCs1Vn+knPsUtiIi6ktkz8LHRSx8Qd9vlTLMccsnSm/FfaepVPLslQ2rA7fpixhWIH/sJizcTubB1ErA8BhDM7exD+UEfmN7CKvarFZxDf3WgckonIGuoS81wT+cZDT m +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCoqI8A+SES/kWp6ZqJ6agbk8lz7UhOIZZrSF1cnuv+9bCq2QtO5qkAalJSr5hNZXsEZl9OfQibcFk7GUWTaEHCg/vdTxfMUdWDQDkOyPNPQD2JRZ3NpcdtkteSEfYzPwyXFV3HSoQys6VQAib9SeMyDtTgFPN+xm2lQtVzGiFg73ny5Lq1PsaS40+6EwGZmMIfUQLVm5OjislDW1p+F1PyYUeM9wiK/KbJl99Pd5CECXN9uunAEOz/siDwpo1TXZ6od6ZKMCGDT3v742cc28HpHxK/GQ9ezXlaTZ4BldTtkoupK6KwxOZ8x/eyiGq00E/YdjtxhLi6ggmjlBk2Gk33 root@data + diff --git a/files/csh.cshrc b/files/csh.cshrc new file mode 100644 index 0000000..7a17366 --- /dev/null +++ b/files/csh.cshrc @@ -0,0 +1,49 @@ +unsetenv LANG +setenv HN `hostname` + +set prompt="%n@${HN}:%~ > " +if ( $USER == root ) then + set prompt="%n@${HN}:%~ >> " +endif + +set history=128 +set savehist=128 +set watch=( any any ) +set recexact +set autolist +set dunique +set matchbeep=nomatch +set pushdsilent +set fignore=( .o ) +set echo_style=both +unset ignoreeof +unset mail +set notify +set time=( 1 " %E [%P] used." ) + +alias a 'alias' +alias h 'history' +alias L 'last -16' +alias ls 'ls -F' +alias ll 'ls -lsah' +alias lt 'ls -ltrah' +alias cd 'cd \!*;echo $cwd' +alias pwd 'echo $cwd' +alias s 'ssh' +alias sr 'ssh -l root' +alias rs 'rsync -va --delete --stats' +alias p 'ps -ef | grep ${LOGNAME}' +alias P 'ps -ef' +alias af 'apt-cache search' +alias ai 'apt-get install' +alias sd 'lsblk -o NAME,FSTYPE,SIZE,MOUNTPOINT,LABEL' + +alias ga 'git add -v .' +alias gb 'git branch' +alias gs 'git status' +alias gl "git log -32 --reverse --date=local --format='%h %cd %s'" +alias gc 'git commit -m' +alias go 'git checkout' +alias gp 'git push' + +setenv PATH "$PATH":/db/bin diff --git a/files/default.jcf b/files/default.jcf new file mode 100644 index 0000000..d2780ed --- /dev/null +++ b/files/default.jcf @@ -0,0 +1,83 @@ +# joe theme — Palette aus mwxcol.go +# +# white #F0F0EA pink #F5B2F7 +# yellow #F9E2AF violet #CBA6F7 +# orange #FAB387 grey #AAAABB +# red #F38BA8 dark #777788 +# green #94E2D5 darker #444455 +# blue #B4BEFE +# +# Ort: ~/.joe/colors/default.jcf (verdeckt die System-Version) +# Getestet mit joe 4.6. + +.colors * + +.set white $F0F0EA +.set yellow $F9E2AF +.set orange $FAB387 +.set red $F38BA8 +.set green $94E2D5 +.set blue $B4BEFE +.set pink $F5B2F7 +.set violet $CBA6F7 +.set grey $AAAABB +.set dark $777788 +.set darker $444455 + +-text [white] + +# --- Syntax ----------------------------------------------------------- +=Bad [red] +=Preproc [orange] +=Define [orange] +=String [red] +=Comment [grey] +=IncLocal [green] +=IncSystem [green] bold +=Constant [red] +=Escape [green] bold +=Type [violet] +=Keyword [pink] +=Variable [green] +=Brace [white] bold +=Tag [blue] bold +=TagName +Tag +=Title bold +=TODO [yellow] +=BUG [yellow] + +# --- UI --------------------------------------------------------------- +-status [white]/[darker] +-selection /[darker] +-linum [dark] +-curlinum [yellow] bold +-menu [white]/[darker] +-menusel [darker]/[blue] + +# --- diff ------------------------------------------------------------- +=diff.AddLine [green] +=diff.DelLine [red] +=diff.ChgLine [yellow] +=diff.Garbage [darker] +=diff.FileOld [red] bold +=diff.FileNew [green] bold +=diff.Hunk [violet] bold + +# Identitäts-Mapping wie bisher: numerische Farben aus alten Syntax-Files +# greifen auf die 16 Farben des Terminals durch. +-term 0 0 +-term 1 1 +-term 2 2 +-term 3 3 +-term 4 4 +-term 5 5 +-term 6 6 +-term 7 7 +-term 8 8 +-term 9 9 +-term 10 10 +-term 11 11 +-term 12 12 +-term 13 13 +-term 14 14 +-term 15 15 diff --git a/files/dx b/files/dx new file mode 100755 index 0000000..a4312ed --- /dev/null +++ b/files/dx @@ -0,0 +1,95 @@ +#!/usr/bin/perl +######################################################################## count files and directories (mwx'2016) +use Getopt::Std;getopts('dnh'); + +$version='1.0.2'; + +if ($opt_h) {;&help;exit;} + +if (-d $ARGV[0]) { + &dx($ARGV[0]); +} else { + &dx("."); +} + +sub dx() { + my($dir)=@_; + $ml=length($dir); + + opendir(DIR,$dir); + while($f=readdir(DIR)) { + if ($f ne '.' && $f ne '..') { + + if (-d "$dir/$f") { + $n=0;$s=0; + open(IN,"find '$dir/$f' -type f |"); + while() { + chomp(); + $s+=(stat($_))[7]; + $ts+=(stat($_))[7]; + $n++; + $tn++; + } + close(IN); + $N{"$f/"}=$n; + $S{"$f/"}=$s; + $ml=length($f) if (length($f)>$ml); + } + + if (-f "$dir/$f" && !$opt_d) { + $S{$f}+=(stat("$dir/$f"))[7]; + $ts+=(stat("$dir/$f"))[7]; + $N{$f}++; + $tn++; + $ml=length($f) if (length($f)>$ml); + } + + } + } + closedir(DIR); + + $frm=sprintf "%%-%ds",$ml+1; + $out=sprintf "$frm %8d %8s\n",$dir,$tn,&formsize($ts); + + if ($opt_n) { + for $f (sort { $N{$a} <=> $N{$b} } (keys(%N))) { + $out.=sprintf " $frm %8d %8s\n",$f,$N{$f},&formsize($S{$f}); + } + } else { + for $f (sort { $S{$a} <=> $S{$b} } (keys(%S))) { + $out.=sprintf " $frm %8d %8s\n",$f,$N{$f},&formsize($S{$f}); + } + } + print $out; +} + +####################################################################################################### SUPPORT + +sub formsize() { + my($b)=@_; + if ($b>1024*1024*1024*1024) { + $s=sprintf("%.0fT",$b/1024/1024/1024/1024) + } elsif ($b>1024*1024*1024) { + $s=sprintf("%.0fG",$b/1024/1024/1024) + } elsif ($b>1024*1024) { + $s=sprintf("%.0fM",$b/1024/1024) + } elsif ($b>1024) { + $s=sprintf("%.0fK",$b/1024) + } else { + $s=sprintf("%.0f",$b) + } + return $s; +} + +sub help() { +print <<"ENDOFHELP"; +dx ${version}, count files and directories, mwx'2016 +usage: dx [-n] [-d] [path] + -n sort by number of files (default by size) + -d count only directories + -h this help +ENDOFHELP +} + +########################################################################################################### END + diff --git a/files/gx b/files/gx new file mode 100755 index 0000000..ebabaab --- /dev/null +++ b/files/gx @@ -0,0 +1,20 @@ +#!/usr/bin/perl +use Getopt::Std;getopts('x'); + +use Sys::Hostname qw(hostname);use Socket; +my($ip) = inet_ntoa( (gethostbyname(hostname()))[4] ); +my($user)=getpwuid( $< ); + +if ($opt_x) { + $comment="[$ip,$user] " . join(' ',@ARGV); +} else { + $comment=join(' ',@ARGV); +} + +$comment='-' if ($comment=~/^\s*$/); +$comment=~s/\s*$//; + +system("git add -v ."); +system("git commit -m '$comment'"); +system("git push"); + diff --git a/files/gy b/files/gy new file mode 100755 index 0000000..84b6e25 --- /dev/null +++ b/files/gy @@ -0,0 +1,51 @@ +#!/usr/bin/perl + +$repo=$ARGV[0]; +$repo=~s/\/\s*$//; + +die if ($repo=~/^\s*$/); + +$cgit='git://git.micw.org'; +$pgit='ssh://git@git.micw.org:2234/home/git'; + +if (-d $repo) { + if (yesno('overwrite existing directory?',0)) { + &cmd("rm -rf $repo") + } else { + exit; + } +} + +&cmd("git clone $cgit/$repo.git"); +&cmd("cd $repo;git remote set-url origin $pgit/$repo.git"); + +sub cmd() { + my($cmd,$quiet)=@_; + print "$cmd\n" if (!$quiet); + system($cmd); +} + +sub yesno { + my($prom,$def)=@_; + my($ans); + if ($def) {;$ans=&getkey("$prom Y/n ? ");} + else {;$ans=&getkey("$prom y/N ? ");} + if ($ans=~/^\s*$/) { + if ($def) {;return(1);} + else {;return(0);} + } + if ($ans=~/^\s*y\s*$/i || $ans=~/^\s*yes\s*$/i) { + return 1; + } + return 0; +} + +sub getkey { + $|=1; + print "$_[0]"; + system "stty", '-icanon', '-echo', 'eol', "\001"; + $key = getc(STDIN);$key=~s/[\r\n\t]//g; + system "stty", 'icanon', 'echo', 'eol', "^@"; + print "$key\n"; + return $key; +} diff --git a/files/joerc b/files/joerc new file mode 100755 index 0000000..5e4c9b1 --- /dev/null +++ b/files/joerc @@ -0,0 +1,99 @@ + +-lmsg \i%k%T%W%I%X %n %m%y%R %x +-rmsg %S Row %r Col %c %p%% %u ^H help ^T menu + +-nonotice +-noxon +-beep +-tab 2 +-indentc 9 +-nobackups +-pg 0 +--autoindent + +{Basic +^Y Save & Quit ^F Search/Replace ^A Begining of Line ^B Block Start +^S Save ^G Search Next ^E End of Line ^W Block Cut +^C Abort ^N Next Page ^U Begininig of File ^V Block Paste +^T Menu ^P Previous Page ^Q End of File ^H Help +^Q Undo ^K Delete Line ^L Goto Line +^R Redo ^D Delete Character mwx'2013 joerc v2.02 +} + +:main +type ^@ TO ÿ + +rtn ^M +backs ^? +abort ^C + +exsave ^Y +save ^S +undo ^Z +redo ^R + +delch ^D +dellin ^K + +help ^H + +rtarw ^[ [ C +ltarw ^[ [ D +uparw ^[ [ A +dnarw ^[ [ B +pgdn ^N +pgup ^P +line ^L + +ffirst ^F +fnext ^G + +markb,msg,"Mark set",rtn ^B +markk,copy,blkdel,msg,"Block copy",rtn ^W +yank ^V + +bol ^A +eol ^E +bof ^U +eof ^Q + +menu,"root",rtn ^T + +:prompt +:inherit main + +:query +:inherit main + +:querya +type ^@ TO ÿ + +:querysr +:inherit main + +:menu +:inherit main + +abort ^Y +backsmenu ^? +bolmenu ^A +eolmenu ^E +rtarwmenu ^[ [ C +ltarwmenu ^[ [ D +uparwmenu ^[ [ A +dnarwmenu ^[ [ B +rtn ^M + +:defmenu root +mode,"autoindent",rtn I Autoindent %Zautoindent% +mode,"overwrite",rtn T Overtype %Zoverwrite% +mode,"wordwrap",rtn W Word wrap %Zwordwrap% +mode,"hex",rtn % % Hex edit mode +mode,"tab",rtn D Tab width %Ztab% +mode,"crlf",rtn Z CR-LF (MS-DOS) %Zcrlf% +mode,"linums",rtn N Line numbers %Zlinums% +mode,"beep",rtn B Beep %Zbeep% +mode,"rdonly",rtn % % Read only %Zrdonly% +mode,"icase",rtn % % Search case %Zicase% +execmd C command +mode O option diff --git a/files/joerc4 b/files/joerc4 new file mode 100755 index 0000000..95b5580 --- /dev/null +++ b/files/joerc4 @@ -0,0 +1,104 @@ +-notite +-assume_color +-guess_non_utf8 +-guess_utf16 +-guess_crlf +-guess_indent +-menu_above +-transpose +-pastehack +-restore +-search_prompting +-nobackups +-nodeadjoe +-undo_keep 0 +-noxon + +-lmsg \i%k%T%W%I%X %n %m%y%R %x +-rmsg %S Row %r Col %c %p%% %u ^H help +-smsg ** Line %r Col %c Offset %o(0x%O) %e %a(0x%A) Width %w ** +-zmsg ** Line %r Col %c Offset %o(0x%O) ** + +-highlight +-istep 2 +-tab 2 + +:include ftyperc + +{Basic +^Y Save & Quit ^F Search/Replace ^A Begining of Line ^B Block Start ^T^H Toggle Hex +^S Save ^G Search Next ^E End of Line ^W Block Cut ^T^O Overwrite Mode +^C Abort ^N Next Page ^U Begininig of File ^V Block Paste ^T^I Toggle Autoindent +^Z Undo ^P Previous Page ^Q End of File ^H Help ^T^T Set Tab Width +^R Redo ^K Delete Line ^L Goto Line ^T^C Execute Command + ^D Delete Character mwx'2017 joerc v4.x.x +} + +:windows Bindings common to all windows +type U+0 TO U+10FFFF +rtn ^M +backs ^? +abort ^C + +exsave ^Y +save ^S +undo ^Z +redo ^R + +delch ^D +dellin ^K + +help ^H + +rtarw ^[ [ C +ltarw ^[ [ D +uparw ^[ [ A +dnarw ^[ [ B +pgdn ^N +pgup ^P +line ^L + +ffirst ^F +fnext ^G + +markb,msg,"Mark set",rtn ^B +markk,copy,blkdel,msg,"Block copy",rtn ^W +yank ^V + +bol ^A +eol ^E +bof ^U +eof ^Q + +mode,"hex",rtn ^T ^H +mode,"overwrite",rtn ^T ^O +mode,"tab",rtn ^T ^T +mode,"autoindent",rtn ^T ^I +execmd ^T ^C + +:main Text editing window +:inherit windows + +:prompt +:inherit main + +:menu +:inherit windows + +:query +:inherit windows + +:querya +type U+0 TO U+10FFFF + +:querysr +type U+0 TO U+10FFFF + +:shell Input to shell windows +:inherit main + +:vtshell Input to ANSI shell windows +:inherit main + + + diff --git a/files/locale b/files/locale new file mode 100644 index 0000000..31062ff --- /dev/null +++ b/files/locale @@ -0,0 +1 @@ +LANG="C.UTF-8" diff --git a/files/mbackup b/files/mbackup new file mode 100755 index 0000000..2586663 --- /dev/null +++ b/files/mbackup @@ -0,0 +1,573 @@ +#!/usr/bin/perl +############################################################################################# mbackup (mwx'2023) +$VERSION='3.2.0'; +use Getopt::Std;getopts('vVDWMYhsfc:');$opt_v=1 if ($opt_V); +use Net::Ping; +use Fcntl ':flock'; +chomp($HOST=`hostname`); + +&help if($opt_h); + +$NOW=time(); +my(@z)=localtime($NOW);$z[4]+=1;$z[5]-=100;$z[6]+=1; +$z=sprintf("%02d.%02d-%02d:%02d",$z[3],$z[4],$z[5],$z[2],$z[1]); + + +$MAX{'daily'}=7; # default values +$MAX{'weekly'}=4; +$MAX{'monthly'}=12; +$MAX{'yearly'}=3; + +$FLAT=0; +$RSYNCOPTS='--no-o --no-g --chmod=ugo=rwX'; + +$RSYNCRETRIES=3; + +$CONFIG='';$REQUESTCONFIG=$ARGV[0]; # load configuration + +for ($opt_c,"/db/etc/mbackup.conf",$ENV{'HOME'}."/etc/mbackup.conf",$ENV{'HOME'}."/.mbackup.conf") { + if (-f) { + $confile=$_; + last; + } +} + +require $confile; + + +for (keys(%GROUPS)) { # build group list + if ($_ eq $REQUESTCONFIG) { + push(@GROUP,@{$GROUPS{$_}}); + $CONFIG=$REQUESTCONFIG; + } +} + + +if ($CONFIG=~/^\s*$/) { # check for valid config + &log("ERROR: config '$REQUESTCONFIG' not found",1); + exit; +} +$REMOTE=0;$REMOTE=1 if ($TARGETDIR!~/^\//); + + +if ($opt_s) { # show configuration + if (@GROUP) { + print "\n"; + print "mode: group\n\n"; + print "group sleep: $GROUPSLEEP\n\n" if ($GROUPSLEEP>0); + + for $job (@GROUP) { + print "/db/bin/mbackup -c $confile $job\n"; + } + print "\n"; + } else { + print "\n"; + if ($FLAT==1) { + print "mode: flat\n"; + } else { + print "mode: $MAX{'daily'} daily, $MAX{'weekly'} weekly, "; + print "$MAX{'monthly'} monthly, $MAX{'yearly'} yearly\n"; + } + if ($#EXCLUDE>-1) { + print "\n"; + $tmp="";$tmp.="$_, " for (@EXCLUDE);$tmp=~s/\,\s+$//; + print "exclude: $tmp\n"; + } + print "\n"; + $l=0; + for (keys(%SRC)) { + $l=length($_) if length($_)>$l; + } + printf "%-${l}s -> %s\/%s\n",$_,$TARGETDIR,$SRC{$_} for (keys(%SRC)); + print "\n"; + } + exit; +} + + +if (@GROUP) { # run backup group + for $job (@GROUP) { + $cmd="/db/bin/mbackup -c $confile $job"; + + &log("{$CONFIG} $cmd",1); + system($cmd); + + if ($GROUPSLEEP>0 && $job ne $GROUP[-1]) { + &log("group loop sleep ($GROUPSLEEP seconds)",1); + sleep($GROUPSLEEP); + } + + } + exit; +} + + + +if ($MY_LOG) { # mysql loging + use DBI; + $dbh=DBI->connect("DBI:mysql:$MY_DB:$MY_HOST:",$MY_USER,$MY_PASSWD,{RaiseError=>1,PrintError=>1}); +} + + +$mode=''; # set mode (daily,weekly,monthly,yearly) +my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday)=localtime($NOW); +$mon++;$year+=1900; +$z=sprintf("%02d\.%02d\.%04d %02d\:%02d",$mday,$mon,$year,$hour,$min); +$mode='daily' if ( $MAX{'daily'}>0); +$mode='weekly' if ( $wday==0 && $MAX{'weekly'}>0); +$mode='monthly' if ( $mday==1 && $MAX{'monthly'}>0); +$mode='yearly' if ( $yday==0 && $MAX{'yearly'}>0); + + +$mode='daily' if ($opt_D); # set mode manual +$mode='weekly' if ($opt_W); +$mode='monthly' if ($opt_M); +$mode='yearly' if ($opt_Y); + + +if (defined($PING)) { # check if host is reachable + if (!Net::Ping->new("icmp", 15)->ping($PING)) { + &log("ERROR: host $PING not reachable",1);exit; + } +} + + +if (!-d "$TARGETDIR" && $REMOTE==0) { # check target dir + if ($opt_f) { + system("mkdir $TARGETDIR"); + if (!-d "$TARGETDIR") { + &log("ERROR: target dir creation failed (mkdir $TARGETDIR)",1); + exit; + } + } else { + &log("ERROR: can not access target dir (mkdir $TARGETDIR)",1); + exit; + } +} + + +for $srcdir (keys(%SRC)) { # check source dir + if ($srcdir=~/^\// && !-d $srcdir) { + &log("ERROR: mising source dir '$srcdir'",1); + exit; + } +} + + +undef(%keycount); # check for duplicate source keys +for $srcdir (keys(%SRC)) { + $keycount{$SRC{$srcdir}}++; + if ($keycount{$SRC{$srcdir}}>1) { + &log("ERROR: duplicate source key '$SRC{$srcdir}'",1); + exit; + } +} + + +if ($FLAT==1 || $REMOTE==1) { # flat mode + $toterr=0;$totfiles=0;$tottfi=0;$totbytes=0;$tottby=0;$totrt=0; + + for $srcdir (keys(%SRC)) { + $subname=$SRC{$srcdir}; + + $cmd="/usr/bin/rsync -av $RSYNCOPTS --stats --delete " . + &exf() . " --numeric-ids $srcdir/. $TARGETDIR/$subname"; + + ($err,$fi,$tfi,$by,$tby,$rt,$try)=&rsync($cmd); + + &log("[$CONFIG] $srcdir,$TARGETDIR ($err,$tfi,$fi,$tby,$by,$rt)",1); + + if ($MY_LOG) { # mysql logging + $sql="INSERT INTO mbackup VALUES(0,now(),'$HOST','$VERSION','$CONFIG',". + "'$srcdir','$TARGETDIR',$fi,$tfi,$by,$tby,$rt,$err,$try)"; + $dbh->do($sql); + } + + if ($HTTP_LOG!~/^\s*$/) { # http logging + $tmp= "MBACKUP,$HOST,$VERSION,$CONFIG,$srcdir,$TARGETDIR,$fi,$tfi,$by,$tby,$rt,$err,$try"; + use LWP::UserAgent; + my $ua = new LWP::UserAgent(); + $response = $ua->post("http://$HTTP_LOG", Content => $tmp); + } + + $toterr+=$err;$totfi+=$fi;$tottfi+=$tfi;$totby+=$by;$tottby+=$tby;$totrt+=$rt; + &log("rsync error $err in $srcdir/. -> $TARGETDIR/$subname") if ($err); + } + if ($toterr==0) { + &log("[$CONFIG] mbackup successful finished ($tottfi,$totfi,$tottby,$totby,$totrt)",1) + } + exit; +} + + +if ($mode eq '') { # check if mode is defiend otherwise exit + &log("ERROR: undefined mode",1); + exit; +} + + +$yweekly=0;$ymonthly=0;$yyearly=0; # search for missing snapshot +opendir(DIR,$TARGETDIR); +while ($file=readdir(DIR)) { + my(@stat)=stat("$TARGETDIR/$file"); + + if ($file=~/^weekly\.\d+$/) { + $yweekly=$stat[9] if ($stat[9]>$yweekly); + } + if ($file=~/^monthly\.\d+$/) { + $ymonthly=$stat[9] if ($stat[9]>$ymonthly); + } + if ($file=~/^yearly\.\d+$/) { + $yyearly=$stat[9] if ($stat[9]>$yyearly); + } +} +closedir(DIR); +if ($NOW-$yweekly>86400*10 && $yweekly!=0 && $MAX{'weekly'}>0) { + &log("WARNING: no weekly snapshot for more than 10 days",1); +} +if ($NOW-$ymonthly>86400*40 && $ymonthly!=0 && $MAX{'monthly'}>0) { + &log("WARNING: no monthly snapshot for more than 40 days",1); +} +if ($NOW-$yyearly>86400*400 && $yyearly!=0 && $MAX{'yearly'}>0) { + &log("WARNING: no yearly snapshot for more than 400 days",1); +} + + +undef(%SNAPLIST); # read snapshot list for current mode +opendir(DIR,$TARGETDIR); +while ($file=readdir(DIR)) { + my(@stat)=stat("$TARGETDIR/$file"); + $SNAPLIST{$1}=$stat[9] if ($file=~/^$mode\.(\d+)/); +} +closedir(DIR); + + +for $n (sort {$b<=>$a} keys(%SNAPLIST)) { # snapshot cycling + $m=$n+1; + if (-d "$TARGETDIR/$mode.$n" && !-e "$TARGETDIR/$mode.$m") { + + if ($m>=$MAX{$mode}) { + &cmd("rm -rf $TARGETDIR/$mode.$n"); + } else { + &cmd("mv $TARGETDIR/$mode.$n $TARGETDIR/$mode.$m"); + } + } else { + $tmp=""; + $tmp="($TARGETDIR/$mode.$n not found)" if (!-d "$TARGETDIR/$mode.$n"); + $tmp="($TARGETDIR/$mode.$m exists)" if (-e "$TARGETDIR/$mode.$m"); + &log("ERROR: error while snapshot cycling $tmp",1);exit; + } +} + + +$youngest='';$y=0; # search for youngest snapshot +opendir(DIR,$TARGETDIR); +while ($file=readdir(DIR)) { + my(@stat)=stat("$TARGETDIR/$file"); + if ($file=~/^((daily|weekly|monthly|yearly)\.\d+)/) { + if ($stat[9]>$y) { + $y=$stat[9]; + $youngest=$file; + } + } +} +closedir(DIR); + + +&cmd("mkdir -m 0755 -p $TARGETDIR/$mode.tmp/"); # create new $mode.0 +&cmd("touch $TARGETDIR/$mode.tmp/"); + + +if (-d "$TARGETDIR/$mode.tmp") { # build new snapshot + $toterr=0;$totfi=0;$tottfi=0;$totbytes=0;$tottby=0; + + for $srcdir (keys(%SRC)) { + $subname=$SRC{$srcdir}; + + $linkdest=""; + if ($youngest!~/^\s*$/) { + if (-d "$TARGETDIR/$youngest" && -d "$TARGETDIR/$youngest/$subname") { + $linkdest="--link-dest=$TARGETDIR/$youngest/$subname" + } + } + + $cmd="/usr/bin/rsync -av $RSYNCOPTS --no-o --no-g --chmod=ugo=rwX --stats --delete " . + &exf() . " --numeric-ids $linkdest $srcdir/. $TARGETDIR/$mode.tmp/$subname"; + + ($err,$fi,$tfi,$by,$tby,$rt,$try)=&rsync($cmd); + + &log("[$CONFIG] $srcdir,$TARGETDIR ($err,$tfi,$fi,$tby,$by,$rt)",1); + + if ($MY_LOG) { # mysql logging + $sql="INSERT INTO mbackup VALUES(0,now(),'$HOST','$VERSION','$CONFIG',". + "'$srcdir','$TARGETDIR',$fi,$tfi,$by,$tby,$rt,$err,$try)"; + $dbh->do($sql); + } + + if ($HTTP_LOG!~/^\s*$/) { # http logging + $tmp= "MBACKUP,$HOST,$VERSION,$CONFIG,$srcdir,$TARGETDIR,$fi,$tfi,$by,$tby,$rt,$err,$try"; + use LWP::UserAgent; + my $ua = new LWP::UserAgent(); + $response = $ua->post("http://$HTTP_LOG", Content => $tmp); + } + + + $toterr+=$err;$totfi+=$fi;$tottfi+=$tfi;$totby+=$by;$tottby+=$tby;$totrt+=$rt; + } + + if ($toterr==0) { + + &log("[$CONFIG] mbackup successful finished ($tottfi,$totfi,$tby,$by,$totrt)",1); + &cmd("mv $TARGETDIR/$mode.tmp $TARGETDIR/$mode.0"); + + utime $NOW,$NOW,"$TARGETDIR/$mode.0"; + } + +} else { + &log("ERROR: can not access $mode.tmp",1); +} + + +######################################################################################################## SUPPORT + +sub cmd() { # run command + my($cmd)=@_; + &log($cmd); + system($cmd); +} + +sub log() { # write logs + my($str,$forceprint)=@_; + my(@z)=localtime(time());$z[4]+=1;$z[5]-=100;$z[6]+=1; + $ts=sprintf("%02d\.%02d\.%02d %02d\:%02d",$z[3],$z[4],$z[5],$z[2],$z[1]); + + if ($LOGFILE!~/^\s+$/) { + open(LOG,">> $LOGFILE"); + flock(LOG, LOCK_EX); + print LOG "$ts $$/$VERSION/$CONFIG $str\n"; + close(LOG); + } + print "$str\n" if ($opt_v || $forceprint); +} + +sub rsync() { # run rsync + my($rsynccmd)=@_; + + my($files)=0;my($tfi)=0;my($bytes)=0;my($tby)=0;my($error)=0;my($try)=0; + + $runtime=time(); + $retries=0; + + for $try (1..$RSYNCRETRIES) { + $rsynclog=""; + + open(RSYNC,"$rsynccmd |");while() { + print if ($opt_V); + if (/Number of files:\s*([\d\,]+)/) {;$files=$1;$files=~s/,//g;} + if (/Number of regular files transferred:\s*([\d\,]+)/) {;$tfi=$1;$tfi=~s/,//g;} + if (/Total file size:\s*([\d\,]*)\s*bytes/) {;$bytes=$1;$bytes=~s/,//g;} + if (/Total transferred file size:\s*([\d\,]*)\s*bytes/) {;$tby=$1;$tby=~s/,//g;} + } + close(RSYNC); + $error=($? >> 8); + $runtime=time()-$runtime; + + if ($error==0) { + &log("$rsynccmd (successful)"); + } else { + &log("$rsynccmd (error $error in try $try)") + } + + last if ($error==0); + + $retries++; + } + + return ($error,$files,$tfi,$bytes,$tby,$runtime,$retries); +} + +sub exf() { # exclude file + $ex=''; + if ($#EXCLUDE>-1) { + $exfile="/tmp/mbackup.exclude.$CONFIG"; + open(OUT,"> $exfile"); + print OUT "$_\n" for (@EXCLUDE); + close(OUT); + $ex="--exclude-from $exfile --delete-excluded"; + } + return $ex; +} + +sub buildsrc() { # build source list (used in config) + my($base,@paths)=@_; + for $path (@paths) { + if ($path=~/\/([^\/]+)$/) { + $SRC{"$base$path"}=$1; + } + } +} + +sub sc() { # build simple configuration (used in config) + my($uhd,$dirs,$exclude,$grp,$opt)=@_; + + $mode=0; + if ($uhd=~/^([^\.]+)\.(.*)\:\:(.*)$/) {;$user=$3;$config=$1;$domain=$2;$mode=1;} + if ($uhd=~/^(\w+)\@([^\.]+)\.(.*)$/) {;$user=$1;$config=$2;$domain=$3;$mode=2;} + + if ($mode>0) { + %opt=%$opt; + $config=$opt{name} if ($opt{name}); + + @grp=@$grp; + for $g (@grp) { + push(@{$GROUPS{$g}},$config) + } + + if ($REQUESTCONFIG eq $config) { + + $RSYNCOPTS=$opt{rsync} if ($opt{rsync}); + $PING=$opt{ping} if ($opt{ping}); + $TARGETBASE=$opt{target} if ($opt{target}); + + if ($opt{versions}=~/(\d+):(\d+):(\d+):(\d+)/) { + $MAX{'daily'}=$1; + $MAX{'weekly'}=$2; + $MAX{'monthly'}=$3; + $MAX{'yearly'}=$4; + $FLAT=0; + } else { + $FLAT=1; + } + + @DIRS=@$dirs; + @EXCLUDE=@$exclude; + $TARGETDIR="$TARGETBASE/$config"; + for $path (@DIRS) { + $tpath=$path;$tpath=~s/^\s*\///;$tpath=~s/\//\./g; + $SRC{"$uhd$path"}=$tpath if ($mode==1); + $SRC{"$uhd:$path"}=$tpath if ($mode==2); + } + + $CONFIG=$REQUESTCONFIG; + } + } +} + +sub help() { # help +print "mbackup v$VERSION\n"; +print <<'ENDOFHELP'; + + USAGE: + ------ + mbackup [-v] [-V] [-DWMY] + mbackup -h + + -D force daily mode + -W force weekly mode + -M force monthly mode + -Y force yearly mode + -v verbose output + -V very verbose output + -f force creation of target directory + -h this help + + CONFIG FILE (/db/etc/mbackup.conf) GLOBAL OPTIONS: + -------------------------------------------------- + $LOGFILE = "/var/log/mbackup.log"; # logfile location + + $TARGETBASE = "/data/backup"; # targetbase for simple config + + $HTTP_LOG = 'log.mxwx.org'; # http logging server + + $MY_LOG = 1; # enable/disable mysql logging (deprecated) + $MY_HOST = 'localhost'; + $MY_USER = ''; + $MY_PASSWD = ''; + $MY_DB = ''; + + SIMPLE BACKUP JOB CONFIGURATION (/db/etc/mbackup.conf): + ------------------------------------------------------- + + &sc(target,[paths],[exclude],[groups],{ option=>value, .. } + + example: + + &sc('root@host.domain',['/etc','/var','/home'],['/lib/lxcfs'],['all']); + &sc('host.domain::root',['/etc','/var','/home'],[],['all'], { rsync=>"-e 'ssh -p 2234'" }); + &sc('root@host.domain',['/etc','/var','/home'],[],[] { versions=>'7:4:12:3' }); + + options: + + name => 'name' # set configuration name + rsync => 'rsync options' # set additional rsync options + ping => 'ip address' # apply ping test before backup + version => 'daily:weekly:monthly:yearly' # define backup versioning + target => '/path/to/mbackup' # define backup destination + + BACKUP JOB CONFIGURATION (/db/etc/mbackup.conf): + ------------------------------------------------ + if ($REQUESTCONFIG eq 'NAME') { # basic backup job config + + $CONFIG=$REQUESTCONFIG; + } + + if ($REQUESTCONFIG eq 'NAME') { # backup group definition + @GROUP=('NAME1','NAME2',...); + $CONFIG=$REQUESTCONFIG; + } + + push(@{$GROUPS{'all'}},'NAME'); # add config to group + + BACKUP JOB OPTIONS: + ------------------- + # backup target definition (use only once) + $TARGETDIR='/backup/NAME' # local traget directory + $TARGETDIR='10.0.1.1::root/backup/NAME' # rsync protocol target + $TARGETDIR='root@10.0.1.1:/backup/NAME' # ssh traget directory + + + # backup source definition (multiple allowd, different keys required) + $SRC{'/etc'} = 'etc1'; # local source + $SRC{'10.0.1.1::root/etc'} = 'etc2'; # remote source (rsync protocol) + $SRC{'root@10.0.1.1:/etc'} = 'etc3'; # remote source (ssh) + + # define eculsions (absolut path definitions from source path) + @EXCLUDE=('/path1','/path2',...); + + # define number of backups to keep, at least one value must be greater than 0 + $MAX{'daily'} = 7; # keep n daily backup (default=7) + $MAX{'weekly'} = 4; # keep n weekly backup (default=4) + $MAX{'monthly'} = 12; # keep n monthly backup (default=12) + $MAX{'yearly'} = 3; # keep n yearly backup (default=3) + + $FLAT=1; # only keep one backup (default=0) + $PING='10.0.1.1'; # perform ping test before backup run + $RSYNCOPTS="-e 'ssh -p 2234'"; # add extra options for rsync + $RSYNCRETRIES=3; # number of retries if rsync fails + + MYSQL LOGGING TABLE: + -------------------- + CREATE TABLE `mbackup` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `ts` timestamp NULL DEFAULT NULL, + `host` varchar(255) DEFAULT NULL, + `version` varchar(255) DEFAULT NULL, + `config` varchar(255) DEFAULT NULL, + `source` varchar(255) DEFAULT NULL, + `target` varchar(255) DEFAULT NULL, + `files` bigint(11) DEFAULT NULL, + `transfiles` bigint(11) DEFAULT NULL, + `bytes` bigint(11) DEFAULT NULL, + `transbytes` bigint(11) DEFAULT NULL, + `runtime` int(11) DEFAULT NULL, + `error` int(11) DEFAULT NULL, + `retries` int(11) DEFAULT '0', + PRIMARY KEY (`id`) + ) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +ENDOFHELP +exit; +} + +############################################################################################################ END + diff --git a/files/mgsh b/files/mgsh new file mode 100755 index 0000000..dcb9970 --- /dev/null +++ b/files/mgsh @@ -0,0 +1,525 @@ +#!/usr/bin/perl +################################################################################################ mgsh (mwx'2023) +use Sys::Hostname qw(hostname);use Socket; +use Config; +use Time::HiRes qw( usleep ualarm gettimeofday tv_interval ); +use File::Compare; + +$VERSION='3.1.5'; +$INFO="mwx'2023"; + +$BASE="$ENV{HOME}/Source"; +$BASE="/db/src" if ($Config{osname}=~/linux/i); +die "$BASE not found" if (!-d $BASE); + +$PRJ=$ARGV[0] if (-d "$BASE/$ARGV[0]"); + +$GITHOST = '141.14.128.56'; +$GITPORT = '2234'; +$GITUSER = 'git'; +$GITKEY = 'mgit_rsa'; +$GITPATH ="/home/git"; + +$URL = "ssh://$GITUSER\@$GITHOST:$GITPORT$GITPATH"; +$SSH = "ssh -p $GITPORT $GITUSER\@$GITHOST"; + +$IP = inet_ntoa( (gethostbyname(hostname()))[4] ); +$HOST=hostname();$HOST=~s/([^\.]+)\..*$/$1/; +$USER=getpwuid( $< ); + +use Date::Parse; # date hashes +@D=('Sun','Mon','Tue','Wed','Thu','Fri','Sat'); +@M=('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'); + + +&cmd("git config --global user.name 'Michael Wesemann'",1); # git settings +&cmd("git config --global user.email mike\@pstbx.org",1); +&cmd("git config --global push.default matching",1); + +print "mgsh v$VERSION $INFO, $BASE\n"; # ready to start + +for (;;) { # main mgsh loop + if ($PRJ!~/^\s*$/ && -d "$BASE/$PRJ") { # set current working directory/project + + $DIR="$BASE/$PRJ"; + + $BPLSTATE=''; + if (-l "$DIR/build.pl") { + chomp($rlf=`readlink $DIR/build.pl`); + $BPLSTATE='/OFF' if ($rlf=~/\.off$/); + } + + $p=$1 if ($BASE=~/\/([^\/]+)$/);$prompt="$p/$PRJ/$I$BPLSTATE"; + } else { + $DIR="$BASE"; + $p=$1 if ($BASE=~/\/([^\/]+)$/);$prompt="$p"; + } + + + chomp($REMURL= `cd $DIR; git config remote.origin.url`); + $REPO=$1 if ($REMURL=~/$url\/(.*)\.git\/?$/); + + + $prompt=~s/\/\s*$//;$cmd=&readline("$prompt > ","",1); # read command from command line + + + @tmpcmd=split(' ',$cmd);undef(@cmd);undef(%OPT); # get commandline options + for (@tmpcmd) {if (/\-(\w)/) {$OPT{$1}="-$1";} else {push(@cmd,$_);}} + + if ($cmd[0] eq 'dist') { ########################################################################### list [-a] + $CP='/bin/cp'; + $CP='/opt/homebrew/bin/gcp' if (-f '/opt/homebrew/bin/gcp'); + + $DDIR="$BASE/dist/$PRJ"; + $DDIR=$cmd[1] if ($cmd[1]!~/^\s*$/); + + if (-d $DDIR) { + chdir($DIR); + $n=0; + open(LS,"cd $DIR;git ls-files |"); + while() { + chomp(); + if (!/^private/) { + if (compare($_,"$DDIR/$_")!=0) { + print "$_\n"; + cmd("$CP --parents $_ $DDIR",1); + $n++; + } + } + } + print "$n files copied to $DDIR\n"; + } else { + print "dist path not found ($DDIR)\n"; + } + + close(LS); + } + + elsif ($cmd[0] eq 'list') { ########################################################################### list [-a] + + $path=".";$path="./archive" if ($OPT{a}); + + open(LS,"$SSH /bin/ls -ltr $path |"); + while() { + if ($cmd[1]=~/^\s*$/ || /$cmd[1]/i) { + if ($OPT{a}) { + print "$1\n" if (/git\s+git\s+\d+\s+(.*)\.git.tar.gz$/); + } else { + print "$1\n" if (/git\s+git\s+\d+\s+(.*)\.git$/); + } + } + } + close(LS); + + } + + elsif ($cmd[0] eq 'show') { ############################################################################# show + $prj=$PRJ if ($PRJ!~/^\s*$/); + $prj=$cmd[1] if ($cmd[1]!~/^\s*$/); + + $path="."; + $found=0; + open(LS,"$SSH /bin/ls $path |"); + while() { + $found++ if (/^$prj\.git$/); + } + close(LS); + + if ($found==1) { + open($FH,"$SSH \"cd $GITPATH/$prj\.git && git log --reverse --format='%h %cd %s'\" |"); + &repolog($FH); + } else { + print "repository not found\n"; + } + + } + + elsif ($cmd[0] eq 'log' && $PRJ!~/^\s*$/) { ############################################################## log + if (-d "$DIR/.git") { + open($FH,"cd $DIR;git log --reverse --format='%h %cd %s' |"); + &repolog($FH); + } else { + print "repository not found"; + } + } + + elsif ($cmd[0] eq 'push' && $PRJ!~/^\s*$/) { ################################################## push [comment] + + if (-f "$DIR/push.pl") { + &shell("perl $DIR/push.pl"); + } + + $comment='';$comment.="$cmd[$_] " for (1..$#cmd);$comment=~s/\s+$//; + $comment=~s/\s{2}/ /g; + + if (-d "$DIR/.git") { + &shell("git add --all ."); + $msg="[$USER\@$HOST] $comment";$msg=~s/^\s+//;$msg=~s/\s+$//; + &shell("git commit -m '$msg'"); + &shell("git push"); + &shell("$SSH touch $GITPATH/${PRJ}.git"); + } else { + print "error, no repository (.git) found"; + } + + } + + elsif ($cmd[0] eq 'edit' && $PRJ!~/^\s*$/) { ################################################### edit [number] + + $num=10;$num=$cmd[1] if ($cmd[1]=~/^\d+$/); + if (-d "$DIR/.git") { + &shell("git rebase -i HEAD~$num"); + &shell("git push --force"); + } else { + print "error, no repository (.git) found"; + } + + } + + elsif ($cmd[0] eq 'archive' && $PRJ!~/^\s*$/) { ############################################ archive [comment] + $comment='';$comment.="$cmd[$_] " for (1..$#cmd);$comment=~s/\s+$//; + $comment=~s/[\,\;\:\\\/\=\'\"\|\?\>\<\-]+/ /g; + $comment=~s/\s{2}/ /g; + $comment=~s/\s+/\_/g; + + my(@z)=localtime(time());$z[4]+=1;$z[5]-=100;$z[6]+=1; + $z=sprintf("%02d%02d%02d.%02d%02d",$z[3],$z[4],$z[5],$z[2],$z[1]); + + if ($comment=~/^\s*$/) { + &shell(sprintf("$SSH 'cp -r ${PRJ}.git archive/${PRJ}_$z.git'")); + &shell(sprintf("$SSH 'cd archive;tar cvzf ${PRJ}_$z.git.tar.gz ${PRJ}_$z.git'")); + &shell("$SSH 'rm -rf archive/${PRJ}_$z.git'"); + } else { + &shell(sprintf("$SSH cp -r ${PRJ}.git archive/${PRJ}_${z}_$comment.git")); + &shell(sprintf("$SSH 'cd archive;tar cvzf ${PRJ}_${z}_$comment.git.tar.gz ${PRJ}_${z}_$comment.git'")); + &shell("$SSH 'rm -rf archive/${PRJ}_${z}_$comment.git'"); + } + } + + elsif ($cmd[0] eq 'init' && $PRJ!~/^\s*$/) { ############################################################ init + + &shell("perl $DIR/push.pl") if (-f "$DIR/push.pl"); + if ($REPO=~/^\s*$/ || yesno('overwrite existing repository?',0)) { + &shell("$SSH 'rm -rf $GITPATH/${PRJ}.git'"); + &shell("$SSH 'mkdir $GITPATH/${PRJ}.git;chdir $GITPATH/${PRJ}.git;git --bare init'"); + + if (!-f ".gitignore" || yesno('overwrite existing .gitignore?',0)) { + open(OUT,"> .gitignore"); + print OUT &gitignore(); + close(OUT); + } + + &shell("rm -rf .git"); + &shell("git init"); + &shell("git remote add origin $URL/${PRJ}.git/"); + &shell("git add ."); + &shell("git commit -m 'initial commit [$IP,$USER]'"); + &shell("git push -u origin master"); + } + } + + elsif ($cmd[0] eq 'login') { ########################################################################### login + &cmd("$SSH"); + } + + elsif ($cmd[0] eq 'cd' && $cmd[1]!~/^\./) { ############################################################### cd + $PRJ=''; + $PRJ=$cmd[1] if (-d "$BASE/$cmd[1]"); + } + + elsif ($cmd[0] eq 'checkout' && $PRJ!~/^\s*$/) { ###################################### checkout [git options] + &shell("git checkout $cmd[1]"); + } + + elsif ($cmd[0] eq 'clone') { ###################################################################### clone [-a] + $prj=$PRJ if ($PRJ!~/^\s*$/); + $prj=$cmd[1] if ($cmd[1]!~/^\s*$/); + + $DIR="$BASE";chdir($DIR); + + my($path)=".";my($path)="./archive" if ($OPT{a}); + my($found)=0; + open(LS,"$SSH /bin/ls $path |"); + while() { + if ($OPT{a}) { + $found++ if (/^$prj\.git.tar.gz$/); + } else { + $found++ if (/^$prj\.git$/); + } + } + close(LS); + + if ($found==1) { + if (-d "$DIR/$prj") { + if (yesno('overwrite existing directory?',0)) { + &cmd("rm -rf $DIR/$prj") + } else { + goto exitclone; + } + } + + &shell("git clone $URL/$prj.git") if (!$OPT{a}); + if ($OPT{a}) { + &cmd("$SSH 'cd archive;tar xvzf $prj.git.tar.gz'"); + &cmd("git clone $URL/archive/$prj.git"); + &cmd("$SSH 'rm -rf archive/$prj.git'"); + } + } else { + print "repository not found, try 'list [-a]'"; + } + + $PRJ=$prj if (-d "$BASE/$prj"); + exitclone:; + } + + elsif ($cmd[0] eq 'cloneall') { ##################################################################### cloneall + $prj=$PRJ if ($PRJ!~/^\s*$/); + $prj=$cmd[1] if ($cmd[1]!~/^\s*$/); + + $DIR="$BASE";chdir($DIR); + + my($path)=".";my($path)="./archive" if ($OPT{a}); + my($found)=0; + open(LS,"$SSH /bin/ls $path |"); + while() { + if (/^(.*)\.git$/) { + print "-$1-\n"; + &shell("git clone $URL/$1.git"); + + } + } + close(LS); + } + + elsif ($cmd[0] eq 'open' || $cmd[0] eq 'view'){ ######################################################### open + $prj=$PRJ if ($PRJ!~/^\s*$/); + $prj=$cmd[1] if ($cmd[1]!~/^\s*$/); + + if (-d "$BASE/$prj") { + $DIR="$BASE/$prj";chdir($DIR); + + $xws='';$xprj='';opendir(DIR,$DIR); + while($file=readdir(DIR)) { + $xws=$file if ($file=~/.xcworkspace$/); + $xprj=$file if ($file=~/.xcodeproj$/); + } + close(DIR); + + $xprj='' if ($xws!~/^\s*$/ && $xprj!~/^\s*$/); + + &shell("open $xws") if ($xws!~/^\s*$/ && -d "$DIR/$xws"); + &shell("open $xprj") if ($xprj!~/^\s*$/ && -d "$DIR/$xprj"); + + &shell("coda $DIR") if ($xws=~/^\s*$/ && $xprj=~/^\s*$/); + + $PRJ=$prj if ($cmd[0] eq 'open'); + + } else { + print "not found\n"; + } + } + + elsif ($cmd[0] eq 'count') { ##################################################################### count lines + &count($DIR); + } + + elsif ($cmd[0] eq 'do') { ############################################################### execute extra script + &shell("perl $DIR/do.$cmd[1].pl") if (-f "$DIR/do.$cmd[1].pl"); + } + + elsif ($cmd[0] eq 'tag') { # manage tag + if ($cmd[1] eq 'add' && $cmd[2]!~/^\s*$/) { + &shell("git tag -a '$cmd[2]' -m '$cmd[2]'"); + &shell("git push origin '$cmd[2]'"); + } elsif ($cmd[1] eq 'checkout' && $cmd[2]!~/^\s*$/) { + &shell("git checkout 'tags/$cmd[2]'"); + } elsif ($cmd[1] eq 'delete' && $cmd[2]!~/^\s*$/) { + &shell("git tag -d '$cmd[2]'"); + &shell("git push origin ':refs/tags/$cmd[2]'"); + } else { + if ($cmd[1]!~/^\s*$/) { + print "unkown tag subcommand\n"; + } else { + &shell("git tag -l --format=\"%(taggerdate:short): %(refname:short)\""); + } + } + } + + elsif ($cmd[0] eq 'help') { ############################################################################# help + +print <<"ENDOFHELP"; + +mgsh (git shell) $VERSION $INFO, builtin commands: + + cd [project] change project + open [project] open project + init make new repository from current directory + push [comment] push changes to git server + edit [number] edit last [number] commits (default is 10) + clone [-a] clone repository from git server (-a for archive) + cloneall> clone all repository from git server + checkout [git options] forward checkout to git + log show log + archive [comment] archive current repository + list [-a] [pattern] list repositories on git server (-a for archive) + show show repository log on git server + dist cp changed files to other directory/repository + login connect to git server + do execute extra script with name do..pl + count count lines in project + tag show tags + tag add add tag + tag checkout checkout tag + tag delete delete tag + +ENDOFHELP + + } + + else { ###################################################################### forward unknown command to shell + &shell($cmd) if ($cmd!~/^\s*$/); + } + +} + +######################################################################################################## SUPPORT + +sub shell() { # shell + my($cmd)=@_; + chdir $DIR; + system($cmd); +} + +sub cmd() { # execute command + my($cmd,$quiet)=@_; + print "$cmd\n" if (!$quiet); + system($cmd); +} + +sub readline { # readline + my($prompt,$input,$mode)=@_; use Term::ReadLine; + BEGIN{ $ENV{PERL_RL} = 'Perl o=0' }; + + if (!$term) { + $term = new Term::ReadLine 'term'; + open(IN,"$BASE/.mgsh_history"); + while() { + chomp(); + push(@history,$_); + } + close(IN); + $term->SetHistory(@history); + } + + my($txt)=$term->readline($prompt,$input); + + my(@history)=$term->GetHistory(); + shift(@history) while($#history>=10); + open(OUT,"> $BASE/.mgsh_history"); + print OUT "$_\n" for (@history); + close(OUT); + + return $txt; +} + +sub yesno { # request yes/no answer + my($prom,$def)=@_; + my($ans); + if ($def) {;$ans=&getkey("$prom Y/n ? ");} + else {;$ans=&getkey("$prom y/N ? ");} + if ($ans=~/^\s*$/) { + if ($def) {;return(1);} + else {;return(0);} + } + if ($ans=~/^\s*y\s*$/i || $ans=~/^\s*yes\s*$/i) { + return 1; + } + return 0; +} + +sub getkey { # get key from keyboard + $|=1; + print "$_[0]"; + system "stty", '-icanon', '-echo', 'eol', "\001"; + $key = getc(STDIN);$key=~s/[\r\n\t]//g; + system "stty", 'icanon', 'echo', 'eol', "^@"; + print "$key\n"; + return $key; +} + +sub count() { # count lines in project + my($dir)=@_; + use File::Find; + $lines=0; + find(\&counting,$dir); + sub counting { + $f=$File::Find::name; + if (-f $f) { + if ($f=~/\.[hmc]$/ || $f=~/\.xib$/ || $f=~/\.lm$/ || $f=~/\.ym$/ || $f=~/\.pl$/ || $f=~/\.php$/ || + (-T $f && $f=~/\/bin\//)) { + open(WC,"/usr/bin/wc -l '$f' |"); + while() {; + $lines+=$1 if (/^\s*(\d*)\s+$f/); + } + close(WC); + } + + } + } + print "$lines lines total in $PRJ\n"; +} + +sub repolog() { # show repository log + my($FH)=@_; + my($o)='';my($os)='';my($oss)='';my($n)=0;my($ns)=0; + my($z)='';my($zs)='';my($zss)=''; + + while(<$FH>) { + chomp(); + @tmp=split(' '); + $t=str2time($tmp[1]); + my(@z)=localtime($t);$z[4]+=1;$z[5]+=1900;$z[6]+=1; + + if (time()-$t<86400) { + $z=sprintf(" %02d\:%02d",$z[2],$z[1]); + $zs=sprintf(" %02d\:%02d",$z[2],$z[1]); + $zss=sprintf("%02d\:%02d",$z[2],$z[1]); + } elsif (time()-$t<86400*7) { + $z=sprintf(" %s, %02d\:%02d",$D[$z[6]-1],$z[2],$z[1]); + $zs=sprintf("%s, %02d\:%02d",$D[$z[6]-1],$z[2],$z[1]); + $ns++; + } else { + $z=sprintf("%s, %02d %s %4d, %02d\:%02d",$D[$z[6]-1],$z[3],$M[$z[4]-1],$z[5],$z[2],$z[1]); + $n++; + } + + $o.="$tmp[0] $z $tmp[2]\n"; + $os.="$tmp[0] $zs $tmp[2]\n"; + $oss.="$tmp[0] $zss $tmp[2]\n"; + } + + if ($n==0 && $ns==0) { + print $oss; + } elsif ($n==0 && $ns>0) { + print $os; + } else { + print $o; + } +} + +sub gitignore() { +return << "ENDOFGITIGNORE"; +.DS_Store +.AppleDouble +.LSOverride +._* +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +ENDOFGITIGNORE +} + + +############################################################################################################ END diff --git a/files/mybackup b/files/mybackup new file mode 100755 index 0000000..c40dc0b --- /dev/null +++ b/files/mybackup @@ -0,0 +1,195 @@ +#!/usr/bin/perl +################################################################################ mysql/mariadb backup (mwx'2021) +use Getopt::Std;getopts('bza'); +use DBI; +use Term::ReadKey; + +$VERSION='4.0.0'; + +$HOST = 'localhost'; # settings +$USER = 'mybackup'; +$PASSWD = 'iexae3aitathoo4k'; +$PATH = '/db/backup/mysql'; +$KEEPDAILYBACKUPS = 21; + +$TAR = "/bin/tar"; +$RM = "/bin/rm"; +$MYSQLDUMP = "/usr/bin/mysqldump"; +$GZIP = "/bin/gzip"; + + +if (!$opt_a && !$opt_b && !$opt_z) { # show usage +print <<"ENDOFHELP"; +mybackup, MySQL/MariaDB backup, mwx'2021, v$VERSION +usage: mybackup -a add backup user to db (root password required) + mybackup -b run database backup + mybackup -z run database backup and compress output +ENDOFHELP +exit(0); +} + +if ($opt_a) { # add backup user to db + use Term::ReadPassword; + $rootdbpw = read_password('Enter password: '); + $dbh=DBI->connect("DBI:mysql:mysql:localhost:","root",$rootdbpw,{RaiseError=>1,PrintError=>1}); + + $dbh->do("CREATE USER 'mybackup' IDENTIFIED BY '$PASSWD'"); + $dbh->do("GRANT SELECT, SHOW VIEW, LOCK TABLES, RELOAD,REPLICATION CLIENT ON *.* TO 'mybackup'"); + +# +# +# +# CREATE USER 'mybackup' IDENTIFIED BY 'Yooch0esh9Ah'; +# +# +# $sth=$dbh->prepare("SHOW COLUMNS FROM user");$sth->execute; # find authentication fields +# $HASPW=0;$HASAS=0; +# while ($dat = $sth->fetchrow_hashref) { +# $HASPW=1 if ($$dat{Field} eq 'Password'); +# $HASAS=1 if ($$dat{Field} eq 'authentication_string'); +# } +# +# $sql="INSERT INTO user SET User='$USER',Host='localhost',"; +# $sql.="Password=password('$PASSWD')," if ($HASPW); +# $sql.="authentication_string=password('$PASSWD')," if ($HASAS); +# $sql.="ssl_cipher='',x509_issuer='',x509_subject='',". +# "Select_priv='Y',Reload_priv='Y',Lock_tables_priv='Y',Show_view_priv='Y',Process_priv='Y'"; +# +# $dbh->do($sql); + $dbh->do("flush privileges"); + + if (&yesno('Write /root/.my.cnf file',1)) { + system("rm -f /root/.my.cnf"); + open(OUT,"> /root/.my.cnf"); + print OUT "[client]\nuser=root\npassword=$rootdbpw\n[mysqldump]\nuser=mybackup\npassword=$PASSWD\n"; + close(OUT); + system("chmod 600 /root/.my.cnf"); + } + + &setupcron(); + + exit; +} + +&cleanup(); + +@DBS=&autogetdbs(); + +my(@z)=localtime(time());$z[4]+=1;$z[6]+=1;$z[5]-=100; +$z=sprintf("%02d%02d%02d%02d%02d%02d",$z[3],$z[4],$z[5],$z[2],$z[1],$z[0]); + + +if (!-d "$PATH/$z") { # make target dir + mkdir("$PATH/$z",448); +} + + +for $db (@DBS) { # dump databaeses + if ($db ne 'information_schema' && $db ne 'performance_schema' && $db ne 'sys') { + my($fdb)=$db;$fdb=~s/\s/\./g; + if (!$IGNOREDB{$db}) { + if ($DBPARAM{$db}) {;$db=$DBPARAM{$db};} + &cmd("$MYSQLDUMP -h $HOST -u $USER -f -F -R --skip-extended-insert $db >$PATH/$z/$fdb.mysql"); + } + } +} + + +$cmd="$MYSQLDUMP -h $HOST -u $USER -c -f -F -R --skip-extended-insert -A -v >$PATH/$z.mysql"; +&cmd($cmd); + + +&cmd("$GZIP $PATH/$z.mysql"); +chdir($PATH); +if (-d "$PATH/$z" && $opt_z) { + &cmd("$TAR czvf $z.tar.gz $z"); + &cmd("$RM -rf $PATH/$z"); +} + +######################################################################################################## SUPPORT + +sub cleanup() { + use Date::Parse; + + opendir(DIR,"$PATH"); + while($file=readdir(DIR)) { + + if (-f "$PATH/$file" && $file=~/(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)/) { + $m=$1; + + $a=$3+2000; + $time = str2time("$a/$2/$1 $4:$5:$6"); + + my(@z)=localtime($time);$z[4]+=1;$z[5]-=100;$z[6]+=1; + $z=sprintf("%02d\.%02d\.%02d %02d\:%02d\:%02d",$z[3],$z[4],$z[5],$z[2],$z[1],$z[0]); + + $t=(time()-$time)/86400; + + if ($m!=1 && $t>$KEEPDAILYBACKUPS) { + &cmd("/bin/rm -f $PATH/$file") if (-f "$PATH/$file"); + } + } + } +} + +sub setupcron() { + open(CRON,"crontab -l |"); + while() { + chomp(); + push(@CRON,$_) if (!/\/db\/bin\/mybackup/); + } + + push(@CRON,"0 12 * * * /db/bin/mybackup -z > /dev/null 2>&1"); + + open(OUT,"> /tmp/cron.$$"); + for (@CRON) { + print OUT "$_\n"; + } + close(OUT); + system("/usr/bin/crontab /tmp/cron.$$"); + system("rm -f /tmp/cron.$$"); +} + +sub cmd() { + my($cmd)=@_; + print "$cmd\n"; + system($cmd); +} + +sub autogetdbs() { + my(@dbs); + $dbh=DBI->connect("DBI:mysql::$HOST:",$USER,$PASSWD,{RaiseError=>1,PrintError=>1}); + + $sth=$dbh->prepare("SHOW DATABASES");$sth->execute ; + while ($dat = $sth->fetchrow_hashref) { + push(@dbs,$$dat{Database}); + } + return (@dbs); +} + +sub yesno { + my($prom,$def)=@_; + my($ans); + if ($def) {;$ans=&getkey("$prom Y/n ? ");} + else {;$ans=&getkey("$prom y/N ? ");} + if ($ans=~/^\s*$/) { + if ($def) {;return(1);} + else {;return(0);} + } + if ($ans=~/^\s*y\s*$/i || $ans=~/^\s*yes\s*$/i) { + return 1; + } + return 0; +} + +sub getkey { + $|=1; + print "$_[0]"; + system "stty", '-icanon', '-echo', 'eol', "\001"; + $key = getc(STDIN);$key=~s/[\r\n\t]//g; + system "stty", 'icanon', 'echo', 'eol', "^@"; + print "$key\n"; + return $key; +} + +############################################################################################################ END diff --git a/files/myuser b/files/myuser new file mode 100755 index 0000000..6d75c43 --- /dev/null +++ b/files/myuser @@ -0,0 +1,43 @@ +#!/usr/bin/perl +########################################################################## mysql/mariadb user manager (mwx'2021) +use DBI; +use Getopt::Std;getopts('hd:x'); + +$VERSION='4.0.0'; + +&help() if ($ARGV[0]=~/^\s*$/ || $opt_h); + +$USER=$DB=$ARGV[0]; +$DB=$opt_d if ($opt_d!~/^\s*$/); + +$PW=sprintf("$USER%03d",int(rand(100000))); + +my $dsn = "DBI:mysql:mysql;mysql_read_default_file=$ENV{HOME}/.my.cnf"; +$dbh=DBI->connect($dsn,undef,undef,{PrintError=>1}); + +&sqldo("CREATE DATABASE IF NOT EXISTS $DB") if (!$opt_x); +&sqldo("DROP USER IF EXISTS '$USER'"); +&sqldo("CREATE USER '$USER' IDENTIFIED BY '$PW'"); +&sqldo("GRANT ALL PRIVILEGES ON $DB.* TO '$USER'"); + +sub sqldo() { + my($sql)=@_; + print "$sql\n"; + $dbh->do($sql); +} + +sub help() { +print <<"ENDOFHELP"; + +myuser - mariadb user manager (v$VERSION) + +myuser add user and database with the same name to mariadb +myuser -d add user and database to mariadb +myuser -x add only user to mariadb + +ENDOFHELP +exit(); +} + +############################################################################################################ END + diff --git a/files/psmem b/files/psmem new file mode 100755 index 0000000..074e824 --- /dev/null +++ b/files/psmem @@ -0,0 +1,611 @@ +#!/usr/bin/env python + +# Try to determine how much RAM is currently being used per program. +# Note per _program_, not per process. So for example this script +# will report RAM used by all httpd process together. In detail it reports: +# sum(private RAM for program processes) + sum(Shared RAM for program processes) +# The shared RAM is problematic to calculate, and this script automatically +# selects the most accurate method available for your kernel. + +# Licence: LGPLv2 +# Author: P@draigBrady.com +# Source: http://www.pixelbeat.org/scripts/ps_mem.py + +# V1.0 06 Jul 2005 Initial release +# V1.1 11 Aug 2006 root permission required for accuracy +# V1.2 08 Nov 2006 Add total to output +# Use KiB,MiB,... for units rather than K,M,... +# V1.3 22 Nov 2006 Ignore shared col from /proc/$pid/statm for +# 2.6 kernels up to and including 2.6.9. +# There it represented the total file backed extent +# V1.4 23 Nov 2006 Remove total from output as it's meaningless +# (the shared values overlap with other programs). +# Display the shared column. This extra info is +# useful, especially as it overlaps between programs. +# V1.5 26 Mar 2007 Remove redundant recursion from human() +# V1.6 05 Jun 2007 Also report number of processes with a given name. +# Patch from riccardo.murri@gmail.com +# V1.7 20 Sep 2007 Use PSS from /proc/$pid/smaps if available, which +# fixes some over-estimation and allows totalling. +# Enumerate the PIDs directly rather than using ps, +# which fixes the possible race between reading +# RSS with ps, and shared memory with this program. +# Also we can show non truncated command names. +# V1.8 28 Sep 2007 More accurate matching for stats in /proc/$pid/smaps +# as otherwise could match libraries causing a crash. +# Patch from patrice.bouchand.fedora@gmail.com +# V1.9 20 Feb 2008 Fix invalid values reported when PSS is available. +# Reported by Andrey Borzenkov +# V3.9 07 Mar 2017 +# http://github.com/pixelb/scripts/commits/master/scripts/ps_mem.py + +# Notes: +# +# All interpreted programs where the interpreter is started +# by the shell or with env, will be merged to the interpreter +# (as that's what's given to exec). For e.g. all python programs +# starting with "#!/usr/bin/env python" will be grouped under python. +# You can change this by using the full command line but that will +# have the undesirable affect of splitting up programs started with +# differing parameters (for e.g. mingetty tty[1-6]). +# +# For 2.6 kernels up to and including 2.6.13 and later 2.4 redhat kernels +# (rmap vm without smaps) it can not be accurately determined how many pages +# are shared between processes in general or within a program in our case: +# http://lkml.org/lkml/2005/7/6/250 +# A warning is printed if overestimation is possible. +# In addition for 2.6 kernels up to 2.6.9 inclusive, the shared +# value in /proc/$pid/statm is the total file-backed extent of a process. +# We ignore that, introducing more overestimation, again printing a warning. +# Since kernel 2.6.23-rc8-mm1 PSS is available in smaps, which allows +# us to calculate a more accurate value for the total RAM used by programs. +# +# Programs that use CLONE_VM without CLONE_THREAD are discounted by assuming +# they're the only programs that have the same /proc/$PID/smaps file for +# each instance. This will fail if there are multiple real instances of a +# program that then use CLONE_VM without CLONE_THREAD, or if a clone changes +# its memory map while we're checksumming each /proc/$PID/smaps. +# +# I don't take account of memory allocated for a program +# by other programs. For e.g. memory used in the X server for +# a program could be determined, but is not. +# +# FreeBSD is supported if linprocfs is mounted at /compat/linux/proc/ +# FreeBSD 8.0 supports up to a level of Linux 2.6.16 + +import getopt +import time +import errno +import os +import sys + +# The following exits cleanly on Ctrl-C or EPIPE +# while treating other exceptions as before. +def std_exceptions(etype, value, tb): + sys.excepthook = sys.__excepthook__ + if issubclass(etype, KeyboardInterrupt): + pass + elif issubclass(etype, IOError) and value.errno == errno.EPIPE: + pass + else: + sys.__excepthook__(etype, value, tb) +sys.excepthook = std_exceptions + +# +# Define some global variables +# + +PAGESIZE = os.sysconf("SC_PAGE_SIZE") / 1024 #KiB +our_pid = os.getpid() + +have_pss = 0 +have_swap_pss = 0 + +class Proc: + def __init__(self): + uname = os.uname() + if uname[0] == "FreeBSD": + self.proc = '/compat/linux/proc' + else: + self.proc = '/proc' + + def path(self, *args): + return os.path.join(self.proc, *(str(a) for a in args)) + + def open(self, *args): + try: + if sys.version_info < (3,): + return open(self.path(*args)) + else: + return open(self.path(*args), errors='ignore') + except (IOError, OSError): + val = sys.exc_info()[1] + if (val.errno == errno.ENOENT or # kernel thread or process gone + val.errno == errno.EPERM or + val.errno == errno.EACCES): + raise LookupError + raise + +proc = Proc() + + +# +# Functions +# + +def parse_options(): + try: + long_options = [ + 'split-args', + 'help', + 'total', + 'discriminate-by-pid', + 'swap' + ] + opts, args = getopt.getopt(sys.argv[1:], "shtdSp:w:", long_options) + except getopt.GetoptError: + sys.stderr.write(help()) + sys.exit(3) + + if len(args): + sys.stderr.write("Extraneous arguments: %s\n" % args) + sys.exit(3) + + # ps_mem.py options + split_args = False + pids_to_show = None + discriminate_by_pid = False + show_swap = False + watch = None + only_total = False + + for o, a in opts: + if o in ('-s', '--split-args'): + split_args = True + if o in ('-t', '--total'): + only_total = True + if o in ('-d', '--discriminate-by-pid'): + discriminate_by_pid = True + if o in ('-S', '--swap'): + show_swap = True + if o in ('-h', '--help'): + sys.stdout.write(help()) + sys.exit(0) + if o in ('-p',): + try: + pids_to_show = [int(x) for x in a.split(',')] + except: + sys.stderr.write(help()) + sys.exit(3) + if o in ('-w',): + try: + watch = int(a) + except: + sys.stderr.write(help()) + sys.exit(3) + + return ( + split_args, + pids_to_show, + watch, + only_total, + discriminate_by_pid, + show_swap + ) + + +def help(): + help_msg = 'Usage: ps_mem [OPTION]...\n' \ + 'Show program core memory usage\n' \ + '\n' \ + ' -h, -help Show this help\n' \ + ' -p [,pid2,...pidN] Only show memory usage PIDs in the '\ + 'specified list\n' \ + ' -s, --split-args Show and separate by, all command line'\ + ' arguments\n' \ + ' -t, --total Show only the total value\n' \ + ' -d, --discriminate-by-pid Show by process rather than by program\n' \ + ' -S, --swap Show swap information\n' \ + ' -w Measure and show process memory every'\ + ' N seconds\n' + + return help_msg + + +# (major,minor,release) +def kernel_ver(): + kv = proc.open('sys/kernel/osrelease').readline().split(".")[:3] + last = len(kv) + if last == 2: + kv.append('0') + last -= 1 + while last > 0: + for char in "-_": + kv[last] = kv[last].split(char)[0] + try: + int(kv[last]) + except: + kv[last] = 0 + last -= 1 + return (int(kv[0]), int(kv[1]), int(kv[2])) + + +#return Private,Shared +#Note shared is always a subset of rss (trs is not always) +def getMemStats(pid): + global have_pss + global have_swap_pss + mem_id = pid #unique + Private_lines = [] + Shared_lines = [] + Pss_lines = [] + Rss = (int(proc.open(pid, 'statm').readline().split()[1]) + * PAGESIZE) + Swap_lines = [] + Swap_pss_lines = [] + + Swap = 0 + Swap_pss = 0 + + if os.path.exists(proc.path(pid, 'smaps')): # stat + lines = proc.open(pid, 'smaps').readlines() # open + # Note we checksum smaps as maps is usually but + # not always different for separate processes. + mem_id = hash(''.join(lines)) + for line in lines: + if line.startswith("Shared"): + Shared_lines.append(line) + elif line.startswith("Private"): + Private_lines.append(line) + elif line.startswith("Pss"): + have_pss = 1 + Pss_lines.append(line) + elif line.startswith("Swap:"): + Swap_lines.append(line) + elif line.startswith("SwapPss:"): + have_swap_pss = 1 + Swap_pss_lines.append(line) + Shared = sum([int(line.split()[1]) for line in Shared_lines]) + Private = sum([int(line.split()[1]) for line in Private_lines]) + #Note Shared + Private = Rss above + #The Rss in smaps includes video card mem etc. + if have_pss: + pss_adjust = 0.5 # add 0.5KiB as this avg error due to truncation + Pss = sum([float(line.split()[1])+pss_adjust for line in Pss_lines]) + Shared = Pss - Private + # Note that Swap = Private swap + Shared swap. + Swap = sum([int(line.split()[1]) for line in Swap_lines]) + if have_swap_pss: + # The kernel supports SwapPss, that shows proportional swap share. + # Note that Swap - SwapPss is not Private Swap. + Swap_pss = sum([int(line.split()[1]) for line in Swap_pss_lines]) + elif (2,6,1) <= kernel_ver() <= (2,6,9): + Shared = 0 #lots of overestimation, but what can we do? + Private = Rss + else: + Shared = int(proc.open(pid, 'statm').readline().split()[2]) + Shared *= PAGESIZE + Private = Rss - Shared + return (Private, Shared, mem_id, Swap, Swap_pss) + + +def getCmdName(pid, split_args, discriminate_by_pid): + cmdline = proc.open(pid, 'cmdline').read().split("\0") + if cmdline[-1] == '' and len(cmdline) > 1: + cmdline = cmdline[:-1] + + path = proc.path(pid, 'exe') + try: + path = os.readlink(path) + # Some symlink targets were seen to contain NULs on RHEL 5 at least + # https://github.com/pixelb/scripts/pull/10, so take string up to NUL + path = path.split('\0')[0] + except OSError: + val = sys.exc_info()[1] + if (val.errno == errno.ENOENT or # either kernel thread or process gone + val.errno == errno.EPERM or + val.errno == errno.EACCES): + raise LookupError + raise + + if split_args: + return ' '.join(cmdline).replace('\n', ' ') + if path.endswith(" (deleted)"): + path = path[:-10] + if os.path.exists(path): + path += " [updated]" + else: + #The path could be have prelink stuff so try cmdline + #which might have the full path present. This helped for: + #/usr/libexec/notification-area-applet.#prelink#.fX7LCT (deleted) + if os.path.exists(cmdline[0]): + path = cmdline[0] + " [updated]" + else: + path += " [deleted]" + exe = os.path.basename(path) + cmd = proc.open(pid, 'status').readline()[6:-1] + if exe.startswith(cmd): + cmd = exe #show non truncated version + #Note because we show the non truncated name + #one can have separated programs as follows: + #584.0 KiB + 1.0 MiB = 1.6 MiB mozilla-thunder (exe -> bash) + # 56.0 MiB + 22.2 MiB = 78.2 MiB mozilla-thunderbird-bin + if sys.version_info >= (3,): + cmd = cmd.encode(errors='replace').decode() + if discriminate_by_pid: + cmd = '%s [%d]' % (cmd, pid) + return cmd + + +#The following matches "du -h" output +#see also human.py +def human(num, power="Ki", units=None): + if units is None: + powers = ["Ki", "Mi", "Gi", "Ti"] + while num >= 1000: #4 digits + num /= 1024.0 + power = powers[powers.index(power)+1] + return "%.1f %sB" % (num, power) + else: + return "%.f" % ((num * 1024) / units) + + +def cmd_with_count(cmd, count): + if count > 1: + return "%s (%u)" % (cmd, count) + else: + return cmd + +#Warn of possible inaccuracies +#2 = accurate & can total +#1 = accurate only considering each process in isolation +#0 = some shared mem not reported +#-1= all shared mem not reported +def shared_val_accuracy(): + """http://wiki.apache.org/spamassassin/TopSharedMemoryBug""" + kv = kernel_ver() + pid = os.getpid() + if kv[:2] == (2,4): + if proc.open('meminfo').read().find("Inact_") == -1: + return 1 + return 0 + elif kv[:2] == (2,6): + if os.path.exists(proc.path(pid, 'smaps')): + if proc.open(pid, 'smaps').read().find("Pss:")!=-1: + return 2 + else: + return 1 + if (2,6,1) <= kv <= (2,6,9): + return -1 + return 0 + elif kv[0] > 2 and os.path.exists(proc.path(pid, 'smaps')): + return 2 + else: + return 1 + +def show_shared_val_accuracy( possible_inacc, only_total=False ): + level = ("Warning","Error")[only_total] + if possible_inacc == -1: + sys.stderr.write( + "%s: Shared memory is not reported by this system.\n" % level + ) + sys.stderr.write( + "Values reported will be too large, and totals are not reported\n" + ) + elif possible_inacc == 0: + sys.stderr.write( + "%s: Shared memory is not reported accurately by this system.\n" % level + ) + sys.stderr.write( + "Values reported could be too large, and totals are not reported\n" + ) + elif possible_inacc == 1: + sys.stderr.write( + "%s: Shared memory is slightly over-estimated by this system\n" + "for each program, so totals are not reported.\n" % level + ) + sys.stderr.close() + if only_total and possible_inacc != 2: + sys.exit(1) + + +def get_memory_usage(pids_to_show, split_args, discriminate_by_pid, + include_self=False, only_self=False): + cmds = {} + shareds = {} + mem_ids = {} + count = {} + swaps = {} + shared_swaps = {} + for pid in os.listdir(proc.path('')): + if not pid.isdigit(): + continue + pid = int(pid) + + # Some filters + if only_self and pid != our_pid: + continue + if pid == our_pid and not include_self: + continue + if pids_to_show is not None and pid not in pids_to_show: + continue + + try: + cmd = getCmdName(pid, split_args, discriminate_by_pid) + except LookupError: + #operation not permitted + #kernel threads don't have exe links or + #process gone + continue + + try: + private, shared, mem_id, swap, swap_pss = getMemStats(pid) + except RuntimeError: + continue #process gone + if shareds.get(cmd): + if have_pss: #add shared portion of PSS together + shareds[cmd] += shared + elif shareds[cmd] < shared: #just take largest shared val + shareds[cmd] = shared + else: + shareds[cmd] = shared + cmds[cmd] = cmds.setdefault(cmd, 0) + private + if cmd in count: + count[cmd] += 1 + else: + count[cmd] = 1 + mem_ids.setdefault(cmd, {}).update({mem_id: None}) + + # Swap (overcounting for now...) + swaps[cmd] = swaps.setdefault(cmd, 0) + swap + if have_swap_pss: + shared_swaps[cmd] = shared_swaps.setdefault(cmd, 0) + swap_pss + else: + shared_swaps[cmd] = 0 + + # Total swaped mem for each program + total_swap = 0 + + # Total swaped shared mem for each program + total_shared_swap = 0 + + # Add shared mem for each program + total = 0 + + for cmd in cmds: + cmd_count = count[cmd] + if len(mem_ids[cmd]) == 1 and cmd_count > 1: + # Assume this program is using CLONE_VM without CLONE_THREAD + # so only account for one of the processes + cmds[cmd] /= cmd_count + if have_pss: + shareds[cmd] /= cmd_count + cmds[cmd] = cmds[cmd] + shareds[cmd] + total += cmds[cmd] # valid if PSS available + total_swap += swaps[cmd] + if have_swap_pss: + total_shared_swap += shared_swaps[cmd] + + sorted_cmds = sorted(cmds.items(), key=lambda x:x[1]) + sorted_cmds = [x for x in sorted_cmds if x[1]] + + return sorted_cmds, shareds, count, total, swaps, shared_swaps, \ + total_swap, total_shared_swap + + +def print_header(show_swap, discriminate_by_pid): + output_string = " Private + Shared = RAM used" + if show_swap: + if have_swap_pss: + output_string += " " * 5 + "Shared Swap" + output_string += " Swap used" + output_string += "\tProgram" + if discriminate_by_pid: + output_string += "[pid]" + output_string += "\n\n" + sys.stdout.write(output_string) + + +def print_memory_usage(sorted_cmds, shareds, count, total, swaps, total_swap, + shared_swaps, total_shared_swap, show_swap): + for cmd in sorted_cmds: + + output_string = "%9s + %9s = %9s" + output_data = (human(cmd[1]-shareds[cmd[0]]), + human(shareds[cmd[0]]), human(cmd[1])) + if show_swap: + if have_swap_pss: + output_string += "\t%9s" + output_data += (human(shared_swaps[cmd[0]]),) + output_string += " %9s" + output_data += (human(swaps[cmd[0]]),) + output_string += "\t%s\n" + output_data += (cmd_with_count(cmd[0], count[cmd[0]]),) + + sys.stdout.write(output_string % output_data) + + if have_pss: + if show_swap: + if have_swap_pss: + sys.stdout.write("%s\n%s%9s%s%9s%s%9s\n%s\n" % + ("-" * 61, " " * 24, human(total), " " * 7, + human(total_shared_swap), " " * 3, + human(total_swap), "=" * 61)) + else: + sys.stdout.write("%s\n%s%9s%s%9s\n%s\n" % + ("-" * 45, " " * 24, human(total), " " * 3, + human(total_swap), "=" * 45)) + else: + sys.stdout.write("%s\n%s%9s\n%s\n" % + ("-" * 33, " " * 24, human(total), "=" * 33)) + + +def verify_environment(pids_to_show): + if os.geteuid() != 0 and not pids_to_show: + sys.stderr.write("Sorry, root permission required, or specify pids with -p\n") + sys.stderr.close() + sys.exit(1) + + try: + kernel_ver() + except (IOError, OSError): + val = sys.exc_info()[1] + if val.errno == errno.ENOENT: + sys.stderr.write( + "Couldn't access " + proc.path('') + "\n" + "Only GNU/Linux and FreeBSD (with linprocfs) are supported\n") + sys.exit(2) + else: + raise + +def main(): + split_args, pids_to_show, watch, only_total, discriminate_by_pid, \ + show_swap = parse_options() + + verify_environment(pids_to_show) + + if not only_total: + print_header(show_swap, discriminate_by_pid) + + if watch is not None: + try: + sorted_cmds = True + while sorted_cmds: + sorted_cmds, shareds, count, total, swaps, shared_swaps, \ + total_swap, total_shared_swap = \ + get_memory_usage(pids_to_show, split_args, + discriminate_by_pid) + if only_total and have_pss: + sys.stdout.write(human(total, units=1)+'\n') + elif not only_total: + print_memory_usage(sorted_cmds, shareds, count, total, + swaps, total_swap, shared_swaps, + total_shared_swap, show_swap) + + sys.stdout.flush() + time.sleep(watch) + else: + sys.stdout.write('Process does not exist anymore.\n') + except KeyboardInterrupt: + pass + else: + # This is the default behavior + sorted_cmds, shareds, count, total, swaps, shared_swaps, total_swap, \ + total_shared_swap = get_memory_usage(pids_to_show, split_args, + discriminate_by_pid) + if only_total and have_pss: + sys.stdout.write(human(total, units=1)+'\n') + elif not only_total: + print_memory_usage(sorted_cmds, shareds, count, total, swaps, + total_swap, shared_swaps, total_shared_swap, + show_swap) + + # We must close explicitly, so that any EPIPE exception + # is handled by our excepthook, rather than the default + # one which is reenabled after this script finishes. + sys.stdout.close() + + vm_accuracy = shared_val_accuracy() + show_shared_val_accuracy( vm_accuracy, only_total ) + +if __name__ == '__main__': main() diff --git a/files/rc.local.debian b/files/rc.local.debian new file mode 100644 index 0000000..352cc5d --- /dev/null +++ b/files/rc.local.debian @@ -0,0 +1,3 @@ +#!/bin/sh -e + +exit 0 \ No newline at end of file diff --git a/files/rc.local.ubuntu b/files/rc.local.ubuntu new file mode 100644 index 0000000..f13c61f --- /dev/null +++ b/files/rc.local.ubuntu @@ -0,0 +1,6 @@ +#!/bin/sh -e + +find /etc/update-motd.d -type f,l ! -name '98*' -delete +/bin/run-parts /etc/update-motd.d + +exit 0 \ No newline at end of file diff --git a/files/rt b/files/rt new file mode 100755 index 0000000..6c616af --- /dev/null +++ b/files/rt @@ -0,0 +1,289 @@ +#!/usr/bin/perl +################################################################################ rt - restic wrapper (mwx'2026) +use File::Basename;use Term::ReadKey;use Getopt::Std;getopts('c:n:i:t:p:'); + +$VERSION='1.5.6'; + +$CONFIG='default';$CONFIG=$opt_c if ($opt_c!~/^\s*$/); # set deault options options +chomp($host=`hostname`);$host=~s/^([^\.]+).*/$1/; +$NAME=$host; +$POLICY='--keep-daily 14 --keep-weekly 12 --keep-monthly 12 --keep-yearly 100'; + +for ('/db/etc/rt.conf',$ENV{"HOME"}.'/.rt.conf') { $CONF=$_ if (-f $_);} # find/load/check configuration +die "Fatal: no config file found\n" if ($CONF=~/^\s*$/); + +require($CONF); + +$NAME = $opt_n if ($opt_n!~/^\s*$/); # overwrite options with commandline (name, id, tag, password) +$ID = $opt_i if ($opt_i!~/^\s*$/); +$TAG = $opt_t if ($opt_t!~/^\s*$/); +$PASSWORD = $opt_p if ($opt_p!~/^\s*$/); + +for ('$NAME','$TARGET','$SRC','$RESTIC','$LOG') { + die "Fatal: missing $_ in config\n" if (eval($_)=~/^\s*$/); +} + +$ID='0' if ($ID=~/^\s*$/); # set repository +$REPOSITORY="$TARGET/$NAME.$ID"; + + +print "rt $VERSION, Name: $NAME, Repository: $REPOSITORY, Config: $CONFIG\n"; + + +open(PW,"> $PWFILE");print PW "$PASSWORD\n";close(PW); + +$ENV{'RESTIC_REPOSITORY'} = $REPOSITORY; # set environment +$ENV{'RESTIC_PASSWORD_FILE'} = $PWFILE; + +$r=`$RESTIC version`; # find restic version +if ($r=~/restic\s+([\d\.]+)\s+compiled/) { + $RVERSION=$1; + @RV=split('\.',$1);$RVN=sprintf("%02d%02d%02d",$RV[0],$RV[1],$RV[2]); +} + +$TMP="/tmp"; + +my(@z)=localtime(time());$z[4]+=1;$z[5]-=100;$z[6]+=1; +$z=sprintf("%02d\.%02d\.%02d %02d\:%02d",$z[3],$z[4],$z[5],$z[2],$z[1]); + + +if ($ARGV[0] eq 'cleanup') { # ----------------------------------------------------------- forget, prune, check + + $ts=time(); + + print "$RESTIC -r $REPOSITORY forget $POLICY --prune\n"; # forget & prune + + $rms=0; + open(IN,"$RESTIC forget $POLICY --prune |"); + while() { + print; + $rms=$1 if (/^(\d+)\s+snapshots\s+have\s+been\s+removed/) + } + + print "$RESTIC -r $REPOSITORY check\n"; # check + + open(IN,"$RESTIC check |"); + while() { + print; + chomp($lastline=$_); + } + + $rt=time()-$ts; + + if ($HTTP_LOG!~/^\s*$/) { # http loging + $tmp= "RTC,$VERSION/$RVERSION,$NAME,$ID,$CONFIG,$TAG,$REPOSITORY,$lastline,$rms,$rt"; + use LWP::UserAgent; + my $ua = new LWP::UserAgent(); + $response = $ua->post("https://$HTTP_LOG", Content => $tmp); + } + + if ($MY_HOST!~/^\s*$/) { # mysql loging + use DBI; + $dbh=DBI->connect("DBI:mysql:$MY_DB:$MY_HOST:$MY_PORT",$MY_USER,$MY_PASSWD,{RaiseError=>1,PrintError=>1}); + $sql="INSERT INTO resticcleanup VALUES(now(),'$VERSION/$RVERSION', + '$NAME','$ID','$CONFIG','$TAG','$REPOSITORY','$lastline',$rms,$rt)"; + $dbh->do($sql); + } + +} elsif ($ARGV[0] eq 'backup' || $ARGV[0] eq 'delaybackup') { # ----------------------------------- run backup + $snap='';$added='';$total=''; + + if ($ARGV[0] eq 'delaybackup') { + printf "$z --- delaybackup (%d sec) ---\n",&dfn($NAME); + sleep(&dfn($NAME)) + } else { + printf "$z --- backup ---\n"; + } + + print "$RESTIC -r $REPOSITORY -vv backup $EXCLUDE $SRC\n"; + + $ts=time(); + open(IN,"$RESTIC -vv backup $EXCLUDE $SRC |"); + while() { + print if (!/^unchanged/); + + if (/Files:\s*(\d+)\s*new,\s*(\d+)\s*changed,\s*(\d+)\s*unmodified/) { + $fn+=$1;$fc+=$2;$fu+=$3; + } + if (/Dirs:\s*(\d+)\s*new,\s*(\d+)\s*changed,\s*(\d+)\s*unmodified/) { + $fn+=$1;$fc+=$2;$fu+=$3; + } + $snap=$1 if (/snapshot\s+([^\s]+)\s+saved/); + $added=&deform($1) if (/Added\s+to\s+the\s+repo:\s+(.*)/); + $added=&deform($1) if (/Added\s+to\s+the\s+repository:\s+([^\(]*)/); + + $total=&deform($1) if (/processed\s+\d+\s+files,\s+(.*)\s+in/); + $files=$1 if (/processed\s+(\d+)\s+files,\s+.*\s+in/); + } + + if ($snap!~/^\s*$/ && $added!~/^\s*$/ && $total!~/^\s*$/) { + $rt=time()-$ts; + + open(LOG,">> $LOG"); # write logfile + print LOG "$z [$NAME/$snap], Files: $files, New: $fn, Changed: $fc, ". + "Unmodified: $fu, Added: $added, Total: $total, Runtime: $rt\n"; + close(LOG); + + if ($HTTP_LOG!~/^\s*$/) { # http loging + $tmp= "RT,$VERSION/$RVERSION,$NAME,$ID,$CONFIG,$TAG,$REPOSITORY,". + "$snap,$files,$fn,$fc,$fu,$added,$total,$rt"; + use LWP::UserAgent; + my $ua = new LWP::UserAgent(); + $response = $ua->post("https://$HTTP_LOG", Content => $tmp); + } + + if ($MY_HOST!~/^\s*$/) { # mysql loging + use DBI; + $dbh=DBI->connect("DBI:mysql:$MY_DB:$MY_HOST:$MY_PORT",$MY_USER,$MY_PASSWD,{RaiseError=>1,PrintError=>1}); + $sql="INSERT INTO restic VALUES(now(),'$VERSION/$RVERSION', + '$NAME','$ID','$CONFIG','$TAG','$REPOSITORY','$snap',$files,$fn,$fc,$fu,$added,$total,$rt)"; + $dbh->do($sql); + } + } + + +} elsif ($ARGV[0] eq 'password') { # ----------------------------------------------- setup restic password file + system("mkdir -p ".&dirname($PWFILE)) if (!-d &dirname($PWFILE)); + + print "new repository password: "; + chomp($pwd = &ReadLine(0)); + + if ($pwd!~/^\s*$/) { + open(OUT,"> $PWFILE");print OUT "$pwd\n";close(OUT); + } + + +} elsif ($ARGV[0] eq 'help' || $ARGV[0]=~/^\s*$/) { # ----------------------------------------------- show help + + &help(); + &advhelp() if ($ARGV[0] eq 'help'); + + +} else { # ------------------------------------------------------------------------------ other restic commands + + system("$RESTIC @ARGV"); + + if ($ARGV[0] eq 'init') { + system("rm -f /var/log/restic.log /var/log/rt.log"); + } + +} + +####################################################################################################### SUPPORT + +sub deform() { # transform sizes + my($s)=@_; + return $1<<40 if ($s=~/([\d\.]+)\s*TiB/i); + return $1<<30 if ($s=~/([\d\.]+)\s*GiB/i); + return $1<<20 if ($s=~/([\d\.]+)\s*MiB/i); + return $1<<10 if ($s=~/([\d\.]+)\s*KiB/i); + return $1 if ($s=~/([\d\.]+)\s*B/i); +} + +sub dfn() { # calculate delay from string + my($s)=@_;my $v=0;my $n=1; + $v+=ord($_)*$n++ for (split('',$s)); + return ($v%24)*5*60; +} + +sub help() { # help +print "\nrt v$VERSION - restic wrapper (mwx'2022)\n"; +print <<'ENDOFHELP'; + + USAGE: + ------ + rt [options] backup run restic backup + rt [options] delaybackup run delayed restic backup + rt [options] cleanup run forget, prune and check + rt [options] password setup restic password file + rt [options] init initialize restic repository + rt help advanced help + + rt other commands will be forwarded directly to restic + + options: -c sets $CONFIG (default is 'default') + -n overwrite $NAME + -i overwrite $ID + -t overwrite $TAG + -p overwrite $PASSWORD + +ENDOFHELP +} + +sub advhelp() { # advanced help +print <<'ENDOFHELP'; + CONFIG FILE (/db/etc/rt.conf) + ----------------------------- + $NAME = 'NAME'; # backup name + $ID = '0'; # repository id (optional, default is 0) + $TAG = 'TAG'; # custom tag for logging (optional) + + $TARGET = "/backup/restic"; # restic target + = "s3:http://188.68.34.116:9234/restic"; + = "b2:mwx002:restic/server"; + + $SRC = '/etc /db /var /root /home /usr/local /opt'; # source paths + + $EXCLUDE = '-e /var/lib/lxcfs -e /var/log/journal'; # exclude options + + $RESTIC = '/db/bin/restic'; # restic binary + $LOG = '/var/log/restic.log'; # log file + $PWFILE = '/db/etc/restic.pw'; # restic password file + + $HTTP_LOG = 'HOST'; # host for logging via https + + $MY_HOST = 'HOST'; # mysql host + $MY_PORT = 'PORT'; # mysql port + $MY_USER = 'USER'; # mysql user + $MY_PASSWD = 'PASSWORD'; # mysql password + $MY_DB = 'DATABASE'; # mysql database + + + $ENV{'AWS_ACCESS_KEY_ID'} = '123456'; # S3 token example + $ENV{'AWS_SECRET_ACCESS_KEY'} = 'abcdefg'; + + $ENV{'B2_ACCOUNT_ID'} = '123456'; # B2 token example + $ENV{'B2_ACCOUNT_KEY'} = 'abcdefg'; + + MYSQL LOGGING TABLES: + --------------------- + CREATE TABLE `restic` ( + `ts` timestamp NULL DEFAULT NULL, + `version` varchar(255) DEFAULT NULL, + `name` varchar(255) DEFAULT NULL, + `id` int(11) DEFAULT NULL, + `config` varchar(255) DEFAULT NULL, + `tag` varchar(255) DEFAULT NULL, + `repository` varchar(255) DEFAULT NULL, + `snapshot` varchar(255) DEFAULT NULL, + `files` bigint(11) DEFAULT NULL, + `new` bigint(11) DEFAULT NULL, + `changed` bigint(11) DEFAULT NULL, + `unmodified` bigint(11) DEFAULT NULL, + `added` bigint(11) DEFAULT NULL, + `total` bigint(11) DEFAULT NULL, + `runtime` int(11) DEFAULT NULL + ) ENGINE=InnoDB DEFAULT CHARSET=latin1; + + CREATE TABLE `resticcleanup` ( + `ts` timestamp NULL DEFAULT NULL, + `version` varchar(255) DEFAULT NULL, + `name` varchar(255) DEFAULT NULL, + `id` int(11) DEFAULT NULL, + `config` varchar(255) DEFAULT NULL, + `tag` varchar(255) DEFAULT NULL, + `repository` varchar(255) DEFAULT NULL, + `txt` varchar(255) DEFAULT NULL, + `rmsnap` int(11) DEFAULT NULL, + `runtime` int(11) DEFAULT NULL + ) ENGINE=InnoDB DEFAULT CHARSET=latin1; + + CRONTAB ENTRIES: + --------------- + 0 2 * * * /db/bin/rt delaybackup >> /var/log/rt.log 2>&1 + 0 7 * * 6 /db/bin/rt cleanup >> /var/log/rt.log 2>&1 + +ENDOFHELP +} + +########################################################################################################### END diff --git a/files/telemetry b/files/telemetry new file mode 100755 index 0000000..f9bb0f6 --- /dev/null +++ b/files/telemetry @@ -0,0 +1,43 @@ +#!/usr/bin/perl +####################################################################### telemetry collector - v1.0.0 (mwx'2020) +use LWP::UserAgent; +chomp($host=`hostname`);$host=~s/\..*$//i; + +$url = 'http://monitor.rz-berlin.mpg.de/telemetry.php'; + +############################################################################################ collect disk usage + +$data = "df,$host,"; + +open(IN,"/bin/df -k -T |"); +while() { + @df=split(' '); + if ($df[1]=~/^ext/ || $df[1]=~/^nfs/) { + $total=($df[2]/1024/1024); + $avail=($df[4]/1024/1024); + $used=$total - $avail; + $per=$used*100/$total; + $data.=sprintf("$df[6],%.3f,%.3f,%.3f,%.2f,",$total,$avail,$used,$per); + } +} + +$data .= time(); + +print "$data\n"; +my $ua = new LWP::UserAgent(); +$response = $ua->post($url, Content => $data); + +########################################################################################### collect system load + +open(UPTIME,"/usr/bin/uptime |");chomp($_=); +if (/load\s*averages*\:\s*[\d\.]+\,\s*[\d\.]+\,\s*([\d\.]+)/) { + $load=$1; +} + +$data = "load,$host,$load,".time(); + +print "$data\n"; +my $ua = new LWP::UserAgent(); +$response = $ua->post($url, Content => $data); + +########################################################################################################### END diff --git a/files/timesyncd.conf b/files/timesyncd.conf new file mode 100644 index 0000000..795125f --- /dev/null +++ b/files/timesyncd.conf @@ -0,0 +1,26 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation; either version 2.1 of the License, or (at your option) +# any later version. +# +# Entries in this file show the compile time defaults. Local configuration +# should be created by either modifying this file (or a copy of it placed in +# /etc/ if the original file is shipped in /usr/), or by creating "drop-ins" in +# the /etc/systemd/timesyncd.conf.d/ directory. The latter is generally +# recommended. Defaults can be restored by simply deleting the main +# configuration file and all drop-ins located in /etc/. +# +# Use 'systemd-analyze cat-config systemd/timesyncd.conf' to display the full config. +# +# See timesyncd.conf(5) for details. + +[Time] +NTP=de.pool.ntp.org +FallbackNTP=ptbtime1.ptb.de 0.debian.pool.ntp.org 1.debian.pool.ntp.org 2.debian.pool.ntp.org 3.debian.pool.ntp.org +#RootDistanceMaxSec=5 +#PollIntervalMinSec=32 +#PollIntervalMaxSec=2048 +#ConnectionRetrySec=30 +#SaveIntervalSec=60 diff --git a/files/zshrc b/files/zshrc new file mode 100644 index 0000000..70a7f8c --- /dev/null +++ b/files/zshrc @@ -0,0 +1,96 @@ + +unsetopt always_last_prompt +autoload -U colors && colors +zle_highlight+=(paste:none) +unsetopt BEEP +autoload -U compinit +compinit + +bindkey "\e[3~" delete-char +bindkey '^[[F' end-of-line +bindkey '^[[H' beginning-of-line +bindkey '^[[6~' end-of-line +bindkey '^[[5~' beginning-of-line + +HISTFILE=~/.zsh_history +HISTSIZE=10000 +SAVEHIST=10000 +setopt HIST_REDUCE_BLANKS +setopt EXTENDED_HISTORY +setopt INC_APPEND_HISTORY +setopt HIST_EXPIRE_DUPS_FIRST +setopt HIST_IGNORE_DUPS +setopt HIST_IGNORE_ALL_DUPS +setopt HIST_IGNORE_SPACE +setopt HIST_SAVE_NO_DUPS +setopt HIST_REDUCE_BLANKS +setopt HIST_VERIFY +setopt HIST_BEEP +setopt SHARE_HISTORY + +HN=`hostname -s` + +PP=">"; if [[ $USER == "root" ]] then PP=">>" fi +PROMPT="%n@${HN}:%{$fg[white]%}%~%{$reset_color%} $PP " + +alias a='alias' +alias h='history -d -10000' +alias L='last -16' +alias ls='ls -F' +alias ll='ls -lsh' +alias lt='ls -ltrh' +alias lla='ls -lsah' +alias lta='ls -ltrah' +alias s='ssh' +alias sr='ssh -l root' +alias rs='rsync -va --delete --stats' +alias p='ps -ef | grep ${LOGNAME}' +alias P='ps -ef' +alias af='apt-cache search' +alias ai='apt-get install' +alias sd='lsblk -o NAME,FSTYPE,SIZE,MOUNTPOINT,LABEL' + +alias ga='git add -v .' +alias gb='git branch' +alias gs='git status' +alias gl="git log -32 --reverse --date=local --format='%h %cd %s'" +alias gc='git commit -m' +alias gu='git checkout' +alias gp='git push' +alias y='yazi' +alias f='fzf' + +export TERM=xterm-256color +export COLORTERM=truecolor + + +PATH=/db/bin:"$PATH" +if [ -f /db/go/bin/go ]; then + PATH="$PATH":/db/go/bin:$(/db/go/bin/go env GOPATH)/bin + export CGO_ENABLED=0 +fi + +tcsh_autolist() { if [[ -z ${LBUFFER// } ]] + then BUFFER="ls " CURSOR=3 zle list-choices + else zle expand-or-complete-prefix; fi } +zle -N tcsh_autolist +bindkey '^I' tcsh_autolist + +if [ -f /etc/zshcomp ]; then + source /etc/zshcom +fi + +[ -f /etc/zsh/zshcomp ] && source /etc/zsh/zshcomp + +if [ -f /db/etc/omp.json ]; then + if (( $+commands[oh-my-posh] )); then + eval "$(oh-my-posh init zsh --config /db/etc/omp.json )"; + fi +fi + +if (( $+commands[lsd] )); then + alias lx='lsd --icon never --tree -la' + alias ll='lsd --icon never -la' + alias lt='lsd --icon never -latr' + alias ls='lsd --icon never -a' +fi diff --git a/go.setup b/go.setup new file mode 100755 index 0000000..f333097 --- /dev/null +++ b/go.setup @@ -0,0 +1,25 @@ +#!/usr/bin/bash + +# Fetch latest version name (e.g., go1.26.2) +RELEASE=$(curl -sL https://go.dev/VERSION?m=text | head -n 1) + +# Detect OS and Architecture +OS=$(uname -s | tr '[:upper:]' '[:lower:]') +ARCH=$(uname -m) +[ "$ARCH" == "x86_64" ] && ARCH="amd64" +[ "$ARCH" == "aarch64" ] && ARCH="arm64" + +# Download and Extract + +FILE="${RELEASE}.${OS}-${ARCH}.tar.gz" +URL="https://go.dev/dl/$FILE" +echo "Downloading $FILE $URL..." + +wget $URL + +rm -rf /db/go && tar -C /db -xzf $FILE + +export PATH=/db/go/bin:~/go/bin:$PATH +export CGO_ENABLED=0 + +/db/go/bin/go install golang.org/x/tools/cmd/goimports@latest diff --git a/perlmodules/MD5-1.7/Changes b/perlmodules/MD5-1.7/Changes new file mode 100644 index 0000000..0acf87c --- /dev/null +++ b/perlmodules/MD5-1.7/Changes @@ -0,0 +1,83 @@ +Revision history for Perl extension MD5. + +*** 96/06/20 Version 1.7 + +MD5 is now completely 64-bit clean (I hope). The basic MD5 code uses +32-bit quantities and requires a typedef UINT4 to be defined in +global.h. Perl configuration data (the value of BYTEORDER) is used to +determine if unsigned longs have 4 or 8 bytes. On 64-bit platforms (eg +DEC Alpha) then it assumes that "unsigned int" will be a 32-bit type. +If this is incorrect then adding -DUINT4_IS_LONG to the DEFINES line in +Makefile.PL will override this. + +On some machines (at least Cray that I know of) there is no 32-bit +integer type. In this case defining TRUNCATE_UINT4 (which is done +automatically for a Cray) will ensure that 64-bit values are masked +down to 32 bits. I have done my best to test this but without easy +access to a true 64-bit machine I can not totally guarantee it (unless +anyone wants to lend me a spare Cray :-) + +There is one remaining limitation for 64-bit enabled processors. The +amount of data passed to any single call to the underlying MD5 +routines is limited to (2^32 - 1) bytes -- that's 4 gigabytes. I'm +sorry if that's a real problem for you ... + +And finally, a minor complilation warning (unsigned char * used with +function having char * prototype) has also been eliminated. + +*** 96/04/09 Version 1.6 + +Re-generated module framework using h2xs to pick up the latest module +conventions for versions etc. You can now say "use MD5 1.6;" and things +should work correctly. MD5.pod has been integrated into MD5.pm and +CHANGES renamed to Changes. There is a fairly comprehensive test.pl +which can be invoked via "make test". There are no functional changes +to the MD5 routines themselves. + +*** 96/03/14 Version 1.5.3 + +Fixed addfile method to accept type-glob references for the file-handle +(eg \*STDOUT). This is more consistent with other routines and is now the +recommended way of passing file-handles. The documentation now gives more +examples as to how the routines might be used. + +*** 96/03/12 Version 1.5.2 + +Minor fixes from Christopher J Madsen to provide +support for building on OS/2 (and to work arround a perl -w bug). + +Remove warning about possible difference between add('foo', 'bar') and +add('foobar'). This is not true (it may have been true in the earliest +version of the module but is no longer the case). + +*** 96/03/08 Version 1.5.1 + +Add CHANGES file to make it easier for people to figure out what has +been going on. (Meant to do this as part of 1.5) + +*** 96/03/05 Version 1.5 + +Add hash() and hexhash() methods at the suggestion/request of Gary +Howland before inclusion in a wider library +of cryptography modules. + +*** 96/02/27 Version 1.4 + +Finally fixed the pesky Solaris dynamic loading bug. All kudos to Ken +Pizzini ! + +*** 95/11/29 Version 1.3.1 + +Add explanations of current known problems. + +*** 95/06/02 Version 1.3 + +Fix problems with scope resolution in addfile() reported by +Jean-Claude Giese . Basically ARGV is +always implicitly in package main while other filehandles aren't. + +*** 95/05/23 Version 1.2.1 + +[Changes pre 1.2.1 not recorded] + +SCCS ID @(#)Changes 1.5 96/06/28 diff --git a/perlmodules/MD5-1.7/MANIFEST b/perlmodules/MD5-1.7/MANIFEST new file mode 100644 index 0000000..1b2cddd --- /dev/null +++ b/perlmodules/MD5-1.7/MANIFEST @@ -0,0 +1,13 @@ +README Guess what? +MANIFEST This file +MD5.pm MD5 Perl Module +MD5.xs MD5 Perl 'XS' source file +typemap Supplementary typemap +Makefile.PL Perl Makefile builder +md5c.c MD5 C source from RFC 1321 +md5.h Header for above +global.h ditto +test.pl Test suite using standard Perl conventions +Changes Version history +examples/mddriver.pl Example driver script after mddriver.c in RFC 1321 +examples/twdigest.pl Example code to format a digest like Tripwire diff --git a/perlmodules/MD5-1.7/MD5.pm b/perlmodules/MD5-1.7/MD5.pm new file mode 100644 index 0000000..3c71d5e --- /dev/null +++ b/perlmodules/MD5-1.7/MD5.pm @@ -0,0 +1,263 @@ +# SCCS ID @(#)MD5.pm 1.9 96/06/28 +package MD5; + +use strict; +use vars qw($VERSION @ISA @EXPORT); + +require Exporter; +require DynaLoader; +require AutoLoader; + +@ISA = qw(Exporter AutoLoader DynaLoader); +# Items to export into callers namespace by default. Note: do not export +# names by default without a very good reason. Use EXPORT_OK instead. +# Do not simply export all your public functions/methods/constants. +@EXPORT = qw( + +); +$VERSION = '1.7'; + +bootstrap MD5 $VERSION; + +# Preloaded methods go here. + +sub addfile +{ + no strict 'refs'; # Countermand any strct refs in force so that we + # can still handle file-handle names. + + my ($self, $handle) = @_; + my ($package, $file, $line) = caller; + my ($data) = ''; + + if (!ref($handle)) + { + # Old-style passing of filehandle by name. We need to add + # the calling package scope qualifier, if there is not one + # supplied already. + + $handle = $package . '::' . $handle unless ($handle =~ /(\:\:|\')/); + } + + while (read($handle, $data, 1024)) + { + $self->add($data); + } +} + +sub hexdigest +{ + my ($self) = shift; + + unpack("H*", ($self->digest())); +} + +sub hash +{ + my ($self, $data) = @_; + + if (ref($self)) + { + # This is an instance method call so reset the current context + + $self->reset(); + } + else + { + # This is a static method invocation, create a temporary MD5 context + + $self = new MD5; + } + + # Now do the hash + + $self->add($data); + $self->digest(); +} + +sub hexhash +{ + my ($self, $data) = @_; + + unpack("H*", ($self->hash($data))); +} + +# Autoload methods go after =cut, and are processed by the autosplit program. + +1; +__END__ + +=head1 NAME + +MD5 - Perl interface to the RSA Data Security Inc. MD5 Message-Digest Algorithm + +=head1 SYNOPSIS + + use MD5; + + $context = new MD5; + $context->reset(); + + $context->add(LIST); + $context->addfile(HANDLE); + + $digest = $context->digest(); + $string = $context->hexdigest(); + + $digest = MD5->hash(SCALAR); + $string = MD5->hexhash(SCALAR); + +=head1 DESCRIPTION + +The B module allows you to use the RSA Data Security Inc. MD5 +Message Digest algorithm from within Perl programs. + +A new MD5 context object is created with the B operation. +Multiple simultaneous digest contexts can be maintained, if desired. +The context is updated with the B operation which adds the +strings contained in the I parameter. Note, however, that +C, C followed by C and +C should all give the same result. + +The final message digest value is returned by the B operation +as a 16-byte binary string. This operation delivers the result of +B operations since the last B or B operation. Note +that the B operation is effectively a destructive, read-once +operation. Once it has been performed, the context must be B +before being used to calculate another digest value. + +Several convenience functions are also provided. The B +operation takes an open file-handle and reads it until end-of file in +1024 byte blocks adding the contents to the context. The file-handle +can either be specified by name or passed as a type-glob reference, as +shown in the examples below. The B operation calls +B and returns the result as a printable string of hexdecimal +digits. This is exactly the same operation as performed by the +B operation in the examples below. + +The B operation can act as either a static member function (ie +you invoke it on the MD5 class as in the synopsis above) or as a +normal virtual function. In both cases it performs the complete MD5 +cycle (reset, add, digest) on the supplied scalar value. This is +convenient for handling small quantities of data. When invoked on the +class a temporary context is created. When invoked through an already +created context object, this context is used. The latter form is +slightly more efficient. The B operation is analogous to +B. + +=head1 EXAMPLES + + use MD5; + + $md5 = new MD5; + $md5->add('foo', 'bar'); + $md5->add('baz'); + $digest = $md5->digest(); + + print("Digest is " . unpack("H*", $digest) . "\n"); + +The above example would print out the message + + Digest is 6df23dc03f9b54cc38a0fc1483df6e21 + +provided that the implementation is working correctly. + +Remembering the Perl motto ("There's more than one way to do it"), the +following should all give the same result: + + use MD5; + $md5 = new MD5; + + die "Can't open /etc/passwd ($!)\n" unless open(P, "/etc/passwd"); + + seek(P, 0, 0); + $md5->reset; + $md5->addfile(P); + $d = $md5->hexdigest; + print "addfile (handle name) = $d\n"; + + seek(P, 0, 0); + $md5->reset; + $md5->addfile(\*P); + $d = $md5->hexdigest; + print "addfile (type-glob reference) = $d\n"; + + seek(P, 0, 0); + $md5->reset; + while (

) + { + $md5->add($_); + } + $d = $md5->hexdigest; + print "Line at a time = $d\n"; + + seek(P, 0, 0); + $md5->reset; + $md5->add(

); + $d = $md5->hexdigest; + print "All lines at once = $d\n"; + + seek(P, 0, 0); + $md5->reset; + while (read(P, $data, (rand % 128) + 1)) + { + $md5->add($data); + } + $d = $md5->hexdigest; + print "Random chunks = $d\n"; + + seek(P, 0, 0); + $md5->reset; + undef $/; + $data =

; + $d = $md5->hexhash($data); + print "Single string = $d\n"; + + close(P); + +=head1 NOTE + +The MD5 extension may be redistributed under the same terms as Perl. +The MD5 algorithm is defined in RFC1321. The basic C code implementing +the algorithm is derived from that in the RFC and is covered by the +following copyright: + +=over 8 + +Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. + +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. + +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +These notices must be retained in any copies of any part of this +documentation and/or software. + +=back + +This copyright does not prohibit distribution of any version of Perl +containing this extension under the terms of the GNU or Artistic +licences. + +=head1 AUTHOR + +The MD5 interface was written by Neil Winton +(C). + +=head1 SEE ALSO + +perl(1). + +=cut diff --git a/perlmodules/MD5-1.7/MD5.xs b/perlmodules/MD5-1.7/MD5.xs new file mode 100644 index 0000000..c4a4ea2 --- /dev/null +++ b/perlmodules/MD5-1.7/MD5.xs @@ -0,0 +1,101 @@ +/* +** Perl Extension for the +** +** RSA Data Security Inc. MD5 Message-Digest Algorithm +** +** This module by Neil Winton (N.Winton@axion.bt.co.uk) +** SCCS ID @(#)MD5.xs 1.7 96/06/28 +** +** This extension may be distributed under the same terms +** as Perl. The MD5 code is covered by separate copyright and +** licence, but this does not prohibit distribution under the +** GNU or Artistic licences. See the file md5c.c or MD5.pm +** for more details. +*/ + +#ifdef __cplusplus +extern "C" { +#endif +#include "EXTERN.h" +#include "perl.h" +#include "XSUB.h" + +#include "global.h" +#include "md5.h" + +/* +** The following macro re-definitions added to work around a problem on +** Solaris where the original MD5 routines are already in /lib/libnsl.a. +** This causes dynamic linking of the module to fail. +** Thanks to Ken Pizzini (ken@spry.com) for finally nailing this one! +*/ + +#define MD5Init MD5Init_perl +#define MD5Update MD5Update_perl +#define MD5Final MD5Final_perl + +typedef MD5_CTX *MD5; + +#ifdef __cplusplus +} +#endif + + +MODULE = MD5 PACKAGE = MD5 + +PROTOTYPES: DISABLE + +MD5 +new(packname = "MD5") + char * packname + CODE: + { + RETVAL = (MD5_CTX *)safemalloc(sizeof(MD5_CTX)); + MD5Init(RETVAL); + } + OUTPUT: + RETVAL + +void +DESTROY(context) + MD5 context + CODE: + { + safefree((char *)context); + } + +void +reset(context) + MD5 context + CODE: + { + MD5Init(context); + } + +void +add(context, ...) + MD5 context + CODE: + { + SV *svdata; + STRLEN len; + unsigned char *data; + int i; + + for (i = 1; i < items; i++) + { + data = (unsigned char *)(SvPV(ST(i), len)); + MD5Update(context, data, len); + } + } + +SV * +digest(context) + MD5 context + CODE: + { + unsigned char digeststr[16]; + + MD5Final(digeststr, context); + ST(0) = sv_2mortal(newSVpv((char *)digeststr, 16)); + } diff --git a/perlmodules/MD5-1.7/Makefile.PL b/perlmodules/MD5-1.7/Makefile.PL new file mode 100644 index 0000000..da6b4bb --- /dev/null +++ b/perlmodules/MD5-1.7/Makefile.PL @@ -0,0 +1,13 @@ +# SCCS ID @(#)Makefile.PL 1.10 96/06/28 +use ExtUtils::MakeMaker; +# See lib/ExtUtils/MakeMaker.pm for details of how to influence +# the contents of the Makefile that is written. +WriteMakefile( + 'NAME' => 'MD5', + 'VERSION_FROM' => 'MD5.pm', # finds $VERSION + 'LIBS' => [''], # e.g., '-lm' + 'CONFIG' => ['byteorder'], # Used to determine 64-bitness + 'DEFINE' => '-DPERL_BYTEORDER=$(BYTEORDER)', + 'INC' => '', # e.g., '-I/usr/include/other' + 'OBJECT' => q[MD5$(OBJ_EXT) md5c$(OBJ_EXT)], +); diff --git a/perlmodules/MD5-1.7/Makefile.old b/perlmodules/MD5-1.7/Makefile.old new file mode 100644 index 0000000..94e939c --- /dev/null +++ b/perlmodules/MD5-1.7/Makefile.old @@ -0,0 +1,1027 @@ +# This Makefile is for the MD5 extension to perl. +# +# It was generated automatically by MakeMaker version +# 7.0401 (Revision: 70401) from the contents of +# Makefile.PL. Don't edit this file, edit Makefile.PL instead. +# +# ANY CHANGES MADE HERE WILL BE LOST! +# +# MakeMaker ARGV: () +# + +# MakeMaker Parameters: + +# BUILD_REQUIRES => { } +# CONFIG => [q[byteorder], q[ar], q[cc], q[cccdlflags], q[ccdlflags], q[dlext], q[dlsrc], q[exe_ext], q[full_ar], q[ld], q[lddlflags], q[ldflags], q[libc], q[lib_ext], q[obj_ext], q[osname], q[osvers], q[ranlib], q[sitelibexp], q[sitearchexp], q[so], q[vendorarchexp], q[vendorlibexp]] +# CONFIGURE_REQUIRES => { } +# DEFINE => q[-DPERL_BYTEORDER=$(BYTEORDER)] +# INC => q[] +# LIBS => [q[]] +# NAME => q[MD5] +# OBJECT => q[MD5$(OBJ_EXT) md5c$(OBJ_EXT)] +# PREREQ_PM => { } +# TEST_REQUIRES => { } +# VERSION_FROM => q[MD5.pm] + +# --- MakeMaker post_initialize section: + + +# --- MakeMaker const_config section: + +# These definitions are from config.sh (via /usr/lib/x86_64-linux-gnu/perl/5.22/Config.pm). +# They may have been overridden via Makefile.PL or on the command line. +BYTEORDER = 12345678 +AR = ar +CC = x86_64-linux-gnu-gcc +CCCDLFLAGS = -fPIC +CCDLFLAGS = -Wl,-E +DLEXT = so +DLSRC = dl_dlopen.xs +EXE_EXT = +FULL_AR = /usr/bin/ar +LD = x86_64-linux-gnu-gcc +LDDLFLAGS = -shared -L/usr/local/lib -fstack-protector-strong +LDFLAGS = -fstack-protector-strong -L/usr/local/lib +LIBC = libc-2.23.so +LIB_EXT = .a +OBJ_EXT = .o +OSNAME = linux +OSVERS = 3.16.0 +RANLIB = : +SITELIBEXP = /usr/local/share/perl/5.22.1 +SITEARCHEXP = /usr/local/lib/x86_64-linux-gnu/perl/5.22.1 +SO = so +VENDORARCHEXP = /usr/lib/x86_64-linux-gnu/perl5/5.22 +VENDORLIBEXP = /usr/share/perl5 + + +# --- MakeMaker constants section: +AR_STATIC_ARGS = cr +DIRFILESEP = / +DFSEP = $(DIRFILESEP) +NAME = MD5 +NAME_SYM = MD5 +VERSION = 1.7 +VERSION_MACRO = VERSION +VERSION_SYM = 1_7 +DEFINE_VERSION = -D$(VERSION_MACRO)=\"$(VERSION)\" +XS_VERSION = 1.7 +XS_VERSION_MACRO = XS_VERSION +XS_DEFINE_VERSION = -D$(XS_VERSION_MACRO)=\"$(XS_VERSION)\" +INST_ARCHLIB = blib/arch +INST_SCRIPT = blib/script +INST_BIN = blib/bin +INST_LIB = blib/lib +INST_MAN1DIR = blib/man1 +INST_MAN3DIR = blib/man3 +MAN1EXT = 1p +MAN3EXT = 3pm +INSTALLDIRS = site +DESTDIR = +PREFIX = $(SITEPREFIX) +PERLPREFIX = /usr +SITEPREFIX = /usr/local +VENDORPREFIX = /usr +INSTALLPRIVLIB = /usr/share/perl/5.22 +DESTINSTALLPRIVLIB = $(DESTDIR)$(INSTALLPRIVLIB) +INSTALLSITELIB = /usr/local/share/perl/5.22.1 +DESTINSTALLSITELIB = $(DESTDIR)$(INSTALLSITELIB) +INSTALLVENDORLIB = /usr/share/perl5 +DESTINSTALLVENDORLIB = $(DESTDIR)$(INSTALLVENDORLIB) +INSTALLARCHLIB = /usr/lib/x86_64-linux-gnu/perl/5.22 +DESTINSTALLARCHLIB = $(DESTDIR)$(INSTALLARCHLIB) +INSTALLSITEARCH = /usr/local/lib/x86_64-linux-gnu/perl/5.22.1 +DESTINSTALLSITEARCH = $(DESTDIR)$(INSTALLSITEARCH) +INSTALLVENDORARCH = /usr/lib/x86_64-linux-gnu/perl5/5.22 +DESTINSTALLVENDORARCH = $(DESTDIR)$(INSTALLVENDORARCH) +INSTALLBIN = /usr/bin +DESTINSTALLBIN = $(DESTDIR)$(INSTALLBIN) +INSTALLSITEBIN = /usr/local/bin +DESTINSTALLSITEBIN = $(DESTDIR)$(INSTALLSITEBIN) +INSTALLVENDORBIN = /usr/bin +DESTINSTALLVENDORBIN = $(DESTDIR)$(INSTALLVENDORBIN) +INSTALLSCRIPT = /usr/bin +DESTINSTALLSCRIPT = $(DESTDIR)$(INSTALLSCRIPT) +INSTALLSITESCRIPT = /usr/local/bin +DESTINSTALLSITESCRIPT = $(DESTDIR)$(INSTALLSITESCRIPT) +INSTALLVENDORSCRIPT = /usr/bin +DESTINSTALLVENDORSCRIPT = $(DESTDIR)$(INSTALLVENDORSCRIPT) +INSTALLMAN1DIR = /usr/share/man/man1 +DESTINSTALLMAN1DIR = $(DESTDIR)$(INSTALLMAN1DIR) +INSTALLSITEMAN1DIR = /usr/local/man/man1 +DESTINSTALLSITEMAN1DIR = $(DESTDIR)$(INSTALLSITEMAN1DIR) +INSTALLVENDORMAN1DIR = /usr/share/man/man1 +DESTINSTALLVENDORMAN1DIR = $(DESTDIR)$(INSTALLVENDORMAN1DIR) +INSTALLMAN3DIR = /usr/share/man/man3 +DESTINSTALLMAN3DIR = $(DESTDIR)$(INSTALLMAN3DIR) +INSTALLSITEMAN3DIR = /usr/local/man/man3 +DESTINSTALLSITEMAN3DIR = $(DESTDIR)$(INSTALLSITEMAN3DIR) +INSTALLVENDORMAN3DIR = /usr/share/man/man3 +DESTINSTALLVENDORMAN3DIR = $(DESTDIR)$(INSTALLVENDORMAN3DIR) +PERL_LIB = /usr/share/perl/5.22 +PERL_ARCHLIB = /usr/lib/x86_64-linux-gnu/perl/5.22 +PERL_ARCHLIBDEP = /usr/lib/x86_64-linux-gnu/perl/5.22 +LIBPERL_A = libperl.a +FIRST_MAKEFILE = Makefile +MAKEFILE_OLD = Makefile.old +MAKE_APERL_FILE = Makefile.aperl +PERLMAINCC = $(CC) +PERL_INC = /usr/lib/x86_64-linux-gnu/perl/5.22/CORE +PERL_INCDEP = /usr/lib/x86_64-linux-gnu/perl/5.22/CORE +PERL = "/usr/bin/perl" +FULLPERL = "/usr/bin/perl" +ABSPERL = $(PERL) +PERLRUN = $(PERL) +FULLPERLRUN = $(FULLPERL) +ABSPERLRUN = $(ABSPERL) +PERLRUNINST = $(PERLRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" +FULLPERLRUNINST = $(FULLPERLRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" +ABSPERLRUNINST = $(ABSPERLRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" +PERL_CORE = 0 +PERM_DIR = 755 +PERM_RW = 644 +PERM_RWX = 755 + +MAKEMAKER = /usr/share/perl/5.22/ExtUtils/MakeMaker.pm +MM_VERSION = 7.0401 +MM_REVISION = 70401 + +# FULLEXT = Pathname for extension directory (eg Foo/Bar/Oracle). +# BASEEXT = Basename part of FULLEXT. May be just equal FULLEXT. (eg Oracle) +# PARENT_NAME = NAME without BASEEXT and no trailing :: (eg Foo::Bar) +# DLBASE = Basename part of dynamic library. May be just equal BASEEXT. +MAKE = make +FULLEXT = MD5 +BASEEXT = MD5 +PARENT_NAME = +DLBASE = $(BASEEXT) +VERSION_FROM = MD5.pm +INC = +DEFINE = -DPERL_BYTEORDER=$(BYTEORDER) +OBJECT = MD5$(OBJ_EXT) md5c$(OBJ_EXT) +LDFROM = $(OBJECT) +LINKTYPE = dynamic +BOOTDEP = + +# Handy lists of source code files: +XS_FILES = MD5.xs +C_FILES = MD5.c \ + md5c.c +O_FILES = MD5.o \ + md5c.o +H_FILES = global.h \ + md5.h +MAN1PODS = +MAN3PODS = MD5.pm + +# Where is the Config information that we are using/depend on +CONFIGDEP = $(PERL_ARCHLIBDEP)$(DFSEP)Config.pm $(PERL_INCDEP)$(DFSEP)config.h + +# Where to build things +INST_LIBDIR = $(INST_LIB) +INST_ARCHLIBDIR = $(INST_ARCHLIB) + +INST_AUTODIR = $(INST_LIB)/auto/$(FULLEXT) +INST_ARCHAUTODIR = $(INST_ARCHLIB)/auto/$(FULLEXT) + +INST_STATIC = $(INST_ARCHAUTODIR)/$(BASEEXT)$(LIB_EXT) +INST_DYNAMIC = $(INST_ARCHAUTODIR)/$(DLBASE).$(DLEXT) +INST_BOOT = $(INST_ARCHAUTODIR)/$(BASEEXT).bs + +# Extra linker info +EXPORT_LIST = +PERL_ARCHIVE = +PERL_ARCHIVEDEP = +PERL_ARCHIVE_AFTER = + + +TO_INST_PM = MD5.pm + +PM_TO_BLIB = MD5.pm \ + $(INST_LIB)/MD5.pm + + +# --- MakeMaker platform_constants section: +MM_Unix_VERSION = 7.0401 +PERL_MALLOC_DEF = -DPERL_EXTMALLOC_DEF -Dmalloc=Perl_malloc -Dfree=Perl_mfree -Drealloc=Perl_realloc -Dcalloc=Perl_calloc + + +# --- MakeMaker tool_autosplit section: +# Usage: $(AUTOSPLITFILE) FileToSplit AutoDirToSplitInto +AUTOSPLITFILE = $(ABSPERLRUN) -e 'use AutoSplit; autosplit($$$$ARGV[0], $$$$ARGV[1], 0, 1, 1)' -- + + + +# --- MakeMaker tool_xsubpp section: + +XSUBPPDIR = /usr/share/perl/5.22/ExtUtils +XSUBPP = "$(XSUBPPDIR)$(DFSEP)xsubpp" +XSUBPPRUN = $(PERLRUN) $(XSUBPP) +XSPROTOARG = +XSUBPPDEPS = /usr/share/perl/5.22/ExtUtils/typemap typemap /usr/share/perl/5.22/ExtUtils$(DFSEP)xsubpp +XSUBPPARGS = -typemap "/usr/share/perl/5.22/ExtUtils/typemap" -typemap "typemap" +XSUBPP_EXTRA_ARGS = + + +# --- MakeMaker tools_other section: +SHELL = /bin/sh +CHMOD = chmod +CP = cp +MV = mv +NOOP = $(TRUE) +NOECHO = @ +RM_F = rm -f +RM_RF = rm -rf +TEST_F = test -f +TOUCH = touch +UMASK_NULL = umask 0 +DEV_NULL = > /dev/null 2>&1 +MKPATH = $(ABSPERLRUN) -MExtUtils::Command -e 'mkpath' -- +EQUALIZE_TIMESTAMP = $(ABSPERLRUN) -MExtUtils::Command -e 'eqtime' -- +FALSE = false +TRUE = true +ECHO = echo +ECHO_N = echo -n +UNINST = 0 +VERBINST = 0 +MOD_INSTALL = $(ABSPERLRUN) -MExtUtils::Install -e 'install([ from_to => {@ARGV}, verbose => '\''$(VERBINST)'\'', uninstall_shadows => '\''$(UNINST)'\'', dir_mode => '\''$(PERM_DIR)'\'' ]);' -- +DOC_INSTALL = $(ABSPERLRUN) -MExtUtils::Command::MM -e 'perllocal_install' -- +UNINSTALL = $(ABSPERLRUN) -MExtUtils::Command::MM -e 'uninstall' -- +WARN_IF_OLD_PACKLIST = $(ABSPERLRUN) -MExtUtils::Command::MM -e 'warn_if_old_packlist' -- +MACROSTART = +MACROEND = +USEMAKEFILE = -f +FIXIN = $(ABSPERLRUN) -MExtUtils::MY -e 'MY->fixin(shift)' -- +CP_NONEMPTY = $(ABSPERLRUN) -MExtUtils::Command::MM -e 'cp_nonempty' -- + + +# --- MakeMaker makemakerdflt section: +makemakerdflt : all + $(NOECHO) $(NOOP) + + +# --- MakeMaker dist section: +TAR = tar +TARFLAGS = cvf +ZIP = zip +ZIPFLAGS = -r +COMPRESS = gzip --best +SUFFIX = .gz +SHAR = shar +PREOP = $(NOECHO) $(NOOP) +POSTOP = $(NOECHO) $(NOOP) +TO_UNIX = $(NOECHO) $(NOOP) +CI = ci -u +RCS_LABEL = rcs -Nv$(VERSION_SYM): -q +DIST_CP = best +DIST_DEFAULT = tardist +DISTNAME = MD5 +DISTVNAME = MD5-1.7 + + +# --- MakeMaker macro section: + + +# --- MakeMaker depend section: + + +# --- MakeMaker cflags section: + +CCFLAGS = -D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fwrapv -fno-strict-aliasing -pipe -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 +OPTIMIZE = -O2 -g +PERLTYPE = +MPOLLUTE = + + +# --- MakeMaker const_loadlibs section: + +# MD5 might depend on some other libraries: +# See ExtUtils::Liblist for details +# + + +# --- MakeMaker const_cccmd section: +CCCMD = $(CC) -c $(PASTHRU_INC) $(INC) \ + $(CCFLAGS) $(OPTIMIZE) \ + $(PERLTYPE) $(MPOLLUTE) $(DEFINE_VERSION) \ + $(XS_DEFINE_VERSION) + +# --- MakeMaker post_constants section: + + +# --- MakeMaker pasthru section: + +PASTHRU = LIBPERL_A="$(LIBPERL_A)"\ + LINKTYPE="$(LINKTYPE)"\ + OPTIMIZE="$(OPTIMIZE)"\ + LD="$(LD)"\ + PREFIX="$(PREFIX)"\ + PASTHRU_DEFINE="$(PASTHRU_DEFINE)"\ + PASTHRU_INC="$(PASTHRU_INC)" + + +# --- MakeMaker special_targets section: +.SUFFIXES : .xs .c .C .cpp .i .s .cxx .cc $(OBJ_EXT) + +.PHONY: all config static dynamic test linkext manifest blibdirs clean realclean disttest distdir + + + +# --- MakeMaker c_o section: + +.c.i: + x86_64-linux-gnu-gcc -E -c $(PASTHRU_INC) $(INC) \ + $(CCFLAGS) $(OPTIMIZE) \ + $(PERLTYPE) $(MPOLLUTE) $(DEFINE_VERSION) \ + $(XS_DEFINE_VERSION) $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) $*.c > $*.i + +.c.s: + $(CCCMD) -S $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) $*.c + +.c$(OBJ_EXT): + $(CCCMD) $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) $*.c + +.cpp$(OBJ_EXT): + $(CCCMD) $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) $*.cpp + +.cxx$(OBJ_EXT): + $(CCCMD) $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) $*.cxx + +.cc$(OBJ_EXT): + $(CCCMD) $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) $*.cc + +.C$(OBJ_EXT): + $(CCCMD) $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) $*.C + + +# --- MakeMaker xs_c section: + +.xs.c: + $(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $(XSUBPP_EXTRA_ARGS) $*.xs > $*.xsc && $(MV) $*.xsc $*.c + + +# --- MakeMaker xs_o section: + +.xs$(OBJ_EXT): + $(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $*.xs > $*.xsc && $(MV) $*.xsc $*.c + $(CCCMD) $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) $*.c + + +# --- MakeMaker top_targets section: +all :: pure_all manifypods + $(NOECHO) $(NOOP) + + +pure_all :: config pm_to_blib subdirs linkext + $(NOECHO) $(NOOP) + +subdirs :: $(MYEXTLIB) + $(NOECHO) $(NOOP) + +config :: $(FIRST_MAKEFILE) blibdirs + $(NOECHO) $(NOOP) + +$(O_FILES): $(H_FILES) + +help : + perldoc ExtUtils::MakeMaker + + +# --- MakeMaker blibdirs section: +blibdirs : $(INST_LIBDIR)$(DFSEP).exists $(INST_ARCHLIB)$(DFSEP).exists $(INST_AUTODIR)$(DFSEP).exists $(INST_ARCHAUTODIR)$(DFSEP).exists $(INST_BIN)$(DFSEP).exists $(INST_SCRIPT)$(DFSEP).exists $(INST_MAN1DIR)$(DFSEP).exists $(INST_MAN3DIR)$(DFSEP).exists + $(NOECHO) $(NOOP) + +# Backwards compat with 6.18 through 6.25 +blibdirs.ts : blibdirs + $(NOECHO) $(NOOP) + +$(INST_LIBDIR)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_LIBDIR) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_LIBDIR) + $(NOECHO) $(TOUCH) $(INST_LIBDIR)$(DFSEP).exists + +$(INST_ARCHLIB)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_ARCHLIB) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_ARCHLIB) + $(NOECHO) $(TOUCH) $(INST_ARCHLIB)$(DFSEP).exists + +$(INST_AUTODIR)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_AUTODIR) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_AUTODIR) + $(NOECHO) $(TOUCH) $(INST_AUTODIR)$(DFSEP).exists + +$(INST_ARCHAUTODIR)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_ARCHAUTODIR) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_ARCHAUTODIR) + $(NOECHO) $(TOUCH) $(INST_ARCHAUTODIR)$(DFSEP).exists + +$(INST_BIN)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_BIN) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_BIN) + $(NOECHO) $(TOUCH) $(INST_BIN)$(DFSEP).exists + +$(INST_SCRIPT)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_SCRIPT) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_SCRIPT) + $(NOECHO) $(TOUCH) $(INST_SCRIPT)$(DFSEP).exists + +$(INST_MAN1DIR)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_MAN1DIR) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_MAN1DIR) + $(NOECHO) $(TOUCH) $(INST_MAN1DIR)$(DFSEP).exists + +$(INST_MAN3DIR)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_MAN3DIR) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_MAN3DIR) + $(NOECHO) $(TOUCH) $(INST_MAN3DIR)$(DFSEP).exists + + + +# --- MakeMaker linkext section: + +linkext :: $(LINKTYPE) + $(NOECHO) $(NOOP) + + +# --- MakeMaker dlsyms section: + + +# --- MakeMaker dynamic_bs section: +BOOTSTRAP = $(BASEEXT).bs + +# As Mkbootstrap might not write a file (if none is required) +# we use touch to prevent make continually trying to remake it. +# The DynaLoader only reads a non-empty file. +$(BOOTSTRAP) : $(FIRST_MAKEFILE) $(BOOTDEP) $(INST_ARCHAUTODIR)$(DFSEP).exists + $(NOECHO) $(ECHO) "Running Mkbootstrap for $(NAME) ($(BSLOADLIBS))" + $(NOECHO) $(PERLRUN) \ + "-MExtUtils::Mkbootstrap" \ + -e "Mkbootstrap('$(BASEEXT)','$(BSLOADLIBS)');" + $(NOECHO) $(TOUCH) "$@" + $(CHMOD) $(PERM_RW) "$@" + + +# --- MakeMaker dynamic section: + +dynamic :: $(FIRST_MAKEFILE) $(BOOTSTRAP) $(INST_DYNAMIC) + $(NOECHO) $(NOOP) + + +# --- MakeMaker dynamic_lib section: + +# This section creates the dynamically loadable $(INST_DYNAMIC) +# from $(OBJECT) and possibly $(MYEXTLIB). +ARMAYBE = : +OTHERLDFLAGS = +INST_DYNAMIC_DEP = +INST_DYNAMIC_FIX = + +$(INST_DYNAMIC): $(OBJECT) $(MYEXTLIB) $(INST_ARCHAUTODIR)$(DFSEP).exists $(EXPORT_LIST) $(PERL_ARCHIVEDEP) $(PERL_ARCHIVE_AFTER) $(INST_DYNAMIC_DEP) + $(RM_F) $@ + $(LD) $(LDDLFLAGS) $(LDFROM) $(OTHERLDFLAGS) -o $@ $(MYEXTLIB) \ + $(PERL_ARCHIVE) $(LDLOADLIBS) $(PERL_ARCHIVE_AFTER) $(EXPORT_LIST) \ + $(INST_DYNAMIC_FIX) + $(CHMOD) $(PERM_RWX) $@ + $(NOECHO) $(RM_RF) $(BOOTSTRAP) + - $(CP_NONEMPTY) $(BOOTSTRAP) $(INST_BOOT) $(PERM_RW) + + +# --- MakeMaker static section: + +## $(INST_PM) has been moved to the all: target. +## It remains here for awhile to allow for old usage: "make static" +static :: $(FIRST_MAKEFILE) $(INST_STATIC) + $(NOECHO) $(NOOP) + + +# --- MakeMaker static_lib section: + +$(INST_STATIC) : $(OBJECT) $(MYEXTLIB) $(INST_ARCHAUTODIR)$(DFSEP).exists + $(RM_RF) $@ + $(AR) $(AR_STATIC_ARGS) $@ $(OBJECT) && $(RANLIB) $@ + $(CHMOD) $(PERM_RWX) $@ + $(NOECHO) $(ECHO) "$(EXTRALIBS)" > "$(INST_ARCHAUTODIR)/extralibs.ld" + + +# --- MakeMaker manifypods section: + +POD2MAN_EXE = $(PERLRUN) "-MExtUtils::Command::MM" -e pod2man "--" +POD2MAN = $(POD2MAN_EXE) + + +manifypods : pure_all \ + MD5.pm + $(NOECHO) $(POD2MAN) --section=$(MAN3EXT) --perm_rw=$(PERM_RW) -u \ + MD5.pm $(INST_MAN3DIR)/MD5.$(MAN3EXT) + + + + +# --- MakeMaker processPL section: + + +# --- MakeMaker installbin section: + + +# --- MakeMaker subdirs section: + +# none + +# --- MakeMaker clean_subdirs section: +clean_subdirs : + $(NOECHO) $(NOOP) + + +# --- MakeMaker clean section: + +# Delete temporary files but do not touch installed files. We don't delete +# the Makefile here so a later make realclean still has a makefile to use. + +clean :: clean_subdirs + - $(RM_F) \ + $(BASEEXT).bso $(BASEEXT).def \ + $(BASEEXT).exp $(BASEEXT).x \ + $(BOOTSTRAP) $(INST_ARCHAUTODIR)/extralibs.all \ + $(INST_ARCHAUTODIR)/extralibs.ld $(MAKE_APERL_FILE) \ + *$(LIB_EXT) *$(OBJ_EXT) \ + *perl.core MD5.c \ + MYMETA.json MYMETA.yml \ + blibdirs.ts core \ + core.*perl.*.? core.[0-9] \ + core.[0-9][0-9] core.[0-9][0-9][0-9] \ + core.[0-9][0-9][0-9][0-9] core.[0-9][0-9][0-9][0-9][0-9] \ + lib$(BASEEXT).def mon.out \ + perl perl$(EXE_EXT) \ + perl.exe perlmain.c \ + pm_to_blib pm_to_blib.ts \ + so_locations tmon.out + - $(RM_RF) \ + blib + $(NOECHO) $(RM_F) $(MAKEFILE_OLD) + - $(MV) $(FIRST_MAKEFILE) $(MAKEFILE_OLD) $(DEV_NULL) + + +# --- MakeMaker realclean_subdirs section: +realclean_subdirs : + $(NOECHO) $(NOOP) + + +# --- MakeMaker realclean section: +# Delete temporary files (via clean) and also delete dist files +realclean purge :: clean realclean_subdirs + - $(RM_F) \ + $(OBJECT) $(MAKEFILE_OLD) \ + $(FIRST_MAKEFILE) + - $(RM_RF) \ + $(DISTVNAME) + + +# --- MakeMaker metafile section: +metafile : create_distdir + $(NOECHO) $(ECHO) Generating META.yml + $(NOECHO) $(ECHO) '---' > META_new.yml + $(NOECHO) $(ECHO) 'abstract: unknown' >> META_new.yml + $(NOECHO) $(ECHO) 'author:' >> META_new.yml + $(NOECHO) $(ECHO) ' - unknown' >> META_new.yml + $(NOECHO) $(ECHO) 'build_requires:' >> META_new.yml + $(NOECHO) $(ECHO) ' ExtUtils::MakeMaker: '\''0'\''' >> META_new.yml + $(NOECHO) $(ECHO) 'configure_requires:' >> META_new.yml + $(NOECHO) $(ECHO) ' ExtUtils::MakeMaker: '\''0'\''' >> META_new.yml + $(NOECHO) $(ECHO) 'dynamic_config: 1' >> META_new.yml + $(NOECHO) $(ECHO) 'generated_by: '\''ExtUtils::MakeMaker version 7.0401, CPAN::Meta::Converter version 2.150001'\''' >> META_new.yml + $(NOECHO) $(ECHO) 'license: unknown' >> META_new.yml + $(NOECHO) $(ECHO) 'meta-spec:' >> META_new.yml + $(NOECHO) $(ECHO) ' url: http://module-build.sourceforge.net/META-spec-v1.4.html' >> META_new.yml + $(NOECHO) $(ECHO) ' version: '\''1.4'\''' >> META_new.yml + $(NOECHO) $(ECHO) 'name: MD5' >> META_new.yml + $(NOECHO) $(ECHO) 'no_index:' >> META_new.yml + $(NOECHO) $(ECHO) ' directory:' >> META_new.yml + $(NOECHO) $(ECHO) ' - t' >> META_new.yml + $(NOECHO) $(ECHO) ' - inc' >> META_new.yml + $(NOECHO) $(ECHO) 'requires: {}' >> META_new.yml + $(NOECHO) $(ECHO) 'version: '\''1.7'\''' >> META_new.yml + -$(NOECHO) $(MV) META_new.yml $(DISTVNAME)/META.yml + $(NOECHO) $(ECHO) Generating META.json + $(NOECHO) $(ECHO) '{' > META_new.json + $(NOECHO) $(ECHO) ' "abstract" : "unknown",' >> META_new.json + $(NOECHO) $(ECHO) ' "author" : [' >> META_new.json + $(NOECHO) $(ECHO) ' "unknown"' >> META_new.json + $(NOECHO) $(ECHO) ' ],' >> META_new.json + $(NOECHO) $(ECHO) ' "dynamic_config" : 1,' >> META_new.json + $(NOECHO) $(ECHO) ' "generated_by" : "ExtUtils::MakeMaker version 7.0401, CPAN::Meta::Converter version 2.150001",' >> META_new.json + $(NOECHO) $(ECHO) ' "license" : [' >> META_new.json + $(NOECHO) $(ECHO) ' "unknown"' >> META_new.json + $(NOECHO) $(ECHO) ' ],' >> META_new.json + $(NOECHO) $(ECHO) ' "meta-spec" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",' >> META_new.json + $(NOECHO) $(ECHO) ' "version" : "2"' >> META_new.json + $(NOECHO) $(ECHO) ' },' >> META_new.json + $(NOECHO) $(ECHO) ' "name" : "MD5",' >> META_new.json + $(NOECHO) $(ECHO) ' "no_index" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "directory" : [' >> META_new.json + $(NOECHO) $(ECHO) ' "t",' >> META_new.json + $(NOECHO) $(ECHO) ' "inc"' >> META_new.json + $(NOECHO) $(ECHO) ' ]' >> META_new.json + $(NOECHO) $(ECHO) ' },' >> META_new.json + $(NOECHO) $(ECHO) ' "prereqs" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "build" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "requires" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "ExtUtils::MakeMaker" : "0"' >> META_new.json + $(NOECHO) $(ECHO) ' }' >> META_new.json + $(NOECHO) $(ECHO) ' },' >> META_new.json + $(NOECHO) $(ECHO) ' "configure" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "requires" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "ExtUtils::MakeMaker" : "0"' >> META_new.json + $(NOECHO) $(ECHO) ' }' >> META_new.json + $(NOECHO) $(ECHO) ' },' >> META_new.json + $(NOECHO) $(ECHO) ' "runtime" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "requires" : {}' >> META_new.json + $(NOECHO) $(ECHO) ' }' >> META_new.json + $(NOECHO) $(ECHO) ' },' >> META_new.json + $(NOECHO) $(ECHO) ' "release_status" : "stable",' >> META_new.json + $(NOECHO) $(ECHO) ' "version" : "1.7"' >> META_new.json + $(NOECHO) $(ECHO) '}' >> META_new.json + -$(NOECHO) $(MV) META_new.json $(DISTVNAME)/META.json + + +# --- MakeMaker signature section: +signature : + cpansign -s + + +# --- MakeMaker dist_basics section: +distclean :: realclean distcheck + $(NOECHO) $(NOOP) + +distcheck : + $(PERLRUN) "-MExtUtils::Manifest=fullcheck" -e fullcheck + +skipcheck : + $(PERLRUN) "-MExtUtils::Manifest=skipcheck" -e skipcheck + +manifest : + $(PERLRUN) "-MExtUtils::Manifest=mkmanifest" -e mkmanifest + +veryclean : realclean + $(RM_F) *~ */*~ *.orig */*.orig *.bak */*.bak *.old */*.old + + + +# --- MakeMaker dist_core section: + +dist : $(DIST_DEFAULT) $(FIRST_MAKEFILE) + $(NOECHO) $(ABSPERLRUN) -l -e 'print '\''Warning: Makefile possibly out of date with $(VERSION_FROM)'\''' \ + -e ' if -e '\''$(VERSION_FROM)'\'' and -M '\''$(VERSION_FROM)'\'' < -M '\''$(FIRST_MAKEFILE)'\'';' -- + +tardist : $(DISTVNAME).tar$(SUFFIX) + $(NOECHO) $(NOOP) + +uutardist : $(DISTVNAME).tar$(SUFFIX) + uuencode $(DISTVNAME).tar$(SUFFIX) $(DISTVNAME).tar$(SUFFIX) > $(DISTVNAME).tar$(SUFFIX)_uu + $(NOECHO) $(ECHO) 'Created $(DISTVNAME).tar$(SUFFIX)_uu' + +$(DISTVNAME).tar$(SUFFIX) : distdir + $(PREOP) + $(TO_UNIX) + $(TAR) $(TARFLAGS) $(DISTVNAME).tar $(DISTVNAME) + $(RM_RF) $(DISTVNAME) + $(COMPRESS) $(DISTVNAME).tar + $(NOECHO) $(ECHO) 'Created $(DISTVNAME).tar$(SUFFIX)' + $(POSTOP) + +zipdist : $(DISTVNAME).zip + $(NOECHO) $(NOOP) + +$(DISTVNAME).zip : distdir + $(PREOP) + $(ZIP) $(ZIPFLAGS) $(DISTVNAME).zip $(DISTVNAME) + $(RM_RF) $(DISTVNAME) + $(NOECHO) $(ECHO) 'Created $(DISTVNAME).zip' + $(POSTOP) + +shdist : distdir + $(PREOP) + $(SHAR) $(DISTVNAME) > $(DISTVNAME).shar + $(RM_RF) $(DISTVNAME) + $(NOECHO) $(ECHO) 'Created $(DISTVNAME).shar' + $(POSTOP) + + +# --- MakeMaker distdir section: +create_distdir : + $(RM_RF) $(DISTVNAME) + $(PERLRUN) "-MExtUtils::Manifest=manicopy,maniread" \ + -e "manicopy(maniread(),'$(DISTVNAME)', '$(DIST_CP)');" + +distdir : create_distdir distmeta + $(NOECHO) $(NOOP) + + + +# --- MakeMaker dist_test section: +disttest : distdir + cd $(DISTVNAME) && $(ABSPERLRUN) Makefile.PL + cd $(DISTVNAME) && $(MAKE) $(PASTHRU) + cd $(DISTVNAME) && $(MAKE) test $(PASTHRU) + + + +# --- MakeMaker dist_ci section: + +ci : + $(PERLRUN) "-MExtUtils::Manifest=maniread" \ + -e "@all = keys %{ maniread() };" \ + -e "print(qq{Executing $(CI) @all\n}); system(qq{$(CI) @all});" \ + -e "print(qq{Executing $(RCS_LABEL) ...\n}); system(qq{$(RCS_LABEL) @all});" + + +# --- MakeMaker distmeta section: +distmeta : create_distdir metafile + $(NOECHO) cd $(DISTVNAME) && $(ABSPERLRUN) -MExtUtils::Manifest=maniadd -e 'exit unless -e q{META.yml};' \ + -e 'eval { maniadd({q{META.yml} => q{Module YAML meta-data (added by MakeMaker)}}) }' \ + -e ' or print "Could not add META.yml to MANIFEST: $$$${'\''@'\''}\n"' -- + $(NOECHO) cd $(DISTVNAME) && $(ABSPERLRUN) -MExtUtils::Manifest=maniadd -e 'exit unless -f q{META.json};' \ + -e 'eval { maniadd({q{META.json} => q{Module JSON meta-data (added by MakeMaker)}}) }' \ + -e ' or print "Could not add META.json to MANIFEST: $$$${'\''@'\''}\n"' -- + + + +# --- MakeMaker distsignature section: +distsignature : create_distdir + $(NOECHO) cd $(DISTVNAME) && $(ABSPERLRUN) -MExtUtils::Manifest=maniadd -e 'eval { maniadd({q{SIGNATURE} => q{Public-key signature (added by MakeMaker)}}) }' \ + -e ' or print "Could not add SIGNATURE to MANIFEST: $$$${'\''@'\''}\n"' -- + $(NOECHO) cd $(DISTVNAME) && $(TOUCH) SIGNATURE + cd $(DISTVNAME) && cpansign -s + + + +# --- MakeMaker install section: + +install :: pure_install doc_install + $(NOECHO) $(NOOP) + +install_perl :: pure_perl_install doc_perl_install + $(NOECHO) $(NOOP) + +install_site :: pure_site_install doc_site_install + $(NOECHO) $(NOOP) + +install_vendor :: pure_vendor_install doc_vendor_install + $(NOECHO) $(NOOP) + +pure_install :: pure_$(INSTALLDIRS)_install + $(NOECHO) $(NOOP) + +doc_install :: doc_$(INSTALLDIRS)_install + $(NOECHO) $(NOOP) + +pure__install : pure_site_install + $(NOECHO) $(ECHO) INSTALLDIRS not defined, defaulting to INSTALLDIRS=site + +doc__install : doc_site_install + $(NOECHO) $(ECHO) INSTALLDIRS not defined, defaulting to INSTALLDIRS=site + +pure_perl_install :: all + $(NOECHO) umask 022; $(MOD_INSTALL) \ + "$(INST_LIB)" "$(DESTINSTALLPRIVLIB)" \ + "$(INST_ARCHLIB)" "$(DESTINSTALLARCHLIB)" \ + "$(INST_BIN)" "$(DESTINSTALLBIN)" \ + "$(INST_SCRIPT)" "$(DESTINSTALLSCRIPT)" \ + "$(INST_MAN1DIR)" "$(DESTINSTALLMAN1DIR)" \ + "$(INST_MAN3DIR)" "$(DESTINSTALLMAN3DIR)" + $(NOECHO) $(WARN_IF_OLD_PACKLIST) \ + "$(SITEARCHEXP)/auto/$(FULLEXT)" + + +pure_site_install :: all + $(NOECHO) umask 02; $(MOD_INSTALL) \ + read "$(SITEARCHEXP)/auto/$(FULLEXT)/.packlist" \ + write "$(DESTINSTALLSITEARCH)/auto/$(FULLEXT)/.packlist" \ + "$(INST_LIB)" "$(DESTINSTALLSITELIB)" \ + "$(INST_ARCHLIB)" "$(DESTINSTALLSITEARCH)" \ + "$(INST_BIN)" "$(DESTINSTALLSITEBIN)" \ + "$(INST_SCRIPT)" "$(DESTINSTALLSITESCRIPT)" \ + "$(INST_MAN1DIR)" "$(DESTINSTALLSITEMAN1DIR)" \ + "$(INST_MAN3DIR)" "$(DESTINSTALLSITEMAN3DIR)" + $(NOECHO) $(WARN_IF_OLD_PACKLIST) \ + "$(PERL_ARCHLIB)/auto/$(FULLEXT)" + +pure_vendor_install :: all + $(NOECHO) umask 022; $(MOD_INSTALL) \ + "$(INST_LIB)" "$(DESTINSTALLVENDORLIB)" \ + "$(INST_ARCHLIB)" "$(DESTINSTALLVENDORARCH)" \ + "$(INST_BIN)" "$(DESTINSTALLVENDORBIN)" \ + "$(INST_SCRIPT)" "$(DESTINSTALLVENDORSCRIPT)" \ + "$(INST_MAN1DIR)" "$(DESTINSTALLVENDORMAN1DIR)" \ + "$(INST_MAN3DIR)" "$(DESTINSTALLVENDORMAN3DIR)" + + +doc_perl_install :: all + +doc_site_install :: all + $(NOECHO) $(ECHO) Appending installation info to "$(DESTINSTALLSITEARCH)/perllocal.pod" + -$(NOECHO) umask 02; $(MKPATH) "$(DESTINSTALLSITEARCH)" + -$(NOECHO) umask 02; $(DOC_INSTALL) \ + "Module" "$(NAME)" \ + "installed into" $(INSTALLSITELIB) \ + LINKTYPE "$(LINKTYPE)" \ + VERSION "$(VERSION)" \ + EXE_FILES "$(EXE_FILES)" \ + >> "$(DESTINSTALLSITEARCH)/perllocal.pod" + +doc_vendor_install :: all + + +uninstall :: uninstall_from_$(INSTALLDIRS)dirs + $(NOECHO) $(NOOP) + +uninstall_from_perldirs :: + +uninstall_from_sitedirs :: + $(NOECHO) $(UNINSTALL) "$(SITEARCHEXP)/auto/$(FULLEXT)/.packlist" + +uninstall_from_vendordirs :: + + +# --- MakeMaker force section: +# Phony target to force checking subdirectories. +FORCE : + $(NOECHO) $(NOOP) + + +# --- MakeMaker perldepend section: +PERL_HDRS = \ + $(PERL_INCDEP)/EXTERN.h \ + $(PERL_INCDEP)/INTERN.h \ + $(PERL_INCDEP)/XSUB.h \ + $(PERL_INCDEP)/av.h \ + $(PERL_INCDEP)/bitcount.h \ + $(PERL_INCDEP)/charclass_invlists.h \ + $(PERL_INCDEP)/config.h \ + $(PERL_INCDEP)/cop.h \ + $(PERL_INCDEP)/cv.h \ + $(PERL_INCDEP)/dosish.h \ + $(PERL_INCDEP)/ebcdic_tables.h \ + $(PERL_INCDEP)/embed.h \ + $(PERL_INCDEP)/embedvar.h \ + $(PERL_INCDEP)/fakesdio.h \ + $(PERL_INCDEP)/feature.h \ + $(PERL_INCDEP)/form.h \ + $(PERL_INCDEP)/git_version.h \ + $(PERL_INCDEP)/gv.h \ + $(PERL_INCDEP)/handy.h \ + $(PERL_INCDEP)/hv.h \ + $(PERL_INCDEP)/hv_func.h \ + $(PERL_INCDEP)/inline.h \ + $(PERL_INCDEP)/intrpvar.h \ + $(PERL_INCDEP)/iperlsys.h \ + $(PERL_INCDEP)/keywords.h \ + $(PERL_INCDEP)/l1_char_class_tab.h \ + $(PERL_INCDEP)/malloc_ctl.h \ + $(PERL_INCDEP)/metaconfig.h \ + $(PERL_INCDEP)/mg.h \ + $(PERL_INCDEP)/mg_data.h \ + $(PERL_INCDEP)/mg_raw.h \ + $(PERL_INCDEP)/mg_vtable.h \ + $(PERL_INCDEP)/mydtrace.h \ + $(PERL_INCDEP)/nostdio.h \ + $(PERL_INCDEP)/op.h \ + $(PERL_INCDEP)/op_reg_common.h \ + $(PERL_INCDEP)/opcode.h \ + $(PERL_INCDEP)/opnames.h \ + $(PERL_INCDEP)/overload.h \ + $(PERL_INCDEP)/pad.h \ + $(PERL_INCDEP)/parser.h \ + $(PERL_INCDEP)/patchlevel-debian.h \ + $(PERL_INCDEP)/patchlevel.h \ + $(PERL_INCDEP)/perl.h \ + $(PERL_INCDEP)/perlapi.h \ + $(PERL_INCDEP)/perlio.h \ + $(PERL_INCDEP)/perliol.h \ + $(PERL_INCDEP)/perlsdio.h \ + $(PERL_INCDEP)/perlvars.h \ + $(PERL_INCDEP)/perly.h \ + $(PERL_INCDEP)/pp.h \ + $(PERL_INCDEP)/pp_proto.h \ + $(PERL_INCDEP)/proto.h \ + $(PERL_INCDEP)/reentr.h \ + $(PERL_INCDEP)/regcharclass.h \ + $(PERL_INCDEP)/regcomp.h \ + $(PERL_INCDEP)/regexp.h \ + $(PERL_INCDEP)/regnodes.h \ + $(PERL_INCDEP)/scope.h \ + $(PERL_INCDEP)/sv.h \ + $(PERL_INCDEP)/thread.h \ + $(PERL_INCDEP)/time64.h \ + $(PERL_INCDEP)/time64_config.h \ + $(PERL_INCDEP)/uconfig.h \ + $(PERL_INCDEP)/unicode_constants.h \ + $(PERL_INCDEP)/unixish.h \ + $(PERL_INCDEP)/utf8.h \ + $(PERL_INCDEP)/utfebcdic.h \ + $(PERL_INCDEP)/util.h \ + $(PERL_INCDEP)/uudmap.h \ + $(PERL_INCDEP)/vutil.h \ + $(PERL_INCDEP)/warnings.h + +$(OBJECT) : $(PERL_HDRS) + +MD5.c : $(XSUBPPDEPS) + + +# --- MakeMaker makefile section: + +$(OBJECT) : $(FIRST_MAKEFILE) + +# We take a very conservative approach here, but it's worth it. +# We move Makefile to Makefile.old here to avoid gnu make looping. +$(FIRST_MAKEFILE) : Makefile.PL $(CONFIGDEP) + $(NOECHO) $(ECHO) "Makefile out-of-date with respect to $?" + $(NOECHO) $(ECHO) "Cleaning current config before rebuilding Makefile..." + -$(NOECHO) $(RM_F) $(MAKEFILE_OLD) + -$(NOECHO) $(MV) $(FIRST_MAKEFILE) $(MAKEFILE_OLD) + - $(MAKE) $(USEMAKEFILE) $(MAKEFILE_OLD) clean $(DEV_NULL) + $(PERLRUN) Makefile.PL + $(NOECHO) $(ECHO) "==> Your Makefile has been rebuilt. <==" + $(NOECHO) $(ECHO) "==> Please rerun the $(MAKE) command. <==" + $(FALSE) + + + +# --- MakeMaker staticmake section: + +# --- MakeMaker makeaperl section --- +MAP_TARGET = perl +FULLPERL = "/usr/bin/perl" + +$(MAP_TARGET) :: static $(MAKE_APERL_FILE) + $(MAKE) $(USEMAKEFILE) $(MAKE_APERL_FILE) $@ + +$(MAKE_APERL_FILE) : $(FIRST_MAKEFILE) pm_to_blib + $(NOECHO) $(ECHO) Writing \"$(MAKE_APERL_FILE)\" for this $(MAP_TARGET) + $(NOECHO) $(PERLRUNINST) \ + Makefile.PL DIR="" \ + MAKEFILE=$(MAKE_APERL_FILE) LINKTYPE=static \ + MAKEAPERL=1 NORECURS=1 CCCDLFLAGS= + + +# --- MakeMaker test section: + +TEST_VERBOSE=0 +TEST_TYPE=test_$(LINKTYPE) +TEST_FILE = test.pl +TEST_FILES = +TESTDB_SW = -d + +testdb :: testdb_$(LINKTYPE) + +test :: $(TEST_TYPE) subdirs-test + +subdirs-test :: + $(NOECHO) $(NOOP) + + +test_dynamic :: pure_all + PERL_DL_NONLAZY=1 $(FULLPERLRUN) "-I$(INST_LIB)" "-I$(INST_ARCHLIB)" $(TEST_FILE) + +testdb_dynamic :: pure_all + PERL_DL_NONLAZY=1 $(FULLPERLRUN) $(TESTDB_SW) "-I$(INST_LIB)" "-I$(INST_ARCHLIB)" $(TEST_FILE) + +test_ : test_dynamic + +test_static :: pure_all $(MAP_TARGET) + PERL_DL_NONLAZY=1 ./$(MAP_TARGET) "-I$(INST_LIB)" "-I$(INST_ARCHLIB)" $(TEST_FILE) + +testdb_static :: pure_all $(MAP_TARGET) + PERL_DL_NONLAZY=1 ./$(MAP_TARGET) $(TESTDB_SW) "-I$(INST_LIB)" "-I$(INST_ARCHLIB)" $(TEST_FILE) + + + +# --- MakeMaker ppd section: +# Creates a PPD (Perl Package Description) for a binary distribution. +ppd : + $(NOECHO) $(ECHO) '' > $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) '' >> $(DISTNAME).ppd + + +# --- MakeMaker pm_to_blib section: + +pm_to_blib : $(FIRST_MAKEFILE) $(TO_INST_PM) + $(NOECHO) $(ABSPERLRUN) -MExtUtils::Install -e 'pm_to_blib({@ARGV}, '\''$(INST_LIB)/auto'\'', q[$(PM_FILTER)], '\''$(PERM_DIR)'\'')' -- \ + MD5.pm $(INST_LIB)/MD5.pm + $(NOECHO) $(TOUCH) pm_to_blib + + +# --- MakeMaker selfdocument section: + + +# --- MakeMaker postamble section: + + +# End. diff --git a/perlmodules/MD5-1.7/README b/perlmodules/MD5-1.7/README new file mode 100644 index 0000000..cda738b --- /dev/null +++ b/perlmodules/MD5-1.7/README @@ -0,0 +1,42 @@ +MD5 Extension Version 1.7 + +This is a Perl5 extension interface to the RSA Data Security Inc. MD5 +Message Digest algorithm. Documentation is in MD5.pod. + +To build the extension, unpack this distribution under the ext/ +directory of your Perl source distribution, create the Makefile using +'perl Makefile.PL' and do a 'make'. + +Note that the MD5.xs file uses the "PROTOTYPES: DISABLE" facility +which only became available in late betas pf perl 5.002. If you are +using a version which does not support this then merely remove +this line. + +The mddriver.pl script gives a simple example of how to use the +routines. In particular 'perl mddriver.pl -x' will perform a quick +test of the routines to see if they produce the expected output. The +use of "make test" will perform a more comprehensive test. (WARNING: +You should not run mddriver.pl directly in the MD5 directory when using +dynamic linking as on some systems it will dynamically link to object +files in the current directory which may not give the correct +behaviour. This is believed to affect at least AIX and IRIX. A similar +caveat applies to the direct use of the test.pl script). + +The module is known to work (using static or dynamic linking) on at +least AIX, Solaris, HP-UX and IRIX. It should work on other +"reasonable" UNIX-like platforms (for an unspecified definition of the +word "reasonable" :-) + +Support is also provided for 64-bit platforms. This should be detected +and handled automatically. See the entry for version 1.7 in the +Changes file for further details. + +Bugs, queries, plaudits to + + Neil Winton + +* Neil Winton Post Point P5 * +* N.Winton@axion.bt.co.uk BT Laboratories * +* Tel +44 1473 646079 Martlesham Heath * +* Fax +44 1473 643306 IPSWICH IP5 7RE, UK * + diff --git a/perlmodules/MD5-1.7/examples/mddriver.pl b/perlmodules/MD5-1.7/examples/mddriver.pl new file mode 100644 index 0000000..82c99e5 --- /dev/null +++ b/perlmodules/MD5-1.7/examples/mddriver.pl @@ -0,0 +1,69 @@ +#!/usr/local/bin/perl +# SCCS ID @(#)mddriver.pl 1.3 95/05/01 + +require 'getopts.pl'; +use MD5; +sub DoTest; + +&Getopts('s:x'); + +$md5 = new MD5; + +if (defined($opt_s)) +{ + $md5->add($opt_s); + $digest = $md5->digest(); + print("MD5(\"$opt_s\") = " . unpack("H*", $digest) . "\n"); +} +elsif ($opt_x) +{ + DoTest("", "d41d8cd98f00b204e9800998ecf8427e"); + DoTest("a", "0cc175b9c0f1b6a831c399e269772661"); + DoTest("abc", "900150983cd24fb0d6963f7d28e17f72"); + DoTest("message digest", "f96b697d7cb7938d525a2f31aaf161d0"); + DoTest("abcdefghijklmnopqrstuvwxyz", "c3fcd3d76192e4007dfb496cca67e13b"); + DoTest("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + "d174ab98d277d9f5a5611c2c9f419d9f"); + DoTest("12345678901234567890123456789012345678901234567890123456789012345678901234567890", + "57edf4a22be3c955ac49da2e2107b67a"); +} +else +{ + if ($#ARGV >= 0) + { + foreach $ARGV (@ARGV) + { + die "Can't open file '$ARGV' ($!)\n" unless open(ARGV, $ARGV); + + $md5->reset(); + $md5->addfile(ARGV); + $hex = $md5->hexdigest(); + print "MD5($ARGV) = $hex\n"; + + close(ARGV); + } + } + else + { + $md5->reset(); + $md5->addfile(STDIN); + $hex = $md5->hexdigest(); + + print "$hex\n"; + } +} + +exit 0; + +sub DoTest +{ + my ($str, $expect) = @_; + my ($digest, $hex); + my $md5 = new MD5; + + $md5->add($str); + $digest = $md5->digest(); + $hex = unpack("H*", $digest); + + print "MD5(\"$str\") =>\nEXPECT: $expect\nRESULT: $hex\n" +} diff --git a/perlmodules/MD5-1.7/examples/twdigest.pl b/perlmodules/MD5-1.7/examples/twdigest.pl new file mode 100644 index 0000000..bf6effb --- /dev/null +++ b/perlmodules/MD5-1.7/examples/twdigest.pl @@ -0,0 +1,35 @@ +#!/usr/local/bin/perl + +use MD5; + +# +# twdigest -- format MD5 digest like TripWire does +# +# This converts the md5->digest binary string to +# 64-radix ascii, given the base-vector: +# 0 - 9, A - Z, a - z, :, . +# + +sub twdigest { + my($digest) = @_; + my(@chunks, $bits); + + # Convert to ASCII bit-string + $bits = unpack("B*", $digest); + + # Round up length to multiple of 6 by prepending zeros + $bits = ("0" x ((6 - (length($bits) % 6)) % 6)) . $bits; + + # Split into 6-bit chunks + @chunks = grep {$_ ne ''} (split(/(.{6})/, $bits, -1)); + + # Convert each 6-bit value to a single character + foreach (@chunks) + { + $_ = pack("B8", "00" . $_); + tr/\000-\011\012-\043\044-\075\076\077/0-9A-Za-z:./; + } + + # Join all of the chunks into one string + join('', @chunks); +} diff --git a/perlmodules/MD5-1.7/global.h b/perlmodules/MD5-1.7/global.h new file mode 100644 index 0000000..741a46f --- /dev/null +++ b/perlmodules/MD5-1.7/global.h @@ -0,0 +1,49 @@ +/* GLOBAL.H - RSAREF types and constants + */ + +/* PROTOTYPES should be set to one if and only if the compiler supports + function argument prototyping. +The following makes PROTOTYPES default to 0 if it has not already + been defined with C compiler flags. + */ +#ifndef PROTOTYPES +#define PROTOTYPES 0 +#endif + +/* POINTER defines a generic pointer type */ +typedef unsigned char *POINTER; + +/* UINT2 defines a two byte word */ +typedef unsigned short int UINT2; + +/* UINT4 defines a four byte word. +We use the Perl byte-order definition to discover if a long has more than + 4 bytes. If so we will try to use an unsigned int. This is OK for DEC + Alpha but may not work everywhere. See the TO32 definition below. + */ +#if (PERL_BYTEORDER <= 4321) || defined(UINT4_IS_LONG) +typedef unsigned long UINT4; +#else +typedef unsigned int UINT4; +#endif + +/* TO32 ensures that UINT4 values are truncated to 32 bits. +A Cray has short, int and long all at 64 bits so we need to apply this + macro to reduce UINT4 values to 32 bits at appropriate places. If UINT4 + really does have 32 bits then this is a no-op. + */ +#if defined(cray) || defined(TRUNCATE_UINT4) +#define TO32(x) ((x) & 0xffffffff) +#else +#define TO32(x) (x) +#endif + +/* PROTO_LIST is defined depending on how PROTOTYPES is defined above. +If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it + returns an empty list. + */ +#if PROTOTYPES +#define PROTO_LIST(list) list +#else +#define PROTO_LIST(list) () +#endif diff --git a/perlmodules/MD5-1.7/md5.h b/perlmodules/MD5-1.7/md5.h new file mode 100644 index 0000000..64c48d8 --- /dev/null +++ b/perlmodules/MD5-1.7/md5.h @@ -0,0 +1,36 @@ +/* MD5.H - header file for MD5C.C + */ + +/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. + +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. + +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +These notices must be retained in any copies of any part of this +documentation and/or software. + */ + +/* MD5 context. */ +typedef struct { + UINT4 state[4]; /* state (ABCD) */ + UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ + unsigned char buffer[64]; /* input buffer */ +} MD5_CTX; + +void MD5Init PROTO_LIST ((MD5_CTX *)); +void MD5Update PROTO_LIST + ((MD5_CTX *, unsigned char *, unsigned long)); +void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *)); diff --git a/perlmodules/MD5-1.7/md5c.c b/perlmodules/MD5-1.7/md5c.c new file mode 100644 index 0000000..67186f4 --- /dev/null +++ b/perlmodules/MD5-1.7/md5c.c @@ -0,0 +1,351 @@ +/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm + */ + +/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. + +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. + +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +These notices must be retained in any copies of any part of this +documentation and/or software. + */ + +/* +** The following macro re-definitions added to work around a problem on +** Solaris where the original MD5 routines are already in /lib/libnsl.a. +** This causes dynamic linking of the module to fail. +** +** Thanks to Ken Pizzini (ken@spry.com) for finally nailing this one! +*/ + +#define MD5Init MD5Init_perl +#define MD5Update MD5Update_perl +#define MD5Final MD5Final_perl + +#include "global.h" +#include "md5.h" + +/* Constants for MD5Transform routine. + */ + +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + +static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64])); +static void Encode PROTO_LIST + ((unsigned char *, UINT4 *, unsigned long)); +static void Decode PROTO_LIST + ((UINT4 *, unsigned char *, unsigned long)); +static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned long)); +static void MD5_memset PROTO_LIST ((POINTER, int, unsigned long)); + +static unsigned char PADDING[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* F, G, H and I are basic MD5 functions. + */ +#define F(x, y, z) TO32((((x) & (y)) | ((~x) & (z)))) +#define G(x, y, z) TO32((((x) & (z)) | ((y) & (~z)))) +#define H(x, y, z) TO32(((x) ^ (y) ^ (z))) +#define I(x, y, z) TO32(((y) ^ ((x) | (~z)))) + +/* ROTATE_LEFT rotates x left n bits. + */ +#define ROTATE_LEFT(x, n) TO32((((x) << (n)) | (TO32((x)) >> (32-(n))))) + +/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. +Rotation is separate from addition to prevent recomputation. + */ +#define FF(a, b, c, d, x, s, ac) { \ + (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + TO32((a)); \ + } +#define GG(a, b, c, d, x, s, ac) { \ + (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + TO32((a)); \ + } +#define HH(a, b, c, d, x, s, ac) { \ + (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + TO32((a)); \ + } +#define II(a, b, c, d, x, s, ac) { \ + (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + TO32((a)); \ + } + +/* MD5 initialization. Begins an MD5 operation, writing a new context. + */ +void MD5Init (context) +MD5_CTX *context; /* context */ +{ + context->count[0] = context->count[1] = 0; + /* Load magic initialization constants. +*/ + context->state[0] = 0x67452301; + context->state[1] = 0xefcdab89; + context->state[2] = 0x98badcfe; + context->state[3] = 0x10325476; +} + +/* MD5 block update operation. Continues an MD5 message-digest + operation, processing another message block, and updating the + context. + */ +void MD5Update (context, input, inputLen) +MD5_CTX *context; /* context */ +unsigned char *input; /* input block */ +unsigned long inputLen; /* length of input block */ +{ + unsigned long i, index, partLen; + + /* Compute number of bytes mod 64 */ + index = (unsigned long)((context->count[0] >> 3) & 0x3F); + + /* Update number of bits */ + if (TO32(context->count[0] += (inputLen << 3)) + < TO32(inputLen << 3)) + context->count[1]++; + context->count[1] += (inputLen >> 29); + + partLen = 64 - index; + + /* Transform as many times as possible. +*/ + if (inputLen >= partLen) { + MD5_memcpy + ((POINTER)&context->buffer[index], (POINTER)input, partLen); + MD5Transform (context->state, context->buffer); + + for (i = partLen; i + 63 < inputLen; i += 64) + MD5Transform (context->state, &input[i]); + + index = 0; + } + else + i = 0; + + /* Buffer remaining input */ + MD5_memcpy + ((POINTER)&context->buffer[index], (POINTER)&input[i], + inputLen-i); +} + +/* MD5 finalization. Ends an MD5 message-digest operation, writing the + the message digest and zeroizing the context. + */ +void MD5Final (digest, context) +unsigned char digest[16]; /* message digest */ +MD5_CTX *context; /* context */ +{ + unsigned char bits[8]; + unsigned long index, padLen; + + /* Save number of bits */ + Encode (bits, context->count, 8); + + /* Pad out to 56 mod 64. +*/ + index = (unsigned long)((context->count[0] >> 3) & 0x3f); + padLen = (index < 56) ? (56 - index) : (120 - index); + MD5Update (context, PADDING, padLen); + + /* Append length (before padding) */ + MD5Update (context, bits, 8); + + /* Store state in digest */ + Encode (digest, context->state, 16); + + /* Zeroize sensitive information. +*/ + MD5_memset ((POINTER)context, 0, sizeof (*context)); +} + +/* MD5 basic transformation. Transforms state based on block. + */ +static void MD5Transform (state, block) +UINT4 state[4]; +unsigned char block[64]; +{ + UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + + Decode (x, block, 64); + + /* Round 1 */ + FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ + FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ + FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ + FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ + FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ + FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ + FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ + FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ + FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ + FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ + FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ + GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ + GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ + GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ + GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ + GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ + GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ + GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ + GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ + GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ + GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ + GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ + HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ + HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ + HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ + HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ + HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ + HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ + HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ + HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ + HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ + II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ + II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ + II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ + II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ + II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ + II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ + II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ + II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ + II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; TO32(state[0]); + state[1] += b; TO32(state[1]); + state[2] += c; TO32(state[2]); + state[3] += d; TO32(state[3]); + + /* Zeroize sensitive information. + */ + MD5_memset ((POINTER)x, 0, sizeof (x)); +} + +/* Encodes input (UINT4) into output (unsigned char). Assumes len is + a multiple of 4. + */ +static void Encode (output, input, len) +unsigned char *output; +UINT4 *input; +unsigned long len; +{ + unsigned long i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) { + output[j] = (unsigned char)(input[i] & 0xff); + output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); + output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); + output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); + } +} + +/* Decodes input (unsigned char) into output (UINT4). Assumes len is + a multiple of 4. + */ +static void Decode (output, input, len) +UINT4 *output; +unsigned char *input; +unsigned long len; +{ + unsigned long i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) + output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | + (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24); +} + +/* Note: Replace "for loop" with standard memcpy if possible. + */ + +static void MD5_memcpy (output, input, len) +POINTER output; +POINTER input; +unsigned long len; +{ + unsigned long i; + + for (i = 0; i < len; i++) + output[i] = input[i]; +} + +/* Note: Replace "for loop" with standard memset if possible. + */ +static void MD5_memset (output, value, len) +POINTER output; +int value; +unsigned long len; +{ + unsigned long i; + + for (i = 0; i < len; i++) + ((char *)output)[i] = (char)value; +} diff --git a/perlmodules/MD5-1.7/test.pl b/perlmodules/MD5-1.7/test.pl new file mode 100644 index 0000000..2f543e5 --- /dev/null +++ b/perlmodules/MD5-1.7/test.pl @@ -0,0 +1,154 @@ +# SCCS ID @(#)test.pl 1.1 96/04/09 +# Before `make install' is performed this script should be runnable with +# `make test'. After `make install' it should work as `perl test.pl' + +######################### We start with some black magic to print on failure. + +# Change 1..1 below to 1..last_test_to_print . +# (It may become useful if the test is moved to ./t subdirectory.) + +BEGIN {print "1..14\n";} +END {print "not ok 1\n" unless $loaded;} +use MD5; +$loaded = 1; +print "ok 1\n"; + +######################### End of black magic. + +# Insert your test code below (better if it prints "ok 13" +# (correspondingly "not ok 13") depending on the success of chunk 13 +# of the test code): + +package MD5Test; + +# 2: Constructor + +print (($md5 = new MD5) ? "ok 2\n" : "not ok 2\n"); + +# 3: Basic test data as defined in RFC 1321 + +%data = ( + "" => "d41d8cd98f00b204e9800998ecf8427e", + "a" => "0cc175b9c0f1b6a831c399e269772661", + "abc" => "900150983cd24fb0d6963f7d28e17f72", + "message digest" + => "f96b697d7cb7938d525a2f31aaf161d0", + "abcdefghijklmnopqrstuvwxyz" + => "c3fcd3d76192e4007dfb496cca67e13b", + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + => "d174ab98d277d9f5a5611c2c9f419d9f", + "12345678901234567890123456789012345678901234567890123456789012345678901234567890" + => "57edf4a22be3c955ac49da2e2107b67a", +); + +$failed = 0; +foreach (sort(keys(%data))) +{ + $md5->reset; + $md5->add($_); + $digest = $md5->digest; + $hex = unpack("H*", $digest); + if ($hex ne $data{$_}) + { + $failed++; + } +} +print ($failed ? "not ok 3\n" : "ok 3\n"); + +# 4: Various flavours of file-handle to addfile + +open(F, "<$0"); + +$md5->reset; + +$md5->addfile(F); +$hex = $md5->hexdigest; +print ($hex ne '' ? "ok 4\n" : "not ok 4\n"); + +$orig = $hex; + +# 5: Fully qualified with ' operator + +seek(F, 0, 0); +$md5->reset; +$md5->addfile(MD5Test'F); +$hex = $md5->hexdigest; +print ($hex eq $orig ? "ok 5\n" : "not ok 5\n"); + +# 6: Fully qualified with :: operator + +seek(F, 0, 0); +$md5->reset; +$md5->addfile(MD5Test::F); +$hex = $md5->hexdigest; +print ($hex eq $orig ? "ok 6\n" : "not ok 6\n"); + +# 7: Type glob + +seek(F, 0, 0); +$md5->reset; +$md5->addfile(*F); +$hex = $md5->hexdigest; +print ($hex eq $orig ? "ok 7\n" : "not ok 7\n"); + +# 8: Type glob reference (the prefered mechanism) + +seek(F, 0, 0); +$md5->reset; +$md5->addfile(\*F); +$hex = $md5->hexdigest; +print ($hex eq $orig ? "ok 8\n" : "not ok 8\n"); + +# 9: File-handle passed by name (really the same as 6) + +seek(F, 0, 0); +$md5->reset; +$md5->addfile("MD5Test::F"); +$hex = $md5->hexdigest; +print ($hex eq $orig ? "ok 9\n" : "not ok 9\n"); + +# 10: Other ways of reading the data -- line at a time + +seek(F, 0, 0); +$md5->reset; +while () +{ + $md5->add($_); +} +$hex = $md5->hexdigest; +print ($hex eq $orig ? "ok 10\n" : "not ok 10\n"); + +# 11: Input lines as a list to add() + +seek(F, 0, 0); +$md5->reset; +$md5->add(); +$hex = $md5->hexdigest; +print ($hex eq $orig ? "ok 11\n" : "not ok 11\n"); + +# 12: Random chunks up to 128 bytes + +seek(F, 0, 0); +$md5->reset; +while (read(F, $hexata, (rand % 128) + 1)) +{ + $md5->add($hexata); +} +$hex = $md5->hexdigest; +print ($hex eq $orig ? "ok 12\n" : "not ok 12\n"); + +# 13: All the data at once + +seek(F, 0, 0); +$md5->reset; +undef $/; +$data = ; +$hex = $md5->hexhash($data); +print ($hex eq $orig ? "ok 13\n" : "not ok 13\n"); + +close(F); + +# 14: Using static member function + +$hex = MD5->hexhash($data); +print ($hex eq $orig ? "ok 14\n" : "not ok 14\n"); diff --git a/perlmodules/MD5-1.7/typemap b/perlmodules/MD5-1.7/typemap new file mode 100644 index 0000000..5c27408 --- /dev/null +++ b/perlmodules/MD5-1.7/typemap @@ -0,0 +1,3 @@ +# SCCS ID @(#)typemap 1.2 94/11/07 +TYPEMAP +MD5 T_PTROBJ diff --git a/perlmodules/mwx-1.21/Changes b/perlmodules/mwx-1.21/Changes new file mode 100644 index 0000000..f0c0712 --- /dev/null +++ b/perlmodules/mwx-1.21/Changes @@ -0,0 +1,6 @@ +Revision history for Perl extension mwx. + +0.01 Sun Jun 1 18:30:04 2003 + - original version; created by h2xs 1.21 with options + -X -n mwx + diff --git a/perlmodules/mwx-1.21/MANIFEST b/perlmodules/mwx-1.21/MANIFEST new file mode 100644 index 0000000..02dfa30 --- /dev/null +++ b/perlmodules/mwx-1.21/MANIFEST @@ -0,0 +1,6 @@ +Changes +Makefile.PL +MANIFEST +mwx.pm +README +test.pl diff --git a/perlmodules/mwx-1.21/Makefile.PL b/perlmodules/mwx-1.21/Makefile.PL new file mode 100644 index 0000000..b5990ff --- /dev/null +++ b/perlmodules/mwx-1.21/Makefile.PL @@ -0,0 +1,17 @@ +use ExtUtils::MakeMaker; +# See lib/ExtUtils/MakeMaker.pm for details of how to influence +# the contents of the Makefile that is written. + +WriteMakefile( + 'NAME' => 'mwx', + 'VERSION_FROM' => 'mwx.pm', # finds $VERSION + 'PREREQ_PM' => { Net::SMTP => 0, + MD5 => 0, + Net::NIS => 0, + Math::BigInt => 0, + Time::HiRes => 0, + Term::ReadKey => 0}, + ($] >= 5.005 ? ## Add these new keywords supported since 5.005 + (ABSTRACT_FROM => 'mwx.pm', # retrieve abstract from module + AUTHOR => 'M.Wesemann ') : ()), +); diff --git a/perlmodules/mwx-1.21/Makefile.old b/perlmodules/mwx-1.21/Makefile.old new file mode 100644 index 0000000..fef5f15 --- /dev/null +++ b/perlmodules/mwx-1.21/Makefile.old @@ -0,0 +1,864 @@ +# This Makefile is for the mwx extension to perl. +# +# It was generated automatically by MakeMaker version +# 7.0401 (Revision: 70401) from the contents of +# Makefile.PL. Don't edit this file, edit Makefile.PL instead. +# +# ANY CHANGES MADE HERE WILL BE LOST! +# +# MakeMaker ARGV: () +# + +# MakeMaker Parameters: + +# ABSTRACT_FROM => q[mwx.pm] +# AUTHOR => [q[M.Wesemann ]] +# BUILD_REQUIRES => { } +# CONFIGURE_REQUIRES => { } +# NAME => q[mwx] +# PREREQ_PM => { MD5=>q[0], Math::BigInt=>q[0], Net::NIS=>q[0], Net::SMTP=>q[0], Term::ReadKey=>q[0], Time::HiRes=>q[0] } +# TEST_REQUIRES => { } +# VERSION_FROM => q[mwx.pm] + +# --- MakeMaker post_initialize section: + + +# --- MakeMaker const_config section: + +# These definitions are from config.sh (via /usr/lib/x86_64-linux-gnu/perl/5.22/Config.pm). +# They may have been overridden via Makefile.PL or on the command line. +AR = ar +CC = x86_64-linux-gnu-gcc +CCCDLFLAGS = -fPIC +CCDLFLAGS = -Wl,-E +DLEXT = so +DLSRC = dl_dlopen.xs +EXE_EXT = +FULL_AR = /usr/bin/ar +LD = x86_64-linux-gnu-gcc +LDDLFLAGS = -shared -L/usr/local/lib -fstack-protector-strong +LDFLAGS = -fstack-protector-strong -L/usr/local/lib +LIBC = libc-2.23.so +LIB_EXT = .a +OBJ_EXT = .o +OSNAME = linux +OSVERS = 3.16.0 +RANLIB = : +SITELIBEXP = /usr/local/share/perl/5.22.1 +SITEARCHEXP = /usr/local/lib/x86_64-linux-gnu/perl/5.22.1 +SO = so +VENDORARCHEXP = /usr/lib/x86_64-linux-gnu/perl5/5.22 +VENDORLIBEXP = /usr/share/perl5 + + +# --- MakeMaker constants section: +AR_STATIC_ARGS = cr +DIRFILESEP = / +DFSEP = $(DIRFILESEP) +NAME = mwx +NAME_SYM = mwx +VERSION = 1.21 +VERSION_MACRO = VERSION +VERSION_SYM = 1_21 +DEFINE_VERSION = -D$(VERSION_MACRO)=\"$(VERSION)\" +XS_VERSION = 1.21 +XS_VERSION_MACRO = XS_VERSION +XS_DEFINE_VERSION = -D$(XS_VERSION_MACRO)=\"$(XS_VERSION)\" +INST_ARCHLIB = blib/arch +INST_SCRIPT = blib/script +INST_BIN = blib/bin +INST_LIB = blib/lib +INST_MAN1DIR = blib/man1 +INST_MAN3DIR = blib/man3 +MAN1EXT = 1p +MAN3EXT = 3pm +INSTALLDIRS = site +DESTDIR = +PREFIX = $(SITEPREFIX) +PERLPREFIX = /usr +SITEPREFIX = /usr/local +VENDORPREFIX = /usr +INSTALLPRIVLIB = /usr/share/perl/5.22 +DESTINSTALLPRIVLIB = $(DESTDIR)$(INSTALLPRIVLIB) +INSTALLSITELIB = /usr/local/share/perl/5.22.1 +DESTINSTALLSITELIB = $(DESTDIR)$(INSTALLSITELIB) +INSTALLVENDORLIB = /usr/share/perl5 +DESTINSTALLVENDORLIB = $(DESTDIR)$(INSTALLVENDORLIB) +INSTALLARCHLIB = /usr/lib/x86_64-linux-gnu/perl/5.22 +DESTINSTALLARCHLIB = $(DESTDIR)$(INSTALLARCHLIB) +INSTALLSITEARCH = /usr/local/lib/x86_64-linux-gnu/perl/5.22.1 +DESTINSTALLSITEARCH = $(DESTDIR)$(INSTALLSITEARCH) +INSTALLVENDORARCH = /usr/lib/x86_64-linux-gnu/perl5/5.22 +DESTINSTALLVENDORARCH = $(DESTDIR)$(INSTALLVENDORARCH) +INSTALLBIN = /usr/bin +DESTINSTALLBIN = $(DESTDIR)$(INSTALLBIN) +INSTALLSITEBIN = /usr/local/bin +DESTINSTALLSITEBIN = $(DESTDIR)$(INSTALLSITEBIN) +INSTALLVENDORBIN = /usr/bin +DESTINSTALLVENDORBIN = $(DESTDIR)$(INSTALLVENDORBIN) +INSTALLSCRIPT = /usr/bin +DESTINSTALLSCRIPT = $(DESTDIR)$(INSTALLSCRIPT) +INSTALLSITESCRIPT = /usr/local/bin +DESTINSTALLSITESCRIPT = $(DESTDIR)$(INSTALLSITESCRIPT) +INSTALLVENDORSCRIPT = /usr/bin +DESTINSTALLVENDORSCRIPT = $(DESTDIR)$(INSTALLVENDORSCRIPT) +INSTALLMAN1DIR = /usr/share/man/man1 +DESTINSTALLMAN1DIR = $(DESTDIR)$(INSTALLMAN1DIR) +INSTALLSITEMAN1DIR = /usr/local/man/man1 +DESTINSTALLSITEMAN1DIR = $(DESTDIR)$(INSTALLSITEMAN1DIR) +INSTALLVENDORMAN1DIR = /usr/share/man/man1 +DESTINSTALLVENDORMAN1DIR = $(DESTDIR)$(INSTALLVENDORMAN1DIR) +INSTALLMAN3DIR = /usr/share/man/man3 +DESTINSTALLMAN3DIR = $(DESTDIR)$(INSTALLMAN3DIR) +INSTALLSITEMAN3DIR = /usr/local/man/man3 +DESTINSTALLSITEMAN3DIR = $(DESTDIR)$(INSTALLSITEMAN3DIR) +INSTALLVENDORMAN3DIR = /usr/share/man/man3 +DESTINSTALLVENDORMAN3DIR = $(DESTDIR)$(INSTALLVENDORMAN3DIR) +PERL_LIB = /usr/share/perl/5.22 +PERL_ARCHLIB = /usr/lib/x86_64-linux-gnu/perl/5.22 +PERL_ARCHLIBDEP = /usr/lib/x86_64-linux-gnu/perl/5.22 +LIBPERL_A = libperl.a +FIRST_MAKEFILE = Makefile +MAKEFILE_OLD = Makefile.old +MAKE_APERL_FILE = Makefile.aperl +PERLMAINCC = $(CC) +PERL_INC = /usr/lib/x86_64-linux-gnu/perl/5.22/CORE +PERL_INCDEP = /usr/lib/x86_64-linux-gnu/perl/5.22/CORE +PERL = "/usr/bin/perl" +FULLPERL = "/usr/bin/perl" +ABSPERL = $(PERL) +PERLRUN = $(PERL) +FULLPERLRUN = $(FULLPERL) +ABSPERLRUN = $(ABSPERL) +PERLRUNINST = $(PERLRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" +FULLPERLRUNINST = $(FULLPERLRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" +ABSPERLRUNINST = $(ABSPERLRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" +PERL_CORE = 0 +PERM_DIR = 755 +PERM_RW = 644 +PERM_RWX = 755 + +MAKEMAKER = /usr/share/perl/5.22/ExtUtils/MakeMaker.pm +MM_VERSION = 7.0401 +MM_REVISION = 70401 + +# FULLEXT = Pathname for extension directory (eg Foo/Bar/Oracle). +# BASEEXT = Basename part of FULLEXT. May be just equal FULLEXT. (eg Oracle) +# PARENT_NAME = NAME without BASEEXT and no trailing :: (eg Foo::Bar) +# DLBASE = Basename part of dynamic library. May be just equal BASEEXT. +MAKE = make +FULLEXT = mwx +BASEEXT = mwx +PARENT_NAME = +DLBASE = $(BASEEXT) +VERSION_FROM = mwx.pm +OBJECT = +LDFROM = $(OBJECT) +LINKTYPE = dynamic +BOOTDEP = + +# Handy lists of source code files: +XS_FILES = +C_FILES = +O_FILES = +H_FILES = +MAN1PODS = +MAN3PODS = mwx.pm + +# Where is the Config information that we are using/depend on +CONFIGDEP = $(PERL_ARCHLIBDEP)$(DFSEP)Config.pm $(PERL_INCDEP)$(DFSEP)config.h + +# Where to build things +INST_LIBDIR = $(INST_LIB) +INST_ARCHLIBDIR = $(INST_ARCHLIB) + +INST_AUTODIR = $(INST_LIB)/auto/$(FULLEXT) +INST_ARCHAUTODIR = $(INST_ARCHLIB)/auto/$(FULLEXT) + +INST_STATIC = +INST_DYNAMIC = +INST_BOOT = + +# Extra linker info +EXPORT_LIST = +PERL_ARCHIVE = +PERL_ARCHIVEDEP = +PERL_ARCHIVE_AFTER = + + +TO_INST_PM = mwx.pm + +PM_TO_BLIB = mwx.pm \ + $(INST_LIB)/mwx.pm + + +# --- MakeMaker platform_constants section: +MM_Unix_VERSION = 7.0401 +PERL_MALLOC_DEF = -DPERL_EXTMALLOC_DEF -Dmalloc=Perl_malloc -Dfree=Perl_mfree -Drealloc=Perl_realloc -Dcalloc=Perl_calloc + + +# --- MakeMaker tool_autosplit section: +# Usage: $(AUTOSPLITFILE) FileToSplit AutoDirToSplitInto +AUTOSPLITFILE = $(ABSPERLRUN) -e 'use AutoSplit; autosplit($$$$ARGV[0], $$$$ARGV[1], 0, 1, 1)' -- + + + +# --- MakeMaker tool_xsubpp section: + + +# --- MakeMaker tools_other section: +SHELL = /bin/sh +CHMOD = chmod +CP = cp +MV = mv +NOOP = $(TRUE) +NOECHO = @ +RM_F = rm -f +RM_RF = rm -rf +TEST_F = test -f +TOUCH = touch +UMASK_NULL = umask 0 +DEV_NULL = > /dev/null 2>&1 +MKPATH = $(ABSPERLRUN) -MExtUtils::Command -e 'mkpath' -- +EQUALIZE_TIMESTAMP = $(ABSPERLRUN) -MExtUtils::Command -e 'eqtime' -- +FALSE = false +TRUE = true +ECHO = echo +ECHO_N = echo -n +UNINST = 0 +VERBINST = 0 +MOD_INSTALL = $(ABSPERLRUN) -MExtUtils::Install -e 'install([ from_to => {@ARGV}, verbose => '\''$(VERBINST)'\'', uninstall_shadows => '\''$(UNINST)'\'', dir_mode => '\''$(PERM_DIR)'\'' ]);' -- +DOC_INSTALL = $(ABSPERLRUN) -MExtUtils::Command::MM -e 'perllocal_install' -- +UNINSTALL = $(ABSPERLRUN) -MExtUtils::Command::MM -e 'uninstall' -- +WARN_IF_OLD_PACKLIST = $(ABSPERLRUN) -MExtUtils::Command::MM -e 'warn_if_old_packlist' -- +MACROSTART = +MACROEND = +USEMAKEFILE = -f +FIXIN = $(ABSPERLRUN) -MExtUtils::MY -e 'MY->fixin(shift)' -- +CP_NONEMPTY = $(ABSPERLRUN) -MExtUtils::Command::MM -e 'cp_nonempty' -- + + +# --- MakeMaker makemakerdflt section: +makemakerdflt : all + $(NOECHO) $(NOOP) + + +# --- MakeMaker dist section: +TAR = tar +TARFLAGS = cvf +ZIP = zip +ZIPFLAGS = -r +COMPRESS = gzip --best +SUFFIX = .gz +SHAR = shar +PREOP = $(NOECHO) $(NOOP) +POSTOP = $(NOECHO) $(NOOP) +TO_UNIX = $(NOECHO) $(NOOP) +CI = ci -u +RCS_LABEL = rcs -Nv$(VERSION_SYM): -q +DIST_CP = best +DIST_DEFAULT = tardist +DISTNAME = mwx +DISTVNAME = mwx-1.21 + + +# --- MakeMaker macro section: + + +# --- MakeMaker depend section: + + +# --- MakeMaker cflags section: + + +# --- MakeMaker const_loadlibs section: + + +# --- MakeMaker const_cccmd section: + + +# --- MakeMaker post_constants section: + + +# --- MakeMaker pasthru section: + +PASTHRU = LIBPERL_A="$(LIBPERL_A)"\ + LINKTYPE="$(LINKTYPE)"\ + LD="$(LD)"\ + PREFIX="$(PREFIX)" + + +# --- MakeMaker special_targets section: +.SUFFIXES : .xs .c .C .cpp .i .s .cxx .cc $(OBJ_EXT) + +.PHONY: all config static dynamic test linkext manifest blibdirs clean realclean disttest distdir + + + +# --- MakeMaker c_o section: + + +# --- MakeMaker xs_c section: + + +# --- MakeMaker xs_o section: + + +# --- MakeMaker top_targets section: +all :: pure_all manifypods + $(NOECHO) $(NOOP) + + +pure_all :: config pm_to_blib subdirs linkext + $(NOECHO) $(NOOP) + +subdirs :: $(MYEXTLIB) + $(NOECHO) $(NOOP) + +config :: $(FIRST_MAKEFILE) blibdirs + $(NOECHO) $(NOOP) + +help : + perldoc ExtUtils::MakeMaker + + +# --- MakeMaker blibdirs section: +blibdirs : $(INST_LIBDIR)$(DFSEP).exists $(INST_ARCHLIB)$(DFSEP).exists $(INST_AUTODIR)$(DFSEP).exists $(INST_ARCHAUTODIR)$(DFSEP).exists $(INST_BIN)$(DFSEP).exists $(INST_SCRIPT)$(DFSEP).exists $(INST_MAN1DIR)$(DFSEP).exists $(INST_MAN3DIR)$(DFSEP).exists + $(NOECHO) $(NOOP) + +# Backwards compat with 6.18 through 6.25 +blibdirs.ts : blibdirs + $(NOECHO) $(NOOP) + +$(INST_LIBDIR)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_LIBDIR) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_LIBDIR) + $(NOECHO) $(TOUCH) $(INST_LIBDIR)$(DFSEP).exists + +$(INST_ARCHLIB)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_ARCHLIB) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_ARCHLIB) + $(NOECHO) $(TOUCH) $(INST_ARCHLIB)$(DFSEP).exists + +$(INST_AUTODIR)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_AUTODIR) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_AUTODIR) + $(NOECHO) $(TOUCH) $(INST_AUTODIR)$(DFSEP).exists + +$(INST_ARCHAUTODIR)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_ARCHAUTODIR) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_ARCHAUTODIR) + $(NOECHO) $(TOUCH) $(INST_ARCHAUTODIR)$(DFSEP).exists + +$(INST_BIN)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_BIN) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_BIN) + $(NOECHO) $(TOUCH) $(INST_BIN)$(DFSEP).exists + +$(INST_SCRIPT)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_SCRIPT) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_SCRIPT) + $(NOECHO) $(TOUCH) $(INST_SCRIPT)$(DFSEP).exists + +$(INST_MAN1DIR)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_MAN1DIR) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_MAN1DIR) + $(NOECHO) $(TOUCH) $(INST_MAN1DIR)$(DFSEP).exists + +$(INST_MAN3DIR)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_MAN3DIR) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_MAN3DIR) + $(NOECHO) $(TOUCH) $(INST_MAN3DIR)$(DFSEP).exists + + + +# --- MakeMaker linkext section: + +linkext :: $(LINKTYPE) + $(NOECHO) $(NOOP) + + +# --- MakeMaker dlsyms section: + + +# --- MakeMaker dynamic_bs section: + +BOOTSTRAP = + + +# --- MakeMaker dynamic section: + +dynamic :: $(FIRST_MAKEFILE) $(BOOTSTRAP) $(INST_DYNAMIC) + $(NOECHO) $(NOOP) + + +# --- MakeMaker dynamic_lib section: + + +# --- MakeMaker static section: + +## $(INST_PM) has been moved to the all: target. +## It remains here for awhile to allow for old usage: "make static" +static :: $(FIRST_MAKEFILE) $(INST_STATIC) + $(NOECHO) $(NOOP) + + +# --- MakeMaker static_lib section: + + +# --- MakeMaker manifypods section: + +POD2MAN_EXE = $(PERLRUN) "-MExtUtils::Command::MM" -e pod2man "--" +POD2MAN = $(POD2MAN_EXE) + + +manifypods : pure_all \ + mwx.pm + $(NOECHO) $(POD2MAN) --section=$(MAN3EXT) --perm_rw=$(PERM_RW) -u \ + mwx.pm $(INST_MAN3DIR)/mwx.$(MAN3EXT) + + + + +# --- MakeMaker processPL section: + + +# --- MakeMaker installbin section: + + +# --- MakeMaker subdirs section: + +# none + +# --- MakeMaker clean_subdirs section: +clean_subdirs : + $(NOECHO) $(NOOP) + + +# --- MakeMaker clean section: + +# Delete temporary files but do not touch installed files. We don't delete +# the Makefile here so a later make realclean still has a makefile to use. + +clean :: clean_subdirs + - $(RM_F) \ + $(BASEEXT).bso $(BASEEXT).def \ + $(BASEEXT).exp $(BASEEXT).x \ + $(BOOTSTRAP) $(INST_ARCHAUTODIR)/extralibs.all \ + $(INST_ARCHAUTODIR)/extralibs.ld $(MAKE_APERL_FILE) \ + *$(LIB_EXT) *$(OBJ_EXT) \ + *perl.core MYMETA.json \ + MYMETA.yml blibdirs.ts \ + core core.*perl.*.? \ + core.[0-9] core.[0-9][0-9] \ + core.[0-9][0-9][0-9] core.[0-9][0-9][0-9][0-9] \ + core.[0-9][0-9][0-9][0-9][0-9] lib$(BASEEXT).def \ + mon.out perl \ + perl$(EXE_EXT) perl.exe \ + perlmain.c pm_to_blib \ + pm_to_blib.ts so_locations \ + tmon.out + - $(RM_RF) \ + blib + $(NOECHO) $(RM_F) $(MAKEFILE_OLD) + - $(MV) $(FIRST_MAKEFILE) $(MAKEFILE_OLD) $(DEV_NULL) + + +# --- MakeMaker realclean_subdirs section: +realclean_subdirs : + $(NOECHO) $(NOOP) + + +# --- MakeMaker realclean section: +# Delete temporary files (via clean) and also delete dist files +realclean purge :: clean realclean_subdirs + - $(RM_F) \ + $(MAKEFILE_OLD) $(FIRST_MAKEFILE) + - $(RM_RF) \ + $(DISTVNAME) + + +# --- MakeMaker metafile section: +metafile : create_distdir + $(NOECHO) $(ECHO) Generating META.yml + $(NOECHO) $(ECHO) '---' > META_new.yml + $(NOECHO) $(ECHO) 'abstract: '\''mikes perl tools'\''' >> META_new.yml + $(NOECHO) $(ECHO) 'author:' >> META_new.yml + $(NOECHO) $(ECHO) ' - '\''M.Wesemann '\''' >> META_new.yml + $(NOECHO) $(ECHO) 'build_requires:' >> META_new.yml + $(NOECHO) $(ECHO) ' ExtUtils::MakeMaker: '\''0'\''' >> META_new.yml + $(NOECHO) $(ECHO) 'configure_requires:' >> META_new.yml + $(NOECHO) $(ECHO) ' ExtUtils::MakeMaker: '\''0'\''' >> META_new.yml + $(NOECHO) $(ECHO) 'dynamic_config: 1' >> META_new.yml + $(NOECHO) $(ECHO) 'generated_by: '\''ExtUtils::MakeMaker version 7.0401, CPAN::Meta::Converter version 2.150001'\''' >> META_new.yml + $(NOECHO) $(ECHO) 'license: unknown' >> META_new.yml + $(NOECHO) $(ECHO) 'meta-spec:' >> META_new.yml + $(NOECHO) $(ECHO) ' url: http://module-build.sourceforge.net/META-spec-v1.4.html' >> META_new.yml + $(NOECHO) $(ECHO) ' version: '\''1.4'\''' >> META_new.yml + $(NOECHO) $(ECHO) 'name: mwx' >> META_new.yml + $(NOECHO) $(ECHO) 'no_index:' >> META_new.yml + $(NOECHO) $(ECHO) ' directory:' >> META_new.yml + $(NOECHO) $(ECHO) ' - t' >> META_new.yml + $(NOECHO) $(ECHO) ' - inc' >> META_new.yml + $(NOECHO) $(ECHO) 'requires:' >> META_new.yml + $(NOECHO) $(ECHO) ' MD5: '\''0'\''' >> META_new.yml + $(NOECHO) $(ECHO) ' Math::BigInt: '\''0'\''' >> META_new.yml + $(NOECHO) $(ECHO) ' Net::NIS: '\''0'\''' >> META_new.yml + $(NOECHO) $(ECHO) ' Net::SMTP: '\''0'\''' >> META_new.yml + $(NOECHO) $(ECHO) ' Term::ReadKey: '\''0'\''' >> META_new.yml + $(NOECHO) $(ECHO) ' Time::HiRes: '\''0'\''' >> META_new.yml + $(NOECHO) $(ECHO) 'version: '\''1.21'\''' >> META_new.yml + -$(NOECHO) $(MV) META_new.yml $(DISTVNAME)/META.yml + $(NOECHO) $(ECHO) Generating META.json + $(NOECHO) $(ECHO) '{' > META_new.json + $(NOECHO) $(ECHO) ' "abstract" : "mikes perl tools",' >> META_new.json + $(NOECHO) $(ECHO) ' "author" : [' >> META_new.json + $(NOECHO) $(ECHO) ' "M.Wesemann "' >> META_new.json + $(NOECHO) $(ECHO) ' ],' >> META_new.json + $(NOECHO) $(ECHO) ' "dynamic_config" : 1,' >> META_new.json + $(NOECHO) $(ECHO) ' "generated_by" : "ExtUtils::MakeMaker version 7.0401, CPAN::Meta::Converter version 2.150001",' >> META_new.json + $(NOECHO) $(ECHO) ' "license" : [' >> META_new.json + $(NOECHO) $(ECHO) ' "unknown"' >> META_new.json + $(NOECHO) $(ECHO) ' ],' >> META_new.json + $(NOECHO) $(ECHO) ' "meta-spec" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",' >> META_new.json + $(NOECHO) $(ECHO) ' "version" : "2"' >> META_new.json + $(NOECHO) $(ECHO) ' },' >> META_new.json + $(NOECHO) $(ECHO) ' "name" : "mwx",' >> META_new.json + $(NOECHO) $(ECHO) ' "no_index" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "directory" : [' >> META_new.json + $(NOECHO) $(ECHO) ' "t",' >> META_new.json + $(NOECHO) $(ECHO) ' "inc"' >> META_new.json + $(NOECHO) $(ECHO) ' ]' >> META_new.json + $(NOECHO) $(ECHO) ' },' >> META_new.json + $(NOECHO) $(ECHO) ' "prereqs" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "build" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "requires" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "ExtUtils::MakeMaker" : "0"' >> META_new.json + $(NOECHO) $(ECHO) ' }' >> META_new.json + $(NOECHO) $(ECHO) ' },' >> META_new.json + $(NOECHO) $(ECHO) ' "configure" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "requires" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "ExtUtils::MakeMaker" : "0"' >> META_new.json + $(NOECHO) $(ECHO) ' }' >> META_new.json + $(NOECHO) $(ECHO) ' },' >> META_new.json + $(NOECHO) $(ECHO) ' "runtime" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "requires" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "MD5" : "0",' >> META_new.json + $(NOECHO) $(ECHO) ' "Math::BigInt" : "0",' >> META_new.json + $(NOECHO) $(ECHO) ' "Net::NIS" : "0",' >> META_new.json + $(NOECHO) $(ECHO) ' "Net::SMTP" : "0",' >> META_new.json + $(NOECHO) $(ECHO) ' "Term::ReadKey" : "0",' >> META_new.json + $(NOECHO) $(ECHO) ' "Time::HiRes" : "0"' >> META_new.json + $(NOECHO) $(ECHO) ' }' >> META_new.json + $(NOECHO) $(ECHO) ' }' >> META_new.json + $(NOECHO) $(ECHO) ' },' >> META_new.json + $(NOECHO) $(ECHO) ' "release_status" : "stable",' >> META_new.json + $(NOECHO) $(ECHO) ' "version" : "1.21"' >> META_new.json + $(NOECHO) $(ECHO) '}' >> META_new.json + -$(NOECHO) $(MV) META_new.json $(DISTVNAME)/META.json + + +# --- MakeMaker signature section: +signature : + cpansign -s + + +# --- MakeMaker dist_basics section: +distclean :: realclean distcheck + $(NOECHO) $(NOOP) + +distcheck : + $(PERLRUN) "-MExtUtils::Manifest=fullcheck" -e fullcheck + +skipcheck : + $(PERLRUN) "-MExtUtils::Manifest=skipcheck" -e skipcheck + +manifest : + $(PERLRUN) "-MExtUtils::Manifest=mkmanifest" -e mkmanifest + +veryclean : realclean + $(RM_F) *~ */*~ *.orig */*.orig *.bak */*.bak *.old */*.old + + + +# --- MakeMaker dist_core section: + +dist : $(DIST_DEFAULT) $(FIRST_MAKEFILE) + $(NOECHO) $(ABSPERLRUN) -l -e 'print '\''Warning: Makefile possibly out of date with $(VERSION_FROM)'\''' \ + -e ' if -e '\''$(VERSION_FROM)'\'' and -M '\''$(VERSION_FROM)'\'' < -M '\''$(FIRST_MAKEFILE)'\'';' -- + +tardist : $(DISTVNAME).tar$(SUFFIX) + $(NOECHO) $(NOOP) + +uutardist : $(DISTVNAME).tar$(SUFFIX) + uuencode $(DISTVNAME).tar$(SUFFIX) $(DISTVNAME).tar$(SUFFIX) > $(DISTVNAME).tar$(SUFFIX)_uu + $(NOECHO) $(ECHO) 'Created $(DISTVNAME).tar$(SUFFIX)_uu' + +$(DISTVNAME).tar$(SUFFIX) : distdir + $(PREOP) + $(TO_UNIX) + $(TAR) $(TARFLAGS) $(DISTVNAME).tar $(DISTVNAME) + $(RM_RF) $(DISTVNAME) + $(COMPRESS) $(DISTVNAME).tar + $(NOECHO) $(ECHO) 'Created $(DISTVNAME).tar$(SUFFIX)' + $(POSTOP) + +zipdist : $(DISTVNAME).zip + $(NOECHO) $(NOOP) + +$(DISTVNAME).zip : distdir + $(PREOP) + $(ZIP) $(ZIPFLAGS) $(DISTVNAME).zip $(DISTVNAME) + $(RM_RF) $(DISTVNAME) + $(NOECHO) $(ECHO) 'Created $(DISTVNAME).zip' + $(POSTOP) + +shdist : distdir + $(PREOP) + $(SHAR) $(DISTVNAME) > $(DISTVNAME).shar + $(RM_RF) $(DISTVNAME) + $(NOECHO) $(ECHO) 'Created $(DISTVNAME).shar' + $(POSTOP) + + +# --- MakeMaker distdir section: +create_distdir : + $(RM_RF) $(DISTVNAME) + $(PERLRUN) "-MExtUtils::Manifest=manicopy,maniread" \ + -e "manicopy(maniread(),'$(DISTVNAME)', '$(DIST_CP)');" + +distdir : create_distdir distmeta + $(NOECHO) $(NOOP) + + + +# --- MakeMaker dist_test section: +disttest : distdir + cd $(DISTVNAME) && $(ABSPERLRUN) Makefile.PL + cd $(DISTVNAME) && $(MAKE) $(PASTHRU) + cd $(DISTVNAME) && $(MAKE) test $(PASTHRU) + + + +# --- MakeMaker dist_ci section: + +ci : + $(PERLRUN) "-MExtUtils::Manifest=maniread" \ + -e "@all = keys %{ maniread() };" \ + -e "print(qq{Executing $(CI) @all\n}); system(qq{$(CI) @all});" \ + -e "print(qq{Executing $(RCS_LABEL) ...\n}); system(qq{$(RCS_LABEL) @all});" + + +# --- MakeMaker distmeta section: +distmeta : create_distdir metafile + $(NOECHO) cd $(DISTVNAME) && $(ABSPERLRUN) -MExtUtils::Manifest=maniadd -e 'exit unless -e q{META.yml};' \ + -e 'eval { maniadd({q{META.yml} => q{Module YAML meta-data (added by MakeMaker)}}) }' \ + -e ' or print "Could not add META.yml to MANIFEST: $$$${'\''@'\''}\n"' -- + $(NOECHO) cd $(DISTVNAME) && $(ABSPERLRUN) -MExtUtils::Manifest=maniadd -e 'exit unless -f q{META.json};' \ + -e 'eval { maniadd({q{META.json} => q{Module JSON meta-data (added by MakeMaker)}}) }' \ + -e ' or print "Could not add META.json to MANIFEST: $$$${'\''@'\''}\n"' -- + + + +# --- MakeMaker distsignature section: +distsignature : create_distdir + $(NOECHO) cd $(DISTVNAME) && $(ABSPERLRUN) -MExtUtils::Manifest=maniadd -e 'eval { maniadd({q{SIGNATURE} => q{Public-key signature (added by MakeMaker)}}) }' \ + -e ' or print "Could not add SIGNATURE to MANIFEST: $$$${'\''@'\''}\n"' -- + $(NOECHO) cd $(DISTVNAME) && $(TOUCH) SIGNATURE + cd $(DISTVNAME) && cpansign -s + + + +# --- MakeMaker install section: + +install :: pure_install doc_install + $(NOECHO) $(NOOP) + +install_perl :: pure_perl_install doc_perl_install + $(NOECHO) $(NOOP) + +install_site :: pure_site_install doc_site_install + $(NOECHO) $(NOOP) + +install_vendor :: pure_vendor_install doc_vendor_install + $(NOECHO) $(NOOP) + +pure_install :: pure_$(INSTALLDIRS)_install + $(NOECHO) $(NOOP) + +doc_install :: doc_$(INSTALLDIRS)_install + $(NOECHO) $(NOOP) + +pure__install : pure_site_install + $(NOECHO) $(ECHO) INSTALLDIRS not defined, defaulting to INSTALLDIRS=site + +doc__install : doc_site_install + $(NOECHO) $(ECHO) INSTALLDIRS not defined, defaulting to INSTALLDIRS=site + +pure_perl_install :: all + $(NOECHO) umask 022; $(MOD_INSTALL) \ + "$(INST_LIB)" "$(DESTINSTALLPRIVLIB)" \ + "$(INST_ARCHLIB)" "$(DESTINSTALLARCHLIB)" \ + "$(INST_BIN)" "$(DESTINSTALLBIN)" \ + "$(INST_SCRIPT)" "$(DESTINSTALLSCRIPT)" \ + "$(INST_MAN1DIR)" "$(DESTINSTALLMAN1DIR)" \ + "$(INST_MAN3DIR)" "$(DESTINSTALLMAN3DIR)" + $(NOECHO) $(WARN_IF_OLD_PACKLIST) \ + "$(SITEARCHEXP)/auto/$(FULLEXT)" + + +pure_site_install :: all + $(NOECHO) umask 02; $(MOD_INSTALL) \ + read "$(SITEARCHEXP)/auto/$(FULLEXT)/.packlist" \ + write "$(DESTINSTALLSITEARCH)/auto/$(FULLEXT)/.packlist" \ + "$(INST_LIB)" "$(DESTINSTALLSITELIB)" \ + "$(INST_ARCHLIB)" "$(DESTINSTALLSITEARCH)" \ + "$(INST_BIN)" "$(DESTINSTALLSITEBIN)" \ + "$(INST_SCRIPT)" "$(DESTINSTALLSITESCRIPT)" \ + "$(INST_MAN1DIR)" "$(DESTINSTALLSITEMAN1DIR)" \ + "$(INST_MAN3DIR)" "$(DESTINSTALLSITEMAN3DIR)" + $(NOECHO) $(WARN_IF_OLD_PACKLIST) \ + "$(PERL_ARCHLIB)/auto/$(FULLEXT)" + +pure_vendor_install :: all + $(NOECHO) umask 022; $(MOD_INSTALL) \ + "$(INST_LIB)" "$(DESTINSTALLVENDORLIB)" \ + "$(INST_ARCHLIB)" "$(DESTINSTALLVENDORARCH)" \ + "$(INST_BIN)" "$(DESTINSTALLVENDORBIN)" \ + "$(INST_SCRIPT)" "$(DESTINSTALLVENDORSCRIPT)" \ + "$(INST_MAN1DIR)" "$(DESTINSTALLVENDORMAN1DIR)" \ + "$(INST_MAN3DIR)" "$(DESTINSTALLVENDORMAN3DIR)" + + +doc_perl_install :: all + +doc_site_install :: all + $(NOECHO) $(ECHO) Appending installation info to "$(DESTINSTALLSITEARCH)/perllocal.pod" + -$(NOECHO) umask 02; $(MKPATH) "$(DESTINSTALLSITEARCH)" + -$(NOECHO) umask 02; $(DOC_INSTALL) \ + "Module" "$(NAME)" \ + "installed into" $(INSTALLSITELIB) \ + LINKTYPE "$(LINKTYPE)" \ + VERSION "$(VERSION)" \ + EXE_FILES "$(EXE_FILES)" \ + >> "$(DESTINSTALLSITEARCH)/perllocal.pod" + +doc_vendor_install :: all + + +uninstall :: uninstall_from_$(INSTALLDIRS)dirs + $(NOECHO) $(NOOP) + +uninstall_from_perldirs :: + +uninstall_from_sitedirs :: + $(NOECHO) $(UNINSTALL) "$(SITEARCHEXP)/auto/$(FULLEXT)/.packlist" + +uninstall_from_vendordirs :: + + +# --- MakeMaker force section: +# Phony target to force checking subdirectories. +FORCE : + $(NOECHO) $(NOOP) + + +# --- MakeMaker perldepend section: + + +# --- MakeMaker makefile section: +# We take a very conservative approach here, but it's worth it. +# We move Makefile to Makefile.old here to avoid gnu make looping. +$(FIRST_MAKEFILE) : Makefile.PL $(CONFIGDEP) + $(NOECHO) $(ECHO) "Makefile out-of-date with respect to $?" + $(NOECHO) $(ECHO) "Cleaning current config before rebuilding Makefile..." + -$(NOECHO) $(RM_F) $(MAKEFILE_OLD) + -$(NOECHO) $(MV) $(FIRST_MAKEFILE) $(MAKEFILE_OLD) + - $(MAKE) $(USEMAKEFILE) $(MAKEFILE_OLD) clean $(DEV_NULL) + $(PERLRUN) Makefile.PL + $(NOECHO) $(ECHO) "==> Your Makefile has been rebuilt. <==" + $(NOECHO) $(ECHO) "==> Please rerun the $(MAKE) command. <==" + $(FALSE) + + + +# --- MakeMaker staticmake section: + +# --- MakeMaker makeaperl section --- +MAP_TARGET = perl +FULLPERL = "/usr/bin/perl" + +$(MAP_TARGET) :: static $(MAKE_APERL_FILE) + $(MAKE) $(USEMAKEFILE) $(MAKE_APERL_FILE) $@ + +$(MAKE_APERL_FILE) : $(FIRST_MAKEFILE) pm_to_blib + $(NOECHO) $(ECHO) Writing \"$(MAKE_APERL_FILE)\" for this $(MAP_TARGET) + $(NOECHO) $(PERLRUNINST) \ + Makefile.PL DIR="" \ + MAKEFILE=$(MAKE_APERL_FILE) LINKTYPE=static \ + MAKEAPERL=1 NORECURS=1 CCCDLFLAGS= + + +# --- MakeMaker test section: + +TEST_VERBOSE=0 +TEST_TYPE=test_$(LINKTYPE) +TEST_FILE = test.pl +TEST_FILES = +TESTDB_SW = -d + +testdb :: testdb_$(LINKTYPE) + +test :: $(TEST_TYPE) subdirs-test + +subdirs-test :: + $(NOECHO) $(NOOP) + + +test_dynamic :: pure_all + PERL_DL_NONLAZY=1 $(FULLPERLRUN) "-I$(INST_LIB)" "-I$(INST_ARCHLIB)" $(TEST_FILE) + +testdb_dynamic :: pure_all + PERL_DL_NONLAZY=1 $(FULLPERLRUN) $(TESTDB_SW) "-I$(INST_LIB)" "-I$(INST_ARCHLIB)" $(TEST_FILE) + +test_ : test_dynamic + +test_static :: test_dynamic +testdb_static :: testdb_dynamic + + +# --- MakeMaker ppd section: +# Creates a PPD (Perl Package Description) for a binary distribution. +ppd : + $(NOECHO) $(ECHO) '' > $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' mikes perl tools' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' M.Wesemann <mwx@gmx.de>' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) '' >> $(DISTNAME).ppd + + +# --- MakeMaker pm_to_blib section: + +pm_to_blib : $(FIRST_MAKEFILE) $(TO_INST_PM) + $(NOECHO) $(ABSPERLRUN) -MExtUtils::Install -e 'pm_to_blib({@ARGV}, '\''$(INST_LIB)/auto'\'', q[$(PM_FILTER)], '\''$(PERM_DIR)'\'')' -- \ + mwx.pm $(INST_LIB)/mwx.pm + $(NOECHO) $(TOUCH) pm_to_blib + + +# --- MakeMaker selfdocument section: + + +# --- MakeMaker postamble section: + + +# End. diff --git a/perlmodules/mwx-1.21/README b/perlmodules/mwx-1.21/README new file mode 100644 index 0000000..624a1af --- /dev/null +++ b/perlmodules/mwx-1.21/README @@ -0,0 +1,35 @@ +mwx version 0.01 +================ + +The README is used to introduce the module and provide instructions on +how to install the module, any machine dependencies it may have (for +example C compilers and installed libraries) and any other information +that should be provided before the module is installed. + +A README file is required for CPAN modules since CPAN extracts the +README file from a module distribution so that people browsing the +archive can use it get an idea of the modules uses. It is usually a +good idea to provide version information here so that people can +decide whether fixes for the module are worth downloading. + +INSTALLATION + +To install this module type the following: + + perl Makefile.PL + make + make test + make install + +DEPENDENCIES + +This module requires these other modules and libraries: + + blah blah blah + +COPYRIGHT AND LICENCE + +Put the correct copyright and licence information here. + +Copyright (C) 2003 A. U. Thor blah blah blah + diff --git a/perlmodules/mwx-1.21/mwx.pm b/perlmodules/mwx-1.21/mwx.pm new file mode 100644 index 0000000..f60680f --- /dev/null +++ b/perlmodules/mwx-1.21/mwx.pm @@ -0,0 +1,281 @@ +######################################### mikes perl tools (mwx,11.09.03) ##### +package mwx; + +use 5.006; +use strict; +use warnings; + +require Exporter; +use AutoLoader qw(AUTOLOAD); + +our $VERSION = '1.21'; + +our @ISA = qw(Exporter); +our %EXPORT_TAGS = ( 'all' => [ qw( ) ] ); +our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); + +our @EXPORT = qw( + sendmail + md5 + gnfip + tosql + tsd + fsd + mkdatequery + mknumquery + mkquery + uniqid + shortstr +); + +################################################################### TOOLS ##### + +sub sendmail { ##### send mail ##### + my($from,$to,$subject,$message,$server)=@_; + use Net::SMTP; + my($smtp)=Net::SMTP->new("mail",Debug=>0); + $smtp->mail("<$from>"); + $smtp->recipient($to);$smtp->data(); + $smtp->datasend("To: $to\n"); + $smtp->datasend("From: $from\n"); + $smtp->datasend("Subject: $subject\n"); + $smtp->datasend("$message\n"); + $smtp->dataend(); + $smtp->quit(); +} + +sub md5() { ##### calculate md5 checksum ##### + my($file)=@_; + use Digest::MD5; + open(FILE,$file);binmode(FILE); + my($md5)=Digest::MD5->new->addfile(*FILE)->hexdigest; + close(FILE); + return($md5); +} + +sub gnfip { ##### find hostname for given IP (bug fixed version) ##### + my($ip)=@_; + use Net::DNS; + if ($ip!~/\d+\.\d+\.\d+\.\d+/) {;return $ip;} + my($res) = new Net::DNS::Resolver; + my($query)=$res->query($ip); + if ($query) { + for ($query->answer) { + if ($_->type eq 'PTR') { + my($ip)=$_->ptrdname; + return("$ip"); + } + } + } + else {;return("$ip");} +} + +sub tosql { ##### convert string for SQL ##### + my($str)=@_;my($a)="'";my($b)="`";if(!defined($str)) {;$str="";} + $str=~s/$b/$a$a/g;$str=~s/$a/$a$a/g;$str=~s/\s*$//g;$str=~s/^\s*//g; + return $str; +} + +sub tsd { ##### format date/time to MySQL date/time ##### + my($tmp)=@_;my($y); + $tmp=~s/^\s*//;$tmp=~s/\s*$//;$tmp=~s/\s+/ / ; + if ($tmp=~/^(\d+)\.(\d+)\.(\d+)\s+(\d+)\:(\d+)$/) { + $y=$3;if ($3>=0 && $3<100) {;$y=$3+2000;} + return sprintf("%04d-%02d-%02d %02d:%02d",$y,$2,$1,$4,$5); + } + if ($tmp=~/^(\d+)\.(\d+)\.(\d+)\s+(\d+)\:(\d+)\:(\d+)$/) { + $y=$3;if ($3>=0 && $3<100) {;$y=$3+2000;} + return sprintf("%04d-%02d-%02d %02d:%02d:%02d",$y,$2,$1,$4,$5,$6); + } + elsif ($tmp=~/^(\d+)\.(\d+)\.(\d+)$/) { + $y=$3;if ($3>=0 && $3<100) {;$y=$3+2000;} + return sprintf("%04d-%02d-%02d",$y,$2,$1); + } + elsif ($tmp=~/^(\d+)\:(\d+)$/) { + return sprintf("%02d:%02d",$1,$2); + } + else {;return("");} +} + +sub fsd { ########################### format MySQL date/time to date/time ##### + my($tmp,$mode)=@_;if (!defined($mode)) {;$mode="";} + $tmp=~s/^\s*//;$tmp=~s/\s*$//;$tmp=~s/\s+/ / ; + if ($tmp=~/(\d+)\-(\d+)\-(\d+)\s+(\d+)\:(\d+)\:(\d+)/) { + if ($tmp eq '0000-00-00 00:00:00') {;return("");} + if ($mode eq 'date') { + return sprintf("%d\.%d\.%04d",$3,$2,$1); + } + elsif ($mode eq 'time') { + return sprintf("%d\:%02d",$4,$5); + } + else { + return sprintf("%d\.%d\.%04d %d\:%02d",$3,$2,$1,$4,$5); + } + } + elsif ($tmp=~/(\d+)\-(\d+)\-(\d+)/) { + if ($tmp eq '0000-00-00' || $mode eq 'time') {;return("");} + return sprintf("%d\.%d\.%04d",$3,$2,$1); + } + if ($tmp=~/(\d+)\:(\d+)\:(\d+)/) { + if ($mode eq 'date') {;return("");} + return sprintf("%d\:%02d",$1,$2); + } + else {;return("");} +} + +sub mkdatequery { ###################### make query string for date range ##### + my($datestr,$field)=@_; + my(@list)=split(",",$datestr); + my($tmp)="";my($da,$db); + for (@list) { + if (/^\s*([^\s]+)\s*\-\s*([^\s]+)\s*$/) { + $da=$1;$db=$2; + $da=~s/(\d+)\.(\d+)\.(\d+)/$3\-$2\-$1/; + $db=~s/(\d+)\.(\d+)\.(\d+)/$3\-$2\-$1/; + $tmp.=" $field BETWEEN '$da' AND '$db' OR "; + } + elsif (/^\s*([\>\<])\s*(.*)/) { + $da=$1;$db=$2;$db=~s/(\d+)\.(\d+)\.(\d+)/$3\-$2\-$1/; + $tmp.=" $field $da '$db' OR "; + } + elsif (/^\s*\-(\d+)$/) { + $tmp.=" UNIX_TIMESTAMP($field)>UNIX_TIMESTAMP(now())-(86400*$1) OR "; + } + elsif (/^\s*([^\s]+)\s*$/) { + $da=$1;$da=~s/(\d+)\.(\d+)\.(\d+)/$3\-$2\-$1/; + $tmp.=" $field='$da' OR "; + } + } + $tmp=~s/\s*or\s*$//i;$tmp=~s/^\s//i;$tmp=~s/\s+/ /g; + if ($tmp=~/^\s*$/) {;return "";} + return "($tmp)"; +} + +sub mknumquery { ##################### make query string for number range ##### + my($numstr,$field)=@_; + my($tmp)=""; + my(@list)=split(",",$numstr); + for (@list) { + if (/^\s*(\d+)\s*\-\s*(\d+)\s*$/) { + $tmp.=" $field BETWEEN $1 AND $2 OR "; + } + elsif (/^\s*([\>\<])\s*(\d+)/) { + $tmp.=" $field $1 $2 OR "; + } + elsif (/^\s*(\d+)\s*$/) { + $tmp.=" $field=$1 OR "; + } + } + $tmp=~s/\s*or\s*$//i;$tmp=~s/^\s//i;$tmp=~s/\s+/ /g; + return "($tmp)"; +} + +sub mkquery { ############################### make query string for field ##### + my($query,$mode,@fields)=@_;if (!defined($query)) {;$query="";} + my(@list,$tmp,$field,@field); + use Text::ParseWords; + + $query=~s/\s*\(\s*/ \( /g;$query=~s/\s*\)\s*/ \) /g; + @list="ewords(' ',0,$query); + $query=""; + my($notflag)=0; + for (@list) { + if (!/^\s*and\s*$/i && !/^\s*or\s*$/i && + !/^\s*andnot\s*$/i && !/^\s*ornot\s*$/i && + !/^\s*\(\s*$/ && !/^\s*\)\s*$/ && !/^\s*$/) { + s/^\s*\'//;s/\'\s*$//; + + if ($query=~/\)\s*$/) {;$query.=" AND (";} + else {;$query.="(";} + for $field (@fields) { + $tmp=$_;if($mode==1) {;$tmp=" $_ ";} + if ($notflag) {;$query.=" NOT($field LIKE '%$tmp%') ";$notflag=0;} + else {;$query.=" $field LIKE '%$tmp%' ";} + $query.="OR "; + } + $query=~s/\s*or\s*$/\)/i; + } + else { + if ($_=~/^\s*andnot\s*$/i) {;$query.=" AND ";$notflag=1;} + elsif ($_=~/^\s*andnot\s*$/i) {;$query.=" OR ";$notflag=1;} + else {;$query.=" $_ ";} + } + + } + return $query; +} + + +sub base62() { ################################################### Base62 ##### + my($s)=@_; + my(@c)=('0'..'9','a'..'z','A'..'Z'); + my(@p,$u,$v,$i,$n); + my($m)=20; + $p[0]=1; + for $i (1..$m) { + $p[$i]=Math::BigInt->new($p[$i-1]); + $p[$i]=$p[$i]->bmul(62); + } + + $v=Math::BigInt->new($s); + for ($i=$m;$i>=0;$i--) { + $v=Math::BigInt->new($v); + ($n,$v)=$v->bdiv($p[$i]); + $u.=$c[$n]; + } + $u=~s/^0+//; + + return($u); +} + +sub uniqid { ############################################## get unique id ##### + use Math::BigInt; + use Sys::Hostname; + use Time::HiRes qw( gettimeofday usleep ); + my($s,$us)=gettimeofday(); + my($ia,$ib,$ic,$id)=unpack("C4", (gethostbyname(hostname()))[4]); + my($v)=sprintf("%06d%10d%06d%03d%03d%03d%03d",$us,$s,$$,$ia,$ib,$ic,$id); + return(&base62($v)); +} + +sub shortstr() { ########################### make short string with '...' ##### + my($str,$len)=@_; + if (length($str)>$len) { + my($tmp)=substr($str,0,$len-3) . "..."; + return $tmp; + } else {;return ($str);} +} + +##################################################################### END ##### +1; +__END__ + +=head1 NAME + +mwx - mikes perl tools + +=head1 SYNOPSIS + + use mwx; + + sendmail($from,$to,$subject,$message,$server); + + $md5 = md5($file); + + $name = gnfip($ip); + + $str = tosql($str); + $sqldate = tsd($date); + $date = fsd($date); + + $subsql = mkdatequery($datestr,$columnname); + $subsql = mknumquery($numstr,$columnname); + $subsql = mkquery($querystr,$mode,@columnnames); + + $id = uniqid(); + +=head1 AUTHOR + +Mike Wesemann, Emwx@gmx.deE + +=cut diff --git a/perlmodules/mwx-1.21/test.pl b/perlmodules/mwx-1.21/test.pl new file mode 100644 index 0000000..0d39eb8 --- /dev/null +++ b/perlmodules/mwx-1.21/test.pl @@ -0,0 +1,45 @@ +use Test; +BEGIN { plan tests => 25 }; +use mwx; +use strict; +#&sendmail('mike@fhi-berlin.mpg.de','mike@fhi-berlin.mpg.de','test','MSG','mail'); + +ok(&md5('Makefile.PL'),'a37560d14c32201defbecaa17f23628c'); + +ok(&fsd('2000-10-18 09:54:01'),'18.10.2000 9:54'); +ok(&fsd('0000-00-00 00:00:00'),''); +ok(&fsd('1999-09-19'),'19.9.1999'); +ok(&fsd('0000-00-00'),''); +ok(&fsd('08:53:02'),'8:53'); +ok(&fsd('00:00:00'),'0:00'); +ok(&fsd('2000-10-18 09:54:01','date'),'18.10.2000'); +ok(&fsd('2000-10-18 09:54:01','time'),'9:54'); +ok(&tsd('23.12.2002'),'2002-12-23'); +ok(&tsd('24.11.2001 14:12'),'2001-11-24 14:12'); +ok(&tsd('24.11.2001 14:12:23'),'2001-11-24 14:12:23'); +ok(&tsd('0:1'),'00:01'); + +ok(&gnfip('141.14.141.141'),'root.RZ-Berlin.MPG.DE'); + +ok(&mkdatequery("1.1.2002 , 2.2.2003","date"), + "(date='2002-1-1' OR date='2003-2-2')"); +ok(&mkdatequery("1.11.2002 - 7.11.2002","date"), + "(date BETWEEN '2002-11-1' AND '2002-11-7')"); +ok(&mkdatequery("> 1.11.2002","date"),"(date > '2002-11-1')"); + +ok(&mknumquery(" 2 - 5 ","number"),"(number BETWEEN 2 AND 5)"); +ok(&mknumquery("11,22 ,33","number"),"(number=11 OR number=22 OR number=33)"); + +ok(&mkquery("tee or cafe",0,'string'), + "( string LIKE '%tee%') or ( string LIKE '%cafe%')"); +ok(&mkquery("'tee or cafe'",0,'string'),"( string LIKE '%tee or cafe%')"); + +ok(&tosql(' test '),'test'); +ok(&tosql("a'b"),"a''b"); + +ok(&shortstr('0123456789',10),'0123456789'); +ok(&shortstr('0123456789',8),'01234...'); + +print &uniqid() . " " . &uniqid() . " " . &uniqid() . "\n"; + + diff --git a/restic.config.enc b/restic.config.enc new file mode 100644 index 0000000..aabe94f --- /dev/null +++ b/restic.config.enc @@ -0,0 +1,6 @@ +U2FsdGVkX1/vb68X/pAIz5XudakFRxh3wBUxNJqWFNOcltEXfbxxegN6PXyHIii+ +yGlQS5zfmPNuZNds7WIE+5E8ah2qemwTLBIidMjxI7Iq0GfJkX5SS6QOAt3Bhxa6 +bsqVjf7keGXKWIc7kIu3AnwQlz+qgkW99WFLJ5MYrd60ePYQ9uAf7foIVdNs/fmz +a47jbHeDDteilzQBSJgiYhhY7Tdc/vOzuAzOXImEX3OG4FyGj90+SMgLnkrIJUOv +4wFpNz4NPXq9rIiav6z/gOblLze+4O7CkkTHqjMSJTeQUSKyXZ0bvZ1mUfzpV7ld +GYUf4zGNcVYSkVWPgS0iJnlcY+psYvk2rPDDxsBCuwk= diff --git a/restic.setup b/restic.setup new file mode 100755 index 0000000..dbbfa2e --- /dev/null +++ b/restic.setup @@ -0,0 +1,117 @@ +#!/usr/bin/perl +####################################################################################### restic setup (mwx'2023) +use Config; +die if (!-f "./files/rt"); + + +#myuname: linux localhost 4.19.0 #1 smp debian 4.19.0 armv7l gnulinux +#archname: arm-linux-gnueabihf-thread-multi-64int + +if ($Config{archname}=~/^darwin/) { # --------------------------------------------------------------- mac setup + + $XRT = $ENV{"HOME"}.'/bin/rt'; + $XRTLOG = $ENV{"HOME"}.'/.rt.log'; + $XRESTIC = $ENV{"HOME"}.'/bin/restic'; + $XLOG = $ENV{"HOME"}.'/.restic.log'; + $XPWFILE = $ENV{"HOME"}.'/.restic.pw'; + + $XSRC = $ENV{"HOME"}.'/Sync /Volumes/Pictures'; + $XEXCLUDE = '-e .Spotlight-V100 -e .Trashes -e .fseventsd -e .bzvol -e .DS_Store ' . + '-e .TemporaryItems -e .DocumentRevisions-V100'; + $config=$ENV{"HOME"}.'/.rt.conf'; + + system('./upd https://github.com/restic/restic -i '.$ENV{"HOME"}.'/bin'); + + system("cp ./files/rt $XRT"); + system("chmod 755 $XRT"); + +} elsif ($Config{archname}=~/-linux-/) { # ------------------------------------------------ ubuntu/debian setup + + $XRT = '/db/bin/rt'; + $XRTLOG = '/var/log/rt.log'; + $XRESTIC = '/db/bin/restic'; + $XLOG = '/var/log/restic.log'; + $XLOG = '/var/log/restic.log'; + $XPWFILE = '/db/etc/restic.pw'; + + $XSRC = '/etc /db /var /root /home /usr/local /opt'; + $XEXCLUDE = '-e /var/lib/lxcfs -e /var/log/journal'; + + $config='/db/etc/rt.conf'; + + system('./upd https://github.com/restic/restic -i /db/bin'); + + system("cp ./files/rt $XRT"); + system("chmod 755 $XRT"); + system("mkdir -p /db/etc /db/tmp"); + +} else {die "architecture not found";} # ---------------------------------------------------------------------- + +chomp($host=`hostname`);$host=~s/^([^\.]+).*/$1/; +$host=&readline("Hostname: ",$host); + + +if (!-f $config) { # write config file +open(OUT,"> $config"); +print OUT <<"ENDOFCONF"; + +\$NAME = '$host'; +\$ID = '0'; +\$TAG = 'ppb'; + +\$PASSWORD = ""; +\$TARGET = ""; +\$ENV{'AWS_ACCESS_KEY_ID'} = ''; +\$ENV{'AWS_SECRET_ACCESS_KEY'} = ''; + +\$SRC = '$XSRC'; + +\$EXCLUDE = '$XEXCLUDE'; + +\$RESTIC = '$XRESTIC'; +\$LOG = '$XLOG'; +\$PWFILE = '$XPWFILE'; + +\$HTTP_LOG = 'log.fhi.berlin'; + +ENDOFCONF +} + + +system("vi $config"); + +system("$XRT init"); + +&setupcron(); + + +####################################################################################################### SUPPORT + + +sub setupcron() { + open(CRON,"crontab -l |"); + while() { + chomp(); + push(@CRON,$_) if (!/rt\s+selfupdate/ && !/rt delaybackup/); + } + + push(@CRON,"0 2 * * * $XRT delaybackup >> $XRTLOG 2>&1"); + + open(OUT,"> /tmp/cron.$$"); + for (@CRON) { + print OUT "$_\n"; + } + close(OUT); + system("/usr/bin/crontab /tmp/cron.$$"); + system("rm -f /tmp/cron.$$"); +} + +sub readline() { + my($prompt,$input)=@_; use Term::ReadLine; + BEGIN{ $ENV{PERL_RL} = 'Perl o=0' } + if (!$term) {;$term = new Term::ReadLine 'term';} + my($txt)=$term->readline($prompt,$input); + return $txt; +} + +########################################################################################################### END diff --git a/setup.debian1x b/setup.debian1x new file mode 100755 index 0000000..ee89c45 --- /dev/null +++ b/setup.debian1x @@ -0,0 +1,114 @@ +#!/usr/bin/perl +use Getopt::Std;getopts('z'); + +system("userdel ppb; rm -rf /home/ppb") if (-d "/home/ppb"); +system("userdel mike; rm -rf /home/mike") if (-d "/home/mike"); + +&ai('dnsutils','net-tools','zsh','joe','rsync','curl','fuse','libwww-perl', + 'libterm-readline-perl-perl','libterm-readpassword-perl','libdbd-mysql-perl','ntp', + 'libjson-perl','jq','unzip','7zip'); + +if ($opt_z) { + if (-x "/usr/bin/zsh") { + system("chsh root -s /usr/bin/zsh"); + } +} + + +system("locale-gen C.UTF-8"); + +system("mkdir /db"); +system("mkdir /db/bin"); +system("mkdir /db/backup"); +system("mkdir /db/backup/mysql"); +system("mkdir /db/tmp"); +system("mkdir /db/log"); +system("mkdir /db/lib"); +system("mkdir /db/data"); +system("mkdir /db/etc"); +system("mkdir /db/src"); +system("mkdir /db/upload"); +system("chmod 777 /db/tmp"); +system("chmod 777 /db/log"); +system("chmod 777 /db/upload"); + +system("mkdir -p ~/.joe/colors/"); +system("cp ./files/default.jcf ~/.joe/colors/default.jcf"); +system("cp ./files/joerc4 /root/.joerc"); +system("cp ./files/csh.cshrc /etc"); +system("cp ./files/rc.local.debian /etc/rc.local"); +system("chmod 755 /etc/rc.local"); +system("cp ./files/myuser /db/bin"); +system("cp ./files/mybackup /db/bin"); +system("cp ./files/dx /db/bin"); +system("cp ./files/gx /db/bin"); +system("cp ./files/gy /db/bin"); +system("cp ./files/telemetry /db/bin"); +system("cp ./files/rt /db/bin"); +system("cp ./files/mgsh /db/bin"); +system("cp ./files/locale /etc/default/locale"); + +system("cp ./files/zshrc /etc/zsh/zshrc"); + +system("rm /etc/motd; touch /etc/motd"); + +system("mkdir /root/.ssh") if (!-d "/root/.ssh"); + + +&readak("/root/.ssh/authorized_keys"); +&readak("./files/authorized_keys"); + +open(OUT,"> /root/.ssh/authorized_keys"); +for (sort(keys(%K))) {print OUT "$_\n" if (!/^\s*$/);} +close(OUT); + +sub readak() { + my($file)=@_; + if (-f $file) {open(IN,$file);while() {chomp();$K{$_}=$_;}close(IN);} +} + + +system("chmod 700 /root/.ssh"); +system("chmod 600 /root/.ssh/authorized_keys"); + +if (!$opt_x) { + system("/usr/bin/apt-get update"); + system("/usr/bin/apt-get upgrade"); + + if (is_debian_13_or_later()) { + system("cp ./files/timesyncd.conf /etc/systemd/"); + + } else { + system("service ntp stop"); + system("/usr/sbin/ntpd -gq"); + system("service ntp start"); + } +} + +sub ai { + my @pkgs=@_; + for (@pkgs) { + system("/usr/bin/apt-get -y install $_"); + } +} + + +sub is_debian_13_or_later { + return 0 unless -r '/etc/os-release'; + + my %os_release; + open(my $fh, '<', '/etc/os-release') or return 0; + while (my $line = <$fh>) { + chomp $line; + if ($line =~ /^([A-Z_]+)=(.*)$/) { + my ($key, $val) = ($1, $2); + $val =~ s/^"|"$//g; + $os_release{$key} = $val; + } + } + close($fh); + + return 0 unless ($os_release{ID} // '') eq 'debian'; + return 0 unless ($os_release{VERSION_ID} // '') =~ /^(\d+)/; + return $1 >= 13 ? 1 : 0; +} diff --git a/setup.phpini b/setup.phpini new file mode 100755 index 0000000..201ed6b --- /dev/null +++ b/setup.phpini @@ -0,0 +1,60 @@ +#!/usr/bin/perl + +for $v ('7.2','7.3','7.4','8.1') { + if (-f "/etc/php/$v/apache2/php.ini") { + $FILE = "/etc/php/$v/apache2/php.ini"; + $OFILE = "/etc/php/$v/apache2/php.ini.org"; + } +} + +die "$FILE not found" if (!-f $FILE); +die "$FILE skipped" if (-f $OFILE); + +$epre = "\"
\""; +$epost = "\"
\""; + +$P{'html_errors'} = 'On'; +$P{'display_errors'} = 'On'; +$P{'error_prepend_string'} = $epre; + +$P{'error_append_string'} = $epost; +$P{'error_reporting'} = 'E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED'; +$P{'short_open_tag'} = 'On'; +$P{'upload_tmp_dir'} = '/db/upload'; +$P{'upload_max_filesize'} = '10000M'; +$P{'post_max_size'} = '10000M'; +$P{'max_execution_time'} = '300'; +$P{'max_input_time'} = '600'; +$P{'memory_limit'} = '512M'; + +if (!-f $OFILE) { + system("cp $FILE $OFILE"); +} + +open(IN,$OFILE); +open(OUT,"> $FILE"); +while() { + + if (!/^;/ && !/^\s*$/) { + print OUT "\n" if (/^\[/); + $match=0; + for $key (keys(%P)) { + $match++ if (/^$key/); + } + if ($match>0) { + print OUT ";$_"; + } else { + print OUT "$_"; + } + } + + if (/^\[PHP\]/) { + for $key (sort(keys(%P))) { + print OUT "$key = $P{$key}\n"; + } + print OUT "\n"; + } + +} +close(IN); +close(OUT); diff --git a/setup.rpi b/setup.rpi new file mode 100755 index 0000000..48453a6 --- /dev/null +++ b/setup.rpi @@ -0,0 +1,34 @@ +#!/usr/bin/perl + +&ai('tcsh','joe','libterm-readpassword-perl','libterm-readline-perl-perl','resolvconf'); + +system("/usr/bin/chsh -s /usr/bin/tcsh root"); + +system("mkdir /db"); +system("mkdir /db/bin"); +system("mkdir /db/tmp"); +system("chmod 777 /db/tmp"); + +system("cp ./files/joerc4 /etc/joe/joerc"); +system("cp ./files/csh.cshrc /etc"); +system("cp ./files/dx /db/bin"); +system("cp ./files/gx /db/bin"); +system("cp ./files/gy /db/bin"); +system("cp ./restic/restic_0.9.5_linux_arm /db/bin/restic"); + +system("rm /etc/motd"); + +system("mkdir /root/.ssh"); +system("cp ./files/authorized_keys /root/.ssh"); +system("chmod 700 /root/.ssh"); +system("chmod 600 /root/.ssh/authorized_keys"); + +system("/usr/bin/apt-get update"); +system("/usr/bin/apt-get upgrade"); + +sub ai { + my @pkgs=@_; + for (@pkgs) { + system("/usr/bin/apt-get -y install $_"); + } +} diff --git a/setup.ssh b/setup.ssh new file mode 100755 index 0000000..1054d5b --- /dev/null +++ b/setup.ssh @@ -0,0 +1,24 @@ +#!/usr/bin/perl + +$SSHCONF='/etc/ssh/sshd_config'; + +$out=""; +open(IN,$SSHCONF); +while() { + + if (/^\s*\#*\s*PermitRootLogin/) { + $out.="PermitRootLogin yes\n" ; + } elsif (/(^\s*AcceptEnv.*$)/) { + $out.="#$1"; + } else { + $out.=$_; + } +} +close(IN); + +open(OUT,"> $SSHCONF"); +print OUT $out; +close(OUT); + +system("service ssh restart"); + diff --git a/setup.ubuntu2x b/setup.ubuntu2x new file mode 100755 index 0000000..da59c1b --- /dev/null +++ b/setup.ubuntu2x @@ -0,0 +1,58 @@ +#!/usr/bin/perl + +system("userdel ppb; rm -rf /home/ppb") if (-d "/home/ppb"); +system("userdel mike; rm -rf /home/mike") if (-d "/home/mike"); + +&ai('net-tools','zsh','joe','fuse','libwww-perl','bzip2','jq', + 'libterm-readline-perl-perl','libterm-readpassword-perl','libdbd-mysql-perl','ntp'); + +system("chsh root -s /usr/bin/zsh"); + +system("mkdir /db"); +system("mkdir /db/bin"); +system("mkdir /db/backup"); +system("mkdir /db/backup/mysql"); +system("mkdir /db/tmp"); +system("mkdir /db/log"); +system("mkdir /db/lib"); +system("mkdir /db/data"); +system("mkdir /db/etc"); +system("mkdir /db/src"); +system("mkdir /db/upload"); +system("chmod 777 /db/tmp"); +system("chmod 777 /db/log"); +system("chmod 777 /db/upload"); + +system("cp ./files/joerc4 /root/.joerc"); +system("cp ./files/csh.cshrc /etc"); +system("cp ./files/rc.local.ubuntu /etc/rc.local"); +system("chmod 755 /etc/rc.local"); +system("cp ./files/myuser /db/bin"); +system("cp ./files/mybackup /db/bin"); +system("cp ./files/dx /db/bin"); +system("cp ./files/gx /db/bin"); +system("cp ./files/gy /db/bin"); +system("cp ./files/telemetry /db/bin"); +system("cp ./files/rt /db/bin"); +system("cp ./files/mgsh /db/bin"); + +system("cp ./files/zshrc /etc/zsh/zshrc"); + +system("mkdir /root/.ssh") if (!-d "/root/.ssh"); +system("cp ./files/authorized_keys /root/.ssh"); +system("chmod 700 /root/.ssh"); +system("chmod 600 /root/.ssh/authorized_keys"); + +system("/usr/bin/apt update"); +system("/usr/bin/apt upgrade"); + +system("service ntp stop"); +system("/usr/sbin/ntpd -gq"); +system("service ntp start"); + +sub ai { + my @pkgs=@_; + for (@pkgs) { + system("/usr/bin/apt -qq -y install $_"); + } +} diff --git a/telemetry.setup b/telemetry.setup new file mode 100755 index 0000000..8682c87 --- /dev/null +++ b/telemetry.setup @@ -0,0 +1,28 @@ +#!/usr/bin/perl +#################################################################################### telemetry setup (mwx'2020) + +&setupcron(); + + +####################################################################################################### SUPPORT + +sub setupcron() { + open(CRON,"crontab -l |"); + while() { + chomp(); + push(@CRON,$_) if (!/\/db\/bin\/telemetry/); + } + + push(@CRON,"*/5 * * * * /db/bin/telemetry > /dev/null 2>&1"); + + open(OUT,"> /tmp/cron.$$"); + for (@CRON) { + print OUT "$_\n"; + } + close(OUT); + system("/usr/bin/crontab /tmp/cron.$$"); + system("rm -f /tmp/cron.$$"); +} + + +########################################################################################################### END diff --git a/upd b/upd new file mode 100755 index 0000000..adfc513 --- /dev/null +++ b/upd @@ -0,0 +1,1227 @@ +#!/usr/bin/env perl +# +# upd - download the matching binary from the latest Gitea/GitHub release. +# +# ./upd https://git.fhi.mpg.de/mike/mgsh +# ./upd https://github.com/sxyazi/yazi --install ~/bin --name yazi,ya +# ./upd --all # everything listed in the config file +# ./upd --all --check # exit 10 if any update is available +# +# Needs only Perl core modules plus curl (or wget) for HTTPS. + +use strict; +use warnings; +use Getopt::Long qw(GetOptions); +use File::Basename qw(basename dirname); +use File::Spec; +use File::Temp qw(tempdir); +use POSIX qw(uname strftime); +use Digest::SHA qw(sha256_hex); +use JSON::PP (); + +my $UA = 'upd/2.0 (perl)'; + +# Exit codes: 0 ok, 1 usage, 2 error, 10 update available (--check only). +use constant { EX_OK => 0, EX_USAGE => 1, EX_ERROR => 2, EX_OUTDATED => 10 }; + +# Options that belong to a single repository. Anything else is global and +# applies to every entry of an --all run. +my @SPEC_KEYS = qw(install name tag asset pattern os arch forge token version-flag pre); + +my %opt = ('version-flag' => '--version', timeout => 30); + +# Leftovers from an interrupted install must not linger next to the binary. +my @TMPFILES; +END { unlink @TMPFILES if @TMPFILES } + +# Run only when executed directly, so the subs below can be require'd and +# exercised on their own. +main() unless caller; + +sub main { + GetOptions( + \%opt, + 'repo=s', 'tag=s', 'install|dest|i=s', 'name=s', 'asset=s', 'pattern=s', + 'os=s', 'arch=s', 'token=s', 'forge=s', 'version-flag=s', 'timeout=i', + 'config=s', 'all', 'check', 'pre', 'force', 'list', 'dry-run', + 'quiet', 'verbose', 'help', + ) or usage(EX_USAGE); + usage(EX_OK) if $opt{help}; + $| = 1; + + for my $sig (qw(INT TERM HUP)) { + $SIG{$sig} = sub { unlink @TMPFILES; @TMPFILES = (); exit 130 }; + } + + my @specs; + eval { @specs = build_specs(); 1 } or do { + warn trim($@) . "\n"; + exit EX_ERROR; + }; + + my @results; + for my $spec (@specs) { + my $res = eval { update_one($spec) }; + $res = { status => 'error', label => label_of($spec), msg => trim($@ || 'failed') } + unless defined $res; + push @results, $res; + warn "$res->{label}: $res->{msg}\n" if $res->{status} eq 'error'; + } + + summary(\@results) if @specs > 1 && !$opt{list}; + exit worst_code(\@results); +} + +sub build_specs { + if ($opt{all}) { + my $path = $opt{config} // config_path(); + my @s = read_config($path); + die "No entries in $path.\n" unless @s; + return @s; + } + my $url = $opt{repo} // shift(@ARGV) // $ENV{UPD_REPO}; + unless (defined $url && length $url) { + warn "Error: missing repository URL.\n\n"; + usage(EX_USAGE); + } + my %s = (repo => $url); + $s{$_} = $opt{$_} for grep { defined $opt{$_} } @SPEC_KEYS; + return (\%s); +} + +# ============================================================================== +# One repository, end to end +# ============================================================================== + +sub update_one { + my $spec = shift; + + my ($base, $owner, $repo) = parse_repo($spec->{repo}); + my $forge = detect_forge($base, $spec->{forge}); + my %ctx = ( + base => $base, + owner => $owner, + repo => $repo, + forge => $forge, + token => resolve_token($forge, $spec->{token}), + api => api_base($base, $forge) . '/repos/' . uri_esc($owner) . '/' . uri_esc($repo), + ); + + my @names = parse_names($spec->{name} // $repo, $repo); + my ($os, $arch) = detect_platform($spec); + + info("Repo: $base/$owner/$repo [$forge]"); + info("Platform: $os/$arch"); + + my $rel = fetch_release(\%ctx, $spec); + my $tag = $rel->{tag_name}; + + if ($opt{list}) { + list_releases($rel->{_list} || [$rel]); + return { status => 'listed', label => $names[0]{out}, msg => '' }; + } + + info("Release: $tag ($rel->{published_at})" . ($rel->{prerelease} ? ' [prerelease]' : '')); + + my @assets = @{ $rel->{assets} || [] }; + die "Release $tag has no assets.\n" unless @assets; + + my $asset = pick_asset(\@assets, $names[0]{src}, $os, $arch, $spec); + unless ($asset) { + my $have = join "\n ", map { $_->{name} } @assets; + die "No asset for $os/$arch in release $tag.\nAvailable:\n $have\n" + . "Select one explicitly with --asset or --pattern .\n"; + } + info("Asset: $asset->{name} (" . human_size($asset->{size}) . ")"); + + my @targets = resolve_targets($spec, \@names, $os); + info("Target: " . join(', ', map { $_->{dest} } @targets)); + + my @stale = grep { !target_current($_, $tag, $asset, $spec) } @targets; + unless (@stale || $opt{force}) { + info("Already up to date ($tag) - nothing to do."); + return { status => 'current', label => $names[0]{out}, msg => $tag }; + } + @stale = @targets if $opt{force}; + + if ($opt{check}) { + my $have = join ', ', map { installed_tag($_) } @stale; + info("Update available: $tag (installed: $have)"); + return { status => 'outdated', label => $names[0]{out}, msg => "$tag (have: $have)" }; + } + + my ($dl_url) = asset_url(\%ctx, $asset); + if ($opt{'dry-run'}) { + print "[dry-run] would download: $dl_url\n"; + print "[dry-run] would install to: $_->{dest}\n" for @stale; + return { status => 'dry', label => $names[0]{out}, msg => $tag }; + } + + # --- download ------------------------------------------------------------- + + my $tmpdir = tempdir(CLEANUP => 1); + my $dl = File::Spec->catfile($tmpdir, $asset->{name}); + + info("Downloading $dl_url ..."); + my (undef, $dl_hdr) = asset_url(\%ctx, $asset); + my $res = http_request(url => $dl_url, headers => { %{ auth_headers(\%ctx) }, %$dl_hdr }, + file => $dl, progress => 1); + die "Download failed (HTTP $res->{status}): $dl_url\n" unless $res->{status} == 200; + + my $got = -s $dl // 0; + die "Incomplete download: $got of $asset->{size} bytes.\n" + if $asset->{size} && $got < $asset->{size}; + + verify_download(\%ctx, $dl, $asset, \@assets, $tmpdir); + + # --- extract and install -------------------------------------------------- + + my $root = extract_if_archive($dl, $tmpdir); + for my $t (@stale) { + my $src = defined $root ? find_in_tree($root, $t->{name}) + : $dl; + die "Binary '$t->{name}' not found inside $asset->{name}.\n" unless defined $src; + warn "Warning: $t->{name} does not look like an executable.\n" + unless looks_executable($src); + + install_atomic($src, $t->{dest}); + strip_quarantine($t->{dest}) if $os eq 'darwin'; + write_state($t, \%ctx, $spec, $tag, $asset); + info("Installed: $t->{dest} ($tag)"); + my $v = installed_version($t->{dest}, $spec); + info("Version: $v") if length $v; + } + + my %dirs = map { dirname($_->{dest}) => 1 } @stale; + warn "Note: $_ is not in \$PATH.\n" for grep { !in_path($_) } sort keys %dirs; + + return { status => 'updated', label => $names[0]{out}, msg => $tag }; +} + +# ============================================================================== +# Release selection +# ============================================================================== + +sub fetch_release { + my ($ctx, $spec) = @_; + + # A specific tag: both forges have a direct endpoint. Fall back to the list + # so "26.5.6" also finds a tag named "v26.5.6". + if (defined $spec->{tag}) { + my $t = $spec->{tag}; + my $hit = api_get($ctx, "$ctx->{api}/releases/tags/" . uri_esc($t), soft => 1); + return $hit if $hit && $hit->{tag_name}; + my $list = api_get($ctx, releases_url($ctx)); + ($hit) = grep { $_->{tag_name} eq $t } @$list; + ($hit) = grep { norm_ver($_->{tag_name}) eq norm_ver($t) } @$list unless $hit; + die "Release '$t' not found (--list shows all).\n" unless $hit; + return $hit; + } + + # The plain case is one request: the forge already knows its latest + # non-draft, non-prerelease release. + unless ($spec->{pre} || $opt{list}) { + my $latest = api_get($ctx, "$ctx->{api}/releases/latest", soft => 1); + return $latest if $latest && $latest->{tag_name}; + verbose('no /releases/latest, falling back to the release list'); + } + + my $list = api_get($ctx, releases_url($ctx)); + die "No releases found in $ctx->{owner}/$ctx->{repo}.\n" + unless ref $list eq 'ARRAY' && @$list; + + if ($opt{list}) { + return { tag_name => '', published_at => '', assets => [], _list => $list }; + } + my ($rel) = grep { !$_->{draft} && ($spec->{pre} || !$_->{prerelease}) } @$list; + die "No suitable release found (try --pre).\n" unless $rel; + return $rel; +} + +sub releases_url { + my $ctx = shift; + return $ctx->{forge} eq 'github' ? "$ctx->{api}/releases?per_page=50" + : "$ctx->{api}/releases?limit=50&draft=false"; +} + +# ============================================================================== +# Asset selection +# ============================================================================== + +# Aliases commonly used in release asset names, including Rust target triples. +sub os_alias { + my $o = shift; + return $o eq 'darwin' ? [qw(darwin macos osx mac apple)] + : $o eq 'windows' ? [qw(windows win)] + : [$o]; +} + +# --- Asset name matching ------------------------------------------------------ + +# Can this machine turn the asset into a binary? Bare names and tarballs +# always qualify; single-file compression needs its decompressor present. +sub unpackable { + my $n = lc shift; + return 1 if $n =~ /\.(tar\.gz|tgz|tar\.bz2|tbz|tar\.xz|txz|tar\.zst|tzst|tar)$/; + return which('unzip') ? 1 : 0 if $n =~ /\.zip$/; + return (which('7zz') || which('7z') || which('7za')) ? 1 : 0 if $n =~ /\.7z$/; + return decompressor($1) ? 1 : 0 if $n =~ /\.(gz|bz2|xz|zst|lz4|lzma)$/; + return 0 if $n =~ /\.(rar|dmg|pkg|msi|deb|rpm)$/; + return 1; # bare binary or an unversioned name +} + +# Compound tokens that name OS and architecture in one word. Rewritten before +# matching so the normal token rules apply. "win32" is Node-speak for Windows +# in general (pnpm-win32-x64.zip), so it contributes no architecture. +sub normalize_tokens { + my $n = shift; + $n =~ s/(?{asset}) { + my ($hit) = grep { $_->{name} eq $spec->{asset} } @$assets; + die "Asset '$spec->{asset}' is not part of the release.\n" unless $hit; + return $hit; + } + if (defined $spec->{pattern}) { + my $re = qr/$spec->{pattern}/; + my ($hit) = grep { $_->{name} =~ $re } @$assets; + return $hit; + } + + my $os_re = join '|', @{ os_alias($want_os) }; + my @arches = @{ arch_alias($want_arch) }; + # Universal macOS builds serve both architectures. + push @arches, qw(universal universal2) if $want_os eq 'darwin'; + my $arch_re = join '|', @arches; + + my (@cand, @rejected); + for my $as (@$assets) { + my $n = lc $as->{name}; + my $m = normalize_tokens($n); + + # Checksums, signatures and OS packages are not plain binaries. + if ($n =~ /\.(sha\d*|sha256sum|md5|asc|sig|pem|sbom|json|txt|deb|rpm|apk|dmg|pkg|msi|snap|flatpak|appimage)$/) { + push @rejected, "$n (not a binary)"; + next; + } + # Cross-compile targets whose triples contain a host OS token: + # aarch64-linux-android is Android, not Linux. + if ($m =~ /(?:^|[^a-z0-9])(?:android\w*|ios|wasi|wasm\w*|emscripten)(?:[^a-z0-9]|$)/) { + push @rejected, "$n (foreign target)"; + next; + } + unless ($m =~ /(?:^|[^a-z0-9])(?:$os_re)(?:[^a-z0-9]|$)/) { + push @rejected, "$n (os)"; + next; + } + unless ($m =~ /(?:^|[^a-z0-9])(?:$arch_re)(?:[^a-z0-9]|$)/) { + push @rejected, "$n (arch)"; + next; + } + # Keep 32-bit "arm" off "arm64" and "386" off "x86_64". + if ( ($want_arch eq 'arm' && $m =~ /arm64|aarch64/) + || ($want_arch eq '386' && $m =~ /x86[_-]?64|amd64/) + || ($want_arch eq 'amd64' && $m =~ /arm64|aarch64/)) { + push @rejected, "$n (wider arch)"; + next; + } + + my $score = 0; + $score += 10 if index($n, lc $bin) == 0; # named after the binary + $score += 3 if $n =~ /\.(tar\.gz|tgz|zip|tar\.xz|tar\.bz2|tar\.zst|tzst)$/ || $n !~ /\./; + $score -= 5 if $n =~ /debug|symbols|static-pie|profile/; + # Only avoid formats this machine has no tool for - restic, for one, + # ships nothing but .bz2, and bunzip2 handles that fine. + $score -= 8 if !unpackable($n); + + # Toolchain preference is a tie-break, not a penalty: a project that + # ships musl only (or mingw only) must not be downranked for it. + my $pref = 0; + if ($want_os eq 'linux' && $n =~ /musl|gnu/) { + my $libc = prefers_musl() ? 'musl' : 'gnu'; + $pref = $n =~ /\Q$libc\E/ ? 0 : 1; + } + elsif ($want_os eq 'windows' && $n =~ /msvc|gnu/) { + $pref = $n =~ /msvc/ ? 0 : 1; # msvc is the normal Windows build + } + push @cand, [ $score, $pref, length($n), $as ]; + } + + # Best score, then preferred toolchain, then the shortest name (which + # avoids special variants like -baseline or -static). + @cand = sort { $b->[0] <=> $a->[0] || $a->[1] <=> $b->[1] || $a->[2] <=> $b->[2] } @cand; + if ($opt{verbose}) { + verbose(sprintf 'candidate score=%-3d pref=%d %s', @{$_}[0, 1], $_->[3]{name}) for @cand; + verbose("rejected: $_") for @rejected; + } + return @cand ? $cand[0][3] : undef; +} + +# ============================================================================== +# Install targets and state +# ============================================================================== + +sub resolve_targets { + my ($spec, $names, $os) = @_; + my $want = $spec->{install} // $ENV{UPD_INSTALL}; + $want =~ s{^~(?=/|$)}{$ENV{HOME} // '~'}e if defined $want; + my $ext = $os eq 'windows' ? '.exe' : ''; + + # --install is a directory unless it clearly points at a single binary: + # an existing file, or a last segment that is one of the binary names. + # Everything else is a directory (and gets created) - otherwise a config + # line like "install=~/bin" would create a *file* called bin. + my ($dir, $single); + if (defined $want && length $want) { + my $leaf = basename($want); + my $is_bin = grep { $leaf eq $_->{out} || $leaf eq $_->{out} . $ext } @$names; + if (!-d $want && ($is_bin || -f $want)) { + die "--install points at the file '$want' but " . scalar(@$names) + . " binaries were requested; give a directory instead.\n" if @$names > 1; + $single = $want; + $dir = dirname($want); + } + else { + ($dir = $want) =~ s{(?<=.)/+$}{}; + } + } + else { + $dir = default_dir($names->[0]{out}); + } + make_dir($dir); + + my @t; + for my $n (@$names) { + my $dest = $single // File::Spec->catfile($dir, $n->{out} . $ext); + # Replacing a symlink would silently break the link, so follow it. + if (-l $dest) { + require Cwd; + if (my $real = Cwd::abs_path($dest)) { + info("Note: $dest is a symlink, installing to $real"); + $dest = $real; + } + } + push @t, { name => $n->{src}, out => $n->{out}, dest => $dest }; + } + return @t; +} + +# Without --install: replace the binary already on PATH, else ~/.local/bin. +sub default_dir { + my $bin = shift; + for my $dir (split /:/, ($ENV{PATH} // '')) { + next unless length $dir; + my $p = File::Spec->catfile($dir, $bin); + return $dir if -x $p && -w $dir; + } + return File::Spec->catdir($ENV{HOME} // '.', '.local', 'bin'); +} + +sub make_dir { + my $dir = shift; + return if -d $dir || $opt{'dry-run'} || $opt{list} || $opt{check}; + require File::Path; + File::Path::make_path($dir) + or die "Cannot create target directory $dir: $!\n"; +} + +sub state_dir { + my $base = $ENV{XDG_STATE_HOME} + || File::Spec->catdir($ENV{HOME} // '.', '.local', 'state'); + return File::Spec->catdir($base, 'upd'); +} + +sub cache_dir { + my $base = $ENV{XDG_CACHE_HOME} || File::Spec->catdir($ENV{HOME} // '.', '.cache'); + return File::Spec->catdir($base, 'upd'); +} + +# One state file per installed path; readable name plus a hash for uniqueness. +sub state_file { + my $dest = shift; + (my $key = $dest) =~ s{[^A-Za-z0-9._-]+}{_}g; + $key =~ s{^_+|_+$}{}g; + $key = substr($key, -70) if length $key > 70; + return File::Spec->catfile(state_dir(), $key . '.' . substr(sha256_hex($dest), 0, 8) . '.json'); +} + +# Identity of a release asset: the digest if the forge publishes one (GitHub +# does), otherwise its upload time - this is what makes rolling tags such as +# "nightly" detectable. +sub asset_stamp { + my $a = shift; + return $a->{digest} if $a->{digest}; + return "t:$a->{updated_at}" if $a->{updated_at}; + return "t:$a->{created_at}" if $a->{created_at}; + return 's:' . ($a->{size} // 0); +} + +sub target_current { + my ($t, $tag, $asset, $spec) = @_; + return 0 unless -f $t->{dest}; + + my $st = read_json(state_file($t->{dest})); + if ($st && defined $st->{tag}) { + return 0 unless $st->{tag} eq $tag; + return 0 unless ($st->{asset} // '') eq $asset->{name}; + return 0 unless ($st->{stamp} // '') eq asset_stamp($asset); + # A locally replaced binary counts as out of date. + my $same = ($st->{binary_sha256} // '') eq file_sha256($t->{dest}); + verbose("$t->{dest}: state matches but binary differs") unless $same; + return $same; + } + + # No state yet (first run after an install by other means): ask the binary. + my $v = installed_version($t->{dest}, $spec); + verbose("$t->{dest}: no state file, binary reports '" . ($v // '') . "'"); + return length($v) && $v eq norm_ver($tag) ? 1 : 0; +} + +sub installed_tag { + my $t = shift; + my $st = read_json(state_file($t->{dest})); + return $st->{tag} if $st && defined $st->{tag}; + return '-' unless -f $t->{dest}; + my $v = installed_version($t->{dest}, {}); + return length($v) ? $v : 'unknown'; +} + +sub write_state { + my ($t, $ctx, $spec, $tag, $asset) = @_; + make_dir_always(state_dir()); + write_json(state_file($t->{dest}), { + dest => $t->{dest}, + binary => $t->{out}, + repo => "$ctx->{base}/$ctx->{owner}/$ctx->{repo}", + forge => $ctx->{forge}, + tag => $tag, + asset => $asset->{name}, + asset_size => $asset->{size}, + stamp => asset_stamp($asset), + binary_sha256 => file_sha256($t->{dest}), + installed_at => strftime('%Y-%m-%dT%H:%M:%SZ', gmtime), + }); +} + +sub make_dir_always { + my $dir = shift; + return if -d $dir; + require File::Path; + File::Path::make_path($dir) or die "Cannot create $dir: $!\n"; +} + +# ============================================================================== +# Config file (--all) +# ============================================================================== + +sub config_path { + my $base = $ENV{XDG_CONFIG_HOME} || File::Spec->catdir($ENV{HOME} // '.', '.config'); + return File::Spec->catfile($base, 'upd', 'tools'); +} + +# One entry per line: [key=value ...] [pre] +sub read_config { + my $path = shift; + open my $fh, '<', $path + or die "Cannot read config $path: $!\n" + . "Format: one line per tool, e.g.\n" + . " https://github.com/sxyazi/yazi install=~/bin name=yazi,ya\n"; + + my (@out, $ln); + while (my $line = <$fh>) { + $ln++; + $line =~ s/^\s+|\s+$//g; + next if !length $line || $line =~ /^#/; + + my @tok = map { unquote($_) } $line =~ /("(?:\\.|[^"])*"|\S+)/g; + my %s = (repo => shift @tok); + for my $t (@tok) { + my ($k, $v) = split /=/, $t, 2; + $k = lc $k; + die "$path:$ln: unknown key '$k' (allowed: " . join(', ', @SPEC_KEYS) . ")\n" + unless grep { $_ eq $k } @SPEC_KEYS; + $s{$k} = defined $v ? $v : 1; + } + # Global flags still win, so --force/--pre on the command line apply. + $s{$_} = $opt{$_} for grep { defined $opt{$_} } @SPEC_KEYS; + push @out, \%s; + } + close $fh; + return @out; +} + +sub unquote { + my $s = shift; + if ($s =~ s/^"(.*)"$/$1/s) { $s =~ s/\\(.)/$1/g } + return $s; +} + +# "yazi,ya" -> two binaries; "yazi:yazi-nightly" -> install yazi under a +# different file name. src is what to look for, out is what to write. +sub parse_names { + my ($list, $fallback) = @_; + my @n; + for my $part (split /\s*,\s*/, $list) { + next unless length $part; + my ($src, $out) = split /:/, $part, 2; + push @n, { src => $src, out => (defined $out && length $out) ? $out : $src }; + } + return @n ? @n : ({ src => $fallback, out => $fallback }); +} + +sub label_of { + my $spec = shift; + return (parse_names($spec->{name}, '?'))[0]{out} if defined $spec->{name}; + my $r = $spec->{repo} // '?'; + $r =~ s{/+$}{}; + return basename($r); +} + +sub summary { + my $res = shift; + # --quiet is meant for cron: report only what needs attention. + my @rows = $opt{quiet} + ? grep { $_->{status} =~ /^(error|outdated|updated)$/ } @$res + : @$res; + return unless @rows; + my $w = 0; + for (@rows) { $w = length $_->{label} if length $_->{label} > $w } + print "\nSummary:\n"; + printf " %-9s %-*s %s\n", $_->{status}, $w, $_->{label}, $_->{msg} // '' for @rows; +} + +sub worst_code { + my $res = shift; + return EX_ERROR if grep { $_->{status} eq 'error' } @$res; + return EX_OUTDATED if grep { $_->{status} eq 'outdated' } @$res; + return EX_OK; +} + +# ============================================================================== +# HTTP +# ============================================================================== + +# Use HTTP::Tiny only if it can really do TLS - otherwise curl/wget. +my $HTTP; +sub http_tiny { + return $HTTP if defined $HTTP; + $HTTP = eval { + require HTTP::Tiny; + HTTP::Tiny->can_ssl or die "no ssl\n"; + HTTP::Tiny->new(agent => $UA, timeout => $opt{timeout}, verify_SSL => 1); + } || 0; + return $HTTP; +} + +sub transport { + return 'tiny' if http_tiny(); + return 'curl' if which('curl'); + return 'wget' if which('wget'); + die "Found neither a TLS-capable HTTP::Tiny nor curl/wget.\n"; +} + +# wget cannot report response headers usefully, so no conditional requests. +sub conditional_ok { return transport() ne 'wget' } + +sub auth_headers { + my $ctx = shift; + return {} unless $ctx->{token}; + # GitHub wants "Bearer", Gitea wants "token". + return { Authorization => $ctx->{forge} eq 'github' ? "Bearer $ctx->{token}" + : "token $ctx->{token}" }; +} + +# Returns { status, headers => {lc => value}, content } - content only when no +# 'file' was given. Never dies on HTTP status; callers decide. +sub http_request { + my %a = @_; + my $hdr = $a{headers} || {}; + + if (my $h = http_tiny()) { + my %o = (headers => $hdr); + my $out; + if ($a{file}) { + open $out, '>', $a{file} or die "Cannot write $a{file}: $!\n"; + binmode $out; + $o{data_callback} = sub { print {$out} $_[0] }; + } + my $r = $h->get($a{url}, \%o); + close $out if $out; + return { status => $r->{status}, headers => $r->{headers} || {}, + content => $a{file} ? '' : $r->{content} }; + } + + my $tmp = tempdir(CLEANUP => 1); + my $body = $a{file} // File::Spec->catfile($tmp, 'body'); + my $hf = File::Spec->catfile($tmp, 'head'); + + if (transport() eq 'wget') { + my @cmd = ('wget', '-q', '-O', $body, '--timeout', $opt{timeout}, "--user-agent=$UA", + map { "--header=$_: $hdr->{$_}" } sort keys %$hdr); + my $rc = system(@cmd, $a{url}); + return { status => $rc == 0 ? 200 : 599, headers => {}, + content => $a{file} ? '' : slurp($body) }; + } + + my @prog = ($a{progress} && !$opt{quiet} && -t STDOUT) ? ('--progress-bar') : ('-sS'); + my @cmd = ('curl', @prog, '-L', '--retry', '2', '--connect-timeout', $opt{timeout}, + '-A', $UA, '-D', $hf, '-o', $body, '-w', '%{http_code}', + map { ('-H', "$_: $hdr->{$_}") } sort keys %$hdr); + + my $code = ''; + if (open my $ph, '-|', @cmd, $a{url}) { + local $/; + $code = <$ph> // ''; + close $ph; + } + my $rc = $? >> 8; + $code =~ s/\D//g; + die "curl failed (exit $rc): $a{url}\n" if $rc != 0 && !length $code; + die "curl failed (exit $rc, HTTP $code): $a{url}\n" if $rc != 0 && $code =~ /^[45]/; + + return { status => $code || 599, headers => parse_headers($hf), + content => $a{file} ? '' : slurp($body) }; +} + +# Keep only the last response block; -L may have walked through redirects. +sub parse_headers { + my $path = shift; + open my $fh, '<', $path or return {}; + my %h; + while (my $l = <$fh>) { + $l =~ s/\r?\n$//; + %h = () , next if $l =~ m{^HTTP/}; + $h{lc $1} = $2 if $l =~ /^([^:]+):\s*(.*)$/; + } + close $fh; + return \%h; +} + +sub slurp { + my $path = shift; + open my $fh, '<', $path or return ''; + binmode $fh; + local $/; + return <$fh> // ''; +} + +# GET a JSON API endpoint, revalidating a cached copy via ETag where supported. +# soft => 1 returns undef instead of dying on 404. +sub api_get { + my ($ctx, $url, %o) = @_; + my $accept = $ctx->{forge} eq 'github' ? 'application/vnd.github+json' : 'application/json'; + my %hdr = (%{ auth_headers($ctx) }, Accept => $accept); + $hdr{'X-GitHub-Api-Version'} = '2022-11-28' if $ctx->{forge} eq 'github'; + + my $cf = cache_file($url); + my $cached = read_json($cf); + $hdr{'If-None-Match'} = $cached->{etag} + if $cached && $cached->{etag} && conditional_ok(); + + my $r = http_request(url => $url, headers => \%hdr); + + if ($r->{status} == 304 && $cached) { + verbose("304 not modified, using cached $url"); + return decode_json_or_die($cached->{body}, $url, $ctx); + } + return undef if $o{soft} && $r->{status} == 404; + if ($r->{status} == 403 || $r->{status} == 429) { + my $left = $r->{headers}{'x-ratelimit-remaining'}; + die "$ctx->{forge} rate limit reached" + . (defined $left ? " (remaining: $left)" : '') + . ". Set a token via --token or \$GITHUB_TOKEN.\n" + if defined $left && $left eq '0'; + } + die "HTTP $r->{status}: $url\n" unless $r->{status} == 200; + + my $data = decode_json_or_die($r->{content}, $url, $ctx); + if (my $etag = $r->{headers}{etag}) { + make_dir_always(cache_dir()); + write_json($cf, { url => $url, etag => $etag, body => $r->{content} }); + } + return $data; +} + +sub decode_json_or_die { + my ($body, $url, $ctx) = @_; + my $data = eval { JSON::PP->new->utf8->decode($body) }; + die "Response from $url is not JSON (is this really a $ctx->{forge} instance?).\n" + unless defined $data; + die ucfirst($ctx->{forge}) . " error: $data->{message}\n" + if ref $data eq 'HASH' && $data->{message}; + return $data; +} + +sub cache_file { + my $url = shift; + return File::Spec->catfile(cache_dir(), substr(sha256_hex($url), 0, 16) . '.json'); +} + +# Private GitHub assets are only reachable through the API URL; curl/HTTP::Tiny +# drop the Authorization header on the cross-host redirect to storage. +sub asset_url { + my ($ctx, $a) = @_; + return ("$ctx->{api}/releases/assets/$a->{id}", { Accept => 'application/octet-stream' }) + if $ctx->{forge} eq 'github' && $ctx->{token} && $a->{id}; + return ($a->{browser_download_url}, {}); +} + +# ============================================================================== +# Verification, extraction, installation +# ============================================================================== + +sub verify_download { + my ($ctx, $file, $asset, $assets, $tmpdir) = @_; + + my ($want, $src); + if (($asset->{digest} // '') =~ /^sha256:([0-9a-f]{64})$/i) { + ($want, $src) = (lc $1, 'asset digest'); + } + else { + my ($sum) = grep { $_->{name} eq "$asset->{name}.sha256" } @$assets; + ($sum) = grep { $_->{name} =~ /^(sha256sums?(\.txt)?|checksums?\.txt)$/i } @$assets + unless $sum; + return unless $sum; + + my $sf = File::Spec->catfile($tmpdir, 'sums'); + my ($u, $h) = asset_url($ctx, $sum); + my $r = eval { + http_request(url => $u, headers => { %{ auth_headers($ctx) }, %$h }, file => $sf); + }; + unless ($r && $r->{status} == 200) { + warn "Checksum file could not be downloaded, skipping verification.\n"; + return; + } + open my $fh, '<', $sf or return; + while (my $l = <$fh>) { + # " ", or just "" in a single-file .sha256 + next unless my ($hash, $fn) = $l =~ /^([0-9a-fA-F]{64})(?:\s+\*?(\S+))?/; + next if defined $fn && basename($fn) ne $asset->{name}; + ($want, $src) = (lc $hash, $sum->{name}); + last; + } + close $fh; + return unless $want; + } + + my $got = file_sha256($file); + die "SHA256 mismatch ($src)!\n expected: $want\n got: $got\n" if $got ne $want; + info("SHA256: ok ($src)"); +} + +sub file_sha256 { + my $path = shift; + open my $fh, '<', $path or die "Cannot read $path: $!\n"; + binmode $fh; + my $d = Digest::SHA->new(256)->addfile($fh)->hexdigest; + close $fh; + return $d; +} + +# Single-file compression: the asset is the binary, just squeezed. Each entry +# lists the tools that can expand it, in order of preference; the first one +# found wins. All of them write to stdout with the flags given. +sub DECOMP { + return { + gz => { tools => [qw(gzip gunzip)], args => ['-dc'] }, + bz2 => { tools => [qw(bzip2 bunzip2)], args => ['-dc'] }, + xz => { tools => [qw(xz unxz)], args => ['-dc'] }, + lzma => { tools => [qw(xz unxz lzma)], args => ['-dc'] }, + zst => { tools => [qw(zstd unzstd)], args => ['-dcq'] }, + lz4 => { tools => [qw(lz4 unlz4)], args => ['-dcq'] }, + }; +} + +sub decompressor { + my $ext = shift; + my $e = DECOMP()->{$ext} or return; + for my $t (@{ $e->{tools} }) { + my $p = which($t) or next; + return { prog => $p, args => $e->{args} }; + } + return; +} + +sub decompress_to { + my ($dec, $src, $dst) = @_; + open my $out, '>', $dst or die "Cannot write $dst: $!\n"; + binmode $out; + my $pid = open my $in, '-|'; + die "fork failed: $!\n" unless defined $pid; + unless ($pid) { + open STDIN, '<', File::Spec->devnull; + exec $dec->{prog}, @{ $dec->{args} }, $src; + exit 127; + } + binmode $in; + my $buf; + print {$out} $buf while read $in, $buf, 1 << 20; + close $in; + my $rc = $?; + close $out or die "Error writing $dst: $!\n"; + die "Failed to decompress $src (" . basename($dec->{prog}) . " exit " + . ($rc >> 8) . ").\n" if $rc != 0; +} + +# Returns the root of the extracted tree, or undef if the asset is a bare +# binary (then the download itself is the binary). +sub extract_if_archive { + my ($file, $tmpdir) = @_; + my $lc = lc basename($file); + + my $out = File::Spec->catdir($tmpdir, 'x'); + + if ($lc =~ /\.(tar\.gz|tgz|tar\.bz2|tbz|tar\.xz|txz|tar\.zst|tzst|tar)$/) { + mkdir $out or die "mkdir $out: $!\n"; + system('tar', '-xf', $file, '-C', $out) == 0 or die "Failed to extract $file.\n"; + } + elsif ($lc =~ /\.zip$/) { + which('unzip') or die "unzip not found, but needed for $lc.\n"; + mkdir $out or die "mkdir $out: $!\n"; + system('unzip', '-q', $file, '-d', $out) == 0 or die "Failed to extract $file.\n"; + } + elsif ($lc =~ /\.7z$/) { + my $z = which('7zz') || which('7z') || which('7za') + or die "7z not found, but needed for $lc.\n"; + mkdir $out or die "mkdir $out: $!\n"; + system($z, 'x', '-y', "-o$out", $file) == 0 or die "Failed to extract $file.\n"; + } + elsif (my ($ext) = $lc =~ /\.(gz|bz2|xz|zst|lz4|lzma)$/) { + # A single compressed file, e.g. restic_0.19.1_darwin_arm64.bz2 - + # the binary itself, just squeezed. + my $dec = decompressor($ext) + or die "Cannot unpack .$ext - install " . join('/', @{ DECOMP()->{$ext}{tools} }) + . " or pick another asset with --asset/--pattern.\n"; + mkdir $out or die "mkdir $out: $!\n"; + (my $stem = basename($file)) =~ s/\.\Q$ext\E$//i; + my $plain = File::Spec->catfile($out, $stem); + decompress_to($dec, $file, $plain); + } + else { + return undef; # bare binary + } + return $out; +} + +# Look for a file called $name; fall back to the single executable in the tree. +sub find_in_tree { + my ($root, $name) = @_; + + my @found; + my @stack = ($root); + while (my $dir = pop @stack) { + opendir my $dh, $dir or next; + for my $e (readdir $dh) { + next if $e eq '.' || $e eq '..'; + my $p = File::Spec->catfile($dir, $e); + if (-d $p) { push @stack, $p; next } + push @found, $p; + } + closedir $dh; + } + + my ($exact) = grep { basename($_) eq $name || basename($_) eq "$name.exe" } @found; + return $exact if $exact; + + my @exec = grep { looks_executable($_) } @found; + return $exec[0] if @exec == 1; + verbose("archive contains " . scalar(@found) . " files, " + . scalar(@exec) . " of them executable"); + return undef; +} + +# Magic bytes beat guessing by file size: ELF, Mach-O (incl. fat), PE, script. +sub looks_executable { + my $path = shift; + open my $fh, '<', $path or return 0; + binmode $fh; + read $fh, my $m, 4; + close $fh; + return 0 unless defined $m && length $m >= 2; + return 1 if $m =~ /^\x7fELF/; + return 1 if $m =~ /^(?:\xcf\xfa\xed\xfe|\xce\xfa\xed\xfe|\xca\xfe\xba\xbe|\xbe\xba\xfe\xca)/; + return 1 if $m =~ /^MZ/; + return 1 if $m =~ /^#!/; + return 0; +} + +sub install_atomic { + my ($src, $dest) = @_; + my $dir = dirname($dest); + -d $dir or die "Target directory $dir does not exist.\n"; + -w $dir or die "No write permission in $dir (use sudo, or pick another --install path).\n"; + + my $tmp = "$dest.new.$$"; + push @TMPFILES, $tmp; + open my $in, '<', $src or die "Cannot read $src: $!\n"; + open my $out, '>', $tmp or die "Cannot write $tmp: $!\n"; + binmode $in; + binmode $out; + my $buf; + print {$out} $buf while read $in, $buf, 1 << 20; + close $in; + close $out or die "Error writing $tmp: $!\n"; + chmod 0755, $tmp; + + # rename is atomic and works even while $dest is currently running. + rename $tmp, $dest or do { + my $err = $!; + unlink $tmp; + die "Cannot replace $dest: $err\n"; + }; + @TMPFILES = grep { $_ ne $tmp } @TMPFILES; +} + +sub strip_quarantine { + my $dest = shift; + return unless -x '/usr/bin/xattr'; + system(qq{/usr/bin/xattr -d com.apple.quarantine \Q$dest\E >/dev/null 2>&1}); +} + +# ============================================================================== +# Helpers +# ============================================================================== + +sub info { print "$_[0]\n" unless $opt{quiet} } +sub verbose { print " $_[0]\n" if $opt{verbose} } +sub trim { my $s = shift // ''; $s =~ s/^\s+|\s+$//g; return $s } + +sub parse_repo { + my $url = shift; + $url =~ s{/+$}{}; + $url =~ s{\.git$}{}; + $url = "https://$url" unless $url =~ m{^https?://}; + my ($scheme_host, $path) = $url =~ m{^(https?://[^/]+)(/.*)?$} + or die "Cannot parse repository URL: $url\n"; + $path //= ''; + $path =~ s{^/}{}; + # Anything before / is a base path (Gitea under a sub-path). + my @seg = split m{/}, $path; + die "Repository URL needs /: $url\n" if @seg < 2; + my ($o, $r) = splice @seg, -2; + return ($scheme_host . (@seg ? '/' . join('/', @seg) : ''), $o, $r); +} + +sub uri_esc { + my $s = shift; + $s =~ s{([^A-Za-z0-9._~-])}{sprintf '%%%02X', ord $1}ge; + return $s; +} + +sub host_of { my ($h) = ($_[0] // '') =~ m{^https?://([^/:]+)}i; return lc($h // '') } + +# Gitea and GitHub expose the same release JSON, only under different API +# roots and with different auth headers. +sub detect_forge { + my ($b, $override) = @_; + if (defined $override) { + my $f = lc $override; + die "Unknown forge '$override' (use github or gitea).\n" + unless $f eq 'github' || $f eq 'gitea'; + return $f; + } + return host_of($b) =~ /(^|\.)github\.com$/ ? 'github' : 'gitea'; +} + +sub api_base { + my ($b, $f) = @_; + return "$b/api/v1" unless $f eq 'github'; + return 'https://api.github.com' if host_of($b) =~ /(^|\.)github\.com$/; + return "$b/api/v3"; # GitHub Enterprise +} + +sub resolve_token { + my ($forge, $explicit) = @_; + return $explicit if defined $explicit; + my @env = $forge eq 'github' ? qw(UPD_TOKEN GITHUB_TOKEN GH_TOKEN) + : qw(UPD_TOKEN GITEA_TOKEN); + for my $k (@env) { + return $ENV{$k} if defined $ENV{$k} && length $ENV{$k}; + } + return ''; +} + +sub detect_platform { + my $spec = shift || {}; + my ($sysname, undef, undef, undef, $machine) = uname(); + my $o = lc $sysname; + $o = 'windows' if $o =~ /mingw|msys|cygwin|windows/; + $o = 'darwin' if $o =~ /darwin/; + $o = 'linux' if $o =~ /linux/; + + my $m = lc $machine; + my $a = $m =~ /^(x86_64|amd64)$/ ? 'amd64' + : $m =~ /^(aarch64|arm64)$/ ? 'arm64' + : $m =~ /^(i[3-6]86|x86)$/ ? '386' + : $m =~ /^armv?[5-8]/ ? 'arm' + : $m =~ /^(ppc64le|riscv64|s390x)$/ ? $m + : $m; + + return ($spec->{os} // $o, $spec->{arch} // $a); +} + +sub in_path { + my $dir = shift; + return grep { $_ eq $dir } split /:/, ($ENV{PATH} // ''); +} + +sub norm_ver { my $v = shift // ''; $v =~ s/^v//i; $v =~ s/^\s+|\s+$//g; return $v } + +# Run a program and capture stdout+stderr, with a timeout and no stdin. +sub capture { + my ($timeout, $prog, @args) = @_; + my $pid = open my $fh, '-|'; + return '' unless defined $pid; + unless ($pid) { + open STDIN, '<', File::Spec->devnull; + open STDERR, '>&', \*STDOUT; + exec $prog, @args; + exit 127; + } + my $out = ''; + local $SIG{ALRM} = sub { kill 'TERM', $pid }; + alarm $timeout; + { local $/; $out = <$fh> // '' } + alarm 0; + close $fh; + return $out; +} + +# Legacy fallback: ask the binary for its version (used when no state exists). +sub installed_version { + my ($path, $spec) = @_; + return '' unless -x $path; + my $flag = $spec->{'version-flag'} // $opt{'version-flag'}; + my $out = capture(10, $path, $flag); + my ($v) = $out =~ /(\d+\.\d+(?:\.\d+)*(?:[-+][\w.]+)?)/; + return norm_ver($v); +} + +sub list_releases { + my $rels = shift; + for my $r (@$rels) { + printf "%-12s %s%s\n", $r->{tag_name}, substr($r->{published_at} // '', 0, 10), + $r->{prerelease} ? ' [prerelease]' : ''; + printf " %-32s %s\n", $_->{name}, human_size($_->{size}) + for @{ $r->{assets} || [] }; + } +} + +sub human_size { + my $n = shift // 0; + return sprintf '%.1f MB', $n / 1024 / 1024 if $n >= 1024 * 1024; + return sprintf '%.1f kB', $n / 1024 if $n >= 1024; + return "$n B"; +} + +sub which { + my $cmd = shift; + for my $dir (split /:/, ($ENV{PATH} // '')) { + my $p = File::Spec->catfile($dir, $cmd); + return $p if -x $p && !-d $p; + } + return; +} + +sub read_json { + my $path = shift; + return undef unless -f $path; + my $body = slurp($path); + return eval { JSON::PP->new->utf8->decode($body) }; +} + +sub write_json { + my ($path, $data) = @_; + my $tmp = "$path.$$"; + push @TMPFILES, $tmp; + open my $fh, '>', $tmp or die "Cannot write $tmp: $!\n"; + print {$fh} JSON::PP->new->utf8->canonical->pretty->encode($data); + close $fh or die "Cannot write $tmp: $!\n"; + rename $tmp, $path or die "Cannot update $path: $!\n"; + @TMPFILES = grep { $_ ne $tmp } @TMPFILES; +} + +sub usage { + my $rc = shift; + print <<"USAGE"; +upd - download the matching binary from the latest Gitea/GitHub release + + upd [OPTIONS] REPO-URL + upd --all [OPTIONS] + + REPO-URL e.g. https://git.fhi.mpg.de/mike/mgsh + https://github.com/sxyazi/yazi + (or use --repo / \$UPD_REPO) + +Options: + --install PATH, -i target directory (created if missing), e.g. ~/bin. + A path whose last segment is one of the binary names, + or an existing file, means that exact file. + Also \$UPD_INSTALL. Default: the directory of a + same-named binary in \$PATH, else ~/.local/bin + --name A[,B...] binary name(s) to take out of one asset, e.g. + "yazi,ya" installs both. Use "SRC:DST" to install + under a different name (default: repository name) + --all update every entry of the config file + --config PATH config file (default: ~/.config/upd/tools) + --check only report whether an update is available + --tag VERSION install a specific release ("v1.2.3" or "1.2.3") + --pre consider prereleases as well + --asset NAME exact asset name instead of auto-detection + --pattern REGEX select the asset by regex + --os OS darwin|linux|windows|freebsd (default: detected) + --arch ARCH amd64|arm64|386|arm (default: detected) + --forge NAME github|gitea (default: github for github.com hosts, + gitea otherwise; needed for GitHub Enterprise) + --token TOKEN API token for private repositories. Also read from + \$UPD_TOKEN, then \$GITHUB_TOKEN/\$GH_TOKEN (GitHub) + or \$GITEA_TOKEN (Gitea) + --version-flag F flag to query the version of a binary installed + without upd (default: --version) + --force install even if it is already up to date + --list show releases and their assets + --dry-run show what would happen, write nothing + --verbose show asset scoring and cache decisions + --quiet print errors only + --timeout SEC network timeout (default: 30) + --help this help + +Config file (one line per tool, "#" comments): + https://git.fhi.mpg.de/mike/mgsh install=~/bin + https://github.com/sxyazi/yazi install=~/bin name=yazi,ya + Keys: @{[ join ', ', @SPEC_KEYS ]} + +State is kept in @{[ state_dir() ]} +Exit codes: 0 ok, 1 usage, 2 error, 10 update available (--check) +USAGE + exit $rc; +} + +1;