_system(){ _system_${1:-s} "$2" "$3"                                  tem_.*\)()/\1/p" /etc/kalua/system|sort ;}
_system_s(){ _system_show ;}
_system_include(){ :;}

_system_crashreboot()
{
	local funcname="system_crashreboot"
	local reason_long="$1"
	local unixtime file reason


	/bin/echo "parent: $0 $funcname() reason: '$reason_long'" >/dev/console

	case "$reason_long" in
		[0-9a-zA-Z])
			reason="$reason_long"
		;;
		*)
			case "$reason_long" in
				nightly_reboot)	reason=0 ;;
				switch_error)	reason=1 ;;
				network_hangs)	reason=2 ;;
				overload)	reason=3 ;;
				olsrd_missing)  reason=4 ;;
				conntrack_full) reason=5 ;;
				flappy_ether)	reason=6 ;;
				flappy_olsr)	reason=7 ;;
				old_lockfile)	reason=8 ;;
				""|manual)	reason=9 ;;
				*)
					reason=${#reason_long}
					[ $reason -gt 9 ] && reason=9
				;;
			esac
		;;
	esac


	reason="ux${reason}"
	unixtime="$( /bin/date +%s )"
	file="/tmp/${reason},$(( $unixtime + 30 )),.sh"



	# CPU: 0 PID: 23018 Comm: ux0,1381076626, Not tainted 3.10.15


	[ -e '/www/CRASHLOG_WORKS' ] || echo "$funcname() reason: $reason_long" >>'/www/everlasting_syslog.txt'

	# fixme, use internal commands for "sleep"?

	echo >"$file" '#!/bin/sh'
	cat >>"$file" <<EOF
( sync ) &
/bin/sleep 10
echo 'c' >/proc/sysrq-trigger
/bin/sleep 10
/sbin/reboot -f
EOF

	/bin/chmod +x "$file" && "$file"
}

_system_maintenance_window_active()
{
	case "$( date +%H )" in
		02|03|04)
			return 0
		;;
	esac

	test -e /tmp/MAINTENANCE
}

_system_architecture()
{
	if [ -e "/etc/opkg.conf" ]
then
		grep ^"src/gz.*/packages"$ "/etc/opkg.conf" |
		 sed 's|^.*/\([a-z0-9]*\)/packages|\1|'	
	else
		_software package_status kernel |
		 grep ^Architecture: |
		  cut -d' ' -f2
	fi
}

_system_get_first_pid ()
{
	local processname="$1"
	local list_pids="$( pidof $processname )"
	local pid
	local max_pid=32767
	local min_pid=$max_pid

	for pid in $list_pids
do
		[ $pid -lt $min_pid ] && {
			min_pid=$pid	
		}
done

	[ "$max_pid" = "$min_pid" ] || echo $min_pid
}

_system_globbing ()
{
	local STATE="$1"
	
	case "$STATE" in
		off)
			set -f
		;;
		*)
			set +f
		;;
	esac
}

_system_version()
{
	local option="$1"				# e.g. "short"
	local file="/etc/freifunk-release"

	if [ -e "$file" ]
then

		case "$option" in
			short)
				head -n1 "$file"		
			;;
			*)
				grep ^Kit: "$file"		
			;;
		esac
	else
		if [ -e "/rom/etc/banner" ]
then
			file="/rom/etc/banner"
		else
			file="/etc/banner"
		fi

		case "$option" in
			short)
				sed -n 's/^.*, r\([0-9]*\)[^0-9]*/\1/p' "$file"	
			;;
			*)
				sed -n 's/^.*, r\([0-9]*\)[^0-9]*/git\1/p' "$file"
			;;
		esac
	fi
}

_system_reboot_safe()			
{					
	local FUNC="system_reboot_safe"
	local REASON="$1"
	local LOCKFILE="/tmp/SAFE_REBOOT_SCHEDULED"

	_linklocal wifi_users $WIFIDEV >/dev/null && {
		_log do $FUNC daemon info "waiting till all wifi-clients disconnect, rescheduling myself"

		echo -e "#!/bin/sh\nrm \$0\n. /tmp/loader\n_system reboot_safe '$1'" >/tmp/.autorun
		chmod +x /tmp/.autorun

		return
	}

	[ -e  "$LOCKFILE" ] && return
	touch "$LOCKFILE"

	_mail stash_for_later_resend

	cron.monitoring send_alive_message no_antenna_test

	_log do $FUNC daemon alert "scheduling reboot - reason: '$REASON'"

	tail -n1 /tmp/ARCHIV_MONITORING | grep -q ^# || {		

		_log do $FUNC daemon info "send_alive_message was unsuccessful, backing up '/tmp/ARCHIV_MONITORING'"		

		local LINENUMBER_LAST_SUCCESS="$( grep -n "^#" /tmp/ARCHIV_MONITORING | tail -n1 | cut -d':' -f1 )"
		sed -n "$(( $LINENUMBER_LAST_SUCCESS + 1 )),\$p" /tmp/ARCHIV_MONITORING >/www/backup_archiv_node_data
	}

	if [ ! -e "/www/SOFTWARE_FULLY_INSTALLED" ]
then		
	
		_log do $FUNC daemon info "safing syslog to '/www/SYSLOG_SAFED'"
		grep -v "kern.err olsrd" /var/log/messages >/www/SYSLOG_SAFED		# we don't need the "add route/del route" errors
	else
		[ "$REASON" = "nightly" ] || {
			_log do $FUNC daemon info "safing last 100 lines of syslog to '/www/SYSLOG_SAFED'"
			grep -v "kern.err olsrd" /var/log/messages | tail -n 100 >/www/SYSLOG_SAFED
		}
	fi	

	_log do $FUNC daemon info "flash free: '$( _system_flash_free )', rebooting in 10 sec"

	[ "$( uci get network.wan.proto )" = "dhcp" ] && {
		ifup wan
	}

	_system_crashreboot "$REASON"
}

_system_load()		
{
	local time="${1:-1min}"
	local format="$2"
	local cpuload decimals nop out oldIFS

	case "$time" in
		'1min')
			oldIFS="$IFS"; IFS='. '; read cpuload decimals nop </proc/loadavg; IFS="$oldIFS"
		;;
		'5min')
			oldIFS="$IFS"; IFS='. '; read cpuload decimals cpuload decimals nop </proc/loadavg; IFS="$oldIFS"
		;;
		'15min')
			oldIFS="$IFS"; IFS='. '; read cpuload decimals cpuload decimals cpuload decimals nop </proc/loadavg; IFS="$oldIFS"
		;;
	esac

	case "$format" in
		full)
			out="${cpuload}.${decimals}"
		;;
		*)
			out="${cpuload}${decimals}"
			out="${out#0}"			
			out="${out#0}"

			LOAD="$out"
		;;
	esac

	[ "$format" = 'quiet' ] || echo "${out:-100}"
}

_system_disc_free()
{
	local disc="$1"	
	local unit="$2"	

	local line="$( df | grep " $disc"$ )"
	set ${line:-0 0 0 0}

	case "$unit" in
		percent)
			local percent_used="${5%[%]*}"	
			echo $(( 100 - ${percent_used:-0} ))
		;;
		kilobytes|*)
			echo "$4"
		;;
	esac
}

_system_flash_free()
{
	local unit="$1"

	_system_disc_free "/overlay" $unit
}

_system_flash_size()
{
	local name hexsize line size=0

	while read line
do
		set -- $line		# mtd3: 003c0000 00010000 "rootfs_data"
		name="$4"		# e.g. "rootfs_data"
		name="${name%\"}"
		name="${name#\"*}"	# strip trailing/leading "
		hexsize="0x$2"

		case "$name" in
			'RedBoot'|'u-boot'|'boardconfig'|'FIS directory'|'art'|'RedBoot config'|'kernel'|'rootfs')
				size=$(( $size + $hexsize ))
			;;
		esac
done <'/proc/mtd'

	echo "$(( $size / 1024 ))"
}

_system_uptime()	
{			
	local FORMAT="$1"
	local OPTION="$2"
	local UPTIME FLOAT NOP oldifs

	local oldifs="$IFS"
	IFS='. '
	read UPTIME FLOAT NOP </proc/uptime	
	IFS="$oldifs"

	case $FORMAT in
		humanreadable)
			UPTIME="$( _stopwatch seconds2humanreadable $UPTIME )"
		;;
		sec)
			:
		;;
		min)
			UPTIME=$(( $UPTIME / 60 ))
		;;
		h|hour|hours)
			UPTIME=$(( $UPTIME / 3600 ))
		;;
		days)
			UPTIME=$(( $UPTIME / 86400 ))
		;;
		centisec|centi)
			UPTIME="${UPTIME}${FLOAT}"
		;;
		plain)
			UPTIME="$UPTIME.$FLOAT"
		;;
	esac
	
	echo "${OPTION}$UPTIME"
}

_system_date()			
{				
	local FORMAT="$1"

	case "$FORMAT" in
		humanreadable)
			case "$2" in
				short)
					_sanitizer do "$( date +%Y%b%d )" lowercase	
				;;
				nice)
					date "+%d.%b'%y-%H:%M"				
				;;
				*)
					_sanitizer do "$( date +%Y%b%d_%H:%M )" lowercase
				;;
			esac
		;;
		full)
			date					
		;;
		unixtime)
			date +%s				
		;;
		mail)						
			
			echo "$( date +%a ), $( date +%e | sed 's/ //' ) $( date "+%b %Y %X %z" | sed 's/-0/+0/' )"
		;;
		unixtime2date)
			date -d @$2
		;;
		2unixtime)
			local DATE="$2"		# output of 'date', e.g. "Tue Mar  9 11:07:44 CET 2010"
						# fixme! uname -a: "5 Mon Apr 11 11:24:07 CEST 2011"
						# fixme! uname -a: "1 So 4. Okt 13:34:39 CEST 2009"

			local WEEKDAY MONTH DAY TIME ZONE YEAR HOUR MIN SEC UNIXTIME oldifs

			read WEEKDAY MONTH DAY TIME ZONE YEAR <<EOF
$DATE
EOF
			[ -z "$YEAR" ] && YEAR="$ZONE"	

			case "$MONTH" in
				Jan|jan) MONTH="01" ;;
				Feb|feb) MONTH="02" ;;
				Mar|mar) MONTH="03" ;;
				Apr|apr) MONTH="04" ;;
				May|may) MONTH="05" ;;
				Jun|jun) MONTH="06" ;;
				Jul|jul) MONTH="07" ;;
				Aug|aug) MONTH="08" ;;
				Sep|sep) MONTH="09" ;;
				Oct|oct) MONTH="10" ;;
				Nov|nov) MONTH="11" ;;
				Dec|dec) MONTH="12" ;;
			esac

			case "$DAY" in
				[1-9]) DAY="0$DAY" ;;
			esac

			oldifs="$IFS"
			IFS=":"
			read HOUR MIN SEC <<EOF
$TIME
EOF
			IFS="$oldifs"

			date --date "${YEAR}-${MONTH}-${DAY} ${HOUR}:${MIN}:${SEC}" +%s
		;;
		evalable)
			date "+DATE=\"%b %d %H:%M:%S\""
		;;
		*)
			date "+%b %d %H:%M:%S"			
		;;
	esac
}

_system_pids_count ()
{
	local PROCESS_NAME="$1"	
	local N=0		
	local PID

	for PID in $( pidof "$PROCESS_NAME" ); do N=$(( $N + 1 )); done
	echo $N
}

_system_ram_free()	
{
	local option="$1"
	local mem line

	[ "$option" = "flush" ] && {
		option=

		[ -e "/proc/sys/vm/drop_caches" ] && {
			sync
			echo 3 > /proc/sys/vm/drop_caches
		}
	}

	while read line
do
		case $line in
			'MemFree:'*)
				set -- $line
				mem=$2
			;;
			'Buffers:'*)
				set -- $line
				mem=$(( ($mem + $2) * 1024 ))
				break
			;;
		esac
done </proc/meminfo

	echo "${option}${mem}"
}

_system_ram_size()	
{
	local option="$1"
	local mem line
	local lowram_border="16384"

	while read line
do
		case "$line" in
			MemTotal:*)
				set $line

				case "$option" in
					is_lowram)
						test $2 -le $lowram_border
					;;
					*)
						echo "$2"
					;;
				esac

				return
			;;
		esac
done </proc/meminfo
}

_system_flash_mounted_readonly ()
{
	local FUNC="flash_mounted_readonly"
	local LINE

	mount | while read LINE
do
	
		set $LINE
	
		[ "${5}${6}" = "mini_fo(ro)" ] && {
			_log do $FUNC daemon info "data-partition mounted read-only"
			return 0
		}
done
	
	return 1
}
