# `eval':
eval '
function grep {(unset grep; ( ulimitme; grep "$@"; ); );}
- function ls {(unset ls; ( ls -bF "$@"; ); );}
- function l { ls -lbF "$@"; }
+ if ls -d -bF / &>/dev/null;then
+ function ls {(unset ls; ( ls -bF "$@"; ); );}
+ else
+ # Alpine Linux
+ function ls {(unset ls; ( ls "$@"; ); );}
+ fi
+ function l { ls -l "$@"; }
if which vim &>/dev/null;then
alias vi="vim"
else
export PS1='[bash]${LOGNAME}@MOCK-'"`cat /MOCK`"':${PWD}# '
fi
export PS1='\[\017\]'"$PS1" # \017=std charmap
- if [ "${SHELL#*/com.termux/}" = "$SHELL" ];then
+ if [ "${SHELL#*/com.termux/}" = "$SHELL" -a "${SSH_CLIENT#2a02:2b88:6:3b57::8f }" = "$SSH_CLIENT" ];then
export PS1='\[\033%G\]'"$PS1" # \033%G=utf-8
fi
# Do not: kbd_mode -u # utf-8
export HISTFILESIZE="$HISTSIZE"
export GDBHISTFILE="$HOME/.gdb_history"
export CVS_RSH="ssh"
-export TZ="Europe/Prague"
-#export TZ="Canada/Eastern"
+export TZ="Asia/Manila"
+#export TZ="Europe/Prague"
+if [ "$TZ" = Asia/Manila ];then
+ alias date='TZ=Asia/Manila date;TZ=Europe/Prague date'
+fi
export PYTHONUNBUFFERED=1
export ASAN_OPTIONS=detect_leaks=0
export GTK_OVERLAY_SCROLLING=0
export MAKEFLAGS=
+export DEBUGINFOD_URLS=
cpus="`getconf _NPROCESSORS_ONLN`"
if [ -n "$cpus" ];then
# *3/2 was OOM for host1 32 CPUs + 16GB RAM
for i in "-v 2000000";do
(ulimit $i 2>/dev/null) && ULIMITME_OPTS="$ULIMITME_OPTS $i"
done
+if [ -z "$ULIMITME_OPTS" ];then
+ # MinGW64 would be printing "unlimited" on each ulimitme() execution.
+ ULIMITME_OPTS="-v unlimited"
+fi
# Prevent: ulimit: -m 100000 -d 150000 -v 200000: invalid number
# by forcing our known $IFS value; eval(1) is needed to take $IFS to effect:
-function ulimitme { IFS=" " eval "ulimit $ULIMITME_OPTS"; }
+function ulimitme { IFS=" " eval "ulimit 2>/dev/null $ULIMITME_OPTS"; }
function finame { find . -false `
awk </dev/null 'BEGIN{ for (i=1;i<ARGC;i++) print " -o -iname *"ARGV[i]"*"; }' "$@"
`; }
-o -name "*.[chCy]" \
-o -name "*.cc" \
-o -name "*.cxx" \
- -o -name "*.cpp" \
+ -o -name "*.[ch]pp" \
-o -name "*.[Ss]" \
-o -name "*.java" \
-o -name "*.p[lm]" \
-o -name "*.py" \
-o -name "*.exp" \
')' \
- |ctags --file-tags -L - --langmap=Tcl:+.exp "$@"
+ |ctags --extras=+f -L - --langmap=Tcl:+.exp "$@"
fi; );}
function ctagsh { ctags "--c-types=+px"; }
function cpan {(unset cpan; if [ $# = 0 ];then cpan;else perl -MCPAN -e "install qw($*);";fi; );}
---restrict-filenames -f bestvideo[ext=webm]+bestaudio[ext=webm]/bestvideo+bestaudio/best
+--restrict-filenames -f bestvideo[vcodec^=av01][height=2160]+bestaudio[acodec^=opus]/bestvideo[ext=webm][height=2160]+bestaudio[ext=webm]/bestvideo[height=2160]+bestaudio/best[height=2160]/bestvideo[vcodec^=av01][height=1440]+bestaudio[acodec^=opus]/bestvideo[ext=webm][height=1440]+bestaudio[ext=webm]/bestvideo[height=1440]+bestaudio/best[height=1440]/bestvideo[vcodec^=av01][height=1080]+bestaudio[acodec^=opus]/bestvideo[ext=webm][height=1080]+bestaudio[ext=webm]/bestvideo[height=1080]+bestaudio/best[height=1080]/bestvideo[vcodec^=av01][height<=?2160]+bestaudio[acodec^=opus]/bestvideo[ext=webm][height<=?2160]+bestaudio[ext=webm]/bestvideo[height<=?2160]+bestaudio/best[height<=?2160]
--- /dev/null
+--restrict-filenames
+++ /dev/null
-.lynxrc
-.procmailrc
-.esd_auth
-cgw
-.qt
-.ccache
-.koji
-.pki
-.Xauthority
-.openoffice.org
-.gconfd
-.bash_history
-.mozilla
-pserver
-.recently-used.xbel
-.lesshst
-.systemtap
-.perlmail-submit.log
-.fp
-.perlmail.log
-.cache
-.fetchmail.pid
-.lftp
-.ocp
-.emacs.d
-netpbm
-.fetchmailrc
-.gdb_history
-centrum
-.eclipse
-.spamassassin
-.aspell.en.pws
-.fedora-server-ca.cert
-.rnd
-.bashrc.local
-.python.valgrind
-.pgpkey
-include
-.gnome2_private
-priv
-.Xdefaults
-.local
-.muttrc.9000
-.hammock-result
-.kde
-.gitk
-.ssh2
-.netbeans
-.xine
-secure
-.wine
-.mysql_history
-.forward
-energie-WWW
-.lynx_cookies
-.wgetrc
-.cvspass
-.cpan
-.swo
-.aspell.en.prepl
-.swp
-.gstreamer-0.10
-.netrwhist
-.fontconfig
-Mail
-.fedora-upload-ca.cert
-d
-.gnupg
-.muttrc.priv
-.dbus
-.phorum
-.gconf
-.fedora
-.fedora.cert
-.viminfo
-.thumbnails
-.=.swp
-.gnome2
-lib
-staticnss
-.gvfs
-.ssh-redhat-last
-viewcvs
-.Scilab
-.octave_hist
-.texlive2007
-.config
set history save on
# https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=106814
set complaints 0
-set record insn-number-max 10000000
+set record full insn-number-max 10000000
+define u
+ up
+end
+document u
+up
+end
define javadump
call _Jv_DeepDebug($arg0)
end
document javadump
call _Jv_DeepDebug($arg0)
end
+define pjstr
+ p *$arg0._body@$arg0._length
+end
define pglist
if (*("$arg1")=='@')
set var $arg1=struct $arg1
+++ /dev/null
-ChangeLog merge=git-merge-changelog
[user]
name = Jan Kratochvil
- email = jan.kratochvil@redhat.com
+# use: .gitconfig.local
+# email = jan@jankratochvil.net
+[include]
+ path = .gitconfig.local
+[init]
+ defaultBranch = master
[merge]
conflictstyle = diff3
+ renamelimit = 10000
[color]
ui = never
[pull]
ff = only
# rebase = true
-# ChangeLog merge attempt:
-#[merge "git-merge-changelog"]
-# name = git-merge-changelog
-# driver = /usr/bin/git-merge-changelog %O %A %B
-# ChangeLog merge attempt:
-#[core]
-# attributesfile = ~/.gitattributes
# golang:
#[http]
# cookiefile = /home/jkratoch/.gitcookies
[branch]
sort = committerdate
# FIXME: It does not work:
-[blame]
- ignoreRevsFile = ~/.gitconfig-ignoreblamecommit
+#[blame]
+# ignoreRevsFile = ~/.gitconfig-ignoreblamecommit
[format]
signature =
+
+# Big files cludge:
+#[core]
+# compression=1
+# bigFileThreshold=100g
+#[pack]
+# depth=2
+# window=2
+# threads=1
--- /dev/null
+pinentry-timeout 1000000000
source ~/.muttrc.addons
source ~/.muttrc.9000
+set from="jan@jankratochvil.net"
source ~/.muttrc.priv
-set from="jan@jankratochvil.net"
set envelope_from
-set query_command="${HOME}/bin/mutt_ldap_query '%s'"
alternates "^(.*@(.*\\.)?jankratochvil\\.net|short(\\+[^@]*)?@(ucw\\.cz|atrey\\.karlin\\.mff\\.cuni\\.cz|k332\\.feld\\.cvut\\.cz|(alcor|amiga)\\.ericsson\\.cz|short\\.mj\\.gts\\.cz|short\\.short|(.*\\.)?(vellum|valley)\\.cz)|.*@((.*\\.)?short\\.ucw\\.cz|dialup\\.netbeans\\.com|kratochvil\\.suse\\.cz)|kratochvil(\\+[^@]*)?@(users\\.sourceforge\\.net|(.*\\.)?suse\\.cz)|lace(\\+[^@]*)?@valinux\\.co\\.jp|(jan\\.kratochvil|jkratoch)(\\+[^@]*)?@redhat\\.com|jkratoch@sourceware.org)$"
+folder-hook "=jklabs" set from=jan.kratochvil@jklabs.cz
+folder-hook "=penzion" set from=info@penzionspicak.cz
+#folder-hook "=penzion" set askcc=true
+
alias gdb gdb@sourceware.org
alias gdbpat gdb-patches@sourceware.org
alias archer archer@sourceware.org
alias binutils binutils@sourceware.org
alias gccpat gcc-patches@gcc.gnu.org
+alias steph Marie Stephanie Kratochvilova <istephielicious@gmail.com>
unset strict_threads
# tw=78 is for gq and RFC 2822 section 2.1.1.
set editor="vim -c 'set noai' -c 'set ts=8' -c 'set tw=78'"
-set send_charset="us-ascii:iso-2022-jp:utf-8"
+set send_charset="us-ascii:utf-8"
set charset="utf-8"
set autoedit
set auto_tag
macro pager <Esc>f ":set pager_index_lines=0\n
macro pager <Esc>g ":set pager_index_lines=10\n"
set user_agent
+set abort_noattach=ask-yes
+# https://unix.stackexchange.com/a/42714/296319
+auto_view text/html # view html automatically
+alternative_order text/plain text/enriched text/html # save html for last
+bind attach <return> view-mailcap
# Mail command
##############
bind index \ca mail
macro index M ":set dsn_return=hdrs\n:set dsn_notify=failure,delay,success\n^a" "DSN compose of a new mail message"
macro index m ":unset dsn_return dsn_notify\n^a" "Standard compose of a new mail message"
+bind index \cb reply
+macro index R ":set dsn_return=hdrs\n:set dsn_notify=failure,delay,success\n^b" "DSN compose of a reply"
+macro index r ":unset dsn_return dsn_notify\n^b" "Standard compose of a reply"
# quote 'macro' argument to prevent: macro: too many arguments
# `spamassassin {--report|--revoke}' calls `sa-learn {--spam|--ham}' automatically.
set pipe_split
color tree brightmagenta black # the thread tree in the index menu
color tilde brightmagenta black
color message brightcyan black
-color normal white black
+color normal brightwhite black
color attachment brightmagenta black
color search black green # how to hilite search patterns in the pager
color body brightyellow black "(ftp|http)://[^ ]+" # point out URLs
+++ /dev/null
-random_seed
-identity
-identity.pub
-IdentityFile ~/.ssh/id_dsa
IdentityFile ~/.ssh/id_rsa
+IdentityFile ~/.ssh/id_dsa
+IdentityFile ~/.ssh/id_rsa-old
IdentityFile ~/.ssh/identity
IdentityFile ~/.ssh/koji-id_rsa
IdentityFile ~/.ssh/id_dsa-sourceware
+IdentityFile ~/.ssh/id_ed25519
Host localhost
#Cipher none
Compression no
-Host sebastian.redhat.com ovpn-phx2.redhat.com 209.132.183.3
-ControlMaster auto
-ControlPath /tmp/ssh-%h-%p-%r.sock
-# Required for: http://intranet.corp.redhat.com/ic/intranet/LWNReminder.html
-# =squid.rdu.redhat.com=file.rdu.redhat.com
-LocalForward 3228 squid.redhat.com:8080
-# Looks to be stucking (=squid.redhat.com=10.11.255.147):
-LocalForward 3328 squid.corp.redhat.com:3128
-LocalForward 3428 squid.brq.redhat.com:3128
-LocalForward 3528 squid.bos.redhat.com:8080
-LocalForward 3025 smtp.corp.redhat.com:25
-#LocalForward 3025 mail.stuttgart.redhat.com:25
-#LocalForward 3993 pobox.devel.redhat.com:993
-#LocalForward 3983 pobox.stuttgart.redhat.com:993
-LocalForward 3973 mail.corp.redhat.com:993
-# Now being gatewayed: LocalForward 6668 irc.freenode.net:6667
-LocalForward 6668 barstool.build.redhat.com:6688
-# http://intranet.corp.redhat.com/ic/intranet/IRCServerList.html
-# devserv.devel.redhat.com is obsolete? "administratively prohibited" now.
-LocalForward 6670 devserv.devel.redhat.com:6667
-LocalForward 6671 porky.stuttgart.redhat.com:6667
-LocalForward 6672 irc.devel.redhat.com:6667
-LocalForward 6673 irc-2.devel.redhat.com:6667
-LocalForward 6674 irc.yyz.redhat.com:6667
-#LocalForward 3389 ldap.stuttgart.redhat.com:389
-LocalForward 3389 ldap.str.redhat.com:389
-LocalForward 3046 curly.devel.redhat.com:4046
-LocalForward 3047 curly.devel.redhat.com:2049
-LocalForward 3234 engarchive.rdu.redhat.com:1234
-LocalForward 3235 engarchive.rdu.redhat.com:2049
-# RHTS:
-LocalForward 3290 rhts.redhat.com:80
-LocalForward 3293 rhts.redhat.com:443
-# www.farm.hsv.redhat.com - http://farmer.farm.hsv.redhat.com/
-LocalForward 3291 www.farm.hsv.redhat.com:80
-# /tmp/tts-fill.sh
-LocalForward 3292 tts.englab.brq.redhat.com:443
-# monotone: elfutils
-LocalForward 4691 ups.hsv.redhat.com:4691
-# Brew is too slow remotely:
-# http://brewhub.devel.redhat.com/brewhub
-#LocalForward 3280 brewhub.devel.redhat.com:80
-#LocalForward 3088 kerberos.corp.redhat.com:88
-# Using RHTS repository instead:
-#LocalForward 3180 devserv.devel.redhat.com:3180
-# [redhat.com #915466]
-LocalForward 3190 calendar.corp.redhat.com:443
-LocalForward 3196 mail06.corp.redhat.com:443
-# redhat.com XMPP
-LocalForward 3222 chat.corp.redhat.com:5222
-# brq.redhat.com XMPP
-LocalForward 3223 services.brq.redhat.com:5222
-# cvs.devel.redhat.com pserver+ssh
-LocalForward 3401 cvs.devel.redhat.com:2401
-LocalForward 3422 cvs.devel.redhat.com:22
-GatewayPorts yes
-# Kerberos
-LocalForward 3749 kerberos.corp.redhat.com:749
-LocalForward 3880 kerberos.rdu.redhat.com:88
-LocalForward 3881 kerberos.bos.redhat.com:88
-LocalForward 3882 kerberos.hsv.redhat.com:88
-LocalForward 3883 genbu.tokyo.redhat.com:88
-LocalForward 3884 kerberos.stuttgart.redhat.com:88
-LocalForward 3885 kerberos.bne.redhat.com:88
-LocalForward 3886 kerberos.iad.redhat.com:88
-
-ProxyCommand none
-StrictHostKeyChecking yes
-Host rawhide64.englab.brq.redhat.com shell.lab.bos.redhat.com
+Host rawhide64.englab.brq.redhat.com shell.lab.bos.redhat.com liver2.lab.eng.brq.redhat.com *.s390.bos.redhat.com tools-qe-01.lab.eng.brq.redhat.com
User jkratoch
-Host tofu.yyz.redhat.com
-User hudson
+#Host tofu.yyz.redhat.com
+#User hudson
Host power05.str.redhat.com
User root
Port 30
-Host *.test.redhat.com *.lab.boston.redhat.com *.rhts.boston.redhat.com *.lab.bos.redhat.com *.eng.bos.redhat.com *.rhts.bos.redhat.com *.z900.redhat.com *.cambridge.redhat.com *.gsslab.rdu.redhat.com prdell.brq.redhat.com *.englab.brq.redhat.com *.eng.brq.redhat.com *.rhts.eng.rdu.redhat.com *.rhts.eng.nay.redhat.com *.s390.bos.redhat.com dhcp45.install.bos.redhat.com
+Host *.test.redhat.com *.lab.boston.redhat.com *.rhts.boston.redhat.com *.lab.bos.redhat.com *.eng.bos.redhat.com *.rhts.bos.redhat.com *.z900.redhat.com *.cambridge.redhat.com *.gsslab.rdu.redhat.com *.gsslab.rdu2.redhat.com prdell.brq.redhat.com *.englab.brq.redhat.com *.eng.brq.redhat.com *.rhts.eng.rdu.redhat.com *.rhts.eng.nay.redhat.com *.s390.bos.redhat.com dhcp45.install.bos.redhat.com *.lab.eng.rdu.redhat.com *.rhts.gsslab.pek.redhat.com *.ss.eng.rdu.redhat.com *.rhts.eng.*.redhat.com *.lab.eng.rdu2.redhat.com
User root
UserKnownHostsFile /dev/null
-Host cvs.fedora.redhat.com sources.redhat.com ovpn-phx2.redhat.com 209.132.183.3
-ProxyCommand none
-StrictHostKeyChecking yes
+AddressFamily inet
Host ovpn-phx2.redhat.com 209.132.183.3
Port 330
User jkratoch
-Host *.redhat.com porkchop devserv barstool 192.168.79.133 shell shell.lab.bos.redhat.com
+Host *.redhat.com porkchop devserv barstool 192.168.79.133 shell shell.lab.bos.redhat.com pkgs.devel.redhat.com
User jkratoch
-#ProxyCommand /usr/bin/ssh sebastian.redhat.com exec nc %h %p
-#ProxyCommand /usr/bin/ssh ovpn-phx2.redhat.com exec nc %h %p
-#ProxyCommand /usr/bin/ssh 209.132.183.3 exec nc %h %p
-#ProxyCommand /usr/bin/ssh host0 /usr/bin/ssh 209.132.183.3 exec nc %h %p
-###bastion:
-###ProxyCommand /usr/bin/ssh -W %h:%p 209.132.183.3
-# iptables -t nat -A OUTPUT -p tcp -d 10.10.36.184 --dport 6667 -j DNAT --to-destination 127.0.0.1:6671
-# iptables -t nat -A OUTPUT -p tcp -d 10.4.122.10 --dport 25 -j DNAT --to-destination 127.0.0.1:3025
StrictHostKeyChecking no
NumberOfPasswordPrompts 6
-Host shell
-HostName shell.lab.bos.redhat.com
-HostKeyAlias shell.lab.bos.redhat.com
-Host porkchop
-HostName porkchop.devel.redhat.com
-HostKeyAlias porkchop.devel.redhat.com
-Host devserv
-HostName devserv.devel.redhat.com
-HostKeyAlias devserv.devel.redhat.com
-Host barstool
-HostName barstool.build.redhat.com
-HostKeyAlias barstool.build.redhat.com
-#Host cvsdevelrh
-#HostName 192.168.67.2
-#User jkratoch
-#Port 3422
-#HostKeyAlias cvs.devel.redhat.com
-Host git.fedorahosted.org fedorahosted.org
+Host git.fedorahosted.org fedorahosted.org *.fsffrance.org
User jankratochvil
-Host *.fsffrance.org
+# https://fedoraproject.org/wiki/Test_Machine_Resources_For_Package_Maintainers
+Host pkgs.fedoraproject.org *.fedorainfracloud.org *.cloud.fedoraproject.org
User jankratochvil
Host virt
# 172.1[6-9].* 172.2[0-9].* 172.3[0-1].*
-User root
+#User root
UserKnownHostsFile /dev/null
StrictHostKeyChecking no
Compression no
HostName 172.20.0.2
-Host bombadil.infradead.org
-User lace
+Host mac
+HostName mac10
+Host mac mac10
+User macbook
+Host virtmac macvirt
+HostName virt
+User macbook
+UserKnownHostsFile /dev/null
+StrictHostKeyChecking no
+Compression no
+HostName 172.20.0.2
-Host nokia6
-User root
+host rh-power-vm17.fit.vutbr.cz
+User jankratochvil
-Host hotelgate hotelgate.hotelsevendays.cz
-User root
-Host hotelgate
-HostName hotelgate.hotelsevendays.cz
-HostKeyAlias hotelgate.hotelsevendays.cz
+Host gitlab.gnome.org
+User jankratochvil
-Host gw.jklabs.cz
+Host bombadil.infradead.org
User lace
-Host tercie.tone.cz
-User short
+Host gw.jklabs.cz
+User root
Host fencepost.gnu.org
User jankratochvil
HostKeyAlias manon.vellum.cz
Host dolly.vellum.cz
User short
-Host rallye.panda.cz
-User short
Host atrey.karlin.mff.cuni.cz
User short
-Host deda
+Host jklabs-sh-server jklabs-sh-server.jankratochvil.net
+User root
+
+Host download-stock
+HostName vps2.jankratochvil.net
+HostKeyAlias vps2.jankratochvil.net
+
+Host cosmo8 cosmo8.jankratochvil.net cosmo8t.jankratochvil.net p20
+Port 8022
+
+# Cosmo:
+Match localuser u0_a184 originalhost vps2
+Hostname vps2.jankratochvil.net
+User lace
+Match localuser u0_a184 originalhost host1
+Hostname host1.jankratochvil.net
+Match localuser u0_a184 originalhost host1,host1vps2
+User lacemail
+Compression yes
+Match localuser u0_a184 originalhost pi
+Hostname pi.jankratochvil.net
User root
-Host jklabs-server
+Host host1 host1s host14
+Compression no
+Host host1vps2
+HostName vps2-ipv4.jankratochvil.net
+Port 122
+Host host14 host1vps2
+HostName host1
+HostKeyAlias host1
+
+Host host2
+ControlMaster auto
+ControlPath /tmp/ssh-%h-%p-%r.sock
+ControlPersist 60
+
+# OpenWrt
+# https://bugzilla.redhat.com/show_bug.cgi?id=1881301#c38
+Host 192.168.66.13 ap13
+#PubkeyAcceptedKeyTypes ssh-rsa
User root
+Host dev? dev?.azulsystems.com
+User jkratochvil
+Host dev1 dev1.azulsystems.com dev2 dev2.azulsystems.com
+#PubkeyAcceptedKeyTypes ssh-rsa
+PubkeyAcceptedKeyTypes +ssh-rsa,ssh-dss
+HostKeyAlgorithms=+ssh-dss
+Host dev1
+HostName dev1.azulsystems.com
+Host dev2
+HostName dev2.azulsystems.com
+Host dev3
+HostName dev3.azulsystems.com
+Host rpi4-05
+HostName rpi4-05.azulsystems.com
+Host rpi4-06
+HostName rpi4-06.azulsystems.com
+Host rpi4-* rpi4-*.azulsystems.com
+User jenkins
+Host zulu-dev
+User ubuntu
+HostName 10.10.164.222
+
Host *
Compression yes
-CompressionLevel 9
+# no longer supported: CompressionLevel 9
ForwardAgent no
ConnectionAttempts 1
UsePrivilegedPort no
-RhostsRSAAuthentication no
+# no longer supported: RhostsRSAAuthentication no
ForwardX11 no
ServerAliveInterval 60
StrictHostKeyChecking ask
if !exists("g:_kratochvil_vimrc")
let g:_kratochvil_vimrc=1
-autocmd! filetypedetect
+"autocmd! filetypedetect
"remove 'set tw=78':
autocmd! BufRead *.txt
autocmd BufCreate,VimEnter * let g:BufEnter_ts= 8
autocmd BufEnter * call BufEnter()
autocmd VimEnter * call BufEnter()
-set runtimepath=.,$VIMRUNTIME
+set runtimepath+=.,$VIMRUNTIME
function BufEnter()
if exists("g:BufEnter_ts")
unlet g:BufEnter_ts
endif
endfunction
-set encoding=utf-8
-set termencoding=utf-8
+"set encoding=utf-8
+"set termencoding=utf-8
" fileencoding is detected from fileencodings, first one for empty files
" 'iso-8859-2,euc-jp' really does not work for 'euc-jp'
-set fileencodings=utf-8,euc-jp,iso-8859-2
+"set fileencodings=utf-8,euc-jp,iso-8859-2
set ts=8
set sw=2
ca X x
syntax off
let g:loaded_matchparen = 1
-set swapsync=
+if !has('nvim')
+ set swapsync=
+endif
" vim-7+ only
silent! set nofsync
set noerrorbells
set nofoldenable
set fo=tcq1
set nojoinspaces
+set clipboard=
"set textwidth=78
set viminfo='100,\"1000,:100,/40
let g:netrw_home = $HOME
set tags=./tags,./TAGS,./../tags,./../TAGS,./../../tags,./../../TAGS,./../../../tags,./../../../TAGS,./../../../../tags,./../../../../TAGS,./../../../../../tags,./../../../../../TAGS,./../../../../../../tags,./../../../../../../TAGS,./../../../../../../../tags,./../../../../../../../TAGS,./../../../../../../../../tags,./../../../../../../../../TAGS,./../../../../../../../../../tags,./../../../../../../../../../TAGS,./../../../../../../../../../../tags,./../../../../../../../../../../TAGS,./../../../../../../../../../../../tags,./../../../../../../../../../../../TAGS,./reactos/tags,./../reactos/tags,./../../reactos/tags,,./../../../reactos/tags,./../../../../reactos/tags,./../../../../../reactos/tags,./../../../../../../reactos/tags,./w32/inc/tags,./../w32/inc/tags,./../../w32/inc/tags,,./../../../w32/inc/tags,./../../../../w32/inc/tags,./../../../../../w32/inc/tags,./../../../../../../w32/inc/tags,./../../../../../../../w32/inc/tags,/usr/src/redhat/BUILD/tags,/usr/src/redhat/BUILD/TAGS,/usr/include/tags,/usr/include/TAGS
noremap <Esc>p :set invpaste paste?<cr>
-noremap <Esc>l :set invlist paste?<cr>
+noremap <Esc>l :set invlist list?<cr>
noremap <Esc>q @q
noremap <Esc>: @:
noremap <C-n> :next<cr>zz<C-g>
noremap <C-p> :prev<cr>zz<C-g>
noremap <Esc>N :tn<cr>zz<C-g>
-noremap <Esc>P :tp<cr>zz<C-g>
-"<Esc>P would auto-type random data after starting it on recent distros or Termux.
-"read(0, "\33P1$r0 q\33\\\33[?12;4$y", 4096) = 19
-noremap <Esc>P$r0<Space>q <Nop>
+if $ANDROID_DATA!=#"/data" && $SSH_CLIENT!~"^2a02:2b88:2:1::3b57:[89]f "
+ " It auto-types random data after starting it from Termux
+ " Now all VIM version are affected:
+ noremap <Esc>P :tp<cr>zz<C-g>
+ noremap <Esc>P1$r0<Space>q <Nop>
+endif
" Termux types <F11>
noremap! <Esc>[23~ <Nop>
noremap <Esc>M :cn<cr>zz<C-g>
noremap <Esc>L :cp<cr>zz<C-g>
-noremap <Esc>f "myiw:grep<Space>-Ew<Space>'<C-r>m'<Space>`git ls-files`
+" dnf install vim-fugitive
+noremap <Esc>f "myiw:Ggrep<Space>-Ew<Space>'<C-r>m'<Space>
+noremap <Esc>F "myiw:grep<Space>-Ew<Space>'<C-r>m'<Space>`git ls-files`
noremap <Esc>g "myiw:grep<Space>-rEw<Space>'<C-r>m'<Space>.
noremap <C-]> <C-]>zz<C-g>
noremap <C-t> <C-t>zz<C-g>
noremap <C-d> G:r !date '+\%H:\%M:\%S-'<cr>kA
-noremap <Esc>d :set hlsearch<cr>/^[+-]\([^+-].*\\|\)$<cr>
-noremap <Esc>D :set hlsearch<cr>/^[+-][+-]\([^+-].*\\|\)$<cr>
+noremap <Esc>s :set hlsearch<cr>/^[+-]\([^+-].*\\|\)$<cr>
+noremap <Esc>S :set hlsearch<cr>/^[+-][+-]\([^+-].*\\|\)$<cr>
noremap <Esc>w 0i <Esc>/[^ ]<cr>vf.h"kyf./[^ ]<cr>vf.h"ly0x:r !date -d "`date '+\%Y'`-<C-r>l-<C-r>k" '+\%u'<cr>yypkV:!tr '1234567' 'PUSCPSN'<cr>jV:!tr '1234567' 'otttaoe'<cr>kJxv0xk0llllllplxxjddk0
+noremap <Esc>e :syntax on<cr>:set syntax=wdiff<cr>
noremap * :let ic_save=&ic<cr>:set noic<cr>*:let &ic=ic_save<cr>
noremap # :let ic_save=&ic<cr>:set noic<cr>#:let &ic=ic_save<cr>
noremap <C-k> :w<cr>:!aspell --check '%'<cr>:e<cr>
noremap gq] gq/^. \?$<cr>
noremap <Esc>1 :w<cr>:make -j1<cr>
-noremap <Esc>m :w<cr>:make<cr>
+noremap <Esc>3 /^<char-60><char-60><char-60><char-60><char-60><char-60><char-60><cr>kmajd$V/^<bar><bar><bar><bar><bar><bar><bar><cr>k:w! 1<cr>gvxd$V/^=======<cr>k:w! 2<cr>gvxd$V/^<char-62><char-62><char-62><char-62><char-62><char-62><char-62><cr>k:w! 3<cr>gvxdd'a0:!diff -u 2 1;diff -u 2 3<cr>
+noremap <Esc>m :w<cr>:set makeprg=make<cr>:make<cr>
+noremap <Esc>n :w<cr>:set makeprg=ninja<cr>:make<cr>
endif "!exists("g:_kratochvil_vimrc")
+++ /dev/null
-unmime
-flock
-nmap
-hexedit
-ghortident
-rmd160
-urlencode
-webcopy
-weblint
-cvs
-
-python2.1
-python
-pydoc
-
-grep
-egrep
-fgrep
-
-ldconfig-docache
-
-iconv
-mutt
-pgpring
-pgpewrap
-
-perl
-perl5.6.1
-a2p
-c2ph
-h2ph
-h2xs
-perlbug
-perldoc
-pl2pm
-splain
-perlcc
-dprofpp
-s2p
-pod2man
-find2perl
-pod2html
-pod2latex
-pod2text
-pod2usage
-podchecker
-podselect
-pstruct
-
-GET
-lwp-mirror
-lwp-request
-lwp-download
-lwp-rget
-HEAD
-POST
-
-xmlwf
-yapp
-pngtogd
-pngtogd2
-gdtopng
-gd2topng
-gd2copypal
-gdparttopng
-webpng
-bdftogd
-xpath
-dbiproxy
-dbish
-xql.pl
-ttree
-tpage
-
-php
-phpextdist
-phpize
-php-config
-pear
--- /dev/null
+#! /bin/bash
+# openjdk: export PATH="$(echo "$PATH"|sed 's#:/usr/lib64/ccache:#:'$HOME'/ccache:#')";bash configure --disable-precompiled-headers --disable-ccache
+set -ex
+rm -rf ~/ccache
+mkdir ~/ccache
+cd ~/ccache
+for i in /usr/lib64/ccache/*;do
+ j=`basename $i`
+ echo -e '#! /bin/bash\nexport PATH="$(echo "$PATH"|sed s#:$HOME/ccache:#:#)"\nexec '$i' "$@"' >$j
+ chmod +x $j
+done
+echo done
--- /dev/null
+#! /bin/bash
+n=false
+if [ $1 = -n ];then
+ n=true
+ shift
+fi
+diff_u="diff $(if $n;then echo -U999999999;else echo -u;fi)"
+if [ $# != 2 ];then
+ echo >&2 "$0: <dir1> <dir2>"
+fi
+for dir in "$@";do
+ if [ ! -e $dir ];then
+ echo >&2 "!-e: $dir"
+ exit 1
+ fi
+ sed -i -e 's#\(failed for \)[0-9]*\(: Operation not permitted\)#\1\2#' $(find $dir -name summary.txt)
+done
+dir1=$(realpath $1)
+dir2=$(realpath $2)
+cd $1
+(
+ for i in $(find -name summary.txt);do
+ echo "$dir1/$i -> $dir2/$i"
+ $diff_u $i $dir2/$i
+ done
+ function prep8
+ {
+ sed <$1 -n 's/^\(Passed\|FAILED\): \(.*\)$/\2: \1/p'|sort
+ }
+ for i in $(find -name "*-test.release.log");do
+ echo "$dir1/$i -> $dir2/$i"
+ $diff_u <(prep8 $i) <(prep8 $dir2/$i)
+ done
+)|if $n;then cat;else grep -v '^+++ '|grep -v '^--- '|grep -v '^[ @]';fi
--- /dev/null
+#! /bin/bash
+for arg in $@;do
+ # http://cherry.azulsystems.com:8080/job/zulu17-silver-build/377/
+ arg="$(echo $arg|sed 's#[a-z]\+/\?$##')"
+ build="$(echo $arg|sed -n 's#^.*/\([0-9]\+\)/$#\1#p')"
+ if [ -z "$build" ];then
+ echo >&2 "parse error: $arg"
+ exit 1
+ fi
+ build="build$build"
+ if [ -e "$build" ];then
+ echo >&2 "exists: $build"
+ exit 1
+ fi
+ mkdir $build
+ outcome="$(wget -O - "${arg}artifact/outcome/")"
+ if [ -z "$outcome" ];then
+ echo >&2 "no outcome: $arg"
+ exit 1
+ fi
+ for release in $(echo "$outcome"|perl -ne 'while (m{<a href="([^"]*)/release">}g) { print "$1\n"; }');do
+ # java17, java8
+ ok=false
+ for file in test-results.tar.gz test.release.log;do
+ url="${arg}artifact/outcome/$release/release/$file"
+ if wget --read-timeout=5 -O "$build/$release-$file" "$url";then
+ ok=true
+ break
+ fi
+ rm -f "$build/$release-$file"
+ done
+ if ! $ok;then
+ echo >&2 "wget error"
+ exit 1
+ fi
+ done
+ (cd $build;if compgen -G "*test-results.tar.gz";then exx *test-results.tar.gz;fi)
+done
--- /dev/null
+#! /usr/bin/perl
+use strict;
+use warnings;
+my $file;
+while (<STDIN>) {
+ if (/^[^+-]/) {
+ $file=$_;
+ next;
+ }
+ my $match;
+ for my $arg (@ARGV) {
+ $match=1 if /\Q$arg\E/;
+ }
+ next if !$match;
+ if (defined $file) {
+ print $file;
+ $file=undef;
+ }
+ print;
+}
#mcheck="-lmcheck"
fast=false
readline=""
-disablebinutils="--disable-binutils --disable-gas --disable-gold --disable-gprof --disable-ld"
+disablebinutils="--disable-binutils --disable-gas --disable-gold --disable-gprof --disable-ld --disable-gprofng"
python=""
while true
"rpm" =>'rpm2cpio $pathname|cpio -id --quiet', #-v #FIXME: --sparse doesn't work, why?
"zip" =>'unzip -Lq $pathname',
"jar" =>'unzip -Lq $pathname',
+ "xpi" =>'unzip -Lq $pathname',
+ "crx" =>'unzip -Lq $pathname',
"a" =>'ar x $pathname',
"deb" =>'ar x $pathname;'
.'for i in *.tar.gz;do j=`basename $i .tar.gz`;mkdir -p $j;cd $j;tar xzf ../$i;cd ..;rm -f $i;done',
--- /dev/null
+#! /bin/bash
+# https://stackoverflow.com/a/37668768/2995591
+git bisect visualize --oneline|wc -l|perl -MPOSIX -lne 'print "Bisecting: ".floor(($_-1)/2)." revisions left to test after this (roughly ".(floor(log($_-1)/log(2))-1)." steps)" if $_'
--- /dev/null
+#! /bin/bash
+# https://stackoverflow.com/a/424142/2995591
+exec git show --pretty="" --name-only "$@"
--- /dev/null
+#! /usr/bin/perl
+# * * * * * nice -n20 /root/bin/heat -s
+use strict;
+use warnings;
+my $schedulefile="/root/heat.schedule";
+my $statefile="/root/heat.state";
+my $resetfile="/root/heat.reset";
+my $usbrelay="/root/bin/usbrelay";
+my $logfile="/var/log/heat.log";
+require POSIX;
+$|=1;
+sub readfile($) {
+ my($fname)=@_;
+ local *F;
+ if (!open F,$fname) {
+ warn "$fname: $!";
+ return undef;
+ }
+ my $F=do { local $/; <F>; };
+ defined $F or die "read $fname: $!";
+ close F or die "read-close $fname: $!";
+ return $F;
+}
+sub writefile($$;$) {
+ my($fname,$content,$mode)=@_;
+ local *F;
+ open F,($mode||">").$fname or die "$fname: $!";
+ print F $content or die "write $fname: $!";
+ close F or die "write-close $fname: $!";
+}
+sub logmsg($) {
+ my($s)=@_;
+ chomp $s;
+ writefile $logfile,POSIX::strftime("%Y-%m-%dT%H:%M:%S",localtime)." $s\n",">>";
+}
+sub spawn($) {
+ my($cmd)=@_;
+ $cmd.=" >&2";
+ system $cmd and die "$cmd: $!";
+}
+my($trash,$min,$hour)=localtime;
+my $minutes=$hour*60+$min;
+if (($ARGV[0]||"")=~/^[@]0?(\d+):0?(\d+)$/) {
+ $minutes=$1*60+$2;
+ shift;
+}
+my $finishline;
+my %schedule;
+my $schedule;
+if (-e $schedulefile) {
+ $schedule=readfile $schedulefile;
+ while ($schedule=~s/^(0?(\d+):0?(\d+)) ([01s])\n//) {
+ my $tm=$2*60+$3;
+ warn "$schedulefile set twice for: $1" if defined $schedule{$tm};
+ $schedule{$tm-24*60}="$1 $4\n";
+ $schedule{$tm }="$1 $4\n";
+ $schedule{$tm+24*60}="$1 $4\n";
+ }
+ warn "$schedulefile garbage: $schedule" if $schedule ne "";
+ warn "Empty $schedulefile" if !%schedule;
+}
+sub schedulenext($) {
+ return undef if !%schedule;
+ my($now)=@_;
+ my($bestprev,$prev,$bestnext,$next);
+ for my $found (keys(%schedule)) {
+ if ($found<=$now) {
+ next if defined $bestprev&&$bestprev>$found;
+ $bestprev=$found;
+ $prev=$schedule{$found};
+ } else {
+ next if defined $bestnext&&$bestnext<$found;
+ $bestnext=$found;
+ $next=$schedule{$found};
+ }
+ }
+ die "No bestprev" if !defined $bestprev;
+ die "No bestnext" if !defined $bestnext;
+ return [$prev,$next];
+}
+$finishline=schedulenext($minutes);
+$finishline=[$finishline->[1]] if $finishline;
+my $silent=shift if ($ARGV[0]||"") eq "-s";
+logmsg "command: ".join(" ",@ARGV) if !$silent&&@ARGV;
+sub info($) {
+ my($s)=@_;
+ print $s if !$silent;
+}
+sub finish() {
+ info join("",@$finishline) if defined $finishline;
+ exit 0;
+}
+my $reset=readfile $resetfile if -e $resetfile;
+my($resetminutes,$resetstate);
+sub resetread() {
+ $reset=~/^0?(\d+)[:.]0?(\d+) ([01s]|reset)\n$/ or warn "Invalid $resetfile: $reset";
+ $resetminutes=$1*60+$2;
+ $resetstate=($3 eq "reset"?undef:$3);
+}
+sub unlink_resetfile() {
+ unlink $resetfile or die "$resetfile: $!";
+ logmsg "remove reset: $reset";
+ $reset=$resetminutes=undef;
+}
+if (defined $reset) {
+ resetread;
+ unlink_resetfile if $resetminutes==$minutes;
+}
+sub finishlinereset() {
+ $finishline=schedulenext $resetminutes;
+ if ($finishline) {
+ $finishline=[$reset,$finishline->[1]];
+ } else {
+ $finishline=[$reset];
+ }
+}
+finishlinereset if defined $reset;
+my $state=readfile $statefile;
+chomp $state;
+info $state;
+my $newstate=shift;
+if (!defined $newstate&&defined $resetstate&&!defined $resetminutes) {
+ $newstate=$resetstate;
+ logmsg "reset: $newstate";
+}
+sub printminutes($) {
+ my($m)=@_;
+ return sprintf "%02d:%02d",int($m/60),$m%60;
+}
+if ($silent) {
+ if (!defined $newstate&&!defined $reset&&%schedule) {
+ my $prev=schedulenext($minutes);
+ if ($prev) {
+ my $prev=$prev->[0];
+ if ($prev=~m{ (.)\n$}) {
+ $newstate=$1;
+ logmsg "scheduled: $prev";
+ }
+ }
+ }
+ $newstate=$state if !defined $newstate;
+}
+if (!defined $newstate) {
+ info "\n";
+ finish;
+}
+die "state!={s|0|1}" if $newstate!~/^[s01]$/;
+sub setstate() {
+ info "->$newstate";
+ writefile $statefile,"$newstate\n" if $state ne $newstate;
+ logmsg "$state->$newstate" if $state ne $newstate;
+ if ($newstate ne "s") {
+ my $pid=readfile "pidof -x dnf;true|";
+ die "\n".printminutes($minutes)." change $state".($state eq $newstate?"":"->$newstate")." refused: dnf running: $pid" if $pid;
+ }
+ my $both={"s"=>[0,0],"0"=>[1,0],"1"=>[1,1]}->{$newstate};
+ spawn "$usbrelay 1 ".$both->[0];
+ spawn "$usbrelay 2 ".$both->[1];
+ info "\n";
+}
+my $newreset=shift;
+die "Excessive args: ".join(" ",@ARGV) if @ARGV;
+if (!defined $newreset) {
+ setstate;
+ if (!$silent&&defined $reset) {
+ unlink_resetfile;
+ $finishline=schedulenext($minutes);
+ $finishline=[$finishline->[1]] if $finishline;
+ }
+ finish;
+}
+$reset=$newreset;
+if ($reset=~/^\d+$/) {
+ $resetminutes=($reset+$minutes)%(24*60);
+ $reset=printminutes($resetminutes)." reset\n";
+ setstate;
+} else {
+ $reset.=" reset\n";
+ resetread;
+ $reset=printminutes($resetminutes)." $newstate\n";
+ info "\n";
+}
+writefile $resetfile,$reset;
+logmsg "new reset: $reset";
+finishlinereset;
+finish;
--- /dev/null
+#! /usr/bin/perl
+use strict;
+use warnings;
+my $psu=system($ENV{"HOME"}."/bin/psu")==0;
+local *F;
+open F,"/usr/bin/top -b -n2 -d1|" or die;
+my $top=0;
+while (<F>) {
+ /^top / && $top++;
+ /^$/ && $top++;
+ next if $top!=5;
+ /^(?:\s*\S+){8}\s*(\S+)\s*\S+\s*([^:\s]*):/ or next;
+ next if $1<90; # CPU %
+ next if $2<($psu?30:1); # minutes it has run
+ tr/'//d;
+ system "DISPLAY=:0 xmessage -timeout 30 -default okay -center '$_' 2>/dev/null";
+ exit 0;
+}
+close F or die;
--- /dev/null
+#! /usr/bin/perl
+use strict;
+use warnings;
+use bigint qw/hex/;
+
+my $opt_f=1,shift if ($ARGV[0]||"") eq "-f";
+
+sub readfile($) {
+ my($fname)=@_;
+ local *F;
+ open F,$fname or die $fname;
+ my $F=do { local $/; <F>; };
+ defined $F or die $fname;
+ close F or die $fname;
+ return $F;
+}
+sub fromhex($) {
+ my($hex)=@_;
+ $hex=~s/^0x//;
+ die "Invalid addr: $hex" if $hex!~/^[0-9a-f]+$/i;
+ return hex $hex;
+}
+
+my $fn=shift;
+my $f=readfile $fn;
+my @f;
+while ($f=~/^(([0-9a-f]+)-([0-9a-f]+) [r-][w-][x-][p-] .*)\r?$/mg) {
+ my $line =$1;
+ my $start=fromhex $2;
+ my $end =fromhex $3;
+ push @f,[$line,$start,$end];
+}
+if (!@ARGV) {
+ $f=~/^RIP=(0x[^,]*),/m or die "no RIP";
+ push @ARGV,$1;
+ my $stack=($f=~/^Top of Stack:.*?\n(.*?\n)\n/ms)[0] or die "no Top of Stack";
+ $stack=~s/^0x.*: *//mg;
+ push @ARGV,split /\s+/,$stack;
+}
+for my $arg (@ARGV) {
+ my $addr=fromhex $arg;
+ my $found;
+ for my $ft (@f) {
+ my $line =$ft->[0];
+ my $start=$ft->[1];
+ my $end =$ft->[2];
+ $found=1,print "$arg: $line\n" if $start<=$addr&&$addr<$end&&(!$opt_f||$line=~/[^ ]$/);
+ }
+ print "$arg: -\n" if !$found&&!$opt_f;
+}
--- /dev/null
+#! /usr/bin/perl
+use strict;
+use warnings;
+my $f=shift if ($ARGV[0]||"") eq "-f";
+my %p;
+my %f;
+while (<>) {
+ chomp;
+ $p{$_}=1 if s/^Passed: //;
+ $f{$_}=1 if s/^TEST: //;
+}
+die "No PASS" if !%p&&!$f;
+my %a=(%p,%f);
+print(($p{$_}?"PASS":"FAIL")." test/hotspot/jtreg/$_\n") for sort keys(%a);
--- /dev/null
+#! /usr/bin/perl
+use strict;
+use warnings;
+my %t;
+my $test;
+while (<>) {
+ chomp;
+ if (/^TEST: (.*)$/) {
+ die $_ if $test;
+ $test=$1;
+ next;
+ }
+ if (/^TEST RESULT: (Passed|Failed)[.]/) {
+ die $_ if !$test;
+ $t{$test}=$1 eq "Passed";
+ $test=undef;
+ next;
+ }
+}
+die if defined $test;
+print(($t{$_}?"PASS":"FAIL")." test/hotspot/jtreg/$_\n") for sort keys(%t);
+++ /dev/null
-#! /bin/sh
-if [ "$*" = "--version" ];then
- /usr/bin/makeinfo "$@" | sed 's/texinfo[^0-9]*/&4.40 - orig /'
-else
- exec /usr/bin/makeinfo "$@"
-fi
--- /dev/null
+#! /bin/sh
+if [ -z "$*" ];then
+ echo >&2 "No PID"
+elif [ "$1" = "-p" ];then
+ shift
+ exec chrt -i -p 0 "$@"
+else
+ exec chrt -i 0 "$@"
+fi
--- /dev/null
+#! /bin/bash
+# 0 * * * * ~/bin/openjdk-find-ccache-bug
+for i in $(find ~ 2>/dev/null -name config.status);do
+ if grep -qw REWRITE_PATHS_RELATIVE $(echo $i|sed 's#/build/[^/]*/configure-support/config.status$##')/make/common/NativeCompilation.gmk 2>/dev/null;then
+ continue
+ fi
+ grep CCACHE_BASEDIR= $i /dev/null
+done
--- /dev/null
+#! /bin/bash
+/usr/bin/acpi|&grep -Eq 'Battery 0: Not charging|Battery 0: Charging|No support for device type: power_supply' || exit 1
+/usr/bin/grpcurl -v -plaintext -d '{"get_status":{}}' 192.168.1.1:9000 SpaceX.API.Device.Device/Handle &>/dev/null || exit 1
+exit 0
if test ! -f $orig
then
- cmp $base $base.rpmnew
+ if [ "$base" = "${base%/java.security}" ];then
+ cmp $base $base.rpmnew
+ fi
mv -f $base.rpmnew $base
continue
fi
if $ok
then
mkdir -p /root/rpmmerge
- rpm -qac|perl -ne 'chomp;next if $_ eq "(contains no files)";next if m{^/var/lib/rpm/};next if $_ eq "/usr/lib/locale/locale-archive";next if ! -f $_;$o=$_;$o="/root/rpmmerge/$o";next if -e $o;$od=$o;$od=~s{[^/]*$}{};system "mkdir -p '\''$od'\''" and die "dir $_: $!";system "cp -i -p '\''$_'\'' '\''$o'\''" and die "$_: $!";'
+ rpm -qac|perl -ne 'chomp;next if $_ eq "(contains no files)";next if m{^/var/lib/rpm/};next if $_ eq "/usr/lib/locale/locale-archive";next if $_ eq "/usr/lib/sysimage/rpm/rpmdb.sqlite";next if ! -f $_;$o=$_;$o="/root/rpmmerge/$o";next if -e $o;$od=$o;$od=~s{[^/]*$}{};system "mkdir -p '\''$od'\''" and die "dir $_: $!";system "cp -i -p '\''$_'\'' '\''$o'\''" and die "$_: $!";'
echo OK
else
--- /dev/null
+#! /bin/bash
+echo "$(date --iso=seconds) shutdown $* boot=$(uptime -s) $(uptime -p)" >>/var/log/shutdown-detect.log
+touch /var/log/shutdown-detect.ok
+sync
--- /dev/null
+#! /bin/bash
+boot="boot $* boot=$(uptime -s) $(uptime -p)"
+echo "$(date --iso=seconds) uninit-time $boot" >>/var/log/shutdown-detect.log
+# Raspberry Pi 3B+: 15 sec
+sleep 60
+echo "$(date --iso=seconds) init-time $boot" >>/var/log/shutdown-detect.log
+if [ -e /var/log/shutdown-detect.ok ];then
+ rm -f /var/log/shutdown-detect.ok
+ exit 0
+fi
+echo "$(date --iso=seconds) unclean shutdown"|tee -a /var/log/shutdown-detect.log|mail -s "unclean shutdown: $(hostname)" jan@jankratochvil.net
--- /dev/null
+# jankratochvil:
+# ln -s ../../../root/bin/shutdown-detect.service /etc/systemd/system/shutdown-detect.service; systemctl enable shutdown-detect.service
+# https://unix.stackexchange.com/a/41756/296319
+
+[Unit]
+Description=shutdown-detect
+
+[Service]
+Type=oneshot
+RemainAfterExit=true
+ExecStart=/root/bin/shutdown-detect-boot
+ExecStop=/root/bin/shutdown-detect
+
+[Install]
+WantedBy=multi-user.target
#! /bin/bash
-tail -fn0 `(file $(find /var/log -name ntpstats -prune -o -type f -print)|grep -v 'data$'|sed 's/:.*//'|grep -v '^\(/var/log/squid/store.log\|/var/log/acpid\|/var/log/btmp\|/var/log/maillog\)$';echo "$*"|tr ' ' '\n')|sort -u` # |grep -v ': bio too big device md3 (248 > 240)$'
+ulimit -n 65536
+tail -fn0 `(file $(find /var/log -name ntpstats -prune -o -type f -print)|grep -v 'data$'|sed 's/:.*//'|grep -v '^\(/var/log/squid/store.log\|/var/log/acpid\|/var/log/btmp\|/var/log/journal/.*\|/var/log/maillog\|/var/log/sa/\)$';echo "$*"|tr ' ' '\n')|sort -u` # |grep -v ': bio too big device md3 (248 > 240)$'
--- /dev/null
+#! /bin/bash
+renice >/dev/null +19 -p $$
+ionice -c3 -p $$
+t=/tmp/upsc-log.$$
+rm -f $t $t.*
+log=/var/log/upsc.log
+exec >>$log 2>&1
+while sleep 1;do
+ date --iso=seconds >$t.t
+ upsc eaton &>$t
+ if grep -q '^ups.status: OL$' $t && grep -q '^battery.charge: 100$' $t;then
+ rm -f $t.bad $t.bad.t
+ if [ ! -e $t.good ];then
+ cat $t.t $t;echo
+ sync -d $log
+ fi
+ mv -f $t.t $t.good.t
+ mv -f $t $t.good
+ rm -f /tmp/upsc-smsed
+ continue
+ fi
+ if [ ! -e /tmp/upsc-smsed ];then
+ touch /tmp/upsc-smsed
+ date --iso=seconds|mail -s "upsc-log $(hostname)" jankratochvil@vodafonemail.cz
+ fi
+ if [ -e $t.good ];then
+ cat $t.good.t $t.good;echo
+ sync -d $log
+ rm -f $t.good.t $t.good
+ fi
+ if [ -e $t.bad ] && cmp -s $t $t.bad;then
+ continue
+ fi
+ cat $t.t $t;echo
+ sync -d $log
+ mv -f $t.t $t.bad.t
+ mv -f $t $t.bad
+done
--- /dev/null
+#! /usr/bin/perl
+use strict;
+use warnings;
+local *F;
+my $ta="/tmp/upsc-log-diff.".$$."a";
+my $tb="/tmp/upsc-log-diff.".$$."b";
+unlink $ta; unlink $tb;
+END {
+ unlink $ta; unlink $tb;
+}
+my $F="/var/log/upsc.log";
+open F,$F or die "$F: $!";
+my $prev;
+my $this="";
+my $line;
+while (<F>) {
+ $line=$.;
+ chomp;
+ if (!/^$/) {
+ $this.="$_\n";
+ next;
+ }
+ if ($prev) {
+ local *TA;
+ local *TB;
+ open TA,">$ta" or die "$ta: $!";
+ open TB,">$tb" or die "$tb: $!";
+ print TA $prev or die "$ta: $!";
+ print TB $this or die "$tb: $!";
+ close TA or die "$ta: $!";
+ close TB or die "$ta: $!";
+ local *TD;
+ my $td="diff -u $ta $tb|";
+ open TD,$td or die "$td: $!";
+ <TD>=~/^\Q--- / or die "line $line: $_";
+ <TD>=~/^\Q+++ / or die "line $line: $_";
+ while (<TD>) {
+ next if /^[@ ]/;
+ print;
+ }
+ close TD; # or die "$td: $!";
+ print "\n";
+ }
+ $prev=$this;
+ $this="";
+}
+die $this if $this;
--- /dev/null
+#!/usr/bin/env python3
+# -*- encoding: utf-8 -*-
+# https://slomkowski.eu/tutorials/eavesdropping-usb-and-writing-driver-in-python/
+
+import time
+import sys
+
+import usb.core
+import usb.util
+
+VENDOR_ID = 0x16c0
+DEVICE_ID = 0x05df
+
+MANUFACTURER_NAME = "www.dcttech.com"
+PRODUCT_NAME = "USBRelay2"
+
+
+def check_manufacturer_and_product(dev):
+ return dev.manufacturer == MANUFACTURER_NAME and dev.product == PRODUCT_NAME
+
+
+def find_device_handle():
+ return usb.core.find(idVendor=VENDOR_ID, idProduct=DEVICE_ID,
+ custom_match=check_manufacturer_and_product)
+
+
+dev_handle = find_device_handle()
+
+if dev_handle.is_kernel_driver_active(0):
+ try:
+ dev_handle.detach_kernel_driver(0)
+ print("kernel driver detached")
+ except usb.core.USBError as e:
+ sys.exit("Could not detach kernel driver: %s" % str(e))
+
+requestType = usb.util.build_request_type(usb.util.CTRL_OUT,
+ usb.util.CTRL_TYPE_CLASS,
+ usb.util.CTRL_RECIPIENT_INTERFACE)
+
+
+def set_relay(relay_number, enabled: bool):
+ b1 = 0xff if enabled else 0xfd
+ dev_handle.ctrl_transfer(requestType, 9, 0x0300, 0, (b1, relay_number, 0, 0, 0, 0, 0, 0))
+
+
+#while True:
+# set_relay(1, True)
+# time.sleep(1)
+# set_relay(1, False)
+# time.sleep(1)
+# set_relay(2, True)
+# time.sleep(1)
+# set_relay(2, False)
+# time.sleep(1)
+
+
+if len(sys.argv)!=3 or (sys.argv[1]!="1" and sys.argv[1]!="2") or (sys.argv[2]!="0" and sys.argv[2]!="1"):
+ sys.exit("usbrelay: {1|2} {0|1}")
+set_relay((1 if sys.argv[1]=="1" else 2),(True if sys.argv[2]=="1" else False))
--- /dev/null
+#! /bin/bash
+fis=""
+for fi in $(git status|sed -n 's/^ both modified: *//p');do
+ if ! grep -q '^<<<<<<< ' $fi;then
+ git add $fi
+ continue
+ fi
+ fis="$fis $fi"
+done
+if [ -z "$fis" ];then
+ echo done
+ exit 0
+fi
+set -x
+exec vim $fis
--- /dev/null
+#! /bin/bash
+set -ev
+wc `git ls-files`
+cat `git ls-files`|sort -u|wc
+cat `git ls-files` |perl -pe 's/^\s*//'|sort -u|wc
+git log -p |perl -ne 'print if s/^[+][^+]//;'|perl -pe 's/^\s*//'|sort -u|wc
+echo done
#CFLAGS+=-O9 -fexpensive-optimizations -finline-functions
#CFLAGS+=-pg
-all: yasm2gas
-# unmime flock pipebuf
+all: streamfer-server streamfer-client
+# yasm2gas unmime flock pipebuf
pipebuf: pipebuf.c
sh $<
yasm2gas: yasm2gas.c
gcc -o $@ -Wall -g $<
+streamfer-server: streamfer-server.C streamfer.h streamfer.C safeio.C safeio.h socket.C socket.h stringf.h
+ clang++ -o $@ -Wall -g streamfer-server.C streamfer.C safeio.C socket.C
+
+streamfer-client: streamfer-client.C streamfer.h streamfer.C safeio.C safeio.h socket.C socket.h stringf.h
+ clang++ -o $@ -Wall -g streamfer-client.C streamfer.C safeio.C socket.C
+++ /dev/null
-BUILD
-RPMS
+++ /dev/null
-cvs-1.11-3:
-cvs-1.10-tmprace.patch
-cvs-1.10.7-fixinfo.patch
-cvs-1.10.7-krb5-1.1.1.patch
-cvs-1.10.8-errno.patch
-cvs-1.10.8-krb4.patch
-cvs-1.10.8-zlib.patch
-cvs-1.11-existence.patch
-cvs-1.11-security.patch
-cvs-1.11.tar.gz
-
-glibc-2.2.2-10:
-glibc-2.2.2.tar.bz2
-glibc-kernel-2.4.patch
-
--- /dev/null
+#include "safeio.h"
+#include <sys/uio.h>
+
+const SafeIOError exception_SafeIOError;
+const SafeIOEOF exception_SafeIOEOF ;
+
+void read_safe(int fd,void *buf,size_t size) {
+ assert(size>0);
+ while (size>0) {
+ const ssize_t got(read(fd,buf,size));
+ assert(got>=-1);
+ if (got<=0) {
+ warning("read_safe: fd=%d size=%zu: %s",fd,size,(got==0?"EOF":strerror(errno)));
+ // Do not throw ?exc1:exc2 as it would get upcasted.
+ if (got==0||(got==-1&&errno==ECONNRESET))
+ throw exception_SafeIOEOF;
+ throw exception_SafeIOError;
+ }
+ assert(size_t(got)<=size);
+ buf=static_cast<uint8_t *>(buf)+got;
+ size-=got;
+ }
+}
+
+void read_safe(FILE *f,void *buf,size_t size) {
+ assert(size>0);
+ assert(!ferror(f));
+ assert(!feof(f));
+ const size_t got(fread(buf,1/*size*/,size/*nmemb*/,f));
+ if (ferror(f)||feof(f)) {
+ warning("read_safe: fd=%d size=%zu: %s",fileno(f),size,(ferror(f)?"error":"EOF"));
+ // Do not throw ?exc1:exc2 as it would get upcasted.
+ if (ferror(f))
+ throw exception_SafeIOError;
+ throw exception_SafeIOEOF;
+ }
+ // return [...] which is less than nitems only if a read error or end-of-file is encountered.
+ if (size_t(got)!=size) {
+ warning("read_safe: fd=%d size=%zu got=%zu",fileno(f),size,got);
+ throw exception_SafeIOError;
+ }
+}
+
+void write_safe(int fd,const void *buf,size_t size) {
+ assert(size>0);
+ const ssize_t got(write(fd,buf,size));
+ if (got==-1) {
+ warning("Error writing %zu to fd %d: %m",size,fd);
+ throw exception_SafeIOError;
+ }
+ assert(got>0);
+ if (size_t(got)!=size) {
+ warning("Wrote only %zd of %zu to fd %d",got,size,fd);
+ throw exception_SafeIOEOF;
+ }
+}
+
+void write_safe(FILE *f,const void *buf,size_t size) {
+ assert(size>0);
+ assert(!ferror(f));
+ const size_t got(fwrite(buf,1/*size*/,size/*nmemb*/,f));
+ if (ferror(f)) {
+ warning("Error writing %zu to FILE * of fd %d",size,fileno(f));
+ throw exception_SafeIOError;
+ }
+ if (got!=size) {
+ warning("Wrote only %zu of %zu to FILE * of fd %d",got,size,fileno(f));
+ throw exception_SafeIOEOF;
+ }
+}
+
+void writev_safe_(int fd,const struct iovec *iov, int iovcnt) {
+ size_t size=0;
+ for (int ix=0;ix<iovcnt;++ix)
+ size+=iov[ix].iov_len;
+ assert(size>0);
+ const ssize_t got(writev(fd,iov,iovcnt));
+ if (got==-1) {
+ warning("Error writing %zu iovec to fd %d: %m",size,fd);
+ throw exception_SafeIOError;
+ }
+ assert(got>0);
+ if (size_t(got)!=size) {
+ warning("Wrote only %zd of %zu iovec to fd %d",got,size,fd);
+ throw exception_SafeIOEOF;
+ }
+}
--- /dev/null
+#ifndef LIB_SAFEIO_H
+#define LIB_SAFEIO_H
+
+#include "streamfer.h"
+#include <sys/uio.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <exception>
+#include <vector>
+#include <string>
+#include <array>
+#include <deque>
+#include <cassert>
+#include <cstdint>
+#include <cstring>
+
+extern const class SafeIOError:public exception {
+ virtual const char *what() const noexcept override { return "SafeIOError"; }
+} exception_SafeIOError;
+extern const class SafeIOEOF:public SafeIOError {
+ virtual const char *what() const noexcept override { return "SafeIOEOF"; }
+} exception_SafeIOEOF;
+
+void read_safe(int fd ,void *buf,size_t len);
+void read_safe(FILE *f,void *buf,size_t len);
+
+template<class F,class T> void read_safe(F f, T &obj) { read_safe(f,&obj,sizeof(obj)); }
+
+template<class F,class T> void read_safe(F f,vector<T> &vec) {
+ size_t size;
+ read_safe(f,size);
+ vec.resize(size);
+ if (size)
+ read_safe(f,vec.data(),vec.size()*sizeof(vec[0]));
+}
+
+template<class F,class T> void read_safe(F f,deque<T> &vec) {
+ size_t size;
+ read_safe(f,size);
+ vec.resize(size);
+ for (auto &elem:vec)
+ read_safe(f,elem);
+}
+
+template<class F> void read_safe(F f,string &str) {
+ uint8_t len8=0; // false GCC warning
+ read_safe(f,len8);
+ str.resize(len8);
+ if (len8)
+ read_safe(f,&str[0],str.length());
+}
+
+template<class F> string read_safe_string(F f) { string str; read_safe(f,str); return str; }
+
+void write_safe(int fd ,const void *buf,size_t count);
+void write_safe(FILE *f,const void *buf,size_t count);
+void writev_safe_(int fd,const struct iovec *iov, int iovcnt);
+constexpr iovec writev_iovec(const void *base,size_t len) { return iovec{const_cast<void *>(base),len}; }
+static inline const/*FIXME:constexpr c_str()*/ iovec iovec_for_string(const string &str) { return iovec{const_cast<char *>(str.c_str()),str.length()}; }
+template<class T> constexpr iovec iovec_for_object(T &object) { return iovec{reinterpret_cast<void *>(const_cast<typename std::remove_const<T>::type *>(&object)),sizeof(object)}; }
+template<size_t iovcnt> void writev_safe(int fd,std::array<iovec,iovcnt> iov) {
+ writev_safe_(fd,iov.data(),iovcnt);
+}
+
+template<class F,class T> void write_safe(F f,const T &obj) { write_safe(f,&obj,sizeof(obj)); }
+
+template<class F,class T> void write_safe(F f,const vector<T> &vec) {
+ const size_t size(vec.size());
+ write_safe(f,size);
+ if (size)
+ write_safe(f,vec.data(),size*sizeof(vec[0]));
+}
+
+template<class F,class T> void write_safe(F f,const deque<T> &vec) {
+ const size_t size(vec.size());
+ write_safe(f,size);
+ for (const auto &elem:vec)
+ write_safe(f,elem);
+}
+
+template<class F> void write_safe(F f,const string &str) {
+ const uint8_t len8(str.length());
+ assert(len8==str.length());
+ write_safe(f,len8);
+ if (!str.empty())
+ write_safe(f,str.c_str(),len8);
+}
+
+#endif /* LIB_SAFEIO_H */
--- /dev/null
+#include "socket.h"
+#include "stringf.h"
+#include <netdb.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+
+int socket_bind(string host_port_str) {
+ const char *cs(strrchr(host_port_str.c_str(),':'));
+ const string node(!cs?"":host_port_str.substr(0,cs-host_port_str.c_str()));
+ const string service(!cs?host_port_str:cs+1);
+ struct addrinfo hints={}; // designated initializer: error: missing initializer for member ... [-Werror=missing-field-initializers]
+ hints.ai_family=AF_UNSPEC; /* Allow IPv4 or IPv6 */
+ hints.ai_socktype=SOCK_STREAM;
+ hints.ai_flags=AI_PASSIVE|AI_ADDRCONFIG; /* For wildcard IP address */
+ struct addrinfo *result;
+ int err(getaddrinfo(node.empty()?NULL:node.c_str(),service.c_str(),&hints,&result));
+ if (err)
+ fatal("<%s>:<%s>: %s",node.c_str(),service.c_str(),gai_strerror(err));
+ int fd=-1;
+ struct addrinfo *rp;
+ for (rp=result;rp;rp=rp->ai_next) {
+ fd=socket(rp->ai_family,rp->ai_socktype,rp->ai_protocol);
+ if (fd==-1)
+ continue;
+ static const int int1(1);
+ err=setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&int1,sizeof(int1));
+ assert(!err);
+ if (bind(fd,rp->ai_addr,rp->ai_addrlen)==0)
+ break;
+ err=close(fd);
+ assert(!err);
+ }
+ if (rp==NULL)
+ fatal("Cannot bind(): <%s>:<%s>: %m",node.c_str(),service.c_str());
+ assert(fd!=-1);
+ freeaddrinfo(result);
+ err=listen(fd,SOMAXCONN);
+ assert(!err);
+ return fd;
+}
+
+string sockaddr_string(const struct sockaddr *sockaddrp,socklen_t socklen) {
+ char hostname[NI_MAXHOST];
+ char servname[NI_MAXSERV];
+ const int err=getnameinfo(sockaddrp,socklen,hostname,sizeof(hostname),servname,sizeof(servname),NI_NUMERICSERV/*flags*/);
+ assert(!err);
+ return stringf("%s:%s",hostname,servname);
+}
+
+string socket_name(int socket_fd) {
+ struct sockaddr sockaddr;
+ socklen_t socklen(sizeof(sockaddr));
+ const int err(getsockname(socket_fd,&sockaddr,&socklen));
+ assert(!err);
+ return sockaddr_string(&sockaddr,socklen);
+}
+
+static void socket_setopt(int fd) {
+ static const int int1(1);
+ int err;
+ err=setsockopt(fd,SOL_SOCKET,SO_KEEPALIVE,&int1,sizeof(int1));
+ assert(!err);
+ static const uint8_t tos(IPTOS_LOWDELAY);
+ err=setsockopt(fd,IPPROTO_IP,IP_TOS,&tos,sizeof(tos));
+ assert(!err);
+ err=setsockopt(fd,IPPROTO_IP,TCP_NODELAY,&int1,sizeof(int1));
+ assert(!err);
+}
+
+int socket_accept(int listen_fd,function<void(int client_fd,string addr)> msgfunc) {
+ struct sockaddr sockaddr;
+ socklen_t socklen(sizeof(sockaddr));
+ const int client_fd(accept(listen_fd,&sockaddr,&socklen));
+ assert(client_fd>=0);
+ msgfunc(client_fd,sockaddr_string(&sockaddr,socklen));
+ socket_setopt(client_fd);
+ return client_fd;
+}
+
+int socket_connect(const string &host_port_str,unsigned retries) {
+ const char *cs(strrchr(host_port_str.c_str(),':'));
+ if (!cs)
+ fatal("Error parsing <host>:<port>: %s",host_port_str.c_str());
+ const string node(host_port_str.substr(0,cs-host_port_str.c_str()));
+ const string service(cs+1);
+ struct addrinfo hints={}; // designated initializer: error: missing initializer for member ... [-Werror=missing-field-initializers]
+ hints.ai_family=AF_UNSPEC; /* Allow IPv4 or IPv6 */
+ hints.ai_socktype=SOCK_STREAM;
+ struct addrinfo *result;
+ int err=getaddrinfo(node.c_str(),service.c_str(),&hints,&result);
+ if (err)
+ fatal("Error parsing node+service: <%s>:<%s>: %s",node.c_str(),service.c_str(),gai_strerror(err));
+ int fd;
+ struct addrinfo *rp;
+ for (unsigned retryno=0;retryno<1+retries;++retryno) {
+ if (retryno) {
+ warning("Sleeping 1 second for connect retry #%u/%u",retryno,retries);
+ err=sleep(1);
+ assert(!err);
+ }
+ for (rp=result;rp;rp=rp->ai_next) {
+ fd=socket(rp->ai_family,rp->ai_socktype,rp->ai_protocol);
+ if (fd==-1)
+ continue;
+ if (connect(fd,rp->ai_addr,rp->ai_addrlen)==0)
+ break;
+ err=close(fd);
+ assert(!err);
+ }
+ if (rp==NULL)
+ warning("Could not connect(): <%s>:<%s>: %m",node.c_str(),service.c_str());
+ else
+ break;
+ }
+ freeaddrinfo(result);
+ if (rp==NULL)
+ fatal("Could not connect(), giving up");
+ socket_setopt(fd);
+ return fd;
+}
--- /dev/null
+#ifndef LIB_SOCKET_H
+#define LIB_SOCKET_H
+
+#include "streamfer.h"
+#include <unistd.h>
+#include <string>
+#include <functional>
+#include <cstring>
+#include <sys/socket.h>
+
+int socket_bind(string host_port_str);
+string sockaddr_string(const struct sockaddr *sockaddrp,socklen_t socklen);
+string socket_name(int socket_fd);
+int socket_accept(int listen_fd,function<void(int client_fd,string addr)> msgfunc);
+int socket_connect(const string &host_port_str,unsigned retries);
+
+#endif /* LIB_SOCKET_H */
--- /dev/null
+#include "safeio.h"
+#include "socket.h"
+#include "stringf.h"
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <climits>
+
+static string get_string(FILE *f,const char *fn,const char *what) {
+ char buf[PATH_MAX];
+ char *got=fgets(buf,sizeof(buf),f);
+ if (got!=buf)
+ fatal("Error reading %s from %s: %m",what,fn);
+ char *s(strchr(buf,'\n'));
+ if (!s)
+ fatal("Stored %s in %s is not newline-terminated",what,fn);
+ *s=0;
+ assert(!s[1]);
+ return buf;
+}
+
+static void last_stored_write(const char *last_stored_fn,const string &filename,uint64_t offset) {
+ std::string last_tmp_fn(std::string(last_stored_fn)+".new");
+ int last_tmp_fd(open(last_tmp_fn.c_str(),O_WRONLY|O_CREAT|O_TRUNC,0644));
+ if (last_tmp_fd==-1)
+ fatal("Error storing filename to %s: %m",last_tmp_fn.c_str());
+ write_safe(last_tmp_fd,filename.c_str(),filename.length());
+ write_safe(last_tmp_fd,'\n');
+ string offsetstr(stringf("%zu",(size_t)offset));
+ write_safe(last_tmp_fd,offsetstr.c_str(),offsetstr.length());
+ write_safe(last_tmp_fd,'\n');
+ if (close(last_tmp_fd))
+ fatal("Error closing %s: %m",last_tmp_fn.c_str());
+ if (rename(last_tmp_fn.c_str(),last_stored_fn))
+ fatal("Error renaming %s->%s: %m",last_tmp_fn.c_str(),last_stored_fn);
+}
+
+static string my_basename(const string &path) {
+ size_t slash(path.find_last_of('/'));
+ if (slash!=string::npos)
+ return path.substr(slash+1);
+ return path;
+}
+
+int main(int argc,char **argv) {
+ if (argc!=1+3)
+ fatal("streamfer-client <host>:<port> <pattern> <last storage file>");
+ int server_fd(socket_connect(string(argv[1]),0/*retries*/));
+ string pattern(argv[2]);
+ write_safe(server_fd,pattern);
+ string last_found;
+ const char *last_stored_fn(argv[3]);
+ FILE *last_stored_f(fopen(last_stored_fn,"r"));
+ uint64_t offset(0);
+ if (!last_stored_f) {
+ if (errno!=ENOENT)
+ fatal("Error opening filename from %s: %m",last_stored_fn);
+ } else {
+ last_found= get_string(last_stored_f,last_stored_fn,"filename") ;
+ string offsetstr(get_string(last_stored_f,last_stored_fn,"offset" ));
+ char *end;
+ errno=0;
+ unsigned long ul(strtoul(offsetstr.c_str(),&end,0));
+ if (errno||(end&&*end))
+ fatal("Error converting offset from %s: %s",last_stored_fn,offsetstr.c_str());
+ offset=ul;
+ int gotint(fgetc(last_stored_f));
+ if (gotint!=EOF)
+ fatal("Stored filename in %s has excessive data after filename %s and offset %s",last_stored_fn,last_found.c_str(),offsetstr.c_str());
+ int err(fclose(last_stored_f));
+ assert(!err);
+ }
+ write_safe(server_fd,last_found);
+ write_safe(server_fd,offset);
+ { struct stat statbuf;
+ string last_found_basename(my_basename(last_found));
+ if (stat(last_found_basename.c_str(),&statbuf)) {
+ static const struct timespec mtim_zero{};
+ write_safe(server_fd,mtim_zero);
+ } else
+ write_safe(server_fd,statbuf.st_mtim);
+ }
+ string last_got;
+ try {
+ read_safe(server_fd,last_got);
+ } catch (SafeIOError) {
+ fatal("SafeIOError reading from the server %s",argv[1]);
+ }
+ if (last_got.empty()) {
+ warning("No more files to transfer");
+ exit(EXIT_SUCCESS);
+ }
+ struct timespec mtim;
+ read_safe(server_fd,mtim);
+ int file_fd;
+ string file_name(my_basename(last_got));;
+ if (last_found==last_got) {
+ file_fd=open(file_name.c_str(),O_WRONLY);
+ if (file_fd==-1)
+ fatal("Error opening for write %s: %m",file_name.c_str());
+ off_t got(lseek(file_fd,offset,SEEK_SET));
+ if ((uint64_t)got!=offset)
+ fatal("Error seeking in %s to %zu, got: %zu",file_name.c_str(),(size_t)offset,(size_t)got);
+ } else {
+ offset=0;
+ file_fd=open(file_name.c_str(),O_WRONLY|O_CREAT,0644);
+ if (file_fd==-1)
+ fatal("Error creating %s: %m",file_name.c_str());
+ }
+ last_stored_write(last_stored_fn,last_got,offset);
+ uint64_t transferred(transfer(server_fd,"server fd",file_fd,file_name.c_str()));
+ if (!transferred) {
+ struct stat statbuf;
+ int err(fstat(file_fd,&statbuf));
+ assert(!err);
+ if (memcmp(&mtim,&statbuf.st_mtim,sizeof(mtim))==0)
+ return EXIT_FAILURE;
+ }
+ offset+=transferred;
+ struct timespec mtim2[2];
+ mtim2[0]=mtim; // atime
+ mtim2[1]=mtim; // mtime
+ if (futimens(file_fd,mtim2))
+ fatal("Error setting timestamp of %s: %m",file_name.c_str());
+ if (close(file_fd))
+ fatal("Error closing %s: %m",file_name.c_str());
+ last_stored_write(last_stored_fn,last_got,offset);
+ return EXIT_SUCCESS;
+}
--- /dev/null
+#include "safeio.h"
+#include "socket.h"
+#include "stringf.h"
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <poll.h>
+#include <climits>
+#include <cstdlib>
+#include <csignal>
+
+// https://stackoverflow.com/a/8615450/2995591
+#include <glob.h> // glob(),globfree()
+#include <cstring> // memset()
+#include <vector>
+#include <string>
+
+static std::vector<std::string> cxxglob(const std::string pattern) {
+ glob_t glob_result;
+ memset(&glob_result,0,sizeof(glob_result));
+ int return_value=glob(pattern.c_str(),GLOB_TILDE,NULL,&glob_result);
+ if (return_value)
+ fatal("glob() failed with return_value %s",return_value);
+ vector<string> filenames;
+ filenames.reserve(glob_result.gl_pathc);
+ for (size_t i = 0; i < glob_result.gl_pathc; ++i)
+ filenames.push_back(string(glob_result.gl_pathv[i]));
+ globfree(&glob_result);
+ return filenames;
+}
+
+// FIXME: Use C++17
+static bool fd_is_open(const char *execname,const char *fn) {
+ const char slashproc[]("/proc");
+ DIR *dir(opendir(slashproc));
+ if (!dir)
+ fatal("Cannot opendir %s: %m",slashproc);
+ bool retval(false);
+ for (;;) {
+ errno=0;
+ const struct dirent *de=readdir(dir);
+ if (!de) {
+ if (errno)
+ fatal("Cannot readdir %s: %m",slashproc);
+ break;
+ }
+ if (!isdigit(de->d_name[0]))
+ continue;
+
+ char buf[PATH_MAX];
+ ssize_t got(readlinkat(dirfd(dir),stringf("%s/exe",de->d_name).c_str(),buf,sizeof(buf)));
+ if (got==-1||got==sizeof(buf))
+ continue;
+ buf[got]=0;
+ char *s=strrchr(buf,'/');
+ if (!s)
+ continue;
+ if (strcmp(s+1,execname)!=0)
+ continue;
+
+ string procpidfd(stringf("/proc/%s/fd",de->d_name));
+ DIR *fddir(opendir(procpidfd.c_str()));
+ if (!fddir)
+ fatal("Cannot opendir %s: %m",procpidfd.c_str());
+ for (;;) {
+ errno=0;
+ const struct dirent *de=readdir(fddir);
+ if (!de) {
+ if (errno)
+ fatal("Cannot readdir %s: %m",procpidfd.c_str());
+ break;
+ }
+ if (!isdigit(de->d_name[0]))
+ continue;
+ char buf[PATH_MAX];
+ ssize_t got(readlinkat(dirfd(fddir),de->d_name,buf,sizeof(buf)));
+ if (got==-1||got==sizeof(buf))
+ continue;
+ buf[got]=0;
+ if (strcmp(buf,fn)==0) {
+ retval=true;
+ break;
+ }
+ }
+ if (closedir(fddir))
+ fatal("Cannot closedir %s: %m",procpidfd.c_str());
+ if (retval)
+ break;
+ }
+ if (closedir(dir))
+ fatal("Cannot closedir %s: %m",slashproc);
+ return retval;
+}
+
+int main(int argc,char **argv) {
+ static struct sigaction sigchld;
+ sigchld.sa_handler=SIG_DFL;
+ sigchld.sa_flags=SA_NOCLDWAIT;
+ int err(sigaction(SIGCHLD,&sigchld,nullptr));
+ assert(!err);
+
+ if (argc!=1+2&&argc!=1+3)
+ fatal("streamfer-server [<listen-host>:]<listen-port> <prefix> [follow-fd-of-executable-basename]");
+ string prefix;
+ if (argc>=1+2&&*argv[2])
+ prefix=argv[2];
+ const char *execname(nullptr);
+ if (argc>=1+3)
+ execname=argv[3];
+ int listen_fd(socket_bind(argv[1]));
+ int client_fd;
+ for (;;) {
+ client_fd=socket_accept(listen_fd,[&](int client_fd,string addr) {
+ warning("%d:%s",client_fd,addr.c_str());
+ });
+ int child(fork());
+ assert(child!=-1);
+ if (!child)
+ break;
+ int err(close(client_fd));
+ assert(!err);
+ }
+ err=close(listen_fd);
+ assert(!err);
+
+ string pattern(read_safe_string(client_fd));
+ std::vector<std::string> matched(cxxglob(pattern));
+ for (size_t ix=0;ix<matched.size()-1;++ix) {
+ const std::string &a(matched[ix ]);
+ const std::string &b(matched[ix+1]);
+ int err(strcmp(a.c_str(),b.c_str()));
+ if (err>=0)
+ fatal("glob: strcmp(\"%s\",\"%s\")=%d",a.c_str(),b.c_str(),err);
+ }
+ string last(read_safe_string(client_fd));
+ size_t lastix(SIZE_MAX);
+ for (size_t ix=0;ix<matched.size();++ix) {
+ const std::string &member(matched[ix]);
+ if (strcmp(last.c_str(),member.c_str())>0)
+ assert(lastix==SIZE_MAX);
+ else if (lastix==SIZE_MAX)
+ lastix=ix;
+ }
+ if (lastix==SIZE_MAX)
+ fatal("Requested too new file");
+ uint64_t offset;
+ read_safe(client_fd,offset);
+ struct timespec mtim;
+ read_safe(client_fd,mtim);
+ const string *fnp;
+ int file_fd=-1;
+ struct stat statbuf;
+ for (;lastix<matched.size();file_fd=-1,++lastix) {
+ fnp=&matched[lastix];
+ const string &fn(*fnp);
+ file_fd=open(fn.c_str(),O_RDONLY);
+ if (file_fd==-1) {
+ if (errno!=ENOENT)
+ fatal("Cannot open %s: %m",fn.c_str());
+ continue;
+ }
+ int err(fstat(file_fd,&statbuf));
+ assert(!err);
+ if (offset<(uint64_t)statbuf.st_size)
+ break;
+ static const struct timespec mtim_zero{};
+ if (memcmp(&mtim,&mtim_zero,sizeof(mtim))!=0&&memcmp(&mtim,&statbuf.st_mtim,sizeof(mtim))!=0)
+ break;
+ if (offset>(uint64_t)statbuf.st_size)
+ warning("File %s has transferred %zu < %zu which is its size",fn.c_str(),(size_t)offset,(size_t)statbuf.st_size);
+ if (lastix==matched.size()-1&&execname)
+ break;
+ err=close(file_fd);
+ assert(!err);
+ offset=0;
+ }
+ if (file_fd==-1) {
+ string empty("");
+ write_safe(client_fd,empty);
+ fatal("No more files to transfer");
+ }
+ const string &fn(*fnp);
+ const char *fn_canon(nullptr);
+ if (!prefix.empty()||execname) {
+ fn_canon=realpath(fn.c_str(),nullptr);
+ if (!fn_canon)
+ fatal("realpath %s: %m",fn.c_str());
+ }
+ if (fn!=last)
+ offset=0;
+ if (!prefix.empty()&&strncmp(prefix.c_str(),fn_canon,prefix.length())!=0)
+ fatal("prefix=\"%s\" realpath=\"%s\"",prefix.c_str(),fn_canon);
+ warning("%s @%zu",fn.c_str(),(size_t)offset);
+ write_safe(client_fd,fn);
+ write_safe(client_fd,statbuf.st_mtim);
+ off_t got(lseek(file_fd,offset,SEEK_SET));
+ assert((uint64_t)got==offset);
+ struct pollfd fds;
+ fds.fd=client_fd;
+ fds.events=POLLIN|POLLPRI|POLLRDHUP;
+ for (;;) {
+ transfer(file_fd,fn.c_str(),client_fd,"client fd");
+ if (!fn_canon||!fd_is_open(execname,fn_canon))
+ break;
+ int err(poll(&fds,1,1000/*ms*/));
+ if (err==-1)
+ fatal("poll client fd: %m");
+ if (err==1)
+ fatal("poll client fd: revents=0x%x",fds.revents);
+ assert(err==0);
+ }
+}
--- /dev/null
+#include "streamfer.h"
+#include <unistd.h>
+
+static void vwarning(const char *msg,va_list ap) {
+ int err=vfprintf(stderr,msg,ap);
+ assert(err>0);
+ fputc('\n',stderr);
+}
+
+void warning(const char *msg,...) {
+ va_list ap;
+ va_start(ap,msg);
+ vwarning(msg,ap);
+ va_end(ap);
+}
+
+void fatal(const char *msg,...) {
+ va_list ap;
+ va_start(ap,msg);
+ vwarning(msg,ap);
+ va_end(ap);
+ exit(EXIT_FAILURE);
+}
+
+uint64_t transfer(int from_fd,const char *from_fn,int to_fd,const char *to_fn) {
+ size_t total(0);
+ uint8_t buffer[0x10000];
+ size_t buffer_filled(0);
+ for (;;) {
+ if (buffer_filled==0) {
+ ssize_t got(read(from_fd,buffer+buffer_filled,sizeof(buffer)-buffer_filled));
+ if (got==-1)
+ fatal("Error reading %s: %m",from_fn);
+ if (got==0)
+ return total;
+ buffer_filled=got;
+ assert(buffer_filled<=sizeof(buffer));
+ }
+ size_t buffer_written(0);
+ while (buffer_written<buffer_filled) {
+ ssize_t got(write(to_fd,buffer+buffer_written,buffer_filled-buffer_written));
+ if (got==-1)
+ fatal("Error writing %s: %m",to_fn);
+ assert(got>0);
+ buffer_written+=got;
+ assert(buffer_written<=buffer_filled);
+ }
+ total+=buffer_filled;
+ buffer_filled=0;
+ }
+}
--- /dev/null
+#ifndef STREAMFER_H
+#define STREAMFER_H 1
+
+#include <cstdarg>
+#include <cstdio>
+#include <cassert>
+#include <cstdlib>
+#include <cstdint>
+using namespace std;
+
+#define PRINTF(f,a) __attribute__((format(printf,f,a)))
+#define UNUSED __attribute__((unused))
+
+void warning(const char *msg,...);
+void fatal(const char *msg,...);
+
+uint64_t transfer(int from_fd,const char *from_fn,int to_fd,const char *to_fn);
+
+#endif // STREAMFER_H
--- /dev/null
+#ifndef LIB_STRINGF_H
+#define LIB_STRINGF_H
+
+#include "streamfer.h"
+
+// template<class... Args>: format string is not a string literal (potentially insecure) [-Werror,-Wformat-security]
+
+static inline PRINTF(2,0) string vstringf_const(size_t sizemax,const char *fmt,va_list ap) {
+ string str(sizemax+1,0);
+ const int got=vsnprintf(&str[0],str.length(),fmt,ap);
+ if (got!=ssize_t(sizemax))
+ fatal("stringf*(): expected=%zu got=%d fmt=\"%s\" str=\"%s\"",sizemax,got,fmt,str.c_str());
+ str.resize(sizemax);
+ return str;
+}
+
+static inline PRINTF(2,3) string stringf_const(size_t sizemax,const char *fmt,...) {
+ va_list ap;
+ va_start(ap,fmt);
+ const string str(vstringf_const(sizemax,fmt,ap));
+ va_end(ap);
+ return str;
+}
+
+static inline PRINTF(1,2) string stringf(const char *fmt,...) {
+ // 189: for i in activetick.data/;do find $i -name "*.xz";done|xargs xz -dc|perl -lne 'BEGIN{$m=0;}if (length($_)>$m){$m=length $_;print $m;}'
+ static const int sizetry(192-1/*+1->malloc()*/);
+ string str(sizetry,0);
+ va_list ap;
+ va_start(ap,fmt);
+ const int got(vsnprintf(&str[0],sizetry,fmt,ap));
+ va_end(ap);
+ assert(got>=0);
+ if (got>=sizetry) {
+ str.resize(got+1);
+ va_start(ap,fmt);
+ const int got2(vsnprintf(&str[0],str.length(),fmt,ap));
+ va_end(ap);
+ assert(got2==got);
+ }
+ str.resize(got);
+ return str;
+}
+
+#endif /* LIB_STRINGF_H */