code:
#!/bin/sh

# wrapper script to set up environment for butch-core
# and redirects to several extension scripts
# + aliases to some commands

[ "$STAGE" = "0" ] && [ -z "$CONFIG" ] && CONFIG="$PWD/config"
[ -z "$CONFIG" ] && CONFIG=/src/config

if [ ! -e "$CONFIG" ] ; then
	echo "error: $CONFIG not found"
	exit 1
fi

. "$CONFIG"

BINDIR=$(dirname "$(readlink -f "$0")")

# butch-core requires these paths
[ ! -d $C ] && mkdir -p $C
[ ! -d $LOGPATH ] && mkdir -p $LOGPATH

usage() {
cat << EOF >&2
butch v$(butch-core 2>&1 | head -n1 | sed -e 's@butch-core v@@')

usage: $0 command package ...

------- available commands -----
install [<package> ... ]  # build and install <packages>
download [<package> ... ] # download tarballs required by <packages>
rebuild [<package> ... ]  # rebuild already installed <packages>

install-service <args>    # install runit system service

relink <package>          # create symlinks for an unlinked <package>
unlink <package>          # remove symlinks to a specific <package>
rm [<package> ... ]       # completely remove installed <packages>
genfilelist <package>     # create filelist for <package>

pack [--method] <package> # create a binary archive of <package>
unpack <filename>         # install binary archive <filename> created with pack
builddeps <package>       # build and install dependencies of package

list                      # list installed packages
files <package>           # show files installed by <package>
mirrors <package>         # print mirrors for <package>
owner <file>              # print which package owns a <file>
users <package>           # print packages with <package> for dependency
deps [<package> ... ]     # print deps of <packages>

checksum <package>        # print checksums of files for a <package>
checkdownloads            # verify all package download links
checktarballs             # verify the downloaded package tarballs

printsec <pkg> <section>  # print the specified <section> of <package>
search <term>             # search for <term> in packages (grep syntax)
ucheck [<package> ... ]   # check for upstream updates in <packages>

dlinfo <url>              # download url, print initial butch recipe

update                    # rebuild installed packages with new recipes

download related actions are performed on-demand, i.e. the tarball is missing

EOF
}

prog=butch-core
case $1 in
	build) shift ; set -- install "$@";;
	download) shift ; set -- prefetch "$@";;
	pack) shift; prog=butch-pack;;
	unpack) shift; prog=butch-unpack;;
	genfilelist) shift; prog=butch-genfilelist;;
	builddeps) shift; prog=butch-builddeps;;
	list) shift; prog=butch-list;;
	owner) shift; prog=butch-owner;;
	files) shift; prog=butch-files;;
	search) shift; prog=butch-search;;
	ucheck) shift; prog="butch-ucheck --check";;
	printsec) shift; prog=butch-printsec;;
	mirrors) shift; prog=butch-mirrors;;
	users) shift; prog=butch-users;;
	deps) shift; prog=butch-deps;;
	checksum) shift; prog=butch-checksum;;
	checkdownloads) shift; prog=butch-checkdownloads;;
	checktarballs) shift; prog=butch-checktarballs;;
	dlinfo) shift; prog=butch-dlinfo;;
	install-service) shift; prog=butch-install-service;;
	unlink) shift ; prog=butch-unlink;; #remove links of pkg
	rm) shift; prog=butch-rm;;
	relink|relocate) shift; prog=butch-relocate;; #relinks the pkg into /
	update) export BUTCH_SKIPLIST=gcc3:stage0:stage0_musl:stage0_gcc:stage0_prepare:"$BUTCH_SKIPLIST" ;;
	install|prefetch|rebuild) : ;;
	*) usage && exit 1;;
esac

exec "$BINDIR"/$prog "$@"

path: KEEP/bin/butch


code:
#!/bin/sh
if [ -z "$S" ] ; then
	echo 'S not set, did you source config?'
	exit 1
fi

pkg=$1
if [ -z "$pkg" ] ; then
	echo 'this script installs all dependencies of a package'
	echo '(but not the package itself).'
	exit 1
fi

fl=$S/pkg/$pkg
if [ ! -e "$fl" ] ; then
	echo "package $fl does not exist!"
	exit 1
fi

butch install `butch printsec "$pkg" deps`

repo_name: aarf/bkauler

path: KEEP/bin/butch-builddeps

license: unknown


code:
#!/bin/sh
if [ -z "$S" ] ; then
	echo 'S not set, did you source config?'
	exit 1
fi

if (wget --help 2>&1 |grep -q BusyBox) ; then
        CMD='wget -s -T 60 -q'
else
        CMD='wget --spider --timeout 60 -q'
fi

tmp=$(mktemp)
cat "$S"/pkg/* | grep -E '^http://|^https://' > "$tmp"

while read -r p
do
        $CMD "$p" 2>/dev/null || echo "$p"
done < "$tmp"

rm "$tmp"

path: KEEP/bin/butch-checkdownloads


code:
#!/bin/sh
if [ -z "$S" ] ; then
	echo 'S not set, did you source config ?'
	exit 1
fi
pkg=$1
if [ -z "$pkg" ] ; then
	echo 'need package name as argv!'
	exit 1
fi

[ -z "$butch_staging_dir" ] && butch_staging_dir=/opt

[ -z "$butch_filelists" ] && butch_filelists="$S"/filelists

fl="$butch_filelists"/"$pkg".txt
if [ ! -e "$fl" ] ; then
	echo "filelist $fl does not exist, probably the program is not installed"
	exit 1
fi
tmpf=$(mktemp)
getsha() {
	local foo=$(sha512sum "$1")
	[ "$?" != 0 ] && return 1
	printf "%s" "$foo" | cut -d " " -f 1
}
for f in `cat "$fl" | sort` ; do
	fs=$(printf "%s\n" "$f" | sed 's,^.,,g')
	[ "$R" = "/" ] || fs="$R""$fs"
	butch_install_dir="$butch_staging_dir"/"$pkg"
	sha=$(getsha "$butch_install_dir""$fs") || {
		rm "$tmpf"
		exit 1
	}
	printf "%s %s\n" "$sha" "$fs" >> "$tmpf"
done
getsha "$tmpf"
rm "$tmpf"

path: KEEP/bin/butch-checksum


code:
#!/bin/sh
if [ -z "$C" ] ; then
        echo 'C not set, did you source config ?'
        exit 1
fi

getfilesize() {
	stat "$1" | awk '/Size: /{print $2}'
}

ec=0
for p in "$S"/pkg/* ; do
	fn=
	fs=
	section=
	while read l ; do
		if [ -z "$l" ] ; then :
		elif [ "$section" = mirrors ] && [ -z "$fn" ] ; then
			fn=$(basename "$l")
		elif [ "$section" = vars ] && [ -z "$fs" ] ; then
			case "$l" in filesize=*) fs="${l#*=}" ;; esac
		elif [ "$l" = "[build]" ]; then
			break
		else
			if [ "$l" = '[mirrors]' ] || [ "$l" = '[vars]' ] ; then
				section=$(echo "$l"|sed -e 's/^\[//' -e 's/\]$//')
			else
				case "$l" in '['*) section= ;;	esac
			fi
		fi
		if [ -n "$fn" ] && [ -n "$fs" ] ; then
			break
		fi
	done < "$p"
	if [ -z "$fn" ] ; then
		# doesnt seem to have [mirrors]
		:
	elif [ -n "$fn" ] && [ -z "$fs" ] ; then
		echo "error parsing $p"
		exit 1
	elif [ -e "$C"/"$fn" ] ; then
		fsgot=$(getfilesize "$C"/"$fn")
		if [ "$fsgot" != "$fs" ] ; then
			echo "$fn: want $fs, got $fsgot"
			ec=1
		fi
	fi
done

exit "$ec"

path: KEEP/bin/butch-checktarballs


code:
#!/bin/sh
test -n "$CONFIG" && . $CONFIG
BINDIR=$(dirname $(readlink -f "$0"))
timestamp() {
	date '+%Y-%m-%d %H:%M:%S'
}
info() {
	printf "%s %s\n" "$(timestamp)" "$1"
}
die() {
	echo "$@" >&2
	exit 1
}
usage() {
cat << EOF
butch-core v0.7.0
syntax: $0 command options

commands: install, rebuild, prefetch

pass an arbitrary number of package names as options

        install: installs one or more packages when they're not yet installed
                (list of installed packages is kept in /var/lib/butch.db unless
                 overridden via BUTCHDB env var.)
        rebuild: installs one or more packages even when they're already
                installed
        prefetch: only download the given package and all of its dependencies,
                unless they're not already in $C
        <strike>update: rebuild all packages that changed since last build</strike>

EOF
exit 1
}
check_access() {
	test -$2 $1 || die "permissions for $1 insufficient (want: $2)"
}
check_config() {
[ -z "$BUTCH_DOWNLOAD_TEMPLATE" ] && die "BUTCH_DOWNLOAD_TEMPLATE not set"
[ -z "$BUTCH_BUILD_TEMPLATE" ] && die "BUTCH_BUILD_TEMPLATE not set"
[ -e "$BUTCH_DOWNLOAD_TEMPLATE" ] || die "$BUTCH_DOWNLOAD_TEMPLATE not found"
[ -e "$BUTCH_BUILD_TEMPLATE" ] || die "$BUTCH_BUILD_TEMPLATE not found"
[ -z "$A" ] && die "need to set A to your arch (ex. x86_64, i386, arm, mips...)"
[ -z "$R" ] && R=/
[ -z "$S" ] && S=$R/src
[ -z "$B" ] && B=$S/build
[ -z "$C" ] && C=$S/tarballs
[ -z "$K" ] && K=$S/KEEP
[ -z "$LOGPATH" ] && LOGPATH=$S/logs
[ -z "$BUTCHDB" ] && BUTCHDB=$R/var/lib/butch.db
[ -z "$BUTCH_DL_THREADS" ] && BUTCH_DL_THREADS=16
check_access $LOGPATH w
check_access $R w
check_access $S r
check_access $C w
check_access $K r
if ! test -w $B ; then
	mkdir -p $B
	check_access $B w
fi
local dbd=$(dirname $BUTCHDB)
mkdir -p $dbd
check_access $dbd w
export A B C K R S BUTCHDB LOGPATH BUTCH_BUILD_TEMPLATE \
BUTCH_DOWNLOAD_TEMPLATE DEPS BUTCH_SKIPLIST BUTCH_DL_THREADS
}
has_mirrors() {
	grep -x '\[mirrors\]' $S/pkg/$1 >/dev/null 2>&1
}
is_installed() {
	echo "installed $1" >&4
	read res_ <&3
	test $res_ = 0 && return 1
	return 0
}
gethash() {
	sha512sum "$S"/pkg/"$1" | cut -d " " -f 1
}
update_butchdb() {
	echo "INSTALLED $1" >&4
	rm -f $BUTCHDB.tmp
	[ -e "$BUTCHDB" ] && while read pkg_ hash_ ; do
	test "$pkg_" = "$1" || printf "%s %s\n" "$pkg_" "$hash_" >> $BUTCHDB.tmp
	done < $BUTCHDB
	printf "%s %s\n" "$1" "$(gethash $1)" >> $BUTCHDB.tmp
	mv $BUTCHDB.tmp $BUTCHDB
}
has_all_deps() {
	echo "hasdeps $1" >&4
	read resp_ <&3
	test $resp_ = 1 && return 0 || return 1
}
dl_one() {
	scrname=$B/dl_$1.sh
	logname=$LOGPATH/dl_$1.log
	info "downloading $1 ($scrname) -> $logname"
	$BINDIR/butch-merge $1 $BUTCH_DOWNLOAD_TEMPLATE > $scrname
	chmod +x $scrname
	$scrname > $logname 2>&1 && echo "OK $1" || echo "FAIL $1"
}

start_dl() {
[ -z "$@" ] && echo "DONE DONE" && return 0
[ -z "$JOBFLOW" ] && type jobflow >/dev/null 2>&1 && JOBFLOW=jobflow
if [ -n "$JOBFLOW" ] && [ -x "$JOBFLOW" ] ; then
cat << EOF | sed 's/ /\n/g' | "$JOBFLOW" -threads=$BUTCH_DL_THREADS \
  -delayedspinup=$(($BUTCH_DL_THREADS * 2)) -exec $0 dl_one {}
$@
EOF
else
	for p in $@ ; do
		$0 dl_one "$p"
	done
fi
echo DONE DONE
}
setup_pipe() {
	fd=$1
	node="$(mktemp -u)" || exit 1
	mkfifo -m0600 "$node" || exit 1
	eval "exec $fd<> $node"
	rm "$node"
}
buildlist=
dllist=
dlerr=
builderr=
mode=
force=false
case $1 in
	install) mode=build;;
	build) mode=build;;
	rebuild) mode=build; force=true;;
	download) mode=download; force=true;;
	prefetch) mode=download; force=true;;
	dl_one) mode=download_one;;
	*) usage ;;
esac
shift
test $mode = download_one && { dl_one "$1" ; exit $? ; }
check_config
args="$@"
for x_ in $args ; do
	test -r "$S"/pkg/"$x_" || die "$S/pkg/$x_ does not exist or no read permission!"
done
in_args() {
	for x_ in $args ; do
		test "$x_" = "$1" && return 0
	done
	return 1
}
add_dllist() {
	test -z "$dllist" && dllist="$1" || dllist="$dllist $1"
}
add_dlerr() {
	test -z "$dlerr" && dlerr="$1" || dlerr="$dlerr $1"
}
add_builderr() {
	test -z "$builderr" && builderr="$1" || builderr="$builderr $1"
}
add_downloaded() {
	echo "DOWNLOADED $1" >&4
}
add_buildlist() {
	test -z "$buildlist" && buildlist="$1" || buildlist="$buildlist $1"
}
rem_buildlist() {
	bl_old="$buildlist"
	buildlist=
	for h_ in $bl_old ; do
		test "$h_" = "$1" || add_buildlist "$h_"
	done
}
is_downloaded() {
	echo "downloaded $1" >&4
	read resss_ <&3
	test $resss_ = 1 && return 0 || return 1
}
start_build() {
	scrname=$B/build_$1.sh
	logname=$LOGPATH/build_$1.log
	info "building $1 ($scrname) -> $logname"
	$BINDIR/butch-merge $1 $BUTCH_BUILD_TEMPLATE > $scrname
        chmod +x $scrname
	success=false
        $scrname > $logname 2>&1 && success=true
	$success && update_butchdb "$1" || info "WARNING: $1 failed to build! wait for other jobs to finish."
	$success
}
launch_build() {
	for j_ in $buildlist ; do
		if has_all_deps "$j_" && is_downloaded "$j_" ; then
			start_build "$j_" || add_builderr "$j_"
			rem_buildlist "$j_"
			return 0
		fi
	done
	return 1
}

deps=$(awk -f $BINDIR/butch-deps "$@")
test $? = 0 || die "butch deps failed"

[ -z "$AWKPROG" ] && AWKPROG=awk
if [ "$STAGE" = 0 ] ; then
	$AWKPROG -W version 2>/dev/null | grep "mawk" > /dev/null && \
	AWKPROG="$AWKPROG -W interactive" #work around mawk bug...
fi
setup_pipe "3"
setup_pipe "4"
(BUTCHBINDIR=$BINDIR $AWKPROG -f $BINDIR/butch-core-helper <&4 >&3) &
hlppid=$!

trap "exit" INT TERM
trap "kill 0" EXIT

for p in $deps ; do
	if is_installed "$p" ; then
		if $force && in_args "$p" ; then
			test $mode != download && add_buildlist "$p"
			has_mirrors "$p" && add_dllist "$p" || add_downloaded "$p"
		else
			echo "package $p is already installed, skipping"
		fi
	else
		test $mode != download && add_buildlist "$p"
		has_mirrors "$p" && add_dllist "$p" || add_downloaded "$p"
	fi
done

echo "*** downloadqueue ***"
for p in $dllist ; do printf "%s\n" "$p" ; done

setup_pipe "5"
start_dl "$dllist" >&5 &
dlpid=$!

dlfails=0

echo "*** buildqueue ***"
for p in $buildlist ; do printf "%s\n" "$p" ; done

while read line ; do
	cnt=0
	for foo in $line ; do
		test $cnt = 0 && status="$foo"
		test $cnt = 1 && pkg="$foo" && break
		cnt=1
	done
	if [ "$status" != OK ] && [ "$status" != FAIL ] && [ "$status" != DONE ] ; then
		printf "%s\n" "$line"
	fi
	test "$status" = OK && add_downloaded "$pkg"
	test "$status" = "FAIL" && add_dlerr "$pkg" && dlfails=$(($dlfails + 1)) && \
	info "WARNING: package $pkg failed to download!"
	while launch_build ; do
		:
	done
	test "$status" = DONE && {
		wait $dlpid
		break
	}
done <&5
echo "QUIT" >&4
wait $hlppid
# at this point the child processes are reaped, undo EXIT trap
trap - EXIT
bfails=0
afails=0
test $mode = download || {
  for p in $builderr ; do bfails=$(($bfails + 1)) ; done
  for p in $buildlist ; do afails=$(($afails + 1)) ; done
}
info "done."
echo "got $dlfails download errors and $bfails build errors."
test $dlfails -gt 0 && echo "failed to download: $dlerr"
test $bfails -gt 0 && echo "failed to build: $builderr"
test $afails -gt 0 && echo "not built due to missing deps: $buildlist"
exit $(($dlfails + $bfails))

path: KEEP/bin/butch-core


code:
#!/bin/awk -f
BEGIN {
	if (!ENVIRON["BUTCHDB"]) {
		error("$BUTCHDB not set")
	}
	if (!ENVIRON["BUTCHBINDIR"]) {
		error("$BUTCHBINDIR not set")
	}
	while ((r = getline < ENVIRON["BUTCHDB"]) == 1) {
		INSTALLED[$1] = 1
	}
	close(ENVIRON["BUTCHDB"])
}
function eprint(msg) {
        print msg > "/dev/stderr"
}
function error(msg) {
        eprint("error: " msg)
        exit 1
}
function say(msg) {
	print msg
	system("") #force gawk to flush stdout portably
}
function get_deps(pkg,   var) {
	if(!GOTDEPS[pkg]) {
		command="awk -f " ENVIRON["BUTCHBINDIR"] "/butch-deps " pkg
		while ((command | getline var) > 0) {
			if(!DEPS[pkg]) DEPS[pkg] = var;
			else DEPS[pkg] = DEPS[pkg] " " var
		}
		close(command)
		GOTDEPS[pkg] = 1
	}
}
# uppercase command: notification
# lowercase command: question
/^QUIT$/ {
	exit 0
}
/^INSTALLED / {
	INSTALLED[$2] = 1
}
/^installed / {
	say(INSTALLED[$2] ? INSTALLED[$2] : "0")
}
/^DOWNLOADED / {
	DOWNLOADED[$2] = 1
}
/^downloaded / {
	say(DOWNLOADED[$2] ? DOWNLOADED[$2] : "0")
}
/^deps / {
	get_deps($2)
	say(DEPS[$2])
}
/^hasdeps / {
	get_deps($2)
	n=split(DEPS[$2],a," ")
	res=1
	for(i=1;i<=n;i++) {
		if(a[i] != $2 && !INSTALLED[a[i]]) {
			res=0
			break;
		}
	}
	say(res)
}

path: KEEP/bin/butch-core-helper


code:
#!/bin/awk -f
# use: $0 <package> [<package>...]
# prints all packages that would be built by building <package>(s), in build order.
BEGIN {
	if (!ENVIRON["S"]) {
		error("$S is not set. be sure to source config: . ./config")
	}
	if (ARGC<2) {
		error("please provide one or more packages to print the build order for.")
	}
	debugmode=ENVIRON["DEBUG"]
	if(!ENVIRON["DEPS"]) ENVIRON["DEPS"]="all"
	split(ENVIRON["DEPS"],x,":")
	for(a in x) {
		if(x[a]=="all") {
			DEPTYPES["build"]="deps";
			DEPTYPES["host"]="deps.host";
			DEPTYPES["run"]="deps.run";
			break;
		} else {
			DEPTYPES[x[a]]= x[a]=="build"?"deps":"deps." x[a];
		}
	}
	recursion=0
	for(a=1; a<ARGC; a++) {
		print_build_order(ARGV[a])
	}
}

function eprint(msg) {
	print msg > "/dev/stderr"
}
function error(msg) {
	eprint("error: " msg)
	exit 1
}

function print_build_order(pkg,		inDepsSection, dep, pkgFile,i,foo) {
	pkgFile=ENVIRON["S"] "/pkg/" pkg
	if (SEEN[pkg]) {
		return
	}
	recursion++;
	if(debugmode) {
		if(debugmode > 1) eprint("< " pkgFile " :")
		foo=""
		for(i=0;i<recursion;i++) foo = foo "-"
		eprint(foo pkg)
	}
	while ((r = getline < pkgFile) == 1) {
		dep=$0
		if (/^\[deps(\.([a-z0-9])+)?\]$/) {
			inDepsSection=0
			for(i in DEPTYPES) {
				if ($0 == "[" DEPTYPES[i] "]") {
					inDepsSection=1
					break
				}
			}
			continue
		}
		if (/\[/) {
			inDepsSection=0
		}
		if (/^\s*$/ || !inDepsSection) {
			continue
		}
		print_build_order(dep)
	}
	if (r == -1) {
		error("unable to read from " pkgFile)
	}
	if(SEEN[pkg]) {
		error("circular dependency detected for " pkg ".")
	}
	print pkg
	SEEN[pkg]=1
	close(pkgFile)
	recursion--
}

path: KEEP/bin/butch-deps


code:
#!/bin/sh
set -e
if [ -z "$C" ] ; then
	if [ -d "`pwd`/KEEP" ] ; then
		C=`pwd`/tarballs
		mkdir -p "$C" 2>/dev/null || true
	else
		echo "error, missing config or not in sabotage tree" 1>&2
		exit 1
	fi
fi

url=$1
if [ -z "$url" ] ; then
	echo error, expecting an url as argument 1>&2
	exit 1
fi

geturlfilename() {
	echo "${url##*/}"
}

getfilesize() {
	wc -c "$1" | cut -d ' ' -f 1
}

gethash() {
	sha512sum "$1" | cut -d ' ' -f 1
}

fn="$C"/$(geturlfilename "$url")
if [ "$USE_CURL" = 1 ] ; then
	curl -c /dev/null -C - -k -L "$url" -o "$fn"
else
	if (wget --help 2>&1 |grep -q BusyBox) ; then
		CMD='wget -O'
	else
		CMD='wget --no-check-certificate -O'
	fi

	$CMD "$fn" "$url"
fi
echo '[mirrors]'
echo "$url"
echo
echo '[vars]'
echo filesize="$(getfilesize "$fn")"
echo sha512="$(gethash "$fn")"

path: KEEP/bin/butch-dlinfo


code:
#!/bin/sh
if [ -z "$S" ] ; then
	echo 'S not set, did you source config ?'
	exit 1
fi
pkg=$1
if [ -z "$pkg" ] ; then
	echo 'this script lists all files installed by a package.'
	echo 'need package name as argv!'
	exit 1
fi
fl=$S/filelists/$pkg.txt
if [ ! -e "$fl" ] ; then
	echo "filelist $fl does not exist, probably the program is not installed"
	exit 1
fi

while read f ; do
	fs=$(printf "%s\n" "$f" | sed 's,^.,,g')
	printf "%s\n" "$fs"
done < "$fl"

path: KEEP/bin/butch-files


code:
#!/bin/sh
if [ -z "$S" ] ; then
	echo 'S not set, did you source config ?'
	exit 1
fi
pkg=$1
if [ -z "$pkg" ] ; then
	echo 'this script creates a filelist for a package.'
	echo 'need package name as argv!'
	exit 1
fi

[ -z "$butch_filelists" ] && butch_filelists="$S"/filelists
fl="$butch_filelists"/"$pkg".txt
[ -z "$butch_staging_dir" ] && butch_staging_dir=/opt
test "$R" = / && R=
butch_install_dir=$R$butch_staging_dir/$pkg
set -e
mkdir -p "$butch_filelists"
echo "creating filelist $fl"
cd "$butch_install_dir"
find . -type f -or -type l > "$fl"

path: KEEP/bin/butch-genfilelist


code:
#!/bin/sh
# install systemwide runit service.

dest=$R

usage() {
	printf "creates directory structure and installs supplied run script for usage with runit\n"
	printf "USAGE: %s %s\n" $(basename "$0") "[--down --force --log] servicename filename_of_run_script"
	printf "%s\n" "--down: service is down by default"
	printf "%s\n" "--force: service will be overwritten if existent"
	printf "%s\n" "--log: create default logging service"
	printf "\n"
	printf "%s\n" "use env. var R to override install location (prefix+DESTDIR-like)"
	exit 1
}

down=
force=
log=
service=
infile=
for i ; do
	case "$i" in
		--down)  down=1 ; i= ;;
		--force) force=1 ; i= ;;
		--log)   log=1 ; i= ;;
	esac
	if [ -z "$i" ] ; then :
	elif [ -z "$service" ] ; then
		service="$i"
	elif [ -z "$infile" ] ; then
		infile="$i"
	else
		usage
	fi
done

[ -z "$service" -o -z "$infile" ] && usage
if [ ! -e "$infile" ] ; then
	echo "file $infile does not exist"
	exit 1
fi
case "$service" in */*) echo "service name must not contain slashes"; exit 1 ;; esac

if [ -z "$force" -a -e "$dest"/etc/service/"$service"/run ] ; then
	echo "service $service already exists!"
	echo "use --force if you want to overwrite it"
	exit 1
fi

set -e
mkdir -p "$dest"/var/service/
mkdir -p "$dest"/etc/service/"$service"
cp "$infile" "$dest"/etc/service/"$service"/run
chmod 0755 "$dest"/etc/service/"$service"/run
if [ "$log" = 1 ] ; then
	mkdir -p "$dest"/etc/service/"$service"/log
	cat << EOF > "$dest"/etc/service/"$service"/log/run
#!/bin/sh
exec svlogd -tt /var/log/$service
EOF
	chmod 0755 "$dest"/etc/service/"$service"/log/run
	mkdir -p "$dest"/var/log/"$service"
fi
[ "$down" = 1 ] && touch "$dest"/etc/service/"$service"/down

ln -sf ../../etc/service/"$service" "$dest"/var/service/

path: KEEP/bin/butch-install-service


code:
#!/bin/sh
[ -z "$BUTCHDB" ] && BUTCHDB=/var/lib/butch.db
if [ ! -e "$BUTCHDB" ] ; then
	echo "error: butch.db not found" >&2
	exit 1
fi
cat "$BUTCHDB" | cut -d " " -f 1

path: KEEP/bin/butch-list


code:
#!/bin/sh
[ -n "$CONFIG" ] && . $CONFIG
[ -z "$S" ] && { "error: S not set" ; exit 1; }
BINDIR=$(dirname $(readlink -f "$0"))
usage() {
cat << EOF
$0 pkg filename-of-template
merges pkg with template and writes the result to stdout.
EOF
}
[ -z "$2" ] && usage
pkg="$(basename "$1")"
template="$2"
[ -r "$S/pkg/$pkg" ] && [ -r "$2" ] || { echo "error could not read $S/pkg/$pkg and $2"; exit 1; }
hasbuild=false
grep -x '\[build\]' "$S/pkg/$pkg" >/dev/null 2>&1 && hasbuild=true
mirrors=$(awk -f $BINDIR/butch-printsec "$pkg" mirrors | sed 's/\n/ /g')
while read -r line ; do
if printf "%s\n" "$line" | grep -x "%BUTCH_CONFIG">/dev/null 2>&1 ; then
cat << EOF
export A=$A
export R=$R
export S=$S
export C=$C
export K=$K
export B=$B
EOF
awk -f $BINDIR/butch-printsec "$pkg" vars
cat << EOF
BUTCH_PACKAGE_NAME=$pkg
BUTCH_MIRROR_URLS="$mirrors"
EOF
elif printf "%s\n" "$line" | grep -x "%BUTCH_BUILDSCRIPT">/dev/null 2>&1 ; then
if $hasbuild ; then
	awk -f $BINDIR/butch-printsec "$pkg" build
else
	echo "exit 0"
fi
else
	printf "%s\n" "$line" | sed -e 's/%BUTCH_MIRROR_URLS/$BUTCH_MIRROR_URLS/g' \
	-e 's/%BUTCH_PACKAGE_NAME/$BUTCH_PACKAGE_NAME/g'

fi
done < "$template"

path: KEEP/bin/butch-merge


code:
#!/bin/sh
butch printsec "$1" mirrors

path: KEEP/bin/butch-mirrors


code:
#!/bin/sh
ec=0
for i ; do
	printf "%s:" "$i"
	link=$(readlink "$i")
	fail=$?
	if [ ! -e "$i" ] ; then
		echo "INEXISTANT"
		ec=1
	elif [ ! "$fail" = 0 ] ; then
		echo "UNKNOWN"
		ec=1
	else
		printf "%s\n" "$link" | \
		   awk 'BEGIN { FS="/" } \
        	        { for(i=1;i<=NF;i++) if($i=="opt") {if(i<NF) print $(i+1); else print "UNKNOWN"; exit} }'
	fi
done
exit "$ec"

path: KEEP/bin/butch-owner


code:
#!/bin/sh
if [ -z "$S" ] ; then
	echo 'S not set, did you source config?'
	exit 1
fi

usage() {
cat << EOF
butch pack : creates a distributable binary archive of an installed pkg in the
current directory.
may require root to catch all files.

butch pack [compressor] pkgname

optional: compressor can be one of
  --none: no compression. plain tar archive is created.
  --gz:   gzip compression.
  --xz:   fast xz compression.
  --xze:  xz compression (extreme).
EOF
exit 1
}

[ -z "$1" ] && usage

comp=none
ext=tar
case $1 in
--none) shift ;;
--gz) comp=gz ; ext=tar.gz ; shift ;;
--xz) comp=xz ; ext=tar.xz ; shift ;;
--xze) comp=xze ; ext=tar.xz ; shift ;;
esac

pkg=$1
[ -z "$pkg" ] && usage

fl=$S/pkg/$pkg
if [ ! -e "$fl" ] ; then
	echo "package $fl does not exist!"
	exit 1
fi

[ -z "$butch_staging_dir" ] && butch_staging_dir=/opt
me="$PWD"

tarflags=cf
test $comp = gz && tarflags=czf
test $comp = xz && tarflags=cJf
[ "$R" = "/" ] && R=
cd "$R"$butch_staging_dir
[ -d "$pkg" ] || { echo "error: $PWD/$pkg not found" ; exit 1 ; }
out=$me/${pkg}_$A.$ext
tar $tarflags "$out" "$pkg"
[ -e "$out" ] || exit 1
if test $comp = xze ; then
	tr=$me/${pkg}_$A.tar
	mv "$out" "$tr"
	xz -z -9 -e "$tr"
	[ -e "$out" ] || exit 1
fi
echo "$(basename $out) created."

path: KEEP/bin/butch-pack


code:
#!/bin/awk -f
# use: $0 <package> <section>
# prints section of package
BEGIN {
	if (!ENVIRON["S"]) {
		error("$S is not set. be sure to source config: . ./config")
	}
	if (ARGC!=3) {
		error("this script prints the specified section of the specified package\n" "need package name as argv 1 and section name as argv 2!")
	}
	print_sec(ARGV[1], ARGV[2])
}
function eprint(msg) {
	print msg > "/dev/stderr"
}
function error(msg) {
	eprint("error: " msg)
	exit 1
}

function print_sec(pkg, sec,		r, insect, pkgFile, isbuild) {
	pkgFile=ENVIRON["S"] "/pkg/" pkg
	insect=0
	isbuild=(sec == "build")
	while ((r = getline < pkgFile) == 1) {
		if (insect && !isbuild && /^\[.*\]$/) break
		if ($0 == "[" sec "]") {
			insect=1
			continue
		}
		if(insect) {
			if(/^\s*$/ && !isbuild) continue
			print $0
		}
	}
	if (r == -1) {
		error("unable to read from " pkgFile)
	}
	close(pkgFile)
	exit 0
}

path: KEEP/bin/butch-printsec


code:
#!/bin/sh
#set -x
[ -z "$butch_do_overwrite_on_copy" ] && butch_do_overwrite_on_copy=false
[ -z "$butch_staging_dir" ] && butch_staging_dir=/opt
[ 1 = $(printf "%s" "$butch_staging_dir" | awk '{n=split($0,a,"/"); print n-1;}') ] || {
	echo "error: butch_staging_dir may contain only one slash"
	echo "good: /opt /pkgs /app"
	echo "bad: /opt/ /var/pkgs /my/apps/"
	exit 1
}

relocate() {
	local dir=$1
	local backlinks=$2
	local do_copy=$3
	mkdir -p "$butch_root"/$dir
	[ -d "$butch_root""$butch_install_dir/$dir" ] || return 0
	cd "$butch_root""$butch_install_dir/$dir" || return 1
	[ -n "$V" ] && echo "relocating $butch_root$butch_install_dir/$dir"
        for i in * ; do
		if [ ! -L "$i" ] && [ -d "$i" ] ; then
			local save="$PWD"
			relocate "$dir/$i" "$backlinks/.." $do_copy
			cd "$save"
		elif [ -f "$i" ] || [ -L "$i" ] ; then
			target="$butch_root/$dir/$i"
			if $do_copy ; then
				if $butch_do_overwrite_on_copy || [ ! -e "$target" ] ; then
					echo cp -a "$butch_root$butch_install_dir/$dir/$i" "$target"
					cp -a "$butch_root$butch_install_dir/$dir/$i" "$target"
				fi
			else
				echo "ln -sf "$backlinks""$butch_install_dir"/"$dir"/"$i" $target"
				ln -sf "$backlinks""$butch_install_dir"/"$dir"/"$i" "$target"
			fi
		else
			[ -n "$V" ] && echo "UNKNOWN object $i"
                fi
	done
	[ -n "$V" ] && echo "relocation done"
}

if [ -z "$1" ] ; then
	echo "tool to manually symlink a built package"
	echo "(i.e. the ones in $butch_staging_dir/packagename)"
	echo "into /"

	echo "error: need to pass package name to relocate" >&2
	exit 1
fi

ec=0

for pkg ; do
	[ "$R" = "/" ] && R=
	butch_root=$R
	butch_install_dir="$butch_staging_dir"/"$pkg"
	if [ -d "$R""$butch_install_dir" ] ; then
		for loc in bin sbin include lib libexec share ; do
			relocate $loc .. false
		done
		for loc in etc var ; do
			relocate $loc .. true
		done
	else
		echo "warning: package $pkg does not seem to be installed" >&2
		ec=1
	fi
done

exit $ec

path: KEEP/bin/butch-relocate


code:
#!/bin/sh
#set -x
if [ -z "$S" ] ; then
	echo 'S not set, did you source config?'
	exit 1
fi
[ -z "$butch_staging_dir" ] && butch_staging_dir=/opt
[ "$R" = "/" ] && R=
[ -z "$BUTCHDB" ] && BUTCHDB=$R/var/lib/butch.db
[ -z "$butch_filelists" ] && butch_filelists="$S"/filelists

usage() {
cat << EOF
butch rm : completely remove installed package.
- unlink the package from $R
    in case the package overlaps with files from another package,
    this may result in missing files. for example gnu wget, if
    installed, overwrites busybox' /bin/wget symlink.
    after removing wget, it will appear as if busybox' wget is not
    available. you can fix that by relinking busybox.
- removes $R$butch_staging_dir/packagename
- remove filelist in $butch_filelists
- removes butch.db entry in $BUTCHDB

these operations may require root access.

synapsis:
butch rm package1 [package2 ... packageN]
EOF
exit 1
}

[ -z "$1" ] && usage
[ "$1" = --help ] && usage
for pkg ; do
if [ -e "$R$butch_staging_dir/$pkg" ] ; then
	butch unlink "$pkg" > /dev/null
	rm -rf "$R$butch_staging_dir/$pkg"
	echo "$pkg: removed."
else
	echo "$pkg: not installed."
fi
fl="$butch_filelists"/"$pkg".txt
rm -f "$fl"
sed -i '/^'"$pkg"' /d' "$BUTCHDB" || true

done

path: KEEP/bin/butch-rm


code:
#!/bin/sh
if [ -z "$S" ] ; then
	echo "error: S is not set, did you source config?"
	exit 1
fi
pkgdir="$S"/pkg
if [ ! -d "$pkgdir" ] ; then
	echo "error: cannot find pkg dir $pkgdir"
	exit 1
fi
find "$pkgdir"/ | sed 's@'"$pkgdir/"'@@g' - | grep "$@"

path: KEEP/bin/butch-search


code:
#!/bin/sh
if [ -z "$S" ] ; then
        echo 'S not set, did you source config ?'
        exit 1
fi

call=
[ -n "$DEBUG" ] && call="sh -x"
cdwasempty=true
[ -z "$UCHKDIR" ] && UCHKDIR=. || cdwasempty=false
store=$UCHKDIR/files
if $cdwasempty && ! [ -d "$store" ] ; then
	echo "$0 needs a working directory and drops a bunch of files in it."
	echo "unless UCHKDIR is set, it will default to doing so in the current"
	echo "directory. if you're fine with that and want to drop the files"
	echo "in here ($PWD), create a subdirectory named 'files' and try again."
	echo "in other words, run: mkdir -p $store"
	exit 1
else
	mkdir -p $store
fi

get_filesize() {
	wc -c "$1" |cut -d ' ' -f 1
}
get_chkurl() {
local chkurl=
tmp=$(mktemp -u).$$
trap "rm -f $tmp" SIGINT SIGHUP SIGTERM
butch printsec "$1" vars > $tmp
grep uchkurl= < $tmp >/dev/null && . $tmp
rm -f $tmp
if [ -n "$uchkurl" ] ; then
	printf "%s\n" "$uchkurl"
	return 0
fi
local mirrors="$(butch mirrors "$1" | head -n 1)"
[ -z "$mirrors" ] && return 1
printf "%s/\n" "$(dirname "$mirrors")"
return 0
}
url2sha() {
	printf %s "$1" | sha1sum |cut -d ' ' -f 1
}

usage() {
	echo -e \
	"$0 --check [pkg1] [pkg2] ... [pkgn]\n" \
	"   the only option for a user to call.\n" \
	"   automates all of the below commands\n" \
	"$0 --url [pkg]\n" \
	"   prints an URL to download\n" \
	"$0 --san [pkg]\n" \
	"   opens .html, sanitizes input, stores it in .new, deletes .html\n" \
	"$0 --dl [url]\n" \
	"   downloads url and saves it to sha.html\n" \
	"$0 --diff [pkg]\n" \
	"  diffs sha vs sha.new and adds sha entry in ucheck.index\n" \
	"$0 --db [pkg]\n" \
	"  adds pkg and sha to ucheck.index\n"
}

mode=
case "$1" in
	--check) mode=check ;;
	--url) mode=url ;;
	--san) mode=san ;;
	--dl) mode=dl ;;
	--diff) mode=diff ;;
	--db) mode=db;;
esac
shift

[ -z "$mode" ] && { usage ; exit 1 ; }
[ -z "$1" ] && { usage ; exit 1 ; }

if [ "$mode" = dl ] ; then
	fn=$store/$(url2sha "$1").html
	curl -L -s "$1" > $fn.tmp && mv $fn.tmp $fn || rm -f $fn.tmp
elif [ "$mode" = san ] ; then
	chkurl=$(get_chkurl "$1")
	[ $? != 0 ] && exit 1
	sha=$(url2sha "$chkurl")
	[ -e $store/$sha.html ] || exit 1
	[ $(get_filesize $store/$sha.html) -gt 0 ] || {
		rm $store/$sha.html
		exit 1
	}
	case "$chkurl" in
		ftp://*) fhref=cat ; fhref_arg=- ;;
		*) fhref=awk ; fhref_arg='/[Hh][Rr][Ee][Ff]=/ {n=split($0,a,"="); n=split(a[2],b,"\"");if(n==3) print b[2]; else print a[2];}' ;;
	esac
	cat $store/$sha.html | sed 's,>,>\n,g' \
	| $fhref "$fhref_arg" \
	| grep -e '[0-9]\.[0-9]' -e '\.tar\.' -e '\.xz' -e '\.tgz' \
	| grep -v -e '\.rpm$' -e '\.asc$' -e '\.sha1$' -e '\.sha256$' \
	  -e '\.sha256sum$' -e '\.md5$' -e '\.news$' -e '\.changes$' \
	  -e '\.sign$' -e '\.sig$' -e '\.deb$' -e '\.7z$' \
	  -e '\.readme$' -e '\.meta$' -e '\.txt$' \
	| sort -u \
	> $store/$sha.new
	rm $store/$sha.html
	[ $(get_filesize $store/$sha.new) -gt 0 ] || {
		rm $store/$sha.new
		exit 1
	}
	exit 0
elif [ "$mode" = url ] ; then
	get_chkurl "$1"
elif [ "$mode" = diff ] ; then
	chkurl=$(get_chkurl "$1")
	[ $? != 0 ] && exit 1
	sha=$(url2sha "$chkurl")
	[ -e "$store/$sha".new ] || exit 1
	skip=false
	if [ -e "$store/$sha" ] ; then
		diff -uw $store/$sha $store/$sha.new | sed 's/'$sha'/'$1'/g' \
		| grep '^+' | tee $store/$sha.diff
		sed -i '/^+++/d' $store/$sha.diff
		test $(get_filesize $store/$sha.diff) -gt 1 || skip=true
		rm -f $store/$sha.diff
	fi
	$skip || mv "$store/$sha".new "$store/$sha"
	$skip && rm -f "$store/$sha".new
elif [ "$mode" = db ] ; then
	chkurl=$(get_chkurl "$1")
	[ $? != 0 ] && exit 1
	sha=$(url2sha "$chkurl")
	e=false
	up=false
	[ -e ucheck.index ] && while read n ; do
		for p in $n ; do
			break
		done
		#p=$(printf %s "$n"|cut -d ':' -f 1)
		[ "$p" = "$1" ] && {
			for q in $n ; do : ; done
			[ "$q" = "$sha" ] && e=true || up=true
			break
		}
	done < ucheck.index
	$up && sed -i '/^'"$1 $q"'$/d' ucheck.index
	$e || printf "%s %s\n" "$1" "$sha" >> ucheck.index

elif [ "$mode" = check ] ; then
	echo "preparing download list..."
	rm -f urllist.tmp
	pkglist=
	for i ; do
	pkg="$(basename "$i")"
	$call $0 --url "$pkg" >> urllist.tmp
	if [ "$?" = 0 ] ; then
		[ -n "$pkglist" ] && pkglist="$pkglist $pkg" || pkglist="$pkg"
	fi
	done
	cat urllist.tmp | sort -u > urllist
	rm -f urllist.tmp
	echo -ne "downloading..."
	[ -z "$JOBFLOW" ] && type jobflow >/dev/null 2>&1 && JOBFLOW=jobflow
	if [ -n "$JOBFLOW" ] ; then
		echo "with jobflow..."
		cat urllist | "$JOBFLOW" -threads=16 -delayedspinup=160 \
			-exec $call $0 --dl {}
	else
		echo "without jobflow..."
		for i in `cat urllist` ; do $call $0 --dl "$i" ; done
	fi
	rm -f urllist
	echo "sanitizing..."
	for pkg in $pkglist ; do
		$call $0 --san "$pkg"
	done
	echo "adding db entries..."
	for pkg in $pkglist ; do
		$call $0 --db "$pkg"
	done
	echo "diffing..."
	for pkg in $pkglist ; do
		$call $0 --diff "$pkg"
	done

fi

path: KEEP/bin/butch-ucheck


code:
#!/bin/sh
if [ -z "$S" ] ; then
	echo 'S not set, did you source config ?'
	exit 1
fi
pkg=$1
if [ -z "$pkg" ] ; then
	echo 'this script unlinks all files installed by a package.'
	echo 'need package name as argv!'
	exit 1
fi

[ -z "$butch_filelists" ] && butch_filelists="$S"/filelists
fl="$butch_filelists"/"$pkg".txt
if [ ! -e "$fl" ] ; then
	echo "filelist $fl does not exist, probably the program is not installed"
	exit 1
fi

while read f ; do
	fs=$(printf "%s\n" "$f" | sed 's,^.,,g')
	[ "$R" = "/" ] || fs="$R""$fs"
	if [ -L "$fs" ] ; then
		rm -f "$fs" && echo "$fs removed successfully"
	fi
done < "$fl"

path: KEEP/bin/butch-unlink


code:
#!/bin/sh
#set -x
if [ -z "$S" ] ; then
	echo 'S not set, did you source config?'
	exit 1
fi
[ -z "$butch_staging_dir" ] && butch_staging_dir=/opt
[ -z "$butch_do_filelists" ] && butch_do_filelists=true
[ "$R" = "/" ] && R=
[ -z "$BUTCHDB" ] && BUTCHDB=/var/lib/butch.db
usage() {
cat << EOF
butch unpack : install binary package.
- unpacks a distributable binary archive of a pkg
- installs it into $R$butch_staging_dir
- links it into $R
- creates butch.db entry in $BUTCHDB
may require root access.

synapsis:
butch unpack filename
EOF
exit 1
}

print_pkg_and_sha() {
	printf "%s " "$pkg"
	i=0
	while test $i -lt 16 ; do
		printf "00000000"
		i=$(($i + 1))
	done
	echo
}

[ -z "$1" ] && usage
[ ! -e "$1" ] && usage
pkg=$(basename "$1" | cut -d '_' -f 1)
pl=$(printf "%s" "$pkg"|wc -c | cut -d " " -f 1)
arch=$(basename "$1" | cut -b $(($pl + 2))- | cut -d "." -f 1)
[ "$arch" = "$A" ] || {
	echo "error: arch $arch of "$1" doesnt match arch $A of config!"
	exit 1
}
fn=$(readlink -f "$1")

set -e
[ -e "$R$butch_staging_dir/$pkg" ] && {
butch unlink "$pkg" || true
rm -rf "$R$butch_staging_dir/$pkg"
}

(
cd $R$butch_staging_dir || {
echo "error: could not cd to $R$butch_staging_dir"
exit 1
}
tar xf "$fn"
)

butch relink "$pkg"
sed -i '/^'"$pkg"' /d' "$BUTCHDB" || true
print_pkg_and_sha >> "$BUTCHDB"
$butch_do_filelists && butch genfilelist "$pkg"
echo "successfully installed $pkg"

path: KEEP/bin/butch-unpack


code:
#!/bin/sh
if [ -z "$S" ] ; then
	echo "error: S is not set, did you source config?"
	exit 1
fi
pkgdir="$S"/pkg
if [ ! -d "$pkgdir" ] ; then
	echo "error: cannot find pkg dir $pkgdir"
	exit 1
fi
search_pkg="$1"
[ -z "$search_pkg" ] && {
	echo "error: need package name"
	exit 1
}
get_section() { #section, filename
  awk -v s="$1" '{if($1~/^\[/){if($1=="[" s "]")i=1;else if(i==1)exit;}else{if(i==1)print $0}}' "$2"
}

[ -z "$DEPS" ] && DEPS=build:host:run
for fn in `find "$pkgdir"/` ; do
	[ -d "$fn" ] && continue
	pkg=$(basename "$fn")
	for i in 1 2 3 ; do
		sec=deps.$(printf "%s" "$DEPS" | cut -d : -f $i)
		[ "$sec" = "deps." ] && continue
		[ "$sec" = "deps.build" ] && sec=deps
		get_section "$sec" "$fn" | grep -x "$search_pkg">/dev/null && {
#		butch printsec "$pkg" "$sec" | grep "$search_pkg">/dev/null && {
			printf "%s\n" "$pkg"
			break
		}
	done
done

path: KEEP/bin/butch-users


code:
#!/bin/sh

SHORTOPTS="LMUc:fw:nqvho:O:"
DEPS="cryptsetup blkid mkswap mktemp"
UDEVRUNNING=0

LOGLEVEL=1
DRYRUN=0
WAITTIME=10
CRYPTTAB=/etc/crypttab
OPTIONS=
FILTER="!noauto"
FORCE=0

ct_print_usage() {
	cat <<__EOF__
usage: $0 [OPTIONS] [-L]
       $0 [OPTIONS] -M [NAME|DEVICE]
       $0 [OPTIONS] -M NAME DEVICE [KEY]
       $0 [OPTIONS] -U [NAME[,...]]

  List, map, and unmap encrypted volumes. The utility is a wrapper for
  cryptsetup which makes use of a crypttab file.

  actions:
    -L       list the names of volumes defined in crypttab, this is
             the default
    -M       map a volume defined in crypttab or defined on the command
             line. with no arguments, map all volumes without the noauto
             option
    -U       unmap volumes defined in crypttab. with no arguments, unmap
             all volumes without the noauto option

  options:
    -c FILE  set the crypttab location (default: /etc/crypttab)
    -f       force destructive operations even when a block device appears to
             contain data
    -w NUM   wait time (seconds) for a device if it is not already available
    -n       dry run
    -q       decrease verbosity
    -v       increase verbosity
    -h       print this message
    -o OPT[,...]
             options which are appened to the options defined in crypttab
             (they take precedence). specifying this multiple times is
             cumulative
    -O OPT[,...]
             filter used *only* when no volumes are given on the command
             line. an option may start with a ! to require that it must not
             be present. specifying this multiple times is cumulative

__EOF__
	exit $1
}

# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #
#                                                                              #
# Utilities                                                                    #
#                                                                              #

error() {
	[ $LOGLEVEL -ge 0 ] && printf "E: %s\n" "$*" >&2 || true
}

die() {
	printf "E: %s\n" "$*" >&2
	exit ${1:-1}
}

warn() {
	[ $LOGLEVEL -ge 1 ] && printf "W: %s\n" "$*" >&2 || true
}

msg() {
	[ $LOGLEVEL -ge 1 ] && printf "M: %s\n" "$*" >&2 || true
}

info() {
	[ $LOGLEVEL -ge 2 ] && printf "I: %s\n" "$*" >&2 || true
}

run() {
	[ $LOGLEVEL -ge 2 ] && printf "R: %s\n" "$*" >&2
	if [ $DRYRUN -eq 1 ]; then
		true
	else
		"$@"
	fi
}

trim() {
	local IFS=$' \t\n'
	echo -n $*
}

get_mount() {
	if type findmnt >/dev/null 2>&1 ; then
		findmnt -cfmnoTARGET "$1"
	else
		cat /proc/self/mountinfo | \
		awk -v dev="$1" \
		'{ for(i=7;$i!="-";$i++); if($(i+2)==dev&&$4=="/"){print $5;r=1;exit}} END {exit !r}'
	fi
}

# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #
#                                                                              #
# Main functions                                                               #
#                                                                              #

ct_main() {

	local action

	set_action() {
		if [ -z $action ]; then
			action="$@"
		else
			error "only one of -L, -M, or -U may be given"
			ct_print_usage 1
		fi
	}

	while getopts ":$SHORTOPTS" opt ; do

		case $opt in
			L) set_action list;;
			M) set_action map;;
			U) set_action unmap;;
			c) CRYPTTAB="$OPTARG";;
			f) FORCE=1;;
			w) WAITTIME=${OPTARG//[!0-9]};;
			n) DRYRUN=1;;
			q) LOGLEVEL=$(( LOGLEVEL - 1 ));;
			v) LOGLEVEL=$(( LOGLEVEL + 1 ));;
			h) ct_print_usage 0;;
			o) OPTIONS="$OPTIONS,$OPTARG";;
			O) FILTER="$FILTER,$OPTARG";;
			:)
				error "option requires an argument -- '$OPTARG'"
				ct_print_usage 1
				;;
			?)
				error "invalid option -- '$OPTARG'"
				ct_print_usage 1
				;;
		esac

	done

	shift $(( OPTIND - 1 ))

	# Warn if any of the dependencies are missing
	for dep in $DEPS; do
		type $dep >/dev/null 2>&1 || info "$dep not found, some functionality may fail"
	done

	# Check for UDEV
	if pidof udevd >/dev/null 2>&1; then
		UDEVRUNNING=1
		info "Detected udevd"
	else
		info "udevd not running, or unable to detect it: waiting for devices disabled"
	fi

	# Pre-parse OPTIONS, a little ugly, but it works
	preparse() {
		local args tmpfs
		if ! ct_parse_options $OPTIONS; then
			error "Invalid options string: $OPTIONS"
			exit 1
		fi
		OPTIONS="$args"
	}
	preparse

	if [ -z "$action" -o "$action" = "list" ]; then

		if [ $# -ne 0 ]; then
			warn "With -L, volumes given on the command line have no effect"
		fi

		list_func() { printf "%s\n" "$1"; }
		ct_read_crypttab list_func

	elif [ "$action" = "unmap" ]; then

		if [ $# -gt 0 ]; then
			[ "$FILTER" != "!noauto" ] && \
				info "Filters from -O are ignored in this mode"
			unset FILTER
		fi

		ct_main_unmap "$@"

	elif [ "$action" = "map" ]; then

		if [ $# -ne 0 ]; then
			[ "$FILTER" != "!noauto" ] && \
				info "Filters from -O are ignored in this mode"
			unset FILTER
		fi

		ct_main_map "$@"

	else

		error "Internal error: no action"
		false

	fi
}

ct_main_unmap() {

	if [ $# -eq 0 ]; then

		ct_read_crypttab ct_unmap

	else

		local vol ret=0

		for vol in "$@"; do
			ct_unmap "$vol" || ret=$(( ret+1 ))
		done

		return $ret

	fi
}

ct_main_map() {

	if [ $# -eq 0 ]; then

		ct_read_crypttab ct_map

	elif [ $# -eq 1 ]; then

		local vol _tmp="$1"

		find_func() {
			if [ "$1" = "$_tmp" -o "$2" = "$_tmp" ]; then
				printf "%s" "$*"
			else
				false
			fi
		}

		if vol="$(ct_read_crypttab -1 find_func)"; then
			ct_map $vol
		else
			error "Unable to find '$_tmp' in '$CRYPTTAB'"
			false
		fi

	elif [ $# -le 3 ]; then

		ct_map "$@"

	else

		error "Too many options given for -M"
		ct_print_usage 1

	fi
}

# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #
#                                                                              #
# Functions for iterating over crypttab                                        #
#                                                                              #

ct_read_crypttab() {

	if [ ! -f "$CRYPTTAB" -o ! -r "$CRYPTTAB" ]; then
		error "cannot read $CRYPTTAB"
		return 1
	fi

	local func="$@" line lineno=0 name dev key options ret=0 adhoc=0

	if [ "$1" = "-1" ]; then
		adhoc=1
		shift
		func="$@"
	fi

	while read -r name dev key options <&3; do

		lineno=$(( lineno + 1 ))
		[ -z "$name" ] || [ ${name:0:1} = "#" ] && continue

		# unescape devname and keyname
		name=$(printf '%b' "$name")
		dev=$(printf '%b' "$dev")
		key=$(printf '%b' "$key")

		if [ -z "$name" ]; then
			warn "$CRYPTTAB:$lineno: the name (first column) cannot be blank"
			continue
		elif [ -z "$dev" ]; then
			warn "$CRYPTTAB:$lineno: the device (second column) cannot be blank"
			continue
		fi

		case $key in
			-|none|"")
				key=-
				;;
			/dev/random|/dev/urandom|/dev/hw_random)
				options="$options,%random"
				;;
			ASK)
				info "$CRYPTTAB:$lineno: ASK is a deprecated key, please use '-' or 'none'"
				key=-
				;;
			SWAP)
				info "$CRYPTTAB:$lineno: SWAP is a deprecated key, please use '/dev/urandom' and the 'swap' option"
				key="/dev/urandom"
				options="$options,swap,%random"
				;;
			/*|UUID=*|PARTUUID=*|LABEL=*)
				:
				;;
			*)
				warn "$CRYPTTAB:$lineno: plain text keys are not supported"
				key=-
				;;
		esac

		if ct_check_filter $options; then
			if ! $func "$name" "$dev" "$key" $options; then
				ret=$(( ret + 1 ))
			elif [ $adhoc -eq 1 ]; then
				ret=0
				break
			fi
		fi

	done 3< "$CRYPTTAB"

	return $ret
}

ct_check_filter() {

	local IFS=$',' fltr opt

	for fltr in $FILTER; do
		fltr="$(trim $fltr)"
		[ -z "$fltr" ] && continue

		if [ "x${fltr:0:1}" != "x!" ]; then

			for opt in $*; do
				opt="$(trim $opt)"
				[ -z "$opt" ] && continue

				if [ "$fltr" = "$opt" -o "$fltr" = "${opt%%=*}" ]; then
					continue 2
				fi
			done

			return 1

		else

			for opt in $*; do
				opt="$(trim $opt)"
				[ -z "$opt" ] && continue

				if [ "$fltr" = "!$opt" -o "$fltr" = "!${opt%%=*}" ]; then
					return 1
				fi
			done

		fi

	done

	return 0
}

# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #
#                                                                              #
#  Mapping, unmapping, finding stuff                                           #
#                                                                              #

ct_unmap() {
	local name="$1"
	if [ ! -e "/dev/mapper/$name" ]; then
		warn "Volume was not mapped (no '/dev/mapper/$name')"
	elif run cryptsetup remove "$name"; then
		info "$name unmapped"
	else
		error "failed to unmap $name"
		false
	fi
}

ct_map() {

	local name="$1" dev="$2" key="$3" args="" tmpfs
	local key_dev="" key_fstype="" key_mntpnt="" key_dev_umount=0
	shift 3

	if [ -e "/dev/mapper/$name" ]; then
		error "Volume is already mapped ('/dev/mapper/$name' exists')"
		return 1
	fi

	# this function sets the args and tmpfs variables
	if ! ct_parse_options "$@"; then
		error "Unable to parse options"
		return 1
	fi
	args="$args $OPTIONS"

	# resolve the encrypted device, can't do much without this
	if ! dev="$(ct_resolve_device "$dev")"; then
		error "device '$dev' not found"
		return 1
	fi

	# parse various key formats
	case "$key" in
		*:*:*)
			key_dev="${key%%:*}"
			key="${key#*:}"
			key_fstype="${key%%:*}"
			key="${key#*:}"
			case "$key_fstype" in
				*[!0-9]*)
					:;;
				*)
					warn "<dev>:<offset>:<length> is a deprecated key format. Please use"
					warn " the keyfile-offset and keyfile-size options instead. This"
					warn " format will *soon* be removed from cryptmount/crypttab!"
					opts="$opts --keyfile-offset=$key_fstype --keyfile-size=$key"
					key="$key_dev"
					unset key_fstype
					unset key_dev
			esac
			;;
		*:*)
			key_dev="${key%%:*}"
			key="${key#*:}"
			;;
		""|-)
			unset key_dev
			unset key
			;;
		*)
			unset key_dev
			;;
	esac

	# resolve any needed key device and mount if necessary
	if [ "$key_dev" ]; then

		if key_dev="$(ct_resolve_device "$key_dev")"; then

			if key_mntpnt="$(get_mount "$key_dev")"; then

				key="$key_mntpnt/$key"

			elif key_mntpnt="$(mktemp -d)"; then

				[ -n "$key_fstype" ] && key_fstype="-t $key_fstype"

				if run mount -r $key_fstype "$key_dev" "$key_mntpnt"; then
					key="$key_mntpnt/$key"
					key_dev_umount=1
				else
					error "unable to mount key device '$key_dev',"
					error " falling back on interactive password"
					unset key
				fi
			else
				error "unable to find or create mountpoint for key device,"
				error " falling back on interactive password"
				unset key
			fi
		else
			error "key device '$key_dev' not found"
			error " falling back on interactive password"
			unset key
		fi

	elif [ -n "$key" -a "$key" != "-" ]; then

		if ! key="$(ct_resolve_device "$key")"; then
			error "key '$key' not found"
			error " falling back on interactive password"
			unset key
		fi

	fi

	if [ "$key" ]; then
		key=--key-file="$key"
	fi

	local ret=0

	# the main event, run cryptsetup (and mkswap, mkfs if necessary)
	if cryptsetup isLuks "$dev"; then

		info "device '$dev' detected as LUKS"

		if run cryptsetup luksOpen $key $args "$dev" "$name"; then
			info "sucessfully mapped '$dev' to '/dev/mapper/$name'"
		else
			error "unable to map '$dev' to '/dev/mapper/$name'"
			ret=1
		fi

	else

		info "device '$dev' assumed to be plain"

		# cryptsetup 'create' can be destructive, don't do it if blkid can
		# identify the device type
		if [ $FORCE -ne 1 ] && blkid -p "$dev" >/dev/null 2>&1; then
			error "Refusing to call 'cryptsetup create' on device that might"
			error " have data. If you are sure this is what you want, use"
			error " the -f option"
			ret=1
		elif run cryptsetup create $key $args "$name" "$dev"; then
			info "sucessfully mapped '$dev' to '/dev/mapper/$name'"
			if [ "$tmpfs" = "swap" ]; then
				if run mkswap -f -L "$name" "/dev/mapper/$name"; then
					info "mkswap successful on '/dev/mapper/$name'"
				else
					error "mkswap failed for '/dev/mapper/$name'"
					ret=1
				fi
			elif [ "$tmpfs" ]; then
				if run mkfs -t "$tmpfs" "/dev/mapper/$name"; then
					info "mkfs successful on '/dev/mapper/$name'"
				else
					error "mkfs failed for '/dev/mapper/$name'"
					ret=1
				fi
			fi
		else
			error "unable to map '$dev' to '/dev/maper/name/$name'"
			ret=1
		fi

	fi

	# clean up after ourselves
	if [ $key_dev_umount -eq 1 ]; then
		if ! run umount "$key_dev"; then
			warn "unable to mount key device '$key_dev'"
		else
			run rmdir "$key_mntpnt"
		fi
	fi

	return $ret
}

ct_resolve_device() {

	local tmp="" device="$1" seconds=$WAITTIME tag tagval

	case "$device" in
		UUID=*|PARTUUID=*|LABEL=*)
			tmp="$(blkid -l -o device -t "$device")"
			if [ -z "$tmp" ]; then
				if [ $UDEVRUNNING -eq 1 ]; then
					tag="$(awk -v t="${device%%=*}" 'BEGIN { print tolower(t) }')"
					tagval="${device#*=}"
					device="/dev/disk/by-$tag/$tagval"
				fi
			else
				device="$tmp"
			fi
	esac

	if [ ! -e "$device" -a "${device:0:5}" = "/dev/" -a "$UDEVRUNNING" -eq 1 ]; then
		msg "Waiting $seconds seconds for '$device'..."
		until [ -e "$device" -o $seconds -eq 0 ]; do
			sleep 1
			seconds=$(( seconds - 1 ))
		done
	fi

	printf "%s" "$device"

	if [ -e "$device" ]; then
		info "resolve: found '$device'"
	else
		error "resolve: unable to find '$device'"
		return 1
	fi
}

ct_parse_options() {

	local IFS=',' optlst="$*" opt key val depr=0

	for opt in $optlst; do

		# separate key and value
		unset key val
		case "$opt" in
			"")
				continue;;
			-*)
				if [ $depr -eq 0 ]; then
					info "You are using a deprecated format for the options field. The entire"
					info " field will be passed directly to cryptsetup. Please use the more"
					info " standardized comma-deliminated options list instead. This format"
					info " will be removed in a future version of cryptmount/crypttab!"
					depr=1
				fi
				args="$args $opt"
				continue
				;;
			*=*)
				key="${opt%%=*}"
				val="${opt#*=}"
				[ "$key" = "$val" ] && unset val
				;;
			*)
				key="$opt";;
		esac

		case "$key" in
			swap)
				# set external variable
				tmpfs="swap"
				;;
			luks|plain)
				warn "Ignoring option $key, LUKS volumes are automatically detected"
				;;
			noauto|%*)
				:
				;;
			skip|precheck|check|checkargs|noearly|loud|keyscript)
				warn "Ignoring Debian specific option '$key'"
				;;
			tmp)
				# set an external variable
				[ -z "$val" ] && msg "Defaulting tmp to ext4"
				tmpfs="${val:-ext4}"
				;;
			size)
				args="$args --key-size $val"
				;;
			device-size)
				args="$args --size $val"
				;;
			none)
				args=
				;;
			*)
				if [ ${#key} -eq 1 ]; then
					args="$args -$key $val"
				else
					args="$args --$key $val"
				fi
				;;
		esac

	done

	return 0
}

#                                                                              #
# ---------------------------------------------------------------------------- #

ct_main "$@"

# vim: set ft=sh noet ts=2 sw=2 :

path: KEEP/bin/cryptmount


code:
#!/bin/sh
if [ -z "$1" ] ; then
	echo usage: $0 [interface]
	echo i.e. $0 eth0
	echo i.e. $0 wlan0
	exit 1
fi
interface="$1"
retries=1
/sbin/udhcpc -t $retries -n -i "$interface" -s /etc/udhcpc-script

path: KEEP/bin/dhclient


code:
#!/bin/sh
# busybox shell doesn't seem to implement "alias"
ls -la "$@"

path: KEEP/bin/la


code:
#!/bin/sh
# busybox shell doesn't seem to implement "alias"
ls -lat $@

path: KEEP/bin/lat


code:
#!/bin/sh
# no command line arguments - assume read from stdin
if [ -z "$1" ] || [ "$1" = - ] ; then
	curl -F 'sprunge=<-' http://sprunge.us
#file name argument: post to 0x0
elif [ -e "$1" ] ; then
	curl -F'file=@'"$1" https://0x0.st
else
cat << EOF
usage: head -n 20 foo.txt | $0
       $0 < foo.txt
text input from stdin will be pasted to http://sprunge.us
TODO: check if we want to use http://ix.io instead

usage: $0 filename
posts filename to https://0x0.st
this can be binary and up to 256MB.
EOF
fi

path: KEEP/bin/pastebin


path: KEEP/bin/runsvdir-start


code:
--- binutils-2.22-org/include/bfdlink.h	2011-11-21 10:29:37.000000000 +0100
+++ binutils-2.22/include/bfdlink.h	2012-01-30 15:02:10.402000027 +0100
@@ -91,6 +91,9 @@
   struct bfd_hash_entry root;

   /* Type of this entry.  */
+  #ifndef ENUM_BITFIELD
+  #define ENUM_BITFIELD(X) unsigned int
+  #endif
   ENUM_BITFIELD (bfd_link_hash_type) type : 8;

   unsigned int non_ir_ref : 1;


code:
--- boost_1_52_0.org/boost/detail/endian.hpp	2013-02-09 09:32:18.027165235 +0000
+++ boost_1_52_0/boost/detail/endian.hpp	2013-02-09 09:45:00.727160619 +0000
@@ -31,7 +31,7 @@
 // GNU libc offers the helpful header <endian.h> which defines
 // __BYTE_ORDER

-#if defined (__GLIBC__)
+#if 1
 # include <endian.h>
 # if (__BYTE_ORDER == __LITTLE_ENDIAN)
 #  define BOOST_LITTLE_ENDIAN


code:
--- boost_1_52_0.org/tools/build/v2/engine/execunix.c	2013-01-04 09:45:43.165000002 +0000
+++ boost_1_52_0/tools/build/v2/engine/execunix.c	2013-01-04 09:46:20.095000004 +0000
@@ -18,7 +18,7 @@
 #include <sys/times.h>
 #include <sys/wait.h>

-#if defined(sun) || defined(__sun) || defined(linux)
+#if defined(sun) || defined(__sun) || defined(__GLIBC__)
     #include <wait.h>
 #endif


code:
PROMPT 1
TIMEOUT 100
DEFAULT sabotage

LABEL sabotage
        KERNEL vmlinuz
        APPEND root=/dev/sda1 rw vga=ask

LABEL rescue
        KERNEL vmlinuz
        APPEND root=/dev/sda1 rw


code:
--- bridge-utils-1.5.org/libbridge/libbridge.h	2013-08-11 08:34:15.976000004 +0000
+++ bridge-utils-1.5/libbridge/libbridge.h	2013-08-11 08:34:39.495000004 +0000
@@ -22,6 +22,7 @@
 #include <sys/socket.h>
 #include <linux/if.h>
 #include <linux/if_bridge.h>
+#include <sys/time.h>

 /* defined in net/if.h but that conflicts with linux/if.h... */
 extern unsigned int if_nametoindex (const char *__ifname);


code:
--- ./finger/finger.h.orig	Sun Feb 25 17:18:59 2001
+++ ./finger/finger.h	Sun Feb 25 17:19:12 2001
@@ -39,6 +39,7 @@

 #include <pwd.h>
 #include <utmp.h>
+#include <time.h>

 /*
  * All unique persons are linked in a list headed by "head" and linkd
--- ./fingerd/fingerd.c.orig	Sun Feb 25 17:21:14 2001
+++ ./fingerd/fingerd.c	Sun Feb 25 17:21:29 2001
@@ -55,6 +55,7 @@
 #include <netinet/in.h>
 #include <sys/utsname.h>
 #include <sys/wait.h>
+#include <sys/socket.h>

 #include "pathnames.h"
 #include "../version.h"


code:
--- btrfs-progs-v3.12-old/bitops.h
+++ btrfs-progs-v3.12/bitops.h
@@ -72,7 +72,7 @@
  *
  * Undefined if no bit exists, so code should check against 0 first.
  */
-static __always_inline unsigned long __ffs(unsigned long word)
+static inline unsigned long __ffs(unsigned long word)
 {
        int num = 0;

--- btrfs-progs-v3.14.2.old/btrfs-convert.c
+++ btrfs-progs-v3.14.2/btrfs-convert.c
@@ -41,6 +41,7 @@
 #include <ext2fs/ext2_fs.h>
 #include <ext2fs/ext2fs.h>
 #include <ext2fs/ext2_ext_attr.h>
+#include <linux/limits.h>

 #define INO_OFFSET (BTRFS_FIRST_FREE_OBJECTID - EXT2_ROOT_INO)
 #define EXT2_IMAGE_SUBVOL_OBJECTID BTRFS_FIRST_FREE_OBJECTID
--- btrfs-progs-v3.14.2.old/mkfs.c
+++ btrfs-progs-v3.14.2/mkfs.c
@@ -21,6 +21,7 @@

 #include "kerncompat.h"

+#include <linux/limits.h>
 #include <sys/ioctl.h>
 #include <sys/mount.h>
 #include "ioctl.h"
--- btrfs-progs-v3.14.2.old/Makefile
+++ btrfs-progs-v3.14.2/Makefile
@@ -29,7 +29,7 @@
 lib_LIBS = -luuid -lblkid -lm -lz -llzo2 -L.
 libdir ?= $(prefix)/lib
 incdir = $(prefix)/include/btrfs
-LIBS = $(lib_LIBS) $(libs_static)
+LIBS = $(libs_static) $(lib_LIBS)

 ifeq ("$(origin V)", "command line")
   BUILD_VERBOSE = $(V)
@@ -57,8 +57,8 @@
 btrfs_fragment_libs = -lgd -lpng -ljpeg -lfreetype

 SUBDIRS =
-BUILDDIRS = $(patsubst %,build-%,$(SUBDIRS)) build-Documentation
-INSTALLDIRS = $(patsubst %,install-%,$(SUBDIRS)) install-Documentation
+BUILDDIRS = $(patsubst %,build-%,$(SUBDIRS)) #build-Documentation
+INSTALLDIRS = $(patsubst %,install-%,$(SUBDIRS)) #install-Documentation
 CLEANDIRS = $(patsubst %,clean-%,$(SUBDIRS))

 .PHONY: $(SUBDIRS)
@@ -80,7 +80,7 @@

 libs_shared = libbtrfs.so.0.1
 libs_static = libbtrfs.a
-libs = $(libs_shared) $(libs_static)
+libs = $(libs_static) $(libs_shared)
 lib_links = libbtrfs.so.0 libbtrfs.so
 headers = $(libbtrfs_headers)

@@ -220,8 +220,9 @@
 	@echo "    [LD]     $@"
 	$(Q)$(CC) $(CFLAGS) -o send-test $(objects) send-test.o $(LDFLAGS) $(LIBS) -lpthread

-manpages:
-	$(Q)$(MAKE) $(MAKEOPTS) -C Documentation
+#Do not build docs
+#manpages:
+#	$(Q)$(MAKE) $(MAKEOPTS) -C Documentation

 clean-all: clean-doc clean

@@ -233,9 +234,9 @@
 	      version.h $(check_defs)
 	      $(libs) $(lib_links)

-clean-doc:
-	@echo "Cleaning Documentation"
-	$(Q)$(MAKE) $(MAKEOPTS) -C Documentation clean
+#clean-doc:
+#	@echo "Cleaning Documentation"
+#	$(Q)$(MAKE) $(MAKEOPTS) -C Documentation clean

 $(CLEANDIRS):
 	@echo "Cleaning $(patsubst clean-%,%,$@)"


code:
diff -Nur busybox-git-orig/util-linux/guess_fstype.c busybox-git/util-linux/guess_fstype.c
--- busybox-git-orig/util-linux/guess_fstype.c	1970-01-01 07:00:00.000000000 +0700
+++ busybox-git/util-linux/guess_fstype.c	2013-07-04 21:02:19.916423619 +0700
@@ -0,0 +1,65 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * guess_fs based on a version by "jamesbond"
+ *
+ * Copyright 2013, ????
+ *
+ * Licensed under GPLv2, see file LICENSE in this source tree
+ */
+
+//applet:IF_GUESS_FSTYPE(APPLET(guess_fstype, BB_DIR_BIN, BB_SUID_MAYBE))
+
+//kbuild:lib-$(CONFIG_GUESS_FSTYPE) += guess_fstype.o
+
+//config:config GUESS_FSTYPE
+//config:	bool "guess_fstype"
+//config:	default n
+//config:	help
+//config:	  Guess filesystem type of device.
+//config:	  (As in Puppy guess_fstype)
+
+//usage:#define guess_fstype_trivial_usage
+//usage:	"[BLOCKDEV]..."
+//usage:#define guess_fstype_full_usage "\n\n"
+//usage:	"[BLOCKDEV]..."
+
+#include "libbb.h"
+#include "volume_id/volume_id_internal.h"
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#define PSTR(x) (x), strlen(x)
+
+int guess_fstype_main (int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int guess_fstype_main (int argc, char **argv)
+{
+	struct volume_id *id=0;
+	int retcode=0; //assume success
+	int fd;
+
+	while (*++argv) {
+		// identify
+		fd = open (argv[0], O_RDONLY);
+		if (fd >= 0) {
+			id = volume_id_open_node (fd);
+			if (id) {
+				// if more than one, show original device
+				if (argc > 2) {
+					write (1, PSTR(argv[0]));
+					write (1, PSTR(": "));
+				}
+
+				if ((!volume_id_probe_all (id, 0)) && id->type) {
+					write (1, PSTR(id->type));
+					write (1, PSTR("\n"));
+				} else {
+					write (1, PSTR("unknown\n"));
+					retcode=1;
+				}
+				free_volume_id (id);
+			}
+		}
+	}
+
+	return retcode;
+}


code:
diff -Naur busybox-1.24.2PREV/include/libbb.h busybox-1.24.2/include/libbb.h
--- busybox-1.24.2PREV/include/libbb.h	2016-03-18 04:35:49.000000000 +0800
+++ busybox-1.24.2/include/libbb.h	2016-05-07 19:03:35.000000000 +0800
@@ -42,6 +42,7 @@
 #include <sys/mman.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
+#include <sys/sysinfo.h>
 #include <sys/time.h>
 #include <sys/types.h>
 #ifndef major
diff -Naur busybox-1.24.2PREV/include/platform.h busybox-1.24.2/include/platform.h
--- busybox-1.24.2PREV/include/platform.h	2016-03-18 04:35:49.000000000 +0800
+++ busybox-1.24.2/include/platform.h	2016-05-07 19:06:01.000000000 +0800
@@ -497,6 +497,13 @@
 # undef HAVE_NET_ETHERNET_H
 #endif

+#if defined(__musl__)
+# undef HAVE_SETBIT
+# include <stddef.h>
+# include <termios.h>
+# include <sys/ioctl.h>
+#endif
+
 /*
  * Now, define prototypes for all the functions defined in platform.c
  * These must come after all the HAVE_* macros are defined (or not)
diff -Naur busybox-1.24.2PREV/miscutils/man.c busybox-1.24.2/miscutils/man.c
--- busybox-1.24.2PREV/miscutils/man.c	2016-02-11 19:50:37.000000000 +0800
+++ busybox-1.24.2/miscutils/man.c	2016-05-07 19:10:06.000000000 +0800
@@ -107,7 +107,7 @@
 	 * Otherwise it may show just empty screen */
 	cmd = xasprintf(
 		/* replaced -Tlatin1 with -Tascii for non-UTF8 displays */
-		man ? "gtbl | nroff -Tascii -mandoc 2>&1 | %s"
+		man ? "nroff -Tutf -man 2>&1 | %s"
 		    : "%s",
 		pager);
 	system(cmd);
diff -Naur busybox-1.24.2PREV/networking/tcpudp.c busybox-1.24.2/networking/tcpudp.c
--- busybox-1.24.2PREV/networking/tcpudp.c	2016-02-11 19:50:37.000000000 +0800
+++ busybox-1.24.2/networking/tcpudp.c	2016-05-07 19:14:46.000000000 +0800
@@ -71,7 +71,7 @@
 /* Wants <limits.h> etc, thus included after libbb.h: */
 #ifdef __linux__
 #include <linux/types.h> /* for __be32 etc */
-#include <linux/netfilter_ipv4.h>
+//#include <linux/netfilter_ipv4.h>
 #endif

 // TODO: move into this file:


code:
diff --git a/editors/awk.c b/editors/awk.c
index fa3fc89..98e7a83 100644
--- a/editors/awk.c
+++ b/editors/awk.c
@@ -2636,7 +2636,8 @@ static var *evaluate(node *op, var *res)
 			var *vbeg, *v;
 			const char *sv_progname;

-			if (!op->r.f->body.first)
+			/* The body might be empty, still has to eval the args */
+			if (!op->r.n->info && !op->r.f->body.first)
 				syntax_error(EMSG_UNDEF_FUNC);

 			vbeg = v = nvalloc(op->r.f->nargs + 1);


code:
diff --git a/editors/awk.c b/editors/awk.c
index 71abca2..fa3fc89 100644
--- a/editors/awk.c
+++ b/editors/awk.c
@@ -190,7 +190,7 @@ typedef struct tsplitter_s {

 /* combined token classes */
 #define	TC_BINOP   (TC_BINOPX | TC_COMMA | TC_PIPE | TC_IN)
-#define	TC_UNARYOP (TC_UOPPRE | TC_UOPPOST)
+//#define	TC_UNARYOP (TC_UOPPRE | TC_UOPPOST)
 #define	TC_OPERAND (TC_VARIABLE | TC_ARRAY | TC_FUNCTION \
                    | TC_BUILTIN | TC_GETLINE | TC_SEQSTART | TC_STRING | TC_NUMBER)

@@ -1990,8 +1990,8 @@ static int fmt_num(char *b, int size, const char *format, double n, int int_as_i
 	char c;
 	const char *s = format;

-	if (int_as_int && n == (int)n) {
-		r = snprintf(b, size, "%d", (int)n);
+	if (int_as_int && n == (long long)n) {
+		r = snprintf(b, size, "%lld", (long long)n);
 	} else {
 		do { c = *s; } while (c && *++s);
 		if (strchr("diouxX", c)) {
@@ -2707,7 +2707,7 @@ static var *evaluate(node *op, var *res)

 			switch (opn) {
 			case F_in:
-				R_d = (int)L_d;
+				R_d = (long long)L_d;
 				break;

 			case F_rn:
@@ -2905,7 +2905,7 @@ static var *evaluate(node *op, var *res)
 			case '%':
 				if (R_d == 0)
 					syntax_error(EMSG_DIV_BY_ZERO);
-				L_d -= (int)(L_d / R_d) * R_d;
+				L_d -= (long long)(L_d / R_d) * R_d;
 				break;
 			}
 			debug_printf_eval("BINARY/REPLACE result:%f\n", L_d);
--
1.7.3.4


code:
From 2227a5969bbf83d05cc6b738670e38d0b56cd437 Mon Sep 17 00:00:00 2001
From: rofl0r <retnyg@gmx.net>
Date: Mon, 27 Aug 2012 21:34:55 +0200
Subject: [PATCH] add blowfish support to bb

---
 libbb/pw_encrypt.c |   23 ++++++++++++++++++++---
 1 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/libbb/pw_encrypt.c b/libbb/pw_encrypt.c
index 39ffa08..d2fb2b9 100644
--- a/libbb/pw_encrypt.c
+++ b/libbb/pw_encrypt.c
@@ -53,9 +53,20 @@ char* FAST_FUNC crypt_make_pw_salt(char salt[MAX_PW_SALT_LEN], const char *algo)
 	int len = 2/2;
 	char *salt_ptr = salt;
 	if (algo[0] != 'd') { /* not des */
-		len = 8/2; /* so far assuming md5 */
 		*salt_ptr++ = '$';
-		*salt_ptr++ = '1';
+		if(algo[0] == 'b') {
+			// blowfish
+			*salt_ptr++ = '2';
+			*salt_ptr++ = 'a';
+			*salt_ptr++ = '$';
+			// 8 rounds
+			*salt_ptr++ = '0';
+			*salt_ptr++ = '8';
+			len = 22/2;
+		} else {
+			*salt_ptr++ = '1';
+			if (algo[0] == 'm') len = 8/2; /* so far assuming md5 */
+		}
 		*salt_ptr++ = '$';
 #if !ENABLE_USE_BB_CRYPT || ENABLE_USE_BB_CRYPT_SHA
 		if (algo[0] == 's') { /* sha */
@@ -95,6 +106,11 @@ to64(char *s, unsigned v, int n)
 /* Other advanced crypt ids (TODO?): */
 /* $2$ or $2a$: Blowfish */

+static char *bf_crypt(const char *key, const char *salt) {
+	// use musl-builtin crypt
+	return crypt(key, salt);
+}
+
 static struct const_des_ctx *des_cctx;
 static struct des_ctx *des_ctx;

@@ -109,7 +125,8 @@ static char *my_crypt(const char *key, const char *salt)
 		if (salt[1] == '5' || salt[1] == '6')
 			return sha_crypt((char*)key, (char*)salt);
 #endif
-	}
+	} else if (salt[0] == '$' && salt[1] == '2' && salt[2] == 'a' && salt[3] == '$')
+		return bf_crypt(key, salt);

 	if (!des_cctx)
 		des_cctx = const_des_init();
--
1.7.3.4


code:
--- busybox-1.20.2/archival/libarchive/decompress_bunzip2.c
+++ busybox-1.20.2.patched/archival/libarchive/decompress_bunzip2.c
@@ -440,7 +440,7 @@
 		   literal used is the one at the head of the mtfSymbol array.) */
 		if (runPos != 0) {
 			uint8_t tmp_byte;
-			if (dbufCount + runCnt >= dbufSize) return RETVAL_DATA_ERROR;
+			if (dbufCount + runCnt > dbufSize) return RETVAL_DATA_ERROR;
 			tmp_byte = symToByte[mtfSymbol[0]];
 			byteCount[tmp_byte] += runCnt;
 			while (--runCnt >= 0) dbuf[dbufCount++] = (uint32_t)tmp_byte;


code:
From 4609f477c7e043a4f6147dfe6e86b775da2ef784 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Mon, 21 Jan 2013 01:22:12 +0100
Subject: [PATCH] mdev: fix mode of dir1 in =dir1/dir2/file rule

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>

diff --git a/util-linux/mdev.c b/util-linux/mdev.c
index 79871d3..75de14f 100644
--- a/util-linux/mdev.c
+++ b/util-linux/mdev.c
@@ -429,6 +429,18 @@ static const struct rule *next_rule(void)

 #endif

+static void mkdir_recursive(char *name)
+{
+	/* if name has many levels ("dir1/dir2"),
+	 * bb_make_directory() will create dir1 according to umask,
+	 * not according to its "mode" parameter.
+	 * Since we run with umask=0, need to temporarily switch it.
+	 */
+	umask(022); /* "dir1" (if any) will be 0755 too */
+	bb_make_directory(name, 0755, FILEUTILS_RECUR);
+	umask(0);
+}
+
 /* Builds an alias path.
  * This function potentionally reallocates the alias parameter.
  * Only used for ENABLE_FEATURE_MDEV_RENAME
@@ -442,7 +454,7 @@ static char *build_alias(char *alias, const char *device_name)
 	dest = strrchr(alias, '/');
 	if (dest) { /* ">bar/[baz]" ? */
 		*dest = '\0'; /* mkdir bar */
-		bb_make_directory(alias, 0755, FILEUTILS_RECUR);
+		mkdir_recursive(alias);
 		*dest = '/';
 		if (dest[1] == '\0') { /* ">bar/" => ">bar/device_name" */
 			dest = alias;
--
2.7.3


code:
From a9dc7c2f59dc5e92870d2d46316ea5c1f14740e3 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Mon, 30 Jun 2014 10:14:34 +0200
Subject: [PATCH] lzop: add overflow check

See CVE-2014-4607
http://www.openwall.com/lists/oss-security/2014/06/26/20

function                                             old     new   delta
lzo1x_decompress_safe                               1010    1031     +21

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 archival/libarchive/liblzo.h  | 2 ++
 archival/libarchive/lzo1x_d.c | 3 +++
 2 files changed, 5 insertions(+)

diff --git a/archival/libarchive/liblzo.h b/archival/libarchive/liblzo.h
index 843997c..4596620 100644
--- a/archival/libarchive/liblzo.h
+++ b/archival/libarchive/liblzo.h
@@ -76,11 +76,13 @@
 #    define TEST_IP             (ip < ip_end)
 #    define NEED_IP(x) \
             if ((unsigned)(ip_end - ip) < (unsigned)(x))  goto input_overrun
+#    define TEST_IV(x)          if ((x) > (unsigned)0 - (511)) goto input_overrun

 #    undef TEST_OP              /* don't need both of the tests here */
 #    define TEST_OP             1
 #    define NEED_OP(x) \
             if ((unsigned)(op_end - op) < (unsigned)(x))  goto output_overrun
+#    define TEST_OV(x)          if ((x) > (unsigned)0 - (511)) goto output_overrun

 #define HAVE_ANY_OP 1

diff --git a/archival/libarchive/lzo1x_d.c b/archival/libarchive/lzo1x_d.c
index 9bc1270..40b167e 100644
--- a/archival/libarchive/lzo1x_d.c
+++ b/archival/libarchive/lzo1x_d.c
@@ -92,6 +92,7 @@ int lzo1x_decompress_safe(const uint8_t* in, unsigned in_len,
 				ip++;
 				NEED_IP(1);
 			}
+			TEST_IV(t);
 			t += 15 + *ip++;
 		}
 		/* copy literals */
@@ -224,6 +225,7 @@ int lzo1x_decompress_safe(const uint8_t* in, unsigned in_len,
 						ip++;
 						NEED_IP(1);
 					}
+					TEST_IV(t);
 					t += 31 + *ip++;
 				}
 #if defined(COPY_DICT)
@@ -265,6 +267,7 @@ int lzo1x_decompress_safe(const uint8_t* in, unsigned in_len,
 						ip++;
 						NEED_IP(1);
 					}
+					TEST_IV(t);
 					t += 7 + *ip++;
 				}
 #if defined(COPY_DICT)
--
2.7.3


code:
From d474ffc68290e0a83651c4432eeabfa62cd51e87 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Thu, 10 Mar 2016 11:47:58 +0100
Subject: [PATCH] udhcp: fix a SEGV on malformed RFC1035-encoded domain name

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
--- busybox-1.20.2.org/networking/udhcp/domain_codec.c
+++ busybox-1.20.2/networking/udhcp/domain_codec.c
@@ -7,6 +7,7 @@
  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  */
 #ifdef DNS_COMPR_TESTING
+# define _GNU_SOURCE
 # define FAST_FUNC /* nothing */
 # define xmalloc malloc
 # include <stdlib.h>
@@ -63,11 +64,10 @@
 				if (crtpos + *c + 1 > clen) /* label too long? abort */
 					return NULL;
 				if (dst)
-					memcpy(dst + len, c + 1, *c);
+					/* \3com ---> "com." */
+					((char*)mempcpy(dst + len, c + 1, *c))[0] = '.';
 				len += *c + 1;
 				crtpos += *c + 1;
-				if (dst)
-					dst[len - 1] = '.';
 			} else {
 				/* NUL: end of current domain name */
 				if (retpos == 0) {
@@ -78,7 +78,10 @@
 					crtpos = retpos;
 					retpos = depth = 0;
 				}
-				if (dst)
+				if (dst && len != 0)
+					/* \4host\3com\0\4host and we are at \0:
+					 * \3com was converted to "com.", change dot to space.
+					 */
 					dst[len - 1] = ' ';
 			}

@@ -227,6 +230,9 @@
 {
 	int len;
 	uint8_t *encoded;
+
+        uint8_t str[6] = { 0x00, 0x00, 0x02, 0x65, 0x65, 0x00 };
+        printf("NUL:'%s'\n",   dname_dec(str, 6, ""));

 #define DNAME_DEC(encoded,pre) dname_dec((uint8_t*)(encoded), sizeof(encoded), (pre))
 	printf("'%s'\n",       DNAME_DEC("\4host\3com\0", "test1:"));


code:
From deebdf59b5cd8cba5a44a6a4fa9a90a87969a181 Mon Sep 17 00:00:00 2001
From: Jody Bruchon <jody@jodybruchon.com>
Date: Tue, 20 Aug 2013 15:42:06 +0000
Subject: fdisk: fix GPT size math errors

Signed-off-by: Jody Bruchon <jody@jodybruchon.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
diff --git a/util-linux/fdisk_gpt.c b/util-linux/fdisk_gpt.c
index d43d9c7..f45f68a 100644
--- a/util-linux/fdisk_gpt.c
+++ b/util-linux/fdisk_gpt.c
@@ -95,7 +95,7 @@ gpt_list_table(int xtra UNUSED_PARAM)

 	numstr6[5] = '\0';

-	smart_ulltoa5(total_number_of_sectors, numstr6, " KMGTPEZY");
+	smart_ulltoa5(total_number_of_sectors * sector_size, numstr6, " KMGTPEZY");
 	printf("Disk %s: %llu sectors, %s\n", disk_device,
 		(unsigned long long)total_number_of_sectors,
 		numstr6);
@@ -112,7 +112,7 @@ gpt_list_table(int xtra UNUSED_PARAM)
 	for (i = 0; i < n_parts; i++) {
 		gpt_partition *p = gpt_part(i);
 		if (p->lba_start) {
-			smart_ulltoa5(1 + SWAP_LE64(p->lba_end) - SWAP_LE64(p->lba_start),
+			smart_ulltoa5((1 + SWAP_LE64(p->lba_end) - SWAP_LE64(p->lba_start)) * sector_size,
 				numstr6, " KMGTPEZY");
 			printf("%4u %15llu %15llu %11s   %04x  ",
 				i + 1,
--
cgit v0.9.1


code:
--- busybox-1.20.2.org/util-linux/fdisk.c
+++ busybox-1.20.2/util-linux/fdisk.c
@@ -85,17 +85,8 @@

 typedef unsigned long long ullong;
-/* Used for sector numbers. Partition formats we know
- * do not support more than 2^32 sectors
- */
-typedef uint32_t sector_t;
-#if UINT_MAX == 4294967295
-# define SECT_FMT ""
-#elif ULONG_MAX == 4294967295
-# define SECT_FMT "l"
-#else
-# error Cant detect sizeof(uint32_t)
-#endif
+typedef uint64_t sector_t;
+#define SECT_FMT "ll"

 struct hd_geometry {
 	unsigned char heads;


code:
--- busybox-1.20.2/findutils/grep.c	2012-06-26 15:35:45.000000000 +0200
+++ busybox-git/findutils/grep.c	2014-11-17 17:25:46.814511033 +0100
@@ -344,11 +344,42 @@
 		while (pattern_ptr) {
 			gl = (grep_list_data_t *)pattern_ptr->data;
 			if (FGREP_FLAG) {
-				found |= (((option_mask32 & OPT_i)
-					? strcasestr(line, gl->pattern)
-					: strstr(line, gl->pattern)
-					) != NULL);
+				char *match;
+				char *str = line;
+ opt_f_again:
+				match = ((option_mask32 & OPT_i)
+					? strcasestr(str, gl->pattern)
+					: strstr(str, gl->pattern)
+					);
+				if (match) {
+					if (option_mask32 & OPT_x) {
+						if (match != str)
+							goto opt_f_not_found;
+						if (str[strlen(gl->pattern)] != '\0')
+							goto opt_f_not_found;
+					} else
+					if (option_mask32 & OPT_w) {
+						char c = (match != str) ? match[-1] : ' ';
+						if (!isalnum(c) && c != '_') {
+							c = match[strlen(gl->pattern)];
+							if (!c || (!isalnum(c) && c != '_'))
+								goto opt_f_found;
+						}
+						str = match + 1;
+						goto opt_f_again;
+					}
+ opt_f_found:
+					found = 1;
+ opt_f_not_found: ;
+				}
 			} else {
+#if ENABLE_EXTRA_COMPAT
+				unsigned start_pos;
+#else
+				int match_flg;
+#endif
+				char *match_at;
+
 				if (!(gl->flg_mem_alocated_compiled & COMPILED)) {
 					gl->flg_mem_alocated_compiled |= COMPILED;
 #if !ENABLE_EXTRA_COMPAT
@@ -363,29 +394,58 @@
 #if !ENABLE_EXTRA_COMPAT
 				gl->matched_range.rm_so = 0;
 				gl->matched_range.rm_eo = 0;
+				match_flg = 0;
+#else
+				start_pos = 0;
 #endif
+				match_at = line;
+ opt_w_again:
+//bb_error_msg("'%s' start_pos:%d line_len:%d", match_at, start_pos, line_len);
 				if (
 #if !ENABLE_EXTRA_COMPAT
-					regexec(&gl->compiled_regex, line, 1, &gl->matched_range, 0) == 0
+					regexec(&gl->compiled_regex, match_at, 1, &gl->matched_range, match_flg) == 0
 #else
-					re_search(&gl->compiled_regex, line, line_len,
-							/*start:*/ 0, /*range:*/ line_len,
+					re_search(&gl->compiled_regex, match_at, line_len,
+							start_pos, /*range:*/ line_len,
 							&gl->matched_range) >= 0
 #endif
 				) {
 					if (option_mask32 & OPT_x) {
 						found = (gl->matched_range.rm_so == 0
-						         && line[gl->matched_range.rm_eo] == '\0');
-					} else if (!(option_mask32 & OPT_w)) {
+						         && match_at[gl->matched_range.rm_eo] == '\0');
+					} else
+					if (!(option_mask32 & OPT_w)) {
 						found = 1;
 					} else {
 						char c = ' ';
-						if (gl->matched_range.rm_so)
-							c = line[gl->matched_range.rm_so - 1];
+						if (match_at > line || gl->matched_range.rm_so != 0) {
+							c = match_at[gl->matched_range.rm_so - 1];
+						}
 						if (!isalnum(c) && c != '_') {
-							c = line[gl->matched_range.rm_eo];
-							if (!c || (!isalnum(c) && c != '_'))
-								found = 1;
+							c = match_at[gl->matched_range.rm_eo];
+						}
+						if (!isalnum(c) && c != '_') {
+							found = 1;
+						} else {
+			/*
+			 * Why check gl->matched_range.rm_eo?
+			 * Zero-length match makes -w skip the line:
+			 * "echo foo | grep ^" prints "foo",
+			 * "echo foo | grep -w ^" prints nothing.
+			 * Without such check, we can loop forever.
+			 */
+#if !ENABLE_EXTRA_COMPAT
+							if (gl->matched_range.rm_eo != 0) {
+								match_at += gl->matched_range.rm_eo;
+								match_flg |= REG_NOTBOL;
+								goto opt_w_again;
+							}
+#else
+							if (gl->matched_range.rm_eo > start_pos) {
+								start_pos = gl->matched_range.rm_eo;
+								goto opt_w_again;
+							}
+#endif
 						}
 					}
 				}
@@ -608,7 +668,7 @@
 	int matched = 0;
 	recursive_action(dir,
 		/* recurse=yes */ ACTION_RECURSE |
-		/* followLinks=no */
+		/* followLinks=command line only */ ACTION_FOLLOWLINKS_L0 |
 		/* depthFirst=yes */ ACTION_DEPTHFIRST,
 		/* fileAction= */ file_action_grep,
 		/* dirAction= */ NULL,
@@ -638,7 +698,7 @@

 	if (opts & OPT_C) {
 		/* -C unsets prev -A and -B, but following -A or -B
-		   may override it */
+		 * may override it */
 		if (!(opts & OPT_A)) /* not overridden */
 			lines_after = Copt;
 		if (!(opts & OPT_B)) /* not overridden */
@@ -683,7 +743,7 @@
 		option_mask32 |= OPT_F;

 #if !ENABLE_EXTRA_COMPAT
-	if (!(option_mask32 & (OPT_o | OPT_w)))
+	if (!(option_mask32 & (OPT_o | OPT_w | OPT_x)))
 		reflags = REG_NOSUB;
 #endif


code:
--- a/libbb/printable_string.c
+++ b/libbb/printable_string.c
@@ -31,8 +31,6 @@ const char* FAST_FUNC printable_string(u
 		}
 		if (c < ' ')
 			break;
-		if (c >= 0x7f)
-			break;
 		s++;
 	}

@@ -45,7 +43,7 @@ const char* FAST_FUNC printable_string(u
 			unsigned char c = *d;
 			if (c == '\0')
 				break;
-			if (c < ' ' || c >= 0x7f)
+			if (c < ' ')
 				*d = '?';
 			d++;
 		}


code:
--- busybox-1.20.2.org/miscutils/man.c	2013-06-02 10:12:54.251000003 +0000
+++ busybox-1.20.2/miscutils/man.c	2013-06-02 11:04:56.191000003 +0000
@@ -150,7 +150,7 @@
 int man_main(int argc UNUSED_PARAM, char **argv)
 {
 	parser_t *parser;
-	const char *pager;
+	const char *pager = 0;
 	char **man_path_list;
 	char *sec_list;
 	char *cur_path, *cur_sect;
@@ -162,7 +162,7 @@
 	opt = getopt32(argv, "+aw");
 	argv += optind;

-	sec_list = xstrdup("1:2:3:4:5:6:7:8:9");
+	sec_list = xstrdup("0p:1:1p:2:3:3p:4:5:6:7:8:9");
 	/* Last valid man_path_list[] is [0x10] */
 	count_mp = 0;
 	man_path_list = xzalloc(0x11 * sizeof(man_path_list[0]));
@@ -171,12 +171,6 @@
 		man_path_list[0] = (char*)"/usr/man";
 	else
 		count_mp++;
-	pager = getenv("MANPAGER");
-	if (!pager) {
-		pager = getenv("PAGER");
-		if (!pager)
-			pager = "more";
-	}

 	/* Parse man.conf[ig] or man_db.conf */
 	/* man version 1.6f uses man.config */
@@ -190,7 +184,13 @@
 	while (config_read(parser, token, 2, 0, "# \t", PARSE_NORMAL)) {
 		if (!token[1])
 			continue;
-		if (strcmp("MANDATORY_MANPATH"+10, token[0]) == 0 /* "MANPATH"? */
+		if (strcmp("DEFINE", token[0]) == 0) {
+			size_t n = 5;
+			if (strncmp("pager", token[1], n) == 0) {
+				while(isspace(token[1][++n]));
+				pager = xstrdup(token[1]+n);
+			}
+		} else if (strcmp("MANDATORY_MANPATH"+10, token[0]) == 0 /* "MANPATH"? */
 		 || strcmp("MANDATORY_MANPATH", token[0]) == 0
 		) {
 			char *path = token[1];
@@ -229,6 +229,14 @@
 		}
 	}
 	config_close(parser);
+
+	{
+		/* environment overrides setting from man.config */
+		const char* env_pager = getenv("MANPAGER");
+		if (!env_pager) env_pager = getenv("PAGER");
+		if (env_pager) pager = env_pager;
+		if (!pager) pager = "less";
+	}

 	not_found = 0;
 	do { /* for each argv[] */


code:
--- busybox-1.24.2.orig/networking/libiproute/libnetlink.c
+++ busybox-1.24.2/networking/libiproute/libnetlink.c
@@ -72,10 +72,10 @@
 	struct sockaddr_nl nladdr;
 	struct iovec iov[2] = { { &nlh, sizeof(nlh) }, { req, len } };
 	struct msghdr msg = {
-		(void*)&nladdr, sizeof(nladdr),
-		iov,  2,
-		NULL, 0,
-		0
+		.msg_name = (void*)&nladdr, .msg_namelen = sizeof(nladdr),
+		.msg_iov = iov,  .msg_iovlen = 2,
+		.msg_control = NULL, .msg_controllen = 0,
+		.msg_flags = 0
 	};

 	memset(&nladdr, 0, sizeof(nladdr));
@@ -106,10 +106,10 @@
 		struct nlmsghdr *h;

 		struct msghdr msg = {
-			(void*)&nladdr, sizeof(nladdr),
-			&iov, 1,
-			NULL, 0,
-			0
+			.msg_name = (void*)&nladdr, .msg_namelen = sizeof(nladdr),
+			.msg_iov = &iov,  .msg_iovlen = 1,
+			.msg_control = NULL, .msg_controllen = 0,
+			.msg_flags = 0
 		};

 		status = recvmsg(rth->fd, &msg, 0);
@@ -212,10 +212,10 @@
 	struct iovec iov = { (void*)n, n->nlmsg_len };
 	char   *buf = xmalloc(8*1024); /* avoid big stack buffer */
 	struct msghdr msg = {
-		(void*)&nladdr, sizeof(nladdr),
-		&iov, 1,
-		NULL, 0,
-		0
+		.msg_name = (void*)&nladdr, .msg_namelen = sizeof(nladdr),
+		.msg_iov = &iov,  .msg_iovlen = 1,
+		.msg_control = NULL, .msg_controllen = 0,
+		.msg_flags = 0
 	};

 	memset(&nladdr, 0, sizeof(nladdr));


code:
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -1109,9 +1109,6 @@ void bb_displayroutes(int noresolve, int netstatfmt) FAST_FUNC;

 /* Networking */
-int create_icmp_socket(void) FAST_FUNC;
-int create_icmp6_socket(void) FAST_FUNC;
-/* interface.c */
 /* This structure defines protocol families and their handlers. */
 struct aftype {
 	const char *name;
diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src
index 61eec26..c5d86c0 100644
--- a/libbb/Kbuild.src
+++ b/libbb/Kbuild.src
@@ -27,8 +27,6 @@ lib-y += concat_subpath_file.o
 lib-y += copy_file.o
 lib-y += copyfd.o
 lib-y += crc32.o
-lib-y += create_icmp6_socket.o
-lib-y += create_icmp_socket.o
 lib-y += default_error_retval.o
 lib-y += device_open.o
 lib-y += dump.o
--- busybox-1.20.2.org/networking/ping.c	2014-01-04 15:31:47.838796917 +0000
+++ busybox-1.20.2/networking/ping.c	2014-01-04 15:49:08.437708254 +0000
@@ -89,7 +89,9 @@
 //usage:       "[OPTIONS] HOST"
 //usage:# define ping_full_usage "\n\n"
 //usage:       "Send ICMP ECHO_REQUEST packets to network hosts\n"
+//usage:	IF_PING6(
 //usage:     "\n	-4,-6		Force IP or IPv6 name resolution"
+//usage:	)
 //usage:     "\n	-c CNT		Send only CNT pings"
 //usage:     "\n	-s SIZE		Send SIZE data bytes in packets (default:56)"
 //usage:     "\n	-t TTL		Set TTL"
@@ -147,8 +149,46 @@
 	MAX_DUP_CHK = (8 * 128),
 	MAXWAIT = 10,
 	PINGINTERVAL = 1, /* 1 second */
+	pingsock = 0,
 };

+static void
+#if ENABLE_PING6
+create_icmp_socket(len_and_sockaddr *lsa)
+#else
+create_icmp_socket(void)
+#define create_icmp_socket(lsa) create_icmp_socket()
+#endif
+{
+	int sock;
+#if ENABLE_PING6
+	if (lsa->u.sa.sa_family == AF_INET6)
+		sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
+	else
+#endif
+		sock = socket(AF_INET, SOCK_RAW, 1); /* 1 == ICMP */
+	if (sock < 0) {
+		if (errno != EPERM)
+			bb_perror_msg_and_die(bb_msg_can_not_create_raw_socket);
+#if defined(__linux__) || defined(__APPLE__)
+		/* We don't have root privileges.  Try SOCK_DGRAM instead.
+		 * Linux needs net.ipv4.ping_group_range for this to work.
+		 * MacOSX allows ICMP_ECHO, ICMP_TSTAMP or ICMP_MASKREQ
+		 */
+#if ENABLE_PING6
+		if (lsa->u.sa.sa_family == AF_INET6)
+			sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_ICMPV6);
+		else
+#endif
+			sock = socket(AF_INET, SOCK_DGRAM, 1); /* 1 == ICMP */
+		if (sock < 0)
+#endif
+		bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
+	}
+
+	xmove_fd(sock, pingsock);
+}
+
 #if !ENABLE_FEATURE_FANCY_PING

 /* Simple version */
@@ -169,12 +209,10 @@
 static void ping4(len_and_sockaddr *lsa)
 {
 	struct icmp *pkt;
-	int pingsock, c;
-
-	pingsock = create_icmp_socket();
+	int c;

 	pkt = (struct icmp *) G.packet;
-	memset(pkt, 0, sizeof(G.packet));
+	/*memset(pkt, 0, sizeof(G.packet)); already is */
 	pkt->icmp_type = ICMP_ECHO;
 	pkt->icmp_cksum = inet_cksum((uint16_t *) pkt, sizeof(G.packet));

@@ -182,11 +220,15 @@

 	/* listen for replies */
 	while (1) {
+#if 0
 		struct sockaddr_in from;
 		socklen_t fromlen = sizeof(from);

 		c = recvfrom(pingsock, G.packet, sizeof(G.packet), 0,
 				(struct sockaddr *) &from, &fromlen);
+#else
+		c = recv(pingsock, G.packet, sizeof(G.packet), 0);
+#endif
 		if (c < 0) {
 			if (errno != EINTR)
 				bb_perror_msg("recvfrom");
@@ -208,13 +250,11 @@
 static void ping6(len_and_sockaddr *lsa)
 {
 	struct icmp6_hdr *pkt;
-	int pingsock, c;
+	int c;
 	int sockopt;

-	pingsock = create_icmp6_socket();
-
 	pkt = (struct icmp6_hdr *) G.packet;
-	memset(pkt, 0, sizeof(G.packet));
+	/*memset(pkt, 0, sizeof(G.packet)); already is */
 	pkt->icmp6_type = ICMP6_ECHO_REQUEST;

 	sockopt = offsetof(struct icmp6_hdr, icmp6_cksum);
@@ -224,18 +264,21 @@

 	/* listen for replies */
 	while (1) {
+#if 0
 		struct sockaddr_in6 from;
 		socklen_t fromlen = sizeof(from);

 		c = recvfrom(pingsock, G.packet, sizeof(G.packet), 0,
 				(struct sockaddr *) &from, &fromlen);
+#else
+		c = recv(pingsock, G.packet, sizeof(G.packet), 0);
+#endif
 		if (c < 0) {
 			if (errno != EINTR)
 				bb_perror_msg("recvfrom");
 			continue;
 		}
-		if (c >= ICMP_MINLEN) {			/* icmp6_hdr */
-			pkt = (struct icmp6_hdr *) G.packet;
+		if (c >= ICMP_MINLEN) {	/* icmp6_hdr */
 			if (pkt->icmp6_type == ICMP6_ECHO_REPLY)
 				break;
 		}
@@ -283,6 +326,7 @@
 	signal(SIGALRM, noresp);
 	alarm(5); /* give the host 5000ms to respond */

+	create_icmp_socket(lsa);
 #if ENABLE_PING6
 	if (lsa->u.sa.sa_family == AF_INET6)
 		ping6(lsa);
@@ -299,7 +343,7 @@

 /* Full(er) version */

-#define OPT_STRING ("qvc:s:t:w:W:I:4" IF_PING6("6"))
+#define OPT_STRING ("qvc:s:t:w:W:I:n4" IF_PING6("6"))
 enum {
 	OPT_QUIET = 1 << 0,
 	OPT_VERBOSE = 1 << 1,
@@ -309,13 +353,13 @@
 	OPT_w = 1 << 5,
 	OPT_W = 1 << 6,
 	OPT_I = 1 << 7,
-	OPT_IPV4 = 1 << 8,
-	OPT_IPV6 = (1 << 9) * ENABLE_PING6,
+	/*OPT_n = 1 << 8, - ignored */
+	OPT_IPV4 = 1 << 9,
+	OPT_IPV6 = (1 << 10) * ENABLE_PING6,
 };

 struct globals {
-	int pingsock;
 	int if_index;
 	char *str_I;
 	len_and_sockaddr *source_lsa;
@@ -341,17 +385,13 @@
 		struct sockaddr_in6 sin6;
 #endif
 	} pingaddr;
-	char rcvd_tbl[MAX_DUP_CHK / 8];
+	unsigned char rcvd_tbl[MAX_DUP_CHK / 8];
 } FIX_ALIASING;
 #define G (*(struct globals*)&bb_common_bufsiz1)
-#define pingsock     (G.pingsock    )
 #define if_index     (G.if_index    )
 #define source_lsa   (G.source_lsa  )
 #define str_I        (G.str_I       )
 #define datalen      (G.datalen     )
-#define ntransmitted (G.ntransmitted)
-#define nreceived    (G.nreceived   )
-#define nrepeats     (G.nrepeats    )
 #define pingcount    (G.pingcount   )
 #define opt_ttl      (G.opt_ttl     )
 #define myid         (G.myid        )
@@ -369,51 +409,55 @@
 #define INIT_G() do { \
 	if (sizeof(G) > COMMON_BUFSIZE) \
 		BUG_ping_globals_too_big(); \
-	pingsock = -1; \
 	datalen = DEFDATALEN; \
 	timeout = MAXWAIT; \
 	tmin = UINT_MAX; \
 } while (0)

-#define A(bit)		rcvd_tbl[(bit)>>3]	/* identify byte in array */
-#define B(bit)		(1 << ((bit) & 0x07))	/* identify bit in byte */
-#define SET(bit)	(A(bit) |= B(bit))
-#define CLR(bit)	(A(bit) &= (~B(bit)))
-#define TST(bit)	(A(bit) & B(bit))
-
-/**************************************************************************/
+#define BYTE(bit)	rcvd_tbl[(bit)>>3]
+#define MASK(bit)	(1 << ((bit) & 7))
+#define SET(bit)	(BYTE(bit) |= MASK(bit))
+#define CLR(bit)	(BYTE(bit) &= (~MASK(bit)))
+#define TST(bit)	(BYTE(bit) & MASK(bit))

 static void print_stats_and_exit(int junk) NORETURN;
 static void print_stats_and_exit(int junk UNUSED_PARAM)
 {
+	unsigned long ul;
+	unsigned long nrecv;
+
 	signal(SIGINT, SIG_IGN);

-	printf("\n--- %s ping statistics ---\n", hostname);
-	printf("%lu packets transmitted, ", ntransmitted);
-	printf("%lu packets received, ", nreceived);
-	if (nrepeats)
-		printf("%lu duplicates, ", nrepeats);
-	if (ntransmitted)
-		ntransmitted = (ntransmitted - nreceived) * 100 / ntransmitted;
-	printf("%lu%% packet loss\n", ntransmitted);
+	nrecv = G.nreceived;
+	printf("\n--- %s ping statistics ---\n"
+		"%lu packets transmitted, "
+		"%lu packets received, ",
+		hostname, G.ntransmitted, nrecv
+	);
+	if (G.nrepeats)
+		printf("%lu duplicates, ", G.nrepeats);
+	ul = G.ntransmitted;
+	if (ul != 0)
+		ul = (ul - nrecv) * 100 / ul;
+	printf("%lu%% packet loss\n", ul);
 	if (tmin != UINT_MAX) {
-		unsigned tavg = tsum / (nreceived + nrepeats);
+		unsigned tavg = tsum / (nrecv + G.nrepeats);
 		printf("round-trip min/avg/max = %u.%03u/%u.%03u/%u.%03u ms\n",
 			tmin / 1000, tmin % 1000,
 			tavg / 1000, tavg % 1000,
 			tmax / 1000, tmax % 1000);
 	}
 	/* if condition is true, exit with 1 -- 'failure' */
-	exit(nreceived == 0 || (deadline && nreceived < pingcount));
+	exit(nrecv == 0 || (deadline && nrecv < pingcount));
 }

 static void sendping_tail(void (*sp)(int), int size_pkt)
 {
 	int sz;

-	CLR((uint16_t)ntransmitted % MAX_DUP_CHK);
-	ntransmitted++;
+	CLR((uint16_t)G.ntransmitted % MAX_DUP_CHK);
+	G.ntransmitted++;

 	size_pkt += datalen;

@@ -423,7 +467,7 @@
 	if (sz != size_pkt)
 		bb_error_msg_and_die(bb_msg_write_error);

-	if (pingcount == 0 || deadline || ntransmitted < pingcount) {
+	if (pingcount == 0 || deadline || G.ntransmitted < pingcount) {
 		/* Didn't send all pings yet - schedule next in 1s */
 		signal(SIGALRM, sp);
 		if (deadline) {
@@ -439,7 +483,7 @@
 		 * otherwise ping waits for two RTTs. */
 		unsigned expire = timeout;

-		if (nreceived) {
+		if (G.nreceived) {
 			/* approx. 2*tmax, in seconds (2 RTT) */
 			expire = tmax / (512*1024);
 			if (expire == 0)
@@ -458,7 +502,7 @@
 	pkt->icmp_type = ICMP_ECHO;
 	/*pkt->icmp_code = 0;*/
 	pkt->icmp_cksum = 0; /* cksum is calculated with this field set to 0 */
-	pkt->icmp_seq = htons(ntransmitted); /* don't ++ here, it can be a macro */
+	pkt->icmp_seq = htons(G.ntransmitted); /* don't ++ here, it can be a macro */
 	pkt->icmp_id = myid;

 	/* If datalen < 4, we store timestamp _past_ the packet,
@@ -481,7 +525,7 @@
 	pkt->icmp6_type = ICMP6_ECHO_REQUEST;
 	/*pkt->icmp6_code = 0;*/
 	/*pkt->icmp6_cksum = 0;*/
-	pkt->icmp6_seq = htons(ntransmitted); /* don't ++ here, it can be a macro */
+	pkt->icmp6_seq = htons(G.ntransmitted); /* don't ++ here, it can be a macro */
 	pkt->icmp6_id = myid;

 	/*if (datalen >= 4)*/
@@ -545,11 +589,10 @@
 		const char *from_str,
 		uint16_t recv_seq, int ttl)
 {
+	unsigned char *b, m;
 	const char *dupmsg = " (DUP!)";
 	unsigned triptime = triptime; /* for gcc */

-	++nreceived;
-
 	if (tp) {
 		/* (int32_t) cast is for hypothetical 64-bit unsigned */
 		/* (doesn't hurt 32-bit real-world anyway) */
@@ -561,11 +604,15 @@
 			tmax = triptime;
 	}

-	if (TST(recv_seq % MAX_DUP_CHK)) {
-		++nrepeats;
-		--nreceived;
+	b = &BYTE(recv_seq % MAX_DUP_CHK);
+	m = MASK(recv_seq % MAX_DUP_CHK);
+	/*if TST(recv_seq % MAX_DUP_CHK):*/
+	if (*b & m) {
+		++G.nrepeats;
 	} else {
-		SET(recv_seq % MAX_DUP_CHK);
+		/*SET(recv_seq % MAX_DUP_CHK):*/
+		*b |= m;
+		++G.nreceived;
 		dupmsg += 7;
 	}

@@ -648,7 +695,6 @@
 {
 	int sockopt;

-	pingsock = create_icmp_socket();
 	pingaddr.sin = lsa->u.sin;
 	if (source_lsa) {
 		if (setsockopt(pingsock, IPPROTO_IP, IP_MULTICAST_IF,
@@ -656,8 +702,6 @@
 			bb_error_msg_and_die("can't set multicast source interface");
 		xbind(pingsock, &source_lsa->u.sa, source_lsa->len);
 	}
-	if (str_I)
-		setsockopt_bindtodevice(pingsock, str_I);

 	/* enable broadcast pings */
 	setsockopt_broadcast(pingsock);
@@ -692,7 +736,7 @@
 			continue;
 		}
 		unpack4(G.rcv_packet, c, &from);
-		if (pingcount && nreceived >= pingcount)
+		if (pingcount && G.nreceived >= pingcount)
 			break;
 	}
 }
@@ -706,13 +750,9 @@
 	struct iovec iov;
 	char control_buf[CMSG_SPACE(36)];

-	pingsock = create_icmp6_socket();
 	pingaddr.sin6 = lsa->u.sin6;
-	/* untested whether "-I addr" really works for IPv6: */
 	if (source_lsa)
 		xbind(pingsock, &source_lsa->u.sa, source_lsa->len);
-	if (str_I)
-		setsockopt_bindtodevice(pingsock, str_I);

 #ifdef ICMP6_FILTER
 	{
@@ -784,7 +824,7 @@
 			}
 		}
 		unpack6(G.rcv_packet, c, &from, hoplimit);
-		if (pingcount && nreceived >= pingcount)
+		if (pingcount && G.nreceived >= pingcount)
 			break;
 	}
 }
@@ -799,6 +839,11 @@
 	}
 	printf(": %d data bytes\n", datalen);

+	create_icmp_socket(lsa);
+	/* untested whether "-I addr" really works for IPv6: */
+	if (str_I)
+		setsockopt_bindtodevice(pingsock, str_I);
+
 	G.sizeof_rcv_packet = datalen + MAXIPLEN + MAXICMPLEN;
 	G.rcv_packet = xzalloc(G.sizeof_rcv_packet);
 #if ENABLE_PING6


code:
--- a/networking/ping.c
+++ b/networking/ping.c
@@ -469,6 +1053,7 @@
 	pingsock = 0,
 };

+static int using_dgram;
 static void
 #if ENABLE_PING6
 create_icmp_socket(len_and_sockaddr *lsa)
@@ -501,6 +1086,7 @@
 		if (sock < 0)
 #endif
 		bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
+		using_dgram = 1;
 	}

 	xmove_fd(sock, pingsock);
@@ -551,10 +1137,12 @@
 				bb_perror_msg("recvfrom");
 			continue;
 		}
-		if (c >= 76) {			/* ip + icmp */
-			struct iphdr *iphdr = (struct iphdr *) G.packet;
+		if (c >= 76 || using_dgram && (c == 64)) {			/* ip + icmp */
+			if(!using_dgram) {
+				struct iphdr *iphdr = (struct iphdr *) G.packet;

-			pkt = (struct icmp *) (G.packet + (iphdr->ihl << 2));	/* skip ip hdr */
+				pkt = (struct icmp *) (G.packet + (iphdr->ihl << 2));	/* skip ip hdr */
+			} else pkt = (struct icmp *) G.packet;
 			if (pkt->icmp_type == ICMP_ECHOREPLY)
 				break;
 		}
@@ -946,19 +1533,21 @@
 }
 static void unpack4(char *buf, int sz, struct sockaddr_in *from)
 {
-	struct icmp *icmppkt;
 	struct iphdr *iphdr;
+	struct icmp *icmppkt;
 	int hlen;

 	/* discard if too short */
 	if (sz < (datalen + ICMP_MINLEN))
 		return;
+	if(!using_dgram) {
+		/* check IP header */
+		iphdr = (struct iphdr *) buf;
+		hlen = iphdr->ihl << 2;
+		sz -= hlen;
+		icmppkt = (struct icmp *) (buf + hlen);
+	} else icmppkt = (struct icmp *) buf;

-	/* check IP header */
-	iphdr = (struct iphdr *) buf;
-	hlen = iphdr->ihl << 2;
-	sz -= hlen;
-	icmppkt = (struct icmp *) (buf + hlen);
 	if (icmppkt->icmp_id != myid)
 		return;				/* not our ping */

@@ -970,7 +1559,7 @@
 			tp = (uint32_t *) icmppkt->icmp_data;
 		unpack_tail(sz, tp,
 			inet_ntoa(*(struct in_addr *) &from->sin_addr.s_addr),
-			recv_seq, iphdr->ttl);
+			recv_seq, using_dgram ? 42 : iphdr->ttl);
 	} else if (icmppkt->icmp_type != ICMP_ECHO) {
 		bb_error_msg("warning: got ICMP %d (%s)",
 				icmppkt->icmp_type,
@@ -1014,11 +1603,31 @@
 	int sockopt;

 	pingaddr.sin = lsa->u.sin;
-	if (source_lsa) {
+	if (source_lsa && !using_dgram) {
 		if (setsockopt(pingsock, IPPROTO_IP, IP_MULTICAST_IF,
 				&source_lsa->u.sa, source_lsa->len))
 			bb_error_msg_and_die("can't set multicast source interface");
 		xbind(pingsock, &source_lsa->u.sa, source_lsa->len);
+	} else if(using_dgram) {
+		struct sockaddr_in sa;
+		socklen_t sl;
+
+		sa.sin_family = AF_INET;
+		sa.sin_port = 0;
+		sa.sin_addr.s_addr = source_lsa ?
+			source_lsa->u.sin.sin_addr.s_addr : 0;
+		sl = sizeof(sa);
+
+		if (bind(pingsock, (struct sockaddr *) &sa, sl) == -1) {
+			perror("bind");
+			exit(2);
+		}
+
+		if (getsockname(pingsock, (struct sockaddr *) &sa, &sl) == -1) {
+			perror("getsockname");
+			exit(2);
+		}
+		myid = sa.sin_port;
 	}

 	/* enable broadcast pings */
@@ -1035,6 +1644,15 @@
 		setsockopt(pingsock, IPPROTO_IP, IP_MULTICAST_TTL, &opt_ttl, sizeof(opt_ttl));
 	}

+	if(using_dgram) {
+		int hold = 65536;
+		if (setsockopt(pingsock, SOL_IP, IP_RECVTTL, (char *)&hold, sizeof(hold)))
+			perror("WARNING: setsockopt(IP_RECVTTL)");
+		if (setsockopt(pingsock, SOL_IP, IP_RETOPTS, (char *)&hold, sizeof(hold)))
+			perror("WARNING: setsockopt(IP_RETOPTS)");
+
+	}
+
 	signal(SIGINT, print_stats_and_exit);

 	/* start the ping's going ... */
@@ -1069,10 +1687,33 @@
 	char control_buf[CMSG_SPACE(36)];

 	pingaddr.sin6 = lsa->u.sin6;
-	if (source_lsa)
+	if (source_lsa && !using_dgram)
 		xbind(pingsock, &source_lsa->u.sa, source_lsa->len);
+	else if(using_dgram) {
+                struct sockaddr_in6 sa = {0};
+                socklen_t sl;

+                sa.sin6_family = AF_INET6;
+                sa.sin6_port = 0;
+		if(source_lsa) {
+			memcpy(&sa.sin6_addr, &source_lsa->u.sin6.sin6_addr, sizeof(struct in6_addr));
+		}
+                sl = sizeof(sa);
+
+                if (bind(pingsock, (struct sockaddr *) &sa, sl) == -1) {
+                        perror("bind");
+                        exit(2);
+                }
+
+                if (getsockname(pingsock, (struct sockaddr *) &sa, &sl) == -1) {
+                        perror("getsockname");
+                        exit(2);
+                }
+                myid = sa.sin6_port;
+	}
+
 #ifdef ICMP6_FILTER
+	if(!using_dgram)
 	{
 		struct icmp6_filter filt;
 		if (!(option_mask32 & OPT_VERBOSE)) {
@@ -1198,7 +1839,7 @@
 			str_I = NULL; /* don't try to bind to device later */
 		}
 	}
-	myid = (uint16_t) getpid();
+	if(!using_dgram) myid = (uint16_t) getpid();
 	hostname = argv[optind];
 #if ENABLE_PING6
 	{


code:
--- a/editors/sed.c
+++ b/editors/sed.c
@@ -330,7 +330,7 @@ static int get_address(const char *my_str, int *linenum, regex_t ** regex)
 		next = index_of_next_unescaped_regexp_delim(delimiter, ++pos);
 		temp = copy_parsing_escapes(pos, next);
 		*regex = xzalloc(sizeof(regex_t));
-		xregcomp(*regex, temp, G.regex_type|REG_NEWLINE);
+		xregcomp(*regex, temp, G.regex_type);
 		free(temp);
 		/* Move position to next character after last delimiter */
 		pos += (next+1);


code:
From 8aa7cf305ba5133721aa9852b398cbf1867fc857 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Sat, 19 Sep 2015 20:06:40 +0000
Subject: sort: fix -kN,M handling (was including last separator into the comparison)

Testcase:

$ printf '%s\n' a/a:a a:b | sort -t: -k1,1
a:b
a/a:a

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
diff --git a/coreutils/sort.c b/coreutils/sort.c
index 1cb4c3e..36f0254 100644
--- a/coreutils/sort.c
+++ b/coreutils/sort.c
@@ -25,14 +25,14 @@
 //usage:     "\n	-f	Ignore case"
 //usage:     "\n	-g	General numerical sort"
 //usage:     "\n	-i	Ignore unprintable characters"
-//usage:     "\n	-k	Sort key"
 //usage:     "\n	-M	Sort month"
 //usage:	)
+//-h, --human-numeric-sort: compare human readable numbers (e.g., 2K 1G)
 //usage:     "\n	-n	Sort numbers"
 //usage:	IF_FEATURE_SORT_BIG(
 //usage:     "\n	-o	Output to file"
-//usage:     "\n	-k	Sort by key"
-//usage:     "\n	-t CHAR	Key separator"
+//usage:     "\n	-t CHAR	Field separator"
+//usage:     "\n	-k N[,M] Sort by Nth field"
 //usage:	)
 //usage:     "\n	-r	Reverse sort order"
 //usage:	IF_FEATURE_SORT_BIG(
@@ -143,6 +143,9 @@ static char *get_key(char *str, struct sort_key *key, int flags)
 					}
 				}
 			}
+			/* Remove last delim: "abc:def:" => "abc:def" */
+			if (key_separator && j && end != 0)
+				end--;
 		}
 		if (!j) start = end;
 	}
@@ -163,7 +166,8 @@ static char *get_key(char *str, struct sort_key *key, int flags)
 		if (start > len) start = len;
 	}
 	/* Make the copy */
-	if (end < start) end = start;
+	if (end < start)
+		end = start;
 	str = xstrndup(str+start, end-start);
 	/* Handle -d */
 	if (flags & FLAG_d) {
diff --git a/testsuite/sort.tests b/testsuite/sort.tests
index 68fa3e4..c4b2234 100755
--- a/testsuite/sort.tests
+++ b/testsuite/sort.tests
@@ -98,6 +98,14 @@ testing "sort with non-default leading delim 3" "sort -n -k3 -t/ input" "\
 //b/1
 " ""

+testing "sort with non-default leading delim 4" "sort -t: -k1,1 input" "\
+a:b
+a/a:a
+" "\
+a/a:a
+a:b
+" ""
+
 testing "sort -u should consider field only when discarding" "sort -u -k2 input" "\
 a c
 " "\
--
cgit v0.9.1