1# $Id$
2# $MirOS: src/bin/mksh/dot.mkshrc,v 1.89 2014/07/28 21:45:44 tg Exp $
3#-
4# Copyright (c) 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010,
5#		2011, 2012, 2013, 2014
6#	Thorsten Glaser <tg@mirbsd.org>
7#
8# Provided that these terms and disclaimer and all copyright notices
9# are retained or reproduced in an accompanying document, permission
10# is granted to deal in this work without restriction, including un-
11# limited rights to use, publicly perform, distribute, sell, modify,
12# merge, give away, or sublicence.
13#
14# This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
15# the utmost extent permitted by applicable law, neither express nor
16# implied; without malicious intent or gross negligence. In no event
17# may a licensor, author or contributor be held liable for indirect,
18# direct, other damage, loss, or other issues arising in any way out
19# of dealing in the work, even if advised of the possibility of such
20# damage or existence of a defect, except proven that it results out
21# of said person's immediate fault when using the work as intended.
22#-
23# ${ENV:-~/.mkshrc}: mksh initialisation file for interactive shells
24
25# catch non-mksh (including lksh) trying to shell this file
26case $KSH_VERSION in
27*MIRBSD\ KSH*) ;;
28*) return 0 ;;
29esac
30
31PS1='#'; (( USER_ID )) && PS1='$'; [[ ${HOSTNAME:=$(ulimit -c 0; hostname -s \
32    2>/dev/null)} = *([	 ]|localhost) ]] && HOSTNAME=$(ulimit -c 0; hostname \
33    2>/dev/null); : ${EDITOR:=/bin/ed} ${HOSTNAME:=nil} ${TERM:=vt100}
34: ${MKSH:=$(whence -p mksh)}; PS4='[$EPOCHREALTIME] '; PS1=$'\001\r''${|
35	local e=$?
36
37	(( e )) && REPLY+="$e|"
38	REPLY+=${USER:=$(ulimit -c 0; id -un 2>/dev/null || echo \?)}
39	REPLY+=@${HOSTNAME%%.*}:
40
41	local d=${PWD:-?} p=~; [[ $p = ?(*/) ]] || d=${d/#$p/~}
42	local m=${%d} n p=...; (( m > 0 )) || m=${#d}
43	(( m > (n = (COLUMNS/3 < 7 ? 7 : COLUMNS/3)) )) && d=${d:(-n)} || p=
44	REPLY+=$p$d
45
46	return $e
47} '"$PS1 "; export EDITOR HOSTNAME MKSH TERM USER
48alias ls=ls
49unalias ls
50alias l='ls -F'
51alias la='l -a'
52alias ll='l -l'
53alias lo='l -alo'
54alias doch='sudo mksh -c "$(fc -ln -1)"'
55whence -p rot13 >/dev/null || alias rot13='tr \
56    abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ \
57    nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM'
58if whence -p hd >/dev/null; then :; elif whence -p hexdump >/dev/null; then
59	function hd {
60		hexdump -e '"%08.8_ax  " 8/1 "%02X " " - " 8/1 "%02X "' \
61		    -e '"  |" "%_p"' -e '"|\n"' "$@"
62	}
63else
64	function hd {
65		local -Uui16 -Z11 pos=0
66		local -Uui16 -Z5 hv=2147483647
67		local dasc line i
68
69		cat "$@" | { set +U; if read -arN -1 line; then
70			typeset -i1 line
71			i=0
72			while (( i < ${#line[*]} )); do
73				hv=${line[i++]}
74				if (( (pos & 15) == 0 )); then
75					(( pos )) && print -r -- "$dasc|"
76					print -n "${pos#16#}  "
77					dasc=' |'
78				fi
79				print -n "${hv#16#} "
80				if (( (hv < 32) || (hv > 126) )); then
81					dasc+=.
82				else
83					dasc+=${line[i-1]#1#}
84				fi
85				(( (pos++ & 15) == 7 )) && print -n -- '- '
86			done
87			while (( pos & 15 )); do
88				print -n '   '
89				(( (pos++ & 15) == 7 )) && print -n -- '- '
90			done
91			(( hv == 2147483647 )) || print -r -- "$dasc|"
92		fi; }
93	}
94fi
95
96# Berkeley C shell compatible dirs, popd, and pushd functions
97# Z shell compatible chpwd() hook, used to update DIRSTACK[0]
98DIRSTACKBASE=$(realpath ~/. 2>/dev/null || print -nr -- "${HOME:-/}")
99set -A DIRSTACK
100function chpwd {
101	DIRSTACK[0]=$(realpath . 2>/dev/null || print -r -- "$PWD")
102	[[ $DIRSTACKBASE = ?(*/) ]] || \
103	    DIRSTACK[0]=${DIRSTACK[0]/#$DIRSTACKBASE/~}
104	:
105}
106chpwd .
107function cd {
108	builtin cd "$@" || return $?
109	chpwd "$@"
110}
111function cd_csh {
112	local d t=${1/#~/$DIRSTACKBASE}
113
114	if ! d=$(builtin cd "$t" 2>&1); then
115		print -u2 "${1}: ${d##*cd: $t: }."
116		return 1
117	fi
118	cd "$t"
119}
120function dirs {
121	local d dwidth
122	local -i fl=0 fv=0 fn=0 cpos=0
123
124	while getopts ":lvn" d; do
125		case $d {
126		(l)	fl=1 ;;
127		(v)	fv=1 ;;
128		(n)	fn=1 ;;
129		(*)	print -u2 'Usage: dirs [-lvn].'
130			return 1 ;;
131		}
132	done
133	shift $((OPTIND - 1))
134	if (( $# > 0 )); then
135		print -u2 'Usage: dirs [-lvn].'
136		return 1
137	fi
138	if (( fv )); then
139		fv=0
140		while (( fv < ${#DIRSTACK[*]} )); do
141			d=${DIRSTACK[fv]}
142			(( fl )) && d=${d/#~/$DIRSTACKBASE}
143			print -r -- "$fv	$d"
144			let fv++
145		done
146	else
147		fv=0
148		while (( fv < ${#DIRSTACK[*]} )); do
149			d=${DIRSTACK[fv]}
150			(( fl )) && d=${d/#~/$DIRSTACKBASE}
151			(( dwidth = (${%d} > 0 ? ${%d} : ${#d}) ))
152			if (( fn && (cpos += dwidth + 1) >= 79 && \
153			    dwidth < 80 )); then
154				print
155				(( cpos = dwidth + 1 ))
156			fi
157			print -nr -- "$d "
158			let fv++
159		done
160		print
161	fi
162	return 0
163}
164function popd {
165	local d fa
166	local -i n=1
167
168	while getopts ":0123456789lvn" d; do
169		case $d {
170		(l|v|n)	fa+=" -$d" ;;
171		(+*)	n=2
172			break ;;
173		(*)	print -u2 'Usage: popd [-lvn] [+<n>].'
174			return 1 ;;
175		}
176	done
177	shift $((OPTIND - n))
178	n=0
179	if (( $# > 1 )); then
180		print -u2 popd: Too many arguments.
181		return 1
182	elif [[ $1 = ++([0-9]) && $1 != +0 ]]; then
183		if (( (n = ${1#+}) >= ${#DIRSTACK[*]} )); then
184			print -u2 popd: Directory stack not that deep.
185			return 1
186		fi
187	elif [[ -n $1 ]]; then
188		print -u2 popd: Bad directory.
189		return 1
190	fi
191	if (( ${#DIRSTACK[*]} < 2 )); then
192		print -u2 popd: Directory stack empty.
193		return 1
194	fi
195	unset DIRSTACK[n]
196	set -A DIRSTACK -- "${DIRSTACK[@]}"
197	cd_csh "${DIRSTACK[0]}" || return 1
198	dirs $fa
199}
200function pushd {
201	local d fa
202	local -i n=1
203
204	while getopts ":0123456789lvn" d; do
205		case $d {
206		(l|v|n)	fa+=" -$d" ;;
207		(+*)	n=2
208			break ;;
209		(*)	print -u2 'Usage: pushd [-lvn] [<dir>|+<n>].'
210			return 1 ;;
211		}
212	done
213	shift $((OPTIND - n))
214	if (( $# == 0 )); then
215		if (( ${#DIRSTACK[*]} < 2 )); then
216			print -u2 pushd: No other directory.
217			return 1
218		fi
219		d=${DIRSTACK[1]}
220		DIRSTACK[1]=${DIRSTACK[0]}
221		cd_csh "$d" || return 1
222	elif (( $# > 1 )); then
223		print -u2 pushd: Too many arguments.
224		return 1
225	elif [[ $1 = ++([0-9]) && $1 != +0 ]]; then
226		if (( (n = ${1#+}) >= ${#DIRSTACK[*]} )); then
227			print -u2 pushd: Directory stack not that deep.
228			return 1
229		fi
230		while (( n-- )); do
231			d=${DIRSTACK[0]}
232			unset DIRSTACK[0]
233			set -A DIRSTACK -- "${DIRSTACK[@]}" "$d"
234		done
235		cd_csh "${DIRSTACK[0]}" || return 1
236	else
237		set -A DIRSTACK -- placeholder "${DIRSTACK[@]}"
238		cd_csh "$1" || return 1
239	fi
240	dirs $fa
241}
242
243# pager (not control character safe)
244function smores {
245	(
246		set +m
247		cat "$@" |&
248		trap "rv=\$?; kill $! >/dev/null 2>&1; exit \$rv" EXIT
249		while IFS= read -pr line; do
250			llen=${%line}
251			(( llen == -1 )) && llen=${#line}
252			(( llen = llen ? (llen + COLUMNS - 1) / COLUMNS : 1 ))
253			if (( (curlin += llen) >= LINES )); then
254				print -n -- '\033[7m--more--\033[0m'
255				read -u1 || exit $?
256				[[ $REPLY = [Qq]* ]] && exit 0
257				curlin=$llen
258			fi
259			print -r -- "$line"
260		done
261	)
262}
263
264# base64 encoder and decoder, RFC compliant, NUL safe
265function Lb64decode {
266	[[ -o utf8-mode ]]; local u=$?
267	set +U
268	local c s="$*" t=
269	[[ -n $s ]] || { s=$(cat; print x); s=${s%x}; }
270	local -i i=0 j=0 n=${#s} p=0 v x
271	local -i16 o
272
273	while (( i < n )); do
274		c=${s:(i++):1}
275		case $c {
276		(=)	break ;;
277		([A-Z])	(( v = 1#$c - 65 )) ;;
278		([a-z])	(( v = 1#$c - 71 )) ;;
279		([0-9])	(( v = 1#$c + 4 )) ;;
280		(+)	v=62 ;;
281		(/)	v=63 ;;
282		(*)	continue ;;
283		}
284		(( x = (x << 6) | v ))
285		case $((p++)) {
286		(0)	continue ;;
287		(1)	(( o = (x >> 4) & 255 )) ;;
288		(2)	(( o = (x >> 2) & 255 )) ;;
289		(3)	(( o = x & 255 ))
290			p=0
291			;;
292		}
293		t+=\\x${o#16#}
294		(( ++j & 4095 )) && continue
295		print -n $t
296		t=
297	done
298	print -n $t
299	(( u )) || set -U
300}
301
302set -A Lb64encode_code -- A B C D E F G H I J K L M N O P Q R S T U V W X Y Z \
303    a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 + /
304function Lb64encode {
305	[[ -o utf8-mode ]]; local u=$?
306	set +U
307	local c s t
308	if (( $# )); then
309		read -raN-1 s <<<"$*"
310		unset s[${#s[*]}-1]
311	else
312		read -raN-1 s
313	fi
314	local -i i=0 n=${#s[*]} j v
315
316	while (( i < n )); do
317		(( v = s[i++] << 16 ))
318		(( j = i < n ? s[i++] : 0 ))
319		(( v |= j << 8 ))
320		(( j = i < n ? s[i++] : 0 ))
321		(( v |= j ))
322		t+=${Lb64encode_code[v >> 18]}${Lb64encode_code[v >> 12 & 63]}
323		c=${Lb64encode_code[v >> 6 & 63]}
324		if (( i <= n )); then
325			t+=$c${Lb64encode_code[v & 63]}
326		elif (( i == n + 1 )); then
327			t+=$c=
328		else
329			t+===
330		fi
331		if (( ${#t} == 76 || i >= n )); then
332			print $t
333			t=
334		fi
335	done
336	(( u )) || set -U
337}
338
339# Better Avalanche for the Jenkins Hash
340typeset -Z11 -Uui16 Lbafh_v
341function Lbafh_init {
342	Lbafh_v=0
343}
344function Lbafh_add {
345	[[ -o utf8-mode ]]; local u=$?
346	set +U
347	local s
348	if (( $# )); then
349		read -raN-1 s <<<"$*"
350		unset s[${#s[*]}-1]
351	else
352		read -raN-1 s
353	fi
354	local -i i=0 n=${#s[*]}
355
356	while (( i < n )); do
357		((# Lbafh_v = (Lbafh_v + s[i++] + 1) * 1025 ))
358		((# Lbafh_v ^= Lbafh_v >> 6 ))
359	done
360
361	(( u )) || set -U
362}
363function Lbafh_finish {
364	local -Ui t
365
366	((# t = (((Lbafh_v >> 7) & 0x01010101) * 0x1B) ^ \
367	    ((Lbafh_v << 1) & 0xFEFEFEFE) ))
368	((# Lbafh_v = t ^ (t >>> 8) ^ (Lbafh_v >>> 8) ^ \
369	    (Lbafh_v >>> 16) ^ (Lbafh_v >>> 24) ))
370	:
371}
372
373# strip comments (and leading/trailing whitespace if IFS is set) from
374# any file(s) given as argument, or stdin if none, and spew to stdout
375function Lstripcom {
376	cat "$@" | { set -o noglob; while read _line; do
377		_line=${_line%%#*}
378		[[ -n $_line ]] && print -r -- $_line
379	done; }
380}
381
382# give MidnightBSD's laffer1 a bit of csh feeling
383function setenv {
384	eval export "\"$1\""'="$2"'
385}
386
387: place customisations below this line
388
389for p in ~/.etc/bin ~/bin; do
390	[[ -d $p/. ]] || continue
391	[[ :$PATH: = *:$p:* ]] || PATH=$p:$PATH
392done
393
394export SHELL=$MKSH MANWIDTH=80 LESSHISTFILE=-
395alias cls='print -n \\033c'
396
397#unset LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_IDENTIFICATION LC_MONETARY \
398#    LC_NAME LC_NUMERIC LC_TELEPHONE LC_TIME
399#p=en_GB.UTF-8
400#set -U
401#export LANG=C LC_CTYPE=$p LC_MEASUREMENT=$p LC_MESSAGES=$p LC_PAPER=$p
402
403unset p
404
405: place customisations above this line
406