etbemon-1.3.6/0000755000000000000000000000000014175712147010051 5ustar etbemon-1.3.6/.git/0000755000000000000000000000000014200452020010666 5ustar etbemon-1.3.6/.git/COMMIT_EDITMSG0000644000000000000000000000133314200452020012755 0ustar Fixes for linux-temp and update changelog # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # On branch master # Your branch is up to date with 'origin/master'. # # Changes to be committed: # modified: debian/changelog # modified: mon-local.d/linux-temp.monitor # # Untracked files: # bin/btrfs.helper # bin/hplog.helper # bin/smartctl.helper # bin/zfs.helper # debian/.debhelper/ # debian/debhelper-build-stamp # debian/files # debian/mon.debhelper.log # debian/mon.postinst.debhelper # debian/mon.postrm.debhelper # debian/mon.substvars # debian/mon/ # mon-local.d/deleted-mapped.monitor # mon.d/dialin.monitor.wrap # mon.d/rpc.monitor # etbemon-1.3.6/.git/FETCH_HEAD0000644000000000000000000000013314170643574012246 0ustar 30aa75487050bafd225a0cf86f3240f65866788e branch 'master' of salsa.debian.org:etbe/etbemon etbemon-1.3.6/.git/HEAD0000644000000000000000000000002713212003645011320 0ustar ref: refs/heads/master etbemon-1.3.6/.git/ORIG_HEAD0000644000000000000000000000005114170643574012154 0ustar 2958412fd501485284fea3c53bf14d899abcbdb2 etbemon-1.3.6/.git/branches/0000755000000000000000000000000013212003645012462 5ustar etbemon-1.3.6/.git/config0000644000000000000000000000062013675267754012115 0ustar [core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true [remote "mon"] url = ssh://etbe@git.debian.org/git/collab-maint/mon.git fetch = +refs/heads/*:refs/remotes/mon/* [branch "master"] remote = origin merge = refs/heads/master [remote "origin"] url = git@salsa.debian.org:etbe/etbemon.git fetch = +refs/heads/*:refs/remotes/origin/* [pull] rebase = false etbemon-1.3.6/.git/description0000644000000000000000000000011113212003645013134 0ustar Unnamed repository; edit this file 'description' to name the repository. etbemon-1.3.6/.git/hooks/0000755000000000000000000000000013212003645012020 5ustar etbemon-1.3.6/.git/hooks/applypatch-msg.sample0000755000000000000000000000073613212003645016165 0ustar #!/bin/sh # # An example hook script to check the commit log message taken by # applypatch from an e-mail message. # # The hook should exit with non-zero status after issuing an # appropriate message if it wants to stop the commit. The hook is # allowed to edit the commit message file. # # To enable this hook, rename this file to "applypatch-msg". . git-sh-setup commitmsg="$(git rev-parse --git-path hooks/commit-msg)" test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"} : etbemon-1.3.6/.git/hooks/commit-msg.sample0000755000000000000000000000160013212003645015277 0ustar #!/bin/sh # # An example hook script to check the commit log message. # Called by "git commit" with one argument, the name of the file # that has the commit message. The hook should exit with non-zero # status after issuing an appropriate message if it wants to stop the # commit. The hook is allowed to edit the commit message file. # # To enable this hook, rename this file to "commit-msg". # Uncomment the below to add a Signed-off-by line to the message. # Doing this in a hook is a bad idea in general, but the prepare-commit-msg # hook is more suited to it. # # SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') # grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" # This example catches duplicate Signed-off-by lines. test "" = "$(grep '^Signed-off-by: ' "$1" | sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { echo >&2 Duplicate Signed-off-by lines. exit 1 } etbemon-1.3.6/.git/hooks/post-update.sample0000755000000000000000000000027513212003645015477 0ustar #!/bin/sh # # An example hook script to prepare a packed repository for use over # dumb transports. # # To enable this hook, rename this file to "post-update". exec git update-server-info etbemon-1.3.6/.git/hooks/pre-applypatch.sample0000755000000000000000000000065013212003645016160 0ustar #!/bin/sh # # An example hook script to verify what is about to be committed # by applypatch from an e-mail message. # # The hook should exit with non-zero status after issuing an # appropriate message if it wants to stop the commit. # # To enable this hook, rename this file to "pre-applypatch". . git-sh-setup precommit="$(git rev-parse --git-path hooks/pre-commit)" test -x "$precommit" && exec "$precommit" ${1+"$@"} : etbemon-1.3.6/.git/hooks/pre-commit.sample0000755000000000000000000000315213212003645015303 0ustar #!/bin/sh # # An example hook script to verify what is about to be committed. # Called by "git commit" with no arguments. The hook should # exit with non-zero status after issuing an appropriate message if # it wants to stop the commit. # # To enable this hook, rename this file to "pre-commit". if git rev-parse --verify HEAD >/dev/null 2>&1 then against=HEAD else # Initial commit: diff against an empty tree object against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 fi # If you want to allow non-ASCII filenames set this variable to true. allownonascii=$(git config --bool hooks.allownonascii) # Redirect output to stderr. exec 1>&2 # Cross platform projects tend to avoid non-ASCII filenames; prevent # them from being added to the repository. We exploit the fact that the # printable range starts at the space character and ends with tilde. if [ "$allownonascii" != "true" ] && # Note that the use of brackets around a tr range is ok here, (it's # even required, for portability to Solaris 10's /usr/bin/tr), since # the square bracket bytes happen to fall in the designated range. test $(git diff --cached --name-only --diff-filter=A -z $against | LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 then cat <<\EOF Error: Attempt to add a non-ASCII file name. This can cause problems if you want to work with people on other platforms. To be portable it is advisable to rename the file. If you know what you are doing you can disable this check using: git config hooks.allownonascii true EOF exit 1 fi # If there are whitespace errors, print the offending file names and fail. exec git diff-index --check --cached $against -- etbemon-1.3.6/.git/hooks/pre-push.sample0000755000000000000000000000250413212003645014772 0ustar #!/bin/sh # An example hook script to verify what is about to be pushed. Called by "git # push" after it has checked the remote status, but before anything has been # pushed. If this script exits with a non-zero status nothing will be pushed. # # This hook is called with the following parameters: # # $1 -- Name of the remote to which the push is being done # $2 -- URL to which the push is being done # # If pushing without using a named remote those arguments will be equal. # # Information about the commits which are being pushed is supplied as lines to # the standard input in the form: # # # # This sample shows how to prevent push of commits where the log message starts # with "WIP" (work in progress). remote="$1" url="$2" z40=0000000000000000000000000000000000000000 while read local_ref local_sha remote_ref remote_sha do if [ "$local_sha" = $z40 ] then # Handle delete : else if [ "$remote_sha" = $z40 ] then # New branch, examine all commits range="$local_sha" else # Update to existing branch, examine new commits range="$remote_sha..$local_sha" fi # Check for WIP commit commit=`git rev-list -n 1 --grep '^WIP' "$range"` if [ -n "$commit" ] then echo >&2 "Found WIP commit in $local_ref, not pushing" exit 1 fi fi done exit 0 etbemon-1.3.6/.git/hooks/pre-rebase.sample0000755000000000000000000001144213212003645015255 0ustar #!/bin/sh # # Copyright (c) 2006, 2008 Junio C Hamano # # The "pre-rebase" hook is run just before "git rebase" starts doing # its job, and can prevent the command from running by exiting with # non-zero status. # # The hook is called with the following parameters: # # $1 -- the upstream the series was forked from. # $2 -- the branch being rebased (or empty when rebasing the current branch). # # This sample shows how to prevent topic branches that are already # merged to 'next' branch from getting rebased, because allowing it # would result in rebasing already published history. publish=next basebranch="$1" if test "$#" = 2 then topic="refs/heads/$2" else topic=`git symbolic-ref HEAD` || exit 0 ;# we do not interrupt rebasing detached HEAD fi case "$topic" in refs/heads/??/*) ;; *) exit 0 ;# we do not interrupt others. ;; esac # Now we are dealing with a topic branch being rebased # on top of master. Is it OK to rebase it? # Does the topic really exist? git show-ref -q "$topic" || { echo >&2 "No such branch $topic" exit 1 } # Is topic fully merged to master? not_in_master=`git rev-list --pretty=oneline ^master "$topic"` if test -z "$not_in_master" then echo >&2 "$topic is fully merged to master; better remove it." exit 1 ;# we could allow it, but there is no point. fi # Is topic ever merged to next? If so you should not be rebasing it. only_next_1=`git rev-list ^master "^$topic" ${publish} | sort` only_next_2=`git rev-list ^master ${publish} | sort` if test "$only_next_1" = "$only_next_2" then not_in_topic=`git rev-list "^$topic" master` if test -z "$not_in_topic" then echo >&2 "$topic is already up to date with master" exit 1 ;# we could allow it, but there is no point. else exit 0 fi else not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"` /usr/bin/perl -e ' my $topic = $ARGV[0]; my $msg = "* $topic has commits already merged to public branch:\n"; my (%not_in_next) = map { /^([0-9a-f]+) /; ($1 => 1); } split(/\n/, $ARGV[1]); for my $elem (map { /^([0-9a-f]+) (.*)$/; [$1 => $2]; } split(/\n/, $ARGV[2])) { if (!exists $not_in_next{$elem->[0]}) { if ($msg) { print STDERR $msg; undef $msg; } print STDERR " $elem->[1]\n"; } } ' "$topic" "$not_in_next" "$not_in_master" exit 1 fi <<\DOC_END This sample hook safeguards topic branches that have been published from being rewound. The workflow assumed here is: * Once a topic branch forks from "master", "master" is never merged into it again (either directly or indirectly). * Once a topic branch is fully cooked and merged into "master", it is deleted. If you need to build on top of it to correct earlier mistakes, a new topic branch is created by forking at the tip of the "master". This is not strictly necessary, but it makes it easier to keep your history simple. * Whenever you need to test or publish your changes to topic branches, merge them into "next" branch. The script, being an example, hardcodes the publish branch name to be "next", but it is trivial to make it configurable via $GIT_DIR/config mechanism. With this workflow, you would want to know: (1) ... if a topic branch has ever been merged to "next". Young topic branches can have stupid mistakes you would rather clean up before publishing, and things that have not been merged into other branches can be easily rebased without affecting other people. But once it is published, you would not want to rewind it. (2) ... if a topic branch has been fully merged to "master". Then you can delete it. More importantly, you should not build on top of it -- other people may already want to change things related to the topic as patches against your "master", so if you need further changes, it is better to fork the topic (perhaps with the same name) afresh from the tip of "master". Let's look at this example: o---o---o---o---o---o---o---o---o---o "next" / / / / / a---a---b A / / / / / / / / c---c---c---c B / / / / \ / / / / b---b C \ / / / / / \ / ---o---o---o---o---o---o---o---o---o---o---o "master" A, B and C are topic branches. * A has one fix since it was merged up to "next". * B has finished. It has been fully merged up to "master" and "next", and is ready to be deleted. * C has not merged to "next" at all. We would want to allow C to be rebased, refuse A, and encourage B to be deleted. To compute (1): git rev-list ^master ^topic next git rev-list ^master next if these match, topic has not merged in next at all. To compute (2): git rev-list master..topic if this is empty, it is fully merged to "master". DOC_END etbemon-1.3.6/.git/hooks/pre-receive.sample0000755000000000000000000000104013212003645015427 0ustar #!/bin/sh # # An example hook script to make use of push options. # The example simply echoes all push options that start with 'echoback=' # and rejects all pushes when the "reject" push option is used. # # To enable this hook, rename this file to "pre-receive". if test -n "$GIT_PUSH_OPTION_COUNT" then i=0 while test "$i" -lt "$GIT_PUSH_OPTION_COUNT" do eval "value=\$GIT_PUSH_OPTION_$i" case "$value" in echoback=*) echo "echo from the pre-receive-hook: ${value#*=}" >&2 ;; reject) exit 1 esac i=$((i + 1)) done fi etbemon-1.3.6/.git/hooks/prepare-commit-msg.sample0000755000000000000000000000272413212003645016743 0ustar #!/bin/sh # # An example hook script to prepare the commit log message. # Called by "git commit" with the name of the file that has the # commit message, followed by the description of the commit # message's source. The hook's purpose is to edit the commit # message file. If the hook fails with a non-zero status, # the commit is aborted. # # To enable this hook, rename this file to "prepare-commit-msg". # This hook includes three examples. The first one removes the # "# Please enter the commit message..." help message. # # The second includes the output of "git diff --name-status -r" # into the message, just before the "git status" output. It is # commented because it doesn't cope with --amend or with squashed # commits. # # The third example adds a Signed-off-by line to the message, that can # still be edited. This is rarely a good idea. COMMIT_MSG_FILE=$1 COMMIT_SOURCE=$2 SHA1=$3 /usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE" # case "$COMMIT_SOURCE,$SHA1" in # ,|template,) # /usr/bin/perl -i.bak -pe ' # print "\n" . `git diff --cached --name-status -r` # if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;; # *) ;; # esac # SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') # git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE" # if test -z "$COMMIT_SOURCE" # then # /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE" # fi etbemon-1.3.6/.git/hooks/update.sample0000755000000000000000000000703213212003645014512 0ustar #!/bin/sh # # An example hook script to block unannotated tags from entering. # Called by "git receive-pack" with arguments: refname sha1-old sha1-new # # To enable this hook, rename this file to "update". # # Config # ------ # hooks.allowunannotated # This boolean sets whether unannotated tags will be allowed into the # repository. By default they won't be. # hooks.allowdeletetag # This boolean sets whether deleting tags will be allowed in the # repository. By default they won't be. # hooks.allowmodifytag # This boolean sets whether a tag may be modified after creation. By default # it won't be. # hooks.allowdeletebranch # This boolean sets whether deleting branches will be allowed in the # repository. By default they won't be. # hooks.denycreatebranch # This boolean sets whether remotely creating branches will be denied # in the repository. By default this is allowed. # # --- Command line refname="$1" oldrev="$2" newrev="$3" # --- Safety check if [ -z "$GIT_DIR" ]; then echo "Don't run this script from the command line." >&2 echo " (if you want, you could supply GIT_DIR then run" >&2 echo " $0 )" >&2 exit 1 fi if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then echo "usage: $0 " >&2 exit 1 fi # --- Config allowunannotated=$(git config --bool hooks.allowunannotated) allowdeletebranch=$(git config --bool hooks.allowdeletebranch) denycreatebranch=$(git config --bool hooks.denycreatebranch) allowdeletetag=$(git config --bool hooks.allowdeletetag) allowmodifytag=$(git config --bool hooks.allowmodifytag) # check for no description projectdesc=$(sed -e '1q' "$GIT_DIR/description") case "$projectdesc" in "Unnamed repository"* | "") echo "*** Project description file hasn't been set" >&2 exit 1 ;; esac # --- Check types # if $newrev is 0000...0000, it's a commit to delete a ref. zero="0000000000000000000000000000000000000000" if [ "$newrev" = "$zero" ]; then newrev_type=delete else newrev_type=$(git cat-file -t $newrev) fi case "$refname","$newrev_type" in refs/tags/*,commit) # un-annotated tag short_refname=${refname##refs/tags/} if [ "$allowunannotated" != "true" ]; then echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2 echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 exit 1 fi ;; refs/tags/*,delete) # delete tag if [ "$allowdeletetag" != "true" ]; then echo "*** Deleting a tag is not allowed in this repository" >&2 exit 1 fi ;; refs/tags/*,tag) # annotated tag if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1 then echo "*** Tag '$refname' already exists." >&2 echo "*** Modifying a tag is not allowed in this repository." >&2 exit 1 fi ;; refs/heads/*,commit) # branch if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then echo "*** Creating a branch is not allowed in this repository" >&2 exit 1 fi ;; refs/heads/*,delete) # delete branch if [ "$allowdeletebranch" != "true" ]; then echo "*** Deleting a branch is not allowed in this repository" >&2 exit 1 fi ;; refs/remotes/*,commit) # tracking branch ;; refs/remotes/*,delete) # delete tracking branch if [ "$allowdeletebranch" != "true" ]; then echo "*** Deleting a tracking branch is not allowed in this repository" >&2 exit 1 fi ;; *) # Anything else (is there anything else?) echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 exit 1 ;; esac # --- Finished exit 0 etbemon-1.3.6/.git/index0000644000000000000000000003575614200452005011743 0ustar DIRC_4o#Z( @.'6J|"N.ZtJFPKc@t .gitignore_4o#Ff'6J}L?c0tVM+3CHANGES_4o#@Ɲ'6JF@5Ȼ q\UZg!COPYING_4o#@Ɲ'6JCpH2忑xg97G]d COPYRIGHT_4o#A'6J 3V}/qn+}'r~CREDITS_4o#F'6J&Ъ`!֎=INSTALL_4o#A'6J{ծ;dg-KNOWN-PROBLEMS_4o#F'6J 7 ~c"xREADME_4o#FO5'6J5uϚ$ œ& < TODO_4o#A'6J-v$!VERSION_4o$Bbb'6Krm'8Qڜ`h3UMalert.d/file.alert_4o$Bbb'6K!s#Lalert.d/irc.alert_4o$_>Pj'pgR|#'alert.d/mail.alert_4o$_'8' 6o,Nv|2RfXZalert.d/mailxmpp.alert_4o$Bbb'6KTާ<Xalert.d/netpage.alert_4o$Bbb'6K,-:H4%U8*|v{3alert.d/qpage.alert_4o$^톇=C5'2 Šȷ# q?alert.d/slackxmpp.alert_4o$F:>8'6Kn ^iٽޭ%Ƥalert.d/snpp.alert_4o$Yw[er [1alert.templatea%;ra%;r)_?|tPQC3 bin/Makefile_4o$[U*5N'S%> IjDMgV}bin/btrfs.helper.cppbS&(dbS%[G)sv9Jf=OzOU#3r}6qclients/monfailures_4o$A'6KmIYUK+kclients/monremote.pl_4o$Y8,#'6KsSepkK$0(5clients/monshow_4o$Bbb'6KK}ЯC,ikg3clients/skymon/README_4o$@Ɲ'6KXLtEg!AݩhȂclients/skymon/allow_4o$@Ɲ'6K(zÉ"8;}H(Qclients/skymon/procmail_4o$Bbb'6K)/i WſK mclients/skymon/skymon_4o$Yw>*'6KxBaRLr~48wclients/skymon/skymon.1_4o -SE'6KW?_a'.Պy'u< debian/NEWS_4o -\; AC' 鿐T>W8ir /TJ(7԰&debian/copyright_4o -Y '6Kxr٘:y}oy(debian/mon.default_4o -XI'6Kޙג%Y].LRwZHdebian/mon.dirs_4o -Y1['6KfXE< o7f[ ̀!;debian/mon.docs_4o -SE'6KbQcόe,rޙdebian/mon.examples_4o B6^k'6jL yPŅBL4~=Sdebian/mon.install_4o -SE'6K]S`{aŜ#U=debian/mon.linksa& Qa& dHK)+ ^a PV kTEdebian/mon.postinst_4o -SE'6KW_%<7ZxX÷debian/mon.postrm_4o -SE'6KGz%%Rr$67debian/mon.preinst_4o -SE'6KFy* +Bҥ(debian/mon.prerm_4o B6^%@P'3ibk$8j]}1[ debian/rules_4o -Y- '6Liӂ~u۟~ђ21 debian/source/format_4o -SE'6K2;r'e$| debian/watch_4o"*}A'6Lj0[n<~R4*vdoc/CHANGES.mon.cgi_4o"*}@Ɲ'6Lk {Q"ep, doc/README.alerts_4o"*}Bbc'6Ll+!P?ޙ!(ydoc/README.cgi-bin_4o"*}@Ɲ'6Lm'}g򴠢|1~voZdoc/README.hints_4o"*}Bbc'6Ln.'E'ΊI^doc/README.mon.cgi_4o"g\-,NY' 2boF7xs8doc/README.monitors_4o"*}@Ɲ'6LpLE[靓gdoc/README.msql-mysql.monitor_4o"*}@Ɲ'6LqZIVWkcR6m0sdoc/README.paging_4o"*}B.'6Lrj[LX|e9F%qdoc/README.protocol_4o"*}@Ɲ'6Ls9f<l]8GY{Vdoc/README.rpc.monitor_4o"*}F9'6LtLbUk"Hf џ doc/README.snmpdiskspace.monitor_4o"*}A'6Lu(=uQ EO qPdoc/README.snmpvar.monitor_4o"*}@Ɲ'6LvCTH&H 9 doc/README.software_4o"*}A'6Lw @NOHAQ0Uזdoc/README.syslog.monitor_4o"g\F0l'v R@QIǢCk$?Pdoc/README.traps_4o"*}@Ɲ'6LyXyTK7L{HǞdoc/README.variables_4o"*}@Ɲ'6LzQ~,1VZ}OK doc/globals_4o"g@Ɲ'6L{ԋNtKO48doc/how-to-write-a-monitor.txt_4o"g@Ɲ'6L|C+%@( doc/how-to-write-an-alert.txt_4o"gYw>'6L}N):13c3o< doc/mon.8_4o"gYw>7™'6L~ gAUPdNy3Y doc/moncmd.1_4o"gYw>'6LN ,8{?$doc/monfailures.1_4o"gBbc'6Lh+o ?s[ doc/monshow.1_4o"g\1'D.V*aͲrQ etc/auth.cf_4o"gF'6LBKkϒEsq)etc/example.cf_4o"g@Ɲ'6L1-EFE+etc/example.m4_4o"g@Ɲ'6L,Ju^3 d1etc/example.monshowrc_4o"gYB@\-'6L" :eW.JfP8.]etc/init.d/mon_4o"g^ś:F'ݐ]ʥ}+DŽ<A0 etc/mon.cf_4o"gA'6L {FyBmd6a ycI}etc/mon.cgi.cf_4o"gSE'6LyI^9NJ8I etc/monshowrc_4o"g@Ɲ'6L+t..UN껵Tetc/na_quota.cf_4o"g@Ɲ'6LއF?`X4etc/netappfree.cf_4o"gF9'6L . 1x{<|rCTetc/snmpdiskspace.cf_4o"gA'6LO'zmPר"WYM>etc/snmpopt.cf_4o"gA'6L DE)ki;%w{Aetc/snmpvar.cf_4o"gA'6L>YL ʺcGF]"etc/snmpvar.def_4o"gA'6L H=vG&A9]F{'etc/syslog-monitor.conf_4o"g_#3'ԖI늏w]۳S)etc/very-simple.cf_i;:<_i:']͈Q (yEFetc/windows.cf_4o#^=n'Ó# ʼnaTyN0&rmona$E8Uwpa$E8n)Ax͟^/X^mon-local.d/Makefile_4o"g\)z' L['Lc @mon-local.d/btrfs.monitor_4o"g^''1\4TNOy}Dh5]D^'6L+$#pnmeFzz!^mon-local.d/softraid.monitor_4o"g^1(i'. !5P0q,%V)1$5mon-local.d/zfs.monitoraH7*Ks]aH7*Ks])6L"PP!i 'Ba7x mon.d/Makefile_4o"Yw=;7n'6Ld_ܟi^pxpmon.d/asyncreboot.monitor_4o"Yw=;7n'6L$_(@|uus"]qmon.d/cpqhealth.monitor_4o"@Ɲ'6LM \mon.d/dialin.monitor_4o"A'6LlY;K 5 [,ǮSOmon.d/dialin.monitor.wrap.c_4o"@Ɲ'6Le0J ]^L4>Gmon.d/dns-query.monitor_4o"[?&'6LBJJ崀 7omon.d/dns.monitor_4o"A'6L@$ L =%<5/mon.d/file_change.monitor_4o"Yw=;7n'6L"^ݷ?Řmon.d/foundry-chassis.monitor_4o"FC*'6L x ɳ :vmon.d/fping.monitor_4o"F@^6'6Ll+ TƊ){;mon.d/ftp.monitor_4o"@Ɲ'6L s^"p*rs{?{lmon.d/hpnp.monitor_4o"YR'6L:3gŊy΋#!mon.d/http.monitor_4o"Fc'6Lr^{'\ZXN&X*mon.d/http_tppnp.monitor_4o"CK'6LwaL_x)͝ mon.d/imap.monitor`~iC`~iC'AۛQTGɬG-mmon.d/imapnew.monitor_4o"@Ɲ'6L$xJo:wI.b!mon.d/ldap.monitor_4o"FbŇ'6Lj[Jc8!P=ORטmon.d/local-syslog.monitor_4o"@Ɲ'6LYթC k|'mon.d/lpd.monitor_4o"F:>;'6LO|F]\8pmfA] mon.d/mon.monitor_4o"Y#G'6LY)x~E'+5o3!mon.d/msql-mysql.monitor_4o"Yw=;7n'6L7,M$o_0-mon.d/na_quota.monitor_4o"Yw=;u'6L" SlSumon.d/netappfree.monitor_4o"ᘴF:><'6L& vW8QqȾ4mon.d/nntp.monitor_4o"ᘴFb'6L*#گU ~F'6LxQ^XTmon.d/ping.monitor_4o"ᘴBbc'6L y`ˣ-#XH|qF9Bmon.d/pop3.monitor_4o"ᘴYw=;u'6L R%l^QV%C䅈dьmon.d/process.monitor_4o"ᘴYw=n '6LS "^zyqəmon.d/radius.monitor_4o"ᘴ@Ɲ'6L}G6dS :cmon.d/rd.monitor_4o"ᘴYw=;u'6L\dgEL DHx mon.d/reboot.monitor_4o"ᘴ]2bmF'6L'ω&bp mon.d/remote.monitor_4o"ᘴ@Ɲ'6L+@êzd'(6aPGmon.d/rpc.monitor.c_4o"ᘴBbc'6L1I}M\hΜmon.d/seq.monitor_4o"ᘴYw=;u'6LD CF } G[:mon.d/silkworm.monitor_4o"ᘴBbc'6L JOZ_Z[ ?mon.d/smtp.monitor_4o"ᘴFct'6LG[[\&L# )mon.d/smtp3.monitor_4o"ᘴ^}'˩Ih}IiMmon.d/smtpswaks.monitor_4o"ᘴYw=;u'6LCu2~7iHLmon.d/snmpdiskspace.monitor_4o"ᘴA'6LBQIQ.ሊ&Fy mon.d/snmpvar.monitoraF:aF:) bN4+V}M-47܅mon.d/sslcert.monitor_4o"ᘴBbc'6L Q,,I=Gcdga}mon.d/tcp.monitor_4o"ᘴBbc'6Lc*kcM'tmuxpect/setup.c_4o"ᘴ@Ɲ'6LgWZaɊQm‰T'state.d/README_4o#Y=&+$'6L٤WD6gʙ!lsystemd/mon.service_4o#X+m'6L$>!p/|<systemd/tmpfiles.d/mon.conf_4o#Bbc'6L a~o -:utils/cf-to-hosts_4o#A'6LQ(*8{_,Kʡ&p>utils/syslog.monitorTREE173 12 ( !G|/񌢼Xbin5 0 D*Y< 70_m뾠mdoc23 0 ~{4ޯcۘ#x[&etc17 1 ~ػ³`'ualert.d10 0  s-Qڢna+clients11 1 5m"adÛwskymon5 0 V2!^muxpect6 0 D޴g{ }D3state.d1 0 +uATȴCpsystemd2 1 FJ0^С Qh)/Utmpfiles.d1 0 N댮LR umon-local.d14 0 0JkZW: d&@/S8 )s~6} tetbemon-1.3.6/.git/info/0000755000000000000000000000000013212003645011630 5ustar etbemon-1.3.6/.git/info/exclude0000644000000000000000000000036013212003645013203 0ustar # git ls-files --others --exclude-from=.git/info/exclude # Lines that start with '#' are comments. # For a project mostly in C, the following would be a good set of # exclude patterns (uncomment them if you want to use them): # *.[oa] # *~ etbemon-1.3.6/.git/logs/0000755000000000000000000000000013212006100011626 5ustar etbemon-1.3.6/.git/logs/HEAD0000644000000000000000000006617314200452020012273 0ustar 0000000000000000000000000000000000000000 edff5c0a55e12219a438c1e67f6feff4c0ba754e Russell Coker 1512574016 +1100 initial pull edff5c0a55e12219a438c1e67f6feff4c0ba754e a1e18032c138a2af26d3b779904669728f8f6c1d Russell Coker 1512574289 +1100 commit: Move template out of alert.d directory a1e18032c138a2af26d3b779904669728f8f6c1d e5e22e35547169888b18bbd338809622fda184e7 Russell Coker 1512574316 +1100 commit: Don't use /tmp for security reasons e5e22e35547169888b18bbd338809622fda184e7 7b1d76289a3b1ee985575025a089de0f22ac19f4 Russell Coker 1512574347 +1100 commit: Longer summary length as we are already over 80 chars 7b1d76289a3b1ee985575025a089de0f22ac19f4 09cfd68e63c68a01a14ed2b14ec7552c3af6ddea Russell Coker 1512574378 +1100 commit: All the latest changes. 09cfd68e63c68a01a14ed2b14ec7552c3af6ddea 449fee8993c375739f31ddd58d9b78de642c8ad6 Russell Coker 1512574401 +1100 commit: Depend on latest debhelper 449fee8993c375739f31ddd58d9b78de642c8ad6 f688c7c9a2d447bf3dd23557f38797df93bc9bd0 Russell Coker 1512574414 +1100 commit: Team maintenance and recommend more packages that monitors need f688c7c9a2d447bf3dd23557f38797df93bc9bd0 4cd5209313a5eb3cabfd56769e684181dae3915a Russell Coker 1512574487 +1100 commit: don't use debian/docs 4cd5209313a5eb3cabfd56769e684181dae3915a 493cc6ff7fd9e812f7fc01a10bd9782459f0a0a4 Russell Coker 1512574576 +1100 commit: Move auth.cf to etc 493cc6ff7fd9e812f7fc01a10bd9782459f0a0a4 f3f3a1fde8a41fee3a92dec0b0033fe6d4d087f9 Russell Coker 1512574677 +1100 commit: Add mon-local.d dir and add more example entries f3f3a1fde8a41fee3a92dec0b0033fe6d4d087f9 5c0c29ebb2f40feccfead2e2cd4d213d92520e05 Russell Coker 1512574705 +1100 commit: Move mon.cf to etc 5c0c29ebb2f40feccfead2e2cd4d213d92520e05 c65949adfc1f5c0f9cd6e3aa8d28b9d3174b1ae4 Russell Coker 1512574740 +1100 commit: Move monshowrc to etc dir c65949adfc1f5c0f9cd6e3aa8d28b9d3174b1ae4 8e27d13fb510bf6026bcd89f8de5de754dbabcdf Russell Coker 1512574766 +1100 commit: Remove most entries, lets use /etc/mon/mon.cf for it 8e27d13fb510bf6026bcd89f8de5de754dbabcdf 4eba223718103fb1a00c53970395192b82086e0d Russell Coker 1512574794 +1100 commit: Add alert.template to the docs 4eba223718103fb1a00c53970395192b82086e0d eaf3d06d92649f3dbc0fa089780f6a7c71c5fd73 Russell Coker 1512574816 +1100 commit: Add mon/bin and mon-local.d to the list of dirs eaf3d06d92649f3dbc0fa089780f6a7c71c5fd73 add1baa61ed261f183e4bdfc420386a8552436b8 Russell Coker 1512574881 +1100 commit: Use /run instead of /var/run add1baa61ed261f183e4bdfc420386a8552436b8 e2c3d659c68dfbe43b7dca832f165c5a890b4e2c Russell Coker 1512574909 +1100 commit: Move the init.d script out of the debian dir e2c3d659c68dfbe43b7dca832f165c5a890b4e2c 0190f7a73b3f02dc58ed35a822335aa82b8ef951 Russell Coker 1512574944 +1100 commit: Mostly move stuff out of the debian dir if it's not specific to debian. 0190f7a73b3f02dc58ed35a822335aa82b8ef951 c3a1a4c6931a558f8bf568f01943dec936bd9ea4 Russell Coker 1512575097 +1100 commit: Use /run instead of /var/run and add systemd support c3a1a4c6931a558f8bf568f01943dec936bd9ea4 386e4135b696a8c98b533e7aebe59835a2257a49 Russell Coker 1512575372 +1100 commit: Remove patches that are now upstream 386e4135b696a8c98b533e7aebe59835a2257a49 923928bf7bdf205fb61ae07b96fea5592407aeba Russell Coker 1512575405 +1100 commit: Systemd support and adding mon/bin and mon-local.d directories 923928bf7bdf205fb61ae07b96fea5592407aeba 5d25d4af602422e6c0b1b24602379293f9af9d59 Russell Coker 1512575434 +1100 commit: Format 1.0 as now we are mostly Debian as upstream 5d25d4af602422e6c0b1b24602379293f9af9d59 88e4706986de4700b35da9939f438ef421d4a4cb Russell Coker 1512575467 +1100 commit: Use /run instead of /var/run and escape - 88e4706986de4700b35da9939f438ef421d4a4cb ed018480f8da3ddf767d02408e06ec92306e993c Russell Coker 1512575505 +1100 commit: Escape - ed018480f8da3ddf767d02408e06ec92306e993c c628bdf15a5a7ca83fbc2c01f2c3963773624484 Russell Coker 1512575544 +1100 commit: Remove old init.d script c628bdf15a5a7ca83fbc2c01f2c3963773624484 830c0c53dd67d6ed186fc46118a638ce37113937 Russell Coker 1512575571 +1100 commit: Use /run instead of /var/run and added @args to avoid warning (I think) 830c0c53dd67d6ed186fc46118a638ce37113937 ba9a48c417f675e3e142cb3e96c15a29817235b1 Russell Coker 1512575670 +1100 commit: Better handle Debian build flags, may not be ideal for non-Debian systems ba9a48c417f675e3e142cb3e96c15a29817235b1 647b98c6889c07512a091eaa661ae6744b1c7cf2 Russell Coker 1512575832 +1100 commit: use Mon::SNMP instead of use SNMP 647b98c6889c07512a091eaa661ae6744b1c7cf2 07952177f7360e52f6ea0a096cdaf68e01722291 Russell Coker 1512575885 +1100 commit: Give a better summary 07952177f7360e52f6ea0a096cdaf68e01722291 35c9bb9a2364c458cb453b17d8484600bf0b8ad6 Russell Coker 1512575969 +1100 commit: Use Filesys::Df instead of Filesys::DiskSpace. 35c9bb9a2364c458cb453b17d8484600bf0b8ad6 dc8d16f3360e1ef50c57e78164ba6331cc178f3c Russell Coker 1512576055 +1100 commit: Move local test for freespace to mon-local.d dc8d16f3360e1ef50c57e78164ba6331cc178f3c 728e78d877145a709f4bb4a0e2c0f10ec2002b1e Russell Coker 1512576180 +1100 commit: Add new local monitors: 728e78d877145a709f4bb4a0e2c0f10ec2002b1e a1741ec392f52e8482b466d515e94ab2f416c64a Russell Coker 1512576363 +1100 commit: Add ps.monitor from contrib and added some new features to it, including a1741ec392f52e8482b466d515e94ab2f416c64a 88d7929b8a96cb1015b1484c226b1dcc9b2eeda7 Russell Coker 1512576417 +1100 commit: Make it work with strict 88d7929b8a96cb1015b1484c226b1dcc9b2eeda7 657d6928fc1f47547ceb50eb8466c69700140e65 Russell Coker 1512576482 +1100 commit: Add support for reading a password from a file so "ps" won't show passwords 657d6928fc1f47547ceb50eb8466c69700140e65 3e6c6138934c34157393749fe3154e3a409f4bda Russell Coker 1512576514 +1100 commit: Support specifying the ping count and also ping6 3e6c6138934c34157393749fe3154e3a409f4bda 9f8922d3a44e1b5662d1e8aae6286a74efb63834 Russell Coker 1512576624 +1100 commit: Use ||= for options in case they were already set and comment that a config 9f8922d3a44e1b5662d1e8aae6286a74efb63834 85fc461036a20c9b5e067996ab22d55f6552c165 Russell Coker 1513758919 +1100 commit: Add all monitors to git 85fc461036a20c9b5e067996ab22d55f6552c165 d01ff140845ab3c2b4c6dfb08bfe3e8afbcc044d Russell Coker 1513759375 +1100 commit: Track all source d01ff140845ab3c2b4c6dfb08bfe3e8afbcc044d 9864be268f4d50301a4f07bc46d3cd253ee7571f Russell Coker 1513759427 +1100 commit: Document change to smtpswaks 9864be268f4d50301a4f07bc46d3cd253ee7571f 0f8d9b329e1a7b9617600b86ae3072a8ec30102d Russell Coker 1514651290 +1100 commit: add setrlimit 0f8d9b329e1a7b9617600b86ae3072a8ec30102d bda92a000b71fa6ff999d1740786cb8a752d7e1c Russell Coker 1514651378 +1100 commit: Changelog for cpu limit in mailxmpp bda92a000b71fa6ff999d1740786cb8a752d7e1c d7a449dc5d0ce269c60cc4f97a0eeccff6c30a9b Russell Coker 1520415694 +1100 commit: Changelog change for release d7a449dc5d0ce269c60cc4f97a0eeccff6c30a9b b7d86251b4eb905297716b714db403b8943d07f3 Russell Coker 1520415746 +1100 pull: Merge made by the 'recursive' strategy. b7d86251b4eb905297716b714db403b8943d07f3 ce6b487922391b6b20f983f7425a190ec765f277 Russell Coker 1526449793 +1000 commit: Add -s option to select whether HTTPS SNI should be used (default yes for port ce6b487922391b6b20f983f7425a190ec765f277 c90c6735aeaa2f3a92b2ff1413f162f081c8aa28 Russell Coker 1526451500 +1000 commit: New upstream release and SNI support in sslcert.monitor c90c6735aeaa2f3a92b2ff1413f162f081c8aa28 9e0f07aaa81c402bf9484aab3b69cd9561d3d095 Russell Coker 1527937880 +1000 commit: Check Received: headers for long delays and clock skew 9e0f07aaa81c402bf9484aab3b69cd9561d3d095 67279e76648973b6ee1a34237789ad449dfdc30d Russell Coker 1528027024 +1000 commit: Correctly handle Received dates, From: date, and delivery date. 67279e76648973b6ee1a34237789ad449dfdc30d 5677b5d053268185f89b9ef5492c99ad312fa378 Russell Coker 1529989536 +1000 commit: Removed defined() around hash and array checks, not supported in recent perl 5677b5d053268185f89b9ef5492c99ad312fa378 505666380f4b81f34633dd674318cd1aca3d3ab1 Russell Coker 1529990188 +1000 commit: Don't abort mon.cgi when $ONDS{$group} is invalid 505666380f4b81f34633dd674318cd1aca3d3ab1 e8cc468b8b8f51612618072cd89ed9bb4a8e9061 Russell Coker 1532224189 +1000 commit: Make loadavg report the system memory use e8cc468b8b8f51612618072cd89ed9bb4a8e9061 288ac0693d5a98232225271d0eb366f21cf1e3d4 Russell Coker 1532309265 +1000 commit: Change btrfs.monitor to use SUID helper instead of sudo and to check subvols too 288ac0693d5a98232225271d0eb366f21cf1e3d4 6f8fa3ee313997acbc2833b4270db9311ff9a174 Russell Coker 1532310164 +1000 commit: New SETUID helper programs. 6f8fa3ee313997acbc2833b4270db9311ff9a174 7cb07655c51a51d6e983ee3239df3125d6248457 Russell Coker 1532323500 +1000 commit: Change timestamp for release 7cb07655c51a51d6e983ee3239df3125d6248457 09d86464189786f3c22977483740528af6125746 Russell Coker 1535983553 +1000 commit: Correctly display summary when multiple -query parameters are used for 09d86464189786f3c22977483740528af6125746 4ea7f0847c0d284b9c37b9137dcdd3a89eda8903 Russell Coker 1555314438 +1000 commit: Link btrfs.helper with gcc not g++ to reduce dependencies. 4ea7f0847c0d284b9c37b9137dcdd3a89eda8903 6e6ca61eb80f177d264dab5897b29aa56c437acc Russell Coker 1555315024 +1000 commit: Remove old helper 6e6ca61eb80f177d264dab5897b29aa56c437acc c056baed2021c98f6e25baf371991ee08183bb98 Russell Coker 1555315119 +1000 commit: Remove btrfs.helper c056baed2021c98f6e25baf371991ee08183bb98 b0ad8088017fb4f368311b58bc2721eaef048205 Russell Coker 1555315158 +1000 commit: rm -f for make clean b0ad8088017fb4f368311b58bc2721eaef048205 7e738f94bf2198f4f03555c71529499c8feda7dc Russell Coker 1555315528 +1000 commit: Fixed some lintian warnings 7e738f94bf2198f4f03555c71529499c8feda7dc 28f76562bf30f8a8f297ea3bab10f3c3487c2231 Russell Coker 1555505417 +1000 commit: Make traps work properly and document them better 28f76562bf30f8a8f297ea3bab10f3c3487c2231 32dd660a2474d15616efdce73984e5a8f6668a68 Russell Coker 1555505447 +1000 commit: Make imapnew.monitor log Message-Id and expunge messages even when there is a 32dd660a2474d15616efdce73984e5a8f6668a68 d17497502e75a67badbedb3b763723a4679e277b Russell Coker 1555505954 +1000 commit: Make it compile the helper programs d17497502e75a67badbedb3b763723a4679e277b d1cc17481f430389aa68fd21df03a8b1da3c860d Russell Coker 1555507386 +1000 commit: Fix count files in btrfs.monitor d1cc17481f430389aa68fd21df03a8b1da3c860d 290672f616a9ccbc7fdd4c2c3fbc415536a6b47f Russell Coker 1555507483 +1000 commit: Removed printf debugging 290672f616a9ccbc7fdd4c2c3fbc415536a6b47f c896d5b94b943a445f4a7278400064b7917e9a1e Russell Coker 1556620734 +1000 commit: Added bug close line c896d5b94b943a445f4a7278400064b7917e9a1e e0679f570f96c298a614696320e4421023f9d8e5 Russell Coker 1556622627 +1000 commit: Make trapbind default to 127.0.0.1 and also add comments e0679f570f96c298a614696320e4421023f9d8e5 55bd4d3d805850c8c2615bd093aa95721bcde4d8 Russell Coker 1556622862 +1000 commit: Fix example config 55bd4d3d805850c8c2615bd093aa95721bcde4d8 92d5cd4d316e90d208009f1c32e4b5dd2f3d4ee3 Russell Coker 1563401501 +1000 commit: Give a better summary line and also show top CPU use 92d5cd4d316e90d208009f1c32e4b5dd2f3d4ee3 89827b77052234730b4ab596ea5208df14b44f24 Russell Coker 1563401541 +1000 commit: Check swap+RAM use as well as load average 89827b77052234730b4ab596ea5208df14b44f24 a8f1b467ba15868e97e1b1780782888d3624b571 Russell Coker 1563401810 +1000 commit: Better log entries on authfile auth failure a8f1b467ba15868e97e1b1780782888d3624b571 857ccb2300c408cc175ad069b725a1b04641a0f4 Russell Coker 1563401884 +1000 commit: Latest changes 857ccb2300c408cc175ad069b725a1b04641a0f4 e6827ce66bdde0e283fc2b25835a892994565628 Russell Coker 1563583023 +1000 commit: Consolidated help e6827ce66bdde0e283fc2b25835a892994565628 605322154fa8534b3f15bbf0345fd67f3cfc7c03 Russell Coker 1563583124 +1000 commit: Changelog for remote.monitor 605322154fa8534b3f15bbf0345fd67f3cfc7c03 1636b2fbb87141699761afd436d66fab10e5efc8 Russell Coker 1578290600 +1100 commit: Add check for deleted but mapped files (for shared object upgrades). 1636b2fbb87141699761afd436d66fab10e5efc8 6c828acd2eb68a128016cbc86858ade26fa55972 Russell Coker 1578290656 +1100 commit: Fix date 6c828acd2eb68a128016cbc86858ade26fa55972 f6a5709fe3f600d4bdb842acaaec7b8b0296d440 Russell Coker 1578301273 +1100 commit: Use SUID root binary for zfs f6a5709fe3f600d4bdb842acaaec7b8b0296d440 bf157a8f53bf9eee483860f8638a3c621cea597c Russell Coker 1578301294 +1100 commit: SUID root helper for zfs bf157a8f53bf9eee483860f8638a3c621cea597c 58559086c0c915d6b5a6a1d9ade463f92be211ad Russell Coker 1578301321 +1100 commit: SUID root ZFS helper 58559086c0c915d6b5a6a1d9ade463f92be211ad 25b8ec5cb1f54daa1ca5d5c076cba84da5e54f82 Russell Coker 1578302150 +1100 commit: Ignore /dev/zero for kernel mapping funnyness 25b8ec5cb1f54daa1ca5d5c076cba84da5e54f82 0c2846e653043723a6b4f4aac07610d609813f69 Russell Coker 1578302410 +1100 commit: Use SUID root wrapper for the deleted-mapped.monitor 0c2846e653043723a6b4f4aac07610d609813f69 24a77f6f6dc255703d87f4f2304570f43c037e98 Russell Coker 1578302480 +1100 commit: Fix warning 24a77f6f6dc255703d87f4f2304570f43c037e98 69085d07fbbe726914ee112ded969225c85616e9 Russell Coker 1578302513 +1100 commit: Changes for deleted-mapped suid wrapper 69085d07fbbe726914ee112ded969225c85616e9 06e9fc97e8d45d44f9bbb059720434838bb5779b Russell Coker 1578302559 +1100 commit: make /usr/lib/mon/mon-local.d/deleted-mapped.monitor suid root 06e9fc97e8d45d44f9bbb059720434838bb5779b 3a3045e5148af3a12406580e2b34a62c7e3a2d53 Russell Coker 1578302572 +1100 commit: . 3a3045e5148af3a12406580e2b34a62c7e3a2d53 d002d0f010f6bfba4f36b216ccb5ca1fcdeac453 Russell Coker 1578302951 +1100 commit: Make it install the real file for deleted shared objects d002d0f010f6bfba4f36b216ccb5ca1fcdeac453 cac8f604f75130f3463b0ac4d39b1aed003c3e85 Russell Coker 1578302981 +1100 commit: build and clean in mon-local.d cac8f604f75130f3463b0ac4d39b1aed003c3e85 17ccc5ed3092d64f9b562960076c7c7b29b025b5 Russell Coker 1578303493 +1100 commit: New release with fixes for the deleted mapped checks 17ccc5ed3092d64f9b562960076c7c7b29b025b5 3737e98a14ec0f6d6aae58eddd5774bad355e5f7 Russell Coker 1580627698 +1100 commit: Update standars version and changelog for 1.3.4 3737e98a14ec0f6d6aae58eddd5774bad355e5f7 98121f0a11b3316c0a4851eaba33e094d47f1f41 Russell Coker 1580627768 +1100 commit: Lots of changes, make it release worthy 98121f0a11b3316c0a4851eaba33e094d47f1f41 98121f0a11b3316c0a4851eaba33e094d47f1f41 Russell Coker 1581078225 +1100 reset: moving to HEAD 98121f0a11b3316c0a4851eaba33e094d47f1f41 2519672ad87bab46eb2fb528f4e18b2427d95842 Russell Coker 1581078235 +1100 pull: Fast-forward 2519672ad87bab46eb2fb528f4e18b2427d95842 7b9d5955ce7cb2ce01694c605e083ba4ef2789c0 Russell Coker 1586043748 +1000 commit: Make it work with latest swaks 7b9d5955ce7cb2ce01694c605e083ba4ef2789c0 828cb88adc26dbebf3e8091b372969a9f24a1867 Russell Coker 1587985323 +1000 commit: ignore useless errors from sensors 828cb88adc26dbebf3e8091b372969a9f24a1867 4ef11c843fbd34efe1224c08d5e56f756a6cbb2e Russell Coker 1590026390 +1000 commit: Made smtpswaks.monitor take a service port 4ef11c843fbd34efe1224c08d5e56f756a6cbb2e 28b6be2de5ed12a9724543ef59c3cb215dce5f7a Russell Coker 1590822795 +1000 commit: add authfile to config 28b6be2de5ed12a9724543ef59c3cb215dce5f7a 3c0e27a3730a1f84a5fb89d6e728063bcc4b03d9 Russell Coker 1591589973 +1000 commit: Change some of the filesystem code as a first step to making it work on Windows 3c0e27a3730a1f84a5fb89d6e728063bcc4b03d9 690ece4d0dac09654c2d10fb56d0efaf533cdb92 Russell Coker 1592624835 +1000 commit: Alert to Jabber and Slack 690ece4d0dac09654c2d10fb56d0efaf533cdb92 edfa34021dcd925d6025c0af1ca7bce1a72530a1 Russell Coker 1594086752 +1000 commit: Remove duplicate summary messages edfa34021dcd925d6025c0af1ca7bce1a72530a1 8b4db85e7c1aff7aa409cc3cf309c475fc39592c Russell Coker 1600600593 +1000 commit: Some changes needed for rpming latest version 8b4db85e7c1aff7aa409cc3cf309c475fc39592c 877b63657cd545f35bcb5320d802d18454955725 Russell Coker 1600606530 +1000 commit: Don't want this 877b63657cd545f35bcb5320d802d18454955725 77ae771aaad17a51336be907c2cd546ddc3c6419 Russell Coker 1600607019 +1000 commit: Updated rpm build to latest stuff and included systemd support 77ae771aaad17a51336be907c2cd546ddc3c6419 6b121fb45405d2cf85fbbba3cc52f86eb9429bb0 Russell Coker 1600608680 +1000 commit: depend on perl-BSD-Resource and fix some perms 6b121fb45405d2cf85fbbba3cc52f86eb9429bb0 8d41ea69885128aa059caa19126f0fbb02621081 Russell Coker 1600952377 +1000 commit: Reformatted source 8d41ea69885128aa059caa19126f0fbb02621081 5403e1ec14081a801080892bc7f53fa1b79d1129 Russell Coker 1607601843 +1100 commit: Made it do IPv6 and IPv6 checks and check all addresses of each hostname 5403e1ec14081a801080892bc7f53fa1b79d1129 aa63082131613ac3479096ded34822d17422f400 Russell Coker 1607601871 +1100 commit: Changelog for libsys-filesystem-perl and sslcert.monitor and depends for libsys-filesystem-perl aa63082131613ac3479096ded34822d17422f400 ed18213f61204716f1bcd912e3fbb3031e2c8a72 Russell Coker 1607607312 +1100 commit: Add a basic config snippet to git ed18213f61204716f1bcd912e3fbb3031e2c8a72 5ec8aa2a9f437b45b996bd3518655424098a28d0 Russell Coker 1607646663 +1100 commit: Fix for sites that don't have both IPv6 and IPv4 DNS records 5ec8aa2a9f437b45b996bd3518655424098a28d0 2e0f7e1356dd3518bc8e476a3e8a0f97008ab334 Russell Coker 1608422985 +1100 commit: monitor and parse smartctl output 2e0f7e1356dd3518bc8e476a3e8a0f97008ab334 d5080cd0d5d44ce349adef429f7655c7684315be Russell Coker 1608423220 +1100 commit: new upstream ver d5080cd0d5d44ce349adef429f7655c7684315be 235be2efdcbcdb56c0ec0421d29e87bd9bf6ea12 Russell Coker 1608424847 +1100 commit: rename for wrapper 235be2efdcbcdb56c0ec0421d29e87bd9bf6ea12 94cd51c2ee973bca91b106472f253c114b9ba3d1 Russell Coker 1608431751 +1100 commit: Add smartctl helper to run it as root 94cd51c2ee973bca91b106472f253c114b9ba3d1 5998ead72add170e2675f4fe6ff82d7dc6e24266 Russell Coker 1608431976 +1100 commit: Use SUID helper to run smartctl 5998ead72add170e2675f4fe6ff82d7dc6e24266 3751d3a9146a0c74c727509e703a751395b29225 Russell Coker 1608436148 +1100 commit: Set perms on smartctl helper 3751d3a9146a0c74c727509e703a751395b29225 c61da090b5d7e9d83698cc66f0cd2df607297a29 Russell Coker 1608436301 +1100 commit: remove mistake c61da090b5d7e9d83698cc66f0cd2df607297a29 7c56a3b9f602d1fd54afa50af4db11528fb12730 Russell Coker 1608438069 +1100 commit: Better error logging 7c56a3b9f602d1fd54afa50af4db11528fb12730 9871854e10df73ee206a051bbaaec5d168b89d49 Russell Coker 1609883670 +1100 commit: display PSI cgroup2 data in loadavg.monitor output 9871854e10df73ee206a051bbaaec5d168b89d49 da44e2601766ce9676872188ef9c6bc936524c7d Russell Coker 1609883803 +1100 commit: Sample config file for running on Windows da44e2601766ce9676872188ef9c6bc936524c7d 0a3276c29c0b519fcdf7bcea7197e0b66d91b6de Russell Coker 1611039933 +1100 commit: "python3" and "python3.9" support in ps.monitor 0a3276c29c0b519fcdf7bcea7197e0b66d91b6de c378b23cc7ebb2740694e8efc26fd3fbe05f8884 Russell Coker 1611040283 +1100 commit: Don't warn on process exit before map file is opened c378b23cc7ebb2740694e8efc26fd3fbe05f8884 01937364a92cc439993221b2fb9ffc0d3411014c Russell Coker 1613962666 +1100 commit: Make deleted-mapped.monitor avoid checking for systemd processes and have 01937364a92cc439993221b2fb9ffc0d3411014c 3a4af870e64bfc81c3d36cdcec01c4dcd9982589 Russell Coker 1613971105 +1100 commit: Fix changelog for unstable 3a4af870e64bfc81c3d36cdcec01c4dcd9982589 f4363ae6682bb7e4d8662b8ac59ff3d0ec990166 Russell Coker 1617599465 +1000 commit: Handle missing Message-Id correctly f4363ae6682bb7e4d8662b8ac59ff3d0ec990166 840eabed552ed394292cdb75f7edd7933b35af6f Russell Coker 1617599494 +1000 commit: Make the deleted-mapped test not alert on sshd privsep process 840eabed552ed394292cdb75f7edd7933b35af6f 7804c96bbc51a71704a9e1b43b6397aff5677ea6 Russell Coker 1617611377 +1000 commit: made imapnew.monitor do case insensitive header checks 7804c96bbc51a71704a9e1b43b6397aff5677ea6 6dc5dd9dc2c88dc456f324e4ecb677e4a911785b Russell Coker 1621757495 +1000 commit: Better fix for imapnew.monitor 6dc5dd9dc2c88dc456f324e4ecb677e4a911785b e98903c9406f73ac4bd526b8415cebbf936c5816 Russell Coker 1621757575 +1000 commit: Added monitoring for HP server temperature e98903c9406f73ac4bd526b8415cebbf936c5816 768d8b60822973d32194eb11d0b80696dac2cfd5 Russell Coker 1623047674 +1000 commit: Added support for MegaRAID AKA PERC to smartctl.monitor 768d8b60822973d32194eb11d0b80696dac2cfd5 272783d9a403a327fa231fa5b7ae920ffba9ea00 Russell Coker 1623049094 +1000 commit: Added support for NVMe devices 272783d9a403a327fa231fa5b7ae920ffba9ea00 fa9fc8a4db33a599df288caea8d7e8d00168ee42 Russell Coker 1629787806 +1000 commit: changes for 1.3.5-7 fa9fc8a4db33a599df288caea8d7e8d00168ee42 30aa75487050bafd225a0cf86f3240f65866788e Russell Coker 1636338466 +1100 commit: Add selinux.monitor 30aa75487050bafd225a0cf86f3240f65866788e 2958412fd501485284fea3c53bf14d899abcbdb2 Russell Coker 1642284762 +1100 commit: Give clearer messages when host has multiple IP addresses 2958412fd501485284fea3c53bf14d899abcbdb2 17d750964f9b45902981abc273458589467bbb65 Russell Coker 1642285177 +1100 commit: NMU from Adrian Bunk with patch from Aurelien Jarno to fix rpc.monitor build error with latest glibc 17d750964f9b45902981abc273458589467bbb65 e6538f64e5aae15d3d02fa251cc1a15bbee4f5ed Russell Coker 1642930276 +1100 commit: Wrapper for hp-temp monitor to run as root e6538f64e5aae15d3d02fa251cc1a15bbee4f5ed 152ed6e16d4e722a25e79f16a22a63b67710ffea Russell Coker 1642930638 +1100 commit: Allow stderr fromhplog and give count of good sensors 152ed6e16d4e722a25e79f16a22a63b67710ffea 1f50fc38d18c0019824e7171de99056017f1949c Russell Coker 1642930743 +1100 commit: Add wrapper for hp-temp 1f50fc38d18c0019824e7171de99056017f1949c 125f7b87dfafde72f3ea62f73612c3586ebee2fd Russell Coker 1642930819 +1100 commit: Add changelog for sslcert and hp-temp 125f7b87dfafde72f3ea62f73612c3586ebee2fd e99ea4b5157a8e6714c9bcc94dcba0582bf861b2 Russell Coker 1642930966 +1100 commit: . e99ea4b5157a8e6714c9bcc94dcba0582bf861b2 fc9ff3c3b5f14a27b89eca2612e4b27c99d97b19 Russell Coker 1642931237 +1100 commit: Use helper just for hplog fc9ff3c3b5f14a27b89eca2612e4b27c99d97b19 89e4a200f02bffeb3a0e000693a5ac5acc4fe9fd Russell Coker 1642931282 +1100 commit: Don't wrap the entire monitor 89e4a200f02bffeb3a0e000693a5ac5acc4fe9fd 02e805e77a210fb2be47aa464e8eb59d7b04c6b6 Russell Coker 1642931422 +1100 commit: Run /sbin/hplog -t 02e805e77a210fb2be47aa464e8eb59d7b04c6b6 2d5df83844a760095485423528a03b46e5d16853 Russell Coker 1642931459 +1100 commit: Add hplog.helper 2d5df83844a760095485423528a03b46e5d16853 c17388523f58e38bfd7a7a7f1e5810433b6e5f10 Russell Coker 1642931517 +1100 commit: Changed hp-temp wrapper to just wrap hplog c17388523f58e38bfd7a7a7f1e5810433b6e5f10 e9089836b6c2adbd8a9a94dc929b32eb31b636ca Russell Coker 1642931730 +1100 commit: correct file name e9089836b6c2adbd8a9a94dc929b32eb31b636ca 97582886694bffb4f08be8193edfb5d4d73516d3 Russell Coker 1642932415 +1100 commit: Fix name of hp-temp.monitor 97582886694bffb4f08be8193edfb5d4d73516d3 996c53aaa2a2023967fdea688ad7d55438311594 Russell Coker 1642933425 +1100 commit: need to call setgid(0) and setuid(0) 996c53aaa2a2023967fdea688ad7d55438311594 dac44bdb8fc19269c76e3bc1954bcb60f0050782 Russell Coker 1642933640 +1100 commit: Run the wrapper dac44bdb8fc19269c76e3bc1954bcb60f0050782 e99e5d583b897f72b15cd562b9682b56180c05d6 Russell Coker 1643281743 +1100 commit: Add -x option to find out what name Proc::ProcessTable thinks a process has e99e5d583b897f72b15cd562b9682b56180c05d6 bd21b92c34606f1ca903231bb9f8c079dbd48e19 Russell Coker 1643281804 +1100 commit: Monitor Dell server temperature via "omreport chassis temps" bd21b92c34606f1ca903231bb9f8c079dbd48e19 cc9e5288ed982c4277f41a38246b96d7226e24db Russell Coker 1643281867 +1100 commit: Notes for dell-temp.monitor and ps.monitor cc9e5288ed982c4277f41a38246b96d7226e24db b7f6e08f147adb53971c83056cb1ad4c29aa622f Russell Coker 1644319749 +1100 commit: Fixes for linux-temp and update changelog etbemon-1.3.6/.git/logs/refs/0000755000000000000000000000000013617253434012614 5ustar etbemon-1.3.6/.git/logs/refs/heads/0000755000000000000000000000000013212006100013651 5ustar etbemon-1.3.6/.git/logs/refs/heads/master0000644000000000000000000006573514200452020015113 0ustar 0000000000000000000000000000000000000000 edff5c0a55e12219a438c1e67f6feff4c0ba754e Russell Coker 1512574016 +1100 initial pull edff5c0a55e12219a438c1e67f6feff4c0ba754e a1e18032c138a2af26d3b779904669728f8f6c1d Russell Coker 1512574289 +1100 commit: Move template out of alert.d directory a1e18032c138a2af26d3b779904669728f8f6c1d e5e22e35547169888b18bbd338809622fda184e7 Russell Coker 1512574316 +1100 commit: Don't use /tmp for security reasons e5e22e35547169888b18bbd338809622fda184e7 7b1d76289a3b1ee985575025a089de0f22ac19f4 Russell Coker 1512574347 +1100 commit: Longer summary length as we are already over 80 chars 7b1d76289a3b1ee985575025a089de0f22ac19f4 09cfd68e63c68a01a14ed2b14ec7552c3af6ddea Russell Coker 1512574378 +1100 commit: All the latest changes. 09cfd68e63c68a01a14ed2b14ec7552c3af6ddea 449fee8993c375739f31ddd58d9b78de642c8ad6 Russell Coker 1512574401 +1100 commit: Depend on latest debhelper 449fee8993c375739f31ddd58d9b78de642c8ad6 f688c7c9a2d447bf3dd23557f38797df93bc9bd0 Russell Coker 1512574414 +1100 commit: Team maintenance and recommend more packages that monitors need f688c7c9a2d447bf3dd23557f38797df93bc9bd0 4cd5209313a5eb3cabfd56769e684181dae3915a Russell Coker 1512574487 +1100 commit: don't use debian/docs 4cd5209313a5eb3cabfd56769e684181dae3915a 493cc6ff7fd9e812f7fc01a10bd9782459f0a0a4 Russell Coker 1512574576 +1100 commit: Move auth.cf to etc 493cc6ff7fd9e812f7fc01a10bd9782459f0a0a4 f3f3a1fde8a41fee3a92dec0b0033fe6d4d087f9 Russell Coker 1512574677 +1100 commit: Add mon-local.d dir and add more example entries f3f3a1fde8a41fee3a92dec0b0033fe6d4d087f9 5c0c29ebb2f40feccfead2e2cd4d213d92520e05 Russell Coker 1512574705 +1100 commit: Move mon.cf to etc 5c0c29ebb2f40feccfead2e2cd4d213d92520e05 c65949adfc1f5c0f9cd6e3aa8d28b9d3174b1ae4 Russell Coker 1512574740 +1100 commit: Move monshowrc to etc dir c65949adfc1f5c0f9cd6e3aa8d28b9d3174b1ae4 8e27d13fb510bf6026bcd89f8de5de754dbabcdf Russell Coker 1512574766 +1100 commit: Remove most entries, lets use /etc/mon/mon.cf for it 8e27d13fb510bf6026bcd89f8de5de754dbabcdf 4eba223718103fb1a00c53970395192b82086e0d Russell Coker 1512574794 +1100 commit: Add alert.template to the docs 4eba223718103fb1a00c53970395192b82086e0d eaf3d06d92649f3dbc0fa089780f6a7c71c5fd73 Russell Coker 1512574816 +1100 commit: Add mon/bin and mon-local.d to the list of dirs eaf3d06d92649f3dbc0fa089780f6a7c71c5fd73 add1baa61ed261f183e4bdfc420386a8552436b8 Russell Coker 1512574881 +1100 commit: Use /run instead of /var/run add1baa61ed261f183e4bdfc420386a8552436b8 e2c3d659c68dfbe43b7dca832f165c5a890b4e2c Russell Coker 1512574909 +1100 commit: Move the init.d script out of the debian dir e2c3d659c68dfbe43b7dca832f165c5a890b4e2c 0190f7a73b3f02dc58ed35a822335aa82b8ef951 Russell Coker 1512574944 +1100 commit: Mostly move stuff out of the debian dir if it's not specific to debian. 0190f7a73b3f02dc58ed35a822335aa82b8ef951 c3a1a4c6931a558f8bf568f01943dec936bd9ea4 Russell Coker 1512575097 +1100 commit: Use /run instead of /var/run and add systemd support c3a1a4c6931a558f8bf568f01943dec936bd9ea4 386e4135b696a8c98b533e7aebe59835a2257a49 Russell Coker 1512575372 +1100 commit: Remove patches that are now upstream 386e4135b696a8c98b533e7aebe59835a2257a49 923928bf7bdf205fb61ae07b96fea5592407aeba Russell Coker 1512575405 +1100 commit: Systemd support and adding mon/bin and mon-local.d directories 923928bf7bdf205fb61ae07b96fea5592407aeba 5d25d4af602422e6c0b1b24602379293f9af9d59 Russell Coker 1512575434 +1100 commit: Format 1.0 as now we are mostly Debian as upstream 5d25d4af602422e6c0b1b24602379293f9af9d59 88e4706986de4700b35da9939f438ef421d4a4cb Russell Coker 1512575467 +1100 commit: Use /run instead of /var/run and escape - 88e4706986de4700b35da9939f438ef421d4a4cb ed018480f8da3ddf767d02408e06ec92306e993c Russell Coker 1512575505 +1100 commit: Escape - ed018480f8da3ddf767d02408e06ec92306e993c c628bdf15a5a7ca83fbc2c01f2c3963773624484 Russell Coker 1512575544 +1100 commit: Remove old init.d script c628bdf15a5a7ca83fbc2c01f2c3963773624484 830c0c53dd67d6ed186fc46118a638ce37113937 Russell Coker 1512575571 +1100 commit: Use /run instead of /var/run and added @args to avoid warning (I think) 830c0c53dd67d6ed186fc46118a638ce37113937 ba9a48c417f675e3e142cb3e96c15a29817235b1 Russell Coker 1512575670 +1100 commit: Better handle Debian build flags, may not be ideal for non-Debian systems ba9a48c417f675e3e142cb3e96c15a29817235b1 647b98c6889c07512a091eaa661ae6744b1c7cf2 Russell Coker 1512575832 +1100 commit: use Mon::SNMP instead of use SNMP 647b98c6889c07512a091eaa661ae6744b1c7cf2 07952177f7360e52f6ea0a096cdaf68e01722291 Russell Coker 1512575885 +1100 commit: Give a better summary 07952177f7360e52f6ea0a096cdaf68e01722291 35c9bb9a2364c458cb453b17d8484600bf0b8ad6 Russell Coker 1512575969 +1100 commit: Use Filesys::Df instead of Filesys::DiskSpace. 35c9bb9a2364c458cb453b17d8484600bf0b8ad6 dc8d16f3360e1ef50c57e78164ba6331cc178f3c Russell Coker 1512576055 +1100 commit: Move local test for freespace to mon-local.d dc8d16f3360e1ef50c57e78164ba6331cc178f3c 728e78d877145a709f4bb4a0e2c0f10ec2002b1e Russell Coker 1512576180 +1100 commit: Add new local monitors: 728e78d877145a709f4bb4a0e2c0f10ec2002b1e a1741ec392f52e8482b466d515e94ab2f416c64a Russell Coker 1512576363 +1100 commit: Add ps.monitor from contrib and added some new features to it, including a1741ec392f52e8482b466d515e94ab2f416c64a 88d7929b8a96cb1015b1484c226b1dcc9b2eeda7 Russell Coker 1512576417 +1100 commit: Make it work with strict 88d7929b8a96cb1015b1484c226b1dcc9b2eeda7 657d6928fc1f47547ceb50eb8466c69700140e65 Russell Coker 1512576482 +1100 commit: Add support for reading a password from a file so "ps" won't show passwords 657d6928fc1f47547ceb50eb8466c69700140e65 3e6c6138934c34157393749fe3154e3a409f4bda Russell Coker 1512576514 +1100 commit: Support specifying the ping count and also ping6 3e6c6138934c34157393749fe3154e3a409f4bda 9f8922d3a44e1b5662d1e8aae6286a74efb63834 Russell Coker 1512576624 +1100 commit: Use ||= for options in case they were already set and comment that a config 9f8922d3a44e1b5662d1e8aae6286a74efb63834 85fc461036a20c9b5e067996ab22d55f6552c165 Russell Coker 1513758919 +1100 commit: Add all monitors to git 85fc461036a20c9b5e067996ab22d55f6552c165 d01ff140845ab3c2b4c6dfb08bfe3e8afbcc044d Russell Coker 1513759375 +1100 commit: Track all source d01ff140845ab3c2b4c6dfb08bfe3e8afbcc044d 9864be268f4d50301a4f07bc46d3cd253ee7571f Russell Coker 1513759427 +1100 commit: Document change to smtpswaks 9864be268f4d50301a4f07bc46d3cd253ee7571f 0f8d9b329e1a7b9617600b86ae3072a8ec30102d Russell Coker 1514651290 +1100 commit: add setrlimit 0f8d9b329e1a7b9617600b86ae3072a8ec30102d bda92a000b71fa6ff999d1740786cb8a752d7e1c Russell Coker 1514651378 +1100 commit: Changelog for cpu limit in mailxmpp bda92a000b71fa6ff999d1740786cb8a752d7e1c d7a449dc5d0ce269c60cc4f97a0eeccff6c30a9b Russell Coker 1520415694 +1100 commit: Changelog change for release d7a449dc5d0ce269c60cc4f97a0eeccff6c30a9b b7d86251b4eb905297716b714db403b8943d07f3 Russell Coker 1520415746 +1100 pull: Merge made by the 'recursive' strategy. b7d86251b4eb905297716b714db403b8943d07f3 ce6b487922391b6b20f983f7425a190ec765f277 Russell Coker 1526449793 +1000 commit: Add -s option to select whether HTTPS SNI should be used (default yes for port ce6b487922391b6b20f983f7425a190ec765f277 c90c6735aeaa2f3a92b2ff1413f162f081c8aa28 Russell Coker 1526451500 +1000 commit: New upstream release and SNI support in sslcert.monitor c90c6735aeaa2f3a92b2ff1413f162f081c8aa28 9e0f07aaa81c402bf9484aab3b69cd9561d3d095 Russell Coker 1527937880 +1000 commit: Check Received: headers for long delays and clock skew 9e0f07aaa81c402bf9484aab3b69cd9561d3d095 67279e76648973b6ee1a34237789ad449dfdc30d Russell Coker 1528027024 +1000 commit: Correctly handle Received dates, From: date, and delivery date. 67279e76648973b6ee1a34237789ad449dfdc30d 5677b5d053268185f89b9ef5492c99ad312fa378 Russell Coker 1529989536 +1000 commit: Removed defined() around hash and array checks, not supported in recent perl 5677b5d053268185f89b9ef5492c99ad312fa378 505666380f4b81f34633dd674318cd1aca3d3ab1 Russell Coker 1529990188 +1000 commit: Don't abort mon.cgi when $ONDS{$group} is invalid 505666380f4b81f34633dd674318cd1aca3d3ab1 e8cc468b8b8f51612618072cd89ed9bb4a8e9061 Russell Coker 1532224189 +1000 commit: Make loadavg report the system memory use e8cc468b8b8f51612618072cd89ed9bb4a8e9061 288ac0693d5a98232225271d0eb366f21cf1e3d4 Russell Coker 1532309265 +1000 commit: Change btrfs.monitor to use SUID helper instead of sudo and to check subvols too 288ac0693d5a98232225271d0eb366f21cf1e3d4 6f8fa3ee313997acbc2833b4270db9311ff9a174 Russell Coker 1532310164 +1000 commit: New SETUID helper programs. 6f8fa3ee313997acbc2833b4270db9311ff9a174 7cb07655c51a51d6e983ee3239df3125d6248457 Russell Coker 1532323500 +1000 commit: Change timestamp for release 7cb07655c51a51d6e983ee3239df3125d6248457 09d86464189786f3c22977483740528af6125746 Russell Coker 1535983553 +1000 commit: Correctly display summary when multiple -query parameters are used for 09d86464189786f3c22977483740528af6125746 4ea7f0847c0d284b9c37b9137dcdd3a89eda8903 Russell Coker 1555314438 +1000 commit: Link btrfs.helper with gcc not g++ to reduce dependencies. 4ea7f0847c0d284b9c37b9137dcdd3a89eda8903 6e6ca61eb80f177d264dab5897b29aa56c437acc Russell Coker 1555315024 +1000 commit: Remove old helper 6e6ca61eb80f177d264dab5897b29aa56c437acc c056baed2021c98f6e25baf371991ee08183bb98 Russell Coker 1555315119 +1000 commit: Remove btrfs.helper c056baed2021c98f6e25baf371991ee08183bb98 b0ad8088017fb4f368311b58bc2721eaef048205 Russell Coker 1555315158 +1000 commit: rm -f for make clean b0ad8088017fb4f368311b58bc2721eaef048205 7e738f94bf2198f4f03555c71529499c8feda7dc Russell Coker 1555315528 +1000 commit: Fixed some lintian warnings 7e738f94bf2198f4f03555c71529499c8feda7dc 28f76562bf30f8a8f297ea3bab10f3c3487c2231 Russell Coker 1555505417 +1000 commit: Make traps work properly and document them better 28f76562bf30f8a8f297ea3bab10f3c3487c2231 32dd660a2474d15616efdce73984e5a8f6668a68 Russell Coker 1555505447 +1000 commit: Make imapnew.monitor log Message-Id and expunge messages even when there is a 32dd660a2474d15616efdce73984e5a8f6668a68 d17497502e75a67badbedb3b763723a4679e277b Russell Coker 1555505954 +1000 commit: Make it compile the helper programs d17497502e75a67badbedb3b763723a4679e277b d1cc17481f430389aa68fd21df03a8b1da3c860d Russell Coker 1555507386 +1000 commit: Fix count files in btrfs.monitor d1cc17481f430389aa68fd21df03a8b1da3c860d 290672f616a9ccbc7fdd4c2c3fbc415536a6b47f Russell Coker 1555507483 +1000 commit: Removed printf debugging 290672f616a9ccbc7fdd4c2c3fbc415536a6b47f c896d5b94b943a445f4a7278400064b7917e9a1e Russell Coker 1556620734 +1000 commit: Added bug close line c896d5b94b943a445f4a7278400064b7917e9a1e e0679f570f96c298a614696320e4421023f9d8e5 Russell Coker 1556622627 +1000 commit: Make trapbind default to 127.0.0.1 and also add comments e0679f570f96c298a614696320e4421023f9d8e5 55bd4d3d805850c8c2615bd093aa95721bcde4d8 Russell Coker 1556622862 +1000 commit: Fix example config 55bd4d3d805850c8c2615bd093aa95721bcde4d8 92d5cd4d316e90d208009f1c32e4b5dd2f3d4ee3 Russell Coker 1563401501 +1000 commit: Give a better summary line and also show top CPU use 92d5cd4d316e90d208009f1c32e4b5dd2f3d4ee3 89827b77052234730b4ab596ea5208df14b44f24 Russell Coker 1563401541 +1000 commit: Check swap+RAM use as well as load average 89827b77052234730b4ab596ea5208df14b44f24 a8f1b467ba15868e97e1b1780782888d3624b571 Russell Coker 1563401810 +1000 commit: Better log entries on authfile auth failure a8f1b467ba15868e97e1b1780782888d3624b571 857ccb2300c408cc175ad069b725a1b04641a0f4 Russell Coker 1563401884 +1000 commit: Latest changes 857ccb2300c408cc175ad069b725a1b04641a0f4 e6827ce66bdde0e283fc2b25835a892994565628 Russell Coker 1563583023 +1000 commit: Consolidated help e6827ce66bdde0e283fc2b25835a892994565628 605322154fa8534b3f15bbf0345fd67f3cfc7c03 Russell Coker 1563583124 +1000 commit: Changelog for remote.monitor 605322154fa8534b3f15bbf0345fd67f3cfc7c03 1636b2fbb87141699761afd436d66fab10e5efc8 Russell Coker 1578290600 +1100 commit: Add check for deleted but mapped files (for shared object upgrades). 1636b2fbb87141699761afd436d66fab10e5efc8 6c828acd2eb68a128016cbc86858ade26fa55972 Russell Coker 1578290656 +1100 commit: Fix date 6c828acd2eb68a128016cbc86858ade26fa55972 f6a5709fe3f600d4bdb842acaaec7b8b0296d440 Russell Coker 1578301273 +1100 commit: Use SUID root binary for zfs f6a5709fe3f600d4bdb842acaaec7b8b0296d440 bf157a8f53bf9eee483860f8638a3c621cea597c Russell Coker 1578301294 +1100 commit: SUID root helper for zfs bf157a8f53bf9eee483860f8638a3c621cea597c 58559086c0c915d6b5a6a1d9ade463f92be211ad Russell Coker 1578301321 +1100 commit: SUID root ZFS helper 58559086c0c915d6b5a6a1d9ade463f92be211ad 25b8ec5cb1f54daa1ca5d5c076cba84da5e54f82 Russell Coker 1578302150 +1100 commit: Ignore /dev/zero for kernel mapping funnyness 25b8ec5cb1f54daa1ca5d5c076cba84da5e54f82 0c2846e653043723a6b4f4aac07610d609813f69 Russell Coker 1578302410 +1100 commit: Use SUID root wrapper for the deleted-mapped.monitor 0c2846e653043723a6b4f4aac07610d609813f69 24a77f6f6dc255703d87f4f2304570f43c037e98 Russell Coker 1578302480 +1100 commit: Fix warning 24a77f6f6dc255703d87f4f2304570f43c037e98 69085d07fbbe726914ee112ded969225c85616e9 Russell Coker 1578302513 +1100 commit: Changes for deleted-mapped suid wrapper 69085d07fbbe726914ee112ded969225c85616e9 06e9fc97e8d45d44f9bbb059720434838bb5779b Russell Coker 1578302559 +1100 commit: make /usr/lib/mon/mon-local.d/deleted-mapped.monitor suid root 06e9fc97e8d45d44f9bbb059720434838bb5779b 3a3045e5148af3a12406580e2b34a62c7e3a2d53 Russell Coker 1578302572 +1100 commit: . 3a3045e5148af3a12406580e2b34a62c7e3a2d53 d002d0f010f6bfba4f36b216ccb5ca1fcdeac453 Russell Coker 1578302951 +1100 commit: Make it install the real file for deleted shared objects d002d0f010f6bfba4f36b216ccb5ca1fcdeac453 cac8f604f75130f3463b0ac4d39b1aed003c3e85 Russell Coker 1578302981 +1100 commit: build and clean in mon-local.d cac8f604f75130f3463b0ac4d39b1aed003c3e85 17ccc5ed3092d64f9b562960076c7c7b29b025b5 Russell Coker 1578303493 +1100 commit: New release with fixes for the deleted mapped checks 17ccc5ed3092d64f9b562960076c7c7b29b025b5 3737e98a14ec0f6d6aae58eddd5774bad355e5f7 Russell Coker 1580627698 +1100 commit: Update standars version and changelog for 1.3.4 3737e98a14ec0f6d6aae58eddd5774bad355e5f7 98121f0a11b3316c0a4851eaba33e094d47f1f41 Russell Coker 1580627768 +1100 commit: Lots of changes, make it release worthy 98121f0a11b3316c0a4851eaba33e094d47f1f41 2519672ad87bab46eb2fb528f4e18b2427d95842 Russell Coker 1581078235 +1100 pull: Fast-forward 2519672ad87bab46eb2fb528f4e18b2427d95842 7b9d5955ce7cb2ce01694c605e083ba4ef2789c0 Russell Coker 1586043748 +1000 commit: Make it work with latest swaks 7b9d5955ce7cb2ce01694c605e083ba4ef2789c0 828cb88adc26dbebf3e8091b372969a9f24a1867 Russell Coker 1587985323 +1000 commit: ignore useless errors from sensors 828cb88adc26dbebf3e8091b372969a9f24a1867 4ef11c843fbd34efe1224c08d5e56f756a6cbb2e Russell Coker 1590026390 +1000 commit: Made smtpswaks.monitor take a service port 4ef11c843fbd34efe1224c08d5e56f756a6cbb2e 28b6be2de5ed12a9724543ef59c3cb215dce5f7a Russell Coker 1590822795 +1000 commit: add authfile to config 28b6be2de5ed12a9724543ef59c3cb215dce5f7a 3c0e27a3730a1f84a5fb89d6e728063bcc4b03d9 Russell Coker 1591589973 +1000 commit: Change some of the filesystem code as a first step to making it work on Windows 3c0e27a3730a1f84a5fb89d6e728063bcc4b03d9 690ece4d0dac09654c2d10fb56d0efaf533cdb92 Russell Coker 1592624835 +1000 commit: Alert to Jabber and Slack 690ece4d0dac09654c2d10fb56d0efaf533cdb92 edfa34021dcd925d6025c0af1ca7bce1a72530a1 Russell Coker 1594086752 +1000 commit: Remove duplicate summary messages edfa34021dcd925d6025c0af1ca7bce1a72530a1 8b4db85e7c1aff7aa409cc3cf309c475fc39592c Russell Coker 1600600593 +1000 commit: Some changes needed for rpming latest version 8b4db85e7c1aff7aa409cc3cf309c475fc39592c 877b63657cd545f35bcb5320d802d18454955725 Russell Coker 1600606530 +1000 commit: Don't want this 877b63657cd545f35bcb5320d802d18454955725 77ae771aaad17a51336be907c2cd546ddc3c6419 Russell Coker 1600607019 +1000 commit: Updated rpm build to latest stuff and included systemd support 77ae771aaad17a51336be907c2cd546ddc3c6419 6b121fb45405d2cf85fbbba3cc52f86eb9429bb0 Russell Coker 1600608680 +1000 commit: depend on perl-BSD-Resource and fix some perms 6b121fb45405d2cf85fbbba3cc52f86eb9429bb0 8d41ea69885128aa059caa19126f0fbb02621081 Russell Coker 1600952377 +1000 commit: Reformatted source 8d41ea69885128aa059caa19126f0fbb02621081 5403e1ec14081a801080892bc7f53fa1b79d1129 Russell Coker 1607601843 +1100 commit: Made it do IPv6 and IPv6 checks and check all addresses of each hostname 5403e1ec14081a801080892bc7f53fa1b79d1129 aa63082131613ac3479096ded34822d17422f400 Russell Coker 1607601871 +1100 commit: Changelog for libsys-filesystem-perl and sslcert.monitor and depends for libsys-filesystem-perl aa63082131613ac3479096ded34822d17422f400 ed18213f61204716f1bcd912e3fbb3031e2c8a72 Russell Coker 1607607312 +1100 commit: Add a basic config snippet to git ed18213f61204716f1bcd912e3fbb3031e2c8a72 5ec8aa2a9f437b45b996bd3518655424098a28d0 Russell Coker 1607646663 +1100 commit: Fix for sites that don't have both IPv6 and IPv4 DNS records 5ec8aa2a9f437b45b996bd3518655424098a28d0 2e0f7e1356dd3518bc8e476a3e8a0f97008ab334 Russell Coker 1608422985 +1100 commit: monitor and parse smartctl output 2e0f7e1356dd3518bc8e476a3e8a0f97008ab334 d5080cd0d5d44ce349adef429f7655c7684315be Russell Coker 1608423220 +1100 commit: new upstream ver d5080cd0d5d44ce349adef429f7655c7684315be 235be2efdcbcdb56c0ec0421d29e87bd9bf6ea12 Russell Coker 1608424847 +1100 commit: rename for wrapper 235be2efdcbcdb56c0ec0421d29e87bd9bf6ea12 94cd51c2ee973bca91b106472f253c114b9ba3d1 Russell Coker 1608431751 +1100 commit: Add smartctl helper to run it as root 94cd51c2ee973bca91b106472f253c114b9ba3d1 5998ead72add170e2675f4fe6ff82d7dc6e24266 Russell Coker 1608431976 +1100 commit: Use SUID helper to run smartctl 5998ead72add170e2675f4fe6ff82d7dc6e24266 3751d3a9146a0c74c727509e703a751395b29225 Russell Coker 1608436148 +1100 commit: Set perms on smartctl helper 3751d3a9146a0c74c727509e703a751395b29225 c61da090b5d7e9d83698cc66f0cd2df607297a29 Russell Coker 1608436301 +1100 commit: remove mistake c61da090b5d7e9d83698cc66f0cd2df607297a29 7c56a3b9f602d1fd54afa50af4db11528fb12730 Russell Coker 1608438069 +1100 commit: Better error logging 7c56a3b9f602d1fd54afa50af4db11528fb12730 9871854e10df73ee206a051bbaaec5d168b89d49 Russell Coker 1609883670 +1100 commit: display PSI cgroup2 data in loadavg.monitor output 9871854e10df73ee206a051bbaaec5d168b89d49 da44e2601766ce9676872188ef9c6bc936524c7d Russell Coker 1609883803 +1100 commit: Sample config file for running on Windows da44e2601766ce9676872188ef9c6bc936524c7d 0a3276c29c0b519fcdf7bcea7197e0b66d91b6de Russell Coker 1611039933 +1100 commit: "python3" and "python3.9" support in ps.monitor 0a3276c29c0b519fcdf7bcea7197e0b66d91b6de c378b23cc7ebb2740694e8efc26fd3fbe05f8884 Russell Coker 1611040283 +1100 commit: Don't warn on process exit before map file is opened c378b23cc7ebb2740694e8efc26fd3fbe05f8884 01937364a92cc439993221b2fb9ffc0d3411014c Russell Coker 1613962666 +1100 commit: Make deleted-mapped.monitor avoid checking for systemd processes and have 01937364a92cc439993221b2fb9ffc0d3411014c 3a4af870e64bfc81c3d36cdcec01c4dcd9982589 Russell Coker 1613971105 +1100 commit: Fix changelog for unstable 3a4af870e64bfc81c3d36cdcec01c4dcd9982589 f4363ae6682bb7e4d8662b8ac59ff3d0ec990166 Russell Coker 1617599465 +1000 commit: Handle missing Message-Id correctly f4363ae6682bb7e4d8662b8ac59ff3d0ec990166 840eabed552ed394292cdb75f7edd7933b35af6f Russell Coker 1617599494 +1000 commit: Make the deleted-mapped test not alert on sshd privsep process 840eabed552ed394292cdb75f7edd7933b35af6f 7804c96bbc51a71704a9e1b43b6397aff5677ea6 Russell Coker 1617611377 +1000 commit: made imapnew.monitor do case insensitive header checks 7804c96bbc51a71704a9e1b43b6397aff5677ea6 6dc5dd9dc2c88dc456f324e4ecb677e4a911785b Russell Coker 1621757495 +1000 commit: Better fix for imapnew.monitor 6dc5dd9dc2c88dc456f324e4ecb677e4a911785b e98903c9406f73ac4bd526b8415cebbf936c5816 Russell Coker 1621757575 +1000 commit: Added monitoring for HP server temperature e98903c9406f73ac4bd526b8415cebbf936c5816 768d8b60822973d32194eb11d0b80696dac2cfd5 Russell Coker 1623047674 +1000 commit: Added support for MegaRAID AKA PERC to smartctl.monitor 768d8b60822973d32194eb11d0b80696dac2cfd5 272783d9a403a327fa231fa5b7ae920ffba9ea00 Russell Coker 1623049094 +1000 commit: Added support for NVMe devices 272783d9a403a327fa231fa5b7ae920ffba9ea00 fa9fc8a4db33a599df288caea8d7e8d00168ee42 Russell Coker 1629787806 +1000 commit: changes for 1.3.5-7 fa9fc8a4db33a599df288caea8d7e8d00168ee42 30aa75487050bafd225a0cf86f3240f65866788e Russell Coker 1636338466 +1100 commit: Add selinux.monitor 30aa75487050bafd225a0cf86f3240f65866788e 2958412fd501485284fea3c53bf14d899abcbdb2 Russell Coker 1642284762 +1100 commit: Give clearer messages when host has multiple IP addresses 2958412fd501485284fea3c53bf14d899abcbdb2 17d750964f9b45902981abc273458589467bbb65 Russell Coker 1642285177 +1100 commit: NMU from Adrian Bunk with patch from Aurelien Jarno to fix rpc.monitor build error with latest glibc 17d750964f9b45902981abc273458589467bbb65 e6538f64e5aae15d3d02fa251cc1a15bbee4f5ed Russell Coker 1642930276 +1100 commit: Wrapper for hp-temp monitor to run as root e6538f64e5aae15d3d02fa251cc1a15bbee4f5ed 152ed6e16d4e722a25e79f16a22a63b67710ffea Russell Coker 1642930638 +1100 commit: Allow stderr fromhplog and give count of good sensors 152ed6e16d4e722a25e79f16a22a63b67710ffea 1f50fc38d18c0019824e7171de99056017f1949c Russell Coker 1642930743 +1100 commit: Add wrapper for hp-temp 1f50fc38d18c0019824e7171de99056017f1949c 125f7b87dfafde72f3ea62f73612c3586ebee2fd Russell Coker 1642930819 +1100 commit: Add changelog for sslcert and hp-temp 125f7b87dfafde72f3ea62f73612c3586ebee2fd e99ea4b5157a8e6714c9bcc94dcba0582bf861b2 Russell Coker 1642930966 +1100 commit: . e99ea4b5157a8e6714c9bcc94dcba0582bf861b2 fc9ff3c3b5f14a27b89eca2612e4b27c99d97b19 Russell Coker 1642931237 +1100 commit: Use helper just for hplog fc9ff3c3b5f14a27b89eca2612e4b27c99d97b19 89e4a200f02bffeb3a0e000693a5ac5acc4fe9fd Russell Coker 1642931282 +1100 commit: Don't wrap the entire monitor 89e4a200f02bffeb3a0e000693a5ac5acc4fe9fd 02e805e77a210fb2be47aa464e8eb59d7b04c6b6 Russell Coker 1642931422 +1100 commit: Run /sbin/hplog -t 02e805e77a210fb2be47aa464e8eb59d7b04c6b6 2d5df83844a760095485423528a03b46e5d16853 Russell Coker 1642931459 +1100 commit: Add hplog.helper 2d5df83844a760095485423528a03b46e5d16853 c17388523f58e38bfd7a7a7f1e5810433b6e5f10 Russell Coker 1642931517 +1100 commit: Changed hp-temp wrapper to just wrap hplog c17388523f58e38bfd7a7a7f1e5810433b6e5f10 e9089836b6c2adbd8a9a94dc929b32eb31b636ca Russell Coker 1642931730 +1100 commit: correct file name e9089836b6c2adbd8a9a94dc929b32eb31b636ca 97582886694bffb4f08be8193edfb5d4d73516d3 Russell Coker 1642932415 +1100 commit: Fix name of hp-temp.monitor 97582886694bffb4f08be8193edfb5d4d73516d3 996c53aaa2a2023967fdea688ad7d55438311594 Russell Coker 1642933425 +1100 commit: need to call setgid(0) and setuid(0) 996c53aaa2a2023967fdea688ad7d55438311594 dac44bdb8fc19269c76e3bc1954bcb60f0050782 Russell Coker 1642933640 +1100 commit: Run the wrapper dac44bdb8fc19269c76e3bc1954bcb60f0050782 e99e5d583b897f72b15cd562b9682b56180c05d6 Russell Coker 1643281743 +1100 commit: Add -x option to find out what name Proc::ProcessTable thinks a process has e99e5d583b897f72b15cd562b9682b56180c05d6 bd21b92c34606f1ca903231bb9f8c079dbd48e19 Russell Coker 1643281804 +1100 commit: Monitor Dell server temperature via "omreport chassis temps" bd21b92c34606f1ca903231bb9f8c079dbd48e19 cc9e5288ed982c4277f41a38246b96d7226e24db Russell Coker 1643281867 +1100 commit: Notes for dell-temp.monitor and ps.monitor cc9e5288ed982c4277f41a38246b96d7226e24db b7f6e08f147adb53971c83056cb1ad4c29aa622f Russell Coker 1644319749 +1100 commit: Fixes for linux-temp and update changelog etbemon-1.3.6/.git/logs/refs/remotes/0000755000000000000000000000000013615500633014264 5ustar etbemon-1.3.6/.git/logs/refs/remotes/origin/0000755000000000000000000000000013615500633015553 5ustar etbemon-1.3.6/.git/logs/refs/remotes/origin/master0000644000000000000000000001157314200452026016771 0ustar 0000000000000000000000000000000000000000 98121f0a11b3316c0a4851eaba33e094d47f1f41 Russell Coker 1580630427 +1100 update by push 98121f0a11b3316c0a4851eaba33e094d47f1f41 2519672ad87bab46eb2fb528f4e18b2427d95842 Russell Coker 1581078213 +1100 pull: fast-forward 2519672ad87bab46eb2fb528f4e18b2427d95842 7b9d5955ce7cb2ce01694c605e083ba4ef2789c0 Russell Coker 1586043802 +1000 update by push 7b9d5955ce7cb2ce01694c605e083ba4ef2789c0 4ef11c843fbd34efe1224c08d5e56f756a6cbb2e Russell Coker 1590026462 +1000 update by push 4ef11c843fbd34efe1224c08d5e56f756a6cbb2e aa63082131613ac3479096ded34822d17422f400 Russell Coker 1607601898 +1100 update by push aa63082131613ac3479096ded34822d17422f400 d5080cd0d5d44ce349adef429f7655c7684315be Russell Coker 1608423230 +1100 update by push d5080cd0d5d44ce349adef429f7655c7684315be 3751d3a9146a0c74c727509e703a751395b29225 Russell Coker 1608436168 +1100 update by push 3751d3a9146a0c74c727509e703a751395b29225 c61da090b5d7e9d83698cc66f0cd2df607297a29 Russell Coker 1608436321 +1100 update by push c61da090b5d7e9d83698cc66f0cd2df607297a29 9871854e10df73ee206a051bbaaec5d168b89d49 Russell Coker 1609883747 +1100 update by push 9871854e10df73ee206a051bbaaec5d168b89d49 da44e2601766ce9676872188ef9c6bc936524c7d Russell Coker 1609883817 +1100 update by push da44e2601766ce9676872188ef9c6bc936524c7d 0a3276c29c0b519fcdf7bcea7197e0b66d91b6de Russell Coker 1611039958 +1100 update by push 0a3276c29c0b519fcdf7bcea7197e0b66d91b6de c378b23cc7ebb2740694e8efc26fd3fbe05f8884 Russell Coker 1611040301 +1100 update by push c378b23cc7ebb2740694e8efc26fd3fbe05f8884 01937364a92cc439993221b2fb9ffc0d3411014c Russell Coker 1613962714 +1100 update by push 01937364a92cc439993221b2fb9ffc0d3411014c 3a4af870e64bfc81c3d36cdcec01c4dcd9982589 Russell Coker 1613971118 +1100 update by push 3a4af870e64bfc81c3d36cdcec01c4dcd9982589 840eabed552ed394292cdb75f7edd7933b35af6f Russell Coker 1617599527 +1000 update by push 840eabed552ed394292cdb75f7edd7933b35af6f 7804c96bbc51a71704a9e1b43b6397aff5677ea6 Russell Coker 1617611400 +1000 update by push 7804c96bbc51a71704a9e1b43b6397aff5677ea6 e98903c9406f73ac4bd526b8415cebbf936c5816 Russell Coker 1621760373 +1000 update by push e98903c9406f73ac4bd526b8415cebbf936c5816 768d8b60822973d32194eb11d0b80696dac2cfd5 Russell Coker 1623047699 +1000 update by push 768d8b60822973d32194eb11d0b80696dac2cfd5 272783d9a403a327fa231fa5b7ae920ffba9ea00 Russell Coker 1623049106 +1000 update by push 272783d9a403a327fa231fa5b7ae920ffba9ea00 fa9fc8a4db33a599df288caea8d7e8d00168ee42 Russell Coker 1629958108 +1000 update by push fa9fc8a4db33a599df288caea8d7e8d00168ee42 30aa75487050bafd225a0cf86f3240f65866788e Russell Coker 1636339549 +1100 update by push 30aa75487050bafd225a0cf86f3240f65866788e 17d750964f9b45902981abc273458589467bbb65 Russell Coker 1642285273 +1100 update by push 17d750964f9b45902981abc273458589467bbb65 e6538f64e5aae15d3d02fa251cc1a15bbee4f5ed Russell Coker 1642930399 +1100 update by push e6538f64e5aae15d3d02fa251cc1a15bbee4f5ed 152ed6e16d4e722a25e79f16a22a63b67710ffea Russell Coker 1642930664 +1100 update by push 152ed6e16d4e722a25e79f16a22a63b67710ffea 125f7b87dfafde72f3ea62f73612c3586ebee2fd Russell Coker 1642930916 +1100 update by push 125f7b87dfafde72f3ea62f73612c3586ebee2fd e99ea4b5157a8e6714c9bcc94dcba0582bf861b2 Russell Coker 1642930975 +1100 update by push e99ea4b5157a8e6714c9bcc94dcba0582bf861b2 c17388523f58e38bfd7a7a7f1e5810433b6e5f10 Russell Coker 1642931545 +1100 update by push c17388523f58e38bfd7a7a7f1e5810433b6e5f10 e9089836b6c2adbd8a9a94dc929b32eb31b636ca Russell Coker 1642931746 +1100 update by push e9089836b6c2adbd8a9a94dc929b32eb31b636ca 996c53aaa2a2023967fdea688ad7d55438311594 Russell Coker 1642933453 +1100 update by push 996c53aaa2a2023967fdea688ad7d55438311594 dac44bdb8fc19269c76e3bc1954bcb60f0050782 Russell Coker 1642933655 +1100 update by push dac44bdb8fc19269c76e3bc1954bcb60f0050782 e99e5d583b897f72b15cd562b9682b56180c05d6 Russell Coker 1643281773 +1100 update by push e99e5d583b897f72b15cd562b9682b56180c05d6 cc9e5288ed982c4277f41a38246b96d7226e24db Russell Coker 1643281890 +1100 update by push cc9e5288ed982c4277f41a38246b96d7226e24db b7f6e08f147adb53971c83056cb1ad4c29aa622f Russell Coker 1644319766 +1100 update by push etbemon-1.3.6/.git/objects/0000755000000000000000000000000014200452020012317 5ustar etbemon-1.3.6/.git/objects/00/0000755000000000000000000000000014173226610012553 5ustar etbemon-1.3.6/.git/objects/00/25b1b178502c8c67d92cf16fd740023ebbc13e0000444000000000000000000000067214173226610017674 0ustar x+)JMU057d040031QMNMIe8;?nN|:/wrq7jMMJҊr2KĿ2sIt#A KII-IMM,(HMK.(`uy&؟jRtW8t&0j=R-77- T= ZEK|{3 tKRs J[3-Pw̲2fӝ UWZz*nM|"zGx̴SX78몣sbm6 V?3c>|*-@C FIo{=>um>TUq*pezrp)ݬK5)M,*I.ɁMPelUYui ޼O+)J̄G kr>YjTmRl 0(*)s^5LӐዊY T^etbemon-1.3.6/.git/objects/00/548de8ee0ad61df0d2441f4e7c8ca19febd90a0000444000000000000000000000141513767516617020310 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3fS7SkԞ9j*.&d3<`JmSkrUԤȦ$33y^N[j[Po1t6P5~U)r:`|>@% .3rVܵMB.%pvLl鄧oCNlq^v`/TEe10>R: ., dZ+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35ݢ{%\\q7tW)Iy {+dO, A'3yG\ N,^ܵsyմsg;?;A(*(a`pޖlҏVmr1(.cڿeK'<}rbk{!*JK2s%A{Bԓ9-I-netbemon-1.3.6/.git/objects/00/cfae76dbb5874eafe513b489c54222602c39440000444000000000000000000000132613212012553017703 0ustar x+)JMU0`040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35ݢ{%\\q7tW)Iy [x^RQosIϸwҧ@'3<t,/<O%D6$e{]$b QQ\ I=lǴ˖Nx1l BTd3Kv'sZ,d-+2<o/>etbemon-1.3.6/.git/objects/01/0000755000000000000000000000000014014616716012560 5ustar etbemon-1.3.6/.git/objects/01/15cf89a90026e3c7e8b462e4ece570bb20fbbd0000444000000000000000000000630213514461057020126 0ustar xZmsWW!:'e:ʹ,Wx4dUG5xg_޳w8J4|=w/,=JQ7tLp;tbLE;{4szǣNIIJT%N?T,3dI"! *Is'/d<1`<\vpı HhjQYOerOz!^jsR*ʖ&1Xcg@M]qm>6v#%悠yC[9"OǦ ?+(w(>g?ʾiL}`c`x*U46h ɢק @65nO#f> Qh芿!h'Hy8).c8:4$!d4fo*zT)œ!Z8RK-#EEp p Ma^=I)Ҏ#ʰsYEF%KEz4ROI@{ s$ITLxro\ey`d+5 g!t6+םC-y((NKrR3Ӽ$~UetTN?^\_^n2qT#^h3]ٹ8q1<ͺB:҅T$00'4YAUA4ȃ> yFg^i,PiO`j.<9$cu2K*)?.eAۋ>OPɣEO˽-LER^x2GR{p?~omR~d4X*+HpY))hoz,(/KThL1neFgbbB柨8c/Aӌ?1q c?L4U=O]eI|^B5 (niElǚԮ+weg{h.+γb{c kO:T7;]ۧ2cB;k&BhGԭ6:m"m6srR3QZ5\~m* sG}~qb;%ld*eQa ̤G<ͿY u ^gOV*:Oڼ#",_B pD5H[gJ(9NK^^ l)0[wAu~{ xdpx*T O$S;,>[J>pEC_zyjX=~EaaM% v?\_^^|>]k>siOGFNj2t&L)F[DZ#BSI-ΞOv7VݪlZ1Lw`OٓDq"?o3w%ijקsҢՄ;`@wa$ypŦ&"[pV `k1j~wqGw?F\5o!DBUe<=;YI#!-J%K갖ȳM뵇r@xMe<#?A^: ?ܬ0Ƀ6C "N"Hrwz4.զt=E-Cr^4osWL˵_J{C+*n>rT<"Ȍlc#+&pȔ=>1nYĸ[,<ݨ[Q$ُm-g"g빢l}6!^pUr˛u`[>\mgCB%;GxwJ͡W*^M8lwMйA%SZv fKP ӔP@̌F:Z&ߥE϶hԪS]|n&}0*:ٔA8dAn.%jt47e.hEu)j60kɿKEW ]Y[{jK58$/@|O3u†tHfy%^N%tky0U]LYڅq+*]i7z9uf֦?J OPs4ZrA J3 r5Oҧ~w_CU9`)|4 GKm/mh"U_q'&:`6?bZ0ԲUs,|'W4ꕊvN۬JM'r[jv '?֑fV(続0 zw9FY[9luѣoY?f{L.E(ܖQJumW1*+K2ABmVϿ_3 ^tcLNjY;$]aX9UvHۦ!oI.nQǷAr,x.oZA- amGNn;6ZHed+\L`>/1޽K._˱V z /UuA)Wd)H6Mv:>L7~Kx 0Y""}#܊3=Tוti`VYp q8U7r6[(T1W&]mnW3aV6M{HrR :m|hr;vQ{ F6./vН 48nU\'8kmO@΁к ;/pLJJ;hDZV*H+ =8mQVMrx,F8$J;E=G٫. HʪL5/Ct!6do|SӾ]f̡;LP++:e - ~ӍSG5dfn wetbemon-1.3.6/.git/objects/01/85fcc9671733a19e957d0d2c60a9b497e8d3240000444000000000000000000000141613604575712017605 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d`|z3שܩ5jϜS 5yBds2SJm0] )5*DEJjRfbC~PZMaoW,*Of6>۔+_{ljI2k?d}}Ƕ'ڡcw+ <../HD3PV7'?91[dX^(1qb~@m~] %*IO„椔XiTe?4&38xrUΝ5er{[NJ?Z}I@{؎i-cȉ- خ셪,G [CA܅/t$/ ވ7(‰'jLWZ4r+զ<}ÓEhM9aK[)27:joԔt >FV?k%cBo)Ϝ+|I_k @4r:j!$ şJХY c%?ea[_oetbemon-1.3.6/.git/objects/01/937364a92cc439993221b2fb9ffc0d3411014c0000444000000000000000000000035414014616716017467 0ustar xJ0E])f%?mn`Ҧ)moo{w.g8ܐS o S/1hƖnZYID瘵Bw6!< o-;C$]tε2>e<5>؄<@YeZWJJQjY*?^@pazHmLMT^DF~A(=J0B) >^+ϥ]#~!metbemon-1.3.6/.git/objects/02/0000755000000000000000000000000014173222351012553 5ustar etbemon-1.3.6/.git/objects/02/cdeff3468536115f3aeaf8717f9055c3c7b5c50000444000000000000000000000141513764422020020003 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3fS7SkԞ9j*.&d3<`JmSkrUԤ<kN-MrEBw[ MO=6eW"Z K3s{:m[oAйkNڐC+1nxoH( ſd$0/.iU4\PuG^{-^k-{`֯ p1z t>|}Rt|P3J+ J\f,g4ۭk\!*K /q O8⼀Z^b`|05tz]XȔyL%9 ÿ=!ɜ$Y :Setbemon-1.3.6/.git/objects/02/d1d4c2aff6df5382faf8da43588d14661cd2c40000444000000000000000000000126713212007456020136 0ustar x+)JMU073`040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35ݢ{%\\q7tW)Iy *SVY=A_ btm#W M-If86ҩ _|eˠc4 ?{m(-ߧo( ~.ygLYLX  2>N,^ܵsyմsg;?;A(*(a`pޖlҏVmr1(.cڿeK'<}rbk{!*JK2s%A{Bԓ9-I-0etbemon-1.3.6/.git/objects/02/e805e77a210fb2be47aa464e8eb59d7b04c6b60000444000000000000000000000025114173222351020042 0ustar x[ 0E*_GDwL҉m#i+@?ˁ4=+KZD@ZS0jOqC ]Po.2W886 MHIeDrq[tI( uYd_R\~x_lb^/;gjg FT۱UW:q x>M4etbemon-1.3.6/.git/objects/02/f6800c9ba9efc3923324d36bb2329b387d62930000444000000000000000000000277013661360226017567 0ustar xVasFWWlNCpFr)Fq3aNT'f\!3iq{IW^}_꼿ybZ.rݤL"5m,Z Mb-(ɢ0u}"_^/7pF)ux-FxtH_?ke*U2 oGvY7k$6xGeJL"lU0 JIu]%$"U܆&b&~9:ɮ{+WfuA$IBh>a!bZn/{8 )GEJ!&vyեU.a~-Td- ٲa"@,٪ sBHqPEJ&uǠ2S%p_*TY -t%e,׉LeUӍ;&Ʋkv1@\m)ML^w), Djތ,(g9 !V m7c~&=?`Pĕ1{Y$^BM1MDo1*KE%qf2C= PYtc^\Ci[vsXb@,7%yK7N]ZN w[ܟcj8 ]y@if'L?K/s],hMl>\lz؛Hxg^`F*VX:s) >tLdCsi~g ;'>ʸg4GY Z: ײ9LƳ{wlrb nۉ]u9s1?f<Sqͦd<>] ov{rΠ=E ĩaImAv5:v УNeo\0ǭeiʧ:J閾 3J>o88G-j寣Ψ}9轺So&|2*.xk uYe{kl eWuO"kP]/UAq^l1OUřr}o7&ܦNTnl?%eAV.¸A QVlJոlziy" a*ChM@Sޑ';7 4aYvqX֫Fѡ=Bz>ag;u1"RwjIl]1M"vhoeQ(JỤȕ1+/W׏ZVjb1JX4n?7e\㾳s14W{{@K|{hZ |u&ceƒsF83rX&-|!Ë K6DZӱ{G9;U{kSg[g_>2bG5CocQMHA>Rv_SW9+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d`|z3שܩ5jϜS 5yBds2SJm0] )5*DEJjRfbC~PZMaoW,*Of6>۔+_{ljI2k?d}}Ƕ'ڡcw+ <../HD3PV7'?91# {obAIT\Pq'aBsR,k4|2W@c Rxe|Xbkiv vQZTP2c9˽-n>]$b QQ\ g=lǴ˖Nx1l BUT# B@}5c (-)f QOX&ZWdxϒUUetbemon-1.3.6/.git/objects/03/740a52b1ef58552f6c8109e925ad9fa9018df60000444000000000000000000000036413324761275017660 0ustar x+)JMU04c040075UH*)J+,/b( 6+4nWI*Lj,.HLN+fOs?ƍ)b6LUWZ[[WdA+=gH/=uOLI,K+]?Yn_@99V)ſ&. o^z";@].8?(13n kr>YjTm/1w |.Rxy ~y[etbemon-1.3.6/.git/objects/04/0000755000000000000000000000000013212012641012545 5ustar etbemon-1.3.6/.git/objects/04/415550f2f30fb5644ed879063359b61bed981c0000444000000000000000000000647013212011021017467 0ustar xZkoM[J%nS- $"b;$'Z2"?ܙ]R@>"wg˥o0'ޖE'[}2>է/_~/N˳W_:=MU7g}ymؤOti=I;WuHxV_N_(@zk[d:-[SdnJ֙GޔwX]ٺ͛z,B?]^]ϧs5>\g9|x:mmlJ^\>|XC,`NʪֽMӫˁn4>0kqװFMZ-5F).̔-6dvٮ׮XƥVvQ7//Soʺ8]Mu|Mo5~iӻ0r{m9c5ow|#㕉K"t6PY {PF0&uY6mv3RCme Dљ#튺努̮ _:=;;+j^p߹5%duQs5c}vryRUI U}V(m6Uٮ7cbj ]Hko"z@ ['o抎\y^މ#?fc  $슟^_~ՙ1pK-z v;QFn.+BlR LZXMDa:vN%I@\/|t+UV0ه(>KaS+ И]Lo#LzC[ $Q(rцʸE3/ 9"-IY7%R?^Jjl1qqG['*@۳?v(~o+8 чY<H Ze0?Qo\޷m$pSekA4@lgh:INKb@#AxDbU&w;3RvzFs RRp.K0zѕPCk,k4gsŝiҍ_!kzcqtk/MBGX!L B06p3e2eFH; s(`3z*nEG"[{ȫb;5 zLdmk-USh-늒G S%a]I0Q tI!{H PN4S+DZu[ k&@F%|`ծGpR,[H//ɤMkrNeЧBGEH0)=|e3m5Y) H.샇[2R7jCDUm!"(U"Kb("oҲ%@ reI-qRr:^0zJ t#TTo®~p啠[w6{+'sFEEm fm>]ڡ=B@=݄'WYXIG5NW!DNn-aYaJ"ޙb {Ӎ)V #NnA4|m ˝ٟ{j@k$4rdl&V)VaVgFDWnK>?  dvo\zS%+>A|1!y@KZK&R8V側0Hm>-\j($ %[5Ny6:0Q\-Qϯ;CdimU)T-~sg@JQQ5Ĺǝ\Q.SPWt0N$&[/W)Rte ],>N gl3Oe-"eT~ W!8lal9`&zqarY2{G-gy إ쑚D~-C0bqD"'ƥRtOQ7Yw5 ND_n;e޼{?`,msýKU3W05HDg5z/\GQC߁vЦ"#Xy/[/@jtFXǕUKjCC0ȸ@@`,煪t 죀s5H U`S7Aݥ3u>D:}T@75/W\y)3''/ 5(% $yǫl%:N DA:L ^y:#4# b7.w`&[0V܁KϱpAɱFtyBzoA;Ċ8tid/U6Q TGenˏ˅8M'. Zc~O-/fipau@Ċȸ˹-D /[YK)] zn~>g~V~|,T(F[!W3/鸬U t%etbemon-1.3.6/.git/objects/04/e34e293afc313385b0c914b6f463a102336f3c0000444000000000000000000004425313212010753017531 0ustar x{syOA͖Is]fהęa[.+.q>r4HDZTePsy?cvx^.}4Wß?W=|v=a}_=mglGtޞNfibm}62Ԡ~߾<|qh_d^чl>:gۛh|޴_^n= m߾|>рI;F\\_~h<5v2[Whͧwgc{6^..fxuf6z=\쮫gs{vۛ~}~wk{Mv1M5Ɵ:ݳӧ'ǯώ_Lh6.``[i_M'tm , b./F,#'t՗Gv2.S>_v.٢^邅lFvm7jQGv=Z߈zۊף،׳v3lM/F9p>mh`>;o;l^]X+F޴אU^ ^(~m P#wrq0:,hn;zwkHo;åל@K5<9nﵾh_nôÓIChSad-J@1! vO7 u` e_0V$VN`|/A'̉Юkhqwf?p^!kH;;cX'5l!;] ~k:MmPR"Z kl|8LՎYߜLG}UasqlKR䧮2Q=r Q/o-Fo2=]^Jd]/'<{O`x |f./|Dh]= ᙧpҘj/ozhvbZk [&j=PGWȟ\WkOQV= J6To!\?K/Nn X/r7,>߶A &mfD,n\W\ ѴtΗ-d"颡Gȵfרa?Q EvnzNK7ϗ`>@ǴmB-)|r)l#4VoѱQN[4nc߅tubkmlH֕aL{=oaG],t/fw=Ԁz荒 H!zB`m@O bDJD' DnP :T<=N0&Svףz Frj{-6poXUbd)M* I7l,4+~fN';edQB,%A%;Dzf>gT IXm!3/-fH&d3nDt8sR* j(*4ײvӟ?A8O羈Mkh#3|´1+|V0Qǘ=]| Y"[T,3A,Puñd2|{~xz͋'5a TLq-!#<`h~~ awlפ", W^C X + 03X|A&Zٗ|,!1F@i);ڲWo^9]$R9XkR !ذ/SZ5ws6L ߽_/ֆ=<~vmċm-*뱥>=>f~d,'nD"uӣOPoU'Ϡ&2R-q ;T+'eJPW5ܯ^>{wzvx1J+.!ƍr\ZɟN㛴`RI"ԃΫE.@(p4ɬ9"j[HDIbhܞ!<`mJ#>Da?c O}rxE6jb ռn$^$Ϣf[I@$AF;&7 U(ސbG .?L1x e9}/CbQ-WˌHTt$eXL $.5!!n1ND/^/FQ#w-hK U[V L@*:]6Re25-MM+؉S&Ƙd#ƵHB { ;,mdfGí Rȍ3%3\iAZyLȬG0O [1Nd~JmnuɁE&@VM5 >?:9)Q6oT4po$KDDYܭO¼7HBe/%@#A&)@Qп]6I]MbeV|(cQpC,KT0G06l.=$#:5gQ\|MmF*ƪHĞ6ln"GcV0о#HIJ-0 U^F$Œ.YeH{2H}dJMNلi6{>g)r2cA*:pJr_ٯtsM~_›y\1":c?QG:FQo 3]+*(U&您wRN]_@Jg@4b(STEfB87AF1NO5"5.K[t(c #G|*dg=Yu>$J[#_i_:'nYw .f(?,|nnWꅽ"ɆpH Tpm(fiRMQrS(tg"xpMnaY=e<^gY$髗 oM0r685#VLoHGOu_Tn|JT?%AG; Lh.yP(OhBZNSNXY;]9nFGR} ŽՖ+ +@UG#QsK9QU;G(rϗou%9mv =SE+};z^Qc|qc5T6Z,e۽y0kk.DvF(ω)q1xaM[uvRI mS5-f1JR9Pw|9l ߢjF~T8L N ,W"Ib" E>2&&6*ŴQ#O  N{_#1=m-Q $kX0un@G̓D/@\Y#$|SFe5&,?Civ-v_Dvv_e.]u9#$HRh'ǘl"(j\M{X8Gz`+e nV zVeSf͘l׬~v2 _ca?ˋ-1[ήʬMQ7))Ҽd*3=R-U!J-JDjk@(tnД_GdaPKiv?@.y99VYGe!.G3rIxEl6S~LV פ'}CUqojڶ9_Yx}ێRz6.?-a89Ώٙl%uK B78{ {pzmKBb͹HDLWxR>P$= 0݀;׶0E{o5y|C;&=;dlrF$LX1mT6`#N/wN,G%2w&'n7[u REID,xMH3Dw{3H~F0Wa)i)jl\QWo^)3ֈH\p9"xrއv@w%(e(sacS `8csIꐇ-e,ӏRSqrnU ߞئtC_JgB^D-\dABq+k¡7О s:҉ur)4J_>{vo @g倛ge50#-XSԚF{ -,?ͱȩX(؊!h1:ej= ʰ5'KcbCm]838Rx4apyQ'7偪jIJ »]^ 3C #'b.D$Np XG@(e[uDɋBD'HWQbm^{'V*lb zZ?R4Ce tΌahQcٍQl^d ی?PSGjד򙶢9M#lw3'׷w!zS'ʷq|!˰hxbc( e. v~=$sY(!^THJUH5O9E-'c nsZC#of6OH~x *(w3Rԁ`̘3OA]|9ס8AdB`/6LK$ ?8 TdBT?cl&  OZĖqtfoάKu{!x)YUTP% A o7z2zD1ήNu[s[23n'%*cO'O'q]Qt0LK8 %&`NACCV!tO|^Ρ9e2yF*V҆jPL*[AY=HWض,Q*&5 A{arXк uwKQzE18 Y"Qe[5{xYNq4]˶̢HrR{!gOY`2̵[r+/3c/S. GU>7@8Ww*@&cVe,VE`U346aͦfrD5_!2p:N%O$;ZνqoHп=x)|TlTD)x΢/(epO1mtP2E y2]4_ M[_= iľjbdJ,`1^{'U$ZFfՃGmR Hf3v gpy9!W җZo*pEBŦcIYp(dw8]IXڞH.@`ZZY`O5]Z U>,8 e6[Π J:l}$C֮z01j7=9to=(5b.mjfTLt)%ϢK¦`CjY"Z fV WSUYOS|+K0INY5t!T[Fwk \t(^j2z }S,㏄Yx勦Ku&al#'B݂eܫؾXPqTEphMl@mњS47GI?EЦg P +8ب9:e9iT<_B/(*#8B}DOF0}"Ā.~-~†1 DEPRT##CSe3U]+}j[Ntƀh 0?咩^ p5OlUm-vuf;"*K tGR9-{Mi^+$Gzz$b!UdRj&' n 4nfE +ilwӆ⃠*Iջ-9q7@D`"Ϩ!}e"P !=5U-閳9X,-]'UV=43kytSv(NduEuB^hIuJԻF^߬cf I~iAud91 KX[j` yF|EŻa( Ws3UU aՅ ^}),<"AtψZ|U&$q~zp $hG % RA@QJ_'Z2*pA\FDT-R%jgG[XcRk9BjP(b`ȿ ;@gC\ JUuFj>zwȝ`gR){v}e5|V)B ۴ ݞ0xqa*+v,Nmիm>&=-]xX~nKix]3t"jPMZ:Bf"!5Gh#]^R`qoϲ3yz$e8mNٿ4kG4bcmdE!o1 umtA:W 8Zo U8YxwjQGO( 7ԉLxa_2.r:Qa )䩕eM:Vj9l0>"Vady^jNj!_ )P}EфlZyJl Xˍvh>XNL챂iȉ Na~4nQB0cZ2`/xA7U#(sK 9BX=Et&ߎb5_1,sΟBUeSZLq)Rn*=eTw,>1èԌX{9%n1lD7vMoٰXDQE.%ͧw0AK0i!m&PvȬP)~h)"D?8ߊR1)-"?(F- e?F*->n}xr|&u\tW{9QUeET_:l¨N ǐ.t-!3lE[&Z i>"Y Ö#V36-'Rj)@MDE9]VWiޭX@'2E=\Rbp*6]:z=l%%ݻn*%nSbL-cz%CYo];]& 4~%QT(%Ckk \@Y"|Nx~Bi8 2Su;¨]p[~}3 U&R\¤-VuC!)ޛic:#ʚSwB TơJ({e9]?$ xG 3}\W#wzp ΘIaa Kkxv2b V3o+nRC:YѥgW,x_;T;m,/0,ts&.\"րg;t.)q#bbsVpF K_}ɀSf~@77@r0?}ZORZάTLH 28(@f;S,?H| O! 4W餭! ,lAeE Xk8 }KG,F+Tk0Y<]z*WJ4 RAu61'Q ݞQ:(JӒ//kujTW6b-Bt^:XM[&Wnw @ :]v0$Gi)?T^UO cؘ>1׭NHfwo!'q `[C)~ȵtfuE Xq7YgHPT3?.1d%iQ)? 2IБjWiRZ KЦ֜<}CBur|'No4|0yoX]Oۛ -%@-޽'yWϟYyÓD?|DM)Xkpzہiԉ@P]Ӻ75ܛ/LGAP6:?mq"$>cc"`&ޔpD4)嵈jTU^oinB'N&MBZb&ӭ"個ʐXˮcfek@-͔ [!3vO]@od@$M W*56ެBGxx]Tm#-XtFRZrZ1fj<+H?=L(CG9*d@_醮]~Qm(@9>qWPk`ؾ( _KQKw~wo)^F5޾ X٤EpMw XC]>*]ػw̩b.%Fc;Z&[Gml>%8P4yWi9)mt _\ar] Xn8h, Ts;ΔJ juR4}x,/!dߥcbZ0'MXG01^-N73 n`h;JPJKL׍+e|/ ` FWz[d{{)[4B^(E4>>z1n fW k׿E#*A0 6# sQzxBW!J-RH4.a8!ٱ&{) jĥӫ\lE}vthƘ@b6dJ^SHZ%}(Jah*j Firs9}J0SFp7bJc J!v],>Ld*5;ܦaVh(4WUjrnd@MzZq Af2-\蘫&PĈ_c2q-YCWIFb`8~Rj߱uvv44a^Wа ښ%Հ3,Џ;hO6倉4C[Չ3l /6du0X]2kU w 90uJŹ]8*6qH-DPg7VjhzEܗXϒX/P"5E2âyz/~++K/%(Q^W{m:r-wɻHV}.JPYr^|/پڜA$S0%"wL{a~PDwWWSJvRwVzPɔY1:[V{}+}\[_# Bs򀷽ExNᣒηlN`,lAgyvHa2Dp"ЙmWO 0sh_mԪS&]UM 66&dA5UK(%'\) 2IA!SLPP-OvQu @ ,lҗƢ0.JP6|I?$8'z~GT|Z k8ŕ+Zb33 iR2VȐȉB;Q:PM2+PQ)82v$!Pl%"=6Fqlud"7`?NkiOeG buЪX(>((L" Lh=f$U>aʣh`X +ш *X@v^hQՃVwqiL=E(xܮMˀY8퓈^Q)91 rٳNs5X&-F=<Q(3߻a^{VYfW(#tDLL1 ɪQ$|veb@-yi'Q"G[Vjb6' ߼pu奮k/N }_Ep0V#T  SBݕB0p\(Df2q"(qJi)x]23h`Qb M^%%bΔ'@' CT6J\=\Gc(J\1̀M)/DM%U)iz/pZ}+1TGİ}x"Q 6•P*C~~ EuK"W^v! l5CM6 =B-՜f#ZMZ=1ރM$[ shu+15HlCtG/ώz޾ ìGY΍Sfعqf[,q*:umuV7T4AT3H1r և$7]N/7mT\ G~xhث͝]c״$kM}cko4W@S1rG_byd|կ4egӁ*gqDkw|V4Q@5F=n#WPeKljQRQ1}t ΎN=P(pVzoƁ%}O޶Uj2ŗƔPnvՁh8qACɜ@+"."s5ZpJ&g޻=zS1(@Df⪌'vD kūo[]wV[qGq[ jTJXKmdFǵ8=vzp|YܷIXIЗ` R B_,?ux@sԩB5L]&;Dg)x𗍦Iy( _nLWKʕ,d8t$zõV,\<3FۇZ+tss:xg?H.s. 6Te}QjwI^^ns뤑4¾4{?NʏKɥ6Z_c>`) Ap_+٣ %(]{0"XcђDBˀJY<= (-z?ǷR3]uglUV{*v T`"#*ٰ̼GՉ(ZjPK:i?vaa~͛I9aXMPCP+CU * [ċDI(i3c4}Vɖ{',|YiʖKVGR/%WӂW;5qW aԖh73(:MmjBF?h!IMm0 CT]mJ[c4d û6͋TN |ʼnXEyDڅ)[)TZ@o4T-MmHa9KXB(Ivچ_/"6%"Սk%%H:hF4)Љj'G*{h0MnLc MqD K=Hue/"+#ǃyX[;Y9/=Uʈp@ۻ>Jh&dS,zH>$ iJ^QaI8ڤ˝(KuB-Gp|%CҾl.H^:nP3ųr3tWYmJaӶ6.\vtC.|SYFdE ;X0 &c+ˡF,;wɒ4 = `ߒB'f˃}bH,?]*w_~~taY$:/Lo\QxF;Q-Y ,%|zůaO_&GoU8Q) :K{hW:OR*!ʠ1kt=;e)n`+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35ݢ{%\\q7tW)Iy [x^RQosIϸwҧ@'3<t,/<O%D6$e{'P~,h+.HMf9pb宝˫;) jFiPA ˌ,f~ wm1DEq 0$%.[:ǐ[]+ QQZS0/9۝iLM@0etbemon-1.3.6/.git/objects/05/0000755000000000000000000000000014057341606012564 5ustar etbemon-1.3.6/.git/objects/05/3664aa2e7e3c0d04265d0e7cdb14d79dfacfff0000444000000000000000000000132613216420274020266 0ustar x+)JMU0`040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35ݢ{%\\q7tW)Iy [x^RQosIϸwҧ@'3<t,/<O%D6$e{]$b QQ\ I=lǴ˖Nx1l BTd3Kv'sZ,d-+2<@etbemon-1.3.6/.git/objects/05/7c9119a2434911c8fca04b2ed3de9cd627a2470000444000000000000000000000120613767544664017731 0ustar x+)JMU07d040031Qs fi^5W~/jbW|W^Es];Ӡ8IMjEbnANj1I+&?<ߓHHL$uy%99 >gJT8Ǥmaq$e9y K%T&vU~ZP[$E% rO8 bڼ{w=CSW|vcEQ#>YUQ*ذ*)UUF5AE*f7/~92Y{6;&-R oMMJAp4iak&,Ψb&(@S5zN ]ϡdn`+ <$9auў;sIwK\G9.etbemon-1.3.6/.git/objects/05/e4bd5ffe72f5609dd91d5f56b7a841c4ddc7d70000444000000000000000000000120614057341606020242 0ustar x+)JMU07d040031Qs fi^5W~AE-@V\̐joʫhrgY#IH-I-f`Ѿ")p{Rܛ.3$1'g,^ʀG[9ԝ >,,'3/a`jĮsʯ]j dCd?[SzghrU_ؘnl~(bcg *JV%(F H2GU4r{u;]ZMPBQ)(&-lޤzEֲS D31hjVIa69yL l֔'$g0̴.sq> nH4,^etbemon-1.3.6/.git/objects/06/0000755000000000000000000000000014032545161012560 5ustar etbemon-1.3.6/.git/objects/06/67c15201e0fa881b887c23a7ddeee22799b7c30000444000000000000000000000223413700752540017725 0ustar xUko6g[@lL~%}rMC^u D(Q#)ƺCʉ۵ۇ9B=\Hw  Q ke8xL%r$זtj? TIW %)*,*)I̮H2MY2%QJɬPUD,4r r8ŠQ͖\󋻋} "y~Gh S*!f$H$cgCnBb\bȡ/Qga8 k./~: א/ ncRM L -nf"kUݔ_ųIA~oݟ[]r#c{eaY BR{T()AmO=`g eRn8ԩ{Tp '^c 3葰Js^伲N6+4џH{~LL*$7)(etbemon-1.3.6/.git/objects/06/8ae1e6ffb52213b7aa5ca81f73f32020d438630000444000000000000000000000141613513716505017702 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d~mmL?2< lrNfj^I1ó k_>v 1ٻ&_HIMLcoǺx/‚v;nUPWmro}_)W,;}Ԓd<,mOCpEe^ޙkYZ ONťٷr-/t4gu}*LxG6 4 %Kz];2I bInit3Cr z0F=0:a*y?]WX; pNꐐﺇVf 4!x @ptԅ+F S},-dH98iչ  \^Bu^1Q3&f(Rzpp4 :wD) G-C罵||ÝOLhPR(F`y&/ݳqfʈ0;CDj$P<^ Qځބi|+d '@;H5hS4)[!PeT*}C?t!7e+mٰ$ d錑tկn6P2MrzhI&d2V'w<T[!9PB=Y[n1282-'(]t |FmM0e(Ό,?~Ū~rt/]RnxgPFs ڴ^t;NȂ8De0Ӭ]fyrJ GI#4;*8I뮫:Zy OiQ:s4[+VI{_he< G>0Zo2 Z2;|G?ۯPtfo_^Bɷ!DIY%)JPY}f^`h aTӞ ! 3uik2rTcu:K)E"RjհϊCAm1Vyb?K81p[6J,D ճ{DE.|FwL0_FtBuN~hq&30GKMŷsk vT PD'*fd/;^eHڊhB# _ J d j>ҭUkT'%LZt[u(% nU]_ب ,Oyڞ4PX0cuC![˲Wŭ4+80(OƬQ5=FfE9I3vP R#KbE8<I}ʺzy[SdNi-qDrD:F4e hb|vS3Ӧjn s -Vf܂B0k,i]hsmP oAN Mk'MNtp`5UY^ [>\6Z; &f@!mx s1t/q\QRTXc|A*OG \GWi; %eav : @IC' y.@兹^xhUPm0޶W5֏Y[m`?pRlV!zQVx%G#*N=1ףGbUٸch]OXd"vk:X;NpCr$x3AY5 荋4p-`= ]\(//X:l8ߡk0NƷBz21b^ A6G=qpQ'j|.g-9蛰#Y<\> K ֯q( #l/O9QaQ4 PdUIW#{gp)N;f%NkӲ%W2m]$ʸZx㍘[YF㨭B[t6&xG2z:h6lVvH"z:YSoqWwG\U4v5Ƥ4Q߂b)EEy$XGkXsч{&2T&x-*L*S^dWBʶz7pj] 1Y 4wE~Ϸ3a?]T3qꎩ'dZ|Z<]QiMSaL̊JU?Dӓ,| NoΖ1 fsʲ@@#<҂~ʧZ'E+@gŎvRQ>ۭ n'y%t[cyЁox[\r_d-9Đ1{۬&UNOPs|}iHadw Ƽ(V,Zڸ^/?Ǔ<9 /-MYv,__{^(iS*es0]av'[֔^Zu\-SA aB 93 jA ŘK2Db`)^~yl֝d-J0?'@yޞ=9?q@?U`W\Rn\[x"`l%pHՋYZhx"cI%TXQRSD* nVA^h]![J쓗%:eJGR+tQG .Qxc0U9eE _i•JMS~P~54|wHEX|Ó0iGMICUi Li'V)%aY\ \%kYeTy *t@tS5M,X2bLQH?3?OSB՜DXES-*6HE SbE$:|TMEQV5sr00' FeV侁XțMԖVݛ>7~\/XF":ioxK񥠣u%.gjk,&t%[rm* cD鼿BF45U޾8[4'ad^qrKs3G,3ٶ{);}-|y?\Ȭs]z IKf@23ޭԋ up-x@7 7+0NG7|_75vStDA1.^ 7{3:u>;dxi DsWEO.n=t:ǴwΚNIP^X{E=UY731eh)9%C8+"8I>WpC#`o#ʾ]a>Aa ,{h,B#8@+!VK9F m.{Ȥ~@o˭~8~*✘Bk:kI߱5leN'#\W:#N{½ޠQNVQAgu{E ++4#r'S+H- c_>{>}#d.?;_2cc1傈AܷCamڌ3{@GIVVi֏QT8May:7K-tk}lҋd9Z jH47BEl6/ƒb8d2(;9YYa0 ji߅בp17$v&#g(!-p2hjt t%0=7Jwe,4Ÿ`FZߢҧ Yi2H/h?Y>%пOVX`8aYm< 4M7t]mxH:GtwZ_ⱿZoCk7oWܜabT]|9)?7F%\j1b-kû& jrIi;Sk@@L.Q/%jӾ^l]w*>Ge%i.")Ixz?0î;-y6זnڝ/, ~1OaFJ ir 拹Ir٦tGV7fEqqmuSʹZ 3-#όdx6"\$fPm KMQu ]GAh~nwVأuhMey"9&5 \*yY`)az|<ɢNݾ r4PlEݘQbd]MXvHIo|*/d>Ce\e02e8NLfiKQ{koU) 1;/\rfJ$USenb: Rxa;ag$˗c;T \~RaGh9r)ݐ,( nWy`tyy/a9(-=XɅ> s(&R!qg0fFt:߆t:Fg6G4ʻ+lq6Dauk ?u=4%bl4n+DT3eŦnĶ7ǯOd 6^_j!b #ُa iN=nEڮ"5'˥+oV*ɼ?DG0cH1s?PZGkoy<ژ[@Z.\aր+xP)abx[۱իbךeCj'e?f"ͧV`qxh r gR4E-!*׆:<6l(FnV1ʀݵ¥ȰV=YPǢYt84r=v|S.M*|"}ڕ GndDtݭ5L5'3&LSCOPC "d;' _+AyE?p~@9v U< @qpw Ҕ{D> t6hk/g} `z;LD톘a]M!kk gAOm/Pb28`C)\=p=.{Oifl Zi{A]flq(y7JPx=<`%ZG?a=B8&.Lhi!8_Tƶ;QD=CaJioK p&8Wt$-'.y"1DKOˋ {̇fN0w{Yj%\yE02f!,BJV$d?'}#?3(DBsh%m'}t,rϜ>̿:rpTc5b"SYІҖ|Ը?O޿<N<%hQ6kn~'Cb;З F6 ȥcn2s`a$$1xDȩa~SsXAg<5nB m2L87Ctg)e/|*HZR{D1ܭ~ Q՝֣yCt<. "VB^eh~o(Ԛ4o­eJ2x@xMt7])7X: &j!q%ZCZ$῵ZUmn0m{Wлd2q͝bJD`lR۸ok#/qtע+rw|Zx$ x-|V%:Pj lV_ NЪɭQQ=Yz,OnD`Q-Q, oO#J |F2w,2,sx@8M)&`.^ EEs*0a!wZ&IR`-*$p#Pb6oG!2dJ~e#;RƞjbUYwYikVjK!:mEŌ8-eS ;'?{e7>Z7 [kb?̋2؜pV*"QnEVv\CXC a]ؠ1QT a`R*ׂ'! +-Ce-lZ0wcBxO(6 ʨCٌ-]Em3她 o`>Eh+p0.ovljls^0xF9ڣX@ǚ~xNФbDHAgm<,ܪaD>|[%= R_WB~M 0$͍Js>.`~%D؞“R:G];L`z2A "g#%}=1sH˵ *JU2Yb3g=xSCTkZ,9!Ze2{mOs^n {HF(F<:L~q NAEt֝ʮV0XI8 k"$_mEXاrs 0[WgZ  bow>L ؞RK>v(]%YI,?`V7Wav} 9~ӻnRzz;ځ: ۦ(eC8OQjӥ?}`z]ۅn6rrG;; jNDV5ˀ^ "Qig$:YnuS'<ĴbVo6إwS wʅ"kes w^;zOPl"R+#"z4G+[☰E"Op_Pr)֘¶m~cB5i9&[""7:Cwm>?y^TH6[I%gGJ&z3Y"31"b(Ҷѐ׬Ԧfj`ۙXPB-z5H6{@*dJyodSTDK)ZN1VLX9p/<%Wv4jv{];5/'RHb0TϜӞa?z(C+2/]>#8دT`aFap;G wz!?K @Ȟ9H`};ctÖ)tp_!lU)()/}+Usٶo'/fhISݨ|0!QA  wkRkt V0e%Ju(Z/5ZaC^6)D*>X%1kDP @ЊTUl o?. 8gBu_2Nj|$L~Cٰ3\[Xm黓1 (|F8/H9 @uBs4%bh= IYzpMuQ~T4L6O^kPTY&,ng,M20m"f'ɀĐg+|&c%^*(O퍒sCq:gS|G&okU?0(o`*i8o1.[RH(3=~\U6Q<8^XqX2 9[{h~ATظK܎{&?y̝HcgK#|yKe՜5LjJz&3K('c\z!Z{> fNa1VjӟkSm'b mo{{xYHx}y;ܼ;y31g3pr jOtQt.9! &-bLNn|vCA`)2ns9b]~슍(IYU2-<=эmNꋹ D[naؘ:[X|n6ʿY Z+<z;>ƒRT$$ zR?TW5Y(sK)9Sx;jCi D+1^눓kOa vC+_A<X݂Rk@ګs"&Q?RWuKK z^=&ԫ|8wHV }\*&p;^uѶkIOQE+cWsU uE]Woh7!)䣟`yiA9~~}:/x]kO%U,W[,ܚŅ*q_;=-yw#FZB._wycN@WV~MPŶm;U}J&z4<[ݵMOd_ ^`VH#r~M:=!yb <9^cA|F"Gs{J/ ·!<"y<>eQB$KcExqoQ hD茢J2.Qns`V;fu i٭r~x\kmDZ$p01i< [AN"l5sJsEyTc8/fGL~{܈$K>E 'oC2V!*yqVU}+([ YjL??eӽw1~5 ו9iw#0=Hαu׹VɣO''e,ܠk=VݺJ ŕJy:jvj.t[e^琝#2[\I|3jR=Dsq)ΩYیMAM"J28g}$Hȓ{O0Hk |PN5PGƟ_n(WJl˦;nSE>(?ۍL>Z Ls[N3[v렬FU翫gH),. 10t"#2|j[E+3mwdC0~ sӷY]sDc5&<-hJ9_[uxe{Jiq䫭 N`2'hǿIczMpd)دK%J=# k," b(;ކo>Z6:px )eGF-e 7Q_Aa뚶!%p]97/Oؚu JY{*sIϕ9.>AQ8:}_ ҷlup:%!d?N:lҎS/lsffF]4yClg*Su>s_O<ִW7p,:ęUݬ-8-q_c2|R6xƮl2l. e/P+`(kiPUTQ*EW>&>T 2Cr:vI oեՊgQ9-U@7`yS,.ŵ4[b]j8'Y/iyAFM 06KƱTngUG֫sUZ;F;mF.n=<0u4_wg?y(aTZY֝@Gy]FC3 ǎЦ6|wC`[?Sjjo~q?ID"Rz\mqo+OԬnRY!] A'USBAЃ7 S̒Yx{@nDt6HigN3"*cDEz }ûiv缲ݝf;0,t{۵! (z 94-'xLpUrJV8XU{KyD5d9p]!RZ-@΍," ;׀}6X1&~]nWp +ya@VpG~!ZI)∍eQ:r+@bVrL*wi=2/buTRMtkgc0h9 7o.Y益$_B Vi@%q'TKY6[(faY7jR8޵KMY(=#0!(IˎҊgi\aG1ѳb0 h&!eɚb-u}oRsHKƹI)C+Sl-}N'C-G~2VWyd ׏? aa7dMV9è*GOitc]}'~}Jcm+؎]6ي/*V?t Fy%H-/םI%}sʟso:n?՛"S[" +e tR8)z }ww+?4^ 3IvD/L9]5tk,%Vۅv`o-MXtÕGL2 U0c)޹ deѲ\.׶2O]6r/]Yb9L5OݨbCw*8^cfAVa~:Q)w)FW]k Ɠ^?뻷]7hU|o.i(рv!wH6~J`=DAL$I{K-PV4ԞPuG&c1Uȷtk&A\aB!gU`zC&xJҒN<-SJ#)DHЊ5&}f~mq͝ On%f93xY$%Z\M/~($`>RQjNd@720"T*d#qY=GC|Z{Y|$(ψaP{-K>]u-gCy܇Sm* JԳ9̱̓ZF9uetbemon-1.3.6/.git/objects/07/66f000a6f3734f01d181b16416c1b41d8094de0000444000000000000000000000323513212011741017441 0ustar xWmsFW+)v-a(v8)I!!c;0trt)äϞ$'E:>r~~W d˅Ndc1ѯءSI4E\PPap/'zY"|-Fn)jk!޷Vf*=e}wJݶ(b% PZ& 슮4 S7iBpEW&!_!b%ʗ$Cv%h{"EtXEIXa((,~WN=:<Y$"솥TЂdF!JjcI6Df؎Wc3^pE1#?``֔X.ˈcXljF\TBVfK:;索,FRxdVH"ʵ GKZs'3=b ͭTU|^wk82,*𲴓+4쑥 Q%J+l GjxiJ!l'ɆBy#!Eb2~=Oh]Cκ@$mB4ua`Q бH7Ff|Q(*d|K!T@HNF \J|rFZ.ͅ[]nR=Yp:5e@">%z< ^9a˔Y J/f1u.u"GF4Цs-9`vWe1iUР˵8Q%n`/K*͝TioMMuR+t4? G'udCN-7ٶ>ӟ[w9aŗO98`ol葱kp- wq)@e̝?S+xqO.Dd脄΋ !PW *K\c1p1/r}4&у4AѰRdi)AǾ+;e,Մ[+9]bA7d6-ތ]!mg]zd'#16N_Ύ~átex8{9M|2[L.^Mft~1;=%;HJil3kSH B@.Go9- y>%gxMDAPTrbTjz)ZKJtĥ:{h㧴Ȗ#ڣy&*cDtB~ |z7 9cƍk~1ѡ f-6[ jX5+.8\ fDMzag 7D"(KNh] ]篱󑓚k>5wYA0ʶ6|z/ﺸv~T9,Qc{6~UVm#VC_5^|݋g>"HmU:OVPhkNMw`܀w73etbemon-1.3.6/.git/objects/07/6d7b87faa6e7f2b54e873c010cbb3e98f6602f0000444000000000000000000000141513221737362020073 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTPv.hMvZh)TIIjnANbI*Cպz SD2dǰ7!aMw!9y% lcN!*RR2խЎi͖ۣ6A'3jNVp9jdWlƽ%Ԓd.g)cz3Po1hD_L'}k6k:D3PV7'?91vrznu7lpU@y]-[{9)lh+.HMf9pb宝˫;) jFiPA ˌ,f~ wm1DEq 0%.[:ǐ[]+ UQY N/ y2ּ?)$3a^r;'D=b$k1_Retbemon-1.3.6/.git/objects/07/952177f7360e52f6ea0a096cdaf68e017222910000444000000000000000000000025013212011701017455 0ustar xM 0F]J& "p 4Qo_H1VadXMNZGFYlPI<(n}3HD"uZ\Z)å+/ ҍ3]HzlR6mƲ^FIyo*9Df-(οts@yI۰)OVJ3 ՙetbemon-1.3.6/.git/objects/07/ed5ad07f3a5cb738f52182bdabede42081b6bb0000444000000000000000000000060413767550465020274 0ustar x+)JMU00e040031QMNMIe8;?nN|:/wrq7jMMJҊr2KĿ2sIt#A KII-IMM,(HMK.(`uy&؟jRtW8t&0lK׹KVz|%u3Ҁ>).HLNpЯxQĻlNg: 8'3B$5z*nM|"zGx̴SXW*BWKYhh] Z*-@ ӷ+dr9{lڤPUŹE%%9pMT{$5\wn୎7`jJ3ǠrڼnOVU[/ JJꜮW 4dbzEetbemon-1.3.6/.git/objects/08/0000755000000000000000000000000013455620411012562 5ustar etbemon-1.3.6/.git/objects/08/22242411a8e23899a18a38b028691013e96c100000444000000000000000000000100513455620411017153 0ustar x+)JMU032c040031QH,-KNc[nF?[>i%Tx TIjEbnAN*HClϜH݅hrM o]a!Nqmw^]U~^qF~yQ2􉏅J7}Zw!Θ3pUM @!3/D/YT{E%ďݓ}LSrԴ<3JFj>yY*3A֊U:妘-JYٲx[*knU~g\}*K/,/IkUzڽ5W׼#0e%i`)%i#aZ,3"Mn1Adg$& +3fq"ΧLFm.JB]|T%Tz[3;ZP##̭hRR|^+ڕKbSVY ̒|yi e n9>VU^ZT[ K(._gx_p{pۚetbemon-1.3.6/.git/objects/08/b1d6780604515eecfb9da6589ba354f687d0ed0000444000000000000000000000211313212013002017765 0ustar x}UkoFW+NM*&’]B,Uj 13tl @-_lǹ{%jVÃLsb³\K0$"͠UxEC 0fc-1x+X"*|>2a&š k 6VB.jK%EF"0z]yy]:߆ W8Qϻ bbB%u9G3Ӽ2IDT<Jc"1\F\#92a| q%,8%"ĭL9%7'i#H8p(4˄pAkSFk C ~ 2zsG,싍 -"V+*+TH8/72>қLzCY薯yL,WddwWgr]nՂA0Nq=qo hzURV2$@215'C.!6REj(}_u f$|oIg < &Ùf?/bͨP3qQ.sچWvc'W]Pܩb+@>o{A$e;}fF!)(}kXN[Joetbemon-1.3.6/.git/objects/09/0000755000000000000000000000000013343237745012575 5ustar etbemon-1.3.6/.git/objects/09/c94ea027b07f2ee822bcbfdf2416ae53ee9dc20000444000000000000000000000006413216421171020264 0ustar xKOR0dPVO/JHMV/ sKKJT [vetbemon-1.3.6/.git/objects/09/cfd68e63c68a01a14ed2b14ec7552c3af6ddea0000444000000000000000000000025413212006661020260 0ustar xQ0E*AI&p`NGߊ;p9y7±O6HgTDPKg@GL,wbh1M<-`dkRậN\V87vy;HS5lod&i6ȣvb eJҔp6eP3yX+&}+7-,´K%ȮV(g`sSȩ/etbemon-1.3.6/.git/objects/0a/0000755000000000000000000000000014001502316012622 5ustar etbemon-1.3.6/.git/objects/0a/3276c29c0b519fcdf7bcea7197e0b66d91b6de0000444000000000000000000000027414001502316020210 0ustar xKj0D)oF%An d, Y^G!գxTQ9F3l(#otH^Ʌ(SZdeE s5Je=ZtV+x󄑼U/dW* >>77_|s@Rxo $(>b1!'Op^aP(y雷'V}etbemon-1.3.6/.git/objects/0a/7bff0f3e05a39ce7f43713113e88b8d8bab0440000444000000000000000000000120713462027016020044 0ustar x+)JMU07d040031Qs fi^5W~`/D_)-H,ar==8qy9:|6-+)ahyŹLjfXdLʢ˄,Ҩ7A (7?O/%5-4bEΛ3]Ya_~̢bORY)'4|^2d5 i6 /J,wAq5Ԋ܂b+WMx'N=A+.Ia{M=wʵKs#]̰akXHlb9[׮UERT_\2!+`ki=R;%jdqSESW|vcEQ#>YUQ*ذ*)UUF5AE*f7/~92Y{6;&-R oMMJA0U~_Ӓ+;]R`b fͭljsh2?J7C)O,I`i]}W鑮i2(etbemon-1.3.6/.git/objects/0b/0000755000000000000000000000000013604576747012656 5ustar etbemon-1.3.6/.git/objects/0b/7e77ed43378370f6a7e69174ba6088137ee9840000444000000000000000000000141613604576747017555 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d`|z3שܩ5jϜS 5yBds2SJm0] )5*DEJjRfbCvI'+7yDU/ UPWmro}_)W,;}Ԓd<,mOC0uW6ˉy\\.;_|=fnN~rb0,Ms[.iߧ|?n$LhNJeFY Ch^qAj2/ρW,w\^5NNP3J+ J\f,g4ۭk\!*K /q O8⼀Z^b`|05tz]XȔyL%9 ÿ=!ɜ$Y .Vcetbemon-1.3.6/.git/objects/0c/0000755000000000000000000000000013604575733012651 5ustar etbemon-1.3.6/.git/objects/0c/2846e653043723a6b4f4aac07610d609813f690000444000000000000000000000030313604575733017415 0ustar xAj0E)fj$KcIPJ!tےGcjEFt}o FoZm.q[K&JDtygdG6r Ay6 Dd0!k?L7(0*:ڵT<][*ԿƏ8p`Gg4Z[NW]?-]]$=G\V/7Y/etbemon-1.3.6/.git/objects/0d/0000755000000000000000000000000013455034520012636 5ustar etbemon-1.3.6/.git/objects/0d/abc35381be755323a4e4a91ef1478ff712c9690000444000000000000000000001265413455034520017731 0ustar x\{tW#YdDzc$m3m]е$DvlG&vDF-yQ uJt.ˣg=m.@@JtwncɁ-'t=~h,9^;{Ν찹c]}>\⭂&ʼnꊣ;57VQ JT}TԪ2+Ac r 9B7_9N0&oP@( ϔBx:~n= eMMo->Ize<I9㬶=d $%~nlw t}|yi3cǒmcLh΍mGZnO; @trj)E8G7.Kw>z?̪"ZdCx0#^ ,(" /,TuLo*߅S[|{ 0e`Tp?8O :-}NGiGC"$\NҎ-RtI J[t&>I9x<;vwoFF6p+H:عDz{0>M ]|˴ ]te0>_t/%}+ ŗO%&VeMTa63JB J*dJ*d?Sb? N^n"v7bllb43^A aeѣT #^73WiHyIIh^xT9ЩӠeڏ:'g|/ P%r;uCdLs_N3 'QqOk_j%ק$rh8"'Z> yZIt=y=}S"?Qvi '&_7bÉ!#pq0\g6\]w身@]| R5\rՂY) T2P@% T2P@% T2Pɀ'ֶ۷wB1v":fg g"e:327S1; on\.3sL&1\*o&mb)+Y?1s K{OTNE(Zbb6W+ڇәvQ(XhG=1i- DBe n3mڙ̃< @w7q<i$msKC ăkC3ΥH⨺k; Q: y,Uҹ;Pj 8(c;z85˞\-]uS(x^Tb0 q{V CG+em'QCMRS INx,Tj/GZ[+I).VJςL0t8Y_HoVVRUp30U^VY.oQ'vl`-Ҩe8XNgXy1qel|6q:Lr¥ 98'Iaԇ|}K8 m` .A{wZ mRcwXh GMI4:-֩*$XM>o,*P{Ǭ=Z?5}.?PTNf#QI1q~#e @dhۊ-?}-/kpOb:OgB#'A/_pX|R#$-3(G؎!J}Jh:nj2ի-z)8tT &D]5 cqC^Zhl\nS]?Uս8C @qk[5qHM@ꔶFeʵϛQ_`$_-C.ޥm 5\5?@)ˆml hˌofr5oQ2TC*ݞ},@m pCa~{Q@uR^ a!VD slx<9% } 'nŹ2߅+w ^hVH"юYzHٞ$ I[H9M̕NiwMإD BȨ=6a" 6$%TdT*P2 nK4Y0q]êZEPjl7Fl';XlVr:JZ0DǷҖ9`T/ GT& ۝߿% _}G@zi ṕflBZ%jKzW FMu@ Qiq+˙}EsDb4Bis`_tig`Nj"1IXuM'KNB%FoQFoF}tH5\HYv&)܈cI+JmZa[!I*?9& ؋f)ٱlPiҘprBPk͎'ڱvm ~Hq ئ80jgsYȌs\^X nyj7thaַSP)WVXa<3ӎ` Ho2\H!iޠWPOfb4N<+kPuB xғfBkg(23)O~Mlw {눍 V l1NZ '7uNKU-S ZOבtҶq'N^Sʯ`[)~\S_+[OO{tW(/fY~8^.^-v?*È(܏}j?vRGu14}Z?VX)(/'\*bQ_hY>m_S;7k)|an_\= _ns%_&J|k.r|'Q}EB=KY>l48pe_O+RyQRI ^Gڥ\{?/E7Uv!!2/miB`Av5SrJ??o| Z*O&l|^Q◊Jv<,c4 1EK+?B|i%d4:ls8ѯ&D[XnU_yx^~ ɟv~ B.X+ebaصko5սʏd$*ƍz|XCv3x(gx&IU-ֻãm9aR3 }|̓FSZ0{)R}fS<()8ff돺Z2NzZ$pP[KSq>Ï+6WFkg9OkL󼁡=ylq)9-?Cuc3'G9d.?Jt+ lixauWa̢᎟] C,j<;{59n-%/5naA [?Px !q3+4@‹UL5K3ǧݸ:~<\;((>ƭ/ZtLjn=KTZ!9N>ӿB8QU30W-^|?HJ Gi^^%X+7.mܫ<ڨh^.RGuxRW󅛕+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35ݢ{%\\q7tW)Iy [x^RQosIϸwҧ@'3<t,/<O%D6$e{N,^ܵsyմsg;?;A(*(a`pޖlҏVmr1(.$cڿeK'<}rbk{!*JK2s%A{Bԓ9-I?'etbemon-1.3.6/.git/objects/0f/0000755000000000000000000000000014173222475012646 5ustar etbemon-1.3.6/.git/objects/0f/1a3f9bd54559a4379076891888ec688102bc1b0000444000000000000000000000005513212007145017510 0ustar x+)JMU06`01\l##IdeXf2ٷNϗ_<-yFq+Hae>'&O/f7]dQG)3&[faҹ*:oLIq <8b%ftF>#Fff}dD4ax2[.IcE&i[;N<@0WBa18g. O423LjMBi4w+8%aQyen>$s se<tX(#B,.8_b\Gb 120,1fuǹ62ymIbӕq<:60kgId<\6XX$ W|8Hiȣ!(W'Vxeتex~ky:jV7á!c;Sv-!8hGPX2slx30em8ӿSŒ[Xj<&PA}fvgcUh֠ީo`w2yoN)4{?nN'Ʊ^'[g]2U$/\/BK]%HlUa~YN Zzh~cGvtsA&Vㇳ=Idx~Nc w1 p#y0ۄi y; =KT-=+DħPˣ>8"(iKIL-F&JZAC +}W޹͊Ȧ *{H_CyvJ9!Yx`FwqLjCXS^<'+P.n|r?Pe msSj[ R&.,_ܖ怛Snizny)rp-B@`jc<v(i<}B$W!uQ {xS!Nyd58gqﺝF5G8f+Xƙ*rnxzJCTצv[L!39@iDtQE(Pheix4ăGPyc  FT0{ϓ%x?$v 7uʥ$KMTh9Cn8[k J!1$ʨ20 Y9΢c _ʼMQp<g)87H ޡKU8 .3Llc>.2 %cxT/fYgi⾪wd !@Qa=OF HcXYZk8#1YǀIq|LH$]N|xb $MO3\,Yf& BH m.8;resϕ/ y4Ɔ|Sp}q 0>B4ӱ"ju9N|/&*pk (:Ñ/ңY DRӸer<\F)93QtGU*g~9H^=úoEH6sa (!t^0P>1T(8 ԅC.#V*c_]I19ؔ *ܴ #J?.>}G9^-Na G:8pB巤]w#>n7ОYccHSr>pI8%8DX9$h=V ZI8Pq P+܄nǯ7zOvu8]"Ԣڂl: x%PЮ(NSgD̃U4%Pg>7Uˎ%ewH6eAoASki8Ǜң'8>67_A#sO0]p}2]F,fDXҁ,>|oԛ*P Ve7z'0 |pAX;DZFPgyYjc{^gNQ !z +|> )Ч0Z@ܹ ̗s* LEaK&pQB!9qQ M?D7&X'B0KxH?1%D? ˷T^!e:UR>TɶKDGU*db5!VpP@w6XAbV.|;/Es4#ylvk^ mW,5 %0 Ƨr05a> %yZUtITDN”ɀ~͖10a o1+6b6 FY-qr2jȫUOByVpOu""dC$^8_RBX n2Pm @,'7؉ @jšywqI^Q`{FO >نt*X"_68!$n"8KK?0'RX=~kn1!HLH'ِ^g\ΥKdVDonL,b#]6t+VK`f}Ʈ6wp3Ǎm,JfDp*k{jz9 ( Dћ%%jU *1B8Nvu@>2)6zi»m5E, 9 _s-ϯAKTF l[ "`U tӘdHP"<ϦMD78{#6Sy%$4ߐ[vɲnU< aaݭo^hL,M~Tǖ8ڍVL{1Qufkd98Ch BOÛ --g|:s=p9ݙXn&D[VTQ!yuME_$(o\, ȓ=o}QQi4Uܐ +K?'3j#Q_>|`5[[sӿi8FcX9e(%T҉a/݄ÅКL!0SFzhol|'!?ɍ8FxKGH9 '48Q=fW˖{D1[hC\~vkQ@0@RKb?| ˒$(b@z*O??$wRvm`&K8wEE kvJW.yBXyAs~)9lDž<36 sxz2dqi%ⷾu6LQ ;sXrks>\|^p;K2H֌is>NE&@" Xxb^k\S]( 2?Fl&7>y=C]eCpB3qYΈ?j0cz$Ч7^< Gp.$X W,H738VP_`(0GMÁD `''Ou}\NCUrz_K-4*rQ񓘣7lD/mԟPz^=9OO>y'T퍧No$=x5 ՝lN?e < U3\hg [pU~<Wֻf 4è >(<;QlFk޸$3 jl?-`4i#Δ{X.a$Xߣ,nI Ô 3-8Z2UJ6h-4(2Dw~{=ƠEuJĵeuOhjeCH ޓ 5I}K"8NԢ"I FFn |ZaF7hLKOBoޟ |cswVSݸH 9:; YAP"\Օ츀kQQbzoB#4oܢ0W2B<Bn_qIy.127ũLod5;\^άnE[V4=dxދ%H]c IOKQZ~ʠ؍U'Ejn?-;u<,MVa+_2"|Hƙ .qWs.רcq `m[QMCk]πuL" cSRYy|ʗzFVJ&VRb| H{bȊӂO;elx]N@ KYuu*o[Ommf }@uFi NMõ3E+߂xp m\%uVX.),#?@nH tTGLVBԊmz8.ү" VbR?}ɰVZRVwU* ËQIjmസ7XPZ y#N3tPRY2E/^L~[ڮN>YT.ᱷ;,ܚ`J闧NNEn Zv(ƺtŃ-':D{hϡۖ^ЭĂq`7w[kآ^[aக@:nopOyhʃl(>yx2%= Fwy pOyde~[ЋyAtC#44#$ʈXCT-y88i5-B"dJNJhMMmN[|_9iVAX5K6Ժ 9}z[:POK=2§0^V.AIq3WM .*?b%TTb8?Tl fًӦ)`Zgg 2 _&w8XRʞNiOF,ŝU84R+4V;sޜf4Z![7 5YMEpVKT ]b f_߰³/ &D^HZũc)V (鑺߲Q**2LPXl DX$&]8h@$bG*=e ۡZ]HA[f=`|E*8oRVCL ^䮄k.A`t)5WNa;~Je-.wQx)<!#[Xb7(1=4 fXl#A =3wCkn'gVPo-`<́a8J.Ѳ"p]lR[8Ec9L{SGdžVltOAic\hD4: `ipŊv-0G09,)U6(B1pW}Th=y$S)$:TB|WD/k F p/dqם\! C,ӨP+YpXh7'$yi5gl,`y㐜ӻ$f^CM>9z~//$ !`( >GQB\;(JЩ|2~"s!X ~Y$A 6]Ib<e,x3M,brӱ}6[[g~f̵RIr .n(P)>@ylߒÿ# A]ws ?3hum*tnzNХO*5п8JwoQBU=D9wc)V  pQG>t{Pksq"klMð +vqJeɟd_O ' "fvG,:ZdD&/[E+:g>qW}p éW`.>}z=HN{*˂D Iph'g>^]U*-\jpS`,SЎ?+n.Q15 dh/p zjK&J ?jbFJ 6٧A^l@2…$|DN}2 S4e* ٱ l/x.V(#X^GzӔ{t&^@K,;LVo~2TҎƙ?:fJi 'ب!hKHoΤ@flr;\ "^͞UykV9n w i׮Gy,3/>~|%p@*Z[bxhd99>pE7]!Qz`~ 59諽 xq:2rJdDi8IͦM7DM"RInR?zV C\]{T" EFdJb%hIT h փAt۩l D!f%rXfM%ϒ;m?=zr)SՓpZ rK|w(-X10x37D+f۬߶] oN:Jq*uEV)4Z^Ei~O\*mZ i-řv?՘yi hip%I{$BI [jY?}[ۉz;&U`Gh:VdK *4^כuU:ЁcUe6&Z&)RNL21P{+"WWAxYbA m {A6zTtc4ȹ3WtZpq Qp8+ 7$(Tol ܨۀSFlҎ@4BJ!Xq.*uRF/#`yxYU2r ˚Ǥ"4=$% 07k,|eMٿZ1#22e`' *.$Pw:kO݌7:Xw(Y1d}|St6^lkhJE6eȩ1%ό5>ڈ617':-SvFLZɀ}gK~o_ڋ?cg(␍{lFq[Bj aJ9F*5beTRGR6++Faj&d3 X36>%jJ%(A)(AU"9aTC?~6Нfz~2 N?vG-Gnx%׃/ .qG{`YXjQ2` ჵQ--ZտzTZ;ß@㹩v/)ܟAa{4.Kw[̸:?}% %ig!te6CnRXRǚ88 gOI]UK.+S>V k؂񾉍m;B%zt|ճetbemon-1.3.6/.git/objects/0f/8d9b329e1a7b9617600b86ae3072a8ec30102d0000444000000000000000000000024713221737242017624 0ustar xKj1D)zoZ 1AK"guމh8s[輁MFjf1_iW >FIetbemon-1.3.6/.git/objects/0f/d7bd7a0988669f08705f188caa2d1788cabd900000444000000000000000000000141614173222475020026 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3OuKjXJ)ԼbgLs|B@bówM. QǠzZjԣj NXnw1TA~2C]ɽɷg|ݦ\pjCdSKb7vKΕۿI 7r:wI\rq? XA4eussa!?߶\Y׼B/>fCgH_>7_ӫW\p9[8nL3Aק*EN5er{[NJ?Z}I@{؎i-cȉ- خ셪,G [CA܅hޡyAf}MqTHpO `^24u릗JBJ5cuo%ѐܧ{?\q|Sh&b껄|ܥ10)]NC'Y!te'ih;mn]}S}i䬙6oK< D `˫hqef] ''Q6h`#S>sєRP2xIoͣ5ɥ<&?5IČ{˹n~4SEh$> OҺd.Zy;;S7b%ڞi`0wZ!v)ϻqː@$amvCfߙNٟC()Ԫ-͙`n~zٷHLHݩ=ڵl֣Aa|GmI"Ť,8՝Ӻ]WY29z7vZ3-ͣec<ĕW EȒ#( DG+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3'}gWuO=%RlrNfj^I1ó k_>v 1ٻ&_HIMLcXyzlr_A'3U[|{mG=D6(+vcM@\[*Tn z#7?sלĵ!zWcހZD3PV7'?91Z[s,~L} \P~5J?=?G^8dqke: z>U)r:`|>@% .3rVܵMB.%pvLl鄧oCNlq^v`/TEe10>R: ., dZ+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTPv.hMvZh)TIIjnANbI*Cպz SD2dǰ7!aMw!9y% 6}RہĔg\~"%5)31a׶[ ,2*`dAʹ 2w^ -ָ"ZP={lv_}f<M苛=^1ofPh''Â+hPFΗkdW_ ,yWeMCr? p1z 2>N,^ܵsyմsg;?;A(*(a`pޖlҏVmr1(.3cڿeK'<}rbk{**ewa!O SƾךW1BTd3Kv'sZ,d-+2<ETetbemon-1.3.6/.git/objects/10/a5ac4ec93ea71567e02ee9a8606144e5eeb4010000444000000000000000000000120613764407317017772 0ustar x+)JMU07d040031Qs fi^5W~AE-@V\̐joʫhrgY#IH-I-f`Ѿ")p{Rܛ.3$1'g,^ʀG[9ԝ >,,'3/a`jĮsʯ]j dKP=Kx| hrU_ؘnl~(bcg *JV%(F H2GU4r{u;]ZMPBQ)(&-lޤzEֲS D31hjVIa69yL l֔'$g0̴.sq> nH44-Setbemon-1.3.6/.git/objects/11/0000755000000000000000000000000013216421174012554 5ustar etbemon-1.3.6/.git/objects/11/0b3fea820821c6e8a354d3caa71b912e0271990000444000000000000000000000251313212012067017602 0ustar xUiTWQ!B %.PDLI&@ u9K]ZAP,H=*V@ J93g~}}AOxzxy4(CQ|WM A?25x&bPRIx(L(1+ɣ^ؤhқchZq AVRnݯ;5r[I"0BgEUo=3;^[WHfHd$V._-1 _<CFpJ attH.G<ٛͻVfUxӬO/ncQPcD[k3>H*DQ:A >J5"28N[7L).i׽0JC7cE7Y L-y 7NT1s~d21 INe;P7 g dӝrQMf˽/mHg$jERl1mMѺ,\&H +UzI:u"ɮ;<ɥFn~F2C_X;jK(9J!}*2WMTY6DǮ*/i5J2}4ӄE~YX6}Ur"SuөeC]4ws8AjJ莇 7)%ՅS=7nS"MO'pV t ;4bT\p;oqe#P)@BNOi[a=~&k+^BRTf\v>v|]cEs)hܞcbVqjEA+z/?:V:wNXyES⚅]F9L Ba4n-' ~~-ۦJw sf >IuY@wr% Uߵ4npJD1`^XNϯ4g{X+,zPڋi*YZtMɐ8 #4C`cQeHF %ҕ/ r/ 3Әm.@Tr3rldݹۄxFp:BqK(ClWk " T i8 P.޿cצ#+s:0:IX'\dM氩acݵ5Aniu@Q6dxLJ4fg=ԗqM-gR<)i 1ڨ'Vn I\uYsƭp٠BL`!+ &BZW fɸ(|B a9>^eǮ?#^etbemon-1.3.6/.git/objects/11/2966559320471cc7b9d5598a519b1681bd74300000444000000000000000000000136713247732002017272 0ustar x+)JMU0400ef&& ~zyz =k[7\ RZB:%3]Y-Rj[/4*Ǡ^̹9>H^yUeFfDO[,$faueP$6U}%O&93g̒b75Lcg_r8J .>]w|h˹Q5$g3\l^6)<[$Y(لܣh Ks}#.pZJS/AVTEp̰͹k{¦~675UFCq^nAJfqvqAbr*\_l266}Zk%uؖ.bUϵZo9h:JR&z{?ţC)S§yEєV͖S@cק:(%~W}faQ]Zp!b]eH_Zos~j߅MOJ)f%X׶raXԫZݛ؎Cde&B#\Axُ^~+1HIV]y,ִ図6㼉4NU75T(Z0<Ӵchܺȶ/ m sS XC>}ߚw8r25i9E@m c{*@gX}5m|m[_튀etbemon-1.3.6/.git/objects/12/0000755000000000000000000000000014173221213012550 5ustar etbemon-1.3.6/.git/objects/12/418dfd19ed491aa9688b481aeb78bbb44486590000444000000000000000000000127013212010712017722 0ustar x+)JMU073`040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35ݢ{%\\q7tW)Iy [x^RQosIϸwҧ@'3yG\ N,^ܵsyմsg;?;A[ZTP2c9˽-n>]$b QQ\ #=lǴ˖Nx1l BTd3Kv'sZ,d-+2</3&etbemon-1.3.6/.git/objects/12/5f7b87dfafde72f3ea62f73612c3586ebee2fd0000444000000000000000000000026614173221213020310 0ustar xQJ0E*_|̤m2t2y6%Moym O)lٌ<:N8x!<"U'2p"D lG)i89$)ALR*|] ^/ޤlxAa@DuH d]rCs `9^nvRetbemon-1.3.6/.git/objects/12/80d089d5797013ecb60408e45b1c35212a10420000444000000000000000000000126713212010614017276 0ustar x+)JMU073`040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35ݢ{%\\q7tW)Iy }n[N"* btm#W M-If8q-]+N9W]~qq{ ȷ 1tOݟ6]۷Y qL}Q3,XQ ,d^~'XڹjڹŸfV00Xroi[Gr6 CTh1_ⲥq 9y۵%9 ÿ=!ɜ$Y o2etbemon-1.3.6/.git/objects/13/0000755000000000000000000000000014170643332012560 5ustar etbemon-1.3.6/.git/objects/13/527656b40223d87cd39c7beb85682559bcb5550000444000000000000000000000141514170643332017514 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3'}gWuO=%RlrNfj^I1ó k_>v 1ٻ&_HIMLc%w|c =톧/mbO*Of6>۔+_{lj PVniܹrT>"Fn~C9kC>\Ǹ#"fnN~rb0,f0޿Ü+,U7]`t4F 5rpZgOUXq3jFiPA ˌ,f~ wm1DEq 0%.[:ǐ[]+ UQY N/ y2ּ?)$3a^r;'D=b$k1_Vetbemon-1.3.6/.git/objects/13/ac70ad777d419f904317adeeaf8656a74920a40000444000000000000000000000233314001503033017703 0ustar xVmSFgň 4i2tt0l_ԻwNdt2Sfho>9y+fwB,( c PQ>0@Z;]RK"w-Tj!h `y ^ôca܁h uOq G N)_Dd܁hl4'Y[>cC:yQܘX&SoqXe7P3Tb`gBN 2L>Nr,G'2ERfB#{ 4ӥAu x?߮χ Zzxm͵lF*&ٕb`P4)uo re6/\LIc-fey^(y$8@~Zf#LYjI&S#3Qnn㟰6[Tp7t`PZH ]de܎X|ecO0WȩowHW3[lgTH8լeVEЈ( 5Қvȵ͚a:aؗ\hM8ݶkᔾAt fOas87U0!ѪǸDk. #tJ8rj 7xYU;.s,xD,O[SM# .Á;>zW''))Ṫx*!}ID)vˆCK'i魜lʾ?a9BqT4Kߤi@hKU)TCJװE)x9Ci*Є5]1KZ`e:)`F.MkbѯfiTCyI;I*]QטzQ5v߈miV;:Vo/P< ď:apsBW_ШDetbemon-1.3.6/.git/objects/14/0000755000000000000000000000000013216421174012557 5ustar etbemon-1.3.6/.git/objects/14/56a48cd20287f69ca732c32194a11aef5e99cf0000444000000000000000000000025713247732002017723 0ustar x+)JMU047f040031Qrutue𮽰^Xns2CU$3t)q]cʳֻ+3h*((OMap~{oh66՘*gW1gbw%V3z7s˅QgP{;|$L,$O?Getbemon-1.3.6/.git/objects/15/0000755000000000000000000000000014173220741012560 5ustar etbemon-1.3.6/.git/objects/15/2ed6e16d4e722a25e79f16a22a63b67710ffea0000444000000000000000000000030114173220741017761 0ustar x[J1E*_Ryu(QLw IZo;p9pnmOPyކBuN"i4ɅXM! 1ڢT5*9cDǼqc j :\_d.xtF-(8r|Øzy= q +sA>Zetbemon-1.3.6/.git/objects/16/0000755000000000000000000000000013733114071012560 5ustar etbemon-1.3.6/.git/objects/16/36b2fbb87141699761afd436d66fab10e5efc80000444000000000000000000000035013604546701020010 0ustar x[j *ǖBxKo9Cwзfƕ˗^Un](t w!̖YD=S&Ԫi*|, ʅ ^0H\= ?Wk|V=J Le^`OnރF ;zWlsȰ'lL[<{G:jqt;`Nt=w\Fpǽ[RNNrW9Q ^\1{gwoϼW)Q:,k#}atVx` 7oՊ+ɮ +'|f6U_QLU}k]Cڬ赞ؗW?]Z g-x;3<QT-ufnx,~.>e(;FQ=0x!(/3|0vDY+#mԻd Cz;`fL=C5~xs:ʶ†Z2'a)g)sr2a|f78*%+DF34}4;W ]7f QLU^P^OivdC8rt(`טmӮz]:, R'\CCԡNI72fBA(O^ D( %HI&t<kIQ0AI⾊ڮE = ֕;!4w4:A brGI;# xϟ?|+mWpwS/ꁨMPX+)znA-B(?JaR9ڣ#s?᯦7%0I<4|I82)4i:OuL2X,sH~Y>##b/UMf#uE͸wA(wDu:S>{Qb˛:$?*4 ׮KJ!j#'+6@+1k+"*gߵ:dtȡ?gbt]P%-A3u>سu=4ЄvL䞬=7'=Pk0]>x.< q Ё( thޑ:Lթ{d6{X;[6s[Z=4]H.ܡ (!2ẩ]_=Y6,77߉}&k^`p3}na_L䯼0VQlD$褃}QU 9KT e`Mv]H@HIGZЧ?x5etbemon-1.3.6/.git/objects/16/8ec518624cc6f28bf0987b9bfb8f227a48d75f0000444000000000000000000002361213216421303020026 0ustar x}ksHN*VE 9 jZk0_>\??:?Wndq0sF&>k9.,Lƌlf;f7Y9?4QKұɣ0N3Df&fDxEGөyFy鯯6Lgp1EcSY4_A~o_E`כ4Oaabb0-o&EMP87^l86oi}iݮ f8\|t/"L {>]꣧aEI4Gڣݖ/p741y~*ҌgArhLӬ$0,b/ưfc2RYϓű;~o~kV"EfR5ʱX0AOpA\$-M|Cet+"QveW4ʓ L%3"p\@rHj(_BaMD)%+7A#2,nTTD=ٲr[\DP"aq0\A$#( g0t\da#T Os9 =_C(ZltnElh@/~9|9֝`M  X` 𫰯!x| gӡΠRį Hep|P7f&Gx?džY.s3[|{AAA"F?h-xU:0pіګZ@2]PԃqU /Nߌc΃6=ME1]$Y|*a"np3Y7 o7 l|6X !Qc a1`M(I{Uy#lA#; 3~&M娨[ ƕÛ؛VYuxe"<۳[2Ճ%5*wuL]d} z?A3d'q ]O/@Mł ڮ FoXAqE:q0+OZ⺻84.N?+Jl&4.XI:|@X^"n]\AkF"#?,fs53BJnVsHWݯsB)TCaNA/W<3A'G趬 k*˯u3ϵ^}I'Iԃ#<~L(qZi y`F`uVf HLӬXI \Za=0ީ+ւzNPURFY-`erYJFcZ+Y竑RHFEs iMԃF[ .Z(|su"N'W7|L4S$*nȫmvF# &H[d"A=?f oՌN`ඊAGEr7vqӽ8~´̗ALOa e,nX- }qaDw›eiȓunt x8,]RDq?28TZ|[X8ZctX'i_ =fqhGǒ-wW,&1= % i;0{m+Ot"NFD׋\qrZmz9 G҄/ao 1fhA* BF l,cJ*=g|EWLO/(D ">iy&`Z ӯ ,ym xK;)>'s?2LS)/i &/a*|^Es*#S8++_,'ۄ&\Au.t̘_P_ QJ ″0Ss'b8YCt&WK_ eexUhFgM1>uM+}d6x0~1ܒl)]-qyW"SZEVk8ݥ/ <{.`\XX s3lY)b ~%vUoN 6BIBR0vz5B+¿]ʣہ'VTwIy?~Ԏ\1V" #+~ 0cO[yMK9X=f0:ZO?ޕ.t;Tjʘ~0OzW\ +H(OkJjU0})F ZuO@=$s@,<{?'BI؃k/oe<*VZקAoi9i6Eyx'dd~h{:̡nOW"MN⛭JzPA35pqfKߧ\0:3\n%E[UTQӃȲ &䦲`iE4c}5Qw&T0TǪi}8C)\ J'fZVu k|bn5ջ~wF }cR:Ix* cɘ^(9QuV ė0cІײ/f۽_70QV%%þѴR SL+XO ,CzGٯw@W*LT S⚗Me|3dHy̔)Y"<&H@.:2h./rС9p4鼹yg%\ jl0%'qEP6̥z`Im̹pf!bFM^?EW+1X6ML]hQ8${LI(\s]1?3Fb&7>y5߷b(\Y_3ӳڙ,g$}%.2)'']مdgWB.Iz @*g L9Bmo2,L:6ON֯?;sK]rz_K-4ҴM]t^G?hHmObԟ PfY=9WO/}8Kt*|rCt퍧4j9 4Tg6k @I>kA؂)䝘H뽄g {jT^{)AّقZvWQEOLm P蚴ؔql@$(`0CϤ=J@>5Dm-R ''Ń 4~#dK#/_GN:ʙgF޶EY1ri#f(|7@X*Q,̈́?C%S ?fyKSs:<G %Q!SZr I\^ϼgC'0XEG"!~bl4ؕ%p$s?ܕ#`@V iKM)-G`4& E ەdNϚvUyi4ݰ\]ɷZ`'#RW`VYhrkvYFA5GjvZwa6 ֦rD%(2)ёr/K+P6ia/n2i/ wz?QNFdp6wY5gq>i QtLu6 J=Rƍ*;<pծőK9g,Uf>{݁zr'Ђזtԑ1h 3ۆPl?96Arۓ7_`MT^qlL$(@RH_֯QVT fYCq3cQ~pll`Yz)nӷDNsKITd%$_[E0K!h"4nܢ1`%9Fis"N#.oۜZo@^Y 5pUrk22=$=ER dخY"X")=a ݮ/2vd=@s'uWU1ߊq}\,M;BmUP-\?^F.|X&LyqKkEE`" _?H8; XǢ B{ ArSYyzFU*Vq =/c^fjP=1d%i|5X/<y Sz|W,,<$4P %#KjmDFK&'M(Qق2V2b ѵMܣI~ 'B.It28 lu!ss#Z/tOmEBa9x-qȃ> "{!)qJC7+tNw_7ފFƩ0Gmв-̛m/LY(i>CƗFm;r;XWS5 amp)n dPv_!قEX@4/պa݌XLk/Bn_ҕ/vD],~}n &'x BkofXrGz+jLAV2*A9PK'@+ b@h,G*{emVeJVtLŲ$>~F ӒIæ. yX+q܅`H $91)k8bFdS2Ta}CW91wՅj^ku~{h|KZQhR7eqApz+xwEoTZrrܓF9Rc.şNW؜TC\K.j>fst0Q{rA[,Hqܜ$"5cڂ\ֱK`ص  é ̃X2L=x*ϛ2L,yjթu.c` 5b ~C=BѾ-=­o^> &O !=(CqrHGsL!?Ĺ$F[mׅ9I~hhAj ڬя4wZfG£_']~4ꅯ%xʵg[} te0V` 9E;_S&"Dez7+) {$W_%yf]ڽ&g%} 㔒[sN Щ}!^5hc46X~5Z==Ŗ5A\b#*088x33pȼ47z+7Vv@n} xpӁvq-bB^&{ Slj ֻ_Nv|%clhD ݎY0XOS!+dsÖR0A c΅p[}th=$)$:Tֱ14\%-L`M֗!@wݙ)2~y/Ie!H8rtbA8MCփgla9wi Dͺ2fԛbr_^P40CU(jZmS :O%d.wRovw*WHT$P=akvv Q~##7G#l-]p-w y-LNCd/Xr/DVAOT(-yqHPPy68<fpֱ=#IPt"H]ʱ0iVհFj:XJ6woF<%AJ/X G"YIhG)MaꁀA}g$zlNB>)@;[Al?m05mkZTD&/-{E\D{%8B!pV,OGus h~a3 v̇ݽ_+-_ qJ]%cYwxaESP@-L uB)KMg43p$Axl߆ޠ4wn[s[ :<<rHzjKY @XSRѭ=i rC(|r`0lrbAx /GXU|'/Al,q*3>$ǕgؔvYd8d wlCKX EkAIf39&+{xV'op>e{hǒOjDxh&.bR_(`1s8b+ X[<X*DH {+f/ vPذ@`WpaJAǾl)2$ Sу.J+2JqM9`c%wx/vԨ"X]GyӴ{G4E@g.Dzw0K[e- zKeay S(=r`0z$7g z06`J^"^͞uyk1EtIX1H@ӒXgI6WO?ESDs-5{^l?O/8HEMl QyX2K?gi|NYUaz^qJʛ(7 'Y|j3YAvҐI(iʮgTwty]kkBieRF<. ߃aeٖ(C[55*b LѹTv=. l$P*N դ.'܅4vA0Rm'z8bAL2B|bn nR?z5ՏtK3<%6c/PE !u*$vMԄ+AU{QȋQe6mˑ,KeW _]}b<ɬ?OpZmn%Cj@ZPj~݉OGaˤ?DE UY~α͔M`}H<=>k4[؁o=}%Gh6u]Ȫ n#icEQoK $םu3~TRJ)HdmV&IlLK5*]w'[c29rH%O:$%.k5NA"mYwuԳp:`ݑbuCY6:3fwlUb% jvjAؤaLi8/Iz*\ g-sQm=klF%aTQoEejf-=#c` GEA:FIt*SĵWE_6TlDzqtp^Yf'Yz l5 Q +R a[HIA1ȊC$LQi gBfyCLptAzͶfkd"d&iBfɁ꺙mr7kp/d5&{C3i.[3nedi;IpH *w.Pw>kOPG";TBuc6i .c1|q.G thL3He2H3q"IjT@̾0E%䟱h\#FkY(|,N2UE67cJkOPIQ6iq.~`4Jsh  : IUCIS1T*")(.?t-c6aktuFUօڼ.#CYh#yJE5_fٕ5\FɃaaeˈcQ]!> X=n  5a3%g 7\tq5BO*,ط8R(Flܤq%o@Wx|)b߱+j|UjkK1Ma(\Zn{߁hnY ڂQ**yetbemon-1.3.6/.git/objects/16/97c40628c533be63134c3ff29cd699e9381c780000444000000000000000000000126713212007540017525 0ustar x+)JMU073`040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35ݢ{%\\q7tW)Iy {.k{lϔXe[+MvB'3yG\ KD ˖Ai>?vP[OwmgD3PO]23yGMϘ(b1G4@ Rxe|Xbkiv vQZTP2c9˽-n>]$b QQ\ #=lǴ˖Nx1l BTd3Kv'sZ,d-+2<1etbemon-1.3.6/.git/objects/16/a3fa1fe06860c0142837721b748310fa7292e80000444000000000000000000000054413733114071017405 0ustar x+)JMU011d040031QMNMIe8;?nN|:/wrq7jMMJҊr2KĿ2sIt#A KII-IMM,(HMK.(`uy&؟jRtW8t&0lK׹KVz|%u3Ҁ>).HLNpЯxQĻlNg: 8'3B$5z*nM|"zGx̴SXW*BWKYhh] Z*-@ ӷ+dr9{lڤPUi%E aPaS`m^TUU'+^B kSS%%uN׫i2|Q1= Vetbemon-1.3.6/.git/objects/17/0000755000000000000000000000000014173220144012557 5ustar etbemon-1.3.6/.git/objects/17/507c6937bd55c2326451e05a878a83b46e2c0f0000444000000000000000000000141514173220144017474 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3'}gWuO=%RlrNfj^I1ó k_>v 1ٻ&_HIMLcXyzlr_A'3U[|{mG=D6(+vcM@\[*Tn z#7?sלĵ!zWcހZD3PV7'?91M֝/);p`a7n >fCgH_>7_ӫW\p9[8nL3Aק*EN5er{[NJ?Z}I@{؎i-cȉ- خ셪,G [CA܅hOz22Ib"#vYetbemon-1.3.6/.git/objects/17/c3b69b7c5c1f71ed2bcc115d19d9b3b071742d0000444000000000000000000000141514057336772020057 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3&Z̺ ML+)fx4w'$?<{)Iy DZs=dveUP u&'ߞurŲw}|M-ʊ--c;Wn'[$c5'qmȡǕk77`yV ON֘{+*j߽]N7gx峃pU@yט[ylP *W\p9[8nL3Aק*EN5er{[NJ?Z}I@{؎i-cȉ- خ셪,G [CA܅@2I&[/O;|X-VLS~T8 ' L&'2apH/^)W6J Ҩ@vD= 7b:dg[] k;J ˅n{,[o-IIigbS/Y^ psZG+Sr.P c޵<d+St}ljWetbemon-1.3.6/.git/objects/17/f44cfdb499a45b83274ce20763e70b10d340a60000444000000000000000000000244513455624433017641 0ustar xV]o7Ũ&Ii 4a'K;J"|"$϶8I:Ro?vggfW&gǏ,W:Irު'қڏF|$ jOP1%;Kiǹ+݈*l~eEM'gǻ׬8ℒbnVs\ve͇S5$.̕#\_&LwKe+%*0B{R0T8 ŭӑ1\FxCX|*Ja1XP8Hr7Lo]/qc_bs׭y} :_qoXQL\Zw]k"|S',]dw]0AeR--m1΅^΃IyG a$':!wetbemon-1.3.6/.git/objects/19/0000755000000000000000000000000014057336772012601 5ustar etbemon-1.3.6/.git/objects/19/3a48bd502bcafd557a71195eebed4f2e45003f0000444000000000000000000000141613604573611020131 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d`|z3שܩ5jϜS 5yBds2SJm0] )5*DEJjRfbC~PZMaoW,*Of6>۔+_{ljI2k?d}}Ƕ'ڡcw+ <../HD3PV7'?91Kw3 }?n$LhNJeFY Ch^qAj2/ρW,w\^5NNP3J+ J\f,g4ۭk\!*K /q O8⼀Z^b`|05tz]XȔyL%9 ÿ=!ɜ$Y \WCetbemon-1.3.6/.git/objects/19/4492c088e9dd3644bbb9d3a3c549dd81b6c0220000444000000000000000000000222414057336772017735 0ustar xUo6g7MC6n` 'ۗ$ dPFRI.wGt{r?M> WKWiڨ<1S~ƌ,I,*d'XVZ3᝼g*=4L` @rau؍=VsPC= , Q',-gqmCZtco5 6h4"}|R6Ҝq8IJcY@L /* i7w,5+1t&ApvIֹ/~<}l{XguH5Qzk64M.RYk.ڜnuoJ/Eu+Z9jk 9 z+Â@63/eTetbemon-1.3.6/.git/objects/1a/0000755000000000000000000000000013216421303012626 5ustar etbemon-1.3.6/.git/objects/1a/5faa1b28408ff4988c7c758975aa1a73225d710000444000000000000000000000606213212011530017633 0ustar xZSʼnp&fjM w& eY^cP_f{v ee~S/~?;?y:1n̛DB{,{qףgO3ꞟu?zx@ok B0s!sʻ\)bRap-҂y#&ذ`bAi&VI};jR/-?‹àI'DN9~۳V?߷0bɔ߄h>kү=Th.?"'NQP)LN#UkZ%5R*FH" G2=#"q3"Kq1KbښͬpX>ƃF(lL]jo`X7ENop^7a^6xi:J& U56T.7\CV;'-$i~{Đ=uK\PP?RY%{`f>u&YvNBiM '0&vx䓮Ge`3iD]T"٢I4?6r8FQilW 2B+8^C9z&?|6q5zR-J776y#"birP$ר$qa'7Hv3bYC."襨-60/fK܋ -QL \{_SG7fö>y 3fmIdtij3!˭4jZ0բ&w^u$x Qsda:уn.wBtnc+ MwhHFu^;end-tG #ΈO[Y(dn  G77l0f3uVꅍ뫅< ^pѓ~5MoPJ#<۸E?]Ab-_| k \6,lKсRBCnVsz|-jYQBov䲭"qϓ`X%VpoI<;ב*4|Mks67 oU_GY/нukiNYKWtݩKN/)Ýqq4|4՛dgy$*-UOŞfgixnnh'1Q~5ڸƨeD5Nla- N1( qO ΀X >ĉyfkU`^21[ŎپU^5@hY=׬{ /&HUiq3}ƃ|7] ?iVVN8XXGDzrqۚVm^PturoB yA'4#[+$y?BZ[/wp E7B>ޱ yRDK13Ao^%@}b)+ˑ_!82$9xV(cw Д&+MTl ~Z2-zE-iz74-^QHSb9g+:b?y#,I5/,oF[\8Φùt30ׄ0.DM0̴%&mOHRŽHum[ z|v+]Jی7WҽbE_嬇-ڄAnbR e g [O[W;O )B#H 6B8{I{Ml `LFI7:8j冾_X_Ǻ{=͙ଃNvL/+;L 3ZuMo105K!ýh"c [SSnc~u,TG9-T7j+\+sm"o1f T71A9f`J~sC %joA= Jo0gf%r;iW'#ߘˆ* V? >Z$pQ%ۇ Fe4922etbemon-1.3.6/.git/objects/1a/8473941d3f242fb31efa6e940a2cb27bf009790000444000000000000000000000141613216421303017703 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°j]͇{V]|)eg 175*)I-I,IeZW/SrP]t"U 2Xr?36$L!.D69'35!ߜ[`i7v:"DEJjRfbC`_֮n&xRdAʹ 2w^ -ָ"ZP={lv_}f<M苛=^1ofPh''âNQT[Oݭ.[=< (Tuk/5Ӓ~q  p1z 2>N,^ܵsyմsg;?;A(*(a`pޖlҏVmr1(.3cڿeK'<}rbk{**ewa!O SƾךW1BTd3Kv'sZ,d-+2<KTetbemon-1.3.6/.git/objects/1b/0000755000000000000000000000000013604573531012643 5ustar etbemon-1.3.6/.git/objects/1b/20ee554a3301cb2a18e7f02192a0025224d2bd0000444000000000000000000000141713604573531017565 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d`|z3שܩ5jϜS 5yBds2SJm0] )5*DEJjRfb]ԈL^>UϺ0c MO=6eW"Z0ze_߱mv7r]zJf91e/ ONʃd읊_>gX (qғ09)?sU>f+ p1z 2>N,^ܵsyմsg;?;A(*(a`pޖlҏVmr1(.3cڿeK'<}rbk{**ewa!O SƾךW1BTd3Kv'sZ,d-+2<^Wetbemon-1.3.6/.git/objects/1c/0000755000000000000000000000000014142105430012627 5ustar etbemon-1.3.6/.git/objects/1c/49e842c402dc66b7d5524c441c2539e5bf649b0000444000000000000000000000120713455035510017640 0ustar x+)JMU07d040031Qs fi^5W~/jbW|W^Es];Ӡ8IMjEbnANj1I+&?<ߓHH ge$0ш&ٞ;Yiڿ%͹.fX5X,AZ6蜭k*")*/.ǐw5۴|V5)+eoW}ac>͢o(lX*"ϛ?rUЬʽZxti7}@E榦 E`H>盿siCk7Ms31hjVIa69yL l֔'$g0̴.sq> nH4zU*xetbemon-1.3.6/.git/objects/1c/6ca44e3fdeb45cb24f1acb5168e4a702233e960000444000000000000000000002707514014616652020134 0ustar x]kwHr}d7IJ{ֲ='' H"V$@ɚgުn|ٓMfFnU7thAF41ςZޟ N,(~?r?œWG<\,q #E*^E^f<7yfE\Y<D7f'&EPkBmBG0y54q}}DsMм-l$UǢ4iCUiXY8$̻OmM({M,kShF)o*EPp'~GV֤L's4yC8/MxUFJf gBK+"Aqx-fpy!Z -A~]p{釸eN ߻CpqP]#b0bH$S2G#SDtW|pX 0K;:?cvAHF43cmWdbbMw`#R-R90^F@%\戒 d4X';{) U,zVw:cb &rPw ]X'uK\Pjq/vx?,rE0o>}5Kg,'"˗sDwxS*O=!i .r!KD RC0o()Q(H8ʚa2"ɣ;t@BJMFb,B5uY z!]#@*[s Yy\@y ] Xc]j]ߍLqLp2Ad/`%NgsU ϑ K D!cH/̀*Ţ"yxKrLZrJm$b [\>N̰&yͺI.G#\7+ ^Y9Q/mm4|vrz~V+p^տD~8ϗ^c =(xY^2Z8jyQ%>H:ҋ\H}1  yp,̯U..wUC%jډBI.٘" BkX: %G"<3x(Tj2y͓붚w|ƘxjP|_vcw״ke'M ]=W6}"'pٷqR{m, {Q|9NgEٗJZ-$Y}f$0?/gL5A_Ga׌D~LJC2zmtsxoO%;5NY3548<~Ḩ6aA/O37z`gny܇&"0ZaDNT+KH,%F"VMNY> >sm$Ij̖nB 8]榎5af%Z|֜W Z9 'i۴ v HsN8IYUŹavTM ə-Qb/X($466_Xo[6*,>Z!vM$ka02V|[MLfBN6Iͳߛ7^d ]]xzAڲeh͖`*CukCu-_iC6CʈD*ǧA "W+\sKZA{o~$  n$M['t v WQX h*H\t^BL@IH,9"yOv:PG4iyL1 f<ڑE%E0 K#L:h.9ey"J<*2G>*F3iU䡳p$kPV\~Wߤj*hI8O 8G3s.()sq P+ӄnǯ7z7!fKx[bZ=7[p$ 4oA& %jd+jdwHoy兔G<ޛ1Lr 𮏼 %s[x$27Lp1PӅ֧yll%yÚ%FLeg": BuBjXޘU?A.ȀzoD#ˎY00D=I {%k+:~|KF&5 谤QdZmVFb]T0SFUאp $GPPD]\@8C& Qr4:A\k:@0}~s 5#WD#ⷤUQ>TŶ m+$m=X %%PO8]*.AZRTGGϢWh,KIb_n"yK2EK( $*>5j d@ )L^(Ek^U+B1k:7L?l`@l\ Z[WYuxG6R0CgtJ^F.(pai1:g "N<˧2MbA.W[0p( dc=`%bQMWc. aN] :JS"M1_̯i BCv[AL^-<('YJQ'*! 5 !"F>߲2,+KuyƬl6wǤo RA)Qe=Ar{>Y>Y)MbɛDIWիw-pQtCF0~[ܝҺ#>kTTf&cO<:)ړF[s.ZFY`MlW`v<F\{E3A@99&(!ٰ:c(1DSV213CVu3訨٫9'~ôh*ŔX dʬc27avKb15ə2̀ ŠWӨȕaŰH[Z>7LhPdG)V5E9<p2ٷ?D32غs@`QYL4o{nBF~:v`P`WX'3ʭxgv{x tS֫3p$Ml{no 1x A*] ԥ6GT|~c >"+'!ݸ,({߯<+-u;- ˃Ѯk1LJm{mk'(0])M }U,ug}} e<zqV,ÙW>X%O MZ.jq15AafMbPsه_k՛5c $a'|Mn^#"5 ?xNB1cAYv49+~V~gcۦM9}5 DX팰9_YʕƘ*bheL?_p^?B RAkJjmi r9 y opG- ֩r%RT&iQN jTٗWëx\9halX_zK{ѣUdsq[>$ Y-a"9-shHw!MN,d;>vJtp3Pch0;3^Z>}.rO.љyw+ -JF,51=,@kBn*NG}kR S (XO _Pb^KaSTЯkcזJ$S6U#״ Z1RiLdH)6,S^)DE y5LVV CX3|jK׹v"}ጜ%Bو3KZnc'x 71cۿ$#䝍AfE& Mő)-v\\7\T͖dNOvUUy~Jp1 cʇo)?ٕ!1+m-n2yƅfIumv/lKu,36*C%m ~؀PonKbc[MN8BuB؀hc6j똡0O qIvU(W;@lue@{!Ыƺ5zϵWFZ-ʏw[7c쥰"6o6/'/ pU7" .9! 4a\㉝l/vAI`*ae-@NkǮ-)*Lh2O,p rG e/<9AAځ.069:W`[ 'VHoM@XrA~@h;fr7Zڹ@SGzGa BA2d -W.MyZwi-Tm'YTcovDH+q_;8#-uw#&ņ#xdSuMՉ;k\*-nFo9%JˀOZ[$ AntA?+k+&PsKimůHg8`&ܼz ~/<]y Sz|W,,')Y?e{dIM=D Jd k+.Оq~^jK@i!V$Щ^Q K6Ժٙ9y? S[p-PXG^K{``Oe`<`W.!{^@O;}v#;Yb>BEF){ Gmв-̛m/LY(iYQ7 pGsK*sj4:]!,2 .ŭ CEir+ܝ-xqcNbݢZ7 yMEhAh~ PJWҿ)v`K󚧛x68 ){[ ^zxlC '=s[Qi [qPK'' b<#@BBeI޾AZ]52#?1 &ce]HD>~A Ӎ>1I$`!0p=d; |'1'(n(] %"&B(#Xbh1jYsHDElpBp59;͡57z+7Vv@n})8\%pP[8FcYWQO_T$=,& \Hn ~OLѐB@!)`;Ks^aiV5;N_9gY[W%{ݟ+cQP{ۙf:M4Sy -Q_cI2~t,X;|0C/@hetL>y|0Y٫x ZD)O>s_OD'0DD.ڼQS`๊4i?=frOi4SpxO73>{FR,d]>)Yő(f{X=Bbv)899iW@.ᮂ3BgEy>=>qr0Ү5U3v?U<8016Iؒg$ #D\c~; U駽}۝1C`2"d#i֩cYw 1fRvVkM!\hiOA6]{|W('jҦߥia.>:AÙL3Bbjn nRj-C !u*$vMXj®e-cdUEiHTYfzr$`w&=b$uGvi|ZW446`O}x)irjd_867BV!~}5Z V&Y-Z*5 gde˪,.U] HCHX|+p吞o]rfSEv>r,#ab4(dg *|u~TRBRY/渭*a Z˶$TS?҅L.~; <˝"Gk<됔GƇLՔ;5COD^SEz۲g= dupxD[ȲglvW@YU-V f bDz.vLF32~ߛ*%Ւ[5ֳf_jQF*hhg@qyYb9n<* :J8ȥ3XN^H Qpu| 8,w3hb{,1N ~&o׀F,ܠIf!%d +\3EOJH+jeD qJ&S;@z]~Q txy i|sYrng@&;oC~krF 92$9ڌW R];5'nr#u|,6n?\UC8hfcL tkX;~]]] Whb-z~/*!Eh1P\Ea|e @o_Ex[1JJkOP C'E_靮~y_ A8imT3 @,oXd|Iq%X%bUD:dUq駓/oyY+7.Jetbemon-1.3.6/.git/objects/1c/a82bfa84765583b75b15babe708f5f2a84c2ab0000444000000000000000000000331213513716505020133 0ustar xXmSFge $-/.HiHi k[tg^Jow'!k?ݝvvg J̽AxȣD *QA 0SR "(_?Yy@$\6 c?R&,f*L?U5X(S(p_$&xDA?#W~9 6PIN u C8U~bs金?i7n|?RDV.ë7+Z8&v&ubQ[Q~ɎaBkgY=mgguhyvW7T?«H䊶p lZ[[bl<;+gZC9^)/ϝ9 CAή+[$PdC{sEQ T 83, U#oɼdyi2̊,2حrwg8JuBdv5#ܴJz&tvGB{ZXWң텺? TGOD> H>M4 ښHT/a\ƥE g5&aLqH 8.Ou0` { q4Yi!Jx!u5֨*<^ư@Xvfx$s5PPV\AҶNakI)(Jާ |Yz:0q;A:Jaj߸kڍ҅*55 I/<IMN4U`YOZH5Vd4 94?D<!#{| r(<$*$s1 QsViZfyy[쮚X !3 7+ byIJ3Nht k`%)GԍuУ4}_N'I5ϥn|De- Da"N&h5iBo we,cHc+%KU(RiF'O z7m8` Pi@i,sZ0(7nT"⏹+e7ܨJ:˕Nú3eNC_\7(?q1?_LU 6m h;R,%[`ܖ͒WYF[2F@etbemon-1.3.6/.git/objects/1c/ba4a1634e24307e73f2589757e2b1aa9b58bda0000444000000000000000000000100613764422020017760 0ustar x+)JMU032c040031QH,-KNc[nF?[>i%Tx TIjEbnAN*HClϜH݅hrM o]a!Nqmw^]U~^qF~yQ2􉏅J7}Zw!Θ3pUM @!3/D/YT{E%ďݓ}LSrԴݞPEy% ^|-ћJ/Ww,$  ݺ$$]+wefCD-&܂dZas3WT,|Tt1רVBI(+"S\wkfgZ WrddMUJjkS_?~[a*suAY43?/̽a5-ǝ]scݪ9R*u3a 2 cnox[Z%tetbemon-1.3.6/.git/objects/1d/0000755000000000000000000000000014170644171012643 5ustar etbemon-1.3.6/.git/objects/1d/0f6746ff1a312acb9037c4f8d71e11c508252d0000444000000000000000000000074513731650502017705 0ustar x+)JMU00a040031QH,-KNc[nF?[>i%Tx TIjEbnAN*HClϜH݅hrFxzWCl_?.v6d n&C1gᶃ&Bf^f^ óJ _' iy WMSKkoyi#hLnN)fgrV&{,V [{hyk|9= KKAfZ7{^'~vo 5LYjIbAA0A ﵻuIHV̆z[LPy)` gY\#!9b$% Qzp}PxW5_;$UeE U50δT-4s+4 v%r1RX;ÔU8$hf~^m{j6[;-ƺUs)>etbemon-1.3.6/.git/objects/1d/3941d55db6e92a595622828a911e7a28bba20f0000444000000000000000000003012714170644171017641 0ustar xvG~VI5YٔEu!_TkZz}Ǣ:-tuyf,@2:dO]dS4a ,)wOSV2-Y,Elq lÖi>szz#\۱*].!O5LA4$O۳>Yil0Ɇ~FĸEYXei8GӃ!q)Ώ~G-0Q-]$KF|9B&)$e9.ٟwoo?j>-b:nb#>I 2!gNjZDիտv$J18%9D4Q ɗ+/Y:_ sJrLJ٢l&!l_$sq'&?Cː.zJM.׉4gl)viNRFF:}x V|m&VM. BF{4Yg#SlPALJ&YN-&o"{/n=wSU,KH)Jp a&gp2ӽdJ~EzoQq>|׮8 N߅b7&-ή>4Yaf↯j}t9#(t=\&5k{=%s8+ZKs~B^OrBJd4SXM& Xa92S3BI۾>/izWZnUlO1I6Ձ9r39">|9 ,lhc<=L{c ZEjUٰKin &`$mV",W7pvi>Em=Q[{lr?BD3(&׆&ŨVZ.՜!4㛽hk>uFUﵻ`{\Mˉ1[E8XeyP3x0x\Z3 <BL"IAk6C]׼C6 ~}Ft?.qlgUa=%h<\cW,:E?FK0 d^;*8s)*ƃTSUԈzͣQ._UyڄuswY`BM~j!g<b\fɯ2߇H%.r}ZĆO|Ʌt{e߰ʽ,ũ|a:"3/ ʹrXk݌FIL^Ȅp!H8!`t!dJPHKD%qc–B^W?ܩ4)(m1;\rq0%Y͓Enr6?|`N#zApdjuG~?* H-^0EE?*j!VDڣ~b`y`EG31) ,P`:'2mr.G} c;oedc̣E6o ΋BȔ?KNFUl.! zf于0.45pF<̮RLKn\ۉk}o2 x"P>"q۷\;g\Y,~n=& a0@|hn. Xǽ9"ѫˑ+ǿsu4G>ؿ1l.vxnmƎ|:[7!=M(gl_?-i+0O 59qҮ%E#m >@ektO߿kǖx5ϖ(IݝD,#Iz2B)iɐYywta5:C`=A'a +\xAn4(.C-vDw>Y\d=PJ4Yhf)(d16+pI#IQ2V3c׳x^k X4:O_edU|ﺝZkr gR4EcsWCu \H:Ɨ@bWtG֒sӇp,*@~A': wrxtkK :#D+HO9>[1&TH jAĒlT^sr̍QȠ˼͢к87t*WqrE O;`CiފI=j_}"SsdFz4hk/w0ET~.xS03Ӌ0Sep,*}Y'l<.WDqO? ] 8@Ҍ ԓA+m٘9q/K A}>]flq+y#Q*>P*A{y:Jڵ~z.#Z6p>NQPDbB%Ra+:ɖ<ieŅ=cz ۠6R`e9*kW-ǖX7doIHe¼QzF*O%!+i/ 8A ڳ @%.iM8"[#gp̞;}y&఩&j84I--qɿ|y28xJc6kߏ`yC`n1-iXL}#R1#s4X.ItS)6<( x99x&j xE#f_LLV3_?s͊ w)$[yb ś!eݲ瞴fmۄzh&*cESi/K=An-SV-+6ڇk;1tx5!U)dB>ZUXHM|"[6WB.XBU9b~R?^3=vldCeK"fi!<NYRF`%5FUI@ P jrlKn~m~ Ps,ɋIMW@FK 5sρK}R~U4JlxeR>$<*S"&b7T`C"B(+󳌝-7O%LmhK*I-Z$O)q끈c ve߀+_yHb|k\9qM j!yT63@9zw%Y;?b'cs+غ7X2.< .b4JV=xZ#n,sa2=D(`̆y_6y2DZ>:Ayх]X}cMz ;ILQޝG>@k>WqrM= ̮FDQU"b{U`鞛dnn~p[inכ {NTI:)B L!\n~/rċR)B9>vڧFUoy}iښUyE+ n{ԥf|c?}|Q1#p9NK"z=OU1{-u< x g ^fFSv%3MŖm4k֍X2k+39h ]WH*V(kOasyؽ-zml"3/@+(:+v%BoѼ&ƙmR `޹/"бڲr J#IJhY"Ĕm%R'?{m7v>\7 [c?"؞pV:"QnEVv\C@ a]آ1Qf*?T=-OCV@[ ;Rҵ)7`&Ŋm-g䁸?s|2u9%ZI͔޺[(iZ ڹ3taw6g6#y9Vjʟc۬USp&= B :+ܪaDxsJ1>_OB~M 0G>ɟHF8g:ny}q0uUdrbΠl[{Gc%}=1sX˵ }{ʂ[ܳ)!*zTŵL%WF|-d\)l ' &ܜ簋,QP ~~d1z4Qx1 ^t֝BnMh].N"lgW8b+qIEʽpfxoUڞi5fσC$l3y/-`{FI.y*T)F؛Wdd5?c0flBqwsz{MJBYO~G3PGqޢ'۔MsuJE?3BD6\FwK 9VL ;4rA1?{:T'GFAvm_p6ɹBhv˛z<d9lЇZ掊]*A~7p\)b=6♏Pqzq|r,lV |T6)=G~*V9&`Eka('cFz]MKBϏLnaD2F4Vp ^%ML7$آ# T?w%˼d _I\OI5]+}f4X&\&}{Z.&}eDD $,Iua]gDFSEDxۊyg=yDo:p4FYD'[ZڏjѕTr_Y7 J\ȣrQ yu0'3NVy8SAOIĹۢEN?M*nD_f$%-iѳ%f^TT>z.v~c Sa- lDEe3+L`!6I!%U*ɈG~AQ7AR1W=ɽ9d00B5n̿d^vM䷮(<-;5朾?gɊcٜCЌnwWbaÀӢ\,(hl&7߼PhoPTY!X<k3m"1bGe4&/C3[ն; hr'8V//;lyxJnoS%>_$/DE0eC鎥e#YOǩ/w\*~f?zk[D_ۨ?τ7Qŵv/;JR4)))▏Zzj+b5́A1ZwXw[he~<ջ@5.0*Ru)<;"䲐GƳ'v(dS?`¡𚁆%1BfPmR1;+s+K<ŗn|mð36.6pۜ-.t3pLvlFHԱ%o8[BZRRnbxn ]=e8R&(Mn f힅'p吐 O)[-E so%5ٰ˽a1hR EGDDD٧cdWt}486Qm@{oZ,?r&!ȪvI/hSY1E9}::luvuUo?~ֿ8cԏ0Z%nhN[MyQ21ܳgD*_* k3.SMT8DE߈].migΜy4v47TTiYs+>Cl:3!ٝW5ag# b6:c;#Q=]i7H5(&t3:3lv:,(\? /|!/)<^Ј$։%K.}NbI>F4;"?( ֩{]W+pZh3-+YE Z%=RpVNT!fnZG?2RUd؞<AG\A}zxE õm19h4ŏPʆt,yP ЂX\j Ȯ?V*7(@`+|Zbfތ_ `0YGGc5햱{ȑJ =-0 \Pp".~@kI$}rTl qEaG2~n !PۯHFfUɔب J4ku:ֆXGѶ8Mr-(]@s O ]?,TeP&ڪچV,CiWzoY&\Ahd6cb.lk`#c/~ʔԮպdq\\Υ:jAu0T|vA+ 9[i[s)R3AaSVY\'el5C*e:(-n[ >|n6Y Z+<z39RT$$%;ctJ9p)wu׭촡\Zp4|rZpZ;^0Qr B}[Zpv@+>1^[)ĹCtFr ݍm/pWع'V;^uѶkIOQE+cWwY 7E]Q$F :51Ep\|,V9/-0Oΰ/Xgċ2^6Yۍ7 nR\/\f bZB._wqcV@WN~MPƶm;U}J&z4|j6ModO^bH#r~M: yÇTy@.@l2zmv!۷(3% x34{v0OƳ'"kIW3~Y;.tOb|LE &3hH|[b vFܷi;4FmS@Kw8@^iMfwMaR>M& u%%Ϸb$YBp- ٺ~R_*U=^hUR'j[KtfٚWnR/ rkC=8L%jxaLI<4?nY 0*wp&(m_=q?I$b1‘~I( w/ȫ% h]"}{^LdP 7@?OT`:1ρ#Lp$!Js6V9`3:PGv?ʈ^ ,ãVe\ӥ*rHkTڗe@^^\d?45Я(1(ZAzZ|A:ak;-*ka3<2=g_رy6G~XB|yfýiб]o5nazN/I@5: MwV)&G%QX7wn-m5RZk{#.I>r_S#\%9}Rkt Y}L6Nw#S8+3*-5cf :Qc~H@q]1gZv'9)ku^.O~>99,`] oWUZH.P*N&&OdNMxuC%2;\I|;jR>DsSq)ΨYߌMC~6vݙ_Ԃwcy $pD9UnBqWBbC,E%#waUD :GdWT@í~?|! ]Z[98"JRŀѻה1/|ҡEdp-+H*('gc}b̑b@4[ۗkF: 1$膢{Ħϱ,b_#ՠδ;4ceWɟ!g#Tt;l% ]i ҅X$'j{4avDSaN̻ݵ_MdASm讃ʜW&pw.b7QhN>( &ռ͂UA e ٧Ux>Q_Vb!XnC?eOF-E^t;(df{vEk!@Q` rWjSfݣV'gxвA]Ud+s]֣@{S~2-uѿdTjujKBL:t6٤^Hy1hLJ^Lhl}I?Xf?]!(LP7άJ#RJ$%kLf:TfuBٛ`^مqgC-SnU&%|LN} )AԊ|ߡJ9XTLmy;ɮ ԥg'3݀M! * |o~vm:N̟9gVZ1-!+d kNvD<^61کl3r- wil*&ޟ~:ͻ#wQiZdZw9#Q\^G4Bo8v6tݵG3Psoɡo1+lγ_W nLt,|G½O~}ģ8~i[uմFF PY/x"k:t4j؎$뻜S?".3݅㯘5=v ҼWv+y`P0 '='mwwؑa;twGEٝPNV;Sgj<6ސ&zy8+Y&~]nWp +ya@V߹%WȯXVP=Y_BE8tVPMo_żT=zd^ډQIKR+s)鳱F4@ڞPlRrVTJL7?,weSDnk4չJEK?E6[(ff7ϬN})n%,Z@R^tqU]c'nY1rɈ:Pt2n\ӯG6\ EgRscajZS!SD?э0zRqWň a{WHH;a^fp&7kD+Vj߹GնԜ9o n .7ؾڂ(etbemon-1.3.6/.git/objects/1d/695158a47bbb015fc5bff608d397b0b1af5ef00000444000000000000000000000043213604573611020132 0ustar x+)JMU061c040075UH*)J+,/bw%>ؓs \vXUZXP1vmؤsAu*.HLN+fOs?ƍ)b6LUWZ[[WCwn*?eىwT'$ÕʬRڼ=Zt׾xCJ ~7vw+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3fS7SkԞ9j*.&d3<`JmSkrUԤ<熧䶺zGI>y}hX28v{^N&\+(.myG,A!A uǤKZ%:? %fNceqOFj*$kS3 eNc!h-]Ջj-BS_$e^IF~.I!byakk5/Y`9FP YmUQd'g()UM7D|;ӾsI^|֪px#~{?d?w%r'ŹGo~xTYMzFjd%SC_u`U ^cÅ0x1}׆kTleoVJ-B1"H{)b`XvRͶRu}@튃LcƦOFZ3yDRv "U‘-4ѧ~ANnCJGEl6keuTMu)'YqEQI%bϜg)!Y˶*g6 3_pq)~m'MG}kg~,"ÃJ\HO%',X'ϸ.>EHծg-_ˍ(+gI|9ՄKZfYǥl8 ( Z5(L4%& BjE^[Ъsm2`SȩZʗ㠐7숮# ^`|T2I;~,X/z!D$_m,M F2юc5>PsY2@`_?$gٔlu4V+4 UֻUa erDr!<Gjĥ ^U~uy<;R[ʢaL\8 9Cg!Ws@Lbɗd?;F ,z}ܸ2UQMQap)ea :RJ 9~1; ӞhioYּ2pbu2UbXmP6kܺfVS0I~"q(>Vnx2XtPdB(r"@nx0Ƈ:tQg/f'Q0etbemon-1.3.6/.git/objects/1f/f0e50e9226f1f01dcc7b70e5e21c013b11b2eb0000444000000000000000000000141313343237701020072 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTPv.hMvZh)TIIjnANbI*Cպz SD2d`َϠ}Qxށ+7$vAds2SJm0] )5*DEJjRfbCkεMtjK, :# U :Y]Ϋ]@dSKj]|.^ASWCǠR}q+35F٬=@Yݜ`XDk4+I Fe_Kv 3/ύ9>9_Mh+.HMf9pb宝˫;) jFiPA ˌ,f~ wm1DEq 0%.[:ǐ[]+ UQY N/ y2ּ?)$3a^r;'D=b$k1_BrPetbemon-1.3.6/.git/objects/20/0000755000000000000000000000000013764536707012575 5ustar etbemon-1.3.6/.git/objects/20/2bd9daa7aded26b7c7a6b245654c21cb22fea90000444000000000000000000000126513212006554020253 0ustar x+)JMU073`040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35Cؔ5toi8.b"%5)31A|Y[9nky TA~2C̟7nm`~aj!% |R'.e93R32 AE-@V\̐joʫhrgY#IH-I-f`Ѿ")p{Rܛ.3$1'g,^ʀG[9ԝ >,,'3/a`jĮsʯ]j dKP=Kx| hrU_ؘnl~(bcg *JV%(F H2GU4r{u;]ZMPBQ)(&-lޤzEֲS D31hjVIa69yL l֔'$g0̴.sq> nH4z+etbemon-1.3.6/.git/objects/21/0000755000000000000000000000000013617253305012561 5ustar etbemon-1.3.6/.git/objects/21/4f16292f8063707f6e452798b8cb827e0c6cab0000444000000000000000000004041113216420065017566 0ustar x}{|Tյ>s2@27 2 (oD^dd3*cZ-Z}z5V?mo+&R k5w䶿?kk?ɞ=5ͭ5* Cs,L*"b|YEVR:DԮ&|,D|zө֐)tUS!A>Z"uK@n*Vj>G^׫tzZ)SmmZNI˫P[v -t.W/"\/:UiM5gNkkn tl>wvn'UkeMڏns&>t5_煟_|ۭ7MՒ雦l<>D"R/g޹ ?qOq:^Y`p}2л!0!?7!k!/aCr(׃/?qc|N!L;!ᷙ__1?#-Y5GM vo[) P{[m͎/޶@[xoo ֶPS.BRo]0^F|[{kVI!km^Caz_6CRMu7Dms [YS}JM뫫k-Z׆v5^ko:0 _B[@o},j/Z--[T t)ATȦd|(mN oǔj6?[|'YxΡ:Ix* kQxNG]o}^_gjʗEnM̴q 9P__?A#M|rrGg :57 .)³n}ymXVOH7D9vkK~F"m§Fۢj+KGUH(+JέQ((<<7 HF᳣DsǢ#FGE{'zSQ1QE/Ÿ{Jl-<{BSOOY7?qic1Hξ&^y^ρhc!wZ>ydZzdmr}d3ogghgHϙշE3ꫴǹEU\]UŞ1CmO&~^&'=&>W`o't&~yOw8ni_z߽^YitQPm^Z&OE8 ? ٝ^`|;ml)X=Ag+޷gnL7ƹl]x}>(gSo50 {z; oxӻ&zn4:n;(\: ox..`rA@M'P*[߻I=w;_G7VVWt'gu#JdYuzƹZOwb2RϼηB# +(^\y^=݋^r{Hz&~Sγzxgﻨ!Pw-#Z_9tݢЄ\u坧{Ԕ`s#:l\ঞvO 3e v y&9t̎׵S>FZEc2Jv!OpǠxO=4.fgi%n|VHб^O:IB{:?N۷#VT{asiH`^{Vxem,7 Wb kF2 ;v+J 0ճd@'cϏtCBVR׈N&Wm$Do1&~{ {r0鮘0OcP(GfM|(s鮞QFEF'Ьħ``Wwt^zr9Ho/gGܮDhMJ8PONr@uݗ 'p^M"l #@"C$3G` },%ПMo:XϝYWB#|}DX`r~.z8].Vw~TJ䷤̧>3{/.BB{0<~RCz0Rxr m{b0E;ys/,\7qVs8n#pMu[-_ֶ6XoAkW~L Nm)l ZD,v_Khj Hm 4C`/uOļ3Uǽ܌zVw5U^j|ƶkeZJIV{r!;`<)QNpZCQJvN{a' ,L'{߉WڛxϿ2iPS#n @]=ib]n C~w,""ܲylmMF7Utu6MFitw8?6[wk;^>J/u@f;]k[|;5~7^67Va- 5}Akm!ٺTDG<`Rh05Als=J(Rcv__C|(R7fIb堈R"-B: vHBj[o;6LHR>[!=T;2[#Nc$#I<nSIwѤυMǠHu.K]f#Z0eƄAR|/Q"qɅPY^ĵ \3ç8biv[qjfi{oTT{ãAU|wؖvKSݷ'N98`0S(h.ПR?N%AnO,M-yXqܽI+R{ #,R`lELa9l?E (e3bdc <[apCCXt{!%qT^WEcD`&4mpM_|+KuL?5WQ\j_໬A+( nĥ[{jԶ-ũ[ؾ+ENaNPp7Qoo)7Ejp[xԢ.?!r|q}/<_x |/+W{du&z\^|?sɋxǟ-yi|RX=WկȄJRq6ňך2I^ Gn-5[*}XϨUYt l^*]u*WVެһUzJV3*}UVG*6webjΪxY^R2=_ O/+=قBP[qdnHqPQZQ(~|Dh7^GːG"Q ck%f}0$$9q^bI l$'$$b-o%^:GJ]7#%nĻ$8A hӃLQI*I$"9) ͂) )RQHHCIaOyݙb(e,b~ /ms쁕 A;*}剔m /ʐXf|RizHm.5Oay6PIYNJ:']#$a7t>5%m t$ X^"v󄝮[`\'s]pO;a lO$TṮ[ɟ.Jʓ'=Tl lIva5gvڶ_CL(=էd{<dА L#i{_*9؅̭#(`eߔdܛ9~2@=\*33o@ݏ4[O1*ZhC=O ?仝cɇhaRp=H0͵oZ'$;P-ՖB,Rb 9pZ+_`/RHM^$Lc>̺@ܱfP-4e(EbF7e41_*-%x$:&T͎̂f%&t1; m@fa @ w<.̃Ȍ~gDҾ#<(>Ci #.${?{naYxάo< ҖSɬ^t $hnTD Nbkf!0./5h᪀d b81'o~g0p)NE͸@b߂aeWSPY ęOa2-~3󕧐:52-,6 bB܉TAv|*p:3W)r~{Jќ$ʪ&O, dٲԐ$(giD߂\4Rh}fkxκnypp[q 6Y-4$c/ | صmF1*ʺ0L5 P"vA'ͺsp2=2w!öqwCR֎ƒ]ϓf \?rW.p} x๮x*kvEX{{ąA `} B6'ITORSBM~.:F]LbNY-4 <ߔ' #+eI/>hgL< ܴXb![dDI.rJ ɾ $;[ u/I.>~ ~h*Ǐsp<9Giha{"Ǟjg//[lqQ Zמ] DhB^eT#[!:7{nJV*(ͮf]SZ)OA6ܝ=ٛEߢ+YpmCd_E8׵Jg{d$7ʹ.dn",A\d W&<]ݵf6vB\?'[/A27&%)B"tC%p !P$J]zIvZſdA?1VCLS[ǯM$'`n0x\Ɏ(Mqp ñ`f9>jTrd!P2@(5َt(9-U `ȹ}tNЎ>aZ roG90Gm 9¨@ 'A[d\oڈ"'$´`nM9{ef0@F2) g5dmp=rn]./9ǁws]Ờ]+*9w$IBx/c{䍕U  ږdLÒ!#k KAqn!x]SۃϢ8NM,"?gH 9 *`i˹Y4Cq6"^{8#ikgrG4.YЃRFrYcw@3r:uD=j="]x6pz6JC tuf\<Fmqi |X~G”||ѵW4l=.}t 43F™ID\1q-]f| íRTvf<^Ar X\orbzb,!lw=B|IxdH5J4R*$\F$2 R2JrS3q1_XlV 26ZJ|o\a! 4rkd!7hdIɦG#+YwY\WѦdsB^rFp]d]ơI;o8mM 䖱B1eSv*TsUp8l 01Rc1_)j*"ǬlcS%F/EIlF.|5 ㈑ⷑ-IKD2iF~pkbER?8K^ƿ e $Lيf4D jmyA OPf[wKWqFDo&K,;$ѥf 6~ ܀8 5Y-G2>F씇mGE]s=cQV@55ewpM?-)4<<_#r~J<%Hcjesw_A vrV9)QbTh)s(,WRU_ /Jc}`^"s *@[5+@<:_rl&Ej%URP۴C,O0˘dl STwSh|V ARTH)/.O6_ BA0]ecB0 7 b99S,dEraC>QDc,Q z"͞!bU).܉FJ" I¿(4BGÊhAX<,t( TJPBDQ_ (,L~n7\ (FXWW w\6u o|V_j@lzk%rm (_/'?9Ys߱KdmN}V.3ʉvA Ay%BR.vV WKi5m7Rzs*&I6u"bm3FޟT G-gVPGQ2W)jyhI22̓vET?bgФoE_aL7Z~1w*SeQyc7wb:*)cKS.g6f#]pؖ"6~au|BW1HC;~lk7̀D~F_m3gmC~.(c2{b= 1iݽ ?/# 115aN]2h_ $d 3uc<VEłaiĚ 9 Đ>e\`%.803H:P6Ӫ1&PKo _K="hQ O 7%Lj4 lZcU;=V[Ɍ@|c)"oc!;((%FeQ:}c&pF1(A/aYR .ddLK&Y`U+}TviT)KFHM1,4Oz=XNEYzqETKe|;RrʈQBjut1Sue4"-"kUU2jm\P4,^g!pd 0 0lA8!&v`1OSGn` :Ӛui8;{:!1 QFX8v -*i ]pG؁y#hLKkq6G?6Zka/ljH ėz|YZ~"+jy0c-45*A/ @2- 3 y歾fmf-IQW%:ӂc䵈Y}4jl ŴJj ~܂[k-/@ǣMqi"%n &5M͡b˫JžT.Zx,Pl=XJ23Lݝ:6~+a>nɑ6.Xs0d&왷tT'̻wc&:+3o pfByP/+6K78܁-7 󩰿lζf(d&MWCi_{NPyP϶;qroޢE_?jJ[]UvK~e 0=(f{@`4gd3>ưаZNtf0껩]PBb>uX{*`_ym-9˞iȿ)ۆ23fS6ra:<!߄ 3:m mk)Ϩt02 \&)UveV_^-m4l:=z1jek֬^#<^ihH@_wxFI]'WvY,~2ZPZu奨R.zW j}{D8[C=Rt@AEebF.§8cp#g9b 5BY?=cPcP W@F.d~cVUW).*!3u PPlXbe0J@{ԬǙop Ou 5[nP.),80^z}YeƊ$i-s*bpY+5tp"% 4m|HX.iVi\zڠo*Uz) ^цfFD/ZkRZKo=SDxY>r{0'^X0Jo+TxX{Dr ⭲]>,Z}a: j_=uYXVJJP\6Q4_4 /Ʀj{S=IFFԸ|(T%#:[AfI70Ml\nT[`/W{ q):wPf[@!PŪ/Z]!5x"S e=+/CT-VޕU_l Ԡޕeo6,weIm@E*x˥RCTj)>QE[XOTլPM1/& Jƥ5b޶@mMCU,mpVysZ :pȮӠޱ 7F f/T N0m \t6G2tЄZO(;㝨ݢPVz@McJ-h6"zZMDC=oJ Zym|;v 6z4^ YHzo3,xA'έ*Bub52X9$1l/,>/D>%|`,#|b,~؃S ]fbiBwjw=.r 6iyѥX|~FcD`wP<֥ѫegp ЫǓx|;a6LK}>Lg|3}HwH4vj|C?/>S8Hq2Kt1"q`>$i2/7x7$~` 8$Q!Q/_qT2}u}d6*ʫ c'0t#݊&:ynvQoZ7 GOr~49>z~ϔrWo*z}猤Ă^$o®h} ARjRarꆐGSF4C}oAx; $>5_!ODx9hTxCޅ gkJ>\!IyPgCTݯi;-qCп*RT%;J9?8/ReA2X{-V/S!3WyG}rog!蹛ۭNFO+,= |G Pe;\r2qϭA?׶zlǞcP_߇mZî"l;bvr)(6AM&ݷ6z[҂.ި܄Q^ݽxe66Q>PqUl{հ[Q<*]^ziqweUe9^l&`Tu} EE+ʗxYނ)?3j)&kNoyJо^YBOWsඦX`%^?69()P[X5b&n oϔJ Ё.[[*ۺH3%JG68FdZ;"*ӎpXLq)_L7 }xG, b[QN~#'M5'KE (6`ӓJ`O,:NUCchd 6ȯxpd@x)@fGRbib7ĖaURƹE)gHv('dr/Llq %%^/RxP{2Z ߠO,wFgc'v}6fHƃ]jVCbт]ZH2m0D>~ϟ_s>˯<+Ŏ$Y-j}Řef2N7"+sQWjnXZH lEĒ0Z,__6[5쫩io9LQ]at+D)I'C YXҺ{!?6|*̯M ˈh~Ib?CcG@,Wx=⛹a{+nwvͯow$C:sUW1{0PZMkP߬yL?^`h~^Mw3tSK@;:տA~8D-N~z{ 뢮W'2}N9ܩuzW~SSu8~ӥ8&%jܷD#폹tz^ůߪ^vM/u'?~>Zi2u/I4~z/p͵]mDX,aN |:}?_UZO-F'EMRw\s䩿"j7ʝI@h\@'\EfV?1>K(|L\ d 8څ?qbuS't:]>D91R}|:DZ"~e^=R''W\3z=rvZж?7-XpmS8.+7Ûqetbemon-1.3.6/.git/objects/21/95e69453efa9fff3aaf4fd86f1a4a920d0f5200000444000000000000000000000120513247732002020137 0ustar x+)JMU07d040031Qs fi^5W~YUQ*ذ*)UUF5AE*f7/~92Y{6;&-R oMMJAlշb#qQp\jb fͭljsh2?J7C)O,I`i]}W鑮i)/etbemon-1.3.6/.git/objects/21/c59eb9f66199ebf2ef524b128d51d5c3da7f1a0000444000000000000000000000054413617253305020151 0ustar x+)JMU011d040031QMNMIe8;?nN|:/wrq7jMMJҊr2KĿ2sIt#A KII-IMM,(HMK.(`uy&؟jRtW8t&0lK׹KVz|%u3Ҁ>).HLNabƋSnmr8'3B$5z^ݭ9U^ OLI,K+Y,y{}Z-VC fSkmឧ1oJ3A rڼnOVU[֦ JJꜮW 4dbzj etbemon-1.3.6/.git/objects/21/fbff736ef34fd91df9ace19973c1cda648d5b50000444000000000000000000000254413212011741020312 0ustar xU}4Ti11(A)X#X)̘\ys5T*l/SQHoJh5'u*/!:Qv:g|<] ӋbEP2,(ceHZf=K+ThTsŠ &Kօh 9)S&k̨q8]Um1R78c0-n7ݫUBگF0d ҿ}qWh m2 WaEetbemon-1.3.6/.git/objects/22/0000755000000000000000000000000014173222122012551 5ustar etbemon-1.3.6/.git/objects/22/081f9b084f3d7719e6791848f56eb9f655d3ff0000444000000000000000000000070014173222122017613 0ustar x+)JMU057c040031QMNMIe8;?nN|:/wrq7jMMJҊr2KĿ2sIt#A KII-IMM,(HMK.(`uy&؟jRtW8t&0j=R-77- T= ZEK|{3 tKRs `Jt8hm/uecdw@dVha"@[_3-fT'$LgȺXz ̘:_ġJ ;wQ^(O|bUU v@^Ai6_czoʽg7RaJsJKrjS5T9[UV.w(rBe7oajJ31àrڼnOVU[妧 JJꜮW 4dbz3+etbemon-1.3.6/.git/objects/22/5050e221a4a0b06920274296026137d078110a0000444000000000000000000000072614170644171017053 0ustar xOo@{e>(`$/+$5 -'zdchwC Ref7?,=ae#T)'V?a M˾jyo|dt9S>e/) rZTŸq^Paӧ9&aw"}r(,H $$K/>6=x˷;gTEnP*Y(noE®#Xy|)Q1ۭ/J\'Zy\;O:rXx-wb潮6ͣq#դD".Z9zCky٨kiu{.W]eRu^HفhP^ Q?[-( YH>Fji5B%?#9[d JS!ĸއTƻ$XUaԲ!F)etbemon-1.3.6/.git/objects/22/a325bcbedcf44117602fccba339fdae66fce5f0000444000000000000000000002376113276746454020450 0ustar x}kwH~_Gn&UcQeXGٳZIH Yh7"D:Ue#327nDt`ꝠD41'AQkx3L"̢5l%Oh/1h&_.iV"5y>FYQÃ"jr,yEFY5h.,6N7 E(̣LDIL,c0skD&.=Ƴy\y4Mr_kt^ ?{4:5A\+S.~V9}OHk<$ '.ɝ '9Kw&&y9?4I&l8̔Cp/?gE-Aθ0y)9!\ɩ^Bh!@ ;B?$i2CJ\L Is'?k9/g,2͓nw2ѯhzSf||-f+},,0h0f(xTQG9d3F3}<U:si%!)aXPi JB#MfüQaX12X)$b(0C.|LH#҅ʗn6/%k37A#2,nT@=|f-wnBh:aLdXL8##-h@k1ӿS/$exT/µD ČYpx፬$Jl:GcH2J;sHz pk Cpc\0{O_tn΢bx6rVsSaK671CXHԆ:t+{ˡnSle&G=15)$CX)>pUoDgr8Ee,cMjj<{m:% 3n j$K,9:qoˋx,6(jGك1̣k |8ԔGF06aLh+DqI|-ϋϟ OWK'īhΑ1oà| LCk;֮*҅ߗ 3_㘻9i|QAKH|D:RS^!D%ňHFH@t87_"Uj L6MwI i3r2B]c8 †ҰN&<6+BYSBO݆? }TԝbJ$ubօ(DٺOcl|~E 1y]$tzbfu n ]O/~H bAmWF7E,P@ z8KĢxrK85'P-qm%Yx|p% Wm8rBD9K73u6hHVD}|!0`tTw+hh)*RUP /&CXG",b#]t,+ &<׺z!fxk&mS~4;|81TY:h)Sã8#:LiK9)+rW@+8zL"wj^ugq3'QqG-akXY&%Ga{˕RQ;$#O"9մ{&ALWjM,^Ìϖyvyr% ߹xWE3%OB9醼:f8I! nE9<bA*#)SkV͈6ntT/qc{7Gp)LObUL͔lpQX8l)mFk+E( dd7Ӑ' +pVd$\%Ж(rתXFK& O{ `vD},/nrwb(x;M^ȶ W`HہCGy3Yt7"rϼZl{j֫ Pe[`Bny:ZxШJ>驫2VRp<+2bzBHA!J}iq" j\_`|͆?Ơ^Tk{z!vZ H%a|Mn^!"5<bE+Ju q0Lp_/ߓ+9v49,fXy]=+~#n5_|d5V5D9O=wK/Z6/y8Ó^ ?BR R-mUsLoCV4ЅFO9`< $㱋>oo9MN-2Ic\ _K}q^Q.ܼ9=zG{I-ʛ;! %L$3cSܡԱcv<{i^wJTlQֽJ6as3Pcpf!nN}h]\. 3WBQAZUE51=,@kBn*"sxːn~]X4jTܲ kK9$ |{kgf8&ہT0TipRN̈x&.7d,w~F|YJO=t:ĈsPPDɉhz]}%성{VM6o~Zlb1Z{I 矴aURQ:MK)">ŴԐb?Jzt{ɔmp8,y؂tK2ߺD([qR=6\}lO1I+1X6ML]hQ8${MI(p]h 20Fb&7>y9wb(\Y0˷o.HʢqFQh܅Yar Njz(!>ȦO]Jw$\6 6ಗ.##`_T&hۖ:(<&R.m %oKX3Ż{]pȱ${tl(p%4`wjQ'($4ęc{QKn!&b7oBD;̒m_%$Ĕu8br. impYb*ByJ {M#krIpQY$]Kk7z]Ww00| &YimqIɠך%ۘC ~m'^2 p̯M2.!4. *ik,t< "U.]69kkչkVƪ"vbkC8oqJdexFޫPvh-5&1pat@"|$j1TI}RE[>p;o/ksp>[g۷+^N^J55xrC T%joE\TV58[ޣ[-@x=-V#l~v h- Ù.IE}cAځ.069:W :^\TұW’cG@B ªMQYppVTK;hr8?:IH5oCtOɕ_ju/ˈTwE(0( "\4f3;,ۊ M#x̓Vj7Dx; թy18r JoLq{Et\3B'#FcKۆLGZK1靴O%Ycl\(0`4'Ayyo_QtLu6 J=Rƭ*;<pծőK9e,U>{7݂zz'Ђזtԑ1h 3ۆPl?;5Arۓ߷_`MT^;qlL$(@RH?\үQVT fYCop |SsTd GϪ[MQw㘾jtž \Ju%3.!zT-rXG9t( 5L nD82ͩ,ol5;0o*Stk21y/"Z v :#DR{2t_d2(gccfN$bӫbݛg1vG ټ뗪LEH-x8%z۵Z΢~>V" _?H8; XǢ B{ bUl6*U9[oٓ"?ef CVЅ}(]~Cq|Ŷ'ΫHgU#3Z _Mvh^aJ@ ?W-Pk^%M"RChKGJxΉ$H7-y:yWIoj:dR9@F_p;W p:G\[VM =FC8Dy76wTyTD$Pe9b~M,JzH k]0 ښ TCBxpwbr4Q`H)ܚ_x/!h|-/g7C^_Kl-5 G< B~=&Fu%S&n+-(sPn%s.]=͝7|G-p (- !#ہ{Z{֜ S[p-PXG^K=`Oe`<®n]CR┴ħ?oր?肝>S;/e#T #SBh]S JE@K6JM),̩߫vȵV*BEir+ܝ-x^qgbPd4{bz^|5i~ PJWҿ)v`-< ){[1b=<6!ij깯a3e[|C-(%"#DuHH$بM1+4=A䟿K0c7Sp| ɦdh*,r_c H^8sޗ޵%~o(V a/' r_c.!79=`,].|LԞ/kIr#:n\fL[:s VW $w85yKݵgcOXy]\]y|P ׏ͻ:.sz?Q"/uGXW}->[q7 ni|:LeCH{Qx OB~sIxۮ scؼGTC3dd VSfE~wIj4;% ~]`tRАPvVp)7nY48gLxҕ X}pJ(^g+~KuoG0i!*cYyOi{_4 Q*Ϋ0~59+1Kܘ+tzg<~N 6(Zzlx>(#XbWh1d=YcAsP؈' ' "(Df ꍶ9?g_=Xpl: g?i?_} h,k^qbC+h6n4_FD5ۑ> `iJ:dscElNrR&(1B->[t^[kI*sؑp a&&L u^{e?Wp3r|$Y 9:lϭǐ~r 4-0.qXmQ١uRLO^}83Ha"(gQԪJt=Jv\H/ tm~3U2$M RݓBy:m99&NDAXt.c>weGi* o8EA-*"g [|8'J;ldu!pV,ϟgus h~a3 v_k-_ qJ]%cYwxaESP@Q@cpdh,(fJIV ( Ai*ZGs[):<<rHzjKY @XSvK֙ !7B̧G8 &w4`ikvB5ĭԒʽ3l}r;,_~_`2_t{]6u%x, RfH"$3b VFw7r,LV&< -)O>sOpHe;hOjDxh&.rR_(`1s8b+ X[<X*ذ@GA`P(]l PUR?0}% c_|N}AbpA}=`؅iK5VQB4Md/Y%];FoYRYtX;ҊfւȞi`QqCh#!E8StWQj8Q(KAr&ύ`yz՗/o߼ESD6s-5{>O/8HEmlzx QyX2K`i|NYUaz^qNFʛ(7 Yse=~+D/d۹WsKC& O;;b4We3 * CYQGط݉3&#z= ) IL?-،z|6%NשP?P6a &\^ ڋF^* 5y_o_dY,P )#i-$\Nh;!+_p2ܻK؂=A?&7Ifejsj_ 1į/8EKFyܝl,LcT Oɵgmf ;ՖCzS"/ͦYӃb$8~( Βŗ@TIz;0l9ff5-ȁ ȹR/t%5 ݭL^kٶ#d}jgTOvdFs4N5JuHJգGC]jʝ9^SEz۲ug= dupxD}sȲѥ`6+f+aP @K3:S?@&Yp-H޶ʽrG&ll9TiQJGQ; w%``pMoDƒtDn%M|ҙXN^=~PW[^UyeApXdg-}o׀F,VH%Ia!%d +\3EOJH+jeD V2ۚa##xg %f>!l@ O< bOsܚs+#KءNGHP1p!Յ]C|J6W<ޣ=ZW8eƐ1VQyrpllI4A.Ӑ} F2枉OFL(Sbm/*! 5bġ鱥§N RAVZ{ЬN:-wy_ F41FHۣR̀ؔIj(ɗ7Yy Q"ZEs#ť"Ͽc=LzmʺTۗB$?z( -q:b^,x+("3y0, lQ~B`c2k!kGm`Ts3=CܾU!F8l&7",]MCaE &3}6!(7i`\Kdž8Jbt wၶ`ʮܨetbemon-1.3.6/.git/objects/23/0000755000000000000000000000000014173222475012565 5ustar etbemon-1.3.6/.git/objects/23/4536b18af3d38a3b18238dae8402bb44379b030000444000000000000000000002656213775160026017556 0ustar x}kwGvm>ϯE)xQl%Eƙ4F7RܹDz9UƃxV&-:us0ӱimOa1ibv뵞2ɋ`b2L&?,iT.'c3_ӠM["Li/|:g&YZ.[.7fM3&B2Mo43yƱy^y__N$]4Gc~ G3i5[iF֨4~?mh'өAVL>۬LML2DanҲXEC!1(0<9a^ȝ<4)d$a׼6nQsмςy< B: DӼM1 +L¼t3Ut)EGQs:Oa B(X0 śC00͋p 0L 'XT5Ƹ[-,E8 N+7riOdO?+\L,B35p1нpjIO۽de^B5hF!dGI̓TsH42qg(9yAiRs< 2k[.K0 ~& nYAw00wT QQ![e8undрbϯ1c2I"K׾2 Vdx&0f7a@栅}By[Tqͮ9Yf*p; uсffTnj{XpRDɥ) 4GdPKŷ +6ȦyR!#Ne~ VW#}Wh{LS3cx\֮& Yy݊eKP0K ։%Et!0,9iaR)X2u#iS7c*>nT⢄RDC58Ik*ҥy)dq/"Ddy@t7Lߣ_b^Nk 2.1D$Abl]2?"Lh%ׄ.0UDWw耄Z AAf5. &c#~bFhB\C>4 oDgC^EJ̸fyúA^   NrxDbǐU_#h6&3YoNN4,XC/9Z ҟopԁ؃򒱎74Q0ib9=Wnk=ˀ!o^1S*YIPj9yX 0Tr ֪(T>xqSJr@R>ŵK,i fRQ*lypA#d))f(Ho[F7_n0ZIBW}bߗ2<2ȉ4CQ{0jѳo㤶8XJr|E7_jjȒXHbUm~)cL;ju4y5Ӕ@0džHӏNTܿSY:# د1X\pF`> m}y_&E)tMD`dDe)LTDE>iH*Y6Q '|v< x&KH -˼\TnN 2 M jX3^.Ku\sΔn9l2{`RqB&Kq YP`hhXXZU#cnͬέ^,&Xr 1OhlY~鵿Oh^s0 qLtH5WGߍ/l 2VG۔G4!1eDtiPB 05|3[Bc헤IvC}5ݵڥX@XWE!`8~J3^0P (4 =CX΄Ps0ɔ_TQ 0N[[UP ޡCU8 Nعibmƚ5}7PLiz:~>%8w.IL[QG"zhOiRt*䩬\$3]fJ8,&]pD VBh q^ rIbkԴ9 G.h f4D^6DIVOqRhRgs_PTƲ:D߃@SDT%"/Ig$!ȋd0tNi5Û f<ۑEE2 K5#L:h.9ʭ4 O3y}# X=F3iU6CgAUG*>PSʼn3OmB!Kh}Ox:><\sd;FރQ IsSy]g#9N[ pMw ܌l@L- tsB0S:W.[?0z yU07[|&SB숑fBa:^d꺼oPhGjLC 谤QdZmVL&qKA1)c8`*T~5:\#s9:T9,gfd1A5J.&Y79p̈́J"4#iD!< |]:1u8Egh|t aV3KWD ݿO5My)*g+4ZV$1/7!<ZeLLwՙ"`Ri0JOw (Z/r+Pd&h ׼+B1k5:\P6cJ 6L--,:  ^)ExCgb-1y$}K9b6(  'h ~i1^ނ ڮ-Vl B,'7ԉ&"p T+\w'qBȚ&q\t+.̗< ȉ]`\AœJtdEb2H-xw6=Jpg,0d) E^\K)Լ Akīb+C4c9e|eeXSY~]Ws:>oYĽgZ})H3I2.hR8Ar8,xYTGMqL"j}-pQtCF0mz͞;um4&^Fjѯd]c>L=&Vlko=θd:Pki'YdMlW`v<F\RmJ q^i倾LW}F#ٰ:c([(Ө213CŚ;~_E^ō9at/Gfy[d|O sVY;2זavKb15ə2̀ ›eiJװbX_QD-xt?*8M_tBAzT^d}'O{`P:>-ѢŻkXT(M޾,=tF[!mv剎eqxdDyU.(b@O2sj7yr-0!&" 4K!ܥ0HO]jsXId/}Wd~0D7e֡{Uߘg%;Aq}gy0u#7Pɱm:S `,D1:[9~J^ӕ?2)_= GrLxZ=]GYQWX%O M>HaWk͘_P QI )A,Jr2̋E4ER@M(=~;Y]iѵio ]Ӥ.MBh@r_eFhй `v$^ CH)r'Z{) sjxp7sBkTݎ~MkXc$e w ( 6B$d'[t;V睧evN5ltNnSY>?V5@ͽb ~%ްĎDzg(kt̆$S5yЊo״+Y_Qg'A$3zj4Wg'6Xy vƶMrj>#basXÏ? m*bheL_ Ɠ^nKHR:twI1E흙冗3&}.rO.љyw+ -JܪDe5!75~wsVs =5"4};֣MH;ȼMn#M6} jvG][}g_ߨ`$Tӎ׿ 5UD1#⥪h^;s$45oR:KIx.!y4 1Tr^pŗ0vϪcІ'KFcl63׼Gn>M'#i)@ħP#!& ][*LTߏP\"2,eo&Cڜeb+@v|`! !zb4R\vp\0 qt\Ɯgl)f$Čm<V$cN1 ؝Mld25. 1\QCZ5㰍R8#M4n,u9It^ S_ߏwegV-g]7n@.IUz ;K&@2j{q0Fʌ ̟D3:>^_?(dpɺ+Q_nUOwDZA)?yW1ϓi(sY 9WO/} y'l ˫KO#y&3idC5t6}P!+ROP Õ}>Y;1<[\/hR#cgxVl'a5l=#XG]&` P蚴Tql@Ig`|&!@B)|M%nkKXctpQvAI`*eev;]'@NkǮ-)at]%Hv]  3ClNPv 2euhC븴Bz->&80l΅%.9J9. cY 'M橖v.(ԑ;Rboc?$jG\5a;I LTD05; ;qWiPywa Q:s8*-ӭ( 3:;BY<h_B6db'1nS5H(~( ceP?21OTPwۨ IWX\(YF⧽緋q BA2` -.MyZwwy[_W}^_%6VG<8@c,IhU?p~rzJۄ}e͵UlCM`{n8s? %+G K64؛7G^ښnr$y 4Q!~ 4͊V%J~'L CmްY|qJɕ9Gq2C3tj_"(kskx˭W9Mk2%־~cON#k :pp""6bs &g9f"|v֍/d<GVz _} 'h,k^q/tZ8wڃ֠;/d hêςzYXkB[JգZrB1٢Dkv6d#ŚDRJu̞X; Z0wcz@︮y=vG<9N#ͬ+cvh@,Ϟ=;;R t0>nUNﷆM*~&s&XMl+mFVjdvV&$xJ}O qn7L߈M2n#[`[tJ[6\wvt\A4ZUHd< yL߲ я:j/,nP]a'n~ۄ _t)O[CTsԩu}^xk^=UgIl'E59w9X=0(v/d_ N>E=;`S>gO> vնϓfv<ӄym,y\3,>ZTD-{ET@W)^I{l.N݊pGq:&Z&s~ޯ–68%쮒;YwI"(o è@cpd^UP8ĕ( Ai[o/ቿ<[ OãQO_T$=*& \!xvu&h !ɝ9 /ϰ4+ ;}'Aك,̭Ԓ3p(L|}p~&Щt<$Hqh'@:Y>ga ["2S&o>y|0Y٫h Z)O>s_x "(j YYn=ljF8iך:ge~<716Iؒg$ #D\c: 駽}۝1C`2:dd0j>-:u=kncOaޡ0%B+`ljrOt.մ =+ n=iy4vA0JK5?pwuyV(]{Ma^MG/cH4SLJ|*%N]רH>҄]ebduEiHT[ΰzr$`w&=b$uG~vh8Eݥil4J '<ɬqZmnďC夌A̲FX*5 iP2a1?euAVKTpR%)C1$Y|+p倞oCrfSEx A;c% ;&LQ%3>Q+ugv״"&" 20m] { ݭLHlLK5*]$OvմXgSjrtPjf k*Ho[]=l(Nwajl8jGgY0аyV]0hm+FK3:SL&wu Aj+qՎMlYd@5( zPn? ޸[,n`OqMo7DƒtD5A%M|ҙHN^H Qpu] זw=po E8VoݓMޮ : $Y̟A BJ@V"fJ;EV8ˈt"7|+Lpw@Pl$83M,9P] ;^ `C}amLP0q,b:z> mF+]3.Tr7vM.c/8"i0]!NpseƓ//4otpv^( f߲߫OYx#Hε\>UG܊2 U㯯"?@ku(( C'E?靮y_ h 99 w?}[&Y$/)n+D UH瘬*.?t-c6a:kt}큫 Oy)4]~kɏʂFKN b^,x+(3y0, jQ~B`c2+!k'@w҄z⇸}9BBqLh}.+=:͟ŀrGڟ?]Ã40cC73Sr߱+|UjÏ\m9ԎM,@4m(UBetbemon-1.3.6/.git/objects/23/55ca3b1ab6002095c526a1ed901358a735bda30000444000000000000000000000120614173222475017600 0ustar x+)JMU07d040031Qs fi^5W~sn)-H,ar==8qy9:|6-+)a`\ydzg˄+),L(a۹L芰"N/z+ԠrRRKsJ:.V9c ٕWjp +,*f$՛ұz>AE-@V\̐joʫhrgY#IH-I-f`Ѿ")p{Rܛ.3$1'g,^ʀG[9ԝ >,,'3/a`jĮsʯ]j d=V-Yjk27ī1fQTƈ@VU 6JJUQ`@P͋l9d hV^ jvT>"sSSRP0MZؚIe6e3jfb fͭljsh2?J7C)O,I`i]}W鑮i,etbemon-1.3.6/.git/objects/23/5be2efdcbcdb56c0ec0421d29e87bd9bf6ea120000444000000000000000000000024513767516624020441 0ustar x[ 0)_My 6٠hmISo0 L qת'G=1Ĉ$t]9ipWl1`ʘm&J2P,L,Y 4h; m] s!Ӂh Qu/[/UIwe>8Letbemon-1.3.6/.git/objects/24/0000755000000000000000000000000013604576026012570 5ustar etbemon-1.3.6/.git/objects/24/07e2f92370ad6e6dd76546c07a7af79321d55e0000444000000000000000000000112713212012107017632 0ustar xmSmO0iVM@B`xٗCnmonK!w\.BM}a/BEPcH q-di(Vi!`-*1(pf\DY*>ux eJuW? ULӬk0*liY5 KU7(K왃 RJr4Tetsyw~AxWZ%ql؆HGx'2@xWAC.hI;piz)L.My. xvI "Z"]qn x U+Lct?igzqV/h'=o$*0%ǣ/Kmd"CXz`C)"*x4L9i6-?>qԟd,*X/|yptEko(l '/HbBBʔ,f^@Dt]|w~q-gR-PLokɍ\Ϣchקs>ۯ@getbemon-1.3.6/.git/objects/24/a77f6f6dc255703d87f4f2304570f43c037e980000444000000000000000000000024513604576026017525 0ustar x[ 0ay) pt^$Mq>~~8q!fN7'$XԷvD;(zr9FC.Hк1G.=6m[/ ۺ8yyHC2UA,G{U\zu4M}a}Ietbemon-1.3.6/.git/objects/24/e070fe3830f21c5a3f4273e851e70418ace08f0000444000000000000000000000043313604546650017633 0ustar x+)JMU061c040075UH*)J+,/bw%>ؓs \vXUZXP1vmؤsAu*.HLN+fOs?ƍ)b6LUWZ[[WCwn*?eىwT'$ÕʬRڼ=Zt׾xCJ ~7vw+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTPv.hMvZh)TIIjnANbI*Cպz SD2d&XS,c'~dML+)fx4w'$?<{)Iy }Goe5W&1C'3jNVp9jdWlƽ%Ԓd.g)cz3Po1hD_L'}k6k:D3PV7'?91y vPRqTe*pXi0ܘse9*܄8d^~'XڹjڹŸfV00Xroi[Gr6 CTh1_ⲥq 9y۵PHapk2')ck+B!*JK2s%A{Bԓ9-I!Tketbemon-1.3.6/.git/objects/25/19672ad87bab46eb2fb528f4e18b2427d958420000444000000000000000000000030213617253305017645 0ustar xj0D{W4h%mlA_{JikiEڒ ^(h`ҪEgCƎ9!4H {Jbj*`Ҍ8[ٍ3[+ڻ膄ɡK۱,0_p?᝙OY{'>4jG-"j-['ǫ__k?ד!|\Bgsi5Ck}h> IHGv$W)N tP$3\OAКl]ϠtLF' }}O 4Kr>166ev$y_t>-7t‡c\f4ΥdCgS< ƭl<[hT{r" $az7 ; 7efb]xy2< C/;:K̯2</eð929JC@CmE`c>K-tk}lEҋd9Z js~Z@Hnl:_p:i?dPV?w?Va6GVY^Pu$\̧ )E4FH?g< odc):ҝd< b$S}kJoQl,R4$חzAFmx6/61NoXnƯr[b2O^C,!+`qbN'jas m>99FvgQuYHn~\idbyL5K!Ԛ8تI̚˄Qc"yʂ|.̦(yH^TBEwr-nQW†a/!?)uX#va`1ODK xH>&foK Ed!]8HmJHʌ=~^+'ɑ<[-o:K?Wht-lr͉%]>>/\A{R ]#Qu_z¸7<#ZOwDgyLAp8_^=z2"jul&GY1K^##&޺菦DUD[teN<E#!`xNA C{FR%v9Ov :gF9"̍ã_߽>#Kp!a&(s~\SL(̇&6|`G[>.X܄q` ;3ο2"~S<ӠW"h8iW6oZZM"VҲu/黷b ܲ\!-/g9.Hd@/t[ٻÃ'1x^G4 9oC{!_۰P +)YR(Bj׊N(Z; ?(-IqA@/n7Rb*DH>qCT5SO":%L fA$s̎9P1E })dufQIX]0kqBnU8" \x<rs4sϚ~wȇ|zrt2~X|fB`ˤK߬=<KI5xmmp"+, 6D%!Q쥋> {haz2hƌ-xyaW|]ⷰLςL48rUCa/i:I4葺0Jhi_TƝ^0I%M%I@V3x#Bё@HXN^dDcڗ)/͜d.l~`+U|_][`*ߊl&R"ynUJJVJ^/pҗ93AV B҆pyҷJ2+j3Τ1DX TĒ'sTqO,Opb*0-ὣ }oT\8&= ?$]Qd4O 9Uofn+(ACf ^W V>sbCl` KTo[g$ )۴sc[%=@ңj8%,x|;] 6D."28٣=r T10ҩ5aE%0:Yg½eYJ2xDxMu7])"6X: &j!Ie %ZCXFĚ{jujskS͸]'s}fGl$W&KfU ƅ}s^!E&]VP]T޽!rjI#^[ K u ^Y!_|y1DV>AE #hW-bĂB@9ˈ q \%y%{{D{VShQF\ A. #qpb)8R.M\*>k1r*0aܡw^&IR`-*p#Pb6oN ^rH م1 |fGੱ*><7zN֬ʛ3Xp٣/4 Sw'0)NTWMTgR͊ xL g% ^Vq% &KwZ}3wiEX礢&Q j,ړqX]=w|D,s 9LEک7J`]]o4I&4Xt.8>C96k1V WjԪƉ#=+c0+C,z_F$t)= ;РI:&I$Xx-$j+f6\gF6UUc0Ra)XtUO59@W?:G%.oS!ܧoGX,]ǜ=89 hm:Uk@࣪hq쌈9⯰r%1aD)Z)ӟ81s=/ RBfDg@cE~Qraѐ׬զfc|e5Bh"(r%mG=z$ρ=!gTiONy8UCOE乛_E6bm+n脵1Pxlޟ?QuSgk_'RH0T\Ҟ?zŖ83/]LMXMkk6K+{7ґs =HϸJ왃ѷ=F7LեU~uGVdԾ531Q\ZW:fmg'ofXI3^ݨ|0">-sEǷ=.ҮK5 aj#[M(#iLQ|jɖ 9Z!Py5*A5NK%\Exfa.Dn̮sDҗqR[#aWʆsNߝY{@3*dűF@l!h¬ݕX)@+aIٮvpt~T6L>O^kPLY,g,M20mg{zYMɀĐ`x|&cB^*(O퍒sCt#dۚc̭>۹x<.&q[VdTҵ6Yqٝ6#trRyBXڀԌ7TPwr*,3m= ?'; )VF*IFo/8"k-&< *VVXp6Ş)8s;!Ȯ@R5'Q7cr ŗd1Kn(Y~[UBnq،Hk\D h CgE`+{\Dkn]g:S{f:(l:k5*VpJ*rms0?"{_o#F!+I cGOoSdPdbg,W.MyZӅxx=2`ug1[}7jT({>qkp )nh+?bXPZI [9QJJ@)tWDm&DXz,]B;~{Dq|+m.pWXgUѥ?):lۭfٱ BXѫ7qwZ弴?e?[ӾbOGרm&ۍ.U۵'뚪 ث-nS”/\זf bcVA._wycN@7VgxPŶvUpBixikLONpCWk+$Б mHG~Mڼ=~eq~{*Zyٴu .:T@Ka}뎃5zUnu"`2Rp4s)Ets 'b܄|1Jo`B"!/MJv"]b0 k^tZL~ Nq`*³QG`FzijqkD6 TV! Ae/%II4G)g s " r%2FPֵ0D?׏t`:1&i8yW@AU/XOz+?`֘7.}%hTS2Rj*oCG6~ F!׫q\-8s"kҗޙGKJ޴ B[iARyMh^hO" rqlc.cWԜT!cQ5:o*Q{:qڝѹ 3vtu%Jl5 QX @q^q<ٰQrwwFy|vjlVlou9WƦ?>b <9^cA}-כnk|48~mo؇DR&.rGac%5 .c05`O찀FTt)Qns`^;fu i٭r~x\kmDZp21i _% j֞gfJSlt*){!Q2⼜5AVeRsJU889wڗ8eo./b<֫&Wkƒ_~IqM ˚sYdp4|#b0kvvZ+U>lu~3<0;g۶yΡXe1K{ Hʼn f}:t?8H'I@Ve}r0ҔpƊz3<娥-* ri~'#8r̶7MF|%YcM%u,Z@`tт!9&lh*T:/ʔ*boe @sԲbнw1~-C 贻Qq4N׾VɣO''U,<C{^Gwj-WA!!MeNQm6{C8uGeVJf%tJuO sOơY;o`YQn36%qqFNO[`[d땦ut+ )#eW዆ÅrϯĸC,E#_DxBM UA BukZTWag?6b|!$ ]ڱ04JXuD5ǍϰR̀W1/|aETp,W3$F#"O{3Gr*}ek샢.բ>i<ȁ&mAG jOK[fp렬ugH),u\Np:SLc$o-8Е3msȆv8}+o&ʼnk>Mx X=_l&a'V:ke u0V_VvdQL0&2Jmץ A7ZY[P P}:;P#m}VGOm) k7}X'<-To !@A` lrWiXãAAOȠnUe|I*Ǖ18z(bgy*vE~_b2/ٌ|[MuH:KB̻eai;6Oga[0#+64ɛw<>48{ 0,1%n0 Q5eCE'WkBfN8&-X[@6{`;;M깝_w J_h"8qյ驲O09baJXTNvmjK5.QUL6gNV4/,pv/ϧɕߪkڥt3b;Eւ4iQ;( Y%Xgj*ģ9&o8FەmN. w4~Zah6ɯN?|Q˜j/v?X恶(6n!^T#Jpw*l_W n\

\\/ݐyOsRд2C5J.)~Aa(+ (~1:U;nZfedRx{Kˈ8 ,"FbUw+Kr+Os)2GRIgfptBoe|؝xݦc)30&1-K#4rCb#b7)'v-7a⋸kSEbȲw7/{ljz'_7ݏǯU*<4<[m%g$ #b3gUζ؝Y!"G{ZO . HaDD<0W9t6 n3GK5?z+(DNK*jvMXJ¶ 2RDFwlޯres~ʻlWr>'-Bg vtik-~zA+ڦMNFPA{wqZ4 <ˬ?96cĐ__5ż..;S )Qb[t˪,?MfTɊ>Hvkk3tف =*"*rlɺQUoEc;*LLGE},^ uLێYuM>jtPiT2 @$2I}@HڶXL%=.2]=~;D3 :գKut0jMSг?:R,ږ]㧉f`t7pDP;n*lpԎlqW@=YU)v ҦWH c%8$"b{QW)#hĕ;jV7gmͮuO :i ~ y{4d{11 1zT<8>GE:s)ޫBZ ؆FT G9{fW +4;lܙ|a %`{۵! )z 5%&[ );6g39|e|$]ՕK[(J= (1EuRc/R#=Jgr>,*Sm^ۻvI~=4Z@#4R,cPn/E,+/c| P[^<Ij b@4BQ,C-+5,Ol\ֻ^mpWe00EkFiAyy ? eqp${{Mwa=rvo"vm26`QmO=- v2y qڭ{-zգ*gq-: rJ\χr[ W*koRIjDWWǫU IbxBi~vMmIp'KV36%.'A*=θ>xP5ece w)_`pNJE `q( 7ֽpq]yB)T_eC0d??Crel}VR[n|G@NhB&uetbemon-1.3.6/.git/objects/25/6d62c6e101b855636a8ac39d9a9921137c2fae0000444000000000000000000000120514200452005017623 0ustar x+)JMU07d040031Qs fi^5W~o^g!sTe@*jmwLP[WӥK*hM*Yd-Q;pM7 P6knfSC$PVjMybIrL=wPOJtM#*jetbemon-1.3.6/.git/objects/25/b8ec5cb1f54daa1ca5d5c076cba84da5e54f820000444000000000000000000000027713604575323020355 0ustar xj!E+>]u?x3 q ?p9).HLNabƋSnmr8'3B$5z*nM|"zGx̴SXW*BWKYhh] Z*-@<'N83=Oc BU秕%fƒAO債ySTU}x5 )MON9]iE,ð_etbemon-1.3.6/.git/objects/27/0000755000000000000000000000000014057341614012567 5ustar etbemon-1.3.6/.git/objects/27/2783d9a403a327fa231fa5b7ae920ffba9ea000000444000000000000000000000026314057341614020037 0ustar xAJ1=}_X:LO".{;fd|#cQTir@}]k".:;2)P)gJaYSׯ3 1ى#fks@,P2}6ݴcҖsڟ29EDsrzsQm_cUAZt3?aPIetbemon-1.3.6/.git/objects/28/0000755000000000000000000000000014173222403012561 5ustar etbemon-1.3.6/.git/objects/28/8ac0693d5a98232225271d0eb366f21cf1e3d40000444000000000000000000000032613325227442017550 0ustar xNj0 9_{!v8kK?@&^ E0h\:ϽBT334ht) kTÝ2 l},Z\feZ;-ehq58%W"cx^@R,q޲vu`keMetbemon-1.3.6/.git/objects/28/e247299bed0e6469c37f292a611013ba5be7b30000444000000000000000000000126713212010655017633 0ustar x+)JMU073`040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35ݢ{%\\q7tW)Iy S.?XòF%<..sy+TA~2C̟7nm`~aj!% 'Et)ُ6N7n+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3OuKjXJ)ԼbgLs|B@bówM. Q@$kCVLJ TA~2C]ɽɷg|ݦ\pjCdSKb7vKΕۿI 7r:wI\rq? XA4eussa!?߶\Y׼B/>fCgH_>7_ӫW\p9[8nL3Aק*EN5er{[NJ?Z}I@{؎i-cȉ- خ셪,G [CA܅(V(6#>Ѱ87QZKNY4 >Q*mek¥7L%GXF98)D:Wհn[ k-+3A*L{pGYMetbemon-1.3.6/.git/objects/29/0000755000000000000000000000000014170643351012570 5ustar etbemon-1.3.6/.git/objects/29/0672f616a9ccbc7fdd4c2c3fbc415536a6b47f0000444000000000000000000000025413455624441020145 0ustar x] 0})](I? ޠ7&h߈7p>oeP7)'f GrH^wűuR%^3kAuVBmh$;@m#?bw~~x_|\*:`]VFkJQ^b竁[,xOd~.9k˒Ό<?ݕx?\9wݹr6$^6M=fq7ƏAogr.ƽgx_Bi~3w'R}̶>f=ze>gǫoYCjn?iXVb{R"˲$;N _ǽ^6O/ޓ"봇ٸOПi/Oٽxuǟ@ ŰgSa|6FeoѠ^RI/kq>ّA"c^=폆O^GGފ\FcEٞq6:gE )W~0 ݬ?NѭSDG/Av.&dly{o=e}oo}OP|z:Ǟ럝1h(9>!no 6<nvpwz@uEN٠`4<WOq6Mq3 EsC8/e[΃OzV/;l LJKOYϲVWWW߳:F'#vO956-|H-<o1{k ei{77v'h7赁R%{ӟg΃.ȸ>GA ix!AVd9=[{EҶNGVGnC8E1Sqe!F)\6wF ?ƽVX/>r~Cxe4N)poEg8}Ha4yk$|0foXz^A PZ h滽C>Og2kN1VR~,>lO;F(%%~7Ź>Vz?W0I 4‚δN}*ꏴ2Z@Z0YRk xta0ýqvB{`ua`&"?9vkAO ٧ɧɴw rg-Űc`;:ġ)ӛLZri36%Tmq8v@yOGPǐBJ#F` ZMbEL0]7+ 4%+Gs) ; EBpKZ%a%DD6"9}UmwPOj{Y;aO.@Ήx|+b, ,)N)幂Q3?hI&W;o6}F.; j5[ V]1XVkll>ZL_ 0wzsswk@ꎆ SSNT.]˩M:}+ ȳ6f&gYy$>{Z2XI;oa΂:Y+2u>0 [+;Ŕ|"\K^e;y*K r R'is &e>xĊ-^MFDHBI).!nu k/`4:*>F+z. >-S*B>4z\)b˄O챐?b`<)Z_0^hy` GgY'l`|oG}2,Q?(2]Q[fEddu-@Uɳ `¡*,cz%'T8@u q ϠZ[$`-Ҽ52XN`8,g:/'BE*H (&ua#'~Gžw47<o:[kFIb<@7h`U zVwgV-Ƭ5JT:oO&Pl1CsҞby,e߽Xzvonl` oXnom\$ Ѹ RN@Bffjm~H{P>ӴɦQ_om|m/ow!"JzW?r^ns`sowokkWuf=l03 ˷6:;\TU  )vm5Ͻ盻}fg{`gMUdHt̎E8Zߒ8 HLl.7~VJ"0<Ի 7w_k }piRj$s^[E+f)sζe#fh` )Gc |:W _A?xq ?ǣ!XIkZ% .Ξ!b(iւqx1 vG\//LàXx+_}s(DtrrqxPG0ad4̚]u\b&E@.s1Zfn,,Q؟AUhOĖcQR_jXGTÂ_tAut+F.`ӗ"r{w Bꝲ;TQDӌ0YĦQC⋍RN<=%XX߻#K)\E}}%LKh~ LX0ҭ̽}F)eV~9_ ס]d(FC隷 ;tG,ZYم Q,OsNϵJ]Z0;PH 9!<tsl %yZt,/dXEiGHF>8uxÄڻ=Gj:BP,C{_ٷD2A;w8y'=䔘l8zYS!M]>z烟Zzy.Q~iyϩI D6+ႍi,o*ݭM^zIL' [n厍Efw0yBϚh./=,:M[6.ֳǴ 4B[uOXXOO>9)=x\;(}EoX@ze3L똲5>)X6^}ځtگxCݔ͚lڬ"DXhP*7gu@:6}5ѳࢋ,U>gBQWާH۵yԽUCH}Z^K(P|W(a>txp3SdOeoVRf?BU=4!٧\pȫDp\sLtC #< o&ЧJ T6\LC X\gS6$: qACi +Xl$i7EH eRheUv.XfjKvk WA`CU'lu`sujSU* Fl\X݆ U]rllmdN]QC5~T0Br#RKĭ#jJ4߬+H)gPNT12E(jډOޅZoGLIaCsk9 CHLҴNA.Qqd ؞85-)cf(XjF %MT*Nba2I!;bAA!hdk LQ+Zs3 w+YgRN,Ī.(pe͂U\p御lrquncJBUZ9EaGR`?Tk ҒLeܛb_dt󬥫|&DB1,? t6T6 8iLKE.5mSբ nU؜C8Ss ]ð#@QhXY!1_cfͨ:&$ Be8_e28!T>*^[¾ RMK\a x4FtMF9 ƅoRD.^9_AVG 25]MTl}+rY~ǽ)iyƴ6_WXVR|w+xŦH kF:+rTURw<Qwr*qy&8Dh>_n |Uf-R ->ʾYscDMl9B`sF{dXP,S+p,e˴$âfhڸ.q8ثaPki U ʐi GRQAM. F?ZpDI`N065T_tC(h6S (Gzs{']P{Ӈ+g|A&vԲH:3`c-sn˩ Y-܄t(ETB[MLm>tC#Ir&P++g'a >}3l]b" RO8.X' .;0?EbQL}~mYn`F Ap.=wjMw)VR2&=J~ԧ7[vHp<>df~FF8-Bgm!O C15V@Đa%Om#m:+EsB,; }ӕ¤·:p~Il(qK'&phV@t mنaL.!'wpZYq0.~ 3B7YypTJUn+]Xri'La`HmgaCn)c<' td) i T-,$gݹ{qr$  O[&l}¤<၍Xe:]d›5Ieq 2δq}T||=7*]ؔ%O(헓Udȩ%ꓯrNَ,șya4EE|\>!c(QwƳɑy0,$(h5}ݪC] $qf(0y">}VJŦsB=UT/VyO~n](-ڨg؂o5dP8#*ƟK+)i0ƺpm d}W M#5!.D{l+sp{L`~MNbdc+bd :VNIy lLj.u/Czl`U8=JZT li!zDa l! 7ͫqLV"upQg]#R!r#,W4Vm{]f 7d69/ ɌHZu[S=Fa;_ دT U(<jkɀPbTaLmtGM`kd("%?#4ahF?n.w$U~h:_QN*] =I!{baQUsդHndm}cjAmyhT18 ؙԒJs:7jI.hgyEz_rf$`lf[* r Pl^>`K@"T9x ;"Я3ئZ:j"@b8w 1Hu`٠ucl6f7,oMU|ވ )y\ =MWƤ/TKC#$ `50!N˄a@VVd^Q~9mT5<8,CZ.ōyt-@a]̄ Y]1HTKw3ؤ;`R.Nhbq.2:0+9J̝!OZB]9.\3j85mINE1&sr *_G 4HUtC}ɽʷ~Fx$s?=ah`}GWu?ed"dػF}&fk62[\HY ZC6uʂ}u5[nwDf)եGQMMCp07@i$_CW"5?~>6Jsy[B7{ m ##HRh1|5{,ѶÖgy]AGq,qLyHFh,S&OF~*7 諔w+nqW,"Õj"ARxa"_I SaV7|6?#E=lbq4!  -9*GGP=3EcP=aZ AEBk|m̓mxwX}oć#erGΘe{^8*U"-Tn͈t$4 Ra}̢o $BrL`'4l4 k Vm<|)6"[f6!;Q.^]Pb% 37$17G哚<< ?IF r5Mrix9pHi$R~1X8<27cڰxڈa> u՗+ yLTH;ɊeM Ox`;i1`x)c &QJJyCRFAAY`.G֏ޥ>7HaSn cez/}dzAl4EHV Uah j! !7T x!ჳ+c gz~@P A.[6&pѫFdH,SɁN?#7 cJ>Gn] 1+e/^rG uuEJKP:#GU* rD(i/ob8 '@`M1?A`UaIXNV<$;Q T t̳a5Mt&Sb=Kc[4=dW8,O[Ic}HÓIBL[b혡D+'Wu\6g6 w+;u砫b̮V T !Uyû"E[|%nQǞi0Ӫ'h!˼!fAox2=--ɭ2Mޘ٭*ljU$ʼ>uhdas吝mfu͜؏[/<={s 4,Mxh^tWBhpu\0:;*ZOs`1%uY.<[hLx\8-K،^rZa!R3lTI56^Cr"oC|ͅǏi.;SLDf#9j[ W2C?Vq2FTLͅM% lhFp [&T3"m|7n絸ER?%uUmƫrJʔU]B#51H(k&wDfSM1T>E%gN6㙟ڂK5z>ⓟZ0w˭ <#'fB©,īS=fD&"šfDZA& rIЋHI>?/@qdSSq2X XrQ+&ӑ0dG ^@įR!T lT^, "OMFd0fj՞)NA Qt}`ckR ;Xbss\Ԏ}<|Tk#wr*jz`c6*[UwUR2j8.&V!,]p[ܿ1 #%Yu9FVh4a汌rIm$]#=KAufʯ#3ŗ }\tt//9: Y>IYL(57 |vԕȘNGLO'yc*^*e_HKR.gZ#bR *iUeV7ZX~/Ee<<7[oq/˗fIΔ!naه$s>.m#2+\q>20uN(B!ԛ^T´ʼn{[&N x Ee}jE(20KV™\r CGpp Zl&@E3,-!H];h-PC=&0ȖWE9[<8,|8D  1M5^aU.>8<J܀gTNJ f4T -K-e UYHU@4e P{2zӧ F+t0aLw&SmԙFUӋ!Ea1 『 tN%Tq:OԚWм=fӒS%6TDN_Z3T zѻsD~Dŗ!װ3V7?2mK~hb: Ɔծ}%LrZD0 +̤gx1-3kU|x nn.ش gAېÍ)bPI"YM:&0ӂTQJ1uV-P,H`@|AaBb,&E. yG[ʢ&cr$2*eS% !6h; m џ6Me "=pdHV$yxh+Xz$=^LLǁ#Muminx#i*|*-Jy" şnEpFrmh3r!}S 喰;"SgW ,m$ œsv?^E&tYJM IF1?FRy1lDqΈˆbYBX6Q:C5,FΜ`X) ľ9sI(?Iͦ/a!Z.rWȋ}0Z3EGĚ4elQ2A/ϧ?v '{ި} ' 1( p1]GLj)3&}-d!Wq/o>BFDԏ -/N|F0aOz0t$DZa!?\b̜E~끂*`vB<JF?em|ڎhG+6K*O!*pȐ:s+8iRUl@|C2`"2CgVqhYVP0e8N+$gFZCᚴp˘:j_.ӭЌdtJB&+b0j!푘H^>18X!1T vLI͏3d)gYCx5+!.dSE5AAQM!„.?r v(GzN/tT{TE,im 7r4W%&+ܮPH_C[HK Cpmwv>-/Ht d8i~I6cqk e]$o :i1udU,R۝PˆMz@tCYϸA1|W󅪏 HG`r!I Sj6QW2PʊprVn 2_+=0\뙌cరo_@ obb{t(7ooCOEVܷ֡`.2I+A6YLn qC7{~"?Œ~v|Ӥ;3 D7F(Y q!RΜ/W*|T9X7@#>$ɫN_>83%Z]|J+x70en #R!#~#JG# GәJcq[pԮ΍0M"m _H4Ik$XH We`SLX"Mv՗-5!Ïu7Y$O5n0 ?rPVr4#Ew3Ts/S94% Zʠ`L5!Ѵ'Qz:(co 7H qEt3\؈fz O!"?]d$dQX@*쒶)7.o2 ϕDqf&?PAb: gIK]#$椨IQQ cdՁєp^ ()c9-$bg1`TN~ ?s %W_Jm䇽eB$"#c ?>N=M .k.pM>r:J" %!z+1n/ِ֟CB@T"ADmIؠgoŻL'#ۡ "J-!]vgk\U.Yi(ޢ?,$p>2cCZ(tv- h.sXL9 @ +J ^VTb9D\V4]U8um6@_(I+ D_" ıZip}vY 4PP+˜ɷ3șl>pI:7ܮr܁l\G k#6>učWXm;xvz:+)$Jh+)6J5>؃c\]C Cޥ9\SAu"؁/ojCYڍC Fh&+w;V"vU;Be.XRRD% '_:JyޛSǀ*e\3ZE"ȳږctHU}>VAGg!h0ܿW]FiY5GR+Hpxx)"?X;X6`߰:tM!kMD$ d@ g!r༓+]lƄM\zFppۋ7WGL[]$XUKV̆yi"0|З2OF]iEESDNfDSji@ /JYRx A=}x:8#u4"NiPDKn qAT슘ʔ2?O%xn+9ϳ 앖]F"(EcOX: Y Z$-̸ {,>|ŽM2{[Mt.(3zcp(PE&F7|lIwXH{qv~-pTuoȴOsE2?iqHp~-^ujwey&,םA=}m{rMEz +'~& _=Ǻu9WVOR7P0qtDa% k_7Vn1P5Y~$—j"2R>UBr/e4-qQ~Pme ?q!pUlT!č\1|á%Y:S0 Lǜx1rIە ds…@[;۲P= q֟1Ȃ-c8$f^I f#,Ta;srR&G(^i70M3*VOBBn@a.ޓj%Q** F(K8a\;Y ƅ~T`;]H(`L't/e[&ԉOFJBtQT4kf!86^)m0g?+8ly/'!C9"X~.,ڻ `KQ1pQ[!h',c+t7ϡ/:Ee<)!(yl-h/HuaB*ӽi%H"ђ{pe%}g?teww9h $3U BCdOgkI)lbJ peƫ7N82l`M'rtq8|%qaXklHOgQ tc H~ S8֔Bgps!%dJ>O$B)zS&p %ZZHn-eص/KqEz` Wp$ՄB0<9" l['ێB̏41 6wX.,N_m']4E8])-3'\^9CsG^fiтiSb5C8`vqі u`r&iY-ܚ9E#ΕRGoӡ*m:*/򶢥DǺ@v?E)| #?0Ѫ{p c/vd~f A+FQOt>L40Ɯ10b/ҹ(} `8 ,WʈZ9ڽ 6*|9!J3!Ykا pݕ+s Ȥi:kd&.UDߊ L1ŬW[!! 1\kUL_C`w zH`,G?;ΞOThpBKKPv@+4p+O!]6ij2"UV$g8x 3#@k$a+&$$e<ЅbbJ]'ܸd+h`NQNr}} n֯[^'o3UjH̷E~Q)l !1Bfb(2#T38 ˼/tT`<>ý2ZT!Vr­YX!P ql R H 9 K~!Y :)IDm2t_Ȅclp4{"Wlf;)Ar$`ӚA0ƪ)Y"+CNÇ[՚t" mY9 qϡP.?ٰ-] 9v {Kh^M4. r2wDf;/=AZ[H6uW fg'`:EL[}:ҥ|.`HKuA$5?{P8^d ae AU UϊfSr2p@%JwŐ" :nw/TUVnP> &FTK9U#?$bITcv9?c7=;rڸqIw" Qe׌T8*pWW%bu(G_Y8Gc ےЄh,MD1H hWU޾@2s ilaǑs vf2(Ǫ]N,e>k>4Ǫ ~[87џ+x77U6(֝2GUʜ_4_.aU T {˚7w@cRZ '7uzFX?I̱2 ;̗h,/-ɀȼn12=K(u3=Uw[QD0aV:£9%x-jQgKXbo Pq[`|P4^o~(;ܕ6c1汇\@b+z+u vqc:c ŇatK|k0znY  Xm,@/DPrGC b0f͂1˙Ζstmw6ϒdsGEľxR FhL g۸I*adQy& ;(vPJ3ˌ]A\im#s3Pa7~a*E {x}ȹ2dbo"kR"4ദ+pB%'UV'g-8I/QA0g`} op+֎/qƵG"jA;3 >j#HYݵՕp?@*R[@S(]tI]ۮl(ypAkb?_ugaKls6B<Qb CǬ^QTyȨ2GeYW)7!0^Hts%H(/T?oy*Jo{6>GG::4opa9-|'.ꊈga" f"mς@gZQ 0@d{^zփ~X,g2oΙҳ UOU+ Yoh2b ڀ| 0Ô*_,O'ZZ.tnz5zr]vs&sMHˏ:b$jRwrAQg}o$zԱL^'YCX aR{qA:W)3T3 ECK@DF+ UU5p@n8 zKL_-DB)Éo6*Y{^eDXb]nlj kEW$lclM>/\Z>Xqv~f[Jf@ 湹7n(S q.葞[AlB2uFk ʱE Qw8KRĴcRsNg,5b(t(m (=* Ñ lE?  [_7 ݴǦ  UAҠ2 ,vKNdk3RH40S1 TM\wڭFHF(.j:XxH @`b~rbTF2BDaKhMnIJVJF &cg?sSGDŽ̔dyyLzqYߚ$vDgRUg"4YQ7n%wZyXZ_;33o !+4}Mkg[gj_w-sظ͉ŬԔyanV)R0zi[26r,5Y x  _'H9_\s9}"bi4ؙ<kRk"Vh!?%#~W(|G\,7h"+'^M 9d8Fb)ĉ\nD*L32;9$Ms7BK<@֦u*C?MJR7ʐÀwǸ-qj =Mn4l"`Sd n*U~<2KX>/vJ%Ӓ(XPDRjN=-Pƻ*~ 1C-o*+Ŗl0nDfTNJ|W8K~+ |X>(xb 2d_)~tv^MJi K'͚B0.W1W*O%:&ㅶB+DH;@ q{M1n]ா>vng2dlpHf] 5sɷ(Egg %o+DnDlr ?n|Lo^'A d/p}K8`-  ՅQxwC ,uJ["X0W,.F҄D \w\tK܃3n? T~P^=4f˺oG'cx?{b{c=?}v&!N2Zj䡼ᶼSynm&@ }*%:;L{Z~:hkؔbEjԎW5SAj`Hh/g9\UTbPsuג$ݽw'0FY>S/wk5Xe@u0ݽsgR.Oo;wׂ&,Hmsj ?1Ya -4 )ڗO~>?7i^a8iPgMn, 8A \VKa޵W)6kTEKu5n21Tagw&:mNǣr Aq$0{l\U\bHhs yDY{>x 2kH6cq#215d:0tl`e\A`-DXZoaJy7l\_.w*M[Jqex1,P`n߀TU]jy? mg7P"dn҂ӐGN@:daMՁ* q'1fie~͡܌=f0qrE:'Q&!ܶzPYoq9F݆."T(m1x_ AA^!.nX7j,9C~ *(s=N^zc4>YT7aLVGfv1!Lg,v͠tLQf\-mi 7]ěk"tE)OXla6K+ASFGgPçRB F0͜؊Գl7V_S.e\_w^oak^,0jaQF9)+h.KV:2ܔ@Yg'eHִ-/9qfDUUޑb`Yp͕$^cϏ̅R#4xZE&H!"5)4%;N4"<}6r5sVfX]B C֭(W/`pa߁ #[bb M9>:A)ABaKSm]8/) AZ6ӥTaI]$aNl5xHׄGI2R/;8uJ)lk 7hdT%(,y|G^6l_{gM9kɺd[W *c>;J9ukRv E4#dqV"y6}wH&k[u jF0ݥldM٩v0D`c&afj7M$7ե%-O=J?E0q/Lr`Oy{mƿG;bχ"/5DpfQ>iep6woެ}Ѧn2LZBw\jX.,QFO ?Kᖌ.?CT17P\A(b0꒷ꜗ~u6pL0.}Oj4ژԸ_G|Pkk&Q"3UR$<޸rhTIa R:cUD2S:P^8( `qCmyeڔ֨*3p'ia->%/"`[!ֈ.mR?`<񧿏{뻤|%`o"'D]cAX>i &)GVoGIP"A?ׇ[k9s$5lT&LѸY$v6CD"R>pebbfv2,C`Ƣ$ cqWO %B9G ^L3UE1 ґ)qGn*~5 K=tYm^9VJ*'sT$MV6}kr@B/B V'SipsMi㭔.J ,զ b4mpЁGs*FM_*VawJE ʲY_1T4]OHR(V-g U &v!ixtT̤:4NU˶'02ۂTQĦ489msXkwi| wpgUt EAxo4q6ŰQ$Ro@! \9a{%[*# 5![isvtk93 1I %wVRjX+܋'K%أg$GtaWrQoRm 1U ;{ZVk }0' g/׹ .{ xG@0J?vP?`ŹN.ZTS#yiܒ<J<6H{Q{^$ 3I31/ADG{4BF`fqQ:^O_(GAFMC 400\%͐NIz-פq< < m&mXK@^dC3oY0s6/ҭ)MnL6GHE',N_{[+?Z'h._R>E{I<64 H2ÔwLhӾtd{ c5[Cw^ g _nM{!-%aOXZcZf?!OIo6(ͻn :9ѼA>LVcY g˖CX. DM;H*uD#HσI6]*|5uS>fJ#7Hŏ@+GT;^I!1'48yմ|ͽ;9LBW:zb#,9qXXA :{0M,<KQalfe$jOT7Q(UnB{a) M(~12NR&ҀB wJuoomllb)&7o)\n'eiy+~ ni}?6yʂĸˤ'.JI\:T Hhj4""Lͅ4zZq KL[0,9xRkͯ6ׁ Z!t=O{V=!Xq~w9"+)_g M/mRd qt pUY#hgz'DvG!- s6G"-P-B <;*". ȸ@ԆȮJ=7^g &eMB 4I|sx,OZ%%n|l jsGVN.JFئ} w(W13OZnU"IL\z?aي> 7H1iNß},袰4M780@rf-A5c36%fx;-ޝa/eEalr?IU߄$Hio}9&=X&,"PRN4ky;oR!Xu=SgP}_G&%HDHk7K a12"Ry I,(3C,̿aUAFl |Ky U[&e~/JvZӚO-8][C. PY2@#fC Ǎ43N8J0%tc0b )+L">̎sDWu14\_„5υ"!TظJ{I {L\{D/MQ.qv䳻"AR C$ _H8z=r\!nd\ZW䏰cd`y2eE q@X0 8m|8w4O7 `^\|£C@l|T2(ͪN.ćF BR'H(R#vYS0+ F%Y@/Q+D2 h鮉63먌:cL*|FbPC͘c(岋*,4M01Vp'4FcSBkƹt@},ZCm HRkU7xgή ]"o5^<* cKIogRf{hXD HaW|.NZsֹwܭқq;PnYG b], i[#d 1|rA^E_Q(Y<ҟ./ و/g;TSMhN9#tiKG>aRX,H7d-cO #ZD@5{TDL_ՃdrZe_D\}Nit!ūp(2x`殿M>,A{6,1 g0pg5kmd[U$L,X{UտI2sdh]qdYp $X ÁsUgzm0d;wyXBhIq#6"$Rր]_蜒̓s[VTC""e,TP ""›F#ujW x~Cۛ5@r\X E'4jSU[hmEt>PSjR<ݿ rȲP]H/oǟp']O|N_"Q.OĩW*q{Mew.B@BQ` $wKC[ kTWDy9PMRo_Ֆ,4nMpYL'1Ol| N]˶Mk V_#% 0''$Bu\a?{tI~R]gݵW.B^$ d{e$wЩx(Yv:J u 0#פVWJ 2/*6*[8=bez{2>u4:vtH?: 9d xq]KKv;6\Q(7RӦhFVn 6„ɬi82:g_I8TXBT"Y>*`Pr =yʲIjʎ*1GDQA;΋$%ݰ}ע-kʍk wL{s{}jk ˮ+fHyda) \r%kp>*d=ޙϘȠ,*X( SJ.4:ZfRS#|v$7V'fݨz$JfbvI_ss%н:\2W,yݕJ/C<@" N V!#8\ċBN[Qrѳu'e@MR :l]vPMB#xJkRBhƂX cw(pi%cls2n:5F:Wf%jyO!@6dX`o#RwR n[5o}ezI!bЃb"[Ajֳ`!B> ^{v8Xpb+"$! pȫRֵ?s0+GD5!g'6KBe`fS7O|}{t8Ͱ-` ƿp"&T,IHwDw‚a< Y}Bx̾Y[o.~}Zrlt#B@NL'TMcEd {L3f;bI`[];cQ e7:f:T$@GS R@mi2bD60+|֡V8XDi u<`,)/qLS Uo)D4B*G`ײad9Fs{ ,bFae"`ptzD(bC͇6ͿAd*k)R姷^;w\m.A^~G` wvvëQq6N`d4eƞ M1#Vd/z;N`A/|h<͸gtЁ%,.1р{D!B! 01hEXMHyepV}-c3;x].fs/`%dF sGRH=-ըa'ѡCtl|Ե.\x`u_&"|8̘QlK  Dמáޑr'uSKkَhrNYTH8Gr7v46G,o&RWfU7XЏ2D[T?:XC R26!ǧx\.Z 5.u>=nf`2'Nr2L& Epɥq&ޅrD݉O"H}џ˸01 tw~z\?n7dk׀#|U@fD>;IWzwu=G/{RWQt<\G w}]F\Wl Y8o-> X1PvdLH>uJGn&_,2Xs5kZ%Cxj䦉!i[sD#JЃpxnYZoc@#~G6X{'ײ]r6ߨ$K%~|Wg_ e ٧IP/a*|ǩ(p.sP|<΃uQNv0brKQROxrpH>(DQYQMD*i}'ZdN/} ]KE`S4W1d" uw sq}lud u$bu4qpA0P tk1=M(mlHԺGgb]۳5-Eӫ`n=C }y(5,p J"V#Rx a I^:\'vD 8O0O0ua6/{2k;SiÇ֩/Xj 0ҕZenƖ}; [ yӜ8G5dy8>4&JN~:Xj+Z}C0p&&n4;Ijc0}L(Ai*J[V̙ g+h B%'ǽosl;K3)|-񝶦w}(\o=et2aD9>8g mLgmkw0¢B&9mvl+=i|?| dcv}bʕVj’6]ሆPDq B<&\F9+vf`_#1Y7X .rӘ33ZȮ! 㑣l#VRp#R42;F+uNMwy7˩9h%_G @úL8GװHV`{bs#d%("8'q(dHqrHC"i[\ltFyjTJ?/( AYkU'%aje;faj]!v$׳(sN 豳]謹9dB$6a?Ԃ@`v(~ܿ >KF3{B F`۠[E cdBjO1_ci Nc#g'RMynZABkWKbYIMT(w1I>Q$1cgHm.Y;IYn(O!ɢ 7"\[r-^n!֥3M']C4|;$sV5lhtMLU'*@L\ m>VR6rfD&ye׷1!K1'FߗiK!KX ąK%l&&pzٸue\*~ԼRD*cMw;xLF(p &iW'^4o@1JN EA(-Nf.2 (]JR !}ѨՑx>FC꬀!etګ( D8*}v{Ei2gQBHrn  uuP}% Đ7UE4]]֛#FQ۵NDb*Zk&|RR<^; 3QLYcp}(U#-/nߊM0}JA%n[7V23c:Kq.5!zGcP%`=NJv V$~aB|%癖HÙ i8|xC)#nV\h# &ĔfTn3ˮ H5:Eq#cwuS_KDMϑ5~묕{Cq*ˬ_ޚYV"Z%ΎW.z΀ueGVSISx]D㪃a%ԿR x@h6Ξ2HDbYm($َ==ONp_eE3; Noj۷1QM )` l*U{hpzJ)G>d Yj:o~jȻMu_ҫ2 "$4@D:+ ?|\>RYIYL˾(*abWke@#7(Uu{;uAxz+>+ڽ>tym/VOlmm,; Հ"u}߰,/ Ջp۲*u_u6_m\Oۇͭhk`rwjޠ0QޕwqS^gcK`ΫJ63l)-W3vq +K_i>pig/m ngN3mVV|`1>7E k?i Y*}ՉwD5-JGvۂw^ x׻pZyc..^w~l;{[;AgowosIǭ핥?bJt׳ǜ8x=SyXɾҫ_zퟶ_,~%s зxҮc1ot$p>M|31!TP}hQ}?~ 5:V yZ;6CnM#Q13܃r!F=j~] %*N8Z1 L(*6w]>t8( c4#(Ylk[u,fw)+ݮMXuE%٦+\}/]䓻NܪS |erzhF(,qФ9r)-`E2hQS嗓CZŞ fE874b&jISrhA:>s.9,󋈓_I)-\~67kQ{# 5 wF 5>{Rtd[{ 3a/jp gPUz&\\fy4-G EV4LE/lZ1_ͱhˉq)@)6<,j.R Db5DV"x*LQEDW V E+*$b1,gP6cno!k1h#充7_3cr @mXw6r߈^FH:9yyFjIQ.i` m0Y*W FHKj%p ]3xĬ6ڟT5.J7_2]-b}+ك8wsx+ s;篈(^@p'!+藉0S\ ·qw4MYIr =8()L8ix葤el,f&t[LHdd}V); LnlL-QZg[F~+#Ksa^!Q^*tC">l}lf4>R MFsG?hkjCG"TX%Ռ6ݐWk%RDL^ݫ22hJK>ԣ/׈3_NTQ^]dwvW3,"Q +U3X3V`}2J; I+,>ߗZn ob6ǵ9(fq;*G"VE]2Έ-?q5usF28B%tGD.wump-U裼<1 烑mz0#;`1 ?P6Ö=348뇰' Mkrz6$J6o$3bƄQc{Ev~V=#fxj P7ݖ^xϢb}70v vqCE3"tCp |4)wq^aQs?YEFb)JMwR8ׂŒLM\ ?R &>7vP&gd~jms %-X ibQ4;v_$0ef@w?4c&Th=gzvC^<RpoK48xEmLo@KG7F7Ԇx`Y+E&qao56)8f_%w$' :YÖz4|D ŻI@~_YL2W S r]ܜ裒erTExeu< 8E~؞#?( "7ƃ)\<򦟆'_N!!E6New7: HIٜ["8op풕L^J3"v ւl#9nk.=hŤjZrZwGdWlQbdWQMkq {eAy C\;Y5IOk3ʗ2.WL&c 9LHyv,1Pk"Mac9u?ƣ/jë9d Ц ht3gS*-zqlU4>.SCI2Q٢͒EO {=9ԗ4;*b뤡0oEF%$B2g֞紘"L>[m}.+^G q5e5&#IA Sij3;l ;A@n1~o$7\$%Di5Wu>T\L- ba836뮴2 LN }pU4VOx6oGCOTTcGSK]+uT K)jF Ԟ*:-FQԮn[act oC\[~2G DH'FVwE37:! |r?$$pKSǮ8 NqVќNYVB(X W2{+s=`3D?>)G1G$Bc}Z \nvGO\ͲݥŷWkO#%ʑ*lVV#Ĵvx|Z S_U9pF}8 fvD;rrB@KVtUpe ̺.Ѹe.zXQ`ɷQq5ѳ4\_V=;$g*|a`\8Q_b\eć? pxvfeE.&\_P9P#>ϫܱ]R26 94R;O)w=H< b+:HƲ0Gq<&!jgǜ:`dG9Ɛ1CH/4!۳oV_&a9h-lc.X@i4<3/-4N2 Oa6UK}WFO'EdW֞W9AIBc/Qa <œ7nno. b/,4J;k&D6SdRAaSv?m8f⧷8Z|=4eDyM@)oUt[qnlo!xu|hyۅe6l@Qx*AU;RSp}f##stڻҙզ9{ >иy2ŹPA`'j#Bb "TvalPEr.zg<{2>C[Q9?ZZF:ht̅2zJBDuٳvh5PkByu%O=v6ހDp/l|i d*ƍ&6e٤Exl/ˊ}*L)W07F!; q0?+@JdmOQ "҆bJD5HΗ"f'3M='pEM)- 2kk+M';)Mh.ř 8Qζql%ܼ˻yfpDH I\ӵ#TKF;Cڢ$)%.vYAER H\-5k1z<2fPi5Paѿ4޳4rse*+ï @@Plc8&`I쳁MVjdpjvX/Qb-">L]jLY-nbx-CI0/9GpJ{b#P1? Mi` Zm4w5x}Ad5( WHetbemon-1.3.6/.git/objects/29/58412fd501485284fea3c53bf14d899abcbdb20000444000000000000000000000030614170643351017777 0ustar xMJ1F]ҕTaNA~d2$io}^кјaQ֐ Z"lLm8$H}%$_"yWgVZ19[m~9õ~rϱ?`1ikN"ì/^/yF7(ܻ`};#^拻Yetbemon-1.3.6/.git/objects/29/787e4518272bc9356f950214e41da119db33210000444000000000000000000000370713212012742017335 0ustar xWms9ޯ+:+C0Ļ .q|7lmJfFHs i l'|YIVOx =M1?ƿS#G$S偽S"V g"kx}6<;l47Cu8\t}3~3:C*m0;g9*0xh !fqDsq+PE!!ikNWTPB+ŹA4l5$]" -YӧBi^Nyf˜H#q!-h^| ~Q34?Gr-6Zȭ@ ĸ ީ&|9HF6ShpѿnU̼}/3ocDT)J$8SM#!sE18rpf5j?׸Hay o`u7b* ^᜙fğXL֗7FH;VT:/ 7ͽ C/ST\J7hL1Ft`Q[7 &ZW T\"[hZ!Zy/6soT螌2~2l#cE¥CEW +>8p/AS[ MhH'XVdA&Swֲw5p VOȝN*A^Π+:#N"w]_n#^c>:HQ/rg6vlBj˛ 4f43 nSMQxTxj.1Y,PTGKU>+nk0<{d;$c m &ܷ7jߏcd5 bS-ܓ)+w`dǡLVW\JM q^8NACJT7h[SS%,gRik yx[kTfu\tP "4l׌Y1i[hl?+_CZġ[Z,xS8Ѷ!#s0 r^4 yWxRvjSygvR{{Ƥ (,+,N\7<ΗܕK./M0pc#+H;(fkYlœ9 P8ELJb4&ZDR }v9H粹m otB%^tIWЉ6)GPetbemon-1.3.6/.git/objects/2a/0000755000000000000000000000000014173226610012636 5ustar etbemon-1.3.6/.git/objects/2a/2e54251cc243b6da4b819d9a4454b65ff27c2e0000444000000000000000000000141413455035510017764 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTPv.hMvZh)TIIjnANbI*Cպz SD2d~mmL?2< lrNfj^I1ó k_>v 1ٻ&_HIMLc|tNA>.2Ŏ*OfL .s|Ȯb{K % 5].Sf/g橫ۡcT)㕙OlufnN~rb0,.R?'>տB)pUҮa1'rU p1z 2>N,^ܵsyմsg;?;A(*(a`pޖlҏVmr1(.3cڿeK'<}rbk{**ewa!O SƾךW1BTd3Kv'sZ,d-+2<yR:etbemon-1.3.6/.git/objects/2a/b909010e2c8f2013edadbbf5a2b287a706c7310000444000000000000000000000141514173226610020021 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3E+҆J?D޷ 1D69'35ܵ/Pj;]˯BT&e&14[gp?ױPsrڝP u&'ߞurŲw}|M-ʊ--c;Wn'[$c5'qmȡǕk77`yV ONƍ:=7u>_w`} (I #}T~MNCh^qAj2lḵ2=_9f>Ԍ Ym9v+hA&!c`8a;K\t7!'8/`V) n ^q2e{yES(DEiIfN1üow>hOz22Ib"#gWetbemon-1.3.6/.git/objects/2c/0000755000000000000000000000000014173220716012641 5ustar etbemon-1.3.6/.git/objects/2c/16bdd01fe2ed0c37756d507fe59524c00d29420000444000000000000000000000126613212007027017700 0ustar x+)JMU073`040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35ݢ{%\\q7tW)Iy GdOEKq1r+*}*Off7 ̏8,_x^-D6$a\#/W ۥB"gFjFAi>?vP[OwmgD3PO]23yGMϘ(b1G4@ Rxe|Xbkiv vQZTP2c9˽-n>]$b QQ\ #=lǴ˖Nx1l BTd3Kv'sZ,d-+2<d/:etbemon-1.3.6/.git/objects/2c/88d8c88132f695d1f4594b7e1776f35c1c9f880000444000000000000000000000221414173224277017635 0ustar xmVmOHsƈĐ;PPZ須p+]C#urBJgޞgS eר2e4U:*d*#RvO ;ljmYĥ*,ٜD傌,dIVf@*%=(A6$E/*|Q̕^R8V(D0T"g]V )CS1ŲTeeLSH;C)3|IֲLBU9 R>Ǥl*KjRvzj4K,RD*jKAd8.nCП)H-Keg9͖r&jF(FNtQYTp\6B}}w;\Mvzl?aW%d>YZ W{ptmi=Ÿ,2q /j*&Au萶= )E'BڦHmGݨṞImy/lhAy,Rb o+yuKSjsa L!bbMgҷu0Ma@zbL8t]%nԼ:ي<+8Z-[BEtn)Ї{K̥#V}_ELͽ{Ǫ')M5LP4p+Q%AM2ʪE&Q.pP0؁/aTLcM^F ª!`6:\> sh e.e&j8-'1aw8ƚEP \g-71gu`w0{VjB=L0%}C{'n5q;E!Jc4~L`.dbY+Z>ފѣrbl4/qy[P' "qQtC޾ǧޡBL:CzOGW etbemon-1.3.6/.git/objects/2c/9bff2453a19ba5aeed0d3e51461888af0fc4630000444000000000000000000000267213661360226020143 0ustar xU{8TiAji% +Dn+]1f8s7]l94dsBx-m%RKꃼ /ߵ_]W[ء`05Tf1•L(V@Q|Aڇ''ETGE+ 34\ZQej@BIW=-\)8uLĿ{AZ}tc̣|3NFTƂxo>=]}poL5K)fQ;&עo8ȼD\'ʞ5.7NX01cĿgb*D@I ,Z\)7He6* =j _ZTp!aIib4*h"d_ Py7M] /' R։uk>TiΈ5mqL)Q=,N]bTePf4{o zɺ?}LK8)7kĨGdu/T _Fq%b1}?dϬn/etbemon-1.3.6/.git/objects/2d/0000755000000000000000000000000014173222417012642 5ustar etbemon-1.3.6/.git/objects/2d/2a227adabd09b5ac779662fdf62914461d52f40000444000000000000000000000270113247732002017770 0ustar xU{8TipfaRD! BdZVdX6̞̚99g2(nźhUD6JB%u]V׍y朙9} Օ$C B5nnߦ'vgTwYp9 bF!,$Lk_]b*C˪O8J @D$Qؘ_j}o{ҤƸEDB@$)yҍEa:L32a(PK鐂S2w5X׍UVp2ƹ)ɩt6+~>ڲC A`SW|WvCWCd{mMoLDu=0eey۲}$Gs#p\SC&Z:6R]ܤ(}OAp"lY^ٗ Z+u3=~DBhQٶ%mg+iY+>bI(v< 9k zߓtFKĎ6yE{EWVp|L}KǶy!{=";Ds`P~޺SniC)38iU}Gf  4"BO)6~e0a(&"..Ez??k&}"=*:}9i6LJoǹ#>3LuHKD\\l|naaт?\U)B=^x+R7*8mCZP4Ay)}UȻTj`dȓRR:xz;kzE3$mO[& B{aj:.?;'E4[E'[kde6u%˛k}&! r]NFzEa- ɛ E)&l[~ìCouc?yb3ʈb߮ Sͬ.vl8ΞP˂u:bpe $U̓a{u>bT ēq-'-p>xˊ7 C’AYݡ26UY`)g~3t]E TkrG ަd0FߑI)^1jlxkk #H(LWMN@"Rvɴgf~+HiӘofةZX4M!RF\}'fvM7GxIQ>F`y#-C;f|ֿ-O+I!KHaR>ko2OmQ}i.Oetbemon-1.3.6/.git/objects/2d/5df83844a760095485423528a03b46e5d168530000444000000000000000000000024614173222417017270 0ustar xA 0={J6M ($Ɗ)i+0 L*lz: ekMɜ|ELKn ;i((9ȚBVh@Qdakcp֕ nN. j{QJTU|kKetbemon-1.3.6/.git/objects/2e/0000755000000000000000000000000014001503033012625 5ustar etbemon-1.3.6/.git/objects/2e/0f7e1356dd3518bc8e476a3e8a0f97008ab3340000444000000000000000000000026113767513131017720 0ustar xQ DSBPc ò07tLc0ǰ7XQM2}F[iMgT;T$0lgWs jcU0& 3,Yo_r&\IAeQfzF eBWgqxiԛ_٠UXSqeNXͮ/RYYfQ1u'ެՓ \>/jbW|W^Es];Ӡ8IMjEbnANj1I+&?<ߓHH ge$0ш&ٞ;Yiڿ%͹.fX5X,AZ6蜭k*")*/.ǐw5۴|V5)+eoW}ac>͢o(lX*"ϛ?rUЬʽZxti7}@E榦 E`*?/{iyaK.)_01hjVIa69yL l֔'$g0̴.sq> nH4o(etbemon-1.3.6/.git/objects/2e/bfb6016e90e768d2ac04256ea7cc8188ac67740000444000000000000000000000060414001503033017767 0ustar x+)JMU00e040031QMNMIe8;?nN|:/wrq7jMMJҊr2KĿ2sIt#A KII-IMM,(HMK.(`uy&؟jRtW8t&0)X[^8w–{*,jK 19fA}6F9;'̼ ݒ'5UYo0bLu~bJbY:\iUGl~f|"UZ+zF}4|+Ģs H.ӻI7V0i%EcPaS`m^TUU'+^BSS%%uN׫i2|Q1= i{etbemon-1.3.6/.git/objects/30/0000755000000000000000000000000014142105451012551 5ustar etbemon-1.3.6/.git/objects/30/94d6db78924448b9c72b4d0e9da115037cedda0000444000000000000000000000120713462022676020005 0ustar x+)JMU07d040031Qs fi^5W~/jbW|W^Es];Ӡ8IMjEbnANj1I+&?<ߓHH ge$0ш&ٞ;Yiڿ%͹.fX5X,AZ6蜭k*")*/.ǐw5۴|V5)+eoW}ac>͢o(lX*"ϛ?rUЬʽZxti7}@E榦 E`*?/{iyaK.)_01hjVIa69yL l֔'$g0̴.sq> nH4(Wetbemon-1.3.6/.git/objects/30/aa75487050bafd225a0cf86f3240f65866788e0000444000000000000000000000025114142105451017553 0ustar xK 1D]&Q7h=8h&ɀ7 \>WU<7VZe(qI.%9>*e=MΓ⅕)t3i!$d Hv/ۺ SJp;rsWJJуu?_rYVMetbemon-1.3.6/.git/objects/30/be14106b9d3b0ae27907df0556d4973ff4a87a0000444000000000000000000000120614057336772017725 0ustar x+)JMU07d040031Qs fi^5W~)7I]f^qIbNY3~s1;i|XIYNf^v1Òb "ղ]Gl_V9IQA~q <:6/]27ī1fQTƈ@VU 6JJUQ`@P͋l9d hV^ jvT>"sSSRP0MZؚIe6e3jfb fͭljsh2?J7C)O,I`i]}W鑮iKM,setbemon-1.3.6/.git/objects/32/0000755000000000000000000000000014032516006012553 5ustar etbemon-1.3.6/.git/objects/32/2dbc953c638fd47d07604839266d5c76424d590000444000000000000000000000313214032516006017433 0ustar xVmo6grɺ8uע|P4СNYm.T^f}ϑ%P`b[swr=_۹'*S*JY2-UbOmzЋLiKZzQƹ!-- I̤)U& j%!+CI\ $xR8"LRkRTҌ{\+^.UtI#Y&ظTۥ$ԣtA{L\! {_1'tiIC5!0c9S(*KBҀ4"0q?tURPQE^x[8*Mد+Y k '}Bsݵc zX HnH|wx(t>5>"8XI#E"@ۭ )9RkEԵad &AGĥTqBAڈd"%̜K,B^I&й0QTdj6u?a;n:Uf/e!Q!0D۝%i#xu6=qhNr.1'X9{/Tȑ!|ˇ4ZB0n}?WPWp謼 שs< *èx[+_e,ɹaymն !i=-<3!F M#VLS +篹-rmBhiʌH/e.u f\x KV8bWԢ`m+"%ƀ{}D"‰9?qrb YjhQVFT'x2z'~OPkAgYjN 5H|.KYX1dRʴ>Wq^_%4F2Ru$3gq%֐wy*p"0 `F_ww ?U)ͮ= _W C.餰2 JA@jRWQ!m"橮D-"Xxepm]u}0׵SƁ~x Z Ħ ZOŖi˄ٲcne韧l]e򦘞u(F8n v@/xrcnB{Lf'(tEԈDB4QaXqvD/%ՄՒӷ߾;urQ+0 a&'b!фw*36dC:#~,YWz0[%qjg4о;waۚ959?=]r,=oib}pG@n@_yM&\v" ;Oǻo|nǴkEy_Zsym4 b]A\'~W+BG 8*6QZv܍-umG좭#M.{5GkH/f8%%e.r-_1O&.η9ǎ#iPfw{j߾d٪򆪝j]SUcu{׹W[~cSWg/E_Vnǁ Bns}?;=etbemon-1.3.6/.git/objects/32/dd660a2474d15616efdce73984e5a8f6668a680000444000000000000000000000034013455620516017667 0ustar xMj0 )/ J)tӴB0̸Z@$"Ajv4mM?jZ+4]+:L ~2z'9BeVB9Ió,1י3;|č|wwٸ<@: ςsꣶ,n@WcXKn398L MP/TGAbf8h;etbemon-1.3.6/.git/objects/32/ff4a0dbd38f52746aff872f74de323db12227c0000444000000000000000000000036513767534207020073 0ustar x]Mk0 w`)$^Fha%^!gQSNmlX@z$.^?۶i5(篛Fl]SJs%dP.@7>9Z&8Z'#,aN&/$0baR&!j띬a G, ؅YkF &lo|CHt/e ˕&* ۀ=)e/A-_!m1etbemon-1.3.6/.git/objects/33/0000755000000000000000000000000013604573531012566 5ustar etbemon-1.3.6/.git/objects/33/801967cfc58aca79b2ce8b23b021f1f7b3b6a70000444000000000000000000000433613212012641020043 0ustar xXis8ݯүК(:&6Q*TqA$dqL*vTkcv?SI@nx~g"K;0,eՋLR[-:w(W$~KA<_R&ARb0_.0WKZ4*"x!H\D Z,oݾˆJѩȹ(<&p^Ka,UJӵ!$Z IWq,n8`ՐUYKgvJ;T-R*_an̻"iFTń(_]2{mL w,ra7l5b%;0*UBGR^c9%.D"0"Y4 _*ig8ں^yvs}K^-"H_4FˑZj;jRݻ-i[-SuHV 丝$P$A! n/23Rsw|F{2贘EO/zNͬ$8Ed@9[iŊlJ W?%d&@(V2$V(̀j  Eo(䜜QəG/p2{_:m $o(0r*|dǃ tx<Ʉt:xN&'qh [_=.K%2a7g UD-č}@T/pZD*2E*Հ9% zd#? -z< kI:/[4-XNEQ8sD^l:DxsCj-~1N8'~S4{ir9جQEe-*븲V1β}4xEӓGE9H,{v69, G4Lgd7>^ }De4GCo?€Atū.!Dٯ_G,IZf#^jۨhEV%WS,)XKwG];wM+QwG2u;V p`/LWggd/QsK!]*bӆEy`EIa-ԃ=dEdNWګrQ"qXQ =x^5ƶ<]BgsWrյFZbna=HK tYWUszzvǮd}TWi*^8&aco!Gy[^X ,W:֍ju[=?CyzI6$n?()`pr9U;!3C # 5KTq"?8,ebLд">Bܚm7c,DqliYek}@G-鎙voA "uxeeɰSՌPH@ibr6p2N=O 3䧉Gg4zd^]hg.=kAgVwFx`){tm+nLm̲02Jʤ;E]n[Ffv_ZVĽΟn4_Xɪ5~=/Ks돝ŏ^|JWpݶKk1 Jluפ:|f6U in" ՚5?e+FhzÒAeN)~kO0'0 , Fp2@o1@۷&sg4?[Lt+ tARig2א\N3 gHW{T,{4=sj^' x x*l?No^-5sO\}.Bf>ZFr-|tsV Ty>b q<6Mdc AI@іdzG1(34l>g2?] tT_`Ʊ`0rTa#G zEVcي/r}aˁ)=U+_E.x&P. 3%cu788^6t3چM"#aK,zѢ0&Z}mRA% ^È]Dܫp5kw_4G\Z!EOw/VӓoSo2ST'FEz/dE7,"2$s7@J-:Wcetbemon-1.3.6/.git/objects/33/cbb30aca61d80b657c26e643653129211f0da10000444000000000000000000000017013604573531017601 0ustar x+)JMU042b040031QMNMIe`GbWjYjUTRVSZ\P`wLoR /mBU)lpz}W/.-?]VX.Y2fetbemon-1.3.6/.git/objects/34/0000755000000000000000000000000014173220716012563 5ustar etbemon-1.3.6/.git/objects/34/1f6f6fa42ac29556bbc0353434367279b9787f0000444000000000000000000000060713767534207017534 0ustar xRN0䜯hT@y_x!qƍlЖ;4+3ޝ`4w! ϼ55f|s%)3g(IZgyRYLawLck )|ŽDlҦB}02"I܎U?.V:O3Wov#R H"0qw+z4Ki C)VI E8A\9 YUVÃ&[|UZ.seZnafB=@.+pqrcEC9ȏ #bN3ύ@Z}Mgi,īvMeŲz,r+ir=7܍KYx;vetbemon-1.3.6/.git/objects/34/3859aad788769f6629d0be314b69b11ff5b9bd0000444000000000000000000000141614173220716017750 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3'}gWuO=%RlrNfj^I1ó k_>v 1ٻ&_HIMLcXyzlr_A'3U[|{mG=D6(+vcM@\[*Tn z#7?sלĵ!zWcހZD3PV7'?91 ғ[h->|r޻D઀P?׮M44&3\[+LJ+nA(*(a`pޖlҏVmr1(.3cڿeK'<}rbk{**ewa!O SƾךW1BTd3Kv'sZ,d-+2<)X:etbemon-1.3.6/.git/objects/34/6a2d1efd434fc6c9b45f9b9aba526a76015fa60000444000000000000000000000120514052407207020131 0ustar x+)JMU07d040031Qs fi^5W~8 ܂-,ӃjPwl?%훬:mF_J *23Jv."lw8S?K5<ԴҜE/;ovjve}2f>If}tOyQ<'3E(䛿*-ܙiHjR+s rRwH \7G:E2f"+.Ia=W2`oN>&u'm#).fX5X,AZ6蜭k*")*/.ǐ{~rO=ޣ\x6,ȪRUI2 *R1y-Qͪܫ1Am_Nj/}TdnjPT I [7f,vF5L @ڬsRMzm^&pC[f5% 3aOB=u[*=51`+etbemon-1.3.6/.git/objects/34/d1aea7778694839be16d3135521372dca435c30000444000000000000000000000126513212006521017470 0ustar x+)JMU073`040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTP%{_λnȰh]h)TIIjnANbI*Cպz SD2dWRpov]lJQW7ŴE? Q ,Ql\g ?!ϛM60?j|}p{ԒdsX\)pn2 uhn~CatkCn>ݵ}˟@Y?w5=cʢez)(.HMf9pb宝˫;) jFiPA ˌ,f~ wm1DEq 0%.[:ǐ[]+ QQZS0/9۝iLUd*etbemon-1.3.6/.git/objects/35/0000755000000000000000000000000014173221067012564 5ustar etbemon-1.3.6/.git/objects/35/71c421e7d9fa8f8f3d66440db5016bc6cff7220000444000000000000000000000141614173221067020006 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3'}gWuO=%RlrNfj^I1ó k_>v 1ٻ&_HIMLcxij_PewrENB'3U[|{mG=D6(+vcM@\[*Tn z#7?sלĵ!zWcހZD3PV7'?91 ғ[h->|r޻D઀P?׮M44&3\[+LJ+nA(*(a`pޖlҏVmr1(.3cڿeK'<}rbk{**ewa!O SƾךW1BTd3Kv'sZ,d-+2<Ytetbemon-1.3.6/.git/objects/35/9c7b4a306283fc19a62ed1e0422d51da88fdd80000444000000000000000000000164013767550465020014 0ustar x}U[s:ٿbq3sS8/4 B3ma^t[5Ȓ巳+z3I^v#Ms~\o+EPjڙ{>aVUf 8TU;ͷ)jcB}b!I2e49~ JCLOp$h3@LhZ̠J4Pj;xI-,K?g:6ٻ34x릶S5-fƂ15"5$؂ʒ* . 9!%ږ.XF%,˫O,ձ邃XGf2f1}ؾ09\[7yy3ϣ#atXgs# a<Ø;(@^\ːn#6 \!iDCど|Z?DX$G7qeIJԅE"= 5 +XBjÔ8詫 !tt#qk_jx[GY0t|Rַp5 u/G998 HdIIV&SLqI[)B*7 c꡿뗐1a4.w1wFR]:ȕע8S q"`}٣8f؍6^Rӽ'ef#مM+"jWIDztt &@)<⢣>|(:!_ZɇO0kgDmnNr 7}G}8Cԫ֩7X_ <ct'uF}MHIC$trzM} Ҋ]FäԻcuF RGG8`.m *$MYOIJetbemon-1.3.6/.git/objects/35/c9bb9a2364c458cb453b17d8484600bf0b8ad60000444000000000000000000000036613212012037017704 0ustar xJ1E]+j4ydQTH{qM.-)VPf"@:.trK^Aq2(+ 2Z cQ-'-CK;n[.H)`n}BOi wOS{ZHmm-\ 9یʺ%g_%T ΥCH8O ;`{%.Pj6ʺ,)W[s<>܌O!  ;petbemon-1.3.6/.git/objects/35/ca5030719519192ccb7f2556293100f42435cd0000444000000000000000000000254513604573611017332 0ustar xWo9+;~dNP*VՕ(:* P{c{wJ )ko޼OgѫW{(*fiRgH2V}j=*'봰d /߃Hj4Ū-&MUnFƒ;oRDBGY:Vpi& b%67/:''?LN>c^vAmmم'Uº [P^fR3 DzbIƇiJ+Ry,.!A&/s$ ܤ@=ҐV8}$w$m .GcFZ]5sJf;Ƒ szKVaSjIdF<q3o!Ŧ, q4n̢P14y b]*2 %L_(G=" 9Gc'9SWEz 'pv=,#VܔlM#p0 6Y 0_X#h&@qgIqQ$Q+i` AbWZii2,ǗZ՚:\^j_@c-M\](QR bGV޺oz-"Uȼ}NmWס\}C@\8r!D2~{"KRI}?˜KJf]@K^zohP-^ 5XFt@t%TDx:L#Š)ʙ$D ,1y5Ϣl=Tr"m40:iX,4m7.T[#Pگ Q^śV}qZ,etbemon-1.3.6/.git/objects/36/0000755000000000000000000000000013604546650012573 5ustar etbemon-1.3.6/.git/objects/36/6ddc2b6dde70bfb0e6ed5b9868babcecbefa7a0000444000000000000000000000120713604546650020744 0ustar x+)JMU07d040031Qs fi^5W~R:VO'hrej"\m_^yuYL4k$59 ;W$\|O#"{0W\0G#d{duk87G2.'3/a`jĮsʯ]j dCVlN{v,JX䋦(!!^7*6F=}TaURkT>o^g!sTe@*jmwLP[WӥK*a4<%cW,-v|͚[='Ԯe2 7nZSX0Ӻh9$S%#]_,(etbemon-1.3.6/.git/objects/36/fb8e317315137258cc2c0bc850b0e35a8520830000444000000000000000000002425013325231224017454 0ustar x}ksH~_Q!{CGuZmZWw"6V IpP2{?tc{Nf>,=GUV>N* ;OQ>fF5^/?^Y7|a0楹o#3qVÍqf8f.f&L8"/_ߟI4]DY#<͘d{F yretj&U0\$cSo_SS ~c1 4=d~pjÛOyߞߤrwg]89rFfy4:zaB\yOlHp<1/Mܤ0ފ/i!puoiR F|R< ->5C~,}e; h]}|&kdt`M_.<™Lc T|E23us "Fae]dy ']3g{zr?Qm+\~v NyX\Yd8IYUXwП :kΙyDa:)3(M$bxmX)ll~jxij8Gba_"Vס0 {Zd>CJOhc0i<0G~0Ahx?gűy;M}iݮL+1\yip J= (a*5kv[< F Q (hbn4(ժvpe0̩˕X(_&cwC@.[~{+]L|P<3Bo=nn>=9fQ +D%QF 7dm9"pyg.tVpCyh^ bqj -g0]Unl-"ZmB:waGFX[.Ѐb̧ӧ^F%< Q ~>%3Q-a侪DdK(1f:!ɈUZo4VNt-"an 8S|,SտdA̜D1)\NX\RG<(,0Э%o)c62w Ř0Jދ˔QRMY˨z \_f8fmL?}CQX>#^Mg[an]4eÒDviy2P4mY5}z<wTHt4Ye%,nXykNK&()f -NΌF  i2otẏ20 +ƣeVː9HCM9<0i3OeB!KÕh\|OxZ'^E uAQS ^b LBe]gs' ;ݿ.)gV9i|RAK,a"!LEF) e^q.IJc¢qc钡3J*aӯ7z\+6.Y-vbc;q3U,.ĠiP?9_Yo8V#;!釥/z+@^KÄ7{e\{:K ^vae@]h}2]té7Y{f!71Q߹ r9)_lw7 k {cVq 2|sN?As S X˜^\FZ.z(skQPRN(Ua/Ǻs,/g8U`54"—a_C5/*TubBꆷìdhWؐy`ffK~ o/()Z"F?hUݪ(uucp_5JԃqM /%Po8]+.m3m8Tp(č]ij剼d|aLLwI i3Fg Ow,sJ|8R%u4_N%]3H?l'fq%`"h o1+6. %n@4noF/ |kTBO%i옠oXڬZhw` _7FJx h F@!, u`J@uwqh_~W^dMii \PJ:|p䄈 r`*"1n>&f*mКB`~ 錩Vh5ю vAQ zJCJas+7xB1tE|D˦aMeu]N0y 1<[cV6qoz}ߙI2h)R8#:Ni4͊ڜ+=&;5`ZPU ⳸)@J(0m-*k{˕RQrd#O"9jڽiV~K<f|xfǓ+adz&)I<#ΪmvF# &H[d"A=?f oՌN}p[E͠VYƍ9et/0m>6U>7Se؂BG)X`IK 9eRƂaFPސ,#(!Oֹ5 +pVd$\%(޲dkUS,[o#@%ybB:>Z`0-wW,&1} .Yx!#&@ů"D'8ɴoDy-U(lFWk#p$Md_[`BnY2ZxШJ>驫2VRq<+2bzBHA!J6S|N^K(e&`O<>^hONM`q_;83T*O7THFzwq/éWX%O M>ȃ\b25?Ai4NEE hI|l)-ݎyW2SZEVk8ݥ/ <{.`5]P ׬c jL_k՛5PER̆ꢞGk2߮i+\_Q'90C; ^'/WK@h:s>iY*)BMs;VGܤkj"YmCă5CO] 7CE 9 xҫZȟ_C*@x~\SVjΆM1z_Ъ{)'ϳPP|>o9MN-2Ic 빹Em*^ţs{r'ڊ<QoO ;I7*IcմcD>3"^ 5Y17Ú][Nro)?ɍ$FxL.2)'c/炙 a3[JE&wc޾B L9Bmo24'/t"l韜_*wHD VZOZhi&鼎~jB/cԟ3PfY=9WO/}8Kt*|rCt퍧4j9 4Tg6k @剧I>kA؂)=7{ίi?9(l8<le'3\Zm,*u2LW@16g;ߒ^OqѢZ2]:2Zaf'dž=HRaa{ +~9N0HJ75jSӊ6AV,]yל<}^0U<]F_kϪ[MQw㘾jtž̧B\ו̸kQqb >c@MfЍ[4`VFQz\‘T7zؔ̚n_][!y/"Z vyII ˧v-HePƪ͝8]I>ĦWVo^ŀb1[YP\Te*Bj~7Lƙmk15X0|=F VTSКzW3`{&6HnJ:=VYwۨT*n?-dOjc}P=1d%i|܏(ϿZ t ɐ-^h\^+@@?`/T𝻶&3> d;S ~_a~l[ muWkwՒ"X;r !"*pkKZhfBԯ&>ЅBw¦Vo{(ü˼t6hZK~P#ӮͶK*67;Z;݁t~ZY:+ D\ЖN썀a imΒ m~ U۵':0vG[عR>k#µn٤c/;Cb.wqcs+I :ѾyeKEDUn[#v3͗+r?nkm-zе]0 Z*sn! !̈"՟>17o+h~ʭ#%-us:ee~[Ћ|͠E!OyAP=&F~b d k+.]=͝d|?% ]/o%j]ܜ~ S[p-PX'^K=`OE`<®n]BR┴ħ?oJtNw_؃PQᲑq~x쑪`[!l fۋ.f)`ZOQ"ob`&a玃5*sj4:]!,rmtվ gAQ}E h aaܛ,F+T놡w3f1=ij~ PJWҿ)v` -< ){[1b=<6!ij깯Na3e[uUsšPOV)7[ qGI^/)ߦjQ lH5X5D>/TaZr9#iشЅ$`!0pgB)^A38Fq3AyFV1ٔ -A~CEXt!UNskqPu3'o~#ûVZM`YEފ6];,ִ\$abQ}̅S8r*v ~1b> t0Q{rz-$U nV[r1; c[kx2ArSPd@]{6 $U%!U7EѱxY.}ԼS2]0Ǟk AZh{zř/pܾQ?Ge:_5\Cq. V`uay<;4=*U_ YiR͎Dɗ£_']v4]7 N-<ڳڭV> O{+N ؝P}/|F2n=EūݯI3.z^㾄qJɭBwɓgԾAPre@[M1edK}?-ƞl'k :HqQ$SD,[AѶC4u+9)N@;R[8FcYL HZAѭwk?N:MTrXY0XOS!+dsÖR0A c ᶨo{~ss!nI?RI$u~[ UVvP8STLBz|l+fwr!|IЕ$ʓݬoD߈M2s l}n=\izCֆήN[hR^ Ş_>$P[60!)YpGMe:+lpxc{F6—D]ʱ0iVհFj:wXJ6oFBN u'TH(h>Є]e-bdUEi#Gnؼ/G,VOy 1#i-$\N]k7 *_p2ܻK؀=A?&7Ifej3j_!1į8EKFyܝt,LcpxYUŧLdZ ևH6NVj!=߲ QїͦY-ӃwB HMNJ,~]| D5Ougv״"&R"FH9D=׫A[0^kٶ#K53*]$'[c2XgSj'rzh|ZMSPPJ,}WGO= g #"ZPENG.]5gUX 6Pƈz\: ֙:gd Ym+vԔ7gm;H$ T:ڙ>W ޸[,{c lz!#0t[(i#\r Ezm؈ -V*༲͠{O8,Sؾek@|kNIAW@+$~ăb2HN'%@52"]CLptAzöfk"df3ӄ̒u0o6^ I9&{+g"oq+#KzB< mF+] .ԝ⏶1 G"{TBuc6i .cy88j6Ȥr A!YGh#ss˔'m_|_h&Gԩ}gVƢ;0(0PO. *; DH(=!vRŵfetRGR~`4Jsh 9 7LUCI)DjIȟ>10a~*Sm^ MS,h}23ޢ*bHWk)ΙeB2Gj| P#.hטRz$O>똥vىt[my?|_\K:@ Q{.JI)cףG:Jj0薎+o TYuUetbemon-1.3.6/.git/objects/37/51d3a9146a0c74c727509e703a751395b292250000444000000000000000000000025713767544676017306 0ustar xAj1 E)Kc6R LJqx)A}[@.͡ )ؘz_6G^2B8󔡏 >RI)_]U5R %#f#}t]teGs,; Fh9+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d`|z3שܩ5jϜS 5yBds2SJm0] )5*DEJjRfbc)ψk]wKdj{oMb>Ȧ$3̽&Afwlg~<{ҰYNry⋄A4eussaq~u>wu`~V-:֖0E% [Y'./1Cǡئpy%E9 Nz/\Uƨ`)Vʢ˄,Ҩ7A (7?O/%5-4bEΛ3]Ya_~̢b閍1$uj"\m_^yuYL4k$59 ;W$\|O#"{3ee00ao/5V?wpĜ+/dŕ1̼b%[De*vr-̼=^޿1q>?27ī1fQTƈ@VU 6JJUQ`@P͋l9d hV^ jvT> P& `hy_{M/\+e,4T?|p~Vt F@Syt-y:C@Rauў;sIwK\GP:etbemon-1.3.6/.git/objects/38/6e4135b696a8c98b533e7aebe59835a2257a490000444000000000000000000000026613212010630017573 0ustar xAj0E)fIcKPJ!7 1"#dZ*\}.G+|~R/@D~tpBWn盫qUwh+7Q~Rcetbemon-1.3.6/.git/objects/38/af3159d49987e083d4c91f8229b924402b06080000444000000000000000000002464213455624272017377 0ustar x}rHȐ=!JqX\eXDz#6V HP21%U%Ds%I:0nDtnNZr ,I4~Ex9ӟ\7434ˢa(I2ɗY42)EߗQG ,h$]$i8 o',<\9}-L##$:Z/e^INca2l2]<1"i,LCc;ɏ?"ūF!-ǒk2˨(0͢yQ.im86|d>>|]+pW'd ,1m GQpha+%횱8BK`MK?7-Z|4޿uy2P9AR~ݙ"/kf;0$@"ntqH%QC2D*yL #5ƌ /wSwKwe~ԽljK>+]x֞dSwRu*w*p &;%af G\Ola#y)bh$!\!+R duHƖΨ{Jثt>N!N2 ys'G|5~ϖS*Iq}iݮl 1^SyI`Hf#8TPNB(2P]1Ue*XQ H("n(Éd]vÂLK>٩ǂ8Ztyjeo~KaiQ,HOfF>POM𡉲 LAJAcFiSeB a$sXBjc֜f_ʼ gMQT=,<F}āyCSpP\2c>)cxT/gYgbYp*<Aq)&\x)BXjC+Xo4VN,"!n48Or2SK$< w3ؤ8 46X*@`/!A"}tK{1pw*BI-Qxlya%el2WR/S12N&6s_Rr:VDN \P^aa c٣Y DRӸr<|6(*G¦`(ch*ZS1:! ȭ&JEUo qAYu|f@T槲drr) # clZBSЖ|~w%\?ЉWB# t K|eZfGu7Bv_ g1w1s W!!wY,!B!LF eQQ.Ečk W,T@*sѫ8;9*  ~c?q찑%fbqi=ăVࣵ_1p9~\%- V |6S8 hyUp-q\h9NX` k&x|J_ z!Xua" |v!]nE4MiD` яEWHـ<|:1U8ŅozQx.a^z#8K(hP;XQivlKyPJ?K!n"EPk Ls{6_|v7DwKU+Kq Ou,` kJb8Q3yZUlITnÌɀ~bk$`"bR8M݂([0Mg |Z.TƎ VpOu!x 6YK bAeW75`@z@8KĢxru@uqh^W؞FCOqa) >Vm>UУ/`|Jbi+"?b_C,Pb[A<;. .#׹t )T,(- ^M:"?"eMǙ!򜬟kUf٧hk:mS~7|dFDZJpN=|вGTg-͊Z+T-6;5`ZPe 4S>ăr;l ![#zEiXZcZ+c\QʐG<dnLԃF[K<2=D-a/ϖyv@x2Bg™ϣB9cyuNёڲrb"hqoFPZv[#¬@{RJBvZ\6F29Y@6q8`f֧a2S0}Akl,⾌;zݧۇUjO!m0˳c&\|˳Z2}W$#(​0Ss06g~ 'H3"#BXF} xM!92#Ϩm83xComooհz`H?"/O#m3y/a{f`]f>㘠tq/t2WkB#4:Xݮ~NomrHc(+аQ⎆WvCaݮyW2Ct˧wj[^dt40a)'wB&7/aZaVn~8扒]*%B9NvT"&Bm6XyfBÑѽhp&^l_/;fSl q^2V$S֒X?ivòt7ꖒ D| ?bRHe>.K l)`qWxQT.sq8 ;+@V|`ȈB!BK\a;vh8.$p!鴹3n6½o}i|6HQ"-;I5\hO1#&vldH|؝M DFgżtUn._ 6 ;6oԽGqfs,[d}:9ll8xUv)dYr&| "^pXɷoP50'%@"RfnE0gTN0dS.j B?9'V$Fe{ wϟUўt^B[W Q-7O-fߜHz j;bi5lW:jK-b ʏưshp~}_$F&+>v `-/NF*|tTi) vW8 WǂCkRbSZ2#di,AYz21>rz(&>T˦3s= JwĬ~m\6 672\ F-,V&( WfN1x <ęc{VKaW3ﴦWC68CT"%~l`4Xv,x$q?#`@,s[,B4LnPChSGJhNF@װp^uʼ,- eO~ Yۍ':0j۰T)>5ɩ1-7!6AX|ZPh߼z_9Tcrr^~|O8$=j.wm ȹ  6\W?Av p)y<}źC\g1!N "xu BHSO{߬EtLw|J,6@ -a.{c:L lAF@KU=>Qu|Fk!#¶Kq}! yj&3/ h)0l0ϏqTJV(AjY4wZfGG.kOo)o/|$^ASnnv. &teV9Yy;?#45w߬/(^e~Cmv] |ѥ\;d+*'0Z\ ,hU2F+@D'W5dh57S`Ѭ:I1NdOꭠh[x#zq4a}DR?i?_{ h,gtρt n[&D y^wei?WQBf[!Ggt1<(W.7l\׻B*Ine ;9(;2r@C@sbu"a֑]a' Nz-B.Ӎ@ 0iVFl*78JPB+;lqq*&e+wԫX0?\$'|ehufח!a(ڳ+kJ W\ DwѠc;S]Pcj*?_L~ ] "g0S5@mT`"4Qw+-@d1su f"VO9d$R&@p*k״Nd` y!!|zd\rcYrYۇnq;9AJO%>Rw𓻙fu&Cm4[߫c[@CicrZ ֝4yBAdoae(yHl=AOU[&_݁C <|JV'ʬLØmxyYK~Ϳd ሥl`-]pTa 3[Aಗ`(i PUT߀}e GZId]VeCٱ .x.V(#X^GzӔ{4%^+Xz7v2+\e:3ubRZٞ66*j5[3)=No%YfϪvr+[m 7F;{lFy,7O/?|O|ȼ9(׬]>B#)ÎM/; 3p WAlVX猖S"&MiltDznc)$xaC9Jp˲kOJ(@ݔTV؜2I#Zo~DhV"l "kZEl;=m?=zrO)SՓpjf!WUnFR,{|Stmř 3M7;(h )!Ӯ{p]]iEB5Ye {ՐHo(\ m2O?\M"m$:idaR@(QTv=.Ktm$P2N4UMyJ;PCKc->νwu]ЫiPwz<ԏ^$^ietE٤|Z;^ބ%'[ki{3r/Ry1t}}Lt9e1坺+ Wn_$Tnj5^IݥhlKfij*wh^V%di5SJ I(qml%rH|JDT~u#]vA=q/|,ĎQ2Vd7' *xY[5-QH B>XLF҄vk;IO)~D ~\=dswtf+"WCך ˬKFj{(8/Ph#D7AE*^vQ=y,,,X or_`=Qw?)sv/*ܟAx=PQ)g@ M~,5M4ϣ̄ }4-(^t^,&FyAӺq2`1fi#/>l>ȑǍ{7<g\["|52yM-eg A&&3_N;=zyX!I{stxy2)Xt,!>@,2ύ9;ds?, =Q$ҳ Uȡ nq~;t< 4R=M&MiI5/#7j}f u2S"F Rka3B{``Z\8S\:tʋqtа=<fGf5 >Tc׻8>D^o#lEZRB -4xRH[ؓ=w"830 ^?C#M1wuz h%glY0m͔Lt؞u¾ 0lȇ04JLy _Rڒ>%44);?! :[2sh|leȥY2eNBPU-DA1qܸ4z= P:w%㻫K"NW!\5VaN˂g~N-Q"-dkiIC#,`T8[!'nKOW`8Օa1́ s=_hh|DI㰔봥-=T~<_73.4w[-|@2cx N OO~[ V+9gfYz~~ w%=h#nFh)晹c\fl ,%KBڝSQ՚upAJɧ #WF̙(4 (WZ*]cI2㳓7q_8oOC1+2 5E`}ZƲA)N:;t&cf‘u"!|cȘ34@[[r`\!-wɉta23Y,=*h:>W]5+&Вޱ*Ճ,[Vd8.Pو?OѾl-,Ap$ո#ZMԶ"kFx T\iELV[sYd fv<(`##c;wKEN\ g-lA;Hi,7 h#;`M+b>f:jԻG2eRZY>mo %c(u[_k?H(4D=F=e4$}%j_VJ GH+5p~%45&#nᬕi\@Aj_88j$q 4'g3L.PCڱVS?lZ0+ 1u%98 ke.W?{4+A)sz]|`nhm 0MD"%ye ]s;xhZ8>U$v]J/ؠң9CJg}?ڜD%OXP-DJBޓrF}ndSFK tu]U9lۀf8 ,iZ"B|X eµnx 5l#_씽ȇ8~y|pj9 rIH чve0ZGHD2uRpE^FyAY;lra@敁=%ZQdf*]Mkyn))8ƈpYRYs7w"ua/|LŸa$Vsr~q}v,Wq픭Sc ~K.TY_ !2`9W9돤J"~yj=g5(*:MP?VA-*1L$k!⸌ݘT& qnf'ϥz:eFʨđUm-VF p%h<buISA#~YA}N+*ֳ/kҕAM7`NbTluډB2e*JoS;*l0A{adĠEwU <"V-~;PiT/,q/[OI&;;,;ip h9wvO8TC"RT&˅v!Z\I|\:YN6Zdُn'$(1x>?ͣetbemon-1.3.6/.git/objects/3b/0000755000000000000000000000000013767513464012656 5ustar etbemon-1.3.6/.git/objects/3b/0b276c6403353e8cc2b3a61c60d827f80675b30000444000000000000000000000006313247732002017536 0ustar x+)JMU06a040031QH/M,aTWOvqs#CBetbemon-1.3.6/.git/objects/3b/3f28c5e3b546e4c86ac13767cf8f1c886f563b0000444000000000000000000000141513325231224020015 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTPv.hMvZh)TIIjnANbI*Cպz SD2dpμ 2_dW^6\ZnND69'35ܵ/Pj;]˯BT&e&1pϯRVKvMMFvR˶8VV: &՞;ݟqX> HIlK$Uc}NGdd~0$6Zfgy0Zb,Ƿ?,I^O|g&-4n$5ybu\|nxbVA&ʏ3:btY7Oa˝<4 򁋅σxf5 ̧uur+^חc6N`1u|bus~}}^ӟ*ny}\&0u0X(yAn 0o?^w &l4')F've ٺc 0 4 lbc*LEfyY|epr"X.x4fp[B#,";ضȥ=?2?0q Li^^81^$iNjۃdylKh ZݻCGvķ*AZ&'adjNYz:S|%)&14^/% :!d+i6|maޠ4{4&A:"vx` 'nص!ZL"8O2_e7fސ<#jFa~9G5G fĄ_]BX@>$r D gY8^Q~ ssknFZ[]v$37$8U507skƿ!.̐B<葾3CԶd-k &9\#U@U)A5z:hr(2=/mm-U ^*JNa> \_CcÓg:l.j)81S lXʿ!~§p˓4"h7'm!BuЪ ߡod[I$*<*Cè I*M+\A{@4U.-Zs9gJA:GP0Kb8fK`˕Ƹ,P(@6CB,4h- FjahxZ$.1Vl̓<)g/~0~dͼr??^S>@%kՑw#ˣ5[ԑW(dyH+SFD7%D\pA:. k Q÷s.4.ad.5vW}+] Y1MN qUn8ch JNP!<*匙5Sm\O+%(LPαV8GwPvnX[fMM) %Sh(εD G0 </6ԑsSpT@{7 kpwn 8FhCS4[m(eds0vq K5o[)k-AxY "اC%~%.S䠂@Py(%Ze?ơzH]1vzjfdKmLTСeu "EK D^]0aɑ8aBӸez:| oR$sb~lGrD7,Qd;Yv+" < TE|"TbUHZ'c.ƣeV|0HCM9pBǦό? m(.wCђ$8|0\sd?FT`Nʻc: u`D`~G,]%b >&,̔dVgt9 f(+҄^h3!kxK0[bڼ7[p$ 4oN& %rd5;$Q-}2Z{ fIH9!^yH!:KqhnbށO%0EkfsYVafQY>V|o[.`@ k {cVqz;z 9 ~zs/b?B숑BazAdhkPhvbL5jQtXRN(26 p_uX@#8`&~5:\# s9:T9T gd1A5gJ f8Bc%_!#iD < |YHpbfh| I¬BIgJ.Ax)*g5Z$17!<ZeN+LZi0JOw (Z/r+Px&h +^U5{wzL.(1$[W&VMbօ{"<۳[joXCL^rz³=zZbKk:`D6xͣ/~i1^ނR@(hB6Y œ[D#&P-pug ؞Ԓ}<>m 6sҚrb+3~0)YE&_@n R m  L('YJ J^L 5 !*B>߱2,+Ky YĽcj|81TF-EtxT$L'h%Ku$Mބ$ B^zWE7dȘᑱ;j # FSSZFceJ5B**ʿ(oasv \y(t%ՁZKQ6Nh`<0sɕ02| ǵ͔jSA䈳K[(te곶ɆC2PGɟZIvx!ь }Kn]{7qӽo6m>RR?KZZdn_[-Ŋ'`* #3ed76(ɕaðH[Z>8~&Ep(=dO)V5E%ȢZCUdT[wVh%,*I`M^P-D8b`Dy^PnŘd"Ԭk (I[`BL:e2YxШJ.p =u `%z_n=Z WP~cm{6h׵_C%ǶL<6`-XTSz<)M YX< `*|^pT:Ju˽ 6 vV۔Ԁ,8(1QȼXF /5$Eb|;Y]i4uKۧIH7bHȳ]t:z~k,īa<~ 1EV_6D+y/%a{n]~b-^*G9Tw݊*8Uc_UM+}d[ADSd8qnaN~)B$N7ӗ&X sHB"gl}jPUwFQ;˞0IR0vˋzOdB+¿]ң;~hTwI[f,#L1V@rcrml۶)A>+=5C_ݮأ"V6+9 xҋϵ~ ] NJRmmYsL톧i r yl"[NS~%˺$4P5jTWm4Ƀ 0{w=ZyEC❐&choP1v?^4yw~BF>J&f=3Pch0;3]-/-guh]\. 3WBQAZUE51=,MAkBnJ"A{bA#6LVB:QM;A@_>3d$V]VČn~cxM@̡KHѫk400In,C:IbDs;'T_ LɉzԾ_v=&B76m_/\Q$b@zjȏX66v^2e[% ?BqMˈ҄ is)Y"<&p+}`\^Jr ۱Csqd"ę>ys -z:NĻu-o]Q 8I=6 _|Yp3KXٰ 3ovg"@ ,!tv ׅ a8 fq㓗K5wb(\Y^1hx.{3D&Hc [䂮Ëb`KBL`M e{ɱBoBjH&\$uLωgPɖJklC'& /]b gwl~c x _.)JG.^ٓlق ONx^FbL` P蚴ql@I)g`|&!@B)|MźnJw%~\6]Rlqx FZi 2'fѱEQ1rif(|ÝK ,Mdb.%uN!ǂ)I'BUB3v'u<RPC9fy=J`cpT"!~dl4v,x"s?ޗ#~`@,FZ.,x#S[KF䒁ᢺhD%szwηwx[tV _SE}Kɮ YimqȠ%?YKxAiș_E1dx&C%m ~ݳYW?'Tx[*[n$TT`eJ-b'6 Z*ͨ=*f( ϸl{m۾?$ Ch0zX^Yj$>ܢ-۝ݹq`/W>۾XpVb.^/*OVy,f)W`Є:;]x-&uG%n9]x7-Q#T xIC4XFDՙ!6'(Z;*ڧ Wu\ZNj[!TnfxCa1G# 6g%a)FE <%:rA]lmGm(㖒z߯5</#R>Y@J7OFvfǙaG5$k1Oڭnݩyi(Os9 KCmV}r Kl1h_B6db'1v]%H(~(cWq (`Ԙ[Fxp.^(m)㵮\&A)ؼGU ڸUTwG6ᶚ.58pzi>*u2XW@nGAQ!-O -ӵ#c<f q[a=PۓĿoj7;K/*a* wW5jSӒ6{~V,]y׼yݛsDv6̎NQ#<*j4-QwwT5:a]S!PKKQzJf\@z-rXVUHMЍ+4`VFQg5mp.T+6)‘ImNeydvNb6ݚ@ezLz Ȱ]DމDR{RtnHePƪjY.^53[ݽ8bt%k5Mu@B6KU$v-q8%O6bK"8a7r(šgԻBXh3ArSYyFAU,Vq m)8? {_`xJ',%-xi/~Dyv9JtT(HlAҥ6+_+簗[JcF];C QEY; AaaAᵍ$%EvcD T*KZhvB4(&>Ѕo $}Q+y nj$.٠i?:l[b3)hvUs "(hrB["8+v>Vs$goڇ>enʒ2@II'zU䓪r*;W r-Ta:9i epRY] X BL |'gNQLP^ MR!ga [!2S&oޟy|0Y٫h Z O>spin!Hv>UVvqseI~dxl2`m``AV(^BΖ*Gn+AJG'YPZ!WEŀyb;ཾQ`uq蜦4`),: t$һki\I-kr\*k?c;Eo(DˍBc 魂mglWo]^8Fٕ-A 7K<~Zr*ύ`yz7o?ʽܵT}(׼n?/8i@d~-zrpw*,Y+ȖQSB4t+Dp'NN#i$xi?jkLPT`T)wؚZ +Džw= u?s!g%rĐXՖ-%MNI1{Jӭ~ثeD6:"!cᙒ_|2sClGHY̮71G6''Js.ᮜ3BgEy>=>qr0Ҿ5U3v?e<04ϴ nՆ1 [daqHy_gֳ~~9xowu[?fLFxdӂ SNѳ6 !8f-* -DvZ](Yk*-DRIK; x, @q81薓6.@cc/ĎԡX=g߻X`ܼܤ~rfxJ_塄B %EB H "Qi[&6mˑ,KS黂Ag8!Nh8Eݥil4B g<ɬ?qZmf} $:2MkZQEw'K,~s^VdiOu7 Ub>$A pZmW[͉o#4.rdտSwLr  9ؑ01\LE}Y2/' *t~TRBRY-+a 鵖m;I6w~D y\=+/w_QTCR=2VS?!yM%mԡ3n"[PInG>!V5g~c l@Jz.vLF32ޛU %oï;j67PjQF*hhwAqywY"9n)!q*DnVv+Nic^?*^xg %a~ l{/T~-+U.vsf$UB!>A%wov|oQ+p+ܘ1V!\܏Q-2){3Her҅{&N[`%J5&ynj)YU\*"/ټ 7{.FVi3FǼb\<&yx؂nr kf1Q"*wl{%b7(ƋbOp%sЋup]q՜@9R[@qQ_!d+KmZdSFY betbemon-1.3.6/.git/objects/3c/2ee7f867243a82c5904f3122fc241cf78f0e3c0000444000000000000000000000334013304475530017721 0ustar xWmo6gbLitMPHkg(2%A4{HrC|) #/~6m7޾vE:{J UIH.b|IZvJTt.tR)LZʒ-&ߜQGe ״TQR1 oe3mZیLT*.iK[dae- cG`nҫef]cs,TM''WYeuY0חNX7ET4 czFI;u`b[̚/ ZwO23ҡ@l'`L4#plIms3p*<|y6byDepL$XT:c"1[E=~!{3}$ _9,y ;| BXWDxs[OWrhT>T %]8_$iz/ON4{|T5)磣)w_V9u)K7#T_[~~^ˇhAШ ikMp V]hd#YTVV^ O>DktgTP9Л177c0L^jp-y7QN}/=˴%{{t[޲cPvE~PYtɎj_1;_5Vx6Яlo{1LBf]^Y眡?&etbemon-1.3.6/.git/objects/3c/e207631c7661eba9f42c3345300ed244fbf00f0000444000000000000000000000141513775160233017677 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3B(GaVvqlrNfj^I1ó k_>v 1ٻ&_HIMLc8~zoU!3K9 ?3nSXv8!%@YelrRbwdy $ 9r,Ԋ 9ɉ9q28-/qߚkb矹WO}Dz]_ryVm+8dqke: z>U)r:`|>@% .3rVܵMB.%pvLl鄧oCNlq^v`/TEe10>R: ., dZ>wu`~V-:֖0E% [Y'./1Cǡئpy%E9 Nz/\Uƨ`)Vʢ˄,Ҩ7ARKfu|vɁO=MO 5"7?O/%5-4!ӊ\M4й&D ̢b閍1$ujR)7I]f^f^ ñ Qi 2]c{ ס*.Ia0a L~B\\yqH#).fX5X,AZ6蜭k*")*/.+.a#ݱ]<[s:M]Q.CxC ٍoEUl{x dUE`êTU}޼ϖCʀfU{nKK5D 0$gC…_շ=k}iZy/cy1榦 E͗H=[1'nۦsmi6߶Λg_>r% 3aOB=u[*=57o^etbemon-1.3.6/.git/objects/3d/473343d6eb185c9593a310552d50a867a94a640000444000000000000000000000067314174476517017443 0ustar x+)JMU057d040031QMNMIe8;?nN|:/wrq7jMMJҊr2KĿ2sIt#A KII-IMM,(HMK.(`uy&؟jRtW8t&0j=R-77- T= ZEK|{3 tKRs J[3-Pw̲2fӝ UWZz*nM|"zGx̴SX78몣sbm6 V?3c>|*-@a>Dօ82ӎm8ȿޔ{n֥Ô&$զj2s:]4Qwo槕%f#AO債ySTU}x5 )MON9]iE,Qpetbemon-1.3.6/.git/objects/3d/7e7921cf786d631fb1df7b711d8fe050f8c79b0000444000000000000000000000120513642215544020103 0ustar x+)JMU07d040031Qs fi^5W~AE-@V\̐joʫhrgY#IH-I-f`Ѿ")p{Rܛ.3$1ݳx%*fmcRw68̼b%[De*vr-y .A'?x,_'+eoW}ac>͢o(lX*"ϛ?rUЬʽZxti7}@E榦 E`85{mYbgN1\͚[='Ԯe2 7nZSX0Ӻh9$S%#]E+etbemon-1.3.6/.git/objects/3e/0000755000000000000000000000000013767516617012664 5ustar etbemon-1.3.6/.git/objects/3e/1c7b30caa60ddc16c9ccc38c044f8075dd20ea0000444000000000000000000000141513455624272020256 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d~mmL?2< lrNfj^I1ó k_>v 1ٻ&_HIMLcD*^"KṴ~Z/zž2(byljI2G3vYl~#Fn~-y-{g̮~f[k5D3PV7'?91+Nx("mފ>~?<᪀l5D.K]wco¡4F 5_+v.vlg'@% .3rVܵMB.%psLl鄧oCNlq^v`/TEe10>R: ., dZ+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d~mmL?2< lrNfj^I1ó k_>v 1ٻ&_HIMLcoǺx/‚v;nUPWmro}_)W,;}Ԓd<,mOC0uW6ˉy\\.;_|=fnN~rb0,.̾my9ӯU.kX] Ǻ7.Ch^qAj2/ρW,w\^5NNP3J+ J\f,g4ۭk\!*K /q O8⼀Z^b`|05tz]XȔyL%9 ÿ=!ɜ$Y gdZ etbemon-1.3.6/.git/objects/3e/6c6138934c34157393749fe3154e3a409f4bda0000444000000000000000000000027613212013055017502 0ustar xQj0 DS述X-'BoО@$67ޠfmKVU!a@Ǒ' ɍAЏ10ql W7) & [#謒7=Wxǡ oK+\/ @3 Εlo>z)68ʒ]<~#Wetbemon-1.3.6/.git/objects/3e/87575bcff90e5846fac04a9e3ecc80ee85afa00000444000000000000000000000162613767516617020341 0ustar x}T]s63ŖL6䥶NDq=cYKxh8!{KqSH''?w}T2 ]0V牝3aΞ^tGHnQx>y")* 7wϠ4!$8"K%sKg&*J”-X U]e'=RUalEJȤo\NV{U!%6@"7*#;bj$Vʒ+t0Θ" j\ BPb^_^\-.]|lI@NMSQ{p Kw*&u,ظaሕNsAsʳ9GٟsʏcC" v S/hF9v:j /r >vx0 Il":6 9\OѰ[Ks9"|q\]Fߊ7ǔoi^x/I5ﯱZ.^Ex[IeخRk \r:\&;#5OS|ʂQ L~Bg(j"[5Scc`-wPӯKg&~듙W<")DLw|Pw{0_)og&&ŧSFA텯4nV7>mڄda\ο# Nzrc7N7Kyz|b:>y}l)@݆,I簋pХ=1jp6R^]wU] o65+stgw#ϛ?5sv~FC >"m ܻ#dkQ}D+\H{[6f֫@jY̿#@etbemon-1.3.6/.git/objects/3e/bc3112745a7d77f0aa9b8cf69043298cc97d1d0000444000000000000000000000036513455624433020020 0ustar x+)JMU04c040075UH*)J+,/bw%>ؓs \vXUX\ W̞abƋSnmr8'3B$5(s;V{ΐ_zٝ SXW(i st K!3'-tywONqng|ɣ{*O+)JLrڼnOVU[Koݹźc¦#_n޳l{etbemon-1.3.6/.git/objects/3e/d809fb491c6a444d67eb56ab1a007de7d3ed860000444000000000000000000000071413325227421020142 0ustar xTj@ĥ .bC RpMe7^*ݕS3# u@ iwvfΙIy{YQϕy=㗥pJ+Jތ9JJhSpv벚9sgl>mL)L$VtɌgJ՝]AdU[-{{ԸύAdNւ6g٩>GM$oo~>etbemon-1.3.6/.git/objects/3f/42f33e0e3087a93257652ec063d410d81832ba0000444000000000000000000000017113325227421017457 0ustar x+)JMU04`040031QMNMIez(;rf.+UTRVSZ\P`wLoR /md<@}C =靖 ~7K3etbemon-1.3.6/.git/objects/40/0000755000000000000000000000000013455620411012556 5ustar etbemon-1.3.6/.git/objects/40/51b7498799c7a2436bfad324c1acd1c93f03500000444000000000000000000000326013455620411017626 0ustar xVn7+j؅-Ž=uPq[-Xv .wEKnx^g+Yi CKrs9 /˯_~4|->K}҄ke$|:!œ*yj5kU#a-!R[U@wD-%f\LYzE*h *Zn5N)!ƪĦgXj hmpa&:隸^uWd`+ySzsw{]|GKw_^"S:'؎Cgrjlwej]`w]y`XFvWHhcͤ6%?_5Ek@ 5'$fܳq{s2lrHI޸]~s:-_`8:T\.Ifdp e=B8pj$ %'Vai\c6:F(tY Ɠie\G Z1W@TrL>[L"~!j۞I/")Yъxwq5H"j<nj~ZxwpN{BӊBʩ:VGw4r7-!փMڨjHZ ¸ 8 `"( بWpԨԿ=shc9F*hɸ!:W pfП*]Gh|YnNg8GK&xs!F-->BȜb0 z ;4*b=K(|^L'ۇ+yM_?l%f݆ tVEbt9툸`oa-_>L#>2|HZkҖݰ&0=Ș0͋D*w+L3O+ق5XoxZHq ,.2%TKboO0!8:;`KѰ@%2':)խF]bN05p 5CtLhHPQ" DjBT&)gm|2""??)?*:9v;^yS><9}RwVü&eCNQ[NBTYƒhetP^ѲӪG~q=eZr+Pr.Ui ބ &7tTZpb8;b2Jn`ΘFR kG*^i8Aߏ)&C~(FrLDЦwu$ G_y`g_'5=(lm/ x>S#TҎe۱{xx]*DolQ.#݄..*]?q~)l/R/_?z9W˚f95✕K[]={5_ͯ" |QzVetbemon-1.3.6/.git/objects/40/c5ce4fb2b46d9fbf52c3f2ea248e00cca1e9dc0000444000000000000000000000141613455620411020420 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d~mmL?2< lrNfj^I1ó k_>v 1ٻ&_HIMLc|tNA>.2Ŏ*OfXvnlb_w|9_Mh+.HMf9pb宝˫;) jFiPA ˌ,f~ wm1DEq 0%.[:ǐ[]+ UQY N/ y2ּ?)$3a^r;'D=b$k1_*Setbemon-1.3.6/.git/objects/40/e62d0469ab49192ab74d22248578d0c99af0ae0000444000000000000000000000126513212006613017631 0ustar x+)JMU073`040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35ݢ{%\\q7tW)Iy ϝu[G} btm#W M-IfX?׈˕>v)șiP1tOݟ6]۷Y qL}Q3,XQ ,d^~'XڹjڹŸfV00Xroi[Gr6 CTh1_ⲥq 9y۵%9 ÿ=!ɜ$Y ,`-etbemon-1.3.6/.git/objects/42/0000755000000000000000000000000014032515751012562 5ustar etbemon-1.3.6/.git/objects/42/3269b7002a5005ef095478b1e7e9489cbb6d430000444000000000000000000000150213212012107017462 0ustar xTQO0s~Ki=d6uMbi@ncĖ@ uH}>w&'goJ`Iˀ;$ (U.*rcJ\bf$}KZV[;H@G l#bHswn2ו$1@\\]>w1 摜t3`R%l EEVe*!)VdTIFnʪXD_@ȌE%> JX4eqCGt EEVS4巯`ݔH? w8)܃uaXLbIVй؁'I(:׍:AZr,m cmj78 ͱS70'(mmN@V pԲ4jϸ=ۘ)4ۋK`q}0qxm (r:/'Fe65R=9U~0V0Wc#z_&%O"<#aO3+)Xu ZP~[)hfm-45kUVo|s#xlJ^NzuL437 MffgScٟᰍ$iWzz]/LCt3lq6c :?3KcπG,@"6̵CMKꎣZnv:ɨ2RMm{R^6 i+00+g84~41~T/2jb*rLetbemon-1.3.6/.git/objects/42/4697fc5b16ca7c6ad864a47d59a483baff49630000444000000000000000000000141514032515751020022 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3B(GaVvqlrNfj^I1ó k_>v 1ٻ&_HIMLcXrTC.Dng*Of6>۔+_{lj PVniܹrT>"Fn~C9kC>\Ǹ#"fnN~rb0,8^<+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTPv.hMvZh)TIIjnANbI*Cպz SD2dǰ7!aMw!9y% OX;5N$syiänԤ<]n2LZ(%Zo 5B'+y5+pXljI2CMŋ?=yv7r4UJ/nxe5G@( Jg;GES9n=ulv*fɓ/hfomh+.HMf9pb宝˫;) jFiPA ˌ,f~ wm1DEq 0%.[:ǐ[]+ UQY N/ y2ּ?)$3a^r;'D=b$k1_Rretbemon-1.3.6/.git/objects/42/f9648973fa91a5500f8713a5da386b50271e500000444000000000000000000000261613212012550017413 0ustar xVsFSlN cI;d[S~zJ'j}wy}E"]-.#/nq$_B5悰erN(f 8JR5>C¥Eɹ{m:3:P՜a]mѵ^N\c9ESǚh5{46qx5tĥ=]r-8r6޴ڹ!ʙNfwlF=DX ]áe+pTԟLoҥp`aBncWhڣ ̑yshSvyt}i=ħړbҟ]:=Zd:LirLF4 DZ(HOe lh`CFei}hkۻU_/Q:ю~R=|W\LkLvsIF/Qqgo~5n毛:ڪRzWMFբZM]W֨T}w=֏EGH,DH79)Uxd>UwDvh(j`ϒM_AULTnvz 3aJMQ¼̞RZ҉qjTRq`.zOݿk=};ޟґ_}Il[ JR@D_IC/[JEک6逺^KCgũLϦQyh<LuM[QQ&iC}G"P " epοf[TBOGGw(l РRo\O[Q/Tk %HmAĀrk7ƷT4\|a0H)k5R߱=ӗ/nm}uN &~wѯF>'jY-+|sp' Retbemon-1.3.6/.git/objects/43/0000755000000000000000000000000013212006554012556 5ustar etbemon-1.3.6/.git/objects/43/3a8d1080a638996ba898ecd0de5a27a52a0c5c0000444000000000000000000000017413212006554017767 0ustar xE̽ ag0s 2ts. -U,׸w{䡍Y5qyRHkoQ\jC.ü#>{O(9u%B7$TmJh6L1&/$etbemon-1.3.6/.git/objects/44/0000755000000000000000000000000014173226261012565 5ustar etbemon-1.3.6/.git/objects/44/1bdb7400be1e7587216a987bf69ee13374e1ae0000444000000000000000000000120513651535653017730 0ustar x+)JMU07d040031Qs fi^5W~AE-@V\̐joʫhrgY#IH-I-f`Ѿ")p{Rܛ.3$1ݳx%*fmcRw68̼b%[De*vr-y .A'?x,_'+eoW}ac>͢o(lX*"ϛ?rUЬʽZxti7}@E榦 E`85{mYbgN1\͚[='Ԯe2 7nZSX0Ӻh9$S%#]R,etbemon-1.3.6/.git/objects/44/2a593c0c3730d45fe2cd6df814e7ebbea06de30000444000000000000000000000026714173226261020214 0ustar x+)JMU024f040031QMNMIeoC5%b:8&(X/#5 H/oO,aj_~UQLT{6^]l'샪-M,*I.AV~/S쳥(swl#U^Lazqi'mq4$Wetbemon-1.3.6/.git/objects/44/526fc9fb33afc1cfeb9a13a0f56f0f5ec33f600000444000000000000000000000151113604576137020276 0ustar xUo6ޫW|"q6cb+ZɳED&r!egP xw?j o_M+mJ_glP[p6R㻭V ?(Zia 6KV^;} o:j6ĬZ\w2jLLyrD@Hkz9 <e83`)hEfqI cӑ,1{p˝pec7Gk1|W.a55-ۿych U*j(ʷmI|{(kPFcp #xk^^^QHYUMO5ɻȡjҎ$3C4jD"/d ynUٿ09@/ep+;jPX /jQEj۳G4;@@d-ւ;-(lrs۷o?_"etbemon-1.3.6/.git/objects/44/9fee8993c375739f31ddd58d9b78de642c8ad60000444000000000000000000000025413212006712020043 0ustar x] 0})](I_`RmJ߈7ec惡, S- eŠј ,Fko- d1'P*TZRiqt)1 < <}y{~sK፾Q^:<#RxMW^!0q"OKetbemon-1.3.6/.git/objects/45/0000755000000000000000000000000013216420065012561 5ustar etbemon-1.3.6/.git/objects/45/3ecf25c293b6451f2f8c09e6453ccad2e171210000444000000000000000000000131013216420065017676 0ustar xT]O0s~D"hT¨ҪM*Mb5؅!w$$6iO:>>ܻݓvw8Zry.FN*Y$Z+Ybe{i2{քFBR\N#pA<Ey4< &Eoє_;<<\ 5V EPuɵ~س Y߈gF1gU>T63nyN;kzdxxфnQ"4!pB1`1Cx:'SNǤ&D)XTYpCGa1 ~J.MRi\+#%LWj[ݷJއ6-'xN)!}VRh̉ ^)Hte-A).S}X֙L znuzZ%l6-M_99ς&+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3fS7SkԞ9j*.&d3<`JmSkrUԤ<,Ytt =~zdj{oMb>Ȧ$33y^N[j[Po1t6P5~)ރ'}~~>"j./NoAh^qAj2lḵ2=_9f>Ԍ Ym9v+hA&!c`8a;K\t7!'8/`V) n ^q2e{yES(DEiIfN1üow>hOz22Ib"#Ryetbemon-1.3.6/.git/objects/47/0000755000000000000000000000000014173226261012570 5ustar etbemon-1.3.6/.git/objects/47/9c2f562ade847be610dbf6a7061ddda9b2cf0a0000444000000000000000000000141514173221067020271 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3'}gWuO=%RlrNfj^I1ó k_>v 1ٻ&_HIMLcxij_PewrENB'3U[|{mG=D6(+vcM@\[*Tn z#7?sלĵ!zWcހZD3PV7'?91  j-] > (I #}T~MNCh^qAj2lḵ2=_9f>Ԍ Ym9v+hA&!c`8a;K\t7!'8/`V) n ^q2e{yES(DEiIfN1üow>hOz22Ib"#a\Zetbemon-1.3.6/.git/objects/47/aaa3b93bab5f77974a147cb42e39ead3a5a36f0000444000000000000000000000141514173226261020213 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3E+҆J?D޷ 1D69'35ܵ/Pj;]˯BT&e&14[gp?ױPsrڝP u&'ߞurŲw}|M-ʊ--c;Wn'[$c5'qmȡǕk77`yV ONF钏^V M0dZq(_*k&1~z~sS7: p1z t>|}Rt|P3J+ J\f,g4ۭk\!*K /q O8⼀Z^b`|05tz]XȔyL%9 ÿ=!ɜ$Y WXetbemon-1.3.6/.git/objects/47/f19c2cbc9f6fab8975d6f3d5508aaebac9cabe0000444000000000000000000000235213615473470020542 0ustar xVMoFYb,˱v pRW.]V.)RA8}3fRsGoN^#J[;E.SZIj;Kͩ̎+L%SUnߎ=;vtIiAaOЫWtTpuiI@$5V"N).L"''WjW4U! c\gmtԴM Lfԯt"U2v/:lY[k( p̺ؕ[ݻi_@SWB@$.u=Q^(횼$ZSm0:圉|FsgD&i2"e Ԑs <&">" ipb2pH,v|Vҏ0{ ͔TD$f&[qf Β҄+qcԩp -Rch)۹u2K(=i5oYd5BG>ǁ3AHRc,%2NrUEe`MLC".U-{6< Ǹc8KfdCLDIonqF @HBw@Ѐ=dJ* :uWUJ7VY$rahM1H|Aθp+5`@M`h ذc~,{}ol<ۆBt4p }])xg:>8Bs>EdpX;JhyxȾ,sJ(/M]k/M EkSudj%~.!T/۶fEt' { p yGqQ wi0L Yyݜ%Ӈml}luVͼϳ%jyE:]b֯Hn|X% kioxVΌ96X_y\O.i|QuFUM0D&6w><ڳGhϢni-}s_.O41%؏~w'#1.'Q<m5;_úԶ[XNuIyj/(}"qSh%e.p \܆/1Uڑf -zp3_2@0a'CA5D?뗬YSŸ w^4váYWr[Z~mα1+0YZ ̏w{*Betbemon-1.3.6/.git/objects/48/0000755000000000000000000000000014032545161012566 5ustar etbemon-1.3.6/.git/objects/48/8ae469ad971abb24b04c30dac59625e62015380000444000000000000000000000371414032545161017632 0ustar xXmogT,|Ϯ!= -_ZQ$].I9>$E3C-rA߿9z󧝯S,tqP:4FN,xV+;u<PPVQDSI4תSfGeAj\ͤ,ْl݌o=,״*k2̈́bI/| VhofнrVB5L'k) m;VwַO1*ϱV50XY]&i[eYi,M"(V1e]W:W`1]| R&4_>c8{ɻ:gLk7f (tMf EFe8,PRU*]R)- E ĊtAm *G!;[y4ooN1;f0|FLR@ 6Mt`? *]KSI^3˟-ˬm%rimT!N-'WX6zd~RJxǬQx֊CBK^Yoz[7QHGH2p,^U=EZFw[NNl&  $N8`~Gp㡰p7xӉdK|V!+0N,W|tVHwQс*IӲ)|)U]ՠ]΁z?ؤhp;( v˭BKr޺9ĿpSq<ؑ @'h@#OG y_%T(>r 8zG[;σaHCFLgAc8):JmԏBľjK;`Ͱ/fbl|x'iZ!F2gx~D-j8(ѨwO)ymlb+y1Xɣ3-*Qx#b\Ah_e/0ztrBӣ 0__* y<vH4qC$E'=~/f>x,y7⋂[0^4HYW`3 1xA ;`9;mފ!5ƀ7n}ѕ0.𹏏3 1ǒG/D/"qߚХyg(7eL%LR؊xBLů:Tc$IrHczkxƃjz~ޢݔٛ߫dI/9r_>W[F8[s'd@/2'&vntʲI6DX7$䌳j 0?;w5ڢetBM}EHݮT-Jt+}7}\{UED$;b4mNY|xg~1nơNp Cvmii7_iS; i˔a$ݦ^%_Yoʗb^m_ۯ?l@CCAۯm|4.߁yl1>|Ľ7E Wesk"U=TMqn!4u$^/"o˧rA54 c$=<[)Y?'ak!d[6 iZΨL^IL$c/X0h .nxo{8xrI47ӡTO _KH0 1I$ ,0|lr\9FeUetbemon-1.3.6/.git/objects/49/0000755000000000000000000000000014173222045012566 5ustar etbemon-1.3.6/.git/objects/49/125ab10d832eb02981dbf48065faec03e5db860000444000000000000000000000267713276743201020002 0ustar xU{8Tip & AkYb%l.cfOgf9g2VQ*Fe]Rm ,Pf{ju[jkCv<Ϝ3?}`];;C$(Å&Ρ6mڜ[D$ ..tA.`v< q֋~z$]yX V_Pp&BK$pGJ P89';B4?Te04$_Wsi]1{3H˅Z{t^ٕP< E"!hԸ~fs˦-`eUΤ9 <g"lT,0'@_qpֱ1eO]=ù@g#[ĐFG}7 =dӵ!0@@ M;zAvkT98`q.,*kKTI9KJ45[#PўT2V&t4I$YfLy_Y}Iű0X5 3e9rJLTBsxS{z2m0T\Jpü9ͷC}0" h&-#zU"WtnͳǛ/Z6m"+ |:vT#t5b1Sb3Y&a61OO.QMOJ<3RvR!X_"OyU/0l*$/Ļ|WXmu$,\BP$^ zQze\~ȶn! xE&Cj},rb`t s"\Uu^maI{^v?; f2H* .k'U[E3j0]{+rMXiJv2x0tŨ#hw؉OۚEI &: [:ee}gn佸LJRi=3eԖRyig,()%c\^j|V{,@Sur'PcR0!k܂]Sm"gu.aߵ!k,.XѼi)?brP-{N#A_00->cFb;~Q7)YOֻ4-Y7<GCu'1#b+*Ny6h=f4Ah2ǫ}W;Duo|%`6MBaT(DDѮ o5qdvː ٽ: UB$rAQrM0ub̤?Fbm  c)2$R^]p=fA DTӘgשRPkxv*D"F+zkMw#8‰`)`v'5]=i2O^E>C-F!vgt}iEqwM?G-etbemon-1.3.6/.git/objects/49/303e88d4a1b8351de271c8a6367625239a44730000444000000000000000000000011613216421171017335 0ustar xKOR040`PVO/VЭPsJҊbR+RSR2SKKT *A@a*!etbemon-1.3.6/.git/objects/49/3cc6ff7fd9e812f7fc01a10bd9782459f0a0a40000444000000000000000000000024613212007171020056 0ustar xK 0@]Jڍ7L'(Z#1V:՛Dp0TRޕBTI9EuXzRG˓u2hI6LLG'Б_jzzq:.X>wu`~V-:֖0E% o]1x>p4<9āso[ ]5xfTfWRPYQ saÙE!^W6A'3qL f?k/go:jb % օ?Õ\C*SPݹyz)i9% V'Zlz|闄5U,'Je3H͢o(lX*"ϛ?rUЬʽZxti7}& `hy_{M/\+e,4T?|p~Vt F@yt-y:C@Rauў;sIwK\G&hetbemon-1.3.6/.git/objects/4c/0000755000000000000000000000000013764536645012663 5ustar etbemon-1.3.6/.git/objects/4c/a6a5f8e43282385377e2f55796f5379a472bed0000444000000000000000000000150313617253321017612 0ustar x}TM6홿b m/vb4@9HA{ed9ͼNBC c4! -,oH^%D صSOZ|qC)y1' h$Tk'!wwm9&jғx?#tߋq~8ReLaϑihʲ6>l@ 87}",܊4Yz`ǩmhSQ͢R7wPyH3z(E"Z}5])iN!)MGIF cDՋخEs}9CzaE'f^L$bP_'՟1;ՠY֊tLm6za}68kKfw|q"er-'}| }Yv[/&\X|dWIt=i4givR Y7f;LU^^Nj;v۱8(|te7hmӮ{-dXn0@.sC\t7i1n˜ !>)zW$4@YPPB)Ina8Ph&.Lz} ՙBW$.ڑ J. Dܝht&*°IrG)yґg;\1%aT1RUوTns$`Ii1]j`;`nea*%bmEFEB5Z^E|>#vaKYJv`lkE=$K cmg'K ٕy$4etbemon-1.3.6/.git/objects/4c/bb9a0d18795098c585f6424c347ec93d53c3170000444000000000000000000000036313604576747017620 0ustar xmAn E%uS:8U"L:hV gm'_&y`F=Jo)D}\ 83z7CO8\jt4CC J Sur,!2OL3XtW.cd|ƿ4l-X A|uYPKI W[F߃YOvp7zVDd\@0tmI:Ю*92QVetbemon-1.3.6/.git/objects/4c/d5209313a5eb3cabfd56769e684181dae3915a0000444000000000000000000000025413212007052017763 0ustar xAj0{+C Vׂ A~ HHlY]a`-c|]TD*=Q$ZS ;w]i8eT/>F~DR/Xqon_>~/^-_EB Ykq\_o Zy}ƛM~etbemon-1.3.6/.git/objects/4c/e6077de29168d970b08b25606cdf4c14b15ae70000444000000000000000000000360313764536707017741 0ustar xXmSH rLܭX8d"®TnT<FьydƁ!fzz~{g:/_͙7t3yh̴$m84;kqzw;iTf|d&n0̦8VK حs4:>]o~oӷ/`4ۣw`t'TI,CYSf8VE:Qk,$JL*6sO4ba~U9gB &@$ɹcs1?RۥPMĩ$x+V&|9.y,YP EƒVdb*Z WA۫Kʊd-ޏ 9o `_qHgb^g0 =X(ezɖm^cZh_3S5?/ %f׳) z*@H#Fqp|^Pz17ametbemon-1.3.6/.git/objects/4d/0000755000000000000000000000000013767534207012657 5ustar etbemon-1.3.6/.git/objects/4d/d34cf669f1f31eac41648a66a4ac1c2e2f855c0000444000000000000000000000141613767534207020151 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3B(GaVvqlrNfj^I1ó k_>v 1ٻ&_HIMLcجx%ScJ3uf΀*Of6>۔+_{ljI2./1GU;K봥VnFn~C9kC>\Ǹ#"fnN~rb0,_^qEyBO2oX;WO}Dz]_ryVm+8dqke: z>U)r:`|>@% .3rVܵMB.%pvLl鄧oCNlq^v`/TEe10>R: ., dZ"sSSRP0LƗ=估}슥N/4Ys0ڼL&PkK3fZ8gz}Uzk>&etbemon-1.3.6/.git/objects/4e/0000755000000000000000000000000013661360320012642 5ustar etbemon-1.3.6/.git/objects/4e/a7f0847c0d284b9c37b9137dcdd3a89eda89030000444000000000000000000000035713455033477020110 0ustar xKj0D)zo0!M6Fj{er> r,U˶\اVI]5峘shrGF$G!xx(d6j10\ *qBw[qe /Gl;aRG&J)޲uIf}tOyQ<'3E(䛿*-ܙiHjR+s rRwH \7G:E2f"+.Ia=W2`oN>&u'm#).fX5X,AZ6蜭k*")*/._^5?}\x6,ȪRUI2 *R1y-Qͪܫ1Am_Nj/}TdnjPT I [7f,vF5L @ڬsRMzm^&pC[f5% 3aOB=u[*=5o)ketbemon-1.3.6/.git/objects/50/0000755000000000000000000000000013455033406012561 5ustar etbemon-1.3.6/.git/objects/50/379fc0d21c612830dc2ea4468645c9b741098a0000444000000000000000000000035113455033406017472 0ustar x]MK@ n~E.YD/R\p)襰ivvd{#Iծm_^o^!o&3'Ƣd+k_b]=0b{񿞝jK-CMCo<O'IޮwkOr/Qa9L'?Aw!|^E:p1a yIl-[b,`Nj0I0·I>r7t‡c\- )_ko}Qn٘`{Mtg jO;|[A$[Vsq:w'M3qE}_ewdn&&[ rp +A A egi?Οr>쮑~H/hv'D~HKn]Waqn $A[ߥE-9LJ@gyA-W#{'b>oHHy ͣGFrчD^KTj}Jfd" ,֣dl܆oCr>]Zk}7,7W-1a)>w}]mxr%WmH6zhfV4G̒9 [st:09jsHOvm&fߗȬCp*bc<{1`8Gnb,\#eҭʟU8_/zT't] b.F_N%!L9B!U%/l?9~}򦾘'3WzXR p,ϗ_CE<(KGPOFxwB(-fxk4a[`13Jh˿b3.qYm'wE#&`PA C{FPG)rfr팭cWh   %0..W)hG/<8DVq/Om kltv*.Zzlb,*$&rsOxGfk۵{wŰ i|y~=!4G7+2rRr0eEfZm if"UmE. <"ag󯌈4`:"&'Nڕh ۅCl4{J 3xmXFhy9(qݝD,#IzΦ_.e=PJ4hf )f(toy<ژ[@ZS"<0L]tr1kͲ!c5B"?/O~ Ϥ<#iݍ=ZBT] uxmPYݬb| !vkK'qax{ô8n ͢[`|xxtm)zU:CiW=Nn= $ncvØȣD,vN5'J_/ ,? 3qO[ *Nw,` M[1ɹGM'!5G&^`A]{?,>3&0gktf%oVQƋ%ܤB6pt+, 6D%I&QJ1vK}Hs84cè?dJC6flN$"Se.~WisYl"' (b{y:Jڵ~z.-ZZ6p>NQPDbR%H $[N\dDcڗ)/͜`nӞQ%\y@n= =E$+BtH,3Uy* YO+xa0I_ J,`^Z-pI¡I2UTϜ>̿:rpTc5b&SYІҖ|ԸN޿i18xJt`6kn~'Cb;З F6 ȥcn2s4H.IFctS)ֱ"(!x99x&j xepxh3X~f1]ѹdU̻-< wr̈́٪egn OZ2mB ѹ4HDROAܖ+ߢe'iQ˺#!\?-ı霴 0ɘ|XL^WIED*G-x@J2Wʛ]IzVqg۱% kfKǒf\d[$D.g)DG `%5FUI@ P r|^l+n̔~e~ gPs,ɋ9+azzCs҇>Ł` KDo[G$ )="UEG ȶt)U(,cgF-SECyHִ%Y|n-T Ǜ8`lkHa0QI/u+A֊*$IDV[ת6O=+u2gvA~ĸONq%n"Dm6^E)Qm\x7ro\h2ݵhj5 E*§4b-sa*6D>a6+ V/OHG'pdjs&`=cqr$+Wjj^gIx{rQ^4Z(cAay _Cp,H7sd0tMG=,3s«fs܉H'EHԿCGwrTʐ](#ghH{j}qnTgeYU C٣.0 Sw3㴔!NTWMTg%͊ x g% ^eV2I7"J042x-ߕj7M9e2VfsBQcN5sIQ9. מl;t-݁4ϳS/@+(:5!h^cLK+M(0\q^}ht-uֆcHTUGzWh`#"iuX!uygW 0cFaUxӒcM'yQWF_E1ʭʎ ck##̸ 6F2*tjX!^JZp>Daq %-]pn Qz0p6ڛ 3*Okfhi&_6S^;o;n*8CSmhT`]8G2LG`$t+sVGϱ5G/IrO-x:X"_uV*kW8p'`aWd6䫭zd6O83a귮TmϴA!6v|♼=$<ڜw'cIRr7Yq_"s0&|w.hJ-zptRk\S] Sc;6Uj G,4|m!Gcq'L۷Hr>YQ&d@}UvbH`Yrf|ڕa>PD[oB}Pa /Bk'Fɹ!R|Lç֯*w,l-+z~:NkTR3 OCPgEs?H\?UȞkqү`ӗ1OIIqԎfW5|͍OPP]KǨiT,-5BW~y B19BLn(,KՑWU䥐P?ZO}JuYsxeT+փ;xzMi PTe0lL5CeO[6!Vo"hlP8ŸlEK!]+is?B''e' ͨ(xCu nUNEgEdiJIɻ޻!%S?3?-d`&ixL@_ X鞪ղ[:^ S+JuQz<0Q阸?#}W]TDZf3RzJH4g 3 A^Kzvҵ8S|o~aXWU;SgsJa=|I٩ íi[ؤg%ucgqb8 *_eㅕ%cs+_ATظK܎{&?y̝HcgK#|yKe՜5LjJz&3K('c\z!Z{> fNa1VjӟkSm'bS~ mo{{xYHx}y;ܼ;y31g3pr jOtQt.9! &-bLNn|vCA`)2ns9b]~슍(IYU2-<=э |@8bGt J+ :'rIiac,~ÙWaK|bBʷQPsoHoqjl %4?]Kof~*Z; T/zCI aL' hK *S5%ttxQk|蒵]{}.`ᏽb,..T)=rqmɻa 6 e(Du7v1t% o+״Ul۶z [է`ONu]$DOjn0W|EB9֟PDnm (y)wxFKu܅抻ܲ;lt{?)NYRfEŒàek-Du [QS"+=[ s tĉdjͫ ȇWOY@Z+&o܆!{&| ~[~V~&}* SNEr1p||rӇO]`Kc**X6GpFK7^|6NcХ^1{nѷ8XCW^eMQ' ¶}iAJJoEńI78_[uv9P2={wqI*A.}̲5/ݤ_$/׆zlq.JxhZ+kܱCUU*LP˾8l {~(6IĐc"ԅ#L"-0P o/ wh]"@ b48ʺF1 L'f19sbINGipP)0d%!xa+5PBfyArsJz'XXL%åb <9^cA|F"Gs{J/ ·!<"y<>eQB$KcExq oQ hD茢e#]Zvw'.[=% M6~ێcI abx@(%Exj5kO Gq~3@IBT|j6:甂AGq^U͎ PyQG2RrNINαj~?REAT:zձnrQ,,藔_=y>:ҰtE k;֊*V{?<Nd?`rnᘃƶK{ OEdžn>lr_S\%9}Rk%O1Y߆&eܭBTNL9+4*VP ~RE{b:.j  +'r&F`zǑc랯sZGNN?e,ܠk=VݺJ ŕJy:jvj.t[e^琝#2[\I|3jR=Dsq)ΩYیMC~;[_4k-zWX%\#ʩr g3_^g): tƻ hJ [5#GD{1G]ln_:4Z}tCŽZTb\6q*A9 nfjPgڝۺMuٲK_eWɟ!#T't)T[d 9 {A6 G09}_57IN4v^iÚSe_W~Gښ씡*svߙ41aGF-1zT4\Wb5 vsʎO9uV<|$C:<&a?žH޵L4&*k7>}]"5ԁ | +5 [ãAAO5k">$\ؙi%ހ/}V[S[Bf-& ۜi/uM޼{m0٫lʄfTܗ` l3·b5>qfUj7gx:j9NrKܯט|1u8&%[ 3C> /wv0Tr;Un@ |D0յɩO0>CCoP,*'LvdۄjE3Bu{͙nY]fkireZ?W6iqdz^qb@+-HcOA`%dmca ~W(vv*ی\l w4{yZa&h wg?y(aTZY֝@G׺l7gM/-Um TL[jr諽] ǂ)O?O+R8^b>N ltYAu;ј"= *CQ@!UR؉9ww2K#Rx]7S/=iVy.,>Ud dNKFLoS1-J_Y!cB*~Bp9kNp_] u"^ein_vӍ{jz4Fڶ'_Wղݏ/U*<4t,}G½~>Q x?YǴ̪jQHY{fWq+iv83 JLoi]o']΍ y ܐPH3_K)}2:(9N@+BY\1F8Jf~;,_Wo,kdžD= ks*G*1#0=qJrB]@ Rfd^1r]8BهA M}p j^WrpC1CH/x [lQ3(XDvmbL^ݮ*uEA4W€^}C~e/*&?Q=Y_RE8tVPMo_żTo=zd^ꨤh%)7n+ais6Cӯw_,^ LUMIӀT*y:zp.5?z'lݣp64ڇEfpKt{.BK>B +..+{č>>+U-q8~"!XGTWNCj#TO@u3^)@㹑w0o)˩q" Fp\qYr]+c $P`{aQfSp&7+D+Vr׹GյԜ9o mIf}tOyQ<'3E(䛿*-ܙiHjR+s rRwH \7G:E2f"+.IaXu9jZWKkO̔de3,y, R-utVkCmcz}ݫxH0d[ǡ+eoW}ac>͢o(lX*"ϛ?rUЬʽZxti7}@E榦 E``6Uzۉ[޸U8.b51hjVIa69yL l֔'$g0̴.sq> nH4K*-etbemon-1.3.6/.git/objects/51/5c50ef53131a12da22318c72d0447c9debe1850000444000000000000000000000141713604600005017603 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d`|z3שܩ5jϜS 5yBds2SJm0] )5*DEJjRfbé&I] W,XP u&'ߞurŲw}|M-If{M\Q=ǃ̲6{D;y S.=qa ߃h''ܴ=2Z}'Y*IO„椔XiTe?4&38xrUΝ5er{[NJ?Z}I@{؎i-cȉ- خ셪,G [CA܅ܸ4Xyɓr ̄N/oO,aj_~U[0 z/쿯".C6@etbemon-1.3.6/.git/objects/52/0000755000000000000000000000000013731650502012562 5ustar etbemon-1.3.6/.git/objects/52/274d28225d2fa87be0925b3360ffddb576ce3d0000444000000000000000000000043213604575306020004 0ustar x+)JMU061c040075UH*)J+,/bw%>ؓs \vXUZXPqCSuέ6G7 :ҀV$&}`X؟b[d܃*+-I-^WwkFN}ן2;aSJeVhj) m-k_AVˡPS|rts;M=4-TUq~ZIQb&_*~*˽vdūqPUHfz*pz0MC/*gtetbemon-1.3.6/.git/objects/52/389b643378a62827c07418d72c99eadcff176b0000444000000000000000000000126613212007361017601 0ustar x+)JMU073`040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35ݢ{%\\q7tW)Iy [ν}Ebom.ݵ}˟@Y?w5=cʢez)(.HMf9pb宝˫;) jFiPA ˌ,f~ wm1DEq 0%.[:ǐ[]+ QQZS0/9۝iLG0Uetbemon-1.3.6/.git/objects/52/bc8e31e2357d05eea093cb05ed801308eef6190000444000000000000000000000264213216420065017766 0ustar xVmSFgc@Nm)481 dh3C>*N9xiB{옗uE.hv/6Lo\DF*u\䙤(0;Iu(JM7C^'8VNK ^wV{KqK7{CAz}8>nÝDF2Qh $[zX/Vh7&ݳ3ߚ65A;áe/ґOKj6X(~"dohӕБeV\S &~SY23i*[J-lWK 2PiX$Ԧk)/3r""Γu,wɀ9NSۯlnd9kqKf?6=C> T=˩S{Y'w@po9ӱ,9w`(s!C3I >v-(S6cwp8I?Yso*z}ߠ͕Ise8XU"w~{2Ug=BQKU+ /e} :U#-i,2&=3ED ɵ\3"8H;;wnNޤ~Œ|94edpl y4{uFRS>C"g_2gt =NAZ)n6Y)zqJԲ -_V@4%5+Q;D\x=%YfPƮ$Ef ({Cv93L;vTz _{N!ݞ; ^:CxVFɚ 5:E Oĕbm&@pJtUE.;q*488&ׇ]YTއ*&چ`ybv9-9s*bj0l 񱽘{5 \!N6(Dɩv8)gvp7 [4s)Vf}F"sPNS %s[shyKu;Fa8expx;/)zG<׈@ fR_I|MPn4媀-~"n8;7_bRu>h"ckڣ` $]'׊r$:MRV%* :S |o&ueɖd|wgdT} eUY-m1`n&K:{{TK G{D^6ӆnȔ*V6YMYh Ɛhر{k}Y;kUwXeabfйVvҴ!.iOs[K|slʗ-*irKwᘦF5& hrYJ354/55<`RBIUvIYr,-+11 ;l=Y:e2JJ+5lb6)[*,^ZՍJrvY,oYf-hSU~/Mm 97j9!/="V›=AZFw)I;>qR &  $4T|p p`C@Xe8盇z%sg>xd fm'3mr@>:ms+d(@@i]m>]iUr@ =Cl҄zmRXNugUhW^.[W73avwz7;R h5o뺄86%GQ]$G3h rq# iՈ4h 5=ATQ3^xZ=]Hg yjcLe\ YO6 Z?Glpo %j,t\C&kw7ZJ/eKCȮov|-'߁i1A\މkī4-U,JUMqn)lr8ۗƼ?c3Ȧr-E,}$F;}qGq:%+܎^.'\8>o;a% dnK2U ^Tpsp)3K V@Jv|y,0R|l_\W 9F*etbemon-1.3.6/.git/objects/52/d5bcdd82932753f97647d0531a14ea124f27260000444000000000000000000000141613731650502017477 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3fS7SkԞ9j*.&d3<`JmSkrUԤ<熧hOz22Ib"#JUetbemon-1.3.6/.git/objects/53/0000755000000000000000000000000013617253321012564 5ustar etbemon-1.3.6/.git/objects/53/6c9cec0e34cb4c2962a143dc69de10b3067b160000444000000000000000000000141713617253321017763 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d`|z3שܩ5jϜS 5yBds2SJm0] )5*DEJjRfbïwL8f,1%AGZ4dj{oMb>Ȧ$3̽&Afwlg~<{ҰYNry⋄A4eussaq~u??jNӤy>5Q24NqGU|cz4Z54JAt8Өoq: 'Ԥ0v26$}|e&Z\Ja_l6֞mn<7ϷkmZ_Ʀ& 16\^ML}lO&\ R3N$6xHȤ&L6^82Idp>Df01ߌ\`4o>=$JS_ȗGh%МLχy;E42!: T:h[<̫ 0nn6]/䪉EN 5k˨o#U<ư <<_Lhc~?9~1{GNO:@Us#p4ƻ4aż:m왓{qfLQ=Ծ)K"ӏ&`f *a{3 cԮa<ѢzW/ŒɪII, Sy^5ڪgӉ@Ȝ V{JϞ_tVͻ=c7766֟󾽇loba/u4Clm/MktI/}Aߓpţ}Lh/Iu00lS}{0MQN*eB/I7N! (w{%Jn`E_XgݛpҳuӨv'q:`0aI_qF]+EdoVoè_|;ҫ=@5}sZ+v:ۇ:39nu'%"pM^D&sbi&Q:lT0C- (zujjO:p' }w~>޶N;|~x:hW8%Hq :xa&6M'vŅQ5H|m֪,;}ۊRG4k߭4#\w.VxQ,aqbNM ^S >ϫh8'r^V AvRVƗ>B5Cw8N&;V   ~:A 6>[ԛL ;#E#iyD˻WdC VatS7~iIȘ9= V\W(̽XCG áeQA:QqRB줯T+hԜc[ǿ,@vhb'?=1;\tpu>vݱuGuEuDkU*bAdN3*phUG6𴳰h]\7|uQPkK]*Y3^7p]YLxҮ2> ׉[4`[+d*V"pAqkr(>ɌgQ;~WWSIbl)$Xpo3P $F#@tЯZVVC"r 3ِD}R;-Lʝ$!vًJ(twC}XgO#Y]QyjÅItf:ˈ.RZklHvR=;+m8+0#.YA&S&Ƌ[[Ry!KB*dž2$d DSJS_XArQs3%ec#h+KFŰN|,. QJ([/"G'jpAcz8/^ MO޲vps]ubĵ{x8@In ]w4UƴژΚk6KϚչkgk&b Bح,Q7$P#2lThcK 2*d)x,%ϊ\;FU%Jٸ0An2g^I Fl\i"×yn\RypAj}y,V&tcm]3ZW\.&X_{|m$Vgϟ?Ek)N0,3> Cbɰ\I [a P(~yB;,ėԴbƾVئ8)oy$ E(PBkrڝ~i::PYZS`Q-J`fduق+_;QhfMIKdR\!j'/Vmp:L6$U ]< ՝v5.Y=>|ɉ# *l26@&gjK'6è kwPB.e^VEܥTv*)wRp[,:UB9{!AP{O_X C0}7tDẁ9kF[#--VQ C&f֪Sb96=^R6cOW͇Ggq_v-|&r\9z' sq+L ")63ɀ% dd#w?x~Z{xj\Dxfՠx62㞘/v*Xُ4-x=bXC ~&B ^JJncۀ/~ F^+ƟG 2fi~-rwThrTkqMXߙ֐e DS؝S*2!b|CGTo^ҲH3J]bG/֗!0rxLjH0T' CWE` 5Li;o1d5u #%CmARv"JTJ!LT,Jص Zڢ-5K`aK-r2"<¾OtZq4™&0[ qEF s2?!rV5єښr$"5MMц2qzlGاVYpqщɆZxMI`cRsgKψ8$LMFm(Me%4`,lt%&j ^$`y~MH,FZ- ePKzs3޸yDcs"3h)jT|xyt+Hf#$w2 E(ߥbSt>In>^:!-iÞLyn|dσ$z,Hd SJX8E^^5H?RE!2.^~!j Qt`?SΖc|yVO2]'@5!V{=9UP[K˅>~TTd'z!?C3BS]!79QBEǷE9*^yo8qf3 ] +8iϞcע0,.bOsm ,lz@.  P"F W+`h!yNq! 8˯D^ yek,}^4rYN0294̡[hy*o=F8uOqC>X9|>^"ˎ%Ѧ*Z~Deb):r/y .;8ۙ[ٲyǷ{ΥE!Mo8٘X#;JWK]h{Wt3&+mAõW˴rD zolsBhKyBrd8\Oť1I%/|'_w\sq-9 eZ5#w`Λ$bΟ/ے)\ag{"3ijv(,YQ@*sP⨚tC!o|YNE;֬sNY?AEl-]K={:tյ"đhOy"^#gV{;2*4e,C>]1|g-jm0JVOh8/FU/ke46"ԮL롒ud4pZU\]J_ Kf 7dv!w`L$f!\nu^l~ae(X\SQ`^ qP7$-Fl ;2{)tl#[Q#&4)f8祆thC@qxy]W}13?o#|#R_V=¥qPZw1G@'lxl1ΗGO֢Jqmî@] aہR !yZŊO9M\&(pTNPXɥkx4gmY*3pҳGSʚvhpGDߍk yՉ r`*xώNX5 X=6%"E`CvPVzgv=_~k9@_㯍֙gx,7XCǞ}*&йpWō=4S|a/ 1OT-JAx "(Rv(RH0$rb,ey.j t\ÍakKIq&)_߶p fgMljԈ@qIAMav퓳PJZmW.268:>kAIFlbB䍑Iw lTp=ig 9Cdϭ?qIے[Jcqf܃xky`* hiV|YI̔[`$ӒzMv6eCUWHY@ .iqOk$DyO]#cmAU,SWVA-&\)L3l'!@"38}y2\/An->w!,Z^ٍM˚l@#i_1&B&-A icrw #Bt\4vA&Ŀ(ޠB<*eYm9jb2a΍/щ0Ū۷- 5A櫢s2%?]_q[H $,U:}1%L_ `d"*r!"9ErUa3;DL1,, [n?sѫZX.^4(Qm",g^}^WTfAEm@wŜrY1nc<"_l 2>~˱зE0M8GZ1H஦HJo`)~ :)q[n]!|mZ"f'&^wv qLrO( c/qo n25y!w.ģ X rI950ŢP3磸>H3kFeٮ-ڧ=[YiYEMbC +pwjbהWI)|]-8H\:&Z̮ˏdEm/8ˋz9zag(ї?bO308d2I 5 P`R`V1Zp[n&'F >ǔt!H~ںLN5i]_1mAɥXLP"Oc)];rx@ޮDP$Jhh KTqQP a?|gϰCg)! r6F[)OD-Bdl?y<.GU@kME$gA_$һ#E~^+n:淨Fvo6`E]isNPP掰kdO$mm!]qz{Zws^V4]~*ĵQO/_afC /pk;t&28Ïc:Ϻ\?ϽN~N4Z^kT˺2fΰEgȧƬTbyW8Dv֖.rzje]G;Gll8 !],4ypIg&J9 8PV± pfEw/;\/Q3U󈲲@ ͪ@^etbemon-1.3.6/.git/objects/54/0000755000000000000000000000000013764407301012567 5ustar etbemon-1.3.6/.git/objects/54/03e1ec14081a801080892bc7f53fa1b79d11290000444000000000000000000000031013764407301017452 0ustar xMJ1]tDW.5jZf#Ign}<|Oʶ}uizUhAsEBB%I !N#R4)owy&ebtd#3$̔ }->zr O/')ۉg #yG"D3a{Ya>~\etbemon-1.3.6/.git/objects/54/178603bcc8a1b48b0ac5619b103655b3983cf60000444000000000000000000000126513212006716017546 0ustar x+)JMU073`040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35ݢ{%\\q7tW)Iy ;d{i) btm#W M-IfX?׈˕>v)șiP1tOݟ6]۷Y qL}Q3,XQ ,d^~'XڹjڹŸfV00Xroi[Gr6 CTh1_ⲥq 9y۵%9 ÿ=!ɜ$Y U- etbemon-1.3.6/.git/objects/54/4e8f1b4f797d44e3b93c534f0e7a928eb567450000444000000000000000000000033713604576020017674 0ustar xUN0 9)"Df ڀ 6TPx[4;N٭ -<,.Ɔ"F%{S)9,TX)˙8 }Pw̷}3)t]C]Fth{4uYT*WT^yjtg6dv=ve~*(ޚY«|1$Fey_wh;etbemon-1.3.6/.git/objects/54/e8326f0059be6135388f8e34999104fdd20f8c0000444000000000000000000000141613664403613017532 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d`|z3שܩ5jϜS 5yBds2SJm0] )5*DEJjRfb,OmwsS|UPWmro}_)W,;}Ԓd]^b&ٟ۫viK} <{ҰYNry⋄A4eussaq%&;޽Ǔ|'[gUufW ^8{麷vn$Ch^qAj2/ρW,w\^5NNP3J+ J\f,g4ۭk\!*K /q O8⼀Z^b`|05tz]XȔyL%9 ÿ=!ɜ$Y 2W<etbemon-1.3.6/.git/objects/55/0000755000000000000000000000000014111113236012554 5ustar etbemon-1.3.6/.git/objects/55/3be0e60175a0f30a6c2fb56126b866e36619a00000444000000000000000000000152614111113236017531 0ustar x}TQ6~PX5 }8Y,mueɕuM'vBamF3}f4 ݾqjxNY%ݎeG~viœ4.ᰣy1G]l&!yњb-u}RsH+KOƹI)C Sl-}tNGC-~2VWydz#_?Lo6ݐ5M2WXNJ}Nˠc(?w<)qjyގ%6뚥؊/*VtFy!A-/םI%}sZ?co:nH"~ 7 D-E lWvEC}9!'p_c[M >3Nr#_r)QEbkJgt.^% nI& }|,, Lv1U1Zl+3$y#wE8C,TS7/ ,*LSO]Ǹ5;*E.ӔDհĿm!">xZncWݽut/;J>p=$9"O(B_$)yoE5jO:#D#[zN_W$A\aB!gU` h!vGCC%iIyMC@hԟ`d"%9bMI=EߦY-8ؙVb3P Ob^h`e@N'ʎ=Tҟ~: {RDpD{r piif>`eP>g kYW`kA=d3>DžXrmS/dPfmB4_etbemon-1.3.6/.git/objects/55/b3fd4e6f5bf262be932594869873dba91ff41b0000444000000000000000000000151314052407067020027 0ustar x}TM6͙b ]lm 1GYSS@RV =vmEK2f q޿؆1ՖM7m/^}PکG->ḡ܈< ]4p{{pru{`5hQ8?\^):ѧHw|0eYzWGq{ ` tu+޾^nEN,=WXI6koufQGy;`etbemon-1.3.6/.git/objects/57/0000755000000000000000000000000013775160026012574 5ustar etbemon-1.3.6/.git/objects/57/0c456a30ceb8066e6301beacc7ac5c339fccd70000444000000000000000000000060413775160026020206 0ustar x+)JMU00e040031QMNMIe8;?nN|:/wrq7jMMJҊr2KĿ2sIt#A KII-IMM,(HMK.(`uy&؟jRtW8t&0lK׹KVz|%u3Ҁ>).HLNpЯxQĻlNg: 8'3B$5z*nM|"zGx̴SXWuѹw61uC [O2VhEmdĢs H.ӻI7V0i%EcPaS`m^TUU'+^BSS%%uN׫i2|Q1= 0retbemon-1.3.6/.git/objects/58/0000755000000000000000000000000013604573616012601 5ustar etbemon-1.3.6/.git/objects/58/1249edf5e771cd7e4de8051ae0d1ff48d4c4620000444000000000000000000000126713212007512020065 0ustar x+)JMU073`040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35ݢ{%\\q7tW)Iy KT_`qF} btm#W M-If86ҩ _|eˠc4 ?{m(-ߧo( ~.ygLYLX  2>N,^ܵsyմsg;?;A(*(a`pޖlҏVmr1(.cڿeK'<}rbk{!*JK2s%A{Bԓ9-I1 etbemon-1.3.6/.git/objects/58/4f37068ff6515d9d9691b18a73c6959730ff610000444000000000000000000000036213247732002017463 0ustar x+)JMU025g040075UHJ,IMH-Ie+So%h٧g~@%g2|:MֵQɬM:G_ BIrn ٓ&[+H42"-13(QϿN9m{*՚6#旤0<={*-3Bxo!K;8#!xglshxny)jEetbemon-1.3.6/.git/objects/58/559086c0c915d6b5a6a1d9ade463f92be211ad0000444000000000000000000000025513604573616020010 0ustar x 0D]+^(y Vq.Ioؚo?py9Ä4MBd"@+2\bu:D<* Rs2 a>Z"RFGJdhrv )u]G8eƭ{Fra9A}Yn rJ 4ΔMetbemon-1.3.6/.git/objects/59/0000755000000000000000000000000013767534565012614 5ustar etbemon-1.3.6/.git/objects/59/98ead72add170e2675f4fe6ff82d7dc6e242660000444000000000000000000000026513767534565020137 0ustar xMj0F)ff@6%ЌGԎ,߿AoGo 1haGJKJ̇8JN摛;1XUJ%2'[lp8M^6ˢ > Ľy/8CJv`a{7=\n:=L;,sn]d8Q$etbemon-1.3.6/.git/objects/59/addd37a68c47f19b662bd462a1a558126bd6600000444000000000000000000000036513325227421017722 0ustar x+)JMU04c040075UH*)J+,/b0$g?9&|#)TaPcqAbr*\1{e/6nL;Ea=̼ ݒj' Z9C*6>1gw3Lu~bJbY:\%Lat❔P:L,5qi[rPUi%E)pUT.X{=@UɊWj}鍹;XwLtp{Vzetbemon-1.3.6/.git/objects/59/d6a67f0c3ec6110efd585cf1b6a007b85445c60000444000000000000000000000120713462026443017777 0ustar x+)JMU07d040031Qs fi^5W~R:VO'hrej"\m_^yuYL4k$59 ;W$\|O#"{0W\0G#d{duk87G2.'3/a`jĮsʯ]j dCVlN{v,JX䋦(!!^7*6F=}TaURkT>o^g!sTe@*jmwLP[WӥK*a4<%cW,-v|͚[='Ԯe2 7nZSX0Ӻh9$S%#]b)etbemon-1.3.6/.git/objects/5a/0000755000000000000000000000000013212007641012633 5ustar etbemon-1.3.6/.git/objects/5a/a566519062994a81329cb3ea5cec55570f12fe0000444000000000000000000000126713212007641017640 0ustar x+)JMU073`040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35ݢ{%\\q7tW)Iy |GqM?4I*Off7 ̏8,_x^-D6$ؔK,p<|:1n4-:47?0|:G쵡||ھf,Пezg󎚞1eQb2=h`&38xrUΝ5er{[NJ?Z}IF@{؎i-cȉ- خ셨(-)f QOX&ZWdx3+etbemon-1.3.6/.git/objects/5b/0000755000000000000000000000000014200452005012630 5ustar etbemon-1.3.6/.git/objects/5b/e508eed670ec03c9b012d773ceee202b4710210000444000000000000000000003050514200452005017740 0ustar xrGo?E<+A>.5c:4s&bcMIAߗYhHxb=16tWW=̪>MB[8KIxܬ֓׿>:yr~N7ߏaM߅\)etl1|:l\[YqtA̹zph+ a6&$a'Ch0oG {NGP_0=[^\d0r=r-tĨl" ` "1<Im$묮V yF*gs|t\O?a> czZV+ZV<h6o kIXNEr6JXK /J]dRX0eK=I$4\g0^l7rt9[N|Ψ4ϓG9:ut).}.d`1 \uhMrc*L_LBih?&jwrtR'"MAJ.pGR3KK%"?L<>?Ĺr1Uo4B_y÷wpxW}4g,rr7ԧ q; h5WE[r71zKn"\$vôqıLzg b':Ct/xػkQ'X4_䘠ٰ6>i%c}%;w?NP1 6 `&aS̒ -2Ōsc8Mbn5{ILsh?B[Y,왡Fw*t,PHՎ+&"'f^$޼ G: ^l6/$tFT|{8P}ʰ$^ Hcow8ѽUjV "Jٌؒe*4CodgSVJ4 V)s2RQf?].,`ڸF^3ͼ'8F-%&+) }uv&xT#i0&y:ɳ@4{7l_:uUMRx指,p1fǐtl:w[_e^\c)Uf'< E P&Gnenk˪Av~?g8|DᮑyHz8<<ݢĨĄyEmEf7~gGX+UySU"Z k~2,IHnqbJ#}t'*Y<,b:DHl,R4&.JI,M\̧Y+pm"^Ǹ(#MN|6E݈ݬg6zjP{ŵMh8v[SX{dr?BnDbsvSXҒ*Ts|nv͊xuSX:dxNw@t"Y9蓔}Skw''mvWcv*P'ӚTQTjH8!t!djrh#PxPR(tA"> fٝE/1I0!WSeab: /}dN#W #Yݱ?cPI`! וHvCcG^e-@PCL;$(== 5BpoBʬəLHiH?eJ7"]lY2Wi)?r-nPW†M53/J]Okc{׾O@:, q-dbvJK !]8HmJHȌ=~^d#n=[-o: eҭ_b~G|7Bm4%bl,[$)1M0T+t)ˊx!9P-3*!)>,B gˌJY!g~@!Gd>G-L쇘=MgΌ/4엘[cz]iFP]hi94XIF- }S, +,_`QP {@za\';~Ud4(.]0cH180fwFdzhBeqE*LÀ 5 %Snu غ;z9\)˓)&eӕ;7L?>B婌uD#͐c mhϖP37kCt6JVpE#E7_ e@]ZIX+RwfXL2ݒ4/"@B<Ɓ;ҒbU}J7SO":ALr fAN&^ɹʺ G!6j|O 8q\r"+.^pl:7LSx+!9?Dާst6l; F_L"*H1?U)JxQ[MY4eKjQBK!.{b@i0O=xAq'W(LRI"wmzi,֣j?" E6O{:Yiby~ny^In3VգJ~u"{vlwEL~+JtH-3Uu*)YO+ya0I_O J,ҜZ-I¡*Eµ2aՙ#7ʂ6\X:~nMpBg>knލ`ySK[З F5 ȥc33,zr@  %h .6r:VP%ă,G;̠A 54h;,h ({bqKSfXMQ,/R1d tHC[Hr͔٪ggًHZ2mB zVt2J2y,Zr A-WU-)7JJpYwb9@ꧣv.g)Dk^ LL 0*kޗ*(N㳢d[ Vn+.k_?U.'fI]܂Lz>q5\8LZO{ \Ї< dSwU!eOƻ訒q Q5ACt<.e VB^Yeh};tjzXQ NřpoYL!?\yn"nLTwU"bp)j!Ie %f8EtjBkV׶q]P1@l\I,QWYJ4xҞg㭧1\w-o\ B-wQyȩ:dOpa6R "_60٬/DyS5Va]bT4]s7O@h(gx$7JhKPdK)[%Xlן1ѢTbQc4vBեM#h4*p0.ûD{Ɯ5vg[=j to~XI,$ނ )Ѿxp E CzZ6O + $TøU ĀT =9{kȆߺJ}j )};@j= -lRIlg4*<ɒSª@T^& 9~]һnZzz;ځ> ۦ)en8٤`Z0=cNK5|K! tw &/m,Z9U?OP(1kͽP~EnZ#;s&TX nG!xM^PGVo6v9*qt|# >#\>w:{>y"&r6漵0{UMDcg:%xXʕĄ-"hLl1Q2bgzCڥx~XnV)=jdNHjlb=ݭ1MPE(Y%[dp= ǃv%ϮlHr`a\_&}KzZfDo Y-Qyx? kJԡ6'Edtbh#ަaO^ 6mGņmltf65+oBAi+yXn;c |$ xJ{ox^#_NSQ.yfpS:u(j6=|oGfOşIɟH!YHR=uI{C1BeQbFe7pVS;96Z'CwI#zza$q3 V?lWʅU~uVdԾ531Q\ZW:fgmgGofXI^ݨ|8􃧥">-sEǷ=@m Sc- lDMeHŐ}hɐClI)olH.*b䑟PA q} hE^**GE4G ؞RXs %Ow"~8-?㳑0+eϼw liy9'o, n9%-9LesDM)lò![Q'e5E[PQ0=L"ny>>򡘲VcM9b+KYX>k63mg{zQMɐؐ`x|C" r3 ox\#<7J͓/DM0c}厅qK`Y)~Dqj,B)ixAW>σisMVq-._yBIn8]]47c+O?Qv}Z0WAkZEse]72PAYr61W0-@gLUe*D6͈dr\\N԰k)}ъ0|zQ ҺEy&SQ,=g¦VriT*mGd/KqS}(]1d%ia`3^6l Pq]X@\j굲$R{Je;޺b;^9Fib7%ል1,(vs$(%zT :R6~E,=A~ .FA!R=+TqjiptwxVc3SъvU]BuxQW0QzCIa,;} X K*Tgk[EFuMx)tqaJA}\VːRv7lAldXY2keĺ|卝[IjL݈kC6vYVrBIntטv3[ _@G#<.D f'q7knR IrM;<| ]"\Ѳܲ;ltEx?)NYRfEŒIek=X4% MF-d EXh+q"$^~ùWzH%BWT]F,½ u8WZ/x"ω/4*ç1>*?b&$q4Y= Mi{쑪Ķh͊i34A]u<Ɨ%Gߺ` ^{5۽NLaR n$3 u#bb8Y@p/F պAR=_D8qI)A2.YK fa nR/ Rr{C=8 V}Eq~ k1)3J*wUp!XD< ?)&2#\NH?sK w'ȫ% ]"dPֵ0D?t`:1&i8;Ý U֘0 wWXOz+?`֘7.LkV00SMH!NU4| -)m6CW<]pDߵע5SB+i"ƻ̓|V(ОD&b4yATgA: \ ~ұ~Ϩ)Qma]*Ftn&]j,]hu ϮUhfTiܵ}O6cE\[uQ~V: /ۥ/w8t=Gg#Bq%gsbLx|wUp fM·^>]~mo؇DR&.r2xZC>Cq.!Ӣ"<ұQhQ hęMRe#zvg^;9^>6E@v`$^b)vq,)\e@1Jqլ=)w'TǩPlt*))~>z'V tS m;߭Z\iTaCB[/Vj+m8uKeVJz%tJuO 3OơY;o`YQn36% 4v&[_4#xצ[]a$WH( _4.{~$_^g)-: tVE_b [-}x{Q˜j/v?X恶(.uB/3c08D1|wG`4~COjog8b)L/:G݋qIQ3 *CYQ@!|ѱkeVF&<. ;Dol?O菊Ͳ*raa$Vqǽ"KP$44+mV"S&P*)5u;iG[[1zYN`v'^-#6"K1}iYrsM7cVjnKw?V1דOoObK"HG %=E[Ϫջm{;ѷBD0t;il?-\v^ņ*4p ~c%IREJ[eCA<@ *NrդMN '%ٙK:=A3緝q MgMa&#ʷ4c)ٌ^D?J"E% g~uB±.RDFwlޯres~ʻlWr<'-Bg vtik-~zA+ڦMNFPA{w»Jm%?jpH |>ҡQ좎3 %EM/8jo"n U ie~$r"RQٗdK֍~-%Qab::(g?gxucv̪k` H ^fDV>i"??Z۶IVwE^f _vhzfE^rϮ#)ǏƧt)?pMmIQڕ;~١aNwGEevBvQ;]gUz6bH^". |L& E]6]YݤM6=0NP Fw M̒;!v$:HQ!`weIf{7i-c*Q1Bu]%8=pg%xւz&n׆|K/`57J9LR x ɵRT)}RZTyY4V2;m E@t^K,7fفmX}M/ͩx[*njt X[UezCDE]plՅVa*X}wuGj]WɲqC5\!/x5a$#̠h_1"$cŘuɻ]ҋ^hEY}^ݡcUW*ZLx$#1s-Kŷ˭D*޾{[1{Т<lZߥ^WSQ}6v mRbX22>PeJ-`T)ұsợ?gMW9hué6/E]$?~( U{#cZEW_ep㡏ϊiU[F(|>UȐI~=BtZ<7?j,c3aǺv^1zeewU"֫L0@mb.EM"!1]X']U6P^漑70{7Dl{׉xn[MDڂ(tSetbemon-1.3.6/.git/objects/5b/ffdcfaef78bcbfef6ee0652b163e359bff51720000444000000000000000000000040113212006554020521 0ustar x+)JMU060g040075UHIKI-*a.wJu[s0 UY UG%"ʛo9gKWPE9PUl {]nYWhs{^KTU^jIAb:Ο!so[.d߶g#^@")NGjVMٮʊ 卻2ﭝؒPU%%PUV ,ff½(Z<10UE0]7f)6 em5jetbemon-1.3.6/.git/objects/5c/0000755000000000000000000000000014001503033012626 5ustar etbemon-1.3.6/.git/objects/5c/0c29ebb2f40feccfead2e2cd4d213d92520e050000444000000000000000000000024713212007370020321 0ustar xA 0={JMD^AE6ߊ?8 Ce ,][ qizޙ9e1~+U &#CrF1E5]KTimR. ?p.p?<;*S#;{vٶ^]ʛa*sG7R0Letbemon-1.3.6/.git/objects/5c/96cea4603b045f2effdbc4c670352caa91829f0000444000000000000000000000120614001503033020115 0ustar x+)JMU07d040031Qs fi^5W~AE-@V\̐joʫhrgY#IH-I-f`Ѿ")p{Rܛ.3$1'g,^ʀG[9ԝ >,,'3/a`jĮsʯ]j dCd?[SzghrU_ؘnl~(bcg *JV%(F H2GU4r{u;]ZMPBQ)(&-lޤzEֲS D31hjVIa69yL l֔'$g0̴.sq> nH4&+etbemon-1.3.6/.git/objects/5c/a90f1eb06400bb6745914c09444814780917100000444000000000000000000000437713212011530017240 0ustar xXkSHݯW\2߄pglTj6֢K-a\ nlaYj=aA(E'JWA8qp6`'4S.zc{p|yb4׉&l"^6Xj"O@Y i8 <;7vr#⟋֪ tsR"!3J~XEAu4zޑ-T_+PjoV#$7Qjj濈.'=$*xr"ƨعAZ 0PXbgֻ"[ŷ x{anqyQ{PTFSRLRG+HMQ&5ZfWywCKJZ.iXSE]%N[eg @Cō^7P]O6MD/ 3C S;4S`я֫Z)q`>@6ӂhųx#qe,i`}H-3hOF\@ GZV~2eu@ 88 ulr/=ݩ}@x.Jj!d%Mumht+"5~hՉqӟHVy:F  <^jhg>1  G>xH^3Ԓs[*$6ټ7q)HF :|Z j܊g<;{3NF6etbemon-1.3.6/.git/objects/5c/b790a0019973545ddb2bbeec6e370bcaf46a240000444000000000000000000000134613462026443020126 0ustar xTn0 ka$Ȳ.K~@e[,6(#Kk R<: tX7jvRV$ژƌBJLYSzƎrsv=(C'lN!3&B{Ij~Ŝ†xb Ox+QfCϕBC0 I-  oHD0a?5[pAD)`A5%_ n(tYTʰhBRPJL"$-uıT Prhg}WRW&u*5%\6.nV(u&w"&ng+phWzI5Mwh]Ә& zu&75GQ.H;+]NK^yܝ޽zدxe/ϫY3ƎiGx:疛rw{[jbKmuI7v[1Bi\~q9aS19|KSg\/etbemon-1.3.6/.git/objects/5c/f39b34701b8cf491aea728bee0cdb1bb288b040000444000000000000000000000267113642215544020213 0ustar xU{8Ti1R3L% +DnmW=Μ̜3眉 QKe*kRrIъl%TTTRrkYjkCvz9g_{(ݜ)N\]Y@2/(fyl0v] ?x( "`w">7g| λH*R~匒8 xe&+V']+)3,JG{jl~eB;[[;P/C  ec`f>nݭ aDK TJ;1o?R. (Pam 2 z7P )Vq$@|!:Ƽ/}Z>+V`#L5YfwاY^4UXE$3S̯)mi?{8B2Zd6 i窩٫OT$Dr 3[ IO@8\-%(Y.Ա۲WΩ9.-bZOwccZM*5_%bf^j9oCOl4-e9B҈|Z!)ږ>_הTS\{̤jtHp\^B8~7zo08<|΍VruH %SCtx"3vRq1 9Fz}˯`qx̀λ3tfk5y(XZJt1֢^֣WlW9dGF[ę4Ї@K"sSSRP0LƗ=估}슥N/4Ys0ڼL&PkK3fZ8gz}Uzk3)etbemon-1.3.6/.git/objects/5e/0000755000000000000000000000000014173223022012637 5ustar etbemon-1.3.6/.git/objects/5e/6353398add00fa60e1e05c367b32198201f8500000444000000000000000000000141613767550465017504 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3B(GaVvqlrNfj^I1ó k_>v 1ٻ&_HIMLc`(Sğz͹ ?3nSXv8!% 2L9?W,ӖZy $ 9r,Ԋ 9ɉ9`u*fWŦ>Qhܶ (-88򾭺V p1z t>|}Rt|P3J+ J\f,g4ۭk\!*K /q O8⼀Z^b`|05tz]XȔyL%9 ÿ=!ɜ$Y MqYetbemon-1.3.6/.git/objects/5e/9a61d4205056f8f6aa098d6b8b0fdd1d54459c0000444000000000000000000000153214173223022017777 0ustar xU]o6ݫ+NFH]غhhZ""I9Kʲ3P ܯMc6X~[j,(:%3U(TU":3ZkiU(.sQ,(VEo s,JK+4J-y2$ņx>p7+]E@l뻈)ɹ  G9H6SiTAtPn&p `:WWI|> I×I&LjE4< #aou'a%g ieY[o|8L0lʥ#$'U=f=-eQĖ=ۈ=j\xz 2Uzgn g'kA3TI&7COOetbemon-1.3.6/.git/objects/5e/b4a493ad63e360a85e8cb743597749d1bf162c0000444000000000000000000000126513212011266017724 0ustar x+)JMU073`040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35ݢ{%\\q7tW)Iy [x^RQosIϸwҧ@'3<t,/<O%D6$e{hOz22Ib"#@/etbemon-1.3.6/.git/objects/5e/c8aa2a9f437b45b996bd3518655424098a28d00000444000000000000000000000031313764536732017603 0ustar xMJ1]s! JOa ?q#I{R]YE 3_%EL"*(7aUMd"]$ 'u94K&}&‰qUKYV+ <5Y41S,,YFSF7fTdӼ1e-NMU{bc eTxtѢ WŬ1p11ޜx(p'577; .&&UCFd<250BfrݕtZwXg<?D z":9JRP'd>9Lqΰ)8]- Cc&lsbyP`|)'RrD¬)ȶ$@O`Y8OeV}T`a̫$ͣ|h AӮNbjMC4{  6 ^; {(I̫<__klNM74` [ak|ӟ$("vɬjt&Jacp/o_;Y^ $=dG4[ϫ;ꛠ3l7v|hGqaQ_*O?}YZ,/n$V}s >ŋhr &1͢(_}UioCH1£NzP_9 hz xg }Lc$4^e钄7Ϣb|fah&lh'yUhsf ^BEhtb췛T QY^C."sG0}p}Q68y|=_u uY:k%|VCUB*ZRU s>`o~G0?6yZUlETnÌɀ~bk$`"r^y)Vm ŦnAA۳[U,W3Ai.PA=a9z//k)],*RkT& XgXOnSe TK\wGyE5>g'1pAE0U 6~tv(ApE:ܪl0w:,թxYTڶΛ2]g 4S>ăr;l !o4k12\f~>Vtb X$8P 2 Z]/]tYD;>[sߓ2| _=~#mڭlWu֖Ô AD ~sz8 4jdH.PiGD% }XwWvc{i7mVnY􃼙tW d(%p^p[vFܒ8q 1nD3fYA YFPEXd@^Z>~:qMZ}pԵ)n(pC -6s2ۛsz*@]A]yE0`dk`PہC]Dgr8i24Brϼ\͗l{4(N#!ny:Y!V}#t. SڜV0F0_= Wp;x < gOJI^(׍@&'(@:C3 q q?6q=lW& f@O"xmCXNk\<\U!gom0;@A$9}6Bg53 JgE4oOZA`2!NlrHc(iw&jPʎSwv_lλLW_>sШ -' K9EUy>?AV {)+wfAvJ Y[?ܼigZDۛ'Jv q8\; |z˸_^]zjG$Wg@H0~G|0仏;yMOP=3)6zi»]5E,Ug s&s#/@@x~`NsΖmz_iz:iL2$g&=yyDԩu^MH\/rd7:a036Ep>i6E;! %D$3cS!ձ#n<{<tLDx&D{͂EW!4[E3M---g|:s=)dC? RT-+hobz Y!$9jbJ~fqXE3g)tj߁-N-hu%V~I%G;6# ;νNv;ASSD!ԈNQ݄ÅКL!0-Afhahl|'!?8Fx[`;ݫk Nϫ5c95Q~PH0D JKb? ˒bШ[J*)hSK}zK 9ljaK l)`qWxQT.sq8 ;+@V|`ȈB!BK\a;vh8.L$p!鴹3n6o}i|>JQ"-;I5\hO1#&vldH|؝M D>Un. 6ZQ~߱PeMC8lkIݫ:wa8I&T^ 'p.$X vW,.778V/P_`(^0'%H"RfnE0ógD!'!Due/VSIɏ?VpvKW6/n({ C 缄ojpi͉Ϡ-^S ʖzEfԲOA#:xz/̯b}.$¨5Z³#ɂ3O:ns|VGb:M6eXp(xM*uKKb,̀%(`p0uC&gRBN‡jtxaXI?FGŃ-4 {#ånyΒ̓vE1&pPQb <e`)"UF1y7aYg,r,=pl,hp-a&#pП -HM9fnq{=Nkz5dSY7O!]Gzɶ. Feb'"ʺ}>w ib;7y)D߿# W!CJvmߋ=} ;m]\#@h%Hېܵ13m%nМYtJ$6fU=+[R] _ Le6B77 QdDwe`cmn8JyJ2؀hc֣llbr |1_bƽv"l :1p њvTpZz-scLw|w^v|dYlqb++zBadF0; {u-29=x;햂pTt˚;AW%)au%$ zc;`AQ pt!bOp3QZ+u%Hڲ]뎺` '4Z=̲!$N kɆ|ؚ$˥_'y? E1Cr˗5"mAfT,]z׼yݛ׼*: hcfv7.ҷFNsVԆH=Wu%;.!y%rب)7( P!dcAĐ5sv#(RQKm6T" v`;<6A!יZ{7 7b>@|!a ?,,(qZc0V\#-9j!R1Z; R+$R+T6[+;g#GU'mTl&8p~KB"GarVB"8/o> VBs6+~}SeٔT.W{,܆`JNNE%n Zv (ƺt':D-;hϡۖЭ3K~лa[k `Пܵ*sRBm ~<4lA6R Ex*%^ Fu<bC9|yy Sz"X2hDS^0zwdDk%'E(W"[̡W\X QMܣY~8!-2&#𻁃{F{Ɯ S[p-(QG%XSi/q+W 8EM>g*?aTb8?԰l vًӶ)`:gg 2 _Z68؈RWڞZޠmOV,ŝe84R+4VE ΜE$ydzPuS AjGłYחYY"/c ULqQ@D]S}uX (c5nP&m,{~"Q,C.W@Hm,_bd7T+S ִ\He݀pD?|FyN`BZWyϘEm XWܱB37\5b(\*.f}(nِFk1|]ͣrU緿獦ַֆlGwFJsZPwQ0Y(g :R]9buI59Ā5_͇l*:jOTNi*Et<5g3bLYQ(ǭUU!3Aڳ6NO2y\;|I>* )wнJ>=ܟ@y4<G ]+zh]js7E»WsFJ/NF3GR!~9]-'WP1}I8FKmՅ9fۇE~l~Gb 1\fjJ~'q" )DȮzl % rcnӲsQ0aK{ ,Ix W9U@ v=`}E*8/3jotmJ.%7l'{]P} ^(c4-,} K{rQcQZ 3C, ͊ pPqtDshDv 9=gKGd,V󥸷pr+yLH 7σn~-Ј"*iV%u4VӔ͋F`N`rXR%lPr˥bᮨP{~{ /I>RI$u!^ӎw%Ocy ʸNT.煡OqW{5*d)MrtfA4MC΃q h: [ Nr['`=tPV~i,5B,.a`PGYaS)]IE6H ^ł 9/ :./\&MyxeWpNItWLQ@;ʮF?7Uƿ1詡(5 E)*akۨDiW4o[C0S#a¾HڵL&bVxvu"k !!#-;˚MevQ xP L*=>n6Z"q0?i6^z_`2/F*m]@pp:%ˌt8dv<&P-aZiI7_K?>HMx`aZhM{Ei>qY}.j1Ү  gB}ǬDl@H+N#YvXJ8RWǃuC`2&L1w .wg]@DX#b"J?VIŀv媳&Ӣ'*j\me m_CƉF>Wi u{Ivc v=t> z5J3NoSPыD?+ДN@}6)N׫~@7a Z^ ܋F^Ljpy_]gY vy )-i #= tn%~ZAWDtF`ҁww)['h? R#"*ru#}vA=q/|,ĎQ2Ud_O@TznjZB:B"h}'*Xי ?Rk-vTO)~D ~\=dswtf+"Wre,]ĵVn-k\CET(\-|;q6L>a1J ݓ] ;up 9:h&񻅔 <(&C5]T)$hP^F W<[٫d; ,K5pDhzI0KaHoY ښl'6GcFs^e>T82ʌCWz ]h:ma`o|o NY1f}|Sg/qJElȩ1%ό5>V.ܜCw֚ ˬKFj{(892Ph#D7AE*^vQ R˒ OՈjPx<$kz P݆ 3I4K㇨}iM!=U4cҸ,UM9B70$wbFBl ݤ5qkp]"\W}:@~e K>t!-"JeU!etbemon-1.3.6/.git/objects/5f/7be63f52feb9881fe2a880c64e87ebdd1a205c0000444000000000000000000000141713514461224020236 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d~mmL?2< lrNfj^I1ó k_>v 1ٻ&_HIMLcK{d~qUa! MO=6eW"Z0ze_߱mv7r]zJf91e/ ONťٷr-/t4gu}*IO„椔XiTe?4&38xrUΝ5er{[NJ?Z}I@{؎i-cȉ- خ셪,G [CA܅J=,q:Ȗ.2yeAm|}TQX:fn}q:Y=IC6 Ymg,`v,2}Zp FQu~l4ƒZty[0M,S朧3JLN& c aiTԆ|B͒5[>! |!!0&ia26xTSL4INlQy.nH_:I¸MmGdSX NxX0Jd'5촄3v|e ly%UwR₴-/:ӥgKeŵMhk1`m)mb1D I̡ZTs|nvVģuWh{u<.ǍxNeA`6Ӌ{Q`&ѨB AhH.іIy*{lw}]-A7 xei:Y̧x1˯{Jx,&xuP;eȢvLpSaU \}aTw3U4B>5}&[H71Ff a3Q@Cx>3MƯr߅H9>v&b_r?`1{yS_̓x=,ϗ@d=1}P6΁y`n'#Fl38ʊY.3B0b`BhkḍhJ_J_LK\VZ_[t0p=g$P?J`3kgܠcY,~f{&Ja]\>FSЎ^xx8:vVs}^lvcqiڍfU\4t]YVHNE ~kfaAVt$Uŧo>Vejb`ˊW@\#< nEaۊ. ؏&agWF|g"Ih8iW6oZZM"VҲu黷b ܲ\!-/g9.Hd@/2-eKjQb.$pi&~ɠC3  ]Gv3mJ r2 ȁ2V) ]'8G2*nLWSqwz$$~7ٖ&YϨxEG!a9yŞ!j_xZX^\c>s ჭVգJ~u"{vlwEL~+JtH-3Uu*)YO+ya0I_ J,b^Z-I¡I*UVϜ>̿:rpTc5b&SYІK>|jR_' &Rm$<0 G7F|.HZR{d*)U)md1DRP!ju!Y&[اٿxH֬dYy e)uJv DxMu7])"6W`_PZ/?BkujskS͸}N.(ӏJ 6$Lƫ,% 6BM^{CT2LV'LUNwcO_z B7ˋ!1*AfĂB@9ˈ q 1+P-QYޞG7>@k>5e+Jmv0w' K KVѧ{m:Fa1Y_^<6 ;NԗF9)B L%\n6~' n%ʐ]g Ss:.4kͪbZ})_YOI߭XT\NRH;^nS$ߘ睞JM'M-@0"J@*^AӋ#2E72J2f,2L%*mf֍X2k+39WJj(kOa}E-X{r҉XAՑ ~BNI^96`gV)ǚO":6'ܱտc[ ck#ə#̄ 6F2*tiX!_JӊZd>Da%s F%Xl7_1ѢTbQcbvBp'h4*p0.D{Ɯr9Qne96!Q}?1*3/]LMXMkk6K+{ґs =HϸJ왃ѷ=vװLեU~uGVdԾ531Q\ZW:fmg'ofXI3^ݨ|0">-sEǷ=.>+beSuK$)"Q)wE"x-r 6)B:>X%1Ϩ 8>"/p "#Kj57Y\2{'~s>> ߸P6Gs}Bp\Jٿd#E6h4lݕX)0DyX0`+lp;fh ?(I7/5[>Sj)Gl4|m)Gcq'LA&9ž^,e|l2 r);1$l93%X*^ii3(ɭX)?a(zJl!5j{p>O&S_`z{{;.e Ewǩʦ\:~6QICoksq/vhSJRlぃe=Is#jP۱9Sem9wiEgq,o6.`lKqV9ug;] YD9=v}U5ï?yֿ8cʇPԏ0Z-nXN[M}YiYdYF1%bC&;caJH_P^DUT ?YSWuKɴkr)q&uN sǐmVp1q)mRS 6h+,(πߖ^ϸhVAd-7Sې? A"WjGID)Gp\d&֋0(@bKrZa+=ok<;`xp2}jw;tnz^x` :nDue+.C5~T@ki$UHOlj\OB4F7_8#eb*D<TX +44;kj_NcUf4},x*Zv1\<ʧ9ݮ2(W}޺F`cla^=PzY&\AYrW0cO~Tm4xKar3XAa7삣(luhͭ+!SQ<=g¦VriT*_6#%| )>b0V0/~Df|>Ee(H&*vzRTW%)爗S*s ]Շ TE;qcS8W#6~İϱ@ڻs&Q?Sܯ*KKLzY-.Ի|wHPB6ʫI\*ptwxVc3SъvU]BuxQWMzc;Xhr^ZRai_lΧϨm&ۍ.U۵7뚪 ث-nS”ܭ}!ǵnق.c-F]عЍh/Y޿&>Tmc%m9%\xvڭ?SCn&8t+ҵy܅#N? mޞ Rr}7IqǑ/׹]:\q[v'_ǻ<)Kj X,|R~e=&i#bsKmp2Z؄}ed dV8\M{n|/+OY$@Z!+.o†!{&| "[~Vq&v>qql15$ ݫ9!SXŒ= Mi{쑪Ķh͎gfitxL /^m[r;PWYS}pԉ lXJd|nV],x$ q(ZOj H n44);_%WYc8/_c?=TUYc^PܜR^ %SMH!NU4| -)m6CW<[pDߵע53B+i"ƻ̓|V(ОD&b4yA\oPsRz\E|DXT)7sf.6u"Wc]EحKRak@N72L㮽 xa(ߪجx.}u߼sM's|>"yr)a^9Z8U=ݯo7 ޚ zhp>}oްL\NjǜKk8v]:a??=ja83:V~┨A90/ge 6[=# K6~ێcI ebc (Q \'VܝP}>7T"De·fSyN[t!(jl\ u*SJ)9SԾ){syの^u4Z(6DvKZkV^\(JI >Ŀ(RD[:m@w-Д_ PkxEuE zc*B`ѥ _㪄9nT~j ޾Qxӄ+cǢ!1f~yj6v9ZV9-PGƟRtC%ZTbg\66Uv9ݤ#Aiwi6u.}_ i8e! |ɂ8N"2|iق]99 8lhӷb.rknRhӄ5MIIU2 lZ-|5A)CwU23YL/# R[u qBiW k,#' b(Fn>[6NJ>#chQԖD&aۖP6!%]9w/O`J:?!V h2>$^= <;"^G/1lF&[Ǻ@pm%!e:tlڎYȊx1hk; 3^eL&4K:l@}y~FBT |fP7.*flwG-InY,je {gbN b9L/:GcK⿟iPAʊ_ YT狎Xs7~G-22qe`\߁=&zcyeD\hU #;Y%9ϕ9}_Z@O#ܳI38:ڊ g2>N6nӱǘ_Y!G1R1fIԛ H0Eܵ)"@Sd~Vdڻt =6j[=FƓojG*frIc6 ؒw3mFIsOֳ|~z~g^Nm#L=rFR]WͿ0"N Ri(nhak -|ҹTVhtp/'8V6_&mGeHe/\4k9>W9t6 ?n3_WK5?z+(DNK*jvMXJ¶ 2RDFwlޯres~ʻlWr<TDT&:"ْunAǭcI2vT.*ҙN^Zk-Qo_U ;w&aXBGn-ؾlvmȷ42H )!^sC @ ICJV<&@)}RZTi<[ŭdwqxұjĢ&0TmM $l= ks*G*1#0=q*C]@!fdQ1rW.XuUàJ&V>=ZWUlP} {9Kk)^F[T<@Ν,2 ׀6X1&~]nW5p +y@VpK_OG8#;ײ4Q|('r+@VzL)7^i=(h%)7n4J+A9ČWۯ\/%Yf类$_B Vi@)K"{8?|Q:taQY7jR$޵Kㇲh{uJ yBQgŴ-#o>D*BdP5R}{ n#Pv+8xn'~ٷ)ՐD6?֍0z2qW刻*a{W&h6HP¢ͦMWԉ.NCV]sk]Og/s=۸$bۻNsDt-R^?^`etbemon-1.3.6/.git/objects/60/0000755000000000000000000000000014173220716012562 5ustar etbemon-1.3.6/.git/objects/60/1b9385f82a2f16a21bc06fa7ada74f8ddd96140000444000000000000000000000076214173220716020057 0ustar x+)JMU033c040031QMNMIexwi_EV3csTT!(X/7?/$A-3D7).HLNpЯxQĻlNg: 8@$5鷦Ŋ6vS~q֓vPO)W;?GqelM;[ƉFoS/~/#3>'31OoWqkѳ8s` ĔIJt::w.f`33棸qD=]a3mS)XAU7PWP wڱ טޛrͺTsĢT UfVU˝&PY[Lx3?\6/zہAV!%&SS%%uN׫i2|Q1= Fetbemon-1.3.6/.git/objects/60/5322154fa8534b3f15bbf0345fd67f3cfc7c030000444000000000000000000000025713514461235017710 0ustar xQj0S- J,P*|Y6xdӼrEL mT?h'"sSSRP0$߹áܵS&4Ys0ڼL&PkK3fZ8gz}UzkX+Cetbemon-1.3.6/.git/objects/60/efe50717e31736168b98f705ce984ecd347d710000444000000000000000000002673614001503033017606 0ustar x}rH![uZmZײw"6V  PzΜ:q^l/ /'glK$PY,V xYh5:^YEfe~q,1ߙb9Xܖ,m0^$-|0,7$e7d,=,Mfgs3\yp<gffg(L-) 31h8LME46LYt=|^E"8Yg{Edr`DB<Ӓmg)J$4i8b.g;ƀxmq^2]5h6`AsoȷZZ(8M61"?%1>/2L(>NYb+-j.k:(AТ ^ڎ˄;rRM,vmN<)t"ϯϡb22fy(n«z2Sh<aWX&?έ%jAp* m@>9YJ80l =Fmuef Pe~Q2I/rqC~@SXlW|Ks񝱤=/a<** ڵaaouMS<,E>nh)ο;5x k}RSda"M7%GR{gBpl[Ge+) BƳ[p}q|/8`SV6e0 Awh=Ʀ@9nz TbŔ4ǹ֟ sC[Uf WqȢ^ [pdrmJG&3E+}*oe\b3gI  +\b+_eWU`̠@zX\{O&JW ,{ )q<l.8Y`[\X!uP#!N KmrHR|Z!w@nf@ Gf˰hʕʌ|R4:naP`lh￧݀\i/*Dk0eW?b|m7'goe.T\LIQ,cu(򒶎74FYGugRʎb5Bk0i zph,V\7+ *]qYm',o]L.fJ#-3Z&bx˅|k: i^  &fPa*dy=ˊ'Ws'}EXxz|j5|/X1{@n4^ESBW}lD#ZDF<2ȉv%)iC*ZC AG:޹Œ7$HFEQBy+nC @/I,Lj@Xs,!dMJٶKX^Yǖ|n̛og0@XT@*s18އ\<~CcvbA7ivuY2츸ghjL6𰄜QDZmTP- t9LeWf_Mk^ ?b,G =QM6PRauvSڌD!V@` K>RR>{4kl =n:cɶ m*$l>X%?K(wP5!I%`t,yZ*$&Fz@SC65vuRa0Rr dSl5Pu^Uen_aڎ3wa*qVq%DbR۸p4ro\h=kRb5 ܇O*4X~t<|?ap9B^Tcz,!/MP[']j ~Sm Xԟ`' ZuIhޝ|GT>}<6% VNSҜ'< pb*0~0'R)QM9_^ w=LH'YHSoWAB 5-&S0-=rīb)C2a:Ex%eS~Ws<>mUu)3XƏAߖ/Jf\ *kd=|в|S͚:oc ^g 49]F %"fhdl[B|Woֵ֘2WJ5B(*̿i䉳(OaufU|[f)y`E,V`t?\ !wp^sLI+(qQh逞,WuֆÐ,X:b((ӨI]AOI^ٍ9tGFV!$Ox:6'ܖտ[;N!aA+P|]V+=R/(z-p>7 h+PdG*V9E9<0p2ڛo%f𺪨c%ZfKSmoM^.svʼnes=j9_ ݊9-ÚZAk GbNoEKjUK"܅0O]hsj_n5Z RWAć|cUk(׍@&ǖD`p̘TSzX Jƃ{JfA-uo{>S-iv ջNrμr/qBM`IjګmxhdᎊjApIfΒ4]ljy1O" /uGμٕf nXI] xEfqɑ|y*r:2U;FO* lm@j佔9Jrgh/`;(]+d$\~3?Yi_ZA[cvszgEJCYMV~Gˠm(tPvMjsuý~1BFng01МeءDsdY+֡*Wd:vs+$f'i0`Zaֆ~]~lgfg?;j,F#Huv_>2d$vUV-+ 50c/ar;|f7ҡS ]J`DǸ QVOTʥjw}};l{vMum藟u(`d$>5-if7jhXJ*SP|=G[|9CCvM_ }aS Xb'޿CqEQIC aJ"X%2b#!P8ťd.:o~\Ey36 cx(YKׅV"ԎhFL~Cٰ3UKXnmO6 gR/"1(4̛3tG@?/Ct<]U5Յ a8f'/k߷l(TY_[hx*{3@'0mD3O/IacUٙ Uə-&n. U| ;K@r{p$a:>ׅfx|~.~QuUܲcs\Tdُ?zvKlԟDž3PQ 9w^z y'եAoIz94Wj:@([앙AJ>AY;54[^痳dRƗ#Ǯ^ɂ3O:ns|^#u˂[XFl=2Ta,@IUG20>rz(&>T˦#$ۚa%{bVm\l30.p;81Cd[e'2\ Z-ଘhl&@ҥ'z͛'޿9e0hn2>Y`mfvw[=w"\Օr(bQ=ķd!57P#[]j?BnoGJ*/ HZm@QY 5Ʃ ѭh 罘.iĒܫ"gAk 4֦JXwYLfl 1[~Ԉ~`S\Wh^h4= _LЊVPyk]9p(3AbSRYyΗfEVN&Vq <{_ 8x7JY Z0i/yDv>TTHH,A ڥz_+sK)9F][iC4QD2~o ~hk-nA$%rCX dֶ̀hXcK | Ąj(sIqj.R*?ٰVhZ\Po#W$Ëb=F PChS'G=JhK *c3쳝l^H6)w]{|.^pk;U rڏVfbC QźtՍ D{hm^ЭSDi;k?v  3BB96^P{4փl >yix2!=x Fuwe |uJB/Y/%VG4hhGqF$ʈXC8[r?8i5-Bʳd͕UhMMhi5wq\\A+lu+&#s2q}s#J/Lmn酂r磐FQ}< ugga bܘŷ֍C2d2hhBčt+W"]3y& ~`@=P-NS`DIGzcjXB V"2Am}q%'"00C"-PAwhamZF=rLl2NP57(~;Ƈ_Pta?#iF0Ѻa0d&Apg3VlC wsfڥN-a1Y .A~S5߁V{_c׫qT^9ay~{h%w^h풊7EqԃV wT lN gQ0^(g :J] |jr ~f[1|hjOTNi3A :nEvHŘ Wtl5@t7CfdjOY' 0 +C7+F1,~lC+٦38s2Ś LËp)a^EZГ5;EGsFJ/F{~)Py\,ËP_!KkV]C}HC8GX',@#cP6+#.Q^Np+٭*x M6Viٱ(pN0ҹ= @[PJHYxϫ GDi$!js7]{N%;4!@Q<(!ΫD1/A Kɕ9Gr2dd*/aDYãWm&lak_ciQf˩ÅmDw_(!(xbMz9oͭDV 9=g_ȱyl8ZV s '8h,{p/4ѱ[fI/t(fURgAc5M6 &%Q-AHnR p#rLPgF_L}&=JxtIu-P '1Y G YpViT([BT,8`C`4ӓZ:Ǔ,j  U0Op&؇cz!9'Yyegg'\2nkCip}; "W)dDLj|BXVw>vjKdvf*&%t~&ls)8XdkE/h=e-G`xL[]]!$W288U.؅/DvAc)~S)¿#N(@]ws >1hum*t.x?jQ{2F♯)B:hJdp(H,בP"{c)V 'K5#QG>tAɽ\T(DZ$m{4`qȇaAiWn4ceɟd_Odg,@ȈLC5i-")3exc  Sb\|x?k^yDKkǚWv~|8A)AweW2'(˜pdp _ .(5u/F_ %7> ȟ-eveo%>V7C#aHڵJ&_AV~MD֐B!%;Ssj^akV{_r`ZGW$Ugǵ1zPNYпdХTlKTױ- BfMic/lqf0ɛҏ&;{DP`EYmM|ua6H)Y (2&,a! /KdZi` P %;n_8qՕSFDaj|>}?Jq0;v ԥe(C4݀MAda/PY%];γJo~rl:3qvZiמܯi:fe~<7ϴӘ} m$:idYaR@(Vt|Gl^&QpdvմBB 2_fa_q[g.@wK?Rk-v'Yݥ .ebp݁5_VXCPmvZN jʟԶUjѮg dw 8"P-ň_hjGWY|6{*a:+`аVNJ z.vLF3d&JAjD&ٗjiQJE=J(7ڛ=ؠ޸[,tqg#1IHGQ#`wD#Μ'E\kU"1TDzˇqv5缶{O0,M|&nF]< $~.%V"fJ9EVpˈp\1G+{LNiw zQ thy D4)\*`4Tc ۄ{/ɽ-+*Ōsedj' sDW ].Ivtv?A&wo|PQ+(ܘ1v rJEeȩ1]!:]1%}j B9/mK{Q3LZEl$}-+OAa܊4 TWaVrT5:/աɗlj?$^Wۮ:iH9`y K]ݔK(J<(AUsLT ɟ~:60f~2Sm^ Nw"Ѧ,({Gax-׃/ .q0ժdD` kcQ]y(<}szT`tW L;~ڗbj$aB ,C{+(.KwU:ߛƀFڛ>B]!H7a\Qǚ87"\8-zT)VRy:yF܀oށxbNDcj"lh D0ࡏetbemon-1.3.6/.git/objects/62/0000755000000000000000000000000014173222045012561 5ustar etbemon-1.3.6/.git/objects/62/6c59aa78653941efe2e7f106fbc90d8d8542d80000444000000000000000000000141713661360226017753 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d`|z3שܩ5jϜS 5yBds2SJm0] )5*DEJjRfb,OmwsS|UPWmro}_)W,;}Ԓd<,mOC0uW6ˉy\\.;_|=fnN~rb0,Duջʖd,** g/].Mc=dh+.HMf9pb宝˫;) jFiPA ˌ,f~ wm1DEq 0%.[:ǐ[]+ UQY N/ y2ּ?)$3a^r;'D=b$k1_Z-etbemon-1.3.6/.git/objects/62/911018d86ce1228d1676f56de07a1fa568fa500000444000000000000000000000141514173222045017556 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)33mꎴi;Ȧen얖 ȝ+K哊-APo1t6P5~]$b QQ\ g=lǴ˖Nx1l BUT# B@}5c (-)f QOX&ZWdx( [etbemon-1.3.6/.git/objects/62/f3e7da3f58677abdba08f4426d0ded7add86760000444000000000000000000000267213764536707020262 0ustar xU{8Ti1R3LD.i"c]cZcҮ33'39gΙLzPl)jʭQlPQPֳ.jU[93ss~G ͍݅ $;B0cr s n8w4tUARG$H!pD];1~[Wϫ8A@(؄SnoȲd&eDy@(DuPWYMIG U_tLBؑKV!7VNi=2pRd-F(t`%n%qtk};5N`ѺK)MThZ>kt=`^q0{0ZyU6n[ߺ x(( !wA'وZھjȜN:*&&A/nLRo {[^`) zS}aH1bkN7KziX6=cLSvbPe ${^x,ȼQjSxP E0O&0UxΫot. J7g15} Fȶ UA^Ż Q1ǖ>;r qU jR1 Š:Ќ[iH{0hID8sVݥ~,㉚d2ro[͔*[AIQvd0?9%M;hfpyo4*W* \T&Gؗq-`p؎<5dy0etbemon-1.3.6/.git/objects/63/0000755000000000000000000000000013455034657012576 5ustar etbemon-1.3.6/.git/objects/63/ad884698e868476f4e3f9fab707d1e81e25e440000444000000000000000000000141313455033406017704 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTPv.hMvZh)TIIjnANbI*Cպz SD2d&XS,c'~dML+)fx4w'$?<{)Iy /;?)bzFI1dAʹ 2w^ -ָ"ZP={lv_}f<M苛=^1ofPh'':O"sC*X* W+f^s\}rn,G[W\/s];WM;wSԌ Ym9v+hA&!c`8a;K\t7!'8/`V) n ^q2e{yES(DEiIfN1üow>hOz22Ib"#Retbemon-1.3.6/.git/objects/63/cefcf64f438441cb40c26dadb36566936e446e0000444000000000000000000000046713455034657020027 0ustar xRJ0ձN2aaC_Kd4,m$Iu{Ӵe>{s=7  :AŠ [ ݗ.hfS.C2 Иd1.SNqa=\KAZ];?V6дRgJJIOB| E Ps^?ސjD(e r0lub̩Ԉd)4ShN<"*#Ls4'h<ۭwܬB@m%Wn[椻V3^JwOetbemon-1.3.6/.git/objects/64/0000755000000000000000000000000014057341606012571 5ustar etbemon-1.3.6/.git/objects/64/7b98c6889c07512a091eaa661ae6744b1c7cf20000444000000000000000000000026313212011550017632 0ustar xA1E]$L"0Z=Ahwt?q|4Pd62M\dh }PNg$CA >:{KJQ'.9JSDv/< ?SZw*䴂-u;_,3éL|cJxPetbemon-1.3.6/.git/objects/64/ea264393171c5e6c8f28d6b2abfa90852feb030000444000000000000000000000141614057341606020003 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3'}gWuO=%RlrNfj^I1ó k_>v 1ٻ&_HIMLc`}7_ׄ7eöpȦen얖 ȝ+K哊-APo1t6P5~^-Fݦ7UZP!L)Cw}҄=kR-}Jz L~4pX/xG&Qz@ac0>.͋TJ9?-3߹DG/ؕ̀ªP>ZmHU_@&62[Z@}Pil35YĊ͂ļY,OO ۠ko%gj4"3\4f,Ix .kUO3UGu'8ԣf=IX:.71i%EޞH;HwV'VhպwE;Ĺ}D-oO`O֛(Ao Z͌&p+;%CԪQ@k>Wφ &dk4 'u#[7URԿ̸Np=gˋ7%h&U5'i| Mz!8ݷ5qEh` :]x@gl#wa`J?,̅1~_^y5<4Ȧ(?etbemon-1.3.6/.git/objects/65/634c8b1dd5c53f92a8ed71a9db7be478bd159b0000444000000000000000000000022013455033406020147 0ustar x+)JMU04`040031QMNMIe0L%nm';rvA$e1xu\YTQefeʳ\K.(`S&7uj)߶AV!L<@}C =靖 ~7D>etbemon-1.3.6/.git/objects/65/69504f9e0759c3ae5556e1bc304e9170745a540000444000000000000000000000055113604576020017434 0ustar x+)JMU04d040031QMNMIe8;?nN|:/wrq7jMMJҊr2KĿ2sIt#A椖&uT]s7э9FVZ; z@{QQAL#qeliLөC2]T$h;ZD-.y% yVnDmP< H0s;8Νu NH#>~X?\vF/bUƨ@m[etbemon-1.3.6/.git/objects/66/d155e1e7b41458e93472aa1f2d9769384db1630000444000000000000000000000132613212012264017504 0ustar x+)JMU0`040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35ݢ{%\\q7tW)Iy [x^RQosIϸwҧ@'3<t,/<O%D6$e{G_ E8,I,ߘ)N)#ŋ3*iޘE2]\xlbsSsHj=Fh12* <:NhQxԄbOMOo__iYYy~f*ҡ?_ dpFDY!3pJ:-;3 Puyx[=fsa%)Dw2e8gNm!19 oMR(} k )9NpaVKd[bL',2>SŒc*t0UQ>4OiWk'}F1V5!o ~ȃ\=+|gd y*ϣ$1L}1 l~4*:5-ߜ/31lͮ>}Oڒ֣dlXJW4ѳ/|#j%._MCvt.NMeJ :f{jcG͇v:]&Ya@:Vחz?Ȭ6Lb n18xMNAuɃL&20|ni.x @/AP =%DOcL;I-Rȉδ%xhrj -hy>`{ߺ͒<CK8͠>b1(dJ2ntybkmBṬE u@wi@q8A$k\av=N\y›p Oք߁Wi!S< :Z䅄KhSa p >xl^}b:qqD|p^TJ MA {.I<ƩвAƼq(xdN`d_{UR^e_@#L| 8WE /S'!MQ"ߘ2L$mFyE7 D2ZYʮ|O ٍaA%oTFcH f=[zr :RdVK'S圓 7S@DYFTk 14ʩ20 Yǹ"5)qHxB\/APe^VQg&p$*\#>P ޡKU8 ..sLly@#J1]g )t$.+}08DX9&(,jʥt^RqC efk aG_ ڂl: Lkf )4༪p<8w{4|,SQZuFSrTs9Rį HD&Xwɗ8JxH?1D? wTY#ek:uR>ɶKDGuyXMm%%Podm;<(S¥7w͢W=[Ds~g>ET@nm;"`NƧr05a1 M* LYR*wgad@~Xގ50a o9bS FY-j*jyȫUOi왠?4{(\r=o󗵔.Qv5*Sm D,'؉%C|bt|*X"_68!$n#8O K?0'RXȏ/7&NBAB Xzq&.!?XEb)A'YGDl8S9$=Ws!m]Yǽkf|c?:};Ẍp9@K"nU6 ѻgZTb :smN+w#s|ȯ +ʈ&aEj<:k<4E2᎒jpA-xfqj.b5sШ -' K9EUy>?AV {)+wfAvJ Y[?ܼigZDۛ'Jv q8\; |z˸_^]zjG$Wg@HU3~G|0仏;yMOP=3)6zi»]5E,Ug s&s#/@@x~`NsΖmz_iz:iL2$g&=yyDԩu^MH\/rd7:a036Ep>i6E;! %D$3cS!ձ#n<{<tLDx&D{͂Y!4[o3M---g|:s=)dC? RT-+hobz Y!$9jbJ~fqXE3g) zj߁-N-hu%V~I%G;6# ;νNv;ASSD!TNQÔ݄ÅКL!0/Afhahl|'!?8Fx[`T;ݫk Nϫ5c95Q~PH0DJKb? ˒bШ[J*)hSK}zK 9ljaK l)`qWxQT.sq8 ;+@V|`ȈB!BK\a;vh8.L$p!鴹3n6Jo}i|>JQ"-;I5\hO1#&vldH|؝M D>Un. 6Q~߱PeMC8lkIݫ:wa8I&T^ 'p.$X vW,.778V/P_`(^0'%H"RfnE0ógD!'!Due/VSEIɏ?zvKW6/n({ C 缄ojpi͉Ϡ-^S {EfԲOA#:xz/̯w}.$¨5Z³#ɂ3O:ns|VGb:M6eXp(xMjzKKb,̀%(`p0uC&gRBN‡jtxaXI?FGŃ-4 {#ånyΒ̓vE1&pPQb <e`)"UF1y7aYg,r,=pl,hp-a&#pП -HM9fnq{=Nkz5dSY7O!]Gzɶ. Feb'"ʺ}>w ib;7y)D߿# W!CJvmߋ=} ;m]\#@h%Hېʐ13m%nМYtJ$6fU=+[R] _ Le6B77 QdDwe`cmn8JyJ2؀hc֣llbr |1_bƽv"l :1p њvTZz-scLw|w^v|dYlqb++zBadF0; {u-29=x;햂pTt˚;AW%)au%$ zc;`AQ pt!bOp3QZ+u%Hڲ]뎺` '4Z=̲!$N kɆ|ؚ$˥_'y E1Cr˗5"mAfT,]z׼yݛ׼*:]hcfv7.ҷFNsVԆH=Wu%;.!y%rب)7( P!dcAĐ5sv#(RQKm6T/" v`;<6A!יZ{7 7b>@|!a ?,,(qZc0V\#-9j!R1Z; R+$R+T6[+;g#GU'mTl&8p~KB"GarVB"8/o> VBs6+~}SeٔT.W{,܆`JNNE%n Zv (ƺt':D-{hϡۖ^Э3K~~H-z]0O Z ȹ  6^W?Av p)y"mźC\g1!N3/ h)0lȏ/@ڟQ a"F=uZX$~U֞`uR!U/|$^ASntZv. &tiV9i6Yy;?745߮/(^e~Cm] |ѥ\;d+*aDY<իve2%V﯁~cO3jL#:Vkaf6Y ޵Xi.4;Aյ4Gsi ~wVcyP@1\y;VG<9Mc j敱;^_..? w]%QiJLv\H- te~wY$YlRDy:½8Xd/k稛X& :l"go(my4^u+\&Pj NK!S)} )##D?K4wq)YG`A(i8<}bpT"T2Ki uk5R}2F/ t"|Q$B͙X̯3D9wc)V  pQG>ttS,/7 z4`qȇaAiWn4j/?}=M4F% h=+;lqq*3e+wԫX0?\$'|eAEQ$I3|@)j0) h_ٟ7(˜28=5u}BWA1#Y% Tr z>rʟm gh݂gaj$SؗI ܄[7״Nd` y!!|vd\rcYrC9J ^]ǧTMv@R"'w3P L%h@We .Q]Ƕ$pс ,䴀j%L+;ik '쇕!e 05zښ6lx3>Qfej7+CX\ <ɂvQAPl^삡qg;CR~B.F}u%#rJQZ!4hV f.ེ^Q`y!TNS h " {g`q7R\srv4FRfJiAd{ب!hKHoΥ@flr;\ "^UyV9n w i،"Xn^|xuo? ȼ9(FS3A^w fLQ٬g#-#DMƳ,E_3*h{8;6 ~(1eٵA-Pf nJV+vl]J+`=DS/k(c՘*b th<+ vWR`=HRLUOawkI&U/ ޱdD6*b Ük/LiAA[HY̮7'v8GD؃:"L+iȲ0'. OE4FCLhyҜh hip%I{$˖BI[jY?xnwZ?vLyڄ4FnU KydU[D'*43\udZ4DRK`p,dӷ x@q8֝6*@aa/Ɏ`r^uAfBrfm jR?zGz &ӂ z(t&,9a߂XK+A{ȋIۃ.c,.]]>%-!b'.wP+L:.Ec \4'?|?c__W-+Ӭ44 vw"$,IJQ1{euBK\3n$`$8n[,gDDe]#8.tdֿ.;:%cؑ01J>pK ^oVMK|T@RP:vt4Gjڎ`)ԏt/ lΌbr]jg2U=2RSʸƜmԡ]3Aw7azFVV;O쭀\6Pوj; Ι<g $J1Zu7jXֳqP T*ufD ǻS Zw'hc`-УF"GΝ֪{k %wqu5p^;v'1,F{k|snNA @$~dVùJ9Eˈ*X^G+{Lptzɲf1.H0bM@4 fICu62i< _[fpoh0qΫG GvBbCOB M-l3-2!)4Ƭq lŽ?Bim95fǪӅV;m^Ph&-ʃjd@쾷g+ڋͤ/(␍{lFq[BjK`*9F*5:beTR4GRva`UW#0i{53,!}W7%fO *W1B?BgZ3]?wuHm?\f -b}r=H[ˮ17 }YaYXjY2` ჵQ or_`=Qw?)sv/)ܟAx=PQ)g+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d`|z3שܩ5jϜS 5yBds2SJm0] )5*DEJjRfbC~PZMaoW,*Of6>۔+_{ljI2k?d}}Ƕ'ڡcw+ <../HD3PV7'?91MEfћ%ץe^ȁ?n$LhNJeFY Ch^qAj2/ρW,w\^5NNP3J+ J\f,g4ۭk\!*K /q O8⼀Z^b`|05tz]XȔyL%9 ÿ=!ɜ$Y 3:XFetbemon-1.3.6/.git/objects/68/0000755000000000000000000000000014174476713012605 5ustar etbemon-1.3.6/.git/objects/68/b537901d9e1f3ae281cfa980c1e821cfdbd87e0000444000000000000000000003030414174476713020163 0ustar xvɑo?EHj {D][Z#J=-EQBb" "ٶ%@UVfd\:MC٭7[}_j~N7l5B>$4,~:_V5[N2tLa4&ϓ0IiΖ0^lw둆2ϊ0Og|t`ct>gqX$r<A:mӰH_0-3٢x.-p=LAa6ZOy/&[@J%|\-z~1__k?W!&C01F^ޫwZwځn,&er>Jw2Nɒ?N,p%B{5ի{v}k-V kWC5%K>fb!NOQN8c ϖٲLZ7~E՛av[].*_G:d|ɾ'՘cKjQ236Z夤"d/G42xM8aͦΦHNR՗ M?uW@(^իտv$J}К). RHL3F p6Ͼ,ZTڔdUJLTf3ROWKӭ S5ȶLGSD ᯇ$Whwƣ*s݃F6YE]KGj@m2V=w)Y%kMdĭnV]Es S& Lh 0=7J)Q; k~Jy6H)B /l1%7пOWFD{ ¿7B2O<]̦rhãGP;[Jul.k־zJ6ƣ_q7Ьavn]͆^0XO Vu#]4\' ٦t%-BR>pqe}g*)J$876,4)Fu }2ًSKhZ^ ޫ,K4a9q8f0@,d5(֢QЂd 2NPC&n8*vg6_nڤ7)tOGlq\mDC4.Br-Q,Lp)*ƃP{Lg*j 1G=]z 7MfLBM~j!g|12Mo==]"'sܧ|_r?+A7,Erox"Kq*fp~mmXė}\n %ƃ@DRt>2pˡ2Rd0N]SQIsG|/𘵰P>D)(m#;\rq0!䙗͓Enr: ?|`N#`&#b5ƺMĠ<@E +Ld%@AE3b]AHN,,=5BpOBmʴɹTHyH˜yMLc2zԣM2_`'q+h1 lT3Y`$uv{p͇Z8)ylv + !}8Kms"{)d8GndzL[VIڰ+8 ŢՉ]>4%bl4/]");?GĤlĶǷoNVd 6^ï9"ѫ̕_߿9c p!f&_Q# bO:Fbhl0v2 !lB9vf;ڈOL^yʟM5&'Nڵh-ۇC{-0owb @*Z^K~"|ɦEh`4d,t2]]F0ZKka!BIrưBuk&Hr;"mWqtJ V*ſHyҥɋ33cx16+ m0ΖpIg!dngVQ^=2R'e?zd?{wa5 93)F"GwcmhsWCu \H:Ɨ@bWtG֒sӇp,*@~A': !\;ځ{҂rN>튻KO9>[1&TH jAĒlD^sr9HRȠ˼͢E87t*$!z'0йAbs~w# a19#wL&d?29a-&n\8 Oaئ "O\(>9X3cè?dJC66'-$HyPlO=n-[\z%J p@ VҮuo#ta\q&6˿8mwz8 Ҿ7*^#\ё@H`O/M?m\]\c>s[ `K|_] [b"Uƿ%!:$yFݪ<0_/b%Hh.5oy‘s/Ϥ6DX e%~95.ϓ1O^$ dq;fv81 ޒv_ń\7Y@.sn a;{K<]"lT 2rM 3 ^z7z!6^&t;F>MC~VX[Z"\lbq $[yb ś!eݲ瞴fmۄzh&*#EDh@nmZ2Rl~Z.N0]~:ZcU 2&V%V#O{x@J2Wț}?BOѫ5wF?0?ȂP^Zn>5K+iqE'hvzbLT5xؐ(!1Jt.g5a-Y!~UxD(#]WtI?Nl !:LWR L2vvoo\?=C2=,F'⛷tkYL ?]y"n7DwKە"|J|!q%fe4*c%^SI73@9zw%3?b'cs+غ7X2.< .b4JV=xZ#n*,sa2=D(`\ Y_6y2DZ>:Ayх]X}cMz ;IL, N?# |F뫸rA^f #q p(*Hysd0t/Yxfn~Sx%ۮ7A:H((lw4!٣[xC*7.!4:ˈG=}>87z˳N֬+ZY0ջԥf|c?۾ǹ6 ;ye؂,ըu.t#$bF#]{aԝú_&|-be:'5>_όdP1gўxK'2Jy6SvhES+256δ҄UG逎-u֖cH@ ~đY"6]bԭzI^ۍ9.`!%O<:'ܲտc[6F3GqhŎ(u3|` Zp>7 h PdG*[9Xel_<gϒT>1Q|QL8«JFQ`; 8D9Q/+H2gU{T fz4XYRY|VU%4mVʳJȯ'{~Cu53\WuzJ&' *6pEFJzbp=k?b:,1g=zSCTkJ,9 Z͗dT)l ' &ܜ簋_HF(?D?M2(&Ul@Lj=G$+rhZEs`'uwqxMf;[Q%R o*U3y~Mݷx&l(%PJb'{YI`V9o} Ӭw VY=nNoorIC(ih( n[ydiqޟcr:]_rFpئ.~i2`!'׊zde.ڟU=f3WCu¯~xndg9g+,fǓx""{Z^;QK% ;E,V'A<*<9/BmwJ{#U&"ű2"h@i+vH䢵0q, Ɉ^?WP.Smض-ѯLazQ007$k&r{cu*ݟe^E$'ܮXŕ>xy ɂm.OŽh-cS[ [""פ:nCٮ3xa" z#ԩ""Amż`E8,"\--k5J~yJm*vmֿ %Q.bFYd9:vk)m 't<$mm"'9ld"1PxYmz`<#`5۽6x)$w1@i1=P.{fnGk*}00~ؠ\[h="3L ?K @Ȟ9H`};{͖)tp_Qߩl]f96߼PiKa|ݛًKZԣg7JLa }@\l 'e)@8®[,LfOϋEqZ5 96)yF8 "BZI%gBٗW"~8_/#a[WʖhsNߟ|QN3$rK6Rds$Թ ]91yE7TeAGE8`3嘺F E5j Xvh\sivIЧ ?* N ,JΌoqVW7ȣɝX?`(j l!5Sr{ |,<|!*l^o?Xp [V0B.trר(ʥgZvkasLTq-{KyJJj8]]V4SKO??CMCy%[,9P V<5f^| ͳ̏{zA29痣L/UGnO\³#"XK. }t8j<+{b'2M6e! QyX %6%1BfPmR13+s+K<Ňn|laXEFyP;Ndҍ2XY2٭fq"RfTD]q*<"2Tdg)IO}ޟ̖2Airc0n4 fNa1V<)[ck(O1Tm֍d^lv w,fbPgClLoEѹ+^]S19q-/}Tt˒lCsdclDIw̮mѰvt &vsNp'Ν."BL S[H1YSCəDc-ѢJbK0 RS;g 쨓RwRűF'[ jUY4*H Voȭieճ.r'|nu f MDy/Og ufuXGQvO^B^;l4#x]B#drX'&jL.9O1&Yx?AiNXhδL]KT$h 8K[9sRU;li{KKkBJUa{~r%C#H ׶p4cxt?B*ұA5Hr_-5I}KjQ妒(uMn >-(-1bY>C_޾ G7h9_tQXFerECs B,ȫlŅK%ZI_#@h o\Q\b?7ÆUWzL #*XFmDVS?lm>!zmJ*r2=7K*pP>mN D[ui-+h޾[v B%sa[9~F[VDv֭G$r.Qr*gԱFPm(lUwso͵+[yJy gLMYeqhtɪ*n >|n6ʿY Z+<z3>ƒRTtKTKP|4Iў#^jO)r[wZNz>͵uhI '7!G,nAßb%tWD.),LP߯Jl[LWr q-QBwb \.v*?})WxZ}3ST qU\BMxQWlujc8'X(Ds^ZP E?;þXb ^_׬n<>ٔTM0^pB~yRݭ0[Q5ZB._wqcV@WN~MPƶm;U}J&z4|j6MOd_^`H#r~M:= yÇw᮫>OE6½\,d3ra"]sLOxTGNX@#zFgPJQ7otVǬ^>[F|5AIFSnun7XH,lQJ$iQ<+N'ǩ(͹ۨZ͔o?B@QU(#+{5b/ӎZZqGLpc;ڗe@^^\d߱45Я(1(ZAzZ|΋ m/[Y[WbѮ7vԲ}ap;~xP-ė'a6 <VV:v:䂞QY*ptW!abrTRhZnP q#h9foQߖgZqwI *X쓚X{$K0g1܆:e܍\TNb觜DyʖBV13wx1l?$߸@3f;ӓ?[|唵: P/çO?3XA<C;{AU+J8Ū.tSe5^en,WaN$)Q>=De*xM, o&!ABVOG`xLj1ݼwU\e8*_W ř_ OʳQ :-"/Wu ԭ-$\؛i%ހ/}V[S[Bf:ᤳ&<6gFZlƋidEX?>$v*2aY:U>%c5}W{)0C8*3RJ' Kܯט|1u8&%[ 7C CYV*[nDM#N_] qLN} )je~*`Q1a[$&S+j"rZrO7`yS,.4[b]j8'Y/iyy/2xK,>SV"YQTyTnM6|['?;twuGʵ:hsG:Ľhd=8p`Цn6|C`[?SjjoNKFlD*2c1EK#+6sl[HEoRN4gv8DBȇˊMzȢw?/i =j5=#ړUlk = OX|lGN#VX0Jj; =+7D? a9dm禮[puEzU<@D+ϟexJ?—EabZ|RTFhpЍ t $[dtyX.xOa7Oa/\j0ԻzQz= Mg/PˑGєF,G"ݽ 蘿pKz6x#Qi[GMt9X.ݕ\'7eIsc]@5wo_+xEӄNg%tvW[9~]!j?j0/ e}XWӕCE3 %EO/oh^VVŧɌWu7*[H}JW4ֶjs?e9b(MtFGeyу;ǂ(71]^2G<*/:mmfUk@U6@eO?mb=Dv/c;擬rN@tj 3ڋ˺¶~!S{etbemon-1.3.6/.git/objects/69/0ece4d0dac09654c2d10fb56d0efaf533cdb920000444000000000000000000000025713673303315020267 0ustar xM1]u*evT JwO{R]{mݮ7f@MTl :̘l XE Oj`ddHR[J!;F31%Aoe{xY>xJoܧi;vz3RQ}p+Qc YNyetbemon-1.3.6/.git/objects/69/1330cbb1df454a0a2b63dd8445f9fed320a5660000444000000000000000000000042113604573531017763 0ustar xuN09) DRUE\)RJ\!;B]CK;ߎYrzutڕĭ+e;gu.]#ݡjEÇo|p5W:_b Qrш:a"pP4v1,{ɮ:H14%LWCG@ҷVcTO/DVt-r̰Ao@Gty[GUc<MHjps}B%N]La}gl ִ etbemon-1.3.6/.git/objects/69/d670e2c5274cf9ab6b844ced166f481b822e590000444000000000000000000000141613767534550017760 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3B(GaVvqlrNfj^I1ó k_>v 1ٻ&_HIMLcجx%ScJ3uf΀*Of6>۔+_{ljI2./1GU;K봥VnFn~C9kC>\Ǹ#"fnN~rb0,NV*Ys S{N'}~~>"j./NoAh^qAj2lḵ2=_9f>Ԍ Ym9v+hA&!c`8a;K\t7!'8/`V) n ^q2e{yES(DEiIfN1üow>hOz22Ib"#BAX etbemon-1.3.6/.git/objects/6a/0000755000000000000000000000000013775160026012647 5ustar etbemon-1.3.6/.git/objects/6a/5ec180eb0696cb480e6588a260aa810446224d0000444000000000000000000000145113325231224017537 0ustar xT]4gV @ "/RO0Zz1@ܲG*fo goqZQb͏w~w?'\etbemon-1.3.6/.git/objects/6a/8ab1abcfd60675110b70b9abbe1c4f75bce3080000444000000000000000000002572713617253305020265 0ustar x}ksH~_Q!{C[uZleODl$A#`dܹ*|X{bmxTeɬ0Nﷺp,3֬swgWbV4\qOƼ0_ (Ehaa؛e8yQ4 b,XLC7Wfr(Yi㑞g>,c& S2տ5~04:11덺>w_O[s"˃ax$щI"Gyr/i8IŷYuWy83aEpdq>~W(~s?yĔ՗fKȚ} *]bN@[ߛhHМ41AfЫtDʂi(Jk$ VjH2:`JU~HB28 iэɖ(y)|Lh"A]KYbx8ʖq64E 4o>~1Lҵ>K'Siɜl?<'`O(^a/,Kұ\3FAN%VK 5LKo"(55][Ɔ:Ȭ,91W(fDVk3 s#|IAV3<̠y11J4 G40Wz+Xb :  ;劚^aq-2'n4O8 8nyWq-ƿ .ވGzaRZ,*kk9\#2PH E ڵ\.ZܘaNu'2r>;wߩ:W0q c YFͳUS*dy'pA_ڭr0¨$~[ƍ~FӮ4-|l?HwL>1h zNozGֲ_Zgmk _l.>Wj%.[Cf$4bΨg4[ߘ I*ʩrui<\y)')0LW p9S, >Z셂CKŁ/0P9zcu(8G!Z!VV#kE ;[؛d1V8 6I ͳVn<ɦ^|??)]۩z@5Gq^0:Gz< F&iҊ8RFD7MQ̍e Zᚃt\ #(^<  EX>V#aIZ;h}kKQY 0r O p &J"%'aF 7P% fv7 d姸'tj,)x SX\gX2 ,\@ x>]. pw*B&G bzˆQRMԅח@gs_PTƲ:DO"ET%.)ǀ1cy.*Oꈞƽ-WSx"3f<wT|rD7,"QvAt)9Vn%Dx oA4 X=`xZev#)5@0fLh+DqI>-ˏqB'^Ku+}A Mf`wu6tC.!Kc"XـeZ 8G3mr.((sq PW ng?QVPoAzMNlŶ*IXF<\HmI,$9,'p1DIsߖ H)Pxtz-㽘%2yx&ޫ#o)&fn] .`z$^͑džWg. aN] ژn$+a>_ ̯FbV!{m &,7ȫ48t:V Akċ"MX!YFGĻlXSY$]WsbyƬl1 PG|8! ŢTF-EtxT'`Dq>Yރ)xYTGMqL īըw}-pQtCF&06zGܝҺ6/#eW!RQrd( -ƞEyuմ{&~%LWj"Fid61,=W`v{r% ߹xqE3sE$ڳt[(te곶1Qmc(1DSV&e4 HɇN`ඊ[~WE.1n \3/.1,Eֱ=eRXqr faDr 3–fA9\Jx8N@G3-C!{J)J7 !HE5tyל?D3"غs,*I`M^Ȏv  i;0(+Ot*#"|r+fn$1f_g@H=y2^xШJ> KmN+wFa_1=! Qƍ`Xr+ e`S^=9)6bwS<2V3FzQ+^,'ۄ&ְZS#Ԁ,8(1b"r7gԐDH0"J@:N A ho>MBh\DBwzCBgnhKj=0BBLy|W=71vpXר /`eex**8Uk>FZ-pGӠmvHɎv_lλJV)/9EUi} ;e>W?V @ͽT;v;-mrٰ[]Գ|Mf^#"5<{6WQv} a<s>jY*~>+~0g6m۔WԢakJA CsX=*b4_/YI/?v)6lCme=o7~}Ľ3Q=hO {b}F#Iuvȿ}g(-T҉/UDEF,߁C2!Fۯ|(o;KNQ\&Bq@x%cz5Ur^vė0vϪc׶/ fۿ_¶p?|Սh`4- SC~tė>nP[b)ACvTb/߿EeDQifuMb21B ;>0KTĐGֲ0h./rء9`<鼹yedyi'ⷾu6䷮(VXrs_~YQBJѿ$OɘQlΛݙФqH0>-E ׅ #a8 fqWs5wb(\Ya\R3D.H.2tIE `KRL`M`C"ɽX?}Ash8e$aaCa0 s`ן.t%˭9/rg?|oٮ_ QeOHC*Ϲ~z6T+=[//oF>$uLωgPɖJ۬e<4 0\x'[pU}<Wg w8 }| 5=Ai/\~w*|uTei v׈X?WBפŦd#dkM6,L53iOClhX)?&GŃMTihރ72ÅnyB̓VX(P1R3tXK ,Mdb(VuN!ǂI'B2g L݉9F@ԟa!SZr I\^ϼӞ^l1M ?2K}Ql;t<SሹˑN_$:-KM)-rM#jrpQ݆,["9=i;~Oi~-h2D+ )^dWPǬsldk͒ۈ,]kR]2 p̯dx mCJ$: ݳ%*8«n bcW-N8ZuZ*؀Ƣk9ی~#X ܗb3n6z^rD`Gl*q`[SKWj}Is#|nw^v|Vd^lvbkk[{O~:Xmz/RS}\AvOD^.U1m&uGVVӅw±V&-LT!'8# .ij, 9AAځ.06>W :^\Tcɯ%.9JQ -$$ua)FE <5:rAtYTv|[I~HuSn?ҟ2̎3Ki"4L!۝ 4x; թy18r JoeZ[QAg?7/u"wx9ѾmȬIRL@z'GdDIJ Ŷٸ߳ jӿͣl48/6xgʽEZW.aXlޣ*mܪI Q#p[MZ[iq84SR:,+@Xy7݂zv'Ђזtԑ1h 3ۆPl?=1AJa{X-W rbtE%LE@b~͞ߴ5KW5^8 hfG'(OWGj4-Qw㘾5jtž̧B\ו̸Qq1bY=T!5C7n-[Fis"ؤL ls*YEfn6ůWs[ӖLI{!!k$ܫ-EIE.b66Vnh(-UC;ݛg1ŰJjleu@B6?KU"v-q8%jE}D `+)pvhM+Ea@=$7%Şzj4zTUr`a-dOQBĐ2?܏(ϿZχ t؂h KuSmVVl>~^*o;wLfo }0@vf A o <0‚kI@_9VKc1Ljm,iQ Ѡ@H.ߺ6~Gq|Ŷ'XH\A*pW+~uٶz7rAWώVǟ@VI/&)Woh!%b`Ak% PZ VC_%j=œ S[p-PXG^K=`OE`<®n]C&Dv4);{v#;Ya>r S\ B˶0o2mgnxlAE@KsV=9,uUlv-BXd0l[\[`>  WdpwyƝ98\Z7 8~`4_vMw_|ҕ/vD],Ҽfg_<u!e7Ts33PF9qcMM=i}'jXAV2eCocq%bDr~D[ qIށAvZyېhwMd;,@" ogt`0yXϱF4ct28X)p,C.\{GL MϜ6)UDL6%CKxpg0@Xt!-c^)L3(gNX;ûVZm`YEފ6},ִ\$abQ}̅38r*v ~1b>K`h&jOԗ@N/ݙJ7r1mAB%Z^Lt3TA,PvמqBg !=(qrZ_Ckgr1%5 l.1}Xdgqt vX@FƠa5mGGpD5f+QE F5 )eWuxONݴϢ9c“^ an5؝P}/b F2^ï*) {$WJ:e7;?T[h'ܘ+tz<~N)6(zՒ:(#Xbh1? h. \b#6'krvCkn&2'hv<͑a8R6bqdEpطpƲ+y<%N'6V~:;nU`C#*`C67VtjyÖR0A-.ۢ^Gݫd#ŚDRG<#LuH |vDµ`@{y2hn8SB>^YQפpCpԒJO->$ 1d=h߸y=fG<9M"ͬ+cvh@gO\^}sHS@GyFQBl;(mTLRzB7VZ Z=Ԏr!bIЕ$ʓ!/'Y;C2Qa##7]g'>ݺ3;B:InerJ%{*{~i$ x9T~R}6F6/ t"YHD>Ob3> -ȹ{aꁀA}g$z ]Xtj/'m.Jy|*v.a&ax }4g'eş乞&l#gdAѢ"2{פ'l-L'J;ldu!p6Gu>|e~1hf$ګ+{J-_MqJ]%cYwbESP@QL 늅RÏ:uBWA1WJJG6@m O }ux+xyOJx \`}r"-Eć6N-Ejjg{Zg2 1LY KS;I n]eƧTMvWGAEOng LKрN}.8D}%Aʌұby< [ ѝ2x.deo1\&h&g8;5!JF1\zAa(* 0|HvT;vl]HLȀDžo<џų`bHjFELg]i?=frOi4SpxdثaS6:"!cᙒ_|2sClY̮71G6''Js.ᮜ3AkzVd{瓔JO@Fk k>T9+ÕyeplȘ-NzF̰8R@$,t}M|9e z;}WpOIt㑃pFߡQPXt][4i5O23VGV!jnALZRj~݉`e|0xw˪,> JR ևDCH㳶NVj=߲QїͦYӃB HEQq`s /κݮiGEL E*d eauU ; ݭLHlLRޥ.ep'[jZ)R|FS]=z4>ef):BJ,"iSt7zVp?TeQ;:OeUeW@YU-mehWϥΙ`q@&YwWW)4myŎ&ll9TiQJG=Nyh7~@ٯ@qywY"A vvK$׀hm$c8ynm sA6\ wwes-~F#HN-\>UG܊2 U[Dx+?@k/( C'E?ny_ h = w˻?XR&Y瑱$[Ql.ͳ >UD:dUqdz?3f6LWWʺTۗB,h!Z.j̲+k7B=P%'6*Z"> Xï_`?-'p\'~ۗ)$ c*By#x~\tq75BW@nbHGkqxrR:6w+<>?%1^:vETmـJt"c?qs*Dh F$0rpetbemon-1.3.6/.git/objects/6a/d541438bfb731bb63c003af9695cf1172cf4170000444000000000000000000000430513775160026017713 0ustar xXSgo)Hшkˡ;]*J0F0{,q*ߢ*I}~=!}OKy̽axȣF!Ii4$MHy)R)P#oE_ l-PRCKA5q'#„LiG& %r 0.b'HS:&9Ӄo#j/"E?:@XH`t(D#[?a$X4뉢BJEXo?n4\:8}vi~!j 0Qtv~t|zJɌaB[/Zq*Zi<6=5ϰu\ͶGPٹظL$eyxlP(ɲEB ;m=e4FRhL&iQA4`TfQyf0Z3&J+T899>y˛3Yb-/R40]oT`^hw+ͤ:ېlIn^w_5=OV}EZuzh^1#"Xo'/5m__iTjtwYm δ뚉 ' wI}2!G'V1,Wg6,BuI )1>t_"kQ<0 Z - 5+}C"+tzYxT;OJJ:a!QsR.D#nZ6N]uRZP+9u;3ĵ ZMf<1gvR@IV)#rXR<&E!G鴋J}.!o=qE~\  W(D6]5M^ fCz ɍi¤!!cn|L:0ྎk"b<تJD'i@ǰ ق]98OD׏vq>fxԒEڱp7y^[Yif+--zyFJ5.(4@u_!9@~\5rx 'bl{9Q󯔺˴קysrZ?Hjm\§#8-TVhHx$)dZ)o9ǡ׌>o>H )~ZDJ++FL;AafzHZlZJt%50]E ;3dAWɈUꭢ2p<M A[N`8uk+VN9 ϱ\AÍѦ%}aq9 G412>y~bg Vfiȶq4Aq:jڔj.%KN0b0{:Ou&}7 =BƷܶ.>Wg>Nw#NSJ5>tF{73g59P`9o=5n? T(kkBӏe]ByEDWo2ib/Ņzim$b`QByRMχ3k!R#?d%L8ѯ9Ju9XCXN^):\\jOKxO?3L=~z96>Ks;hEm5vzRەRl?X틹"lYmPncp=Z+P 9iyKSlmyЏXƁ$X_?5++Oוf ZPڟlr*ߨy0%˔B푋PcL{/uW49k[{lمϩ]XLW,%r"m2Sj3y[Ae BE&etbemon-1.3.6/.git/objects/6b/0000755000000000000000000000000014173222122012635 5ustar etbemon-1.3.6/.git/objects/6b/121fb45405d2cf85fbbba3cc52f86eb9429bb00000444000000000000000000000027413731654657020223 0ustar xAj0{+,PJh5 -#ס?q^ZQI(qIJ>q$.(!n@fkHSB"Lԡq&v,]"9 ;}oZ^X1Ez Vaetbemon-1.3.6/.git/objects/6b/4235734e4911f3477b73ffda4caa352da795400000444000000000000000000000141514052407207017634 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3B(GaVvqlrNfj^I1ó k_>v 1ٻ&_HIMLc0ҕٳve1/*Of6>۔+_{lj PVniܹrT>"Fn~C9kC>\Ǹ#"fnN~rb0,J?'ͪ(Sƞ<*kLD[-]$b QQ\ g=lǴ˖Nx1l BUT# B@}5c (-)f QOX&ZWdx~Tetbemon-1.3.6/.git/objects/6b/4c74f88bef2664b592b62c43d0b292572abce50000444000000000000000000000614213216420065020001 0ustar xZms6JKMdr/s\|M{윇` E#]$(Rnr/u26 ,Ͼ`p%eѰ$+Ftp,Oi~{t"3 hĔJ) EMFj&Te2,+SIIJ*8@$GĿh0|a$ ?1"pJCKy6N8V1 3uQE!gYpȊ2HBl`Ige7mciT3iWqx=$Lf1>\ˌؑ۟^X W1)!5MU $q<5) YVX;4*f mʱnǯx~,-ox<>BwXB_L~/U0kUYuį~dOO&K2^K &t ѝ;@Kz+YXk|i8yNWBAhυVMSyКN# Qmc u8Jdt4E\ѥIֻ_B-75 q8n֮iEl\qt }KW2FGGOG4;d1? ^WF!W'W r~+H`ԁ,gUlj Ax:ƃ%bq=~ ~c6GO|bB,svp4Bhԭ m":S[D=4/*8m% GǞߵp*|لnU> > FVkqG_vr*O.Gcyɱxk[ &䂕s(gjO_\Gko&jІxOX %S4vzrś ^LhMPQ)_DA;9lu~3W9WLH~% ,*KZ=g:և{e߅V(8ؓ8(t SSm̘ߕģ+5LlO -skvH8t0Xlf_sp4Tޜ](lz%lm<r*:9CV(PPN4RלJJ%>ұeoʹr&3w& Tk@R JS0 /P}G@8Zfu7yO/ ahWmyH(ǚ}\ڲ[ ĮVV3BZ3'aH(nP2ad31W}Q|Br՝͒} {>џT#ʧۅ2<}E"_;&Ұi62ISJpOC_OxGKu r(Q_5'lJ6nX]>mx%3_)etbemon-1.3.6/.git/objects/6b/6f52c43a6bad3fa8563a82e2e98091f270a52e0000444000000000000000000000141614173222122017770 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)33mꎴi;Ȧen얖 ȝ+K哊-APo1t6P5~+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35ݢ{%\\q7tW)Iy ^dy\8һqBm btm#W M-IfX?׈˕>v)șiP1tOݟ6]۷Y qL}Q3,XQ ,d^~'XڹjڹŸfV00Xroi[Gr6 CTh1_ⲥq 9y۵%9 ÿ=!ɜ$Y Y8-&etbemon-1.3.6/.git/objects/6c/0000755000000000000000000000000014142105442012637 5ustar etbemon-1.3.6/.git/objects/6c/828acd2eb68a128016cbc86858ade26fa559720000444000000000000000000000024213604546743020020 0ustar xA 0={ʦI dEk%M[a` s*(, o"?.X7Fmщ _L0` 4%&prt䁴ڞOƾOwM[1MJe3d}Y r0 r=C+ʎvSo Emǡ(ȩ*~ }>_}>{>é]q'1{6wlh #.q~R]; ];8ttޣ6]{IG~h`Eks<$ʹ 3@DgLSNpH H9TMsoOj ^X{F \~R׵UtᘖR?bۈwHaϭijj/D6 Щq.c"B (BmD#00 9"3}91]k102Ù|:U8:5Gsqiv!wtjmװ{}]^;m|g| ?U+ tx~z j%,- 'C日L@ LW^q?YD}#ɤko7lJn%dDW׻Gn Y|f .ٯvH`Ra$NdЌ#sBh63yt8'Dr@ T9:#]Z<ižL‹fs/]lQR%CTNZ RÊzܺQfA v^rb+~@ҰvYo< J)2^jje2u͙ *2?3g65cCq*E6lbR$Xf>V#0<0cG0q P4xN2dK*~qPiE}-G8& ň=N87-يV%Un6 Qg5=rTdQ%tT Iw5zVBÄ!'_3a-R-SktSF7HZ)*(|COU`a-٢Obbs+x|pŽ<&ax/KЂ^!rgg1/㣚/\F@إK$e$ROG @,0vk#Q*6!Gu߭nhI =dԷ`^d:x t~k=@pot/Tԅ6n>sQDX0riL"7&@,]clL7dHy?钪"-eR"A8r*Fo L7Zr*yJwmfh߻JN? .p`~K3nP %P8R9Ӳe)a|WuLpsӃGGF:iŊTH}F(Ar{,*[y,ϑXTe%iB*0&T{lڂa\Im7o2[ 7J ?iq@s +!6 _e*^[ w+cg@ A#Ste}%peW 8 ;d H  L1ΰLJ-VҫN0'|DX@\aUfY)=+i28TfJ*^E& @dS+=;pf"kUݥ--JᦝӦ!>;Cy84q'\*ݳ Fil#A-yO^;# '0tR۬ 9U`QOetbemon-1.3.6/.git/objects/6c/f85f36591c991067da7360912bd690680894cc0000444000000000000000000002774214142105442017456 0ustar xvɑo?EIs$W^0rKwn5dٳ"P$(@}}}}YDlϴ2#EdhzKx: Ov[;||e:aw p<<e:eY/t݄0_b:t>oj,`d+}W,n4aJcbr$բ"ϊ-Y4yt~ ^e,:xyzz#ز2], EŖ8LA:mKl^ߞ"Lt`{I><5J9I`qӰӰgl4 )\a~zG?3Q-'<-j'a:[d0)7d/Fj'ep͇W!_fBLgMl^ŷݟO0H?g0w;ͯD8IRcA:Jal|fȍXq6>l%D`*mu2Y*K맢6GH=].,ɝl\# {&?EzNr&i`d cm(gSmL{0&y:ɳFʁtv LƭVsM&\x,p1fEtl:u[_νr}KFͯ2ۻy2:v&:[ ⴗ WL֖U:q׳FZ!HE8::]ZdaFmE(f7t~`T?Ⳕ *h6aV3yA-&#{'b>׺FF/_~|6Jnӷ9.g~ˇk$2OnMyi>"noWІGX/w[_vvކdn|+wלMΊḆ1R\̖wuge5+,Gn6w5 DL;Ӿ^l]wv?~I rpqmuZ 3Km)mcccr%A 76,5|NK5gf'~.m=Z^~=TNsF,'laoAɢNݾMQbR3c X$hGǖs}*{l7}]B7xei:Y̧x1˯պ)C4.+`qN%j2ThmW_f(՝3z8굏zzv 7MfLBM~r!g<b\WB$9>vbA¨'@cʾb)ڵ;YS6tkk"7 ʅrXiKt>2&ˡ2R.2N]SQIsG|'𘵴P=5*}l yspu "+6\4Ly}EG«,Ȧ^-8#YcѦb C<@Eˑ+Ld%@AEb]AHN(-= HifɅZc[9is83|L3SOVej|`ˊV@\#< nEaۊHgV92~Y|gL`ȷRxQś"`=<ܤ^j gAOm/Pb28`C)\=ct'4cI36SO=dcAs a-VJ~u"{zlucHVVd3X!kgtTҟV`~X=Z6Cϓe:~ ӇWgRj"`CLBd* 0Qڒ?'sЉdqFbmͻ,pb(0m&쫱З F6 ȥc3s4H.IFctS)ֱ"(!x99x&j xepxh;X~鏖f)z&7GbWA0BH@4"7>7Ctg)e/"_uV*kW8iY,yܩQS=2اrK 0[WgZ  bo|㙼=$'1\a!X4M= k6?ief_]jA~7p\O*bQ6♏{=88΃Pmy+aT>*ʈ# *V8&laE+a#"'#Fz7'T\ 5궻mq~na`akI+& {lu_U^E'דpEnW,J_$'bӤoq/5ZԖw,<<5[owO=py^TH6[I%gn%teb\nhiۿhHG׊kVjSmc|e5Lh,(r!uG=Z$ρ= ~2pLé z*%B-r 0nVqC&,4%Wv4jv{][5/'RHb0TϜӞa=P.{fnGk*}0DZX\q^Q;kFxU d$f^]:8QݯNߪlڷvstm䗿~֕êٹl73WGnT>{RQA V73`Tu%),Q)wE"x -rmRk@U|J2bđA @ЊTUl o?. 8gB+cԖHag><ڜw'cSr7Yq_"s6M ]є<,zpuRk\S] Sc-*k5ք#ԽGcq'L۷Hr>YQ&d@}UvbH`Yrf|ڕYaPD[oB}Pa /Bk'Fɹ!R|Lç֯*w,l-+z~:NkTR3 OCPgEs?H\U\˞kqoM_<%%Q;8]]47KO??CMCu%,9P <5f^| ͳʏ{zA29H/UGnO\7gKDB C{:j=zb'*Me! QyX %6%+0BfPmR1;+s+K<ŗn|lfXE36.A.t3pVLvnGLԱ%onC -<+"CH+UJJލo Av/*Yl!&73vOcx8 HHąJT"׹~^l^x?TE|^Qrh ぉOiﻂF48M7M)-YqLB풞t-d9[s>:t&UYRF)BR?B~v*pken9m56GIscgqb8 *_eㅕ%cs+_ATظM܎{&?y̝HcgK#|yKe՜5LjJz&3K(~'c\z!Z{> fNa1V<)[ck(,mH~R?,6oo$wgg1sz='.`m~.Υ=B8]\욚퍏n(b;?VTfm#_kÏ]%)1WSG6'qL /PgNp'.."Y*k.#^ڄxSPr&Q@D`s/ ?GYBff ysy䩝3 vI;☮<$Q*IVFFZs+"RmKT }*3rkuZ'9`) nwYn"KxE:c3fH2?ExXϘcu XIbhX2Ժ>Q.ƘdcEc 2~ACx:{?cV:8Ӣ6tm.Q%Xb,7nIUj5q#.-qJq+UJ)Tq go g\4 2\ۖFQulH }#$"#8.բM%) |&7VX}lLe św/~0ܤgbL,惵Znݚ@ %Y.)8QT]يK|m?*$FG|{A1qEaGr~ !Pۛ/HFfUɔX +44;kb_NcEf4},x\v=y̒ 3?ͩv]0WAhkZxHEn޾kv u,☘ *;1@'Tee*D6͈dv\\Υ:j^u0T|vA+ 9[i[s)R3AaSVY\UZdUtPb[n >|n6Y Z+<z3>ƒRT$$%;crͫJ9p)wu׭lw(Q} Dp4\| Z pZ;9VHW{uND9*X niQQ– ńzoAO +(m\ls=yX]ZxՉGۮ%73?Ew\UI*]uz^ݤ0˓~J4)|:xQk|蒵]{}.`ᏽb,..T)=rqmɻa 6 e(Du7vn1t% o+״Ul۶z [է`ONu]$FO൛ <`pm:r!7!?;;tAHQ7&ߗS98%:w w]Jwew ~Spj%Atͷ[444#뜑4IhoQS"+=[ s tĉdjͫ ȇWz%WTMF,ܽ CM8J/LmqBC9y M쎁}* l1p|՜_Vtb|LE&3hHU|[b fłofiTë=—o=qRʚ탣N!6mK)v4ӂԕ<:?ߊ ϓd1q7dIr0zdz^x FKT]n.љek^I-8' H^c 8\09(!0%=дV׸e5b$`nUÙ2}q$Ql!D GDV[`&2ܝ ʗ܆ju`v/@l2{g(A xG*0xΉ&i8YW@JkL+gC _5)K` Zb1U `TeMopٲuOal`|@ق7Y~ \R^({ZJ6 sZEBg)X/.:R]1 quAIrj |SC%;/RD&\,E.ƒұ[(6fdi<mO6cE\[uQ~^ kv]m:QLϙ.80 ϓO1JoNWwֿ]$|hn/X{C?$G2q/g? > CӗDx)pa??S=j9aQT@)UF=B%umwJ~g8:1|oS`H_ _oPДkcw82i< [A?|"?ҰtEPE5VxkJl[fi Lvl |20C9pAc=̆{ӢcCi?7:/= (fUVg!5M د7LJJ]-@-7n-m RFgs#],}侦Js::-Y-J0dc Mʸ[YrVViTl)d!0 3~{޻NC 贻q$غ\VGb駓}j 7`hg߫~BrqRibDj VYiW7SDfk4o&PBMWg(s}2<9u8v y(oР6v']nѻ*I2QNh8>P.:%l9Rftr(Qz!Ptq96Mc?> vܦ|P |ԙvnSfҷAY/U翫gH),. 10t"#2|j[E+3mwdC0~ sӷU]sDc5&<-hJ8LImxe{Jiq䫭 N`2'hǿ IczMpd8FSK%Jou5/_`9nC1@6|C<@*qW}V}ّkKiMz'>}["5ԁ | +5 [ãAAOe}7:%ɾW2G"vdZ'ɦ7Kߪ%Ԗt8lI;:O͙bYwͻ֏ LhNl}I?X f?]!(LP7άJfL&,In/ل3v`asAvf(5Wtva(kiPUTQ*EW>&>T 2Ar0-vmުK5O6g˛BdTv/ϧɕ*k\Rtƙ?rzM = "6jz񖐵Y25|r;T!YQTykTiM|/N?|Q8¨j-N;?X恎(.pun!7;B^n #R7W{6ٯ+ySx7 &tS8W6K7p޽}D4-sfr^GcK4 eF/,EN̹hY20.nzMsaaVqǭ"KP$㹲4te?<p=H<4֖L ?swU^iz}iQȊ iRgY]sMk|ZQ,K{w|nlVգ1Ҷ=~?~bV/woMH"{$ ˖FIm3gUκ8Y!,y4w .Hq`DDαu ޒi@oa ߡwL԰k1-M>\p~y{lr8 xqddtAW:(#%ٙK:=azscBsPl~9jҿz1H3R/jVQvT(nM "*D9_f`˻tWr<2RSʟTҶejnbG bdwvCZh+`>[<PqV0c iSWÅ2a8?Iv]\UJ-n-q剚M*Y;d+A8zJ(7z0OPo[,uqg1IHQ!`&p4.^BXKx1Tp>4s^NgPk o']΍ y (įѥ>`ck R'eNu|,*%3`^/ JG 4ve ذ~qhG~amN_ŷV9f'uQ]N 8Dʌ+FW ']h:0?!շ|o)x,7Tn_ =4ZW+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d`|z3שܩ5jϜS 5yBds2SJm0] )5*DEJjRfbÆ75l.|}xDdj{oMb>Ȧ$3̽&Afwlg~<{ҰYNry⋄A4eussaqnZܞ wM>},\Pq'aBsR,k4|2W@c Rxe|Xbkiv vQZTP2c9˽-n>]$b QQ\ g=lǴ˖Nx1l BUT# B@}5c (-)f QOX&ZWdx2|Xetbemon-1.3.6/.git/objects/6d/93c7944dab5811873bdcd5494e533a842c3b390000444000000000000000000002347413212006652017657 0ustar x}kwH~_Gn&UcQeXGٳZIH Yh7"D>D7"ӃY:0voQ1ibNZV2ɋp0,I W?ͣQO<7d<0M,?y4'^|<;5gi}iݮ8L<Ghdbf|.i0,bHc" o&i6?+hQy h~NI[_115Jދ˔Q\Xe7XejfItgm:ƚ xȜKfF3ԎIdfYsuHOޖخ]W>FYQj(jGbC1̣<'^T?V,s%JR55+uZ, G|B[Нʭ(#S *E(?ś&C8 >8!ƊAU2d:PSZ;t>FAZb^ZmXD'ˇ+ђxLN |UPAh9;1tߠK|eZޱvU.tg9n:GA9#i|QAKM(UIJVId2u;ul9 y33'SY;F Fń&DM<;Ƒ| PfY| ӏ!Fv(UQ>.B*EJ##`KogNyЦ6q ճ-inϒx]a"np34-o7 l|6XN&:AHT|kcaCiX XjpJRy^Uh,[)!G'nÌea$eEI LNbo1_g)m]86!ExCgdn/J}kTBO똺VparUOu:p$N$ipU/)],*hT DgXOn%C kbOb\ U)f z̥J1HVDB`~ P[ABڠlsVCxh7|B :"F>BGceC_וd\@xk&mS~4;|81,)Qec{`dVgm4͊ڜ+b-WuY\ L %nEQKVm-IQh^re~}Ľ3QoO {I*ISմSD_}8C)\ J'fZVu k|bn ջ~wF }cR:Ӊ$FxߺD([qR=6\}lO1#&f +Oɘ ,&`w.4i(`=ΦLn0_ 1;1o7oko$e8#M4,u9IO'^ Ɔ#_ߏweM!z "^z lr/9V;/(pN$@2Y8F 0ND?;ۼ?UΉ.t%˭}/H.6?y!7QޯHCgdw\}?,!ЩW -7O#i|s"g3idKm+b%+ROP å}Ys;1{&w,#^{%^ٓقOZvWVEL6m  P蚴ؔql@$(`0CϤ=J@>5Dm#R ?&GŃ 4~'eK#/RT&hۖ:(<&R.m %KX3Ż{]pȱ${tl(p%4`wjQ'($4ęc{QKn!)p0XCG"!~fl4ؕ%x$s?ޗ#=wI0 Mh+4 ԥ&V߿#PbkA^K L--{ɜ4{FUyz8@-`4|M-'MBҶ)A75K_1xmN|Aeș_ d\Bha*ik,t< "U.]69kkչkVƪ"vbk9ی~#X V$/d3n6z^rDk2T+h0z#IT{ύOZ-/y{Y۝Q-غW>۾XpVb^NVy,>R {u,r'v[MV/+.lmrn^[8vFhI+:A2`'Z8# 3]4jrz={jӍ/Ec;2 Ҵ?r{7݂zz'Ђזtԑ1h 3ۆPl?;5Arۓ߷_`MT^;qlL$(@RH?\үQVT fYCo 4G(?:5GE BQpzu7[F'칋p˥$*]W2oG"G%ߎq4C7n0P\ʹPoN#.oۜFo@^Y 2EdDezLzދȰ]DީDR{o]_d2(gccfN$bӫbݛg1ŰvGKllebe2(/Npv_clE5w>ֱ?Flܔt{?e^QUʁU?-dO;.~O YIZDy({A ,ϿZ)t ɐ-^h\^KO"]'RyKe ߹kg2? d;Sc N7'@Vp Jm\'}vX-)###RFm'DJ]؇2 ; uMm۞:F" V!,w&GKN4V/LhvUj dZ"(irFB["8&K\JxN6װq޴϶X6^' MK}'mD ^\)Xk#ĵn٤ lx!dSu;IMՉ<_*"ur۲1o&\%zOX$qtm _!][3ʜ[zHCHg小il6R-Џ5 L1"_Bb_!w[_n燼)x+ Zkx (%56".ٸ6\Fd [\:&D6qvsg (U \BJ $Ajv^*օ޾5>BV4pK/gp`i|At/xy譹ldJzd*V-¼˴u"3fP44Mlĝ"qRʜNiW mKq}! ~L%ٛ3M ]]A V 2  W+4=A䟿K0sc7S&b5knMR!;TEBY\4wgAz]`Cע/9kEKJ QihARiM5_pO"&6嬿\8C\o`sR{qY\-ED鹶XT)7&9[InEjƴ c;kx2ArSPd@]{6 $U%%!U7eѱxY.}ؼS2]0Ǟ k /ARh{z5u}-~[z[q7 ni|:LeCH{Qx OB~sIxۮ scؼO!U YiR͎D£_']~4kxʍg[} te0V` 9Y;RLEʘoVS HJ*c7;*o{MJ)%7 b'OMS{!^5hc46XZ==Ŗ5hI\b#*088x33pȢ47z+7VvHn} xpvq-cR^&{Slj ֻ_σv|%clhDՄnG,`)͍ml9AaKzTPK1B->[t^[kI*sؑp a&&L u^{eYF^ʦCfw\H8rtfA8M[!Au h6ZV`\㰜4f]Cꤘݺ;7ke`Z&TBF"c*O~J8QSG`A(`s >18pԞMe:$ .X4jXC5G;,%hcd# ADG#l>$ȣf&'b@Ӿ3un|=G6ErR UO ir㝭v}Ɔ4g'eş>eGi* o8EA-*"g [|8'J.q̅WC l?]'|eA1hf$ګ+{N [ 㔰JƲD;=(! S[뒅RÏ>A+%Y% £d 6էAvh"s;8nӧhq"-e$aN>NHTFxvu&h !1`ikvB5ĭԒsnrW`Sۙf:m4Sy -Q_cI2cw7@:Y>% [ 2S&o?`a7aehyHy{,'_ACX <|JU',ØG3q0ZE[diOR!B 9Xx6{Y ņ U*W/8eKG'YtQZ!Wcl.;ཾQ`u!tNqL=G"v߲ `=ᥲмҊfւȞi`QqC0=[si=ENw% UfϺeW9{,$w il$r/_޾y;Ӌ,m>[ k.=}5^pđ:R5@d~ =9-*%Zg:l5)7QnN4I?"ܫ!JQB\]40 eE܅?ʤ x\Z8.|o-; Q<+ d6ojT.1x{m*1{J;SiRL^x9^҆M[t,B3%K#d&'ўe1ٜԛ9GLCN+xL)gEy>IYH=ljHwՌOǧ*ge~2'zN63Oб%).++G $gѹTv=. l$P*N դ.;'܇4vA0R'z8bލiV(]LMa^MG/gniftE(!PwN p{%3j/Jy1,t}M|9e B + WogʓpMWQd6ZW44`O|ϥMyYH 22jRQEw'?%K,78*pmdnr-C$Y|+p吞!9B"GV<q ǽT;&F/`bw%U: [YwM ?*r`)%rP>!~Yf _k-vRMJ2]p{hƳ)R|F3I z2DZMSP?k*Ho[]='NwouCY6:3fwlUb% jvzAؤaLi8/Iz*\ grQm=lF%aTQDeif-=#c`- GEA:EIt*SĵWE_6TlDzqtp^Yf'Yz l5 õQ +R aXHIA1Ȋc$LQi gBfyCLptAzŶfkd"d&iBfɁ꺙mr7kp/t=&{C3i.[snedi;Ip`' *kOP"{TBuS6i .c1|q.G thL3He2H3q2I?zT@̾1E%a?F8T#9ײtQTY8`%J%M`mBVHAq/y^+7.ptH(}'@wfg'pLO/GUH< -?ȼᢔ)x:}T1`ľÑB16Bf 4& k#3OI]UK6Rc?]s]obY CrۇDsz <RU:Netbemon-1.3.6/.git/objects/6d/c5dd9dc2c88dc456f324e4ecb677e4a911785b0000444000000000000000000000026014052407102020150 0ustar xAj0uF4#1&edUtŒX<*b3zDB(֑CBbvffqzޅ-2!鉽`Ʈ. YZ>yu_oHŒy[5.TMPoetbemon-1.3.6/.git/objects/6d/c89ff6463a4ad87d911db7e7915631faee1bfc0000444000000000000000000000153714173221067020246 0ustar xU]o6ݫ+NFH]躤h-h""I9Kʲ](PD0`sVYaӋ&ҹI2]ZXeҺ+K%7KZ)3c7K6^Zuwl bq1_\a1g=EȢ$2J4z6%8OmƐđGJI22z9Z/p6?|t$p1{`IIG[Xcq|Gow##vpz{2Uzkn gGoA3mUI_.͋W7o_Uetbemon-1.3.6/.git/objects/6d/cf9350c01c0ff2cea30c7d6e66e3d78c27bae60000444000000000000000000000152213767544664020316 0ustar xUmo6WW<"q6ckb:lؗ}؊Hʩ)b@B=wϽjӘ W/=7JNf ?6vaJ,o(iΌ֬|#<~5bu\]n03owdQZ^ QUUo S1$qR̨ W@9gYgWΖG2N0e ; 1H s`o+k4 7 <7o݆ڄX[tn; K|Ɣd.!O2mEבJyt iIFm R7;VIB6yEk]A~&LѯHXm4<5wCV5,pp=#qZqV4Za_H%:9MqT$9ndHgZXdWWY.U@=DitvctCĆAs) rH֠Zp9Acڳ3J{kd_i5(#<\iU&\t!0ܯJW:d}ѝ5%9^;=A`P&}Jkva< ˇ ?0]!n$X]erQv㇤G$LjE4D:wxNG^~-S'GrENI2NL'|xarAKr\j1Bb} 'v3ּ1#cY~v6bO0x_ *3w|3TI_&o~h>A\ netbemon-1.3.6/.git/objects/6e/0000755000000000000000000000000014111113236012635 5ustar etbemon-1.3.6/.git/objects/6e/0bb9d7a5803f6dda84c025ceef51ed3c9648550000444000000000000000000000141413343237701020150 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTPv.hMvZh)TIIjnANbI*Cպz SD2dpμ 2_dW^6\ZnND69'35ܵ/Pj;]˯BT&e&1T\(Dt03P ie8[qoD6$e{N,^ܵsyմsg;?;Am**(a`pޖlҏVmr1(.3cڿeK'<}rbk{**ewa!O SƾךW1BTd3Kv'sZ,d-+2<,Retbemon-1.3.6/.git/objects/6e/59ab7b827e089df6020a171d068b4a82e7ef970000444000000000000000000000141514111113236017725 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3'}gWuO=%RlrNfj^I1ó k_>v 1ٻ&_HIMLcza}g?%xSb TA~2C]ɽɷg|ݦ\pjCdSKb7vKΕۿI 7r:wI\rq? XA4eussaݿn)m,ZS$4{Du_#|5gWXW8dqke: z>U)r:`|>@% .3rVܵMB.%pvLl鄧oCNlq^v`/TEe10>R: ., dZMetbemon-1.3.6/.git/objects/6e/7fab79fb766dd05888dd5a3f9c016bb2aa48b20000444000000000000000000000063714057341606020242 0ustar x+)JMU05`040031QMNMIe8;?nN|:/wrq7jMMJҊr2KĿ2sIt#A KII-IMM,(HMK.(`uy&؟jRtW8t&0j=R-77- T= ZEK|{3 tKRs Jg/2vuQ.;5*4'3UUܚ*E,7i1:?1%,npUGl~f|"UZÇ+zF}4|+Ģ̜*s;M9ݛ0i%EfPaS`m^TUU'+^BBSS%%uN׫i2|Q1= &δetbemon-1.3.6/.git/objects/6e/fee6a2818dfa07b4c669c9e224b998a22ff6d20000444000000000000000000000126613212011070020150 0ustar x+)JMU073`040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35ݢ{%\\q7tW)Iy [x^RQosIϸwҧ@'3<t,/<O%D6$e{+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3'}gWuO=%RlrNfj^I1ó k_>v 1ٻ&_HIMLcXyzlr_A'3U[|{mG=D6(+vcM@\[*Tn z#7?sלĵ!zWcހZD3PV7'?913GkpapyZ᪀P?׮M44&3\[+LJ+nA(*(a`pޖlҏVmr1(.3cڿeK'<}rbk{**ewa!O SƾךW1BTd3Kv'sZ,d-+2<{Wetbemon-1.3.6/.git/objects/6f/52621bf2e32a82175647ec7761d77854a55a1c0000444000000000000000000000120713604573611017510 0ustar x+)JMU07d040031Qs fi^5W~6^6: wimڦlĆ~O#%SG"q!um\&4wiZfB5rNbZ3Ӓ ZUJ^/EnH?Lt*鶠Fz޶} E^QnHT$PBHfu.̟8 er~\&N\f(TNL™Y9Ikdd,ʒ<=ר 3gկ# Q k&}!?$s|CrĊ6idY-(RӶc$C>pb(J\d% X}Z0֫2,f>Qʄ~FoU_lYtigf*ٰL1 MHnUbap>Y0.iM~_22ց?E%P!ޗ9!gJtNgȽ$h(r BVjG麔zGy" ej3>$IS~|jkjNZӧq"%,IFq䧵|InA3p%B.i0{1]˭{6h}o0%yxUt'wFrzjXAcVSIgi\5SzKup#f;t[}5E ܐOu|7em2l k`Īe]g݆E R:4n+cG \EN [i:"KIP7)P"|p1+i K4ftm(Y0<Qߟ7>C&߲RLTzN6-hNdMd.p^]]]|b]܁lJuQbK8҃d$@LYoa<~iD3]\t&^z|qtfɅ/(X7\q#";Oj%Lnh~r'm#鈹YKrtiG&;iJ&6fHZ<5Y͆AIQ2ppl(ۑ?9+(XVvPɛ_C8'.cTn`~XZnZ9I\ M^ˀ{a6[/ Bx1iWQ$.&sŖSG[1}FkR*o2h; _I\$r/S=]AdWR]iFﻝN8ŭ0p*h磾[+Jb2ؚK+ h5Dԇ⣑ ֢lje5NFw6klgܠp$i'EM&)(t^ L:u٩S_]sc1Cy5%,b7V[ň(hS„GY=ܸ\j' לу Rvƀʹbe#ڠaopr.\x3ppャՕ> i3G/|4-*{IxN7';J$+OB#jH`V}}zt%-pB)ZPvKY'UAT!.nesFqUfp|m q~~n(?br [ b ^?(SU0$"ibHsfbǀϮ@픏fML}#X5H惣)X&Q SL-JX&F{pX-}c:]v1(2`%Viht( g46KL!#6uuڙ/ [Ӫl>S]HU^ RzuV؈֨N#ķsp1 J{(yv]%puNV4c2ZF,s*zV6J:FpTb}4D8 .U3(ͲH`8쳶V {0f<: V*2#Eieb8 X5ii!B3p UO-ه?]nؾt@$vFV 8-_ G߫R42>Kc2P:aӖmn#t5g6)4Ar@3AǾQGpq~۩v2˥ IEZzP @]yy3[,Vwl6|+(b]Ɲ(uTeܰ!RgX:nSz&uIb^}ے6Ƽ8-P=vC]۳QmSSA쁺һ},UQbfVE*" &VΠ,i%a[Z+ld4t`MA!3g^:leq%Se;it+4wMD۞:ʻw!)_^ʔNJ8&d:4flb*./XDp9TiXͼ~ᝂ'!%ޔ0dۜ~^| v•3=|n&^:˩+-`3j _Rv-PIk5hɪa]򲼍p?e9q>vopV!Pl9in81hKӮAs$H7>0/n'$pBJNŸs!yӲ!F?lU9۴Շ-4 ?g] T#+Z7ˮKH x4EWͱz?R[i?XUaZ;JbW,W#uE [))/,x@Q󀛚2l>̗JV!&q'pVz)i+[UtXI`rELdE[=ͨqqQNGB3vw?j^k.R7 1!2aDasݺ,񿨈99n֕Ztd Ki;ވ _U_P^(wDaT6+A~{ H9-w[]Á$ڞ>z<~.SݗAxz!xի$k$@E0JG7]b

OtG-#KYU{xZӟHK4l?ڴD7\m3sLWN|/bބt[ Z~mu oijta{Ӈ4/AwPni]e=8>?;{q|E2dC!5#\*S3jAQsx{0hI a<f}ikϖ-A-Ǝ1+fqgǘ!/]oS+8*7`;_4gSdBRCjc^p9##6PRи-}϶[\޴$p:oe ֟t{ : l*V0i]6?vInKV{jIh≠cTxLw4{eZԤN]VPf}o#vx1WQ@^^Žs]{^ sW.8)Rz45s2^'bFL@<.-fU$h ?M J蠑zMtGKn|l/๟&5YT5Rx8g c| T˙ 岓o4ɛ|6@׺z_R6㶍Ȏoa𚗂 S.y7\nQ:z9mWQ Zn7qؓ&3ϻTzZ'Wl5 +EUT aϓQKǕ34P1 aǚ2 m](EPpHdM"K`y9^yJTR"%_`!vo4nla`2h};뵯eH0ہ6o~VTVx^yruxMD6ZZS=1?'rRh/~_p'Lq@z[ []*{ռùQ-~/]?dn:жu>YX5q~s|]H~mU6gm9x # ,tQV7z/m+L#=zڬnjetbemon-1.3.6/.git/objects/71/0000755000000000000000000000000013462026443012565 5ustar etbemon-1.3.6/.git/objects/71/ec5b281721bc984bf168971efa3e62cb2947af0000444000000000000000000000141613462026443020013 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d~mmL?2< lrNfj^I1ó k_>v 1ٻ&_HIMLc ߈q=Ṵ~Z/zž2(byljI2k?d}}Ƕ'ڡcŢ2e~̀5߬stKph''nPITmU{Mp9Y+ Wgy(&buYS~߸ p1z 2>N,^ܵsyմsg;?;A(*(a`pޖlҏVmr1(.3ȞcڿeK'<}rbk{**ewa!O SƾךW1BTd3Kv'sZ,d-+2<RXetbemon-1.3.6/.git/objects/71/fe92f98dedb1005ec7e5488ab34839308c9f530000444000000000000000000000273713216420274017755 0ustar xm{8Tii45ä ! BdD.IdX6̞f3;3d&D=tT*MjU(%T*f{j]jץEe>sLϳ>}{#AqZ 5 0ˉs #;uf4k\]"0apP(v ƍ3 p*_N՜PY9gB"6l 3JMV|}@d08LڠX4=I0c̻dD|6)Z&(la_u9(:Ã/E& [coІ+*5߅X՘0ݙoeb;`A"ڏ*tyY{f}^a?ʅ є#`CY5>B^]"/D@A"IiӂkuYOH?mGo傏QY%*~#=fH4"KC;l?e./F h 9"vt7h5]n< ~oË_uR)C6FL`,% >W1E"2ӶҝF6+]񔁥EK~s6WiIbz2̪ :G^|=8:wD :t:}{IJ9"gm\N :Rqypf2S?;'΢>gؚo2ViyEDYjv2#鼹ѧF{uB;gKhA )Db3ߠ2AD}X&Y7#Q˧j^<ЕDS wcE).ey0KQcwq6H(/"%.RNAPc֬j{[Q 1ѪYsVMaEW[B`cɏ(B!.gd[ֶ,݉t& a>f{^! yטk5p׆ĭVP5lPbcYu ZӶ5P($s]VMG:@~.B!"T`;׼%\攜 E"F8<ߗe4c.k*ah>q=ڟbm\c%Y &<4eqzaϨ^֠֬9=̠[eura{,5!,h4>1n\ki & 'Xˆ4Xf2Eh!UT%i4D կ7&G̖4__e>B'etbemon-1.3.6/.git/objects/72/0000755000000000000000000000000013764407263012576 5ustar etbemon-1.3.6/.git/objects/72/85aa08804def974aab8d38eb2bfd76e0368f270000444000000000000000000000267313764407263020116 0ustar xU{8Ti1R3LD.iPDƺƊ6ʥ]e1s21393  vXPhU(6* rk y朙9}9{#EALrrt\ $Mg]е4?ߕ͍ ` 1`X ŐFI/O !iۆ3R2 c, DDc< q}~i@la~qhH]Ŵ*w:w>а{OoW#P3P(ՁfjrAޘWvL?w\ƚ9'5*gGք(,ۭ['_k1HNpQZwkǐX1 .썦r/ɂ 䱤2T>koPYf1etbemon-1.3.6/.git/objects/72/8e78d877145a709f4bb4a0e2c0f10ec2002b1e0000444000000000000000000000035413212012324017663 0ustar xMK@=ﯘP2GU!z6$[6w //i2$4FP\`cluj"uv}:Z)ɜ!h{mUTl8j|Yњ1A.#<œ$KW|?p6+E*U%e.|fF<䘖zh_ށeJJ%"O:D @ߒKa2 5z+߮%Rڀv~Pietbemon-1.3.6/.git/objects/72/cf6e64b1842b6f05f8c5ba07b5bfd7fa8a18850000444000000000000000000000141513304753620020150 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTPv.hMvZh)TIIjnANbI*Cպz SD2dǰ7!aMw!9y% lcN!*RR2vmu0jkɂ+8j*OfL .s|Ȯb{K % 5].Sf/g橫ۡcT)㕙OlufnN~rb0,*4Mo᪀ %OsibHg4F 5_+v.vlg'@% .3rVܵMB.%pvLl鄧oCNlq^v`/TEe10>R: ., dZ+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3E+҆J?D޷ 1D69'35ܵ/Pj;]˯BT&e&14[gp?ױPsrڝP u&'ߞurŲw}|M-ʊ--c;Wn'[$c5'qmȡǕk77`yV ONEҳV]R}>fCgH_>7_ӫW\p9[8nL3Aק*EN5er{[NJ?Z}I@{؎i-cȉ- خ셪,G [CA܅gr@!nFh1Ed DmK"ȸ~u>v{y:Nf]֎?7tҿ8d~$!Gtske% bhzyM.'ap-a-( >䫑"ʑ0Og|t`mt>gqe3Z-|\y:+bz:'B8]N~c2 FGV<o6n泰|n6Nɂ?UKy\rI}:d,1IjWֶ޷ @lZ_dRô۞s,)=dCl[e-E}=<~lZN{xpߢN"p>ojb=[XgŒ}w?O`1 Oa1L{jQ&0]5OQ{3ȃ2}Z2.¹G,e[+Rqt"ܶd&uTg?y4Aak$ORqӰӰg!q)/DG ' Fl)'E1*ٟwoo?r6b:nb#:I 3AHekwz7v{N$W1 d6&J!2͐l}JTڔdUJLTf3RO 4Kr?k*N\Er6Uf!cl<[H DF:LC^󵭂X L׹,Y:b~"_ewd |!h6qqor`u/u[[V5/3\i"5*T/C,74j>BF{4Y #So#~OazU29 j6y{>q빝uרbh_B5C *M5܇ĝ@azoD%Sͣw@!QZQl, ɗbAFMp./6wpz>4a)↯j=ns:ΖRlڍopŽ9 ѥbw?!c/z-k0&p e5+,Gn6w5 `L;F45Bl;+TNx%+ce?0î(w~g͵%[ש=@/) ӒUHi$M|1I.4.=EY*.nZy[av}3'jkU/RȕH5o mXjRjSRBdtmͧnVأu7h{4;l.z ^"-<(Yԩ=UNjY~\CZre1vUHzN%j2ThmW]f(՝3z Q6_S{ڄu wY&3&Wt!ی&b9ѐ3 .u[#iOX< ?<<%r#(h Od)N ίoI|W.Jklg]b<D$5KSy!c*#R㄀х)ADŽ13Np.Xe6G͛42Slq6Dauk,@6{p퇸J8))xl JK !}8KmrHH=~] ZNzdZ\uP=A-Fˤ[oٕdcE^Ă~s16@W.=d1/ma񛓷<0(Ow+[}1 '&ݺ@Xm8QẔА~gc6)f~*f:] N,FLނNeFP%v9Ov1+t4ύx~v|d mv;>8DVq/Om \84FM3U\$t]YTssOxGf ͵kpoo`Uc|ye:rCh(ŧo?Uej|`ˊV@\#< Mc\Vtq|r.D+ǿsC̚M$uG8>Cu|hl0v颀 !lB9vf;ڈOL^yʟM5&'Nڕh ۅCl4{0owb Xø@*Z^s\zwi?HR^deZX(% 2 b #ُak/NvEڮ'˥ ~T?Oy1yaƐb~`Lt}Ϣ6sxl W{*JBvulz:e൞b##eqRvCh\䗵'e;\OilE3ƩXT ꘔw኎BE6O{:}iibyqa^ n`-VJ~u"{zlucHVVd3X!gtTҟV`~X"Z6Cϓe:~ GN_I98l1 ,hDiK>rj\'>bH m<0 F7G7Ctg)e//R`efJ 2nr srR9rɤ+W?Pɥܹ}X@>|*HZR{D*)U)md1DRP!bu!Y[觊ڿGyHִ%Y|n-T 8@č[nh*Ro@<$15 øTrlkjV}ƴ)g\A$s}fGdlnW&KfUƅx!E&]۪WP]Dޭ!|#)&K\DXʧjb/ a6+ V/OHG'( oz,0 XXܟ`'#%{D{Sh}W.Vޱ 8a$N])7o.^ Fu}ͯ{ CvmRp'*, [-*$p#9{qH#^~ c 2-)cOm}_O1΍򬻬Ӵ5VL.u)XƏ /*f.i)CR/ ;ye؂,īj4=9]&FDIČFfo%|[ƾ;u5LZʌuN(j|ɠfVlkOn_:іVzLIکJOͮD78J Tqr;l6C`bh'8S_!|]bԝ恓ڟ\-σWBLK5xE^ulNc("+;.!!g0.lЊ7Qz*?%yI}oЖơ2ȖTts 1D"ckho.x }b]c6DK3qyYw W>:ѨPp9qqljls^08!0neΪ)Q}?< 'hRܳx "FvK! i<ǭ` |R<p?>t™HUH:=P't5`8"g#%}=1sX˵ }{ʂ[ܳ)!*zT͵L-F}e2{mOs^n {/$#wT&g]gɲ‹q6 nxc#zYw iavqxEf;[Q-jS o+U3y~Mݷx&l(%PJ2{$K_O?0QWav} 9uN7)}e=[@mSz[lR?-6=sNKK Tw /m,Z1U/L١Qs#Ǭ}4JuNNkl=>ls`V7x2+rؘbG;;*vT|Ýr>|:Dٜ:g>:CMv|Bm;[ c/| QD8VFDiTWr1a D.Z G̲ps=/ R8"8QYK4<AW6O@sLTq-{KyJJvqw ϖ`%/,~ꉝ`-:"Bef L}:&OH{4¥iql<ڀ(^S -YqLB풞t-d9[]h}tM~)ͳ90S>G6nL74&>(d:{7,(R\U6Q<8^Xqo¹blt *ZFXr l&nG=p핁hkOa vC+_C<X݂Rk?JjΉ\RZ(GBK_--9j3 UxᷘPm![: _b6 \ܓU`WK~SP :h۵f槨ޱ* BXѫ7qyOPZ漴B~}: ^_ntڮ=>YTM^opkB~yRݍ0[Q5ZB._wycV@WN~MPŶm;U}J&z4|ikv3 _@G#<&Dg%`.tx{~SC6)y$9r!G]]W]nٝ|y6½\,e3ba2]s$!*s>l5sJfʷt!(jl畽1XZiGGʸ#KU8Vͱz{BJKL(@WG:M2XUxW_=y>E tK6C-֬wZ+U~6[H;gxdjξcl8ʹå=̆{ӢcCi?7:/= (fUVgBz3<䨤5* r~FrРʿ+E^kt67d#58>Uѱ'hHJ(`d}q Q9%ϋrVV}#([ YjL?̬^t.ư~r;tLO8slS(@\ >>|rr/,`] UZH.T*̓QCLȜX-Vp*+mCvlr&JJLsνOTơxX;ngY^n36! vz:[wg~V ޵+ .T](JHl|zPdn@,'(_D'Pq h܏"Tt/`Kk O*[Gds\V0%lS9Rftr(Qz!Ptq96Mc?> v)|P |ԙvnSfݠ*3c`j΂hɈ Vo-hJL['o,ِ. \|V$9yͧ kv $#a~mYگզp ʇ6tXeNЎVVNΤQ1=&82 mץA7亚YP*7 z!tSwjG8J>chþH޵L؋x'Dmqִ` u 1> ,CJ͹yy֬sPP3AQ8:}_ ҷlup:%!dN:lҎS/lsffF]4yClg*Su>s_OOo߼; GVE֩uG<D#!6tݶG3R7W{6ٯ+Sx7 &tS8W6K7p޿}*{8l%L9/vhnŸH{O Pfb";_TĜ;JqK)6q 4<F`Uw*K2+Ksp5e;p=HJL]OQwkK&Q/ ,CīdFb)30&ncZ-4bCZ1fT&Dsi׊sLk|ZQ,K{w|nlVգ1Ҷ=[Uv?V1;ŷ&q$=meKsOѳ*~~ag^NcMK9GEex?YǴ̪j` HYaGT5X-Pw;2vn#в}p@_G⩀z\A=XmHZ". ,Y&u"Rz\mqv'jV7gͮuK *AЃ=~ z*fɬ{<=A o7HF:F ]^I"9ͬת^s (\/|x:ͮWp_ͯ4_Truq܏Gqrc7vދ*&.48\U(,O' {#|8:*&. Dܾ7St>U(Vb愱'{N,@]nŅ(z/Mg[} AYFB mŮN܏<+-ƪ_Q 9ƥ1+@U7vIDJc磡a5]iNxk;8eUoY*@L# ӗ|sCbh_^AC8 VE tgAm{.C (VU&,Ӹ i0HiJ{1Q肊 rT=7*a|087_e0'A\Q ݽHM9#1)7s]B>ƆMMZw`7V+2 Q>ZF'+j%tHXx" "*=  3ń" .;&qߍAxg)w \mp45צ٣bߊ:w|"R{p1bINZz9|xVݸ_*uj4Po#^dd U[AcJ5)Zf.GxW"oh1{.Jc܊N>\fGfS8}Ip`(z.Iep25ۙ=&(pf h.Edۤm0KV0v9 G)`OJ܏bK*{Wmbս3_pWP̽wAt9^0K EF$MJ,ٞ170`7n>8%(D,sÓWЉ9[ۍk3\]J0 \/ϋq`2kq^/B-؝C0|S,,aOlŘ.@^k9T !ن꟎iGa,7iA:o} &~вD3_!l7LG:Ghu;;z {_vnjzJrnxMfi%Y`ElSA-5ƁqQ0yҽ32@/t4taiM|8Bp ""0 #7 W06u,w.c9A10RuDe5^0сXurִl~Cb><BXЎ$t=,T\wy0Nee*6:KAQL\Nwn$;(@vlE1XȬGhj9k]vD:JVU*`au/V֟0yǙkf=UF 6~F'^#SNV t]9HOewE4*G6,QecDCPW 0X!&s;Pģ=Z7 MP㏀*I.#;:CV/&@uc(f,}zLB#,c# ħ+4^R_pXxP@5 rSMHȍD @C?:JD,4Gd B@ds9-P ʶ 9r?Q"$uXQ='w< k]JGME.Ep#EcpT]Ǖ\.>ov5Fgk?7U]1v`;> %P(Ⱥo8]$ԁ,ɢ^f/e"ȿTL67Vqj5)q%&Tɿ}N[vp$ ^C11aFMthbfft˶:UWni[]].; VSdht%8ʡw!S#KǗ[;)9A!*EȪbzK:Au!0tWTFK0\3ةWpR_RJjrLtN!+3{$uj|Ɛz@>dyX;H~eF/:Rrx>.1ASngeܩtF}ȭN-_5iQfc2pэٙRQ|n4 ɀ!p,P>qĜ$/L@_hG1~w'M=PRc7A,Mϑ@([x2Wr?i͏Xs p˷]zv#'0ˆth;U(R-=κt#);zkxAj|8^_PȒB@:P8Sˋc'>H\`M[:E&(YC>Gf#uUQ5AvI4"?]^7$C`@em+ェ"kl1CGP͒XVvu_YJQ԰+5u>*HPpWpj.]ADTCZA\wPTmHVDא;}5;];Z4F3Vm5GnkL9ݻ*Wzy)5>= yBRRy)N@AUT.[J_#ZṆTDR'rB^ AQ'`NH]&Zl%Ux)h$4t`=PYz5闬8ɄԮs tϡP4u@6{@ZWyږQH-흄<:) FD(!ʂU,2.!:fUx#P0 LӟT!taymQ,c:r". Ax,)Mc-Ŏ]AD -n-F׶dGNCYSfap%|(!evr icSPAY |QP8 :*H L!UMA=(f'V2; F+՟_*ف2yp=Ɓ%מA7*½ b(R"(@fj^,g 1 O=} qPKf2wp.FRN97B,p;+W{sJƜV""=+I_r5?UI!<#z HPjMnARJu|X KfWD#nټ^$ܤ;2h6Z;HjXFu`gkjWJ]Tˆ/L jkO%mВݪ"xLb|*[_;!^l SK~.櫞XT5r!_ȇI)g/Wt v A @\ bw-Cwo g$:<$͹hW2s (Ґ"4(\Dm4Nsa(vkMh+"‘VDTHJ. KsR'g~,JKk!lۖM>+z_GZ6?䔵[|q3YU$[bwf5mڼoJ%l5oTmyTb3nAZ՚T &X9#:̚-Q y,ʰS28J<.9ZiW q\vk[H} #=G77Z`IP2@n:Եcy2+J~12X%z)u$H@F#}RTu8v[~%lG+rj~QQr,58/eG=O"uhGz` mdmޜ]4=T*u**;MuEFkSvJccǛ|XkCͱGF8 j(Jc$hqV L8OMJ×*n|/\'-pFå[m`N5R0K =W)g:@`B׊_S"?ǧk}tGA$Aі՜ 99|fF&"F)dg^RxsV2ķ@Aݲ 3OVt.DPd͐t k޶֨ ƬԊߗL[GSLL9:1WUɆuzH+t֏ B"6TZ&}{5t.m8b#̑ŶɠBJOM~>/go9tA2/㊍TLGH'4jvUZ늮äjӚOH(Xۚ}eLwtAsx:K{^*Vi[K4xU:,qdYJ$6-sFWt`"gc׃6u:H%JX ͔w?T'/>JmX{s\%L ^\|2漄Hmn`mZ`Bpf9S&Zl4fQJ =[etbemon-1.3.6/.git/objects/75/b94e2bf4eb9fa1203ca829adb25b6b135f24670000444000000000000000000000213713212012107020035 0ustar xV]s76a!Ku]O`}β+X Bڑ4v{ϕ0Lbt=s%LgϟeTV%伕6I;V֞łpEZc0874 IICKަHNe͔fKVT‘Η3ۋ^JRkOi1~Xv r*,SɋB>*IMc EFJI=QːCRXHui@R?)1%1X cV BĸPIvޞ2;VyFY ӰBʍZ\%_*B+ghARrz;bZ Z횺6qdE!cjla BJ*T4@4:JXBSZAfeVAJ+t̄i9"쳦all:A?55L2  ac' *C@ܙtwи"oT4(}25G㫫_{vp¬g*P~ƒzb굅F&sB),ۯdYw44lcD^T;^`h;o'g?wO 9I)ӣWߑhA^}>ìnO-$/<fآ2˚B@e{_P܇(#UZ(DlG׸#T@7ߘE^ӊ6 %<*f5R{jÃF>vF ;g;+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3'}gWuO=%RlrNfj^I1ó k_>v 1ٻ&_HIMLcxv_e!ܿp[&% ?3nSXv8!%@YelrRbwdy $ 9r,Ԋ 9ɉ9nHo`PmqpU@݇Lb(kozu@c R.g ǭ|&T7fV00Xroi[Gr6 CTh1_ⲥq 9y۵PHapk2')ck+B!*JK2s%A{Bԓ9-I[Netbemon-1.3.6/.git/objects/76/0000755000000000000000000000000014057337013012571 5ustar etbemon-1.3.6/.git/objects/76/76787c06316220434f0b069b790116ee20e0550000444000000000000000000000025113247732002017165 0ustar xK0)z?ĨZAKnY8WAQЛ*ptL)@H"՜QrD]%󖦯yZZSJ#2Y(|r#+#[- ۺ4("2;]OHm~5_7WTV1Hetbemon-1.3.6/.git/objects/76/8d8b60822973d32194eb11d0b80696dac2cfd50000444000000000000000000000030614057337013017642 0ustar xJ0@]+f/L X.D$T/67%pPʠ^ '\H,dmƐCIzFe^n %Aj FH&e\ Z*)-A;#:jc˺¥}ju#SZ!{RS|Ŕsɰ:r8O0M2_5v&^nWn]Xetbemon-1.3.6/.git/objects/76/c40380f9f4a8d6d0296692118ddd56dd0c3b1c0000444000000000000000000000044213247732002017717 0ustar x+)JMU06d040075UHIKI-*a.wJu[s0 UY UG%"ʛo9gKWPE9PUl {]nYWhs{^KPHUEnATeOs@W_jJ3Ԡ奖$\3D~{˅lvc B$eW螰0Q Ъ)13TYqּq3{XήT[$6g^e3Wxs^R-D]7f)6 eetbemon-1.3.6/.git/objects/76/c42b7c030d0cd89ce0d5e4cea3fe6a413d20d90000444000000000000000000000267513343237701020212 0ustar xU{8TipaD.% ƊuX 3{:sbg9LL(tMjG!Q*K(Ժ!;=Ϝ3?~~ 'W'G5..&@"C*l0V- ?#xˌ K mE^s_*'9kΣhi9QQD %~{0U|@\bʼn`'Xeːvf _~ү}ʖE#ˮDH a*C0LҼc%y L/bԗi!crT\0C_IH1/%K]Ww yN8dAlNߍB܂/ ;zAVKT9$$P}l붦\TX99K@ cfp! eaP`J,ko?TV_Rr\Ui5Lt!K-=Z- |-M.{nvQޜBI-{=|Ǟ:k7$yJ!W& MI.X2m[$ # F:vT=t7h5Slӳ ңW_)WwkyHZPt!S>"7rb`t~ ra_;B )1 KPdq۩ۿэɖ(zI|lh"w%h|Y;?8WPq cb,Y96<'3b[Mߜ_\iTkOߙB,[z7@a̡S)jA#[wɝGZ+3-e2z2h2𮤠9pcpmiq04V)>؄X*Ǥ(aVKd[!xtXyv*{,8HM&Pq40O~*N #jN7:߸ѯw[eZ^MSCW!*<5t_foРe}G[ĮS6ċ-6WoTj%.[Cv$4bg4[Q]$cx!-6^M#5O?~)|hqđچ0췐0~x| Hf"6AB-_$s E5ұp3>Y pH TTDI[j xp|j|e0ߡ#fed1|z,*ڗ0""x`QLjAYSĕݽyHVS-{F[gw3(A.I 1 WQР q%žpUwΐ膮gRMs4Yl 3)>B>|/5-g rD&Q~T! Z 5F A {,&q4WAǼQhhN^hZ$z촴wn~|9Ƴk 5<\ 9l7<:fCUj7((Iq4$xTEQ7*j \HGбV=E ʓ $> nlx Q zZz)b22BzN á7S8[o J0ɄC(`炙b`B!dN:7Cs4 %qq_Uwd KH1 IDF!<6J ^'*Zm#(Fxp DUF$mr#$pAD $b*q ^@`Et]췛Ԑ )cT&zak^D^6 rmπD=.\L q`bq ]XcUJ*H^MQ/L%2hL#/R֬dhi۲|5k>w)9m3QlGU*gE2ر ,Z$*%N:.ʭ dE< E|7U *$Ja,}"#0Hprk٩믮x8Ĕ #8´-E|y%R_>b΁M j@aK $!;ڮP;r \8.va )]V %AeA ¢ji(Ò`0A^y@! 71s5"4wLp@Ӄ'j<6LGә^#bew鱥"ߛ{5]xkU }cVqvKd#C._GX07FG?Y0y{/%gAdhkA;hgܨa"ÒrDiYU0Kr랁f]T J7Sxuq $hPa-8N 35ZL&Z'wpMJ d jFҨ9@Ƌ&UR>"DzT Hl^MɊ!jb!F,F{٧I{xPJ¥0nD"EP|| 1v"[֮!6X) %\c9K8ܺ j"y=_J_^&KPN ҥWbh'/8D)g!벝$+d\k9db+wLQm>v~HvcQ #r-EtWX'ˆ=|г|S) fESn7ƱW8B.膌3,2TxG,deht1w Zox)~%"U|LOEy5Kwi7uc~%Y܁XKY<ђEĜ V9J(s뚋dJYi#Ϊ/mЕrxd>Cj Cߜ!? 0)Cf*n]%{sN^n7LOr`d|OD@%--d-hdb@)ŒpaVxF4 %xq ,Q < m*SʦUIQn G*/ج|Y7CUd[w 3iv& /`d +p0C]q3aN3Ve`"Ԭks(IzBgFoWԫ2`] ԥ6+)wFa_Q= Qƍ@X1ݮyW*{' :~t:O^x`'wd\&PH\ ]k6!4*/S—dۍVc@F(̫w̺*Sc5y oyZytǯ 69Jq Qt23#q18R"9mny=s{8m[j"vFXӏ} vRT*ӯ<ϵ?U. j7۪l~%J O@=$3eٲHvy4:UwdUd s9z.E ?xyfgEVlxgȂ*cHPQv=^4yw~BF#D{{ !z`(3@ch@m&q0ݲ?SF{rO.raֿ_EQVvԬ@4$ XmU8NFi)Oc@TN#?$|2 m`ʶHvX5-/c&-ɐBl`S^)DE y-Ta- 4R\v9qx,o]QD([~Z`I˭Ϲpf!ƌ 7cۿ$OɚQlΛ3u@ !l\j7Lڂ̆Q~0erF IYH>j ]`d1ԓËM٥ E˙-6AM } B l9Am/Ha,Fg6 6?叕;r.4%j˭}/QєĜagIGey evϟUџu׭W{B^8^L=|HDϠ-VY% ^x.쓎w[pUy<7e weMTp>r |U=A/N~wƳj$vdSY*` al@IT3y0>Jz .>TϦOʷ Jwŭ9?ڹh @UCDO̒m_ێEu9rFi>Yr*BR_ T& d9Ii{ ;m_oG!Za4|M-'2:fm Sv#n^kFD-ïmKu.3lakgJ75HtgV}MAt\.]ⶸk*sRZOd[m|Gnrx8#l~m рm80r beI8Ax. 6>S #k.ndS%p8ZII R1,R,88}Syk4 9qIeP81(:Qƭ$WZ_kx^DzD7L{J7;,ۊ0I#'VlDέSQ:3'Z.AL(ʾDgn%~+ǚcKh؆z~.JH(|،Icod.0 ePc}eXQ :p[$u6 J=*RF=\Ԥ(UMs6q84SR mѼXPTn~Kz=EAkvm:h 3ۆPl?;5ABxUۓ߷_`T^qga* WkԦ mZ$Ly7<*-EkE.b7Wm:hnJ!6kg{,l\EJ֪leu3@B6oa*S!R^ɸP\%jE}p0|=A ԺBֱ? gĦxqU.[FJ,R`~ ~~5>d~YFW0 P[mrͪ׊.&K-5 F];CtrY:zwahkmaAa$+%zcx T6XZHvB4&>?B˷(CQKq y5lд gWW;uٶZI$NaG+d&jo‹b3GChKG=JXΩ$H7C2KeIY<.rYoj:dSS@6</v˵؇Ӑ?BvlBl1 J?XP_#ضCf r&rEko0I?qآY[/%_!]+@E-<.h;Riڃn (>}UCruN<9ɗE !oA^^+-5XK0@,I8_r?8i-mB"dZ &@6β@> @ZG/ ]HP`oޘWzgj+pK/2xOc<©]v^$zzߔ:{z3;Y >r S`I%@˶0o(NF7<'[PpTOJ]{=5~rL¶8n_a@)BCo 1yպQMK:Ӭ"k⣔j,`+v[x6Ep.jnqn&X8(G Fz:x )cnYP!<8bD8rNa/TbyX M] T 2 sW+4=AQ9+?`3'(n&(MEkJlMɐRTE\QbtXc|!3'oM}]kZm`Q mmKt0Q{tzU fVr1uAB%Lak$wn<%Ԟڳ>N'y¼.Y.8HWfr]]̹6]2ǙakFp /aRh{zkL:co=;0zt,c8GX',@#cа6##)Qnꊗ|.8u{egKCʿٕ/|a$^RnYYQaׄipX'd &IZ ; 0Op&l[Csoi3P}&I705 8E[ q0*~ѯSSKŪɶzgS;*U7 PCWgX(O8`a }bQrӵ186\7B:In e2 ř_*pAOVH,1ASG`Pi68<}b0pT&T2D2?ͫlQQd39zml3_H`E+QYbH>Ob3> -ܽ8shZ Ġ8i_j:4 NY>EaSE?ߥ;LD? G LJ[礙=\ն_;zp4Kp%`  F"2{Ӥ|(@WLΔ}$  S]|x{Q/F$^ɼ^U-jrS*oϊKZL-Cx2$35 u ]%RUAx݆ܠ4w#Zp/g+3`uhI҄k٫!<:7@` 8Ҝ^u 3A<ʌO58><GE,Od K^ͱ. 8Dmǒ e:`h;lgaK0C+kw'M|y|0M4Ʉ-Äƈ'n{;H(jDhq0K!Xlek:VA%9X8`l -UJW/\8JG'Q`C̟08XT,?jjG u9M4`FSPY t(ӻkGiH-k2U.C18ǓYivxvF FGBz`. pcCRQj(ٱpܾ%/ ?\_}9gaj/2Om>Gs׼lA?1&;3%Kkd5 KD()ay,M0W6C"FҐN.qUviPA=*Վ[s@-22Bˀq{^"?wŲ2rƐX-%:Rm?zR%j'p䨗ثeD6:"c,Lu~;.zSpds2iWsD=|0.9E^Ȣ0') *ZM w?yʜh p$Ig$BIgGϪݝNc!Da2fLgT?-ءv2yP1 %LJ촺(WB!\HiOA6=;Dn5i}nTvԡٱ:a뺠׳Pz¼ԏ^iatE UrZ;nل$[T,W7qx_o[dYNy )= axdpLnhR5KV$2ô'H *2IkJQEŏA˦?`˪,> 8f! |Kp倖ٌQїɦ Yq ꁎ{BؑabO4Y23"* ^F'v:0m,XW҄~/鵖c;w~B y8\=dkwM+p"W<գ!.35IAT`ֶ(@z@nqp;TeŨg쩀ͳRA(}Dz.v|LǙwWW)"h\-y:5Ml8ds(A(zLy"h7~@د;,D c lzEzTw{S41ȥ3WL^Hq Qapu\]%8p<` E8Vk'۸];\uH !0$!%V#fJ=EV1ˈp<c=J&qtzŶf1)1Y`fY2P] @|"Nx08W37y]P/A6#a+¥Tf Trfպ)4Fx}L/'`llMr@AYGh#sUI?44_Cdy!}wGo_˿`-?q(F2=0QTQV [(% X\+}`;tR4GR͟R+ TT] (f7 Iػ+V$7QR=(EUbsFT ɟ~:>0nʁz*Sm_ I?vG'sWj=(2ˮop }t&-# O>XjdHP5V'@wB fg<12B\ r9f 7R\&xJbo+ h `#еٸxr:ƒ:AV8>Jb:tQ 5\9XĎM,}B4 @[ J$kIetbemon-1.3.6/.git/objects/76/cea98dd12f36a9e58587ed8b3bf147431b1f280000444000000000000000000000141613731651453020031 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3fS7SkԞ9j*.&d3<`JmSkrUԤ<熧γXH-2N_> QM#BP23qF%tU&69"*jSf <#iTNğ4 u. .zSU8fLn0;aU9$$efQf2"ni"f}ruqGQwŞW15 q0=UWE\,8Ǭt S9KVӷcXbK;Ӫc@CeIRuZ^\ϙ ޻T,qT)dpuZo-f?viknE$1Ʊ}v4}LDY˯?.I _>Y 9MH9rOal Rsʨ(߇C)Ŧafvhl#m"32EׅXZ8f_茠sgf"ׂ5)9ZTL˟_"WT幺)V{7ĹΕI@.cwλt=e/t;cɮlJ^=2ξ .pz ɝ 5;2Ĺ5wNg.;&O?7yb ޙt[5oo4dlg#nfg*)fËyvc9Πo?v!yxN.Wiph{sAZ~hwwKsLڊar#Mi`Bk-H_~]8w?%etbemon-1.3.6/.git/objects/77/0000755000000000000000000000000013731651473012601 5ustar etbemon-1.3.6/.git/objects/77/522420e2865c2b23f49091b6abdecfd112058c0000444000000000000000000002362713247732002017630 0ustar x}kwH~_GMʮlewMg h%zgc{oD&>,gGfdO|hI4y)9}CQhZ@MX.̙ζr /$m v\Gvie6P4mEN Y y~Q|GݎDGQIcGE]`¤D(c0X4SR%&Y8 oW,!kcoEZ(L(`oU~ʏe*5%#-F`54*¯þ\k$^)AA ??JNr#YLhBAvuvWbPy*| ӏ!&v͚([Cqs|I:RS^!D%ňH=H@t8,ut4,3,5 %)M*ov/锐`dga*yu'غ0q|{:KoX l]1t{6~K~ۇF>Tƞ NspGOu:p7Ev®g ~H bAmWF7E,P@ z8+ĢxrK85'PpmwYx|8 ֒s_īW K3u6hHVD}|!0`F(] ޝi!`[CJd+ȷxB :"F>"eEוgk]3S5feiC?Dy>`Q*cZ1N=|0|6S@bfRmNJ b#WMY\L %nEQKV6]+Qh^re[sJs񆯞c>JEt۽v$r oNPO&;<[5#؄>&vSQ\Ǎ9gt/0m>5U97S2@!|GVa{m+0ZX/B1n0AyKVx`= y΍aͰkEK•\ mjb-y-,}jemȱd:OYl7JfqhGǒ+wװ,&1C` ʧkt0ࡈ<љ,N 3/,10_-j ]s _"uͳăFUQХ0HO]v~ XIſ5 a8^"(qؽXSޓzA~ v݈aCQG p'qSz0WyS(C='^<H"PX욏 y'L4Q@&!B4^yAHJ3j~CBgnmL F!!ݠQ$l kR4.e]qf~ 25UhVoC1ޯMM+}d*2~#c$^t;.evN5t;ltNCTB"g*_!1 b ~-l77N 6BIBR0vzN%B+¿]ڣ'VTwI;Ryu%B1V" #(+~y>n7?|d5V5D9ӏwKZ6_/yI!~iC:Զ9[~AiBdHFx\Eyx'd~l;:v̡mugW"MޛN۝=sIY qj Ԍ#%3O=ܓeatfJ(*HR#a#9(yMMͣ_dy\n. 4,N7}mӯ fU[6amm6^w_q`}mE냨vνIvw$թj)"!3-5Y1DaCr;߯|X~'zZ#jy1wb(\Y0o__iE6Ѹ @&^{~xqN~~?ޕ]"- vWB.KUz D*g L9Am/ GHQ3`ggן9%D}USi0:~4:1/i({ৗޟ%:>!EgZ ߜHy z3Ri5X $TpetGlqNoó~~S2^ 3xdk{q0Π4Qc.M[cBd =~-4&-6U$s![3 6,L=3iOCl8u}OÃpư\2Õ~w k"mn̓vZ*H R3tXK ,Mdb(uN!NJIǧբd•Lݙ9F@L(gYG-$jg޳Ta|ʳߣ?1K}Qʒt<Sሹˑ~pI0 Mh+4 ԥ&߿*"Pb+AѐK" J^2'A5+}U%OGh5KPԷ46 uJnXmz/R&0H&ձ5n97 ;ZEyiw9]x7-V#l~Uv h D⤈tDac_ s&@z^ǥuM?;RXr QRhAXI R#+bjji BN1G?fm|Qƭ~c0`/#Rt(pј8&o+B,+qu: 4šmlLsKPz[eR+:,ha/i2i/wz?QMFdp6wY5?q1F\ON3^y֕K$(JAjR#V˅VGZN/TTN 6FBt [.Zԟ@ ^[kQGx£+lB԰ ^=L>lO~5Qyo )v1I RFm zZSV?hJe}ś/߿yM/**NQ/#pmS@MЍ4 Ԩs3mp.TSȤ6Pdn{ì?Ju5Q"B@2l7,w*䞰|[n9 XuǺ+ɇ@rY ظ>.æƶ|P-\TejB~?Lk .ۮj+"8a7jA١5g:G݈ bul7.*u9[I~}2BĐE4`|AP قh KQ$uB?`/v&lgj66zWaaA嵍$%UvcD T6ҨhXSKM| PC!T|}'!lCv^ ϋmOpW#qM;SF]'mTl&ovBwd*\BMzWT4H~C+@-W;u Z+9_f?{>b]d- mOZ~Uۍ':0jOۈعR>?.cNGk+JI^v (r]:Nj@uC(dܶ,G[A^~$w6I?qܢ][肀!WHL2m;R17Mwp<R1ߗ690FKZ<.u63r+~~[Ћr͠U>OyA P`,Ih]?p sTCAU̥cjBtmh7wqV܀I_%+]/e}s#Z/tOmMBa9y-q>U"{[ !)qJC7kNN97ޚFƩ0Gmв-m/LY(>GƗְm{r;6X5WS amq)n/(dPv_!قEXBw(hj8' ӋЮt%+]-b f__³/ Źb(c8鉦߉6@P(j JP{8 ЊBX"9BP/ZA?Kođ$yپD|G"]%k찬0(}Ƈ_Ё´2{s&Ұi +HJCfawc'?Rrw fqfؠ1ٔ -A~CEXt!UNsk1zPuԫgNX;ZûRZm`YEފ6};,ִ\$abQ}̕s86'ռgſ]4LԞ/~ *Ft7g+H͘ Wul?v@&Hpj* (Sk8!Jd;bT Wͻz.sz?%X(Fhx:D#,ԫik#[IxwkHh$B#2T/t|r|>/cKkv]c-8G+ #cа6+c##MNݓ(WU FW- )e~|' rYNeEsƄ']ڽwaiN{VNLGfF6~3۵TE#ū3.A 㔒sNЩ}!^hc46X%Z==Ŗ5G9A\b#*088x33pȢ27f'hVvHn}.`,L~:N)¾sl45_qρt8[fy/t hۑ> i*:dscElNrR&(!r p!u]:Z`voo/-G5ĹuH |q_CIK0Xetr:/}p+Rtl8 gV C,>fcz@s]5{ڭ8,6YWЀz]N^~8g/M7LP3: bAT^sS3 n}&U7)$CW{X(F5Y@։(e-[`tJ[;B:InerJ-{*T{~i$ z=#?Ong LKрN}.8D}%AʌXdv<$`^lNZヅ!g`khY>jd3>Qeei7<+J&X N&O{ R ţ ˂](.6P:U@|@ı/[ >b> pD\ 'vU(sv`,HYx#XAOx,:gx#iEJkAd4ܨ! -¹4"n׆W{`]qzF]=n ;x6|Myz/o^;Ӌ,m>[Kk.=}5^pđ&R5@d~ =9*%Zg:l5)7Qn,͖Eb YAvҐI(iʮgwty]kkBheRF< ?ceV(Cۘ5*b L< NI1{J;iRL^x9^Җ[t,B3%K#d&' j1ٜ+9bR>xwXS{E@M5=+j=I@' aVKF|5a~?>9+9ѓpy-NtXX:R@$ѹTn3. l$P*N MyK;+c,>k;ም{7:WP<ԏ^$niftE(!Pw^ +M7 5*JfP^6rR[zr$`U|WxNI+n9'.qFߡQPXt] 4i5O2/3V[@V!~}1^Ʒ Vy#Z*5 IX2Q9ꂬ> fJb>$A pW[Q̈?$Gh6u]Ȫ #iSEQ_pp6 DfwÖcf]@Ja Bw?]R ʄq/鵖m;Iw~B y.=dkwLf4G_)Z\]=3"ef)ٟ5X Pz6@VGD۷:,[}fw4lUb% vzAZss&Xg4z$= ^wuVWYĶM6 T#0*Pw"j/y@/AqywYbA vvK$6/"i0]!-d='-s~CQN{S?X1^Bk-ޢkĈC5c+O N RAhq;Yag:,FibNOoF5rRO&YꡤXRd )DjYȟ~:10a~*Sm_ MS,ht ၶ`Daetbemon-1.3.6/.git/objects/77/ae771aaad17a51336be907c2cd546ddc3c64190000444000000000000000000000030713731651473020057 0ustar xMj!S~`KmB`nRҤm-} AVA9-%&&9"6~KD.jW--odp Hbb@9H *\}+5x?|xxi0 M !̗</yN*~pcZI4ks*Su~\+etbemon-1.3.6/.git/objects/77/c8827906fe6610dc7f12b170f6df3b8a5a1de70000444000000000000000000000263513216421171020012 0ustar xVioFg, J]v$TZqlGAPPRڄ2KKB޷KhA?Tkͱov 8x+x+LR1RZH瀲(aʤ]a<&3Kl"$e"K)9D)2kTe\q$ 5Ka>f)ǰ )"3IP cQkMu$c]& *`00KwV3ynԎVZ]۳8+("z]$QW96L5lMR)t*YN"3F"놥9=*= Gt?O{tIg,}:҈&i0>Mir;g]"BP*߈vu)%C5kiVƴ1~!E(M2"[ogWWC BԟR˳K< b4IÈFQߥBiW#`0 On;[Ssz_?ΛphiT:& kb7՞<ߓ{r''{2Xvܓ=y5tV7R/[y6zC'Z $QcF VPu\Om ky<X`SMYΖ揩JIs^Km$ģ˳iS/ԸعyԨ9c8Qj5~8\Mt i%[ځ{oՏ=f{Sj4tlKg2qѦCy1G+Ayg'%n 4Gܫ V5Lp6AwB-DiizLG=^ jԤA(/$5??9:9~Մ1Rg=Q4*'#HΛjIl;t;11kcߥبuYK\W\gZ.o&=<߭cHs!EYl o@`:w|&$ P/+'@NŖx'#V@T>!<&6&]W,tZetbemon-1.3.6/.git/objects/78/24e749bc6414f484fb9916ae36b817f11c12f40000444000000000000000000000141613247732002017575 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTPv.hMvZh)TIIjnANbI*Cպz SD2dǰ7!aMw!9y% lcN!*RR2>~ϫmd… P ie8[qoD6$e{]$b QQ\ g=lǴ˖Nx1l BUT# B@}5c (-)f QOX&ZWdxc3Uoetbemon-1.3.6/.git/objects/78/42a7f761d4efb8524c18727e34381877ca058f0000444000000000000000000000221513216421171017521 0ustar xU]o6~B/MZ[9% I|{>BI+DHʪ;l b0tJ_~HV1r?zqNƤ. )򻟥aD͎͈wRUN)*DcC3rpdqDq;!ۦ3' ڕl^, dqR{u49+asd])-d[J+{kN!m]3kmGTh`*v?"ʾ |R,kȩb*.e`/v4`BFKZD;iPZ.7#dJ p6t.}.@aFN*fZkvrNP6KQWcM_kE1ylBd9Kt5Dy 7k^Ԃ*zZCQ $մ*.j.W#McUnŜ04>3:MNT2 aO[$uCh饎_ }sG4FgA aI(T9sdP&7P a59+Q:p@wd'z%$6WCUՓ }c׭!)̃Ez4.4C ={sds o]|apմan|b > <;NC#,(n׃(~E֎~h Q1lIdL6s(!1)><ΞuyR`|+tUλTY wE'>߳sh#D(/ñQ#à <l Do%}#Gt‡Oe‹^+E=Q+` z> /#?;k C^Ietbemon-1.3.6/.git/objects/78/456d2cd6687197ef342c7d759e44a1562acc1d0000444000000000000000000000120513325263254017662 0ustar x+)JMU07d040031Qs fi^5W~AE-@V\̐joʫhrgY#IH-I-f`Ѿ")p{Rܛ.3$1'aF5N+-qoν,'3/a`jĮsʯ]j dCVlN{v,JX䋦(!!^7*6F=}TaURkT>o^g!sTe@*jmwLP[WӥK*Tm'oFzWḈ͚[='Ԯe2 7nZSX0Ӻh9$S%#]n+cetbemon-1.3.6/.git/objects/78/b5ed9ddbd41d0338b5e3f686440cfe8d21cc4a0000444000000000000000000000133713212007361020216 0ustar x+)JMU07d040031Qs fi^5W~>wu`~V-:֖0E% [Y'./1Cǡئpy%E9 Nz/\Uƨ`)Vʢ˄,Ҩ7ARKgЙq}-GwˆXSiEyBŦW~I\[rYYfQ1{ktFWޘhЍȺXd5 kn Kx;ujfn#IH-I-f`Ѿ")p{Rܛ.3/D/X4 k~~SPT$0&\y!\.8㍏de3,y, R-utVkCmd0.- 9` uE /lg76YU13M+JV%(F H2GU4r{u;]ZM$$9Z.}^K3{˫175U(*goܽ@1:4=qs6kKu<&P,ai]}W鑮ic^etbemon-1.3.6/.git/objects/78/cd9f5eb6959fa6c8f2c32f1ed6d358d3cb5ed90000444000000000000000000000036014173222122020327 0ustar x]AO0 .+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTp5ğ? anleD6sSS܂ĒTu9% E^)^e1+)3fS7SkԞ9j*.&d3<`JmSkrUԤ<熧R: ., dZ,ytK$UY8y24i?0%ssך׮̗ߝ^Y|qO29嗷gfƋ05$5L$r sf>CE$e+\HL68&5啑E"P뺃zkPCZkMh(IS 3^3Ss7f8XߗfH!c)*Ţ"Ys5cցz`(r$zb /v!W7f0Yk"D1>;~Pu/a8pp*+sgU6:?=8iz5'7R,[zW,x 0f5jA<1RûBΪcͲ o!/ty2C=܄wU.)s ׁU%9TZlM/3\F!r!Bl <P rXpU00RA&8 'znc|F5'oZnݖ/7rvi+xesyfݜ.Rxv Aó7ec"~j-IUŬEϕeZd ˖d]0V5e4Zf3j<4d~`H Fב:ޟ]u,F 7|'`q#8ϣgpF`6U)[^fIn/P t,+Z -DFF$z&*v--O0}d[8>6_ʲZu8op0]&+!#s ߇w,[̔s " od"0ýy8O"]``3(7n +$@:+ w =\Y)')0\/ys9S, >Z셂A xSQH3`Ƹ,P(0q4}B,4h- Fރ:OhU!NydIv5ϖz'qWtAg+Dƙ:rnxytLT(q )#(F2|\* x6xv,OBx Q vZZRd%* O p &JJ!cIe !TI,8&L|3 ~ j2*>7A#a5Xr h${Cp@]fxd[Zo:O, HGFt}&J pn$. {;O@H":!ɈUZoV|o{VgJ> P'*U+Y>/G>\_,ԛ;{ʏeG,80r{Ygi4Y $g>E %pYU0 r;=r6tSXCC("|5:\#1s9:T9033Sdhͯ&Y'wpM,aWDHQ6xm_僮NpLNQlټ0:%]!iCR(ɍ,=|CSťmƱA"e+y B܈Ey0|)|"S?`ycĭDxt7])6X* !]c8 ܆ Mds=oݫbtITw'A"yVq%`"h o1+6.$xm@4no>&Q=e  ڍ=?#ց#D l-~!/)],r@\(hB6Y œh FZQ`^~W؞!'Qs䄈rb+3~0)YB`~ 6 kM0PN ХTb2q@X!MфE|Df5Eu:<׺z!fGM;Ҍo$lRA)Qem{`dyV4S fR n7!1W8UF %2fxd-ȷ;ֵјx)Eu *?ayx'`Qd]ڽi Q~K"тĜ,^9ɕ02| 5͔j<#ΪmЕڈrxd>DoFPO";jY*9DYʃXVq@>+=5c_ݶء"VJcœ1痐 ڥx~ZSv jΆ[bP?4 tSN2$(g&\<y~iudUd ss1z.U ?xyf8-EVmx'd~h;:̡igW"MN[JԾWl qj mb$7=w'{r,׿[ EiQjVwl 4% xme83*AČn~#xM@̡?Iѫvk400I,C:Ĉ2w>4~HɉzԾ_=&B^6Uv/ŐT^GnXh`4- SC~t9b(eص;ɔMp8,E ;Q5R 3e+@v|hE y-La%R*K c!<Λ_gxzr6No}il6o\Q 8I=6\hO1#&2gۿ$OɘQlΛݙФqH0>.E5ׅ 3a8 fq㓗35[1Q_3hx&)Gmqs [d zIEs`K{e˙-jxDe;ɱBo}AshxH&\Ca0 3`''ן.Yw%˭}/ШhEOb~Ѱ׳]z<ʼ_2*Ϲ~zS3/np4!i#)O?#AOCu&* ^xj.쓎w-8Ϊ>Bs]_;2&*yx>r>vώg .P?i;~Y]<:2Y;+DF, BCk[D25hT3y0>jz !>ȦOnkJX>?:(l:<lqx Fi8 e2OZfccBHQbo.*4!U:X X:Y  J' 4JW!( VB3v'u<R8srO5j-$qU{=N{z*4ដ*DC,E!hXXLY#~+G:y`@,FX.,2^r;@hYM..kٵ%r|/ӓVv^پ*_&Ch%([OveuJvۼX XVb^NVy,Tf)W`Є:;^x &uGn9]x7 [ZRֿ x[&H!,#DVX( ClNPv 2EOhC븴B'ǒ_ KA8JQ -6 D]*FE egoj5OsF!)x*]V leJrUdD[4 tadkvYJa5G'VyiNs)KPz+2݊ ")̼ЉeXs } ېYoץ\NZ'Ɉ{-wbGAyYgⅲF\OZ&rox֕K$(JA7jRC&VӅVGZN/TN 6h <(*D %^E e6ud 'V" _M?H8; XǢ0D{ bUl5*U9[ޖ'E~ (p{bJ҂gG_f:HGb,vzRTU[O[*cF][C Yzwc~lk muWkwՒ"X;r !"*pkKZhfB4&>Ѕ $MQ)y y5lд {W;#Dm#HW%jӋID>zm;XZ y-I+LЧRY,nL~ҬQ]{|ncwDH+q_p:G\[FM =F#8Dy7T<+@׸Un[Co&\%zO^[$qtm5G@ 3BV2ʜ[zHCwq>u9cnpv`H)u\Lq1"_B}\'ܲ(@("/_b3hQO)/X?{dIM=DeŒI)m 9k+.]=͝d7|_5% G/ K6z9}w[z8{ xx]ܺ<8 )FNSw=ӽgj?c%#TTldTZyEi3E0mtd *_w8XcK~2fo"aRj_a("Coϋ 0i պQ],g5][/>JJPX".bg_<u!e7TsS3PF9qcMM=I}+jLAV2eCocq%bDr~D[ qI^/٦jQnC5-?1klk0(}сtu`=r$>$)بM1+4=AQ9+?`3'(n&(]Ք*"&B])bI;Ԙ1h=Q_9= *Ft7g+mH͘ Wul?v@&Hp* (Sk8!Jd;lX ׏ͻ8J9=ܟc@Y!4Kgh_ Τcpn&#Oél{h0@u\,磣ëwh L!;Ĺ$F[mׅ9мGk22 h `i :d}cE#G Jmp ߹nz]m:Z`v\[kI*ֱ14zhׂ嚬/63Kye{E* < N-9ĂI<Cփ'j`x㰜$f]Cu>=zz_I%@ P835bATn_g2ҋUwɶzgaLfgsHT$P }66<&]u4¶إ[W̵ẳ+Z&TBF"c*O~H8QSG`A(H]s >18pX&T2K9?ͪ ~`) h޾F#̗9R:xJTp,Wq$"'_ZQsaꁀA}g$z ]Xtj/'m.Jy|*v.~&ax }4c'eş乞&Ml#gp  hQ>+Nز[D9tə2OĹwBԭX?\}'{2c$IS3Wv~N [ 㔰JƲDg=( 2뒅RÏ:uBWA1WJJG6@m O }ux{<'l%<} 0F>A|SԖCp'p"5{5=3DCnM M,ix9Ҕ뷺N_9c9[W%{ǕgQP{ۙf:M4Sy -Q_cI2:t,X;|J0C/@hetLߟy|0Yٛh Z O>s_l&_ACX <|JU',F s }dx`l2`m``AV(^BΖFn+AJG'Y:wRQ'vՎU(svӀ`,HIp#yr,:gxr]4{xnDˍBc -4# nKCDիշ.o8Fٕ-A 7K<~Zru62ϧ~åU{k]`1ܢ^dj?#8ZÒXK+\lUX^W-MF4Yl 3YA{HSH2 ^xڡi%ʮgTwdJc܅ʤ x\ և!(CbU4*b LT9+å928N6`TdL–DD'=#YfX) rH-n=痳{v;QcP9du`T}Zp1Cu=;݆0"r<[cN~K3)Dr8K-40Ȧg/JšĠ[Mt=]:;Rb<9]`]zJSNwSpX?-،]zB%N׭P?}6a Z^ ڋF+ 7y_o_dYNcFRx6KoT)dw{*MnZ͓fߑ |@b__-IZ J/;1x,L}pxYUŧL*I1X !i86v[-˦DDE_wM]9)[9bؑ01'>,M /κiGEL E*d e1 9VU%t2a#ֲmG0IyjGTIOvմXgSj'rzh|ZMSP?t5X- Pz@VGD۵:,.}fwlUb% jv@#ss&Xg4z/Iz*Ւ2QSĶM6 T#0*P)(%67.V3K$hn<*1J8ȥ3"*Hk^c*6j 8 8,woa{,q7wO6y&ķ64! 0iG BJ@V"fJ;EV8ˈt"7|+LptAzŶf1)614!@u66952&{J9#a|[Y9Nh3T _*\Hu|v<ޢ=ZW8fƈ1VQy88j6Ȥr A!YGh#ss˔'m_|_h&Gԩ}wVƢ0(0PESeq[Q"j poVZЬNH~y_ h 9) ƦLUCI)Dj YU\*"ltֆ ԛ=WYjRh;$?z( -q:b^,x+(3y0, hQ~B`c2%BP5Z'@w3I<h 5嘩p!g< ~\tq75BD1`ľővQkqxrR:6AWx|xQe*5\m9&j&w wˁ@[0J$1Setbemon-1.3.6/.git/objects/7b/0000755000000000000000000000000014174476517012662 5ustar etbemon-1.3.6/.git/objects/7b/1d76289a3b1ee985575025a089de0f22ac19f40000444000000000000000000000030313212006633017633 0ustar xAj!E Z] CmVA5!ml;anCnZ{tԛ9p`rtu>4&[(4yÌxl^XDZ`^v~l-0M8?~אnWetbemon-1.3.6/.git/objects/7b/9d5955ce7cb2ce01694c605e083ba4ef2789c00000444000000000000000000000026213642215557020020 0ustar xAj0E)f"u7tvyDq JtU#/nJB!ZqBh%ĉ MpjGQ6h>t sN3k#s-3MWOӯd"_3˘iji5f66 lvdN8N6=% ,Ӏsl[Zʴ'z5Hnv[4fӹ#Nɕ0ƍ1;=2aAk}q $SQۗ TMKno/uESp%#Çp0u®ھ\ޗoKj-ybWjNJHv}ۅ|j<+YAP$TH2nM/76EXa"+ٖcJH@GA8W&>Goi џjǼ PLK]y=_<8D!_Gg'E$-&-47DS Ox_R>USY}{r(5y䍓s^8E'k9[ ?-׼ϼ*rIa+~.6\R炪e }s04LA ,f yq@/tZ*'+*E| \D>etbemon-1.3.6/.git/objects/7c/0000755000000000000000000000000014173221203012636 5ustar etbemon-1.3.6/.git/objects/7c/259434c66dea7abea95d4f780408eeac0e106a0000444000000000000000000000251313212012742020124 0ustar xU{8TiplfL*MEd,!km.+. fOgs39LfHe̶YFV)JJ[h5\jCzj<眙98}x{/YP,LF S=[-K>wNM? TCkQLKشH뚣p &@0NTnݯ4;Պr;9MNa1 Ha^͍㼭vؘxMMo1+0/$ri ^?NFx:4B W1ѽcxܴ٬X/6.Ό*2`UV:[ǻZr5c=ɅbJJ$b<:C!g|yg7Q"U fXt筛^w_Ԇ6jJjK0d ܧ{?|IeKU;u4$1IN}T^Voݚs#`mHw; {rҎ46NcA\3NpȉH8YtQqo?Kvx2Lg]0ff\*_F+Gv[`zhmu4 {*YMhȱxwm! t26>Qlp`CGFjoN6?jsv$&HCH=mG=|۴]$j׶9^PQdKC$*di9G hb^ylLg9WQ" 2:_>h|eSzl,8 7qʒ}1uO_DPܨ]/'L*JK=9ؤ63bo,;|9OɶoInuf 4-n44)0+lF5vLCIҬl1eZD !eFǼ숷1_#Zsn69~3vPxxm(|@F!+ Bj=\滩JH`@@0ҎKa#wxpRw}D_jetbemon-1.3.6/.git/objects/7c/56a3b9f602d1fd54afa50af4db11528fb127300000444000000000000000000000024613767550472020051 0ustar xA = &e?CEd yYe/qMRG AB3() ^Zy@=8t4Ul B1!錗>r}h-?S%| y~:~5.k+ٕ5<:7 JLetbemon-1.3.6/.git/objects/7c/5a7f2862f0f17068d8e21644c638bc3f6fbbcc0000444000000000000000000000141614173221203020061 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3'}gWuO=%RlrNfj^I1ó k_>v 1ٻ&_HIMLcxv_e!ܿp[&% ?3nSXv8!%@YelrRbwdy $ 9r,Ԋ 9ɉ9HCK_lkޝ&W}x$Ov}n*W4F 5rpZgOUXq3jFiPA ˌ,f~ wm1DEq 0%.[:ǐ[]+ UQY N/ y2ּ?)$3a^r;'D=b$k1_k2Zetbemon-1.3.6/.git/objects/7c/819bd6a4e02b1db566f559b99201e9ff5d89120000444000000000000000000000254313212011530017726 0ustar xU}4Tiid3c(XckU""vi΍v;T+JLm-#jC%QJ$JsKmȡNmΙ{gg<=y~G!R8\.+ A`1Ds{ĥ oh ҥ %dD&qJy#xRUKzWwQ"tD SIl#(]޷ݙr1QBRR8{U3?n3ɉ"]_K4@AJBUS/Fo_ӱDcN{D0s}I>Rk-Î1ɮrh!\G38$:`* MH#RcZ02 { .SHh:[`\2d}˛ZuPIx=)$1O37ݪΣ?Vb Ih{_o4.tEjq7c\KKiU[jjҿX*"ջ$G]+Q3d'&n϶V jg;/|xi`||'WIs6fNjW%ږQmBYhOcS, Be̿SXN8J'1K26}ND]HCxDHS+,g2 U1m$ M"&ƃ/Lk7-$&%_R_=3x%SX{[Γ:-r H{:q-r}MtA;pA6hO껌XUnCGjOm?̟&n}zwp8"p}jj_:铀Wmg"km&׷;[SQ0wyF V!M|J9>3jTC8/NįY&g]F8TB_$Ni}vLvQ ̙͙,I~1w=+lONoaдI5`?XN,3BJ}ʊHZJfm_F*^7as{-ͳ5a?"1HN@Jq~'Lm=?x,P i;_ 96ؿ?ݵ,0'"RblVhQkc8dx'N= 5]( B}=iEwlyk\5Yi`# NYǸ?ۑz16C'6q St8$B/X*vuh,K-;C|æ͉V,=36uLBT04'yƵHɐ$ D\6Q9c0-ƛ*!W #qT ߾+4Xԅ64$etbemon-1.3.6/.git/objects/7c/8a4344b764f75d6b73a3f02ff5c2f30395ab870000444000000000000000000000100513247732002017720 0ustar x+)JMU032c040031QH,-KNc) e٧:&}s JR+s rRAzg`~$Gװ.DSk`x \}tk۽3ˋO|,TӺ qƜ)hb y%z) ϢW+*!~$|cΟ\uѵ  M;UgTutM1[82ٳe=UPܪ$+ϸF],3 U_X_2٫B??{{kȯyG`RK Ҁ RxݭKGܵr7Xf6Dԛb*,-H,..HLV8g8E GE!O#/(zo\+»"!*K,:ufvjy'GF[T1V8+㗏*-mݱ8'?]ę%@3lVr|i?7֭Z,R8PX/3]𺫿+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35ݢ{%\\q7tW)Iy [x^RQosIϸwҧ@'3<t,/<O%D6$e{\]OcbR%K! ,QH;7YR`;tz_ \uy337[o'\GEDӎfYo.w~#Z9 5 :`Oetbemon-1.3.6/.git/objects/7d/0000755000000000000000000000000014173220144012642 5ustar etbemon-1.3.6/.git/objects/7d/2aaa6f0f856c388f7740f895f3294256e747940000444000000000000000000000073314173220144017542 0ustar x+)JMU032f040031QMNMIexwi_EV3csTT!(X/7?/$A-3D7).HLNpЯxQĻlNg: 게ݒR}U>swX_vkh 5]9-GVN5-VaSSԶ+@a*nM|"zGx̴SXs CUGl~f|"UZ+zF}4|+T N; {S=YjSXT\W٪i%Tx TIjEbnAN*HClϜH݅hrFxzWCl_?.v6d n&C1gᶃ&Bf^f^ óJ _' iy WMSKkoyi#hLnN)fgrV&{,V [{hyk|9= KKAfZ7{^'~vo 5LYjIbAA0A ﵻuIHV̆z[LPy)` gY\#!9b$% Qzp}PxW5_;$UeE U50δT-4s+4 v%r1RX;ÔU8$hf~^m{j6[;-ƺUs@Ug +e^w6,&Teyf^J~y1ȕRw)`h_m etbemon-1.3.6/.git/objects/7e/738f94bf2198f4f03555c71529499c8feda7dc0000444000000000000000000000026313455035516017772 0ustar xAj0E)fxV@  F ˤǯKo͇u]s$қ*2!0B|"0rJ8ET󐦥C2{uS !NE%6x߷MnK?_<Ǻe1䬵8~= []\zOi%yOetbemon-1.3.6/.git/objects/7e/7b34deaf63db98f5b62378a6c35bddff26f1ef0000444000000000000000000000136713462027016020406 0ustar x+)JMU0400ef&& ~zyz =k[7\ RZB:%3]Y-Rj[/4*Ǡ^̹9>H^yUeFfDO[,$faueP$6U}%O&93g̒bOt3 S[H)-.ͭ@b)/z7;9USAbzf^:(%a³EnM=jP($?9?!ڧ;R G;2onEUZT wAZ ٜ;&YG\},ljsSSh4dg$&%I V)1iccڧ]j H_Yb\miB)6^\ f#?<(a⬷CX<:Ԟ{l=%|WMieqN~:l٩~OoxI'Nowf]LH/% 8% >7$ yb< 讔<8TgQB1^6 5X.VB:Mt~1E ij8Dba>/*- FVilJ$bUac0Y<0'2Aq4'^l<;57OD@5G$ 6-IwZTk6|yL(ly4E17jUik=#l7S EڟSwC@.[~[+]Lbጐ*3~jMePD GP V 3J.nJb9F8f8%(D@E"- Ck[Lad;tC8`(K\xd h-|w}H"uQ|:~>%4΢(_}UA,oPbD:"zPH_5 hFcUAxT.̀PxTwyE 1)r;D :/: m&(CXc^v2f. F\duѣS\{ #Jʵ)>7iKL 8|B2ձ&j}55 ET% k%&.ͲHgꐞƽ-/㱼St(FU;5(,ᝃE" K4OUiۨf0Vn%D T,]F)T4qYuzfAU2d:PS: `lZSV|~w%Z?WB#t "%|>2 mc:Izt/3_㘻9@PAKdB0a`" 82;"ƵKX+f(ϫMgr90YB[P^tڌ73aܣ%`Fԏx27kIBe,Fv Q#CK_J<:&d##U ")WΒ ^v;fpw(Bd9CY2^sWESSf6/UFxbx,=|C cťmDZ-A*x]"ܞ͗90"yj vB lTCàt4,S,5P\ BYS*驳0grA~ؼNu%`"h o1[g)m]8JL݂([i ݞB1y]$e.Zow` _FJx h F׿iB6Y"œ[Jơy{yQ^Qb{҃ӆI \t|+,^ q>Wc. #L] Z4Qa1[̯%Vh5юKvAQ zJCJd+ȷxB1tE|Dv5Eu:<׺z!fxk&mS~4|81TF-etxT'`Dq>YރY)Mb6'%pE hWIN XTիwe@J(05~[ܝҺ6׺\ =_ Huqa}A5޶zh+t%ՁZ kxf|̳3xfǓ+adz&)I<*#ΫmvLW}V#) &H0"A=?f oՌN}p[E͠w3nǏR6Ū?ț)w@`%--2WavKB_b`KpaKVx`= y΍aͰ@Z>8~&ep<ꁷ\p)- 9b&O{`y P:>Z`0-wW,&QKdᅌl_!m{vdqҤoDy-U(bS֫ P8&-0!R,-AF %hI|l1nZw.3_>sPz gvr+!r}~5{ boZf}C@`#TT+$aܼDhEkZyt;Ċ67WI8 NB/ޒ˫+@(9,-s{VGܤkƘDX-޳چk»]7GE~ |M'ߩ`$NUN?p.%(RM4\o941 ջ~wF }cR:Ӊ$Fxy1wb(\Y0x!{3D..2tIspKRɲL`ERgsɽXoྠPC4000'%@)3pL'&grtNpɦ+Q_nUxFe):~RsOV:Fe{" evϟU1s@g^!7D^8ZL<|H}s"g3idKm^zj.vt-8Ϊ>Csil?H1JMW| 5=^-8k{gUTd?0h^ IMG D  S!mVʾ#a$x`otpimT&hۖ:,<&R.m %oKX3Ż{]pȱ${tl(p%4`wjQ8 (yi3,TBW3ﴧW)r|ҿy ?2K}Ql;t<Sሹˑ~pI0 Mug#[,PX%S[|:@riyM..kٵ%r|/ӓfuv^پ*\h%([OuJn۾XpVb^NVy,>R {u,r'v[MV/+.lmrn^[8vFhI+:A2`'Z8# .IE؜ k@dj+І^qi/ndSO%p8ZVm7ZڹFSGnz$Lצ!GV6b٩aཔ{|؞$k@Sܪ:8Ct vH= wR=h4l%@ҕ'z/߽ hGȖ7GϪ[MQw㘾jtž̧B\ו̸QqbY=cT!5A7n-[9Fis"_r.tyT76z̚Nnn׿].lnM[F2=&=ER dخY"T")=a ݮ/2vl3@s'uWUC;ݛg1` X dƶ|P \Te*Bj~7Lƅ*R:+gQF+{$؊j ZS cQ={MIg^6nUXX-eI~RmJ'$-xi/~Dyj6HtT.D[@\Fb RyKe hwܹkg2{cB35=4|\8|ᰍ^۸NjαZRFkG?F@ncIKN=!T|}'!ljE^ ϋmOpW#qMwu)ï59jduٶzIfRfG+tG;UK +ڤyEI74yQw5l\a7C27Kir BBvuɦr6"/vZ~yqm[i6)6%ZK]IRmNor3qܶ,loD/?_w[8nу肀!WHL2m~4l6R yx2&^| A}fCn9\|yy Sz|W,,'񔗬4P #KjmD!Z\,6p{_lAïֱb ѵMܣY~gnS \BJ $Axjv^*օ^6>BV4pK/gp`( ˥wup,%sz?$X(Fhx:D#,+|Ѿow^> ϲ !=(CqrOߡ539m]>chݣR3 #cа6+b##MVّ(e F- )e~l' rYVaEsƄ']ٽwaaN{VNϩ&"Dez7+) {$W_%yAh&Py[krV5 `Rrc!v+:'\,hqU6Flc{_ؓ-dD՚)4FVwg`,[AѶC4Gus9NH;R[8FcYLHZAѭwkN"MTrXY0[OS!+uuÖR0A-;mQߢfBߒLXHP /x(ifl.C63+ySe^G <2 'NrtfA8MCփ'la9i Dͺ2fI1=yz_QzH7p,gjl-Ķҩzϧf2ҋ;`[pLfo ]Ib<`m99&NDAXt.c>7=i6Clx9ҬC8I n]eƧTMvW`Swۙf:m4Sy -Q_cI2:t,X;|fr,LV&< -)O>sOpi!Jv>UVvãsYK~d`ርl2`m``AV(^Bf]+A#v,LE(|+ .;ཾQ`u!tNqL\ݵ, oX9U.E_o h@i-7=[3i=ENw% UfϺeW9{,$w il__}>'^dZW?|(]>Aۏf 8czq^?<<,_4BOV bf zzSpdsrҮ4 {H `Of5Ȳ0') Z 9i k}rV+seplȘ-NzF̰z5 y)sIEfxJlF^D=>BN u'TH(h?Ԅ}e-cdUEi#/Fnؼ/G,VOy )#i-$\Nh;4 *_p2ܻK؂=A?&7Ifyjsj#1į/8EKFyܝ~2 KX&>*w8*pm Hgmf ;ՖCzS"/ͦYӃRJH%cEQqL&D;v90`_kybUU6Hw+Z&Yߥ.ep1Q)R|F3]=z4>ej)(O(yMmԡ3n~"FvtF]5gUX 6 t93u=$= ^wuAjVWYĶM6 T#0*P)[$(67.N3K,hn<* :)J8ȥ3W"*Hk^c*6j 8 8,w3hb{,q7v pmi )"@`0?,$ d1kSI iPHW!p* /qpll14AB} F2枉OFL(Sb=S?X1^TBo5bġ鱥§_o DH(=!ŵfetRGRv{J`09u4r@͔jݿU&Y瑱$_Rd )DjYU\*"ltֆ O})4e.wZqu#4RAE*YveWQg`Xj2XeTC@9kGm`TO DO/GUHA.L?{࢔)x:?}% &3} ]Ã40cC0tgOI]UK6Rc?obovobC}g=h F/ġl etbemon-1.3.6/.git/objects/80/0000755000000000000000000000000014014616652012566 5ustar etbemon-1.3.6/.git/objects/80/0946e8e1cf1bbe06677f749e2f5e50443342b10000444000000000000000000000060414014616652017566 0ustar x+)JMU00e040031QMNMIe8;?nN|:/wrq7jMMJҊr2KĿ2sIt#A KII-IMM,(HMK.(`uy&؟jRtW8t&095uU}/B8Ҁ>).HLNpЯxQĻlNg: 8'3B$5z*nM|"zGx̴SXWuѹw61uC !w Qls:M6 87$$nj/?.>p Lm~ZIQb&<TT.X{=@UɊWjTATIIa _TL=Betbemon-1.3.6/.git/objects/80/95ebc7c706f8baac52f422fc6885c6c8293cb30000444000000000000000000000031113617253321020066 0ustar xJ1=),LE7I:β3%ɠ<U_QT,v頼fqi)+ })M1(nTy<*̒gq4,Ie})ގx]\SGbNtGR+ Nj˞Q^KoP2ąwn#peT^G}78[etbemon-1.3.6/.git/objects/80/b894fe9b0c34050e8152d03311fee468eb6e570000444000000000000000000000141613667336125017654 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d`|z3שܩ5jϜS 5yBds2SJm0] )5*DEJjRfb,OmwsS|UPWmro}_)W,;}Ԓd]^b&ٟ۫viK} <]s׆}\Əq{GjE@Yݜ`X\w-3#9YpU@yU^-]Dz#W\/s];WM;wSԌ Ym9v+hA&!c`8a;K\t7!'8/`V) n ^q2e{yES(DEiIfN1üow>hOz22Ib"#p[Vetbemon-1.3.6/.git/objects/81/0000755000000000000000000000000013212007361012555 5ustar etbemon-1.3.6/.git/objects/81/23d164dc24fcfc62894604099a80aaab5033d50000444000000000000000000000075413212007361017621 0ustar x+)JMU04`040075Uc}SIt^򙆲GߚgL:D!$C/9pؗ)dv$Jp *IH-Iz}\w)^úPSMU W7lpu;)mk+//Jf>POn2sn;j"T1 K<6t 7^y_}uLnN)fgrV&{,V*/14$٫B??{{kȯyG`RK ҀARxݭKGܵr7Xf6Dԛb*,-H,..HLV8g8E GE!O#/(zo\+»"!*K,:ufvjy'GF[T1V8+㗏*-mݱ8'?]z%@3lVr|i?7֭Z,R8Ŭ._gx_p{pۚketbemon-1.3.6/.git/objects/82/0000755000000000000000000000000013651535662012577 5ustar etbemon-1.3.6/.git/objects/82/8cb88adc26dbebf3e8091b372969a9f24a18670000444000000000000000000000026113651535662020033 0ustar xQj0DS %m$Aޠ7$JTzcfmkKt*1p*쳓0M+[Kh^YeJ).eD+`t%{YlT5y>>Dx]qbHup cYؖ@T6XndoͮRetbemon-1.3.6/.git/objects/83/0000755000000000000000000000000014173223022012560 5ustar etbemon-1.3.6/.git/objects/83/0c0c53dd67d6ed186fc46118a638ce371139370000444000000000000000000000032113212011234017543 0ustar xAj0E)fRH!@Vz4JDbHrz |໼,NԊiV U8mhF }r 8>h˖h)Йi0DfvZ~sICÓˎ#hђUkm^_}T}YT`8y`É˥B=|qI1] 5K .]etbemon-1.3.6/.git/objects/83/3b2f56c704891847ccfd417129a52366dc87c50000444000000000000000000000120514173223022017506 0ustar x+)JMU07d040031Qs fi^5W~sn)-H,ar==8qy9:|6-+)a`\ydzg˄+),L(a۹L芰"N/z+ԠrRRKsJ:.V9c ٕWjp +,*f$՛ұz>AE-@V\̐joʫhrgY#IH-I-f`Ѿ")p{Rܛ.3$1'g,^ʀG[9ԝ >,,'3/a`jĮsʯ]j dCܬ+ a?+:M]Q.CxC ٍoEUl{x dUE`êTU}޼ϖCʀfU{nKK5*275U(*ѤٛTVoZ;vo&@Mm9)̦v=6/It3ԚĒ E{0':-qFX+ etbemon-1.3.6/.git/objects/84/0000755000000000000000000000000014173226610012567 5ustar etbemon-1.3.6/.git/objects/84/0eabed552ed394292cdb75f7edd7933b35af6f0000444000000000000000000000030714032516037020233 0ustar xMJ1]o"k7ޠtǛ⃪Tΰ;d&J2*EƪѰPvɹuѓɫsK\1PΒRR9'vƠ}/R=nxrL0𬤔bs%OoĔ_l20 2N0Ɩ6&Co]etbemon-1.3.6/.git/objects/84/0ede370186a6197827416a3a351053059c8b6d0000444000000000000000000000224314173226610017336 0ustar xmVkO8wCNiffA<>m,;osFHM__97fLw~[=mNJYJR'ҙ n,ѩdJ4=}='+YWW W =VzB.eenfUt ҒO+-)5 QtfB;K3鳢xW\Y ѡ)*5]<;bc>!\ $!':2SvD.ƲfTO'p6{sS:u:{y|vO/vIa// 9'JRt(􊣪OsMF>EѮ(]뵰52Z Sr8)?(HYfWwp[72+tgۙynӨE5^CaCxxGsg. Th-AmH3B(-sI?釸TwN[yx;dWv/=V9}D7q]=3܁1 @q l)RbMiOd2OjX>&0S0icwj)JVm#Iɿ7ZJ1bf3,iUrV &C!lc Z6h' mբR&l{CqI6?$ZU)]JmM`1 sB l Z޲٤ $[l;jBӢxQQ?|1v8t@5y f8`HDۖpm`p8 ^t8i2 iEwt+)8*G=ynI]B)K˚>=o\xϯ̀m9zy\ޣJ>Yd¡ew axku ~*7HN VVL =aT{q95ZZL<2nMDoaPtṼ:s>Dc3ȇ oUg`&X& i ecobw 8a6e* p5ƛQOV|w5ŘJ|̤65}o8Ʒ#~14xYBetbemon-1.3.6/.git/objects/84/a13fc7e338bd371520116458cfacc517ad82e30000444000000000000000000000036513513716435017716 0ustar x+)JMU04c040075UH*)J+,/bw%>ؓs \vXUX\ W̞abƋSnmr8'3B$5z^ݭ9U^ OLI,K+}䴆9_ۥG哖_UZp<'N83=Oc BU秕%fMTaS`m^TUU'+^B7b1aӑE O7Y|etbemon-1.3.6/.git/objects/84/d301dc0016ec68e261b6fb67afbf1fb0e628fa0000444000000000000000000000141713642215544020211 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d`|z3שܩ5jϜS 5yBds2SJm0] )5*DEJjRfbm]d e8> ?3nSXv8!% s+xY{hz#7?aޥ?4l\v޿"{@Yݜ`X([ןy ^=|^ (yItϗk{pvnnh+.HMf9pb宝˫;) jFiPA ˌ,f~ wm1DEq 0%.[:ǐ[]+ UQY N/ y2ּ?)$3a^r;'D=b$k1_Zetbemon-1.3.6/.git/objects/84/ebb6e8cea030022690983905bfb3536fa4a9990000444000000000000000000000150313455035510017644 0ustar xmTQo63šCZr`fY{ȓE $eQRg `I;?~1{ j&; ;ҶwA}NPګ{BqGq:нy4' h.#8ޝw)Z{'_K<ܪ?/rLHK.G7wE_Ɣ{(Gt)H_V}'8Xc?{z!,kʉ-YMWT5r]T~}k]Cm赞ؗW_]V -oxs؇(S*c:qyx"q.K4Pv(ZzdەC^(߁`$숲6ߩGڭ0Sy4/ v̘zjLlktNml [=> v2?s._ej*K.r5 ƶV߽D& O!_YEpR_r&etbemon-1.3.6/.git/objects/85/0000755000000000000000000000000013767534550012605 5ustar etbemon-1.3.6/.git/objects/85/17f60b4158c48f96d41cde839c7dce055e8cc30000444000000000000000000000141613731635021020024 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3fS7SkԞ9j*.&d3<`JmSkrUԤ<熧N*^E 9 jZk0_>\??:?Wndq0sF&>k9.,Lƌlf;f7Y9?4QKұɣ0N3Df&fD#~OZ8&4o>}1E<{Y\`4g.yMMzee0OM7gVU7 6PaI^i[od< aY<0G/4Ahx?&Eؼyͳnw2/hrEi̋h62Ej0tEf &tekv[<2=(ly~*gArhLSȖK. I"2` [ <;+h.Qym޺%_Eڄu.(S9kZ( ay:.0Kp-3;r8|#N᭬$E\\B1Q99$c3T@{7 OD➎COr uBfs Ng$*'h. ],XOyQ@h3Cy!<ImC;e&]n`r|(^<\ʏ&I8,x$!ƊAU2dN:PSZ;t>FAZSF|~%Z>ɱAT6hI88LX9D-1f4&,ZI)]2tz\0Cy^%lFO>s^tRoAx}e*S" +Aozs:\A])Q#:6/zݺGǥ6xSz+x?YbYFKx$2:ʀtF,N©7Y{bDʁy9oSoKc;@js87'( 7>`AoT~ ʏe*5$ E E6V 4qO&Ytd,PQFUאpċx<>3PmgP)Q|$ M28>Nsϣa<^c, -`WD^e~*G]#U8ŁhKB@2]PԃqU /Nߌc΃6U) q#r, 4w'B<}J@ q;ɺnxI,e3Fg Ow Jb8R#P[/m'قN 9 <FvrfL.(QQ+776. E7 ExCgdnKkTBO똺6*W,_QGOgLpd zϝ~oꗍ.vi4*Sl D,'7ԉY}šywqI^Qb{ |5ǧ 1pJ~xqor=L] Z4Qa1 ̯!JWw+hhEJ6G(P~CJ2tP+s 7xB :"eEוgk]3SO}Gy>maQ*4)Q_08,YT"w$zX U;A]|W9He滂zo˭g)9 k]g FJ!y.9.ݛ6Qm.d:Pkaa'<;W`v?\ #w.3qL'QtC^nlt7YL1AZ"Ud5yfDtUD :*j=#f,&f}[P(g%ppSf2n)VPk #B0$CPސ,#XMCskX1{Zp%(gB[CXx G_b"~r,SD6S|N^*e`OS<>^hOAM`q_;83T*O7THFzwqV,©WX%O M>ȃ\|15Abga"Npxʣ$ҙw ),(K`!<'$G@fU!!3C7F^ W뇐Sdn(htJug.u$qj~ ? o 謩Su;Ƈ5bO@Fo_5:[=zK{I-ʛ;! %L$3CSܣԱevxi^wJTlPփJt #G7^Z>}.rO.љyw+ -JܪDe5!7~fqXDȓt<^es7MT7.,e5*n؄ Txm>}}Ľ3Qy[}gҿ8N#Iuv_ч3•tbFeU7pQ!&w X\wwk47I-C:ĈrP/=ՍU7lPJ| c8f m?y-`݋e~1ZyI aURQ:MK)">ŴԐb?wJzt;ɔMp8,y{ԊQ0sILJ!%*b#`pKѡАAsy)%lDžgL/3<./v|SrWe#\Ɯl)f$ČSTx "1esE& @Cd5ׅ 3a8 fqW}+•5BމKx0ϯAnൗ| 4^-8k{UTd?/0h^ IMG D  S!Nt+eߑ}rpQۼXpVb^NVy,>R {u,r'vMV/k-@NkǮ-)at%]%H!,#D"wDp qGQ_:t9:W ח:^ ɦ%p8ZVm7ZڹFSaO@|'+_ ɈT7(0]+ ,\4f5;,ۊ MUl5;V{ ͻfGkS\9cpVivHN~G(40ڗP ~~˗br;i=('#JPl;`hӏ,8ϴۨ IW :xKR׺r bU)hFMjRـjjHR3@3]H[xPT@~Kz=EhAktm:OxjmC( KɇI/&* 86&^TT )$^רMAO+* [ P8p7`(?86E BApzu7[F'칋p˥$*]W2G"G%ߎq4A7n0P\PWtk'‘ImNeyc7 ȬY8Lu5Q"B@2l,w,䞰|[n XuǺ+ɇ@roY ظ>.æƶ\b (d_2!|X&LyqKkE}D `+)pvhM+EA@p7b䦤xaU/zJU,m8? {_`1p{bJ"C j`yr6HtT(HlAʥ(FbZz:[*c][!ۙw^b? 6~XXPzm: 諵;jIa9%-5j3!WR.X._Iko{(üWy5lд a!/~19jduٶzIfRfG+tG;UK +ZyEI74iQw5l\a3-y:yWYoj:dR9@Fpk;W r-1@JQ@?$"&=ƈ| A}f}n_|y<@89"X`3hYyH)/X?h*[KG$ڈЍ#|L%ٛ3M ]]A V 2  W+4=A䟿I0sc7Sp| ɦdh*¢,r_c׫ XG.p﹣/9kEKJ QihARiM5_pO"&,Kt:C\o`sR{q/YEDm RnDMpsܒԌi rZǶ.c* d&2bɀ2lI4KKC>occ3\yWVe`N=) ,^ jFZnޚ7z|4x?ɶ7 U"^39m]>$y 4Qf 4͊Hzhv$J zmeiٗr@O?UطpƲ y<%N'6f[~9 ڝNUMT7t;gc=MIohcB[JգZ%$;mQߢfB<ܒLXHP @[sUl?^,AJve2;\eHwÕ6\wvtB4JU(Hd< yL߲ я8j/,nQ]agn3 L'dAХ fU k{Syd39xml3_t"|q$"'_ylV;pڗzF܍F^N*c\ $-_t6XӶVfvä󿇴h8IMs'w0EEd r[EyΘqt >WG|0@=IOm)  tjqBʺ"55=3DCnO MP,K^$: n]eƧ$sC4ס lNc] ph:Kұby<(I ѝ29p&deo0 G,|u a5X U cEX\ +%,{Glek=uK)doQe. `v(TT L_Ip ؗ-Sfda*zEiX;\))xՎU(sv`,Hfix+XAOx,:gxiEJkAd4ܨ! Ù4# nWWg]qzF]=n ;x|My~g.y7z"pbxۏf 8RGQs[HTY_'SDVlUX^W-:&MI&"'?F$LVP{5w4dC5Jh(#]u~ښ{ZK+owXt%?u!g%rfM%ϕwz~~A+zh'pd^!zWeDK1vL/><(~ǂZ̮71G6''Js.ޝV^FPS8hMϊ,[{|PQ+{بՐ]#Ͻ)ׄXWHOr :$":Ee`EbH$GjqYU?}۷݉3&#=ምUz3 y)KIT?-،zB%NשP?P}6R.cdUEi#/Fnؼ/G,]U(|w򘑴Cy h8EݥilഠJV$ ptH(}'@wfg'pTO/GUH< -?gȼᢔ-:}:T1`ľőB17Bf 4& +#3OI]UK6Rc?]s]?lbX CrDsj <RUetbemon-1.3.6/.git/objects/85/72b12796184a96a93f036a19aab698820419910000444000000000000000000000063713767545036017321 0ustar x+)JMU056a040031QMNMIe8;?nN|:/wrq7jMMJҊr2KĿ2sIt#A KII-IMM,(HMK.(`uy&؟jRtW8t&0lK׹KVz|%u3Ҁ>).HLNpЯxQĻlNg: 8'3B$5z*nM|"zGx̴SXW*BWKYhh] Z*-@ ӷ+dr9{lڤPUŹE%%9pJ~yf) ?rP?"~gw]0 i%EfPaS`m^TUU'+^BHSS%%uN׫i2|Q1= Petbemon-1.3.6/.git/objects/85/7ccb2300c408cc175ad069b725a1b04641a0f40000444000000000000000000000024713513717241017605 0ustar xAj@ sW^0+{eBמi-!q\ס?q&rvtF'FCX1u&1kȌ(hW -l$,dtZo?>g~cץH}"$c8qY}[<[K etbemon-1.3.6/.git/objects/85/fc461036a20c9b5e067996ab22d55f6552c1650000444000000000000000000000025713216420330017475 0ustar x]j0S{!x^A) AoV8*|*W1궭o¤)QjB%"~.Ei$'MbhmvlFe%$ײcV|;|_m~YDN#8bwi2/0^%g1kۡW^sMletbemon-1.3.6/.git/objects/86/0000755000000000000000000000000013216421171012565 5ustar etbemon-1.3.6/.git/objects/86/208db2e22cee8e1ffc38f77be21a3f938fde240000444000000000000000000000113113216421171020222 0ustar xSMo0 ٿ)+bi"a@.MdɐzM6|z̥a6!9?} cHW <Ń0A kСa=_1ZwI km@gXhU³nܬO+fS3.X8U`ЮFF`CHj3-0rA40hPx@GKaY.꾥ϊIݏ JF"wP.rapr FT#L%0cq,.]R.H9)9|ć"ٯܶpn<>:բGNmࢠ FI.83h0Ga  z͖Y[.7!fwֻ0JoO`LNO~w$YN#h,Mam.':/6wΡ{fP+ ׍(+t?JS6 1{YҰcn"/Ogr3Lq*Mwd=cEXletbemon-1.3.6/.git/objects/87/0000755000000000000000000000000013731650506012576 5ustar etbemon-1.3.6/.git/objects/87/7b63657cd545f35bcb5320d802d184549557250000444000000000000000000000024713731650506017362 0ustar xK 1]s!H?AO z: 3F2oQ< <(6VE;r ZysVK&T&+xQMh8YRΞ``֜u_mflP,hmR.K&8Gp?<\=Gѡa'QWnKyn}Jetbemon-1.3.6/.git/objects/87/c9bb04d4a3e15ec04cd908e155a016c24723900000444000000000000000000000141713651535653017634 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d`|z3שܩ5jϜS 5yBds2SJm0] )5*DEJjRfb}rY3{h\pTA~2C]ɽɷg|ݦ\pjCdSK^WTO ; ^?Fn~ԽK\i,'qqE 9ɉ9P+Θ<{W蓂x-{#4|mR eݸ[@c Rxe|Xbkiv vQZTP2c9˽-n>]$b QQ\ g=lǴ˖Nx1l BUT# B@}5c (-)f QOX&ZWdxqBXKetbemon-1.3.6/.git/objects/88/0000755000000000000000000000000013775160226012602 5ustar etbemon-1.3.6/.git/objects/88/5113831abbba20ef280084790faea94546b31a0000444000000000000000000000127513775160233017626 0ustar xTMk1; I)44mH "k^QJHuLό{h 8ڙ7o߼ºLOOO^ .ne魆UcCn蜻?MU9p ҁ2)Ѹꀙ ;Pgs"8tNM_ma0NIKP{P.w /dhT0]0D\&3 T=0"JyS&jHH@D!.MZ)+?@aAV'ϩP ^N9 /) JD~ G' Mζx0H>B6ZbfHsSiXW.EÐP@?nNF4+·"PCֱFঌj.I<:@\Ge1d:`AhJjHVɫIcPJc18RgA,OmY:zNyS!uK5imN$2;){(ܝr4@IYô{#qtSW1uMͮ t r.H;J,齹+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°j]͇{V]|)eg 175*)I-I,IeZW/SrP]t"U 2Xr?36$L!.D69'35!ߜ[`i7v:"DEJjRfb+״T\3)~P ie8[qoD6$e{]$b QQ\ g=lǴ˖Nx1l BUT# B@}5c (-)f QOX&ZWdxHU3etbemon-1.3.6/.git/objects/88/d17872e989d998b6c83a9b797df0be6f7928080000444000000000000000000000032513212007456017653 0ustar xMj0D{W ʵ14P()M#܋lY Ҫ_%vlB $ !b YR"j}$+ԣ]`l䀆]x?ԲUWU&3t M3K7Vp_fv>b.6DHu%ZF럡JZb&2]?J:X.'evus<|?O_[]Uetbemon-1.3.6/.git/objects/88/d7929b8a96cb1015b1484c226b1dcc9b2eeda70000444000000000000000000000030013212012716020042 0ustar xMJ1F]L%逈0΍7N*vHxKm]ÓtfXJI$9b֙o)rI90&@&t8vD3#h +tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3fS7SkԞ9j*.&d3<`JmSkrUԤ<熧R: ., dZ|e<g돾GoY]j>^|gl)[_#I,zb4<3|=uxx2lin Q?I7Mؽxuz'A t鎲0:gΛ;jq^Rq7kq>ٱA"^ 5 nGފ\Ά#EњQ6`% 1뷀W^ENH'Ά`~?;fqd_@×o͝dlo1OΆxU`~=G#0^o?{J?n>>:8^g767{[YvZ( bOdFݬӝ ǡ0b>t1nlempx6hmN@'w rLB+8/af{VL ,g?Fz3<\___YgٛMNFmO߹s1o4{h^x'^wvz<=ZcnMѭ~LQ@mCf^ɣv8F's:%0xҚLamO5iu?Z=@;6^4x>@N Vw<[ImT5i1;Ôތ& }jtG#`6hTiLj9.Jd@3{4a٥CRpj0z&ISxouaI$"?9wmBI\ F_Λ͓nGOqu@gxΦne>:RO?~h DIFAl}0goV@hZ2VR& p21NSJl Dr3|Um yNAα}/Vt$. 5)T幂F]GYVl8(S݃Ý[RT>#RyJݽ-mpgxq,gӟ?H5 ^FB6.%/aY~s(Xu &i/ǭ~Cjן-ètK_Ɗ򼅙*O=[DF6TRI)qǤ5+‡^R[cp2uZM8P8^&.Fݓ.ai6ҹ}{m7O\Ӂ}{K@{IyZ stB7 %q]g`n=*,dD4k$X~BxV@ AaĿݽҚ,Pc="d>I'˕fL zFcpyFhx:ft#sد.R0'ԐGygi~ {X[su'E ޤ0'e.UTԧ(-dj-BUE| U X`|-Sk8\ / ڈ0W(\(جɑn/#97mR eb @ #+}%k+A×^??afg77Zmk1l5Χ&2Vq}%?B,6>5:@*_SF'[М`7{7/6_·7ϞaQoX%lDq9U:|9 >@O*|@}j{绿xy~I/䯷~叻v9>ZqkKo6 |[DHF3OW)b@CJyG;#?9sbM,soNE2d_j>Gaxj dRa%~D淤mCC-|p7[0G~VJm)p&p{yr%/pG6-8BJު.Z3 ߶wwTOJG$z,L9(V\d2lh 6A͝?xq|?>FMX k^%<ޟ=dXK l$'PXGg8(SkB,ۼ֡ /~nc S1<{~MQ=zu ?-Gdv" ;s~Z*}|]D}YRZT}trMC~]uw-덞~}=VIkuӡO,%vA(vq}1M51  &S͙g(Q`6Gv)=*"YĘ@'t.5ⷄvsV0W\>\\eUN#Pujj l /EVs?v*AY \Yb}- ?X*T-ii[OH,[?a>=OnHd)ղkUmlt^oU} Йf|t0Gu^Xz-b\^?NQo| sB>km9ː!x^\qj'L;[ :Htu'2(BLSBE' RV)ӟJGD!Ȃ>U.WIU(?{Ql&nڂz" ~[)٠PCձ`;/-oPb0 _Nd $yt H r2=qI ??OkeCaK,CilPx3W28¯r Ӳp< ?;T^x+_(=jqxiianT u uxHͿ7C @#{//LXx+_s_Dt{rrqGxP0Ad4ub&%@s1|Ffn,,Q؝AuhOĆcOR_;kX?R\Su<2 S܈[ޝkz|m4c4 gsl(b?a,6O TJ5Q_~FόƽSz\hg QXwzq-d:e8D?LW~lkrC 6~T Q[C϶O>6,{@t e+D8,|Abāg1v:MڄD)Sƀ+ rh+`3Dg!w2N`5>h(MqkM$vIL*%rLR a vx-w$*>lbꄭl."Ab QJB3"ވ[7@8 zN#j2**#WuT^9֑J)RgKoVKZPg(Bm'I"\̵*>׼ apQ,! ͭB/0q"q 2ZJ;Gő6`{^|RJ.hI30LDba!Ca@#J8L~o/c2!.hsB&dL@(&h8Tng+xF_蕅8N#1w ͛Q,Pp||CJ ;RLjӈH,!+⾒WGa€ V6!tmQnO9X.F fkeTc\h P?C=d YkIS6U2 ǪXX=7߫5(lr~)*bEk{_o訒nI-; ܮGޕ5 Vpu#ҕ⣲]Fʙ/A!})e)Wi,KV7H-B Qݺ/JKF0QǗQw |]%HӦ>X EFkp6KP[7Sy/Q 46MUH4P~VasLI;gt âY>G8ƣ&Bb\D̚QIuLHIXql eB`(3} 6 U,"C..LA?is &>$4&kﯡtu+D .*IdܕE}9,jz ה;UbS$puA 5#9*;eQioL;9Z(r<BB/VE7xMNN}Je\"Qc@x,.؜QE% , weZiaDna3tڸ.q8ثaPkj ɕU ʐi GRQApf-8CR$0lnN/AW4 Pyzsp`Iw@ɮs½iM)5*itfqb[(S V[ PN^ Z=.+C宭)3bπuEijK=ḴaA2^y:Xicf*'Ģ6x۴ZF$lA*;.O]z{,$_6UV@LZJD,\k~* Rr>jo*"QhpC({m5a_hg/4"5jNiR86pNǫ.mgZl%oخ#:1@]"\ WPHI~ј?Wn@ݬ  8k`m -WwZPr !vdlc ^X9(ܼTFi̅D`<#r)R0CIV ޽Đk9 Ԯ:WL/$D7P0>dnf~FF-Bgm!O C15V@Đa%tVN7]'$nXv" +Iu$FP(N.*./Z X6,X/!'wpZYq0.~ 3B7YypTJUn+]XriLa`HmgEaCn)# td) i T-x8|>P_͆'^ʏ-6>aq'Fъ~*l"2qMfRFΐ GRwJ\[qB)9saBȑ gpd <30vS"YX<gǁdqd^3Rxx&5QdЗyx=uFTd\+NHeL Qۈ akTa^=숻fb'_D ۠c84 bj#z4"=T$df'a,^yIMH^GҪۚA$6ؾ e}n~Vf.7CiT[K{ #5|` o#=Uh['G)!$=qCE3*qt0MU/ *GpS#$~:V9¢*I yԆ+<42cp3%֩%BunԒ]*8N<) I >ɑͶsWUXټB=DBf3@,cb hiD܉֢`nj#g*qe֍٘ް6VQ`y#6o$8 Φqi.7'~7]T6S-Mm rLp? Y[ {5Fjn S@8hi7BPyV"ji.jYWw0".du}ǀ_F\=v,cFl):8ƹzkhP`*1Zv@i uxүrO2Դ%;YŘ@΁-KWt[\j~.а"W9 K%VR*zNj]$0gzC8 8 `.3 !{295066_qԹVGzΚh`A!oEhS^q,WuK~Q,g--]_~ؤM8 sF=t,Kg/沕aw\_q.o|+\_f}o}!\-cdI <f:Z;{L7lݠ#D gpLԹlc+Q;Y r^ ѭ!)Fqaԓ#Y* obM DH m:bas RV*=w]=%Fd چ9d#ʅҫJ114{Dz:ARUGRPSU'4@j%D_I=O= Z=dB1b gzffL O ѐLG]c%W5\@r =\ p7)/e,tZ$>o8J_{)5/cCj( L_{ѽgf)l-2{L7bxZsNPNL2 l1qP~`e7Kr lkjsU2-_*l3ڜO)IajG.@>rS\R;gR;gK>O]5gOs dKwɄk@d/P3*o,fkke_hJ ɏёDl,9aTV1ɣ6\>EJKP:#GU*urD(i/ob8 #@`M1?A`UaIu3yđwgGj.M#[ ({Zhz0q$Y  ' $ CA9T1V Ty qP$cdAF!~bJmM΢ ,SxZ K{8ꪄgo_o+60dhPKrKGǙV4qaCwް(yRWAEht2YjR_9"R1z ɫ7^Z]Y9nre}ӏx VdȆqT4H1ǃT хRa蕕3|pv7S82Ɂo\_x^wKb:hW:+ԍQtPRBwRfZlE 4q$c =p#Mp݁8R &1nSOz%8R '@(}DPyQL>Lxւ7pXpElt*SDvxGϱ#oR Pc\k;ll`xDYC-,9 }|'̘#G9r˲}l:ҔW9S\Ìn]mfRRa} wrg/6rtv|Iӭ ćҐB\Z?Iknki*z. Amk_+`/Օwr-ݎ hC!io]9~E ) RJ@.JAvwϲǼp~<]+nWl[#_z) vrΑK`{gL r{T6p4 RJvlhKl,<[ho.iH/}G2 x9+y.@Y]{ !|/Z?20ヲ}K!!u#';,!i䄬FU㛲ڷ_c{Oz-#4Ucyb#3X['sKG?TʺO4! o V c9عTHH&ueܐKUQ'LL\إa[fP憎vhgл jBA8O'wc6}ڸ+qua#:6\9%eRFj.!UǑw4fN"3FJ^Vշ){&*3z'wOmA% R=T{zq#S'䚪.S(q4 "BA& rIHI>/@qSs릁5Xv Xr~aшˡ;&ӑ0*ҩMh"'-Se1B'n4Ť/vcrgS@0 T"i#kZ⤞1X`IW}ݝEի *8ٸmnvk HDk0q]N 0X bEȑGaeELy:ibE+E2yxr,]送oe/9: Y>IYL(5 xԕxʘGLO'y0^*eI/1)3y)4*fI-W,ȗrmz YHIcbdmۛ77KJwȣ|cqx gʈ0YGHċ9s] WLL]Ö(XpEH>&3sqb5'(W^Bx{pZ` !?pS>ơyPnD̈́@(cѲEPt)y`d:ԈinhKI{(U1soW ̣9 u/3[Ic <+FPD:9QnA| 3J͏35>ꁸm⢋K6EXa)]ԹQ$'՜Z*LHJ*H_Y`7: 9xDqJ~픑rBLGeQvvr#wO|U[aҿjj΅Ui?o$0K68"qTo3ݽߺ)]PER+(p?oVSLX+;j w8m ݹ lXۤnsP%_|#"A{R9*ÔZ;}r bc$\f["G̗J-q>. &X)8,ۅ9h@P,{~E9m詈:E;z%9& 9~8I-W!nc&p8cOXϯ[nty)qqF!?0(t%KS"! ^ VU*=hħ yui7"gGt]S[^jMk<{Y#Kp'P^ IGa+ HF@><Դșό01"{q6#gUf< ɷ'nNwYB6 D-ޱ)#&e˅#U12eN:GnCG T$?z1{hH{J̿`ڳ5x`Ol!wZ* nlӽ]r`PAZ3| zAwq *'%у' dzP@%[tȬc)֟]pug,\ωesذQ!i ? o12YF`)Y^ #GP1GPC$F^LbM8LGxz $εi+XI04< /G: gocf y3EL&[PD$JXNeVj?lbJc tI 01R< M)NZ@^@pým"UoE#hKLN!a [: tv_PQ)#Ҥ2]6mҁtJq ^g\.9CSEK6ͭcN2$w6|AkrN VJ7Ex(4ǽSfN7qQ7bUz6X<ⴰNPTd4eZhlg?ty٫ݭo=DMMwP^11\w}#϶Nh[P16X'+'^|\R 7O` ]wꯓ`;9{i+̬f/ЀrtT!\@ >9gymGj fv"GFlP0Pei-L;kQ..Ҋ݉< ~x8vJ]KNŒaa{c G m;~UmmMFMjs \Muzג $ N8N%ٞ٫j߸s2J}%-ĩ!N[ 8.b "-͞WG2)r;ϟ77w’=Ƴ]\^4wh\nd;n~l.'Y ~Sdzb4 #rHeF=y#\ZlpqFlV`ow٣]۵(bb$.<~Lvwv\IV*Ʒ:HB!ⲢY4&ԗ"*LqH*^a (jqxӾHۍo o\XL=)-Gt`K mv=-) R"ԧ 7;o _ap^B8#BS$?Px4ޢί>$>( glXA~fڀPZƊV{C#Jp&VVC !pQNnOOԬi5. Pl=8oLej,Յ1m?b,t#7\0ZJqw ,x詛b)85Ѭy範 PőUd҄篅t 0&&kz$xNjbni>($Ws#ֻIP x(`C㧰D=E}?/Jc_b`v4xGfGH- :o}{tZ}bƔxa*TOX$bHNj|KpU`@c^K/ف)r`|vqDH}ݡI8iX6Q_o>G>aSk KH\(Eƍ2 @E,`GcbYRN<Gbj`L={i@ a2"[[bYmtz{8[>Ó`6#h0ܿ*sY5RMpY8)DؕKY݆DǿabR"E23`r5{;c^'En =U}vEpk 7&x@.KO%+f>K .`l7 Kx̎ 2{ۆˍu.(3Z$iSE&Ϗ{7@a% aR Z\/9MsE2?/iȯpq-wjuijy͍&1~5oꎺrMEz +ئ _l>urԃ鯎ڟ"ex66^a28Kרc\.P5Y~+$—k"2R>UBr˒e4{qQ綒Pme ?n!pUŤT!\G>2\ĵ%gԃsdpIX=_74:fzY®>=LN;TX.ba iKXeκX=I =VL2pP5ƝPF5*Q>/Juph$ V P~!c0zm7S'>e AHQH^0  BLi9r_vS:OB"sB/E!8б\XʵwͷbxKᢶBlOXV])oC_txRB.[=PZ^ÄT2[JRDf%*D ~q7s.Hg<c4 ג.SQ9.;q.)p e!šVO2L4p:Kġ,wرȗ ?ؐ:+谇&eq)dRCJ|1|8KR1$G]^εP.P@}b_HH,aك1cT@"o;r 1?Ҭf *qc6;UZbty$ӀPXchpy a{C JM VnIS*ġrD2/8󏘼&FpƧLh[P8WJa&FMȷhJD<ۊ9]gYkdf~%Dj1#QL>1E@2SE=KX0֜s,gP碠׆6\)#j]j 3[HtY + dicG/yfO%w 679|=LHT-x33HPU|`W[_ 9ljɅo) S!4I+怦.ɬ(`H$KF%=ѮX[*d>Z:.Ik⠬G 6l}ᨾNF}z?&@%DʨFX<v>H P_.$'@e{ɖ|ʊџ"-z@3SocZym}CQ,W[ NA3$t;CpX#QްV ,+N~ v"#yyZB==}K3>AN(m dUI\ z# R&򀼓g 'b솶 ۠ zM )Cغ@ `8; D["%4mJE!D ;$4J:CiYX0HEpy0$& =lHdIRKV?8W jJ%cTY Y'@ڮg?zAQAq CYNSnSx^IZ5ߧIE|hNLzgת1#Hv2B`ӆX{;A;8UʓRG9ts.&g ȋ0d5{U#!"QJY1SqJNuVTD y2)AǍE=j؅ʧԒ׈j)7jD0j Ѯ3 ?u/R| 16^R$f 7r&>;U/vr!L:[qBE=Eÿ.鼝 J걪sFO6ͱ*~BM' MM"5d2W?͗@?hXg+Ղ2E޲UXV)"e gnsa4Že*:KK2 2[Ldtp79匮zrOUV>y3Lnh?Nhf (b2[T'@+ۯoś W͘ahL䧄y7;?eJ݂y?BaݒC+_[<{upG @yLx,K__ O X5m,@^0DPrGC b0f͂1ΖsGmw6ϒdsGEľxR FhL g۸I*adQy& ;(vPJ3]A\im#s3Pa7~a*E#3E>y\ 7IE Z)Y pZS8̓*ɾڳָ Xc` ٗ7GC]akǏz'8ZU܋#I9`w{Z .,ZfJq*y[@S(]tI]ۮl(rAkb?_tgaKls6B<Qb CǬVQTm](Ϡp[ 61KT*#&IKN`Y"zDo 兪z-OE)QvǧHgWg7,gqE],LBd|>]Jݲ Y0^tmTz^0< Dm烕4WWTv:cEOSdHgsSUOU  Yoh2b ڀ)H0C o4*K}18~^g}\0wַ&9ɤYTrՙ>beVf&/dI$%V$jeƌaF=c M_DYVٴzLCgj'oE9ksD1ks75%g_ޫUw T(L^Ca8mKFsTZžD;K"/aїisZ8 kZH/WYD>MF;"2szMӦuM\T4 Mddj3%pMae~4_櫩=G ߈^LQQ>38Q+}H% |Ff'#\dи)u.W^]b [ԹNeHIIjf.W y0P*C*CmA5g /],Upʚ _Eʏ'[~+NIqpa#+o4% n3jSO jCFPKJu%[-̩+Q.9Ū_{U8Rʂy?2+- ި))WJWcEZm9/x>Is y?U$,hLhCky GN)灉xP QNg?P6!oj ~$o:ϽLo~F%ܪǒvQr;fm*=j'GYIBJ|3+[9GbI~Pj \hƬȱd-"-Cu!+{%&'\ﯤUf6{c苪/iQyՌ!CçaKW)`%=W9PiOp$7_lM1"_ 5W5}SAj`Hh/g9\UTbP}u/$I\q |O`< ]mPtbI~X@pC8f'%<]N p=^8$w$: Hv<εsgc[DWs "Q@&7?x(a,*d ,0 ˬ*}fbkH` t`%4͹ȃZ6æzo"XkY4k$Xt/ٍN`ý,P`u߀TUjKz? d"dhjpr7hiv' kO&@8ߓl2PnD_[0qrF:5Q>"\zPY/sziކ."T(m x_ AA^!.|X7j,)E 7*k)s=VNnzc4ZY^X7b̢VGfv0fj,wԠtGSTfc-mC s8܆k"nuHEXLb6+ASVFG&TçRBBF0.ќԳ m W_z.ܫ_vv_n9Ƀ ׼GYaP\rS4g\.t4ԓ>0)lbE1VgGgH֤%/9qʞDUU^b`Ypoԕ$^c/څR#{xZE&H!+>5d)4%F[N%>y=R6ÁfUYMrC C䖯6`d߁)#熛bb;M9L:A)AkCaKS9m]() AZ6ӥDV}Iy$`vڬmxHׄGI2R/;vJ)lK 7hdT%(y |6lxkM9kɺd[WX*c;Jv\Rv E4#dqV"y6}{HlYu j70ldM٩v0DS.`c&fjN$7E{,-OJ?E0qKLrgOyg ʿGb"/5Dpf2Q>ie6vv7_ocɦn2LNZBw\qX.,QF ?MQ 2?ijT17Ј\A(b0꒷j~56L0.S}Oj4ZԸmG|Pki 'Q"sYR$gUD9SQn8/ `qQmzeڔXXu𡤅$BVЇX#>N $ǷJ͊O> c:ğ>o?[o 5"mj`TI$ Pp,;ez$@HMC\n "z( cCy\DRxLAFZng ደO/h(}(4c9;񿦈i162,C`Ƣ$ cqWO %B8G /^L3E1 ّ )Gn*~5 K=tSlkȌ6+%͓nq= [&x95ef BNA!!Pf AaWIAs %EiTnytƈj|o=8]@v O 9z^/0H،H U%"e٬/o*Vc'{D)|GpA; }4<*&KemhӨb|q^O]@lO:4HFpvvV;8*jkU:HGsu7`UK O[;\ b(Ri)sJշxN_0ٕZoh9">1y{̆pBRCɝJ2 2F쒃=}z|I?tY@, !ziMmSj|T[*DChUp%N;vf `'OLѼ^Eu܈ \Ph|٘Qj-ְ"D_7zV]Z+nJIV7'̓W'.f+'3^)r8lhJJز@qTp7!>x™'UT4YhnIJK$lF=/i$b}߉w!"1vl!H #08`frXӧ/U fL_q]r Bs=pIon3$Sp5i:OfDKR0P?w"0tkJ7B S 6<I~?l<=ԩ O{/b*5| !4}z 0ڴgXsНW+{0b^HKɢ>tX6سُiSR J.qfkG_2G[Nmr5Gahx4n@f֠!E)?jKB0ѭmJ]ok+ň%:`"੅`/nC _AMMyLSiCa{e~ ]\vK)1愆26Vt'gIhxJG8]< hN!Vhms06)}Ђ91^0e,OpR06q0T59'!>?(;*T7PUwP󭽭Mn89(AgxxBr _hB񳍑t**7a\$wZ(S/T|N/o0 \2hR~O|RݟrE_Rg/~<ȃM 12&.hReQfEEags(`oZ4M;Z/@,hsa3 A,e ]Q tQX ^ 9B3`3TnPxN2~ WovRW9$*om>Bg (nuO ѵ7H 1Ҿ#`_BjH"$ ^[uaQ!^z_ K8r*{ @u-2?%Y;Ulmi'AORnl %(gy,'N"ixF'P%u e1e{&y\eyImf9㫺 J/7bBR]B~*l\$E=`.gٽݦ(p; v BHfkv$97HB2Fke YaG|PO+G12<"8 ,׾;e z蛅j0.vs>Q ׾*tfUc!y@ú JĈ݆zlVT%گ^IKT 8Qj!L{Zgk̭QV*xƄF>1 i3f`,#i$ 5M3*L\r: QؔКq.A6P_Do:P.F %H.Fb>JcR)+[㩔@Z1RK>A(?:5]%[9Y'lk'|ui-9_-RtJz'YU #ĒЗ#ܡ8mYEֺtSrmu ;4Ra7:Ʈϰ۬ļcFE5 pI*Eъi%|P 3Mx/|:>n4 &2nwnܲxr|F[)<eB/3WYP7̴_09TWG#1z(R漇FtVzyd=u)B8ܜaweWG.qՓprC= T+Q0id) e\%GtbybTk!]B}(ƃZ47tH&n>=l[9MFƿ @u˹[ .Z0n=5|.wd(8QOMg~ۇQEOPpȪ.E[k0R&G)j(΋pko DtESGR_A$O7@hG +'b Y8bV{lP,PJَ#T0ÅZ0(ūӎ-S߯[TqX(l]$qYXKƭϴ;e!@qeG2p޺bb6O} A=>%due,Ԧm1!OyNeSD'Hl(d#.R=Ne`D79 q]-/^$Ja97mݸBQ?4]qmjbgtƹZ,;%e'w{o$ϑ8gI  `[hk-O#Zd@-[7TS"NՃbrzȐ55B7FP'$?|qhebn JXp $X Á{ *{ p@36=\|f|֟b޽w)h$f k@.yBIadܖ6D?pH29*ԥDH4qHyaZUB!j? БV@=Hx|T"0'auG)TlezO> ?!,D7sepJhOͮc/x' {EA?žyS䝋PÝ`P Dc(+D*%7pM: Y긝+ᒅ%>K;Fxmױy gTuyպ䙍OĿ @/lU?+Ȁ<.vgjF8W Pgv G ɧΏqAM ~Y/Sέq_ /7^|WKm5E%E)~ǘoSMk#δ"? (( iu!`?*VoE'ɑ C]ӀV]IC֮5 M~Kv6\bУ X*!>OUZFX:zWT #QĂL8f i(?h.A&'5FY4'QHЇm03lHM~\iҫo)+"I.оS?ɵǷ8#Yl{ zi$`<2,.8% r$>B"tƫ7_l큭"׽yOIʢhy84,u6"gV/gBYg*QϺQ:IHJkx|izgd0 TgD ƽ>]ApdŵrOs] GD%m&f]d$IምWimՇ" _:2= > |(!i}Х}=ZjF ?EciIϺrMԭ\J\4cFqJQ{\l0)%K&j)bN\-BaPUv5^8#H;aɕ8CmBYJ>"wnÈg:㏭|UGrٸ*ԞvNRE 9)8񗋹,me>xZ"^vDKF΢E‰?+!A4?e#Rz2 씄ER~)&m  vGp7kqvn p3 ٓ;jrzDӥp'=dq&ޙ&sD݉O"H}6Xʸ02?ov~y^ V7~yO[:b<](8B-Dci eUkA Grm O`هo)D0~*"U3|vW -AzCb Lc{_V4H uý}?Pըqe$|m4j_Aj,/}@>C.H 1j1'#7 !jE}hLƪd&0AW|X)O| q"W}Ha#alY2Ft\OڐʳE(7Fyuaqc=k)lv\qIoAs>E6DccCF1cB{ Q^/P\OšxIzBKE$@%a.Jm(u=NhcKCgwd)a \}k)`k,cԄʭGc?^:\vE s8O0WxP:É؁ab4{'3k7S2pC@Ȳp`,e~4-9qӜHE$Az 04fJ>A:Xj+Zb0+s&&n4;Ijc0}̞2B+JJ`n%r\g\׈l?o513vhefR멹[;)3 zdÈ dEs}p0ژ.=\4!aE9ׅLc— Wz;ȄG 46->)+.᙭[i&$9*5 %(*;OrVN,&WF*c.71^5hf36D45#E)O|)QGTGܥi+dv,MaYkLMzW˩h%vH @ú0KװI V`bxlTy8|TX8@Y^z4o hn>Hrͩ&k8~xɽ_CMe.؞cӬAKTcOQ+0\|HWdQ>N(ЙeM`󴠺i8WD V56AKxM9Q?㢀GbU۱c% sz F"XIv3nE`^n&\XC)BLlndG|c#z̖y|YQGYƴfd*O_OrZJ$r2u\G>$WSZD,_A 봘 >)DQ^A0 G";X3n<31?TREtdK_ 0H/lƨV;Hgo*2R:fX].A'ޥ#iϳxa [ K(~ r(-ʈ6qON4H +XxQ]WR4u+hp8a#wgnvYʱJVS0-)A[ºz ƞॴ=9҃<[@,N#{V i>K.)DBRmx7io=HDA%0xif,P]q=]|sr/3;ұ7 ?Zg/h3i d9g axs,KpJpIf8j3xeV2UFoI`YWNMt,3G<{@3|f&BM2OOKA9%N?CĖZF>H؄m-؉5H_sɐRHU`l~dLU01kGGJB GS<솶XD-!@3]`xBzVT4Iؙ4R B|mRSH2j™\, {{ۉ#DCH};d~9#}htKPLcWd4(6H+i_z)ڬarڄĹ/%.EgM "j򸎢[zi8}S53/Bsխk2!״ǑtY/OtSog#Cp7u%%uZ_ޝ %(u=%|$Oy(s.z%sn!] ZpEk?KəoTep\yKVmՀ-Y '+j{ANejDc/CPޞ.UB8ÁK:FPJ2H8^YAx} _;\_JzHlt*i, ' 4_;ur6j<솁ME :y?9cޥCX p<2|p6h1QEop (ƀ|`$aj;4W~tNkNi&1e(:ͧEAlm6]Dk5[/ZlHND̈́]5}UTmţ@T Zœ=jQ%`㡓qFR$Ƌw~wo-Fg?wE h Q*l-'?;yn Bǃ϶u%F'8pzQQc\ C%Ox>v}4g'cل tZn>9<fZ2 pBERioyy8B QQs( _YTP2mkgL+,V Ԟ_&¬Nq)&7 yX~GCބ*5ѵ(G8`@0y"~$Ȅ OI*1NPfipsa9u65qڤ,y:.Ugt6ԉxTQh_c4F9+1] (/xpAHBw_D@3IB`)&dK#U=y8;DAȍ PKNmhŵ!}KU eA+e՜"mG_4v[҄ͅAb6v^L  v2Տ&kru]~ͨy* c΀\D",IK?"} A$[W!3~<%JT,'FnaFPg*baUA"  p_`gekD|59<6@iWu&PLP5ilO'j%wF:@5|fP. N>޸2c#1MI:SJ'"h@,~yLz#,vA ݎJ-j=>T唆!߀~=յn  uW+lRq qKJʫY(~7GNAJ/gav-%h AwjF2 0\Z4 h]+宸G%<%<+B"fx,ANq2hgŏ]/IwG~4S:Dn3%SGxM??C,iem4nou@9凷FSEpߜo/j=[́4#.,| H-r&rB̳cPѿFɫUnR1o&õZ|3øZF  bf`KtIBMo 8m[mGs:eY `5\̄IclN!j̧ Ƹ3I>#Ť\ʊvg?gm?z+oY^=trH N}:r8hAv*WPR B] Eiw!d4p_,M=H"P{ɐ<qfOпq!#,/+B_XR4MLo,GQ) $T"monT ~:loʻQ4ҠUIq@1/N=n2O2a0aZOŁ ܳ1´B2~|_B27dQN⅔S'^pE>, qW fL%Pg1b'Gu8Ό%r>All6.&1(:g1_yObx [h%["aȕ-w䠛 r"efW}d4 ;GH/(<8id>#}HOtB'2NghB󄞨g?L X [|qy$' Ue_#)j;d]\Nk[JCxq15Ra3GjH.cqSVb&cھ/QG{,j)J80Qֽf20\C1Clb* )8BN1i`[pÛ4˷4u!bZ;8\m}X=OP[Odegk"?Ck٢х?ĥG6PlX3O5"+(2LvfY`ba3X2AN5Pjg8&1G-EUѡo$wWHf,h;` KZ6VיU}Z( |Uf•%8 bF}PM EQ`ɷQq9ѳ4\V=$g|Ѱ ᭱v}DE";J)$(̆+oaMjϹrx˨t-WLμ \/Jo- PِY9mSFa;NHFW]0j-ATiFWL} zXAwLa5b#>Ui`EͅTΓr]Oo4L,Ċ74D49Oubk9=o9uHrca ? SgznK[̣6[(h]pFڣ0*BX'^8C*<rz`*o򄗹,qA^/,q9}+4~98輆|0%_4J;hk&D6SdRw8BaSv6څkI-> dDyMw4@)? 5yE9>؟t Zm؀ާ)2),w}ݰu:q#*ᭌsKhQ]G ƆP^_G S/^?z9 Q%K;~;8O ?t|0۴;8hvʱqMY6)~)3˲k6z5mJ@$̍Q1q1@3z,^-8 @#ʫ,c9['=zSTEp7Qpf ȼ- qS &|(|Ks cEW  J N t2=:ZKq!-N-a1[Dz/ז8byfR qv%B-#&$rM׉xS-E," z9<߆/OK5"1]i0b>yVe.p#jic2xu?Bdž8&pEMVjƢE%K=b?rW(SdVKA9ت?^ːFAKN~xYfL8OBDS~aY\bxߨ"Y *Ipetbemon-1.3.6/.git/objects/89/c125dcbf217fdfac6840d4ad76bb6a2713301f0000444000000000000000000000647113731635021020131 0ustar xY[W>կuXHHBI۲^VEV4h8_:]dl$ mf޳/߾ Rz{=R0$ Tgb$)V -$uC[kQD%u`/JG@*Ida_f$CC|4 /eF8X&&PؘtѸ<^ C)(6@yQЕoPl"mOC_)L܄QyXl6Ɍq$(ތLipH#0*P,ΠzS&2vȍU2$`¤P(Q*uD:٤6uJa)9<0{C"ͅg94JɈs9{'ΞVyZ~'7݃[JϠ@Τy#雬!@`pz*L3yy~u^gFoK"R"SzHA#SCsk S?׏B8;KTho MV:g;,xaC,/Xy{0o=c6.lu-I2Spu~#gDwюS$S~!h]:L9VtR# ~ #xT9 8a$a ![i2z''\-#adJ29J8DE`MJXM11cV C>DtRiHh߰hKEb_Ppl`a(QTc@@f()ރpF2ZDnTayDބ* 0G,#3 usd$TlFc u+8 ^8@, eX9s3dr H@RUIaDV{H2N5,Z,G*[|֥XC2U*tfc!`{4h'~[3nV9" 7s𳝛1,Q3y@[loڅ?1B2τ>SDM {ǩg)o+E;# g7[P;9oK&/\IrO yy˓宁` !Y_pH/S?>'+o-wW^󷦻An%c\! ID,qt)076؀e~hqΫ?BAN$eZC,o-u#c2P υ|b+/sSn C䝏;K4>)}vאq1s>eVfi(-y(j{⣛xT.TކYi89o昸M ?#`v;{4ޓnD9KUfIWX3Y+VW -rrlj [+ JӭSz/?{%fCF]>2hL}gxDoƿ? wІ\⛼fw1|$ !ljAԂqmf/N6D`[-9E/՘Fg jǭ%WAVwBrCb B̖ո%w3\T D3 R!+GtQϞr~# mzH!O=nR+?ׯ+.-BЪts:v8&`kX׸\Afw}ɯG{ow>t;ϣ㟏ܓaNA{LU(77bW \<a"Z6E_aPCXڸv{rxi]#;.Tdeqrb*[n2G@ɖ'8@*W6eF,IeDX_[^=E2xu%7FROTqEO5GaqB"W/85|^ݏ^шw¹Y^`b Ⱦr\z(׸/&W+r{a1t - {%ac>5i@7&2  f"7^Ng8֘ȀIEd WL1b[ "v{5KU7JJvtKoT<3o"IPӄG yfF/j`{ WUy ?cA%0r>ҁR"1(i9@?6Ǐ#uP! 4sjΝH LЖ_s 4g5yIQ.ylGG!VH:p̺΀6ӫ`J3/('TcA2:0xI^J?7>N۴$0)[5DÊ(|+KwN~ ]讣"Q%߻Yet$/`=Fۦp&0do9RhPf޲k7 ˔ojJ]|]T:Ïm̯j=@i>g/Z0]aʡXZ¥FjA;'lZ{6i2:B{dZ᰹Z͓?Ŵ!*<4/gZCJ]T΁[(BC3Z`sm;Q8 pYt y;BR 5m ?^ Xh$S̉{Y }g1_(hY9-) wC Fq0'!ϸijZϳ9d9MO{wNE=cU|ٱ 4ًzX`4o=,\mZ=o`C(r8Nm*#v1COLuO3s(K.8ryEK7T *llZ6fb;]|Y(b9X47^ȆnͫhQ0髻pj"hq14̞m+g΁s^g%ƧI- .1,Metbemon-1.3.6/.git/objects/89/e4a200f02bffeb3a0e000693a5ac5acc4fe9fd0000444000000000000000000000025714173222132020327 0ustar xA 0={ Hi,,oxIeUg#l倂BAkv(U9Q6H7(]>ݨ/^*\K!}*Ӟ#!Yagje[zu)]`=T桕>Petbemon-1.3.6/.git/objects/8a/0000755000000000000000000000000013604576747012665 5ustar etbemon-1.3.6/.git/objects/8a/73a0ea98f542e04def3d667d0b8b92db39f2130000444000000000000000000000141513221737232020063 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTPv.hMvZh)TIIjnANbI*Cպz SD2dǰ7!aMw!9y% lcN!*RR2C v=twv4+B'3jNVp9jdWlƽ%Ԓd.g)cz3Po1hD_L'}k6k:D3PV7'?91vrznu7lpU@y]-[{9)lh+.HMf9pb宝˫;) jFiPA ˌ,f~ wm1DEq 0%.[:ǐ[]+ UQY N/ y2ּ?)$3a^r;'D=b$k1_[Qetbemon-1.3.6/.git/objects/8a/b7191ee4a86fb02c336e491c5b067a479cbf190000444000000000000000000000120713604576747020023 0ustar x+)JMU07d040031Qs fi^5W~/jbW|W^Es];Ӡ8IMjEbnANj1I+&?<ߓHH ge$0+Q0h7'ő.fX5X,AZ6蜭k*")*/._^5?}\x6,ȪRUI2 *R1y-Qͪܫ1Am_Nj/}TdnjPT g] P6knfSC$PVjMybIrL=wPOJtM#K(uetbemon-1.3.6/.git/objects/8b/0000755000000000000000000000000014173220716012646 5ustar etbemon-1.3.6/.git/objects/8b/4db85e7c1aff7aa409cc3cf309c475fc39592c0000444000000000000000000000027313731635033020234 0ustar xAj!E !r5e9ӤA? 7σ5}i4Nu.9JlՃ7G)iʢi5"iEgr^K7 |GsgjrLYTnҡDfN{!}ע~*W#etbemon-1.3.6/.git/objects/8b/806787e0307c6fa345ed7193686b7ae05f5e380000444000000000000000000000073314173221426017607 0ustar x+)JMU032f040031QMNMIexwi_EV3csTT!(X/7?/$A-3D7).HLNpЯxQĻlNg: 게ݒR}U>swX_vkh 5]9-:7N4}zKwxP9y(60?]ŭRD}3`SaaȺXz ̘:_ġJ ;wQ^(O|bUU v@^Ai6_czoʽg7RaJsJKrjS5T9[UV.w(rBe7oajJ3ɠrڼnOVU[BLON9]iE,_}etbemon-1.3.6/.git/objects/8b/8fb2f9caf7461f64860d28042a0f95a46099320000444000000000000000000000063714111113236017570 0ustar x+)JMU05`040031QMNMIe8;?nN|:/wrq7jMMJҊr2KĿ2sIt#A KII-IMM,(HMK.(`uy&؟jRtW8t&0j=R-77- T= ZEK|{3 tKRs J>~kZhj7l=mUWZz*nM|"zGx̴SX78몣sbm6 V?3c>|*-@C FIo{=>um>TUqnbQIrIT UfVU˝&PY[LxH3?\6/zہAV!E©:U4 M΁etbemon-1.3.6/.git/objects/8c/0000755000000000000000000000000014173226261012650 5ustar etbemon-1.3.6/.git/objects/8c/5ce73f84837b5145444842fa267522101098260000444000000000000000000000271413221737232017212 0ustar xVioFg,J]vR7TZvlGe "@"&$]]RGs J ^3o}T^do^dꔊҒGzhS͘9p( yʊLj1Yf!)=,%\*M)!J_W, x#Y] c[jFZby B*̀;UjT'O8NkҰ2]Y* F 3dJA{gE1S@n5˪յ=ӿ)%mNBiu\`tjkJ43jtQ7Y7,/q`Wvi=~I78;qcW5Yx~&䋥YO A!BIG"%J6() s,,%µvf82 f2S$;K34-)G,G0nf҆d\~.T qKgRVpcV<*5PTUהs6FaZ'n:Gp[2u+{ /on]ѫl6خUxV#2>T:&糳84:_;SfF#fj4lzw| AT|%ե լq;Yb2gHw=6!t|a]] ' ҃ե$ŕ]]Qץ'O)`iF%4*. [LFD`n7_<5O۳-ۄ5栁0^["i1PyHj KL-.Y^6O[@xX)i*tbXMؼJ4]9w\}Cy&{ʵbkjxXRn'm{csN PeX]=2 ^etbemon-1.3.6/.git/objects/8c/7610394aca663def4ff83c4a8ab23d50bf60be0000444000000000000000000000036414173226261020215 0ustar xuOK0=S V⿋x[ "i1-T]vݝTCt%\Gh+3( vY[Ҷ,rHh %8;u55,X Hxu)<ίCK!%^mL:g2_JgPu 4Mo D/Ѧmo&Ez c(_gTV,f%}4x>qnbnzetbemon-1.3.6/.git/objects/8c/8c2f05aa9e5bda74952c6fd45bd767a7cba1770000444000000000000000000000060414001502275020222 0ustar x+)JMU00e040031QMNMIe8;?nN|:/wrq7jMMJҊr2KĿ2sIt#A KII-IMM,(HMK.(`uy&؟jRtW8t&0lK׹KVz|%u3Ҁ>).HLNpЯxQĻlNg: 8'3B$5z*nM|"zGx̴SXWuѹw61uC !w Qls:M6 87$$nj/?.>p Lm~ZIQb&<TT.X{=@UɊWjTATIIa _TL7etbemon-1.3.6/.git/objects/8d/0000755000000000000000000000000013733114113012642 5ustar etbemon-1.3.6/.git/objects/8d/41ea69885128aa059caa19126f0fbb026210810000444000000000000000000000027613733114113017535 0ustar xKj1)zo0}GBLnHnl<>>2AEQhD,f,f|Fg= -$c6q2Hn95U;Jq[mpqW}P3r6'eJ{MJ)X/*׋+qm% Ά$.9/Y|<?}P~[etbemon-1.3.6/.git/objects/8d/d81a11d94419ac3b0c3419a9445beae6c687b40000444000000000000000000002575513642215544020015 0ustar x}ksH~_Q!{C[uZmZײw"6V HPz?tc{Nf>,ytK$UY8y24Hҁi~OQ1fF՟qO2Edl͋s3F,\,Q O4eQ-|?48[ҵYo=7 MDḿwy`$T^uDYcFL(ag>-D_1]Y4f$*0Yy\@y͘(Y#ĐGo*<.9BRk: }[v|Xa\Y+q:j`nlk 8z*Ţ"yxG7v9Z`ÑjW@n1j$zj!eتw l׬;m i^~Pu-1F"0dWkj[e?]׊,\C'Lq/#+u(0gjae OM w?nyzkՑ^,Mtx4@޼ :]IPj9yGXaC%!KQ|0 2e(a-)ԡó >cU ,Ja>.o^\(35wj>f 7rviW>2:">~};7ƣllcYįS&M4Ƌ/6+jȒXf9JĪzL0kV7ߘу,"r!psxߞNk07|c`qGG:|*jfyZ`=Kp^ڡEOnyԇ&"02"[0QR GEc+YA CߺJy5-//87΢H2vUн#x&^B $uCxJ_5 hFcUAx> d姸di.(xD X|3R,YC,L@ x>]. pw*B&G zQRMԅחiVimL?}CQkj*H^t^2P4aÒ#/q°:)W,cyͧ6C2gxF1Q%\_^@X$/+ݰDTb$Iҥ0g[FVi&/x^/sc0 @Rzf8wXWGR>jʁbnZSF|~w)Z?OXct=54 nYFrB.7zP.%axfdj>hIRH&,Td6B`nw2żCLZ&(s,Le=oIN5b.+LěeTX:!5Py\io*NQ~A9 7v"vʏeG,UkIxZJj FɬryEF(Gf^LD%"jp8Xw{4l ,X2¯¾\k$^ ?f.G ? ,&?F06 CX,aWDHQ6xm_僮NpLNQlټ0:ߥKB҆0PkY"E{K{yЦHJ¡7.BϢWhR||1f"fޮ,HBC1caCiX Xj2y=AdÉg4^8B_Z R\ܲd! DgXOnM`EM%'{j}<>m+I|YrBD9K?HSWiҔ"wSk Uhn+hܣwIRU*^L 5 n,,b#]6t,+Kuy YĽmAG|8! ƢTF-eTY'`Dq>YރY)MbɛDIWիw-pQtCF&0~[ܝҺ6/#eWRQ',=ϔ/,ʛsXK7m4/]ptu00,Ҧdg' O;o8hThtN=Nr@G>k#m` E~32pJ*ä afD UD :*j}*n|){0m>6b ܥ8 ~:6ܔٿ [+N1HΔa\ؐ,#XM"WJ'K jЖlZf {"uM+}d[⎆Al1nZw.3_>sPz gvr웋+!r}.5k{ WboZf}M@vVH fnuQO#5yЊo״vwm(3p$-3zd+|ʳT$mV@`nll۴)E@=簆~)v;Tjʘ~0a'+~%v)֔hAma~SꞦ.4zI+ٲ dg-3Pch@mI8Ҳ~=w'{r,׿[ EiQ A*وAdYJ^rS)0h yb-乛"l7lBځM:^u_q`}mAl[SΤ\+!zǿQHR# ׿ JP:1#⥪h^;skwn;魥tCIx.!y( Œ1(9Q]fׅWVg1[hC\~vkY^/\Q(b@zjȏ?gPb~]Tb'߿EeDQYxMb21B ;>0KTĐGd=CCT.:4FBy37 в,nrD֗vP;g%Bو3KZnc6 3JH) "afE& @Ct1/5. 1Q~ߊpeu8lᙤ,g$m1l]d ēË爱]م0e˙-jxf|e;ɱRo}Ash8a$aaPK0RfNM0OucBVVtl~MIO?zKbԟ PfY-9WO/ y'tȇ7GR~FBs]_[2*E4a;{gGFg .P?i^Y]<:2Y;wX?WBפŦd#dkM6,L53iOClxX)K*4 4;H[k=;B`[WGĬ+%q`QzϵkO絮[w[7g#쥰"g+^N^JxrC *ox# ZvNRtnXwnxjnj9]x7 ke"A oW +d8D"wD0х8ʣDacLpq+|}:.EK?f֑w),9tQRha'&K%HA0<M橖v(ԑ;R ͷ}!f2n%k^;b*?eٚgmEhEMC*u2XW@nGAQ!- -O -ӵ#c<Ѫf ~rl؃xO5$X-Wrb^xE%LE@b~nа5KW5O_;?Cd1h2:^`Yz)nw.(=u%3.!zT-rXVUHMfЍk4`VNQz\+6)υ#~ۜZo@^Y 5~eִ̦e*C^D(@tFx=$*ev=.ePƪ B!6jhg},\Ap6]ZmU-~Tn`3 .Wk,WcEp `o[QMCk]πu,"b ),<XfmR m8? {_`xJ'$-xi/~DylBP قh KuSm^Vl>~^*o[wmMfg }0@v*@~k !<0‚kI@_9VKc1-iQ Q@'CIZQ8SBb\H\A*pWK~uٶzrAWώVlw ]@VN/&)Woh!%r`Ak%זfbCQtͭ$&D- 5Cۖ吳[y&|Im-~Ev7G@ 3Bb9&nH~Mcn<Rrc7~_/!hq>wē}n_|y\y Sz|W,,'@=&FUŒI)m 9k+.]=͝נ|_%KG/oj]ܜ S[p-PXG^K=`Oe`<Įn]B&D{߬;}v3;^b>BEF){ pI e[7^t6NQB7<"ob}玃5zUhtzMBXd0l\[p6Wdpwyƭ9͋$CnzQ"k %Rb,-< ){[1b=<6!ij깯Na 4PdpWuUsšPOO"x GIođ$y٦jQnC5-?1klk0(}сtu`=Gr$>$`!0pB37 f>sfDfŭ"b)Z*ă; ¢,nytcNy4*p﹣/9+EKJ QihARiM5_pO"&l\?C\o`sR{q/<5_̇l D鹶;T)7&9{PK.R3-Uhۺ]+ ;n<%ڳ1N'yiqqrww% @::66/˥wupΕ,sz?$X(Fhx:D#,+|ѾI7M[sFZ/S'a~9^·GWB~sIxۮ scy4Q!~ 4͊zhv$J>=򓿦!埠V/|I\{Vjg1Iv/cЃSB0Gz=+w'T_k>Q[f=a|D*D82vL ^Dk>A8\;Cі3tjO5DY<֫&lc{_ؓ3297Spi؜wGi,[AѶC4u ǑaӁb×b)6˚/e@:u n[4hw:͗| hêςzYXѮ!-QA-aR[.w.ۢ˿EG ͅ%H&9n示#P h/1Y_mug*"Ч+2*l:d6P,; Oiz Y7+``O@Ѳ:rNoi3ʘP'嗋Oy&I7pjC9#(jZmS :O%d.wRovR[&U9$CW{X(O>gf}DAXt.c>w7Ob3> -ȹ{Gb@Ӿ3un|=.,: e6<>PM@;|l?m0ro = *bo}r;,_~_`2_t;]6u%x, Rf@EkYf39&+{2@(g#` =m-4cΧT5|nD85!JF1\zAa(+ 0|HvT;vl]H=LȀǥw{t%?u!g%rĐXfM%UNI1{Jӭ [$'~^ ѱ cϔ,]ⓙ(f{X=Bbv)899iWsĄ=|pwD֏Ba2RԱSxvoҏ8U-9df'ʭ֚JC>ѹTv=. l$P*N դM繿KKc,>={: Pw¼ԏ^&niftE(!PwN KM5 ]2JfP^6bTYfzr$`w6;f$uGnkik-~FA+bNF`с{wi'h>Mȩ4i5O2SV_ /חe|beբR'-}dk@|kNIAv0?,$ d!kSI iPHW!p<η[wNmc2l2bO3ǙiBfɁmmr7k+cr-+W37θ]P'Qf$rUB!>A%wot|oQ+Icp]Ã40cCntgOI]UK6Rc?BrDsj <3:I`-etbemon-1.3.6/.git/objects/8e/0000755000000000000000000000000013455034657012662 5ustar etbemon-1.3.6/.git/objects/8e/27d13fb510bf6026bcd89f8de5de754dbabcdf0000444000000000000000000000027713212007472020444 0ustar xAj0 E)oD8PJ7h$b;==]qy`WU8Rh( Y,;MU8m$1yt!bmWwCRg쟥lM>ʗVx7@֯n ٌcTa7WG!ad] Mᢝ/8A{7Yetbemon-1.3.6/.git/objects/8e/c5ff3d4d3fb5079b2a9adfc38f74ddd49376030000444000000000000000000000120513455034657020247 0ustar x+)JMU07d040031Qs fi^5W~YUQ*ذ*)UUF5AE*f7/~92Y{6;&-R oMMJA|7rnNMgb fͭljsh2?J7C)O,I`i]}W鑮ij*etbemon-1.3.6/.git/objects/8f/0000755000000000000000000000000013455620411012650 5ustar etbemon-1.3.6/.git/objects/8f/217b12aba684938fa55c1686c726220e6aeed60000444000000000000000000000214413455620411017721 0ustar x}UmoF+戫^&1Mz@)Rh=kp(ޙ5䚖`}gf' Ob 2* [R-5ԱUN OGSh:]6 `_ZEj@ /YVA, ȕ\(>Pȹ^1%,#Qh%f 4uv2B0M"DE97nFSW,I9KD""09IG0DT%fZȬI,K mM&HUd3M+9ykHʭsE)# /F 2D,sl+ƘJ$ 8MLU> i玂+ZU0d2w3:{a0\=pazjzz0z?hRiS8D\3"eA̖Xb B-J--үbE[)A U0VN!IB^ deք;t:^`8޴7\#ow2s+>ӕ\[z,NH:'p YEL/~?~-e+U! PkX`ƼO5ZM~yr H9=kr5?wׄg, >RNܙ;a<LȐDp)؁6ֈڦ kqSdx}6*괆YS`~~ET)06?G&;O| 4"d X!:e|T% xǗuR$ A(?0tOz͝ ^'ېӨ #BЀJXIنG쏮wsi=Ih[T,xAYHo_J̩Cō7N= 5w?T% wo+ ti1*rFz#ߎ=WoPC>P /u#^PCtLeujAxU[N/ &pfdetbemon-1.3.6/.git/objects/90/0000755000000000000000000000000014142105442012557 5ustar etbemon-1.3.6/.git/objects/90/a558d0a76c3c20d6e778a1e92a41147df67d070000444000000000000000000000141514142105442017633 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3'}gWuO=%RlrNfj^I1ó k_>v 1ٻ&_HIMLc%w|c =톧/mbO*Of6>۔+_{lj PVniܹrT>"Fn~C9kC>\Ǹ#"fnN~rb0,f0޿Ü+,U=^c":oA+,֫@h^qAj2lḵ2=_9f>Ԍ Ym9v+hA&!c`8a;K\t7!'8/`V) n ^q2e{yES(DEiIfN1üow>hOz22Ib"#V;etbemon-1.3.6/.git/objects/91/0000755000000000000000000000000014032516006012560 5ustar etbemon-1.3.6/.git/objects/91/825373f756e306d7b6bcc4232a1c6f82c0a6c70000444000000000000000000000012113212007145017617 0ustar x+)JMU07d040031QKNc`3И3!hNf TE *?Iy3x>sv{9etbemon-1.3.6/.git/objects/91/982561fd9a03fa4f07f99af2a7ed0a757132320000444000000000000000000002724414032516006017650 0ustar x}kwH~_G.&UcRUƲ=5}ΞՂ$(E,C3ͽ Ѓg۶D║q#21CӨ}D0yzi~8pv28;W̮dt<wʜב)G<\,Mѵ oxlQ63,ɣMGQGaanä)R3IQdyu^˂?-6r]{qdb.nkxH3sD&44ˢQa,Ç(s64Ms{?H<\,Ty^GyoF6Jp1_#wf~=0A4>|6D|iI^YׅW&E`WY8 qrenbjg8ˋh>D'&]1f(ܙy-/S~,$Dp9+L׫#492){xLbf9X4i0z=7qRD"AC-f;iq̩թ,1,oeyl3 &Fh$r A$E{I2̯ D7R1)}]"eʍ9,3*K4p~,2Y/$"i|5x xGowzߣc6s(UG-sQEan3BctkqMhrZ.Q^șe h&WQ׸KZoNه~9&=BFLBu,*Kӟ9Tym00Y 5X<[u h3'x68IAQTNFI=6V= (`ou'q*1KiŶqGNL R'$GfxaIɼߓ^ըQQz =}Y,N<E9B#tbyv1Ax7䬠7St>Nrz_ 1b2J"Kgկyo2zKND] HTDo1 8aW/c8սCBBPo^{ uk!񙘑BL3qr1ƗA. 2\2V9yR!&#Ӂ]{"Ek?1)6h ccW`׸W#R9@rF@%\U: BZ@,c4ΰK)ab)$zi4S46c*>QלE⢄RĈC8Q{E0>%9;)gw_;\4t~Wr 8O@y*"QRģPpn%5eD[耄Z 5jMdTCd-Mt!GPT9ߙ8f""k@"Y#$+Y\\ %QR5X5 R:Dn! |B9x9} qa A RZ,*wtc_o8pTIV+Ryx2lr86"5N$ S\6<3nW.# cdxd緢?D1DfVdB=Łnq/#=t={PtZ8jql UGz1ɇs@Ic :yp,̯ەU..wYC%@/E lLIfr!Bl L.E#Y\X3q<|RP })1Fy/;5 N N3vi[>OBD: H~}'5'Aƴ/7Lhb38RVE2qψ$V &hs<ѣOpHFBbu?}<$M87\@c0/:|*jf$-0Rp U+w" |  >wJ@sK -/y9/0TP/7qMjX3~!lM9c`ffQ5*}8+% O)XJ[5*C*J8N#aOp$3afN|IWK2jU|f9 縆Vy8ݡ8Cw ;7"-dYӧA:˫s.3QsLt Co c!vI7Qx*\${f#!)Zfm(ns!q K5w[)sAxy aG%~)SVL@Pp0J%Xe?ơzH]1vxjfdKmL_}2ٱ& T$6Ut ą ҙ3W0ȋ9aBӸr2\D-1XUEr3 S oH6KaNYᩄ4O3y}# X^F3iU䡳p$;V\~W8ԔUxĴ2)a Z?΁O'Α1$x:GMpl*0%Mݲv:\ofr)qm w܌leZi"LEF\3Jltz\3iB=LxoXp1]-TU MEےXHrEOMcl55;$ͧ_@J £ki͘Q&^9KOxGޖTs;בeq".>-c e([g5b.+޳$|y7.`@ mJ{cVq;z9*?J?Ϣv?A1툑 s3 K)2^OZdF( z Oh&:,)hVUQ/Ǽ󹥠,C8U`*̔~5:\#s9:T9,Q9F{:WP`+ `-jZ?Jd G7GpZ3zE>2^s;UQ>TŶ ]+$mX %%hp?U\#΃6=E'hY Fh 8d3^3 oWe JQ@HT|k@ zXFSL5P_ϋּoQĽmA})H3I2.h)Ss|4|2S fR n7!1WZ,膌 <2&qK-a+[;u]G˕q!RQQՓ>=r'Vlkwm9e:;PkiGY`6F xfɑ02| k.)e ՛6QpgmD9\ +k#rTs2pJ*Ť afD UD :*j*n 㦻0m>2څJ18 ~2|ঌeRqr faDr 3† j5V=bkQ %̄ (eת(݀p7P#6\[ PWuP}l9^EgWL&Q}7Yx!#f_!m{v剎erY߈=v9_܊gf@15jZۼ GfNo 4K!ܥ0HO]jsXIG+2bzB܍GAJPő:^s"v]a5TrlmX; GEu?'şCؔWxhOAM`q_;83Tx+O܃Mp7siB?ְ˹ZeL(F(0'r4yJI^%uڰNsU$PV7WQFitT}Ƈ5bOyK0裀ph ݒl)ns:o.9SZEFwK,9UߜX 3 ۬c j-PU+{z&vL==Ca^`6V'$[V;KOhs}F.!F7{f,#^!ˎf\1f9>̃@^kw6mڔWs> &Šmgea ?.T4PE+cœ3\s-o KTF j[݆M1z_Ъ{)'g{$[?r`*["uMAe; ׉9Cm*E񡷴=ZE6EC❐&Ch)nQ2V ^>]4ywABF[cg?yDg ן853YxeG{pOp ҢmRQӃȲ &\X.]CB[0z3ɛ9 WV׌6JʢqFQh܆Y@&9?$16#R~+;&l9Xm`]wA.Iz  =wWLd 5 fP)3d4}aLx[P9!R}XqsШlEOj^ag*Fe{?# e~ΟU2sЇm0С7/<|H}B/gPɆJkP!+ROP å}'wb~ckx0ofAG.ǎAّق ZvWYEX3uTen !2eU<Ŧd#dkM6LL5 3ic1,)|M':okHXsrpQhOR6\UV?3K}Ql;t8Ss?ܕ#r2ib{mdyR\͂82/ KA^CV9YnJ;پ*w .G!Za`4My-'2:fm SF#ݸ, \{i'ҶT798a YqAbݯ6 |'Tx;*n$TT`ej)b'6 Z*8ͨ=:f(̓׸^[$( Z u ~I̺2 =ÐUc]^z=ZڣkWZMO;y{ۭG1RXsӡKK[{O~:XnzRS&gc<퉷pnwn~Yqf+h Ӊw+5BKwx )Zh0- CY 3",NPv 2EοZ l:^  ]:’!%ڜ G'<%:rA[]lX(:Qƭ$W~ YԽ`'#Rݹ?eGs@iZ9cV&Z I աz1ac(2] "P.yyfc1%mC&VynRL@z''`DIV{-wbAyyFO /I=%l{T5!JUpwdnBc#-uJsXR'qtr4ߒ^O/qТzZ2\:2K-}̶!.?2A'|$X-[rb;ҋJ$%~nа5KW5gO~8;Ed1h2:Z`Zz)nw.(=u%#.!|THkZ$6r ͡h PX*r;=RȤ6Wdtvsͬ?6ݚ<J-af#$2tePƪ B!6jhg}}ql\'aӕVl~뗪LEH-8U^;jHE}`0|9V[QMCk]πu,#b ),<XfmR 8xZȞ17^É!+I e$~Q?S  ![mr.ͫNJ-9r3q묭쌡֨Т~_a~l; muWkwՒ2X;r !"*pkSZjfBԯ&>Ѕ?BwºCo{(üWy5lд Rx?lvh^RvBwd*\BuzGzm\+XZ y%I?f?;>b3eb~ U۵'txݎ)xs`};S/NGcKHI^v(r]:Vj@u}{hm[O 2 S&I?at.A@ 3Bb96ZT8iٝ@JQ7|eE{:9 p;s5|:š/yArC3lhKֱF$ڈCX09i=mBق2ZJ&i7w~_WO-p (-#!#ہ{Z;;3'zkj+ c3`\XSXCDӮ7+tNw_NXPQᲑq~x`[!l fۋNf)`ZFVT44M,ܑ\qRʘNig mKq=CNN׷قyX@$/fuлް4_vačt%K]Nb f15og_\u!e7Ts3Xrǚzc+jXB Ta+UCr8 BX"9Bwሾa"-Pܣ$o T.l!d̝k0(O_Ёt|e$^$`!0pW=d; |/kNPLQ^,IKDL6%CKx_2_dq˭{\_ fAWQ; xY` sE/xB+,Sƻ+RiM5_pM"&l\8C\o`sR{q_ͧl~3%+mw&R.DIpsɮ%(m”,ɃPd@U{6 $U%%!U7ˇeҧcc3yW\43ǚ k aF =_{ұGu[Ix{inHp(B#2T/'dr!%1 l.!}HC 8GX+, #cа6+b#]Vّ(Jx˲O- )[mv'rZVaEsƄ+ Z l aa^\Pů>&"D噻oVS !HwJ6c7;*w{MJ.%fd gԾBPre@K2%־~c 5Nd;\F 'XZs#Q>zmeiײlUُ7ź,49_rtر4zItod= D%UI4%] G/#1ɉcDGpK2bM&JtX; Z04h;S b,˨pwp Ԓ->+1d>hW>y5Fxs"[s]+Gԫb__J%@ P֞[ Q+JЩ|*~&s.X ~2U2$%7]Ib<b{66<9&{b1rӱ}46e l}n=\i[=ۻB:IeXU.r/DfA/OP(-y.GMe u?:+lpx`í#]oPt H]ʶ0i^հFj:_0l4ߡxk^UgJl+E5w9X=0(Va/d?>0taѩT(esqjTw6í]p0)QYDie,] ,݁Pkq ]so,wXBԥX? gucYrL4Zd9ZvazewiaW8%쮒;Wi`ESP@-u 뒅RyG'tY0eT9OVr˽p):< eOE][HmBmtkg{Zg2\ 1 YSnq stZ|ʱr l= *bo}r+,_~_`2_t;]6u%- RfIk^fx ;erTヅ^cL("J ۞6jdS>Qeei7Ņ]W+J&X;&-vLlX %/VB~AdfFn+>8Օ)O0=>̟pXXT>0wiӗV;jT9t h &x.QZ*ʤڱqX'{IJkAd4ܨn -¹mgl*Cիٳ.om;FY-An 7H/'_N_ Ҫ\~.Qpldy j?=#ئ[ÒKwڛ٪g=N8!EMiQnM|ǷD_NLҐI(q+(%٩Rر5w!2)#V wOD'n3DD.ڼQC`๊4a?=fri4SpO73>{FR,d>\StWfnfv )$d]bR>xիPS{Ey>}MnZ iל<OU<40/t1V,IDt=e"IN1¥gUzyoV'~*됑߽[puYw ?yJØ~K63Y)`c\Si':*ZڮeaMn_CʼnA8wi{ u{)v<m?Nwu}w P¼ԏ#] O^YǷPBi{  {Ԅ+AU{Q*5xˑ,K]Ag8y\hEݥil{7R '<ɬL[mnY k$h߀Xdh("ßÒ%A~)6/ 4\U] Hkmf +ՖCzS"/OM]90=q'|,XbGh6Q{@Txuc63iGEL E*d e¾㮪mV&H,L:K53*]w'[jZ\/oQXC2VS?yM%mԾ3n"l9F~"FvtD쪀ͳZA.Xňz\: :g2  1UJ%o[5ֳf_jQF*hhg@qzYbݮcn<* :Jȥ3Xv^b!*[=>OWnM,[|a%Xlv oma )"@`5&L )I<(&Yq)*}RBZTc/#U<\,R2Ƽ-_*^cxo.2K6Te l{/={[WU\.Vuf$rY8B!>A%wot|Q+UXp`C 8rpllA 4A.Ӑu F2殉W.nW6p;tk`y}g~_ƋJ?epqFe8q/ DHU'hqeѼ0:tRMtkJ`UF6HO39by%>`%J%M`eBȾ$UD:dUq/0f6LWgot]e]xC]$?) -@#4RAE͗YveqWQ{eˈcQ]!> Fߪo`?-xn;~ۗ)$HńܟD0|xe+k{W@.bH;'kqxrƕtl{+Ʌ]Ϯ% UN^漑7`zm wV m(1_etbemon-1.3.6/.git/objects/92/0000755000000000000000000000000013604576137012600 5ustar etbemon-1.3.6/.git/objects/92/16b703f4f889fd0e92e3a077e8a53e443d758c0000444000000000000000000000141313455033406017664 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTPv.hMvZh)TIIjnANbI*Cպz SD2dǐ-{o Wޮ~RWt6D69'35ܵ/Pj;]˯BT&e&1|^o8{{%)Ǡ 5B'+y5+pXljI2CMŋ?=yv7r4UJ/nxe5G@( <TIocoP2\8kyynypɹmnBh^qAj2/ρW,w\^5NNP3J+ J\f,g4ۭk\!*K /q O8⼀Z^b`|05tz]XȔyL%9 ÿ=!ɜ$Y ISIetbemon-1.3.6/.git/objects/92/3928bf7bdf205fb61ae07b96fea5592407aeba0000444000000000000000000000030213212010700020113 0ustar xKN!D]s1&@O@&,7pWTVJ h  2>J&@e@NT'HgHq].h)"IBh3GrA:+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d`|z3שܩ5jϜS 5yBds2SJm0] )5*DEJjRfbÆw~On;A=eVVdj{oMb>Ȧ$3̽&Afwlg~<{ҰYNry⋄A4eussaqnZܞ wM>},\Pq'aBsR,k4|2W@c Rxe|Xbkiv vQZTP2c9˽-n>]$b QQ\ g=lǴ˖Nx1l BUT# B@}5c (-)f QOX&ZWdxX)etbemon-1.3.6/.git/objects/92/d5cd4d316e90d208009f1c32e4b5dd2f3d4ee30000444000000000000000000000030313513716464020050 0ustar xAJ1E]J՝0 "xJR4v:CVQoXr^;*Ɇx΁4kqlK9n\e@ҔlrH0hf=zi1:$Sr~-^d\ޥCO'b'>Al'Ԅ5"Q}!w9sm k^np~yXZetbemon-1.3.6/.git/objects/93/0000755000000000000000000000000014170643332012570 5ustar etbemon-1.3.6/.git/objects/93/4e341d2bc25690f37d4d2d3437b8dc85aba91e0000444000000000000000000000362214170643332020001 0ustar xXmSFgk`ShBR:0IFs'Pu }N$@2|Ƞg}9ꌞz}͹6Ϣd3Yh̵$m(0;k%QrwkiTjˆ|n*;L?#)nۑh?}) ǣ?:z=Mwr`p@VTaRE`df?kwb%2ܹ#rpz[ Isөu\eYRf3G$DDXjO)U.Me(污_<xtH^!ܧPeNε6$O 5Ϩ37b{nêkn=hZֶ]w<ٺv>j۷ڥ(d4 jU;Ʋrk4mXC4f Z]=Ej2"-RS&g"b&[.pk7'[O~ۃK9fyx\VVեvNH]E8$ejnn4rDFBi" }n D˖?PA2&:\[f"^B> JS=* O핻P&'_,-v@$ʜesO|[x&oՑV}Ͻp~(ԪJ qkufݵdڛw6ݓ<{9=K[9htRT9mxD]H҅Є H{ fɍ?!̝?Ff+{s? ~4kq)&a,lΨ*Xy5CZDZV*y ukWF",%8&'3X#;NK^ t|ʙR 8T M:*H*䞶tNK}Yu.ha&Ei9%z|}d1»sD6϶-Pk)/|]e_NZiN:":RbCB˭iiX`TƅW OËZRd5M8/5O0 @FQW++COvlC~p)[mxnHҏUj~AkE7\+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3B(GaVvqlrNfj^I1ó k_>v 1ٻ&_HIMLc8~zoU!3K9 ?3nSXv8!% 2L9?W,ӖZy $ 9r,Ԋ 9ɉ9q28-/qߚkb矹WO}Dz]_ryVm+8dqke: z>U)r:`|>@% .3rVܵMB.%pvLl鄧oCNlq^v`/TEe10>R: ., dZ?;8;&|x,ٟd s"7f43y4EYfұ9^  m}<-\XM%8g/"g| BР0Y}'{Z؛t>N!V8 6I̳?0| ]]_!#Lq^Le|Qn˗G$CZʈƣ)ѠMsKZA{ov$OB/%H5eo޵ڥiQ2sj Rp g`bTPQQtpCxU9gf|WK7T䧂MQT@p܂9;8wCp@]\2tA͚>s$@&O^>ki?tHgQ$</:Gi< Hz pJFeOSx4H]bFE1,MO)!f& CX c.8;r!es =`JCKeh()צ ALC4+4ζ&Сeu^55I|/MU/]qr(0aɑ8a BӔ+㱼st!یgUE2 K4OU+Ft,] s [ hd%f*2G>›*y s Ҫ$aas[[̏T>u$áx!ό? m(.ɗ%q>Iċh:;FރQ LC0*l$'}R☛9@nF6 vY냖,a"!LEF\3Jltz\3iB=L';6LZ[P6^tz'nvFJfpBoKb!g1>7Ȏ!jdwH[2 e\4fIpxGRMtdnbޡ O yl9jO7'1QYV|o{n2*PVm7f( rpAX;Dz#F*5$=bli Z|ȆipLSB/oA2ve@C810(P'%P-Y84O>+JlOx|0 Vs䄈 rb+1~0)YE-@n#1АVӹG Z,ɫ9t)U Ak"Y!YGĻlXSY$]Ws:>{ԃj|8! ƢTF-eTY'`Dq>Y>Y)MbɛDIWիw-pQtCF&0~[ܝҺ6/#eWRQ',=ϔ/,ʛsXK7m4/stu1w`sߓ+adk&)զ9hϫmБڈrxd1DC,DO";uM+}d[⎆Al1nZw.3_?wPz gvr죛+!r}.~5k{ WboZf}M@vVH fnuQO#5yЊo״vwm(3p$3z/d+|ʳT$mV@`nll۴)En@=簆~)v;Tjʘ~0'a'+\ W ڥx~ZSVjΆM1z_Ъ{)'g&\<y~iudUd ss>|.U?xu0-.q[ڋ"ۢ!Nl !47(ulChDɠntb!#@7cW*ٜ- @-B'dKߧ\0:3\n%E)f#e(yMMţhoÜ/)hiʆ鷐nsO4ըa7o$ |{kgf>;r}F#Iuvȿg(-T҉/UDE,߁C4&zho,XJO=t:Ĉ2wB,ӫjz]}%l{VM6gux@0/)QahZJ))s !& P׵kK%v)*QkZ_FdH)6,S^)DE y5LV34d\^Jr ۡCsqh$ę>ys ϸK׹v"Ԏ !'qEP6gۘsB<Ō_'d̆f`y;S4a0FżlP?d~f6L n|jFV +ka O%e8#M4nlar LO'^^_?V(dpɺ+Q_nUOO)?yӏ-Ra4=ৗoNϼ@EjiCgR~N@s]_³UTh>r>vώ`e/\~*;uTen v_n0^ IMG tm0Xj!gBM% ‡ \m-R 'GŃ Tihށ7v2åyR̓fQo[,HR3tX%P&2Jgw3@'kcIT#!`[Ss:ֱ?gb䦤xaU/zJU,eI~}c5>\(YFc/~DylBP قh KuSm^Vla/Tvǭ&3> d;Sc NN57aaA鵍$%evCD T֖Ԩ̈́_QKM| Buߡ$MP)y j$.٠i|:l[b3)hvUs E^Q$" =DpR|,hHR d?;>)sT&8ˀE4kO-tx͎)xs`}7.cNGkKHI^v(r]:Vj@u}ghסmrY<A^ SI?qܢ]# _!][1ʜ[zHCw N?17ogl)E1/Slruȗhy>/8JU \BJ $ANjv^*օh=  xVT !akH"W ]j?c%#TTldTZyEi3E0-t0*_&w8XcW^eNF״+EöվgAQ}E wg aaܘH[T놡7%XLk/B&[/JJP\".bi^³/ ʼnc(c8鑦ߊ6MUJwUP%|L;9&q yX+q܅`$1)kɦdhl&;=_cwk; V7玦]_rxB+,[ƻ+RiM5_pO"&l\?C\o`sR{q/<5_l.&jOԗ@N/ݙJ7Zr1mAB%Z^L@t3TA,PvמqB iJ:d}cEg9l)U j rs!u]-:Z`von.-G5q='v@2ڵ`@{y2h;S@>^YQoIe!ဇb?ݩ%[}a}nҭ+MoypIr-P* VK#UG1J~F'D? S)ҿ# 9xZGu Oum*|N~NХ ?ͪ֨PQKf@s وgΑ Vg#?$ȣf#=C08#w>0taѩT(Ƕ8bl; `i؇QӮ x̎Uն_zh8M% |`G9\eϷ 芓3e+sﰑ օ[.>}x9(N{"˂c$IS3Wv~|58@)awe7ϊ zQL-CyCFe 35KJ ?jboG6@m O}ux+xyOJx\`}"-e$6N Ejtkg{Zg2 1LY Knq =9ܺʌO-ܛ><G[4ס lNc] ph:K'cxzB+;erTヅ^#L("Jy{mO|u a5H)U c+EX\ +%,Glek=uKBl` %w6(T5rT L_Ip 8WW >b>T?2J0OhK5VQB4Md/Y%];JoY\RYtX;,zh@i-&ZnTkHHolc >c"x "(j Yek~OR*=>qr0Ү5U3v?U$@ p-W[Oʾ#4.rdտSLr K9ؑ01JƊ,~m /κiGEL E*d eEp咚mV&Z&Yݥ .ep'[jZ)R|Fc]=z4>ej):"J,ۖ}WGO= g #"ZPŠ}fwlUb% jvjAss&Xg4z/IzUJ%oͽrG&mWiQJG=Nyh'y@/@qyYbA vvC$UG܊2 U[Dx[1JAk'( C'E?靮˼˯SQu4r@͔j{p,wP/)n+D UH瘬*.?t-c6a:ktuFUօڼ.?vGeA%~'1 zPtQe]Ycn<Z(l?!|1VBP5V Ђ~R%z⇸}9BB r9f8@o,]U}aoD(,ط8Flܤq%q-"lW~:ArDsj <3:I`W etbemon-1.3.6/.git/objects/94/abaf741b4f2eddd539f013e44818020c6b3b5e0000444000000000000000000000130713212010171020025 0ustar xT]o0v44u0B /<4\ڑύӴE2(Rds=׳09dOzOG3mF>OzIo[7ťp6RR7fZus;=@vA68L'^y9,>5}T#5Қ^TC$RJܢ>04GvXZa.Ai7I.3>NqtXڀMJQawz"'y =G\`ન N!̅Yuٍ,TqWȎk!dN.KJ:l!NJsv:aA_ٺ񟯮):Sm&xU@iZJSTetbemon-1.3.6/.git/objects/95/0000755000000000000000000000000014052407207012570 5ustar etbemon-1.3.6/.git/objects/95/1957e7de1b052d212062a2691c3f0b7757eddc0000444000000000000000000000063714052407207017637 0ustar x+)JMU05`040031QMNMIe8;?nN|:/wrq7jMMJҊr2KĿ2sIt#A KII-IMM,(HMK.(`uy&؟jRtW8t&0j=R-77- T= ZEK|{3 tKRs Jg/2vuQ.;5*4'3UUܚ*E,7i1:?1%,npUGl~f|"UZÇ+zF}4|+Ģs H.ӻI7V0i%EfPaS`m^TUU'+^BBSS%%uN׫i2|Q1= -Oetbemon-1.3.6/.git/objects/95/1f960e6e4b99cb199e56be0721757342d223d00000444000000000000000000000046713455621442017526 0ustar xR]O  δuhL85&[R2(n^J/'ιpb.1<ƥV1fE,Жpt)#Yݽ/#4%yJ#ӌST?~?' P""нm&;+.'ua=8@x_-VAOT+A4#m0^ I-vqLDI1R7ړ\fHPmɤ;kCD8DW3Z>)UD ҆u.[A.5etbemon-1.3.6/.git/objects/95/3001a1842886330560e4d10e3892ee4ab304220000444000000000000000000000012213212007325017215 0ustar x+)JMU07d040031QKNc8ڄK|Ӆ&|x}RE *?Iy3x>sv{"etbemon-1.3.6/.git/objects/95/9425a4897fc6017c04ac24575e5e6e82f377850000444000000000000000000000120513212010655017442 0ustar x+)JMU07d040031Qs fi^5W~>wu`~V-:֖0E% [Y'./1Cǡئpy%E9 Nz/\Uƨ`)Vʢ˄,Ҩ7A (7?O/%5-4bEΛ3]Ya_~̢bORY)'4|^2d5 i6 /J,wAq5Ԋ܂b+WMx'N̽H2Ksre]Ψ!nR3e$e9y K%T&vU~ZP[$E% ^_"w'LjMybIrL=wPOJtM#,etbemon-1.3.6/.git/objects/95/9f31e4fbf1604336c6b468a84b9f896cf85b5a0000444000000000000000000000267214032515751017762 0ustar xU{8Ti1RIVAukm"+aW.33'sg9g&3!B]t.=rl6KȥBYϖ[Zֆ93ss~G ͍݅$!Lƺ:A7NН;Pww&E< GA>-4kƧ9Ρ2y%bMe;.@4KZf[Ɖ0$"[+Ct>^1K}n}n@_J$ @yr71u 1GT\ %E8K,19̠-sn~l^[$[خl<9R~1CR[ QHU:G|zg^A#R+p%3Mv ^+-n+@,A!Q i сŵ zm5:4_wP ^SDK]Ia{jƺ_*\|jᔱd_}„幦't6g˫;r*-PsJPe ۷y{c~г*WjH%bfi&rYEL5'H5$W8ȎJ "Wɂ .+&`.aDb&yM|f.8/(|~U޽2j{z)!YJ@\'*<_U ݣ0K(WN8 $ȁ;"鴡=ΦE}J GE'b2S_[a:˜ꓬ]HpAgb&Bԙs{0I8u%kv\ *j㭔bv7g'@\uZÜIӰ/ܿu@I1IUi\]vyKN=uq)Bv=5`hZ~FlDP_~K+ G4 H_!P1PQcYgV)9s(Zq56hlYۼxꓖ8(& %w^+H((5uŠy88'&!=/OЏ }{n`̜)T fP7FCcjN7z11bmFV't @< HTniy`ɣn^*|OQ9i˱7Ż;"G+sClFU2USMaySA|v /TT*]1->YiJ376hvI.U721D6(5mt3ҾT08pRIT`u+%M3jiz0'J2W*,AK"@f| f#=S>D0etbemon-1.3.6/.git/objects/95/bda5cff1a931831e1648d1a71d9efe5f7213de0000444000000000000000000012225513513717122020152 0ustar xm[[9.|:bq!dzLdBt 3;}ۀw&ts"iؐtfs0ӱT*JRt4eaѿ{wW.&㕣p7ܹw^v6f٤s^ zlwzٴ7NM?1]q?&eQC δy0HV1Z>x=zV+>_ɫgg 1: NYsc1[ӟ=I,N|<:2|=zdtz}gAXy+r)f{J5lj^,*vP:q::GNQ//KhujA탿=Ao{{ v> =~BƛͽW뭃/ً^lm}|e PXl˺)p7 (ic?v9g֦ۃDz t"_=p4].}t$ 㼔m ;Svz-e?>\~Mz=|LJeo9w0:3}r٧|mDjቀX[[(K|Vg=GǽA ()ݛ<wtG)}v>?SHÝõg: Qץ˿,_w߳7=t)+ 0 M! 3O0`p4:zǓ/qwO[կ/:@C@zǯ0^C%y烑6|Ћ Zfy{~a]ߦ b/3}2rқNdtmʦ[!#d{nouzrq/O[=D^C+yA`D{8m;9< F'}2:;C/sϺ4nx{*O酷4 zi š{]A;6흷F }?=Y{~ `ްu1fe{1bvG)) O/M:x`QtuڞSaVut>/=zgZNƣ '?mu['+sOv7a14(^ rjP>M>M3EP`v}>kAF?/{ۡ'ULdcL)z7hۀ{s{:<SbF0HѢlذ(`izYai.Y<K!gpIx(ʀ[Җ&2-+!%)Ť#"el#.Z|R:gAce|rqrN [Qc1O`1wN1wJ/xheFO2?^)Eu3r!?TPZ:ǘFR1Z`e$dbRXľkכ[Uw4\bw"Ԡ}4u \@%XNobXQ@13G~`赁3, !ToJD21?s#߻ԢNrE} s9ZIq︇qd-ehu.Zɠ(<tmw(F^,-ہ;UY;HؐsY8.OS0i/ Vlj2"BJLqi9W`)P)?D" 2+J&0'kY_}*/M'}U9.X`a/-ud? kLu W&^Wm%qta9|?2.RAZ@1 Ih>A;x|7m.^ 7b%MIE=OЃ0 ?|>H׭7;[;{(ow_o"C*cvٹņ펬k\{-暵߾JA]\Խ~_sʷק_Jwo?\ox2@]tK _s|0H:,³5TkJ+؞ͻ]̮ Aכ(eX*|V=/ 17% y]*ϕ*r|1 XYduu9B y}k'WoX~CtW"ij e(Oj %h8k< }&]_h_t4\{ "\G/@wRvy?OŰh'>3( ೦8:Yϫ⪾;/1lteQ2&M ;!LA. Qs?dw宖0'fKeE|tGם@\%VTr]wM;"Kp[I ڤPCV`;..dY%VQ @a`NX@n '=# ~1)\V6:$ Ms!cp(:W0- q~+_“\aBa!?scWK JPDX >pl؄ެ3 }PHI佱>//ݝy0~ya\aC!ϕ/c=ƃ*^>xG K'a3A-:u0f2+mtca o @{"ӌFP:⤓ Bh ,\0pc1|ǐ+`ݻSpRݡ"f"6rG_ll 2t§)\J*+g]*Gk`znM}g 3bO.b=r7%D@6zzG}mXߡ;gM.\byp߯msxeTZZGRHω֘P輻xq[ecSO/0^cy!J,N[Tc|JV3$CG6ʿj|`OȜA9:oF2 p46;& =R bʾ% I+4;Q!ox57fSȚ i!E$>\ڝ˫Wow=jK;xNmEL'з&_1 lO`~SYW_nn흽Md:e(?Gނw.wl,r5C 6AT Q[CӶ!6,ǚG{B޴;\c ņ9n-Znꖍ*#~ٻbRQ:P;aA;':G9gsn;iu/K3XnG $:tP}-BmYuGݬ ej2A\E>wyaImڲq=`H!߿hLү{/zz ɩhMqg1bA[-2.~;Ǻ+ `]ǔO6;XvgTWo~k-ldf!EÄP9 1u]leޯ9#:PR 85?>MlDڮẹB꫆X]B`G BW 38.֠Ã㼜"{b/|4y 9>E4]皝$C^%+_V7ꟳeCj/%_qYݷNx64>UT1 `Z_:# .4D$YȝXͨJS`\fS%I(BR(JE3-{E'sb7ӽTCXl$[ j$/zX:a; Cs-PBTRAЌm/7bb<4b6L:+>`ck#spTJG𣪨yUH c^*%nQ{Vf5(XEJ9{"4v0)BEV3N^F\~_tV.x8bJ C[i^`D@eBw r %#`-iI30G1DŢV3)9sȐ`|8qЈ&6KcǘLhH {%m;9 BLzp= A ze!ӈ:}]/f?bBf21C"*%AŀzЬjŽl3nl @ d -XI"؞`l dþ VZ6 ;gh b859Kb-)iʦJWpX QO!C2D 3kF%1!%V*[-! l/؀T18 ejZ^ 3A6#o2pq`0X6.|  Rv JW=J@Đ٬)nO`]YԗS,̢;pMI#6|Yp5IJ"3_Y]+6EWPX3YXXrU3!$,DbUtW4*4kܗZhT]̚_$jbs /03#ÂdZ+`y,[&)M66Ckƭp^` C}7]KKXjPLMe8 jr!l6т3 % MsʆFQtEA3hX@9 ՛;7ot'.:*ܛ>|X9K z6Y԰EҙFms\NU0Zm&C9],zjbh lsGqOr W6]Y9; Sf(g7gzq8apf(g@Gmj-p3 s>gwSKlH>JX6)&V#`>?x߲;UDp_quA]| TsI:=~?E Jź~uif,ڧtCw}p]%ߓBaz gqEc{"\"QJw΂^7_L)9_%D\ݍjAm0,gۑ[#Nob7+Aj5RvtD L%@#H2 "L2MМ%,]v=$(֡7;2f7x1g%m$ˬԁKeC_:1?@{[_>o6 ct 99W̾m#ʲvUy>' |,R uĀRr35]BŒK =eDj;.r~WL]98aS%LI`H٧jy`q 9΍7(ߋȗ#eXlx(2a& l-9@dV&N(%#g7Zhq!ڃgx]Ccn*pC$['SUѰ8?.wNk`g"PuyK}@hB`pVעHeL ۈ akTi^=숻fb'_D ۠84 ajcz4#=T$df'a,^yIMHf^GҪۚA$6ؾ e}n~Vf.7GP[K{ #5|` o#=Uh['G)!$=q,CE3*qtPMU/ *GpWgI 9 [&Et#kSol,CРʌaPΔXV չQKzwQF;/ң*3K$;`$G6Z]UQcUHf [  j d / fh~Y6UQ"# (GUc13ay mFlHpM \nNFA]n5&}lZ'i)1NqZ_&\"j iΧpfZu)n)<2vƄ'u.ۃ1xNV:ix|tkF|&@HΠQ\H [dm|S c?eX\U0nEW~G|OI2ar!:k /o=螹䥞$9oE.Q H2RhsOcSɅCVO#$ӆF4SQ|XU]ׅf''?cBB,l.IV,nhx/iO{ K V0RP@K~g6 ""Sv'@>~.G r o8+|;EeWd)BS! GfGU QUgb 1LX(c9sP"h=2uٲ1^4&CfaJtyi}S9|*6 妸v"w: ,>uLVք=rwĎmI%I@eD<}I)b'$?ʃ%-]g`cld[$V_կ+<] cv|%V:O o͔Pο#/D<-Av:L+i?Ve8AU^ 1 zÓihInyhnUPgS'IUUC'cDF'{?mm5f6k xtF~lB>ׯw~A,D؛[am(CDڇW+.b$E$悙QzV)̨rp17Bт&4{$#)`bW'4+*)OVt<:wA0IuWΓhiv$-VLIz UfrOX8~:_h%qMUAy>g U8.ST)%jX#_2,qRZh%&w[9+:Q LPMS1:7DKt`d^| 鎔ˮA˳2s2K4]׼0N$@~ڈUc84@c\ŤoQ2qݖIcoȤ?I8d8_BҝUΙS֊}e2U(`i{#p_MI7hP 柀dtQ3+q"\yvBͽU3dêQɊu nLT$-O_r{Oy$NwG"OjS<=2E_ ^R߭JHZxzfKdF!ʆhGXa[?L?N} !O `}9C '},MnCF>@UZ+ZD5O!yu^r@֋Y)*;mg6fogwt\0 +NdC8*yD$a*h.Gfqq/*ze /|{]N$vr}Ļ׫ן!0&+tM\%D< hI!=BcGC/Ev'7UCh =whN=Yv6 @y,&zs[)dnc5`qoYft*S pva%ߤPMz&N7I?ՕyKl.<~VOt%ޙb"2cH!V+ܲlu1̭I#@#xzH=݉ 4(Z2h4!{L`-shyvq$XhW qN$*A6bjRgê\|p8x%36YϢZ̖i&,k)Z[4/R.7h.)e&O&ιWBa)/=8&'Lzѩ3. C"7$+c   -yH s!t"y\Yאk,} RK8t5*xʅ™Ҷ܊I7y;EM퀮[ȍxO\I&TW LcNտϖWWpNG@tLqG.|/GAPVToۆ ïX]2 3ƀi,9: r"+ܜaT onpMHIm?Ni,}Q kOdFH5$%$B;"FBĻ&g'w#J-z!!bFOI6czDS܆ &sv`dA,m7xy|,"y{̦%Kl*He,]Łf>Zw5ȥ]/CUagέn~erۖNt4 /]3%BK"$c崈`D%$V\IbF[f<תNR 2%\iAN7!A "SΡipE=HttsMaK,c`V)ᏭZءX* "C>(XLx\"Lp>ܷE=$M:HN H-re UDJCl]v?mADz008 Z\GIޑѪW9Hz"!55"F h8GҞ+JUTZ0(hEA?CUgBptA-aչw*EήGXH97|59;~)Lzmڝճt! & b =1!~RQ3 cوp1]1l9y mttW1jEYP9c]r')`SbuA}?+s"9-P2I V<+M_BJ׵]"Nafz5iGAˤ٢d^O$Op Q9aANԣbP-*c~d! 5նRng$L[<ȶCh[+^|?Llj9,~ =CZh_>`ž&\`&ID5PC~39>mUxy^}mY_q:?WvmUBTla!quVp\Ӥ;`ٜ-eDd\ *9Ga pd3V>-Hθ˵0.5iu1uJ\[5莕D MV1ĨaB#1-A}acp&!4C:c t5+gSPβG=k WbC\tqɦ+,E:w9j\BBS ]~\I+FG!'Ph73Bɯ27_耩,X|.@nijK2LWԝ]MM*򭷐wwV|I#g#[^wpjmⰻ[@: ʺH*:`|%Nu *b;bpaG Y ;7󝡖 k膲q b. UA BܓAUժ7Lm飮e#2669dVj{q`3Jaa.1? RQo8ކCo\dHWl l74r6n0,D~%Iw gnsoMQ4%Bh19_`UUs9nF|JIW7v#|&pDgK{9ѵ<%$V n;8hgIeS#GХ t ʶ?[cDt-:/m[kfCIt>/ābOK×ӻGH/IQA4ɪw))@PS *rZIscl[hcP~!$Jvۀ{9 <WUIDG ) C}Ϋ?zxYvO^ ٝ^[)' )+9 cg}ŐmƓ\bzHs?,U4=eP5 9rXXrV$U XG?xr6߰K,TnTly-Bpf[/_]&ch$xREUfx2 KƇ Ρ1\yϘv dY 0&J,M`yJ6wyPHiW~.zO-ƭ4S}) Y/%BƟ3dlA'Z6هku!SФ+3edؤ`pb4A&É7!-s(a:z\W/䲇tMo#[gC EP%uc3=`Cn ԞZ"Sl( lw-j۝qU>)dzh>h⨽'eptF0,c i&OS8hx1%$ϊ4#-H8:LJ׬|"ϩTxH>ܙ\A%;&8 smao iw -k<}9o%,BAL.&S%AZd㏛;ҘќWq3kW4x.BxSJ c0\Xo[mr!3SpCD85BsC)TuA4@g-t ݺRY"WKPjQҷoskX@찓 ɝ ;_КhUMQ:=l1*6IMFyͼ{WϟN3å'8-S%U#M7y~ه(imlzgg_s p) rԧ&7 _aaq^B8AS$:P*>$>( WXv8~ڀPZRUvC#Jp p&ݖVCgupQNns]4Yj\+]Axzc[3Kprub g+ Ej)ݡJ)tlb(⡧nw$}'ୈF{bH]?%TІ(t!\zmĝcȝnυ5a6Y4c"DO* E=> Kzp=OaՉ{v3b~V0ŻsiG+ei73 dj4N+C;,]Ps>t/zF5go/3:7d:n.KQs#BKUL3: 'Zz~9Z;X1B'UuH*bI[J2l|r(yo>ScNqh?RAphٳ< j[Ӎ#UŋX]f[zX!r~\AvMf=ZJ] ^ѧb"`ڀ-4q5.35ȁN>hZw3^6q-Vݧm/ހ_a1[ov`]r|:T-Y1IŊdMFC_f@Vh>;t "9Nي>9mL~3 <*rfI)mbԑӈ:MtA- R[(Pn)nuS+bb(S2x§3?ϊ]c:>&?#WZ*vYw@Txx=U^^c'd1h_V07a ;z7uo{^7ѹpkC߲?D*a% aR S׽!Z\? 5#˧e qx5w@l\wZIk;5nG55k|`~9`z5< ~)2!N|j7VJ\3 BLi9ʽCɖ'b|2z -" 7ROPF[ &x2AwHyS\ƓrYւT&90ݛV$2-WZwKWvw7pGb=X-4I\xftɝF(xϡTp Wh>k?^͍sIK0(3@_ִz!gHY"gƎEftF\@=΀ΰZ?cM,t'-0R+A(D2+rW?e 9zZUZQqj]k|A"!Q &PpGRMHy,tÓ#E|R)H3, ZhsǍxHr`Tiٖ{LnZU>Ba1Z~啃/00|e6-(a6%V33X fJXnmɼP &>aΚuz­3m{X4B\IJ(YxTp6"ߦ) o+ZJt taYD0Î 2֎bg,AJoYLa4-A`Dc#. 6#ru+h—#`/$:}l]2H߁LL0Ff"rPE\#/U^o~+|'r'FZ8 *N$Z$+C|֒ОGnHDbeEhJ|&D֞l}>q.~L$ Q&UM&=Pyx8HKR8:v^l*s'xRR$PscGY yUZ!^b_̵,y_u8L vr#O:YLE['%m BlμmsM<+#b^nEzʋ q;>0 F[bIBRs ]h,&/L4Q}2͍K6y ь$7Ooѷf5~rn+?Sq|k0\$& R#af<,"3B5Ϝ+,PBJ*3+CEb%G-ܪlunR ;M^V|? ݀,a@ b2MD&CEߌ>J~L8fOM3'rUf(G<įl(R*{nN><|{QI(Ж  ҵِcgڻUZKSV^yR4΀jE!埥[CV:UyCp܀nBR% Z{Fy”Ѐ! +q,%B@IDNb*>!W+~@L)UEi8'˼Rtk׊RDzV0{`9`DRV%K|HK@I<#C^ťL*}=kF&%nHH_[?on>v>H P_.$'@e{ɖ|ʊџ"-z@3SncZy欑o4JV4@f`!1Hrõy>!Z4 7"X&+=rIbB$ؔX6qÕH-\"!H"^pS-։{Q_>6@` L1VZ[PfP:'[PY+x5,IY Ă5 l%fu8$+<#+ yKu1VtԂxw儹&ȗzRf\\&b"|A 7@Rwr!+CɐY{` *\Eׂ6!`N/aJ# 5!^8,- (oXWPv;qZ=%RGO_S 'Sf2$hT.c)y@3igoz1vC[5RU[@&]QŔ!lWE0@n[-]=`6%ϢOy"EsevQL6ġɌ,T,$PR"py0$& =lȗdIRKV?8W jJ%cTY Y'@ڮg?ޒAQAq CYNSnSx^I4ߧIE|ANLzg1#Hv2B`ӆX{;A;8UwSGqs.&g Ë0}d5{U#!"QJY1SqJNuVTDxR$AǍE=jMʧԒ׈j)7jD0ߗj Ѯ3g ?&b`GNw~4.)ND!j GQlE"?< h[I(0YHf}!͂V-8rx߿tL%`Xչˉg͇X?o &tc wfźSfJU4jqjA"uoYh]Va䆳NK'9V0@a2r%-F&2r[g erFW|*n+ &74]q\x4t]m1pl\X n ̕Ƌo6af04&S<H c\on<}rSro0no-o766Fob8-;5pKҡm=He;8*T.>(pDY,AY0f9rrR`qvYlAoXjaRv}7I"tw3*:݄`vîݞ*74Ri|++-5Mv$vnqu"0Ov4LVu/x9WlzCMbmRpVJVf5zAJ*G=%*,XnEW`%1θV"HRD-hrgGmdA)K.gZE@Rj h25ikە-x%#.(bum7T1Y>K ;,rm~&v#CZ"YaTx@+j*6s"A#Ϡp[ \#1KT*#&$@KN`Y"zDo 兪z-OE)PvHgWg7,g/qE],LBd|>]@ݴ Y0^"[2axF̃cX_j=X~qɌ=r]p&F>(=PTUϾ&*/:/f (3tdTy~Q|0Ɂ$G~G]7zHݱbZ) }GLt8\p(AEBAW'Ge;G l2'܄T#HMI&q.$ugFK$u?d΋ ٌ x2C83RY8Ddt}12PUU#N!:䆣K쿜0Yџ5B4*t=~1k, mͼUvKEo FxOX桦ܰf[tEBv-=BȥAkgd m|~2% !1+Ħ/$PgР_epǯ-ELkn]<}!U=tRO+FB,Җ b0>,A6`_PӪ0a eEzcMzl0hYկ/ a)ӠrhWpD6C eDL N9@ͅx'꟡jar8K.OƬ5׌ވ &&qW)'@y!Ay`x(-DdyQDfjAdUj4 i2{F37zD^qLxLI֝S %iiEr, *(\.`[Rc/XtR=aENd:q7Et^$U4L=|$*[m?ň<Z(Iel:$&t(\8c6)Y }9'pƌ`RGPSÊ)&6­+yFC\a-jONVGβyԣ oǐ˧5l{`ӱv^Dŭ#^a-9gA2Dh:^+*j(3-Qx獲hQ;ٍZ5xYv&,3('{_D'%@w(@8׹fi_kw)_?äY1̝IwN2iG4y/U\uρ,B{ YpG'A1c8QpBW:Ѥvͽz6*yגЙZ1lj[+hQڜ(F^>#1IL2hܔ:+PÌ.T - tykm\2$Ӥ$u3ZxI i< X(~G_y'ءгdH.*8eM"QǓ-cԏnb^BX[ʛ?-k Z@)j{ǐc;ԒR|]lV sJjvN}ya.k `χŸC7*,sJFaJGgtV[B ϰtܬ)㮫;B~ ! 0ytZ^BѩSAy`>^h+ԼBw<۴ÿ! Nso~j ӛQIj]?nŀ\3ǎ|knaJQtVPrMFJV+g1Ƨ$uR@ڇ1Z`rYAP]Ewɳ+iՀY}b9 ?aZF^5c9s+0E0x DUf֒ձ'3k1>\Y\cV][̇ lUng*Y-φ|w  ,fa3$\|4D6(` ms'Jds]"[W^z`+r_(SDh_Fgɏ@\w1juPeTղr%{a=3EQuZ..k>͞/婓e{9d-&Ϧ-&М8"CP 6g? k'zF_$)&"l1SA?݊A[S;FVXX8aГ|=Zw5umXXh-nd)suA8TR(bl{5l ( "b-a)-M8Z`AuGEw:D=8#n@cJcn ?=ˍv~/,;!&in:S>hgo2/oxﯥFʛn;g^ܿhRdЧR¡ʹ5ak}/vM)FZKFq,\_'9©|C1je!_UM%)Ai5;i]x-I{m}i1rV%]ƣfN1M%IzoImߑ|4pafb t2l Jw?9eҖ0y_E&O!P2āfP۽0`>itdz5|Q-%`O s̹ώH=Ζkxce?\ƅJe{K1Oe8rkc…yrd#,M dK Aq~a^dMl_MZQ)FaЛ\IW\(52KeXi<`D2;].RC BQbm4@#ӧ.i3,W3<aEhKX%)0Dn*bq"*F 0r`%.0۔1/޺>yAK.E0e8]JHU;H؅?Hb>q̆\苄yMz$!#ST;J?OU¢?wT5ofw֔Kxqe1泣DZݮ&;jwZdMCY9~`YH&a(j3J޷z/d[vkJ]njAؔj CtA_ 6`jюqo}D}[دX][ ^ԣCQ"X$a ퟷw~hZ,~TiN*,|(ҡXAgf%Vwos{'m)-;%tʅV@qRBetn#Hl=&^p2(OŊj<yN.S&0`ByDny$ꑔ;%"4 s}(%0Fi<* !0Ir]sȶJeIK[jEbg3D/~qN+Ei^@/)ֈy`vwa.2f,i.8o0c/4"n!x[#L ֈqVd*ܴPpaAfx.J6NJ܀"" GoT,iI+LP mΰd /^+hyrdUGJS.MMtkE,iv\HJ݁S @2q(%]xJ֟ Prg%ž̽x@_=z8KpDXqE+x8?;_ Ֆ ySɀ#/Ρe曠2qr)벷8~4c|lC &<@XYKesq@i Bm +\X%1 }x%4XƜ zJ5v17Dya5DZ1,sq?3!HUlYD@*6"E]G! uD59C*6ۢ׌[ O雘k*̃R=UtB>C<kǑbz|"A]AVљ63~4J:VOkF/6yeۃr5j}Օˆעf06n*8}MOpI=>}F?-Ci cÈE1#-D>CLO;D{ԟԚ ^@Sÿ_\h \+ Iꔤ7rMð&a҆ OeL643a."ݚ=AdpTt*pOuߏ%N u*x^ 1c (iqH#M|,3>;LyA.6[JG89\35BྀJ q9Ɓ̫k5ə`^+Na͉;Ċmv6<%wZ08 l2e_R c3.c Qcqxcҡ[z>@8Oc㴋ynJDzm zts/ !WֵQ]sz jy[\k8jd%7(,)cʾTA69$Y+rX|ۃ*ě9н t㲆*晘>*T7PUwP-n8/AgxjBr K_hB񳍑t**7a\$Z(S/T|scok`kg;7}H4)|kOr'>)K\TpOy#W$]&=PTu1xU,Lס2L@lE Uag%m.l5LӒ Ybڲa9ϙdЕ\k~ٸL|ʎIB2'GFG " >n 0@J?Ij)4BۤJȨs5s89ˮd$1oaX0H~c iĊk[˙d|^I: 0Thr~hz`&K/}爣[؀{ \G;>;!= q0nQTi=Itؕ05lrhIJ٭ TtY&G6@vU깹<:L5,kbOC\cyZ*) wcQ[>rM>rrQ 4*6k]CdyԒ tIuO4gdR V< F21,Hp eU@Šis 40o j)1Cᦨhm~)o(j fgsHBH&&AJ{1*t6a0vZd]; |$J :*=2$.(!@ H$B"X5YПh_lHgAQgaE 2d`[ZC X2)#~QSv֚|o$rQrpȒ4L8nq UR(Y]KHA\afv#:٠r&(P,.ѵ.IUKRTcr :~mr#- jP-4d&fWB q$$cy)V B۟fq}2Ԋ"#˓!/,R‚Nic)S~YJ$6hTH6C+"Bx^@ s ֧p:(pǞ3״Tν9|1 넓mXc-?02ԫE*n_I$뷰Jq2r @, }YO:I ݖt]o֝7W $ Rs1vx-f%4*Q@N:gWحnVL+QbǝnK|x[^9(PMwnlČKݹr1j<=XTnZS#`y$ʄ8_ g'0g|rnibhs#\g9FbdPZ yY,1Ȃ]C {R3c9!<"+=Kc3h] t|'W߷5d+zV` QBF$Ln+/:􁚊LOVgdC=Gzy3=;zvwy"NPau(G3o*s qx,X b^h Ex HT&nD@Ɂll:n'}ڮdt{%nȒEd:Q}8gel^pBZl]]?yf#kpdFЋG+O 2 O0Z-E{֯!bkݬ L"g* l*OO1G<゚^{>E8W^}WKm5U%E)~ǘoSMk#δ"/? ((ie&⋇ހ֟4Xe~]j_]::pJ9dϥ9 x`=d*?PЄ@짺lcÕ)=* UǢ[Y50ұлgZ e1kN0XL*h+9(D|T:Zpٟ𿧙a3GnM^}U9+d불;0%\mn_^[P|z3Uq'@k=ήFf+)0 XS A@2+#$_J1ꫵ]Udz5)1)CYTPM:Ue*Z嬃P(>@ԕZ%6JY7$ YCi O^<=\ :(3S,݅J/0F<@" N !ɻ9\ ѣV8ʚ@ tغlF#-SVׄьŽ 5wvi5'hAy3Zx5S iai'>ֆ1`M+@%+گ#85ǗRJCJ1noзռqkqly`R[Ԫ6dRalV2zş~g+ȼm&J^ :Tn߂172{%$xNO'DC^چi8ʸvS+? fT/'pĚȫﵞ?s+[(0/qQTR> qvb0!4 fh1qx7 ӾM h`nDoB'Ѫ*杠`HR+CjD4/oVk}Coo7Ƚ(6(aebx6x&5X)Z3ֲis{cu;="C{ؠJ2-%|.ة'؝Zh.7b+K^J[6 /G8Ua."~fK'K&gŌ[ m:A኉frNBѱc Pkp>vG.#Z6 aH.2jxإp+봶nO/r߁JV~ptiskG{mZQOCFk] Q&:LD.%p.18_妇L6>sN!'Ey[an2>%K&L9ĜZ>„!ꡪ,+jh)@C pGvRjF+qЇY eg]6+Vܕ #|>֘=&|IƵkwxGpa@_m &P/ԖtE,\Aq #v*z"r$raӗI7F++t6bf1]ރB$)IguU>n?\?YV/%[|rk[9Z]YqCU=M4ALsRp/s7Y|,8D&gE5$!wcW@Clh~ RGN[ueV) u +SMexH>"ݫ*Ar|-uMnP] 2fL''N e>L]̄?50$4|7#¯N|YDELƅ9qyeӓಿ0q}#k:YNDlF&_}T w34kA:}!ѱSzu$ zkH0?p`LFYj!%rL)*^\ Jh| Oy%; "/8\<ʧǶKX0hh S Hg88j]Yzg[OkV-TP! Ӑ"tHaA;E; X \2F&oo/g&%CC-#,8E֍4vc| f"v鳚NH<`(atjsd㸁&~[JŬLi;z}}$HcBK:T%} M(Y흭:;8eūJ ?=/ H !@ =4Po,+$C0W8H uLHPIh `MUhy&{0PB;J,C\`)xRϸX0S-X9$ѧMq'<1czi <(yiE!̃V%iD=ezLg_r3\Gl: láYBm-/ ~NHV?s4aǢ |:+>_V4H Mý}?Pըqm$|m4h_Aj,/}@>C.H j1'# !jE}hLƪd&0AWdY(ֆ¼TC T=H sd-eˌ1z׆T5׈,Li/Dq) 7{ ^OKd{y ):!:"78%DQ|$(T$9NT6[akR7S넦94Tm}Q@ȕ]~Ŀxf<;Z@Mzd9%e a(X0ǎCz8ۑk~8&F~2:%?"7dWq[WkLsٲqaK8?T;zsi$hϕ&fXOGK`VX feĤpPÍf'#Im ٓ^F"\hE]t:d A|dm~{j_3mv_f&%Θ.O?֐~gN9h@V4 #u@FXsy]d?͎,| r'oLxpLӮoC쟲*X,?fKR30Q(=B(gtrk2&2Y|sUfF8cS M6X9 QWb~j$E$d!<) >Pny~^$۠ͽ_$GфjV?T2)k?6*$ LUq2Pu tEdBy\6 zx;cO: ZB*|BX=Ҝ/Kkg.l6m\h`1%n]LRc(X~ֵSJ37L&đ"M7J^>aj9r!v$RsN 豓]ఙ$$6a?Ԃ@` v(~]%)=H!ʿBVqmP"12BTR1_3P)b`1> k(hࢇTd(n6H+)YG"x<]"ؐ#f%w%[C U6J5 ؘ5LM8-Ty;RD*cŝw;xF(p&iW'^4oxf.E1$3Xs#e %S]{1ۀa xh'FCDaf4*wu$)< <{4^DQ$2)V#Nb(>@ӍTUI.m!D!s|}`Lm:Uok5ǯKJ gxzq yȾTz`"3Wo}]qYmIF~ApVlɫP,vغƶόT4>,i2ք4.^TYIYL˾+*abW+e@#7(Uu{[ҁuAxz+>+ؾ It`Lz|]6흕'W6V66~Z.Ǧ; Հ"uuװ,/ Ջp۲*tV_t7_UgO؅.=k`rwjޠ0QޖvqNgcK`Ϋ=J63l)-WSvq K _e>pig/<#M vg 3mVV|`1>{>iqkwosUNj?! zs*^nt}ENn<1I x'/1#o}]a{;߿7E +?i Y*|щw@+5-JGvۂW6Wv^ xϛpZycy/^w~[;[^gg{g}ۭ=?cJt׳Μ8x=[SyVʾҫ_z͟6_ .~}} 7xn$d1o-t$p>M|A!oTP}hQ}?~ 5:V yR[63vM#Q1Hs܃[r!F=j"IP{Ρbx_"&%b̓c# mm+Nv`.ea? Y/$ۤpe<Ҙ1/^tuG;!dRpNSNa &]}Q{ABX+&ˠsDO_r YE~{.%@%lF%Pv2̑;JK<^h/"Nv|%(8pܬES@(^4-rn2j}Kщq5NpNG=^{5/<&DFuj3@*.qQhtJaǼ<#$vĨ?h4XF \,`C+nDHKb)p ye3]x6ڟT5w9_JE2]-b}+ك83x+ s;篈(^@L+`t]q@!V9vU;Cu޾E @ o8"fe&-U Bܐ[# >h;PZ0&`WS,nEEq0##N Y<=:{ob"8&GSF|ͩQ^xv0 gW8V.PuL~pL̛l3GFf9e'r#@*в $Z18DW'P{~:ťް*|GX~GCބ*5Y(G8`@y"!2ȄI*1NPfrHmkЯI7>+$&;>(w3+NړV$>6X|.|~ŷ1l.kz0s+ 00QIW?"q]~8#U uK%=8B%tGu> E +'.3[$Gyyb#`FPoס*bF[UAfp_`˞™kC59 =6@i׀u&P̘6jlNJ:R U VအRYK/b+d`Hrrr:E=8CC&JC+7]M[ܰK053-@M7TӚFV"M,+{H<v+fJK[]d>I^mqan>L~ILz+8; TyJj5Z*58xAmLn@KG/7_F7Ԇp`i+Eqag56)8f_%w8,'֓ v:{[z4|D Żq@~[YKF8XJX+庸қ2OsI9f*Jк1KjS ڱtc?lKݑheXQ.yyOãSHHEv0Sٝ͵RR6h\G`P{K9fĩłdEq~m&^_fEiP܄@c !'9Gю>pM@VI5l,/x1ǽjt9`Yx5g,ڴ@c-< ntsJEO7mU [cfJDi6u>T\L- bga836.2 Ly'̘'?i(2m̏ i!+ ]ǎs;+uT K)jF1Ԟ*:-FQԮ.Mm[act /Cu\[~2G DH'FVwE3ג:! |r?$$pLSǮ8 NqVќNYVB(X W2c{+ks=`3D?>)G1.G$Lc}#\nvg7/ 4݅k#%ʑ*l ^֡`` Jj>y;'wqoNvy B9dȐ枅,PC*qI</\:C(@qxm#&Rp6c/:3;ĞgÉvf\LEbcxyw1AfG?$ΰV ?HJj)2\~rL)"WPkvE)*6AHIx$ƒ~&L-nS* +b;_؇D(N/z"ct&zM||O[Ibq|b_2`O}QWA`Yr& 3@h-x+ko]\ }dȖ5 x0f_0k^GQ 3٪#|eq- uCzX(xj^q$C}}g3Kn^Oƛvm6V96n4)&;A>㱽,+\3٦4_ DT;ւ04B)?UkI۞D Ŕ.k4/ENn!fiz^O0CዘP+ [@0ehWNXwR৛\Sipm 4J+xY#w̎ .!9[JkGz"w UeEIRJ\m?ȗf Xh0b>xVe.p#j.igS;e*+ï @@Plcç8&`A䳁MΥVj.ƢE%K=b?Q(SdVKA9ت?^ːFR>KN~^fL8OBDS~V]a+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTPv.hMvZh)TIIjnANbI*Cպz SD2dpμ 2_dW^6\ZnND69'35ܵ/Pj;]˯BT&e&1var֒WFY,qzU :Y]Ϋ]@dSKj]|.^ASWCǠR}q+35F٬=@Yݜ`XDk4+I Fe_ (@zYd>7&<[  2>N,^ܵsyմsg;?;Am**(a`pޖlҏVmr1(.3cڿeK'<}rbk{**ewa!O SƾךW1BTd3Kv'sZ,d-+2<'SZetbemon-1.3.6/.git/objects/96/45aa13993611640a580d8387caf0ff4a4032ea0000444000000000000000000000126613212007325017544 0ustar x+)JMU073`040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35ݢ{%\\q7tW)Iy f:o'Wڬ\ Uͦonq5pX>8ZljI2F,_ 8KDΌԌL:47?0|:G쵡||ھf,Пezg󎚞1eQb2=h`&38xrUΝ5er{[NJ?Z}IF@{؎i-cȉ- خ셨(-)f QOX&ZWdxr]/etbemon-1.3.6/.git/objects/96/610a4ce6893b1f84fe164459a896026e8a3a2c0000444000000000000000000000254513212011266017572 0ustar xU{8Tip!L1ZzH62LǙ#̜3, ӓhe(eVH*RiT"]PyPvzsL_;(}=<ܼ==YQ@*Az]V\%(hޭ<|9%ち$ԴCP[HB}Z?M{ܼD '1Pg|mS.:~Ų#-!!Kf[؁8 Ӓ":yl_E3;w=829g].~d|bMK T? (/_]`NխS,‰:nAv99p-&ʎc"X{&D>v'g_OzD@Uw/ce;1N0M M wIٌw&&qr/Nz#xe#۹>=U| #*9B#-GjoLZ$UJ%sSTmb0I-A̵>Ӥ=GTNt>~>o1A435 :rO!]~wYr F&V$kgVM:YLec'8+rOHqCKI iQYo>ÃKcǏNPeZo>g Fw<;B55ڮo ۙ7\-V1YګOg1[U6$3(ٮ.U_G*^4/jGmޭ3a?$%^AqIeƨyNQbBQF){0r;6W;94DFu͊6kE__wvWaYVӞfbICewp}>c% %bD 24Y꿫Z۰N濂 @b)+@!p*An ϝ\9b0OUPH!~yl Zo|{-(d )Qqز9ֲۼ#~ v MLO1/Qqyeŵ7'Ҭ 3kwِ+"rpDi~ pV+zվ V^etbemon-1.3.6/.git/objects/96/ff8cf043f625c79d9147dc642ca89c39bc5f3b0000444000000000000000000000141613733114071020111 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3fS7SkԞ9j*.&d3<`JmSkrUԤ<熧U)r:`|>@% .3rVܵMB.%pvLl鄧oCNlq^v`/TEe10>R: ., dZ2ͅ?KFr Fx+Q!~&|1{oc| _W`*/vhJXJ;|qX #JH4I4e># 9|%ن#| 鼱2!m=qF8jc2w5#i(O 8fYOر#h.uNh PQISȌ>B:o5]an9aNaC^lR{!2ԕAaw 1#F)@N͌0'V>d5N.q*J&"HCfM ‚:/J]E .2!&ؔȒ֖Ӱb[T ܉0Prhg}URW/u*5%\A/jqNL++d:;pw⋕PXr4H¤~qH]Z }}M)I}T@aǎ,/'|WcRbFgW#^jƆtz댾Sr;;&KM1/-K\ML_o|O)*J 17] ;[cRpI{ KSg7> /etbemon-1.3.6/.git/objects/97/fcf7bcda403608bd0393d8554b172f8341a47b0000444000000000000000000000132513212012742017710 0ustar x+)JMU0`040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35ݢ{%\\q7tW)Iy [x^RQosIϸwҧ@'3<t,/<O%D6$e{etbemon-1.3.6/.git/objects/98/0000755000000000000000000000000014142105442012567 5ustar etbemon-1.3.6/.git/objects/98/02ff5b280bbfb83700dbf5d4041f217d17a7e10000444000000000000000000000067314142105442017762 0ustar x+)JMU057d040031QMNMIe8;?nN|:/wrq7jMMJҊr2KĿ2sIt#A KII-IMM,(HMK.(`uy&؟jRtW8t&0j=R-77- T= ZEK|{3 tKRs J>~kZhj7l=mUWZz*nM|"zGx̴SX78몣sbm6 V?3c>|*-@C FIo{=>um>TUq*pezrp)ݬK5)M,*I.ɁMPelUYui ޼O+)J̄G kr>YjTmRl 0(*)s^5LӐዊY,etbemon-1.3.6/.git/objects/98/121f0a11b3316c0a4851eaba33e094d47f1f410000444000000000000000000000027213615473504017607 0ustar xAj0E)fdPJ۬z(."ɔ>*A?y߿> 2 :9Ȳ$I8;F g曊Zϻ4L6uI>xi!qޫOhhk.yԪ^?8':`ц1DxkM}e[W]NW~T~ri믹UAetbemon-1.3.6/.git/objects/98/257688f0f6d5de34c097e5495335c847c0f9250000444000000000000000000000005513212007325017455 0ustar x+)JMU06`01< [4ڌY\䳘k3ڷ aetbemon-1.3.6/.git/objects/98/4e10e1f812ee299e93c0be9a1d0faac900b0350000444000000000000000000000131013642215544020042 0ustar xT]O0s~D"h4) QUU:jg CIIlHӞu||w%''-eq:]TT40 I&5(Vņd| =.TG xA3x0xiy0DM8ߢ)wxx |ktk5g 78&9 鳍*} b6Ϫ|mf0j-vF (@! EhBb,c uI)L& $S`6>b8@]VFKԶXom R[ORB 3SĽRp- ZRq#\f3Kp| lZp7yWsrDMx2,䚂4"L&|bfix<봪Yz>daY ~U)DRUJ~s}yT!aQWؐ&@Zh蔪 dfaL\wVHؒ&t̚"\EZ |Јt"^G?$D f{xʆg{/wetbemon-1.3.6/.git/objects/98/64be268f4d50301a4f07bc46d3cd253ee7571f0000444000000000000000000000026313216421314017715 0ustar xAj1 E)c(М 75r& |x|<\8LGgG.',;I.lm +tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3B(GaVvqlrNfj^I1ó k_>v 1ٻ&_HIMLc`(Sğz͹ ?3nSXv8!% 2L9?W,ӖZy $ 9r,Ԋ 9ɉ9h-ڨ>MkJ{,Uf4HN'}~~>"j./NoAh^qAj2lḵ2=_9f>Ԍ Ym9v+hA&!c`8a;K\t7!'8/`V) n ^q2e{yES(DEiIfN1üow>hOz22Ib"#˫Uetbemon-1.3.6/.git/objects/99/0000755000000000000000000000000014173226302012573 5ustar etbemon-1.3.6/.git/objects/99/2af374e84d5f6374f05cb1105a238a835508050000444000000000000000000000306413276743201017426 0ustar xWS7+6sj$mL!:0ؓ_s#tp,9'Mҿo}L3ƖVo֧߮>W:=}R|4U+#gZa$pDRuf6֞zdݾ[aE_?Ķ.${7j; X~n'OҡvRIvsb=LAscv'"etkOnSC`R% Zw:"K4G4ҹ62Efu^7Ο tۧ`lܡD5k5]hc:s2G]ӭ}·oRڤՍZm%fY\#jxwɎf ;ls]8 =J CxMxФi֞?[ Xd8)l n'S溰j5|H"#${9Ƃ s&(vbt\PܳLy_M~npKMZ4'{Z9 vplO B4Rjة{]}&R'_&#?u _&Qi{*;݆{ZuS]7o$/qLy=P>gz xGqHR{ShyN +&=#t. 2*J [r1ep"yۉ^s1w?=;y=J+HXǗGSe= wAõ{]2Z7D>Ϝ 6.ztRӹڢjY(rƴi{6/*k*1ڜ-݊ZkW%L&X8:-%]”6tX< vbQi?bS VvYyZ :v]oݓns|ŇJg^װT&n&v6ZMV܈봸x!Ѕ#&CՂ_h]rPYJ#"4~QKmRRj7dW7g"^G?"o-%#)8c号xr%ckFK.=d6BKf<}GZ)|nSe*hs4nLD CDv'!zSIuL]*7(2d2v9n93*S@9~ hq 14>tƫЩ <?TI& ;̕ uj !!p>CV9Ly/q3{AKdAi|a1= >ݴ Bݥ.qc%)B ةwFI+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35ݢ{%\\q7tW)Iy [ޞRo+v]dEq2TA~2C̟7nm`~aj!% 'Et)ُ6N7nRv%z`%ڐ*|8 1 3umt ̘"&Nz=&(\-ꗻ,\Tk:$AGR-Ty|UaWp?r.!Y3[QWjDV&|J#L>檁~wl2 vu@>=x-$\^H&SŹ(Q4:%BmZT5mh7u>Emmp^tnX C-Q *1mIL"2h*&9J <46g8DArywjm|vC 1q1_sMڀv K,s5{q2GC!ihv5ȍ-RNK!rG wE)y&.,erK*&'yNGo9K_$?Q-=I\ץVd/'aNv,qT6=|'vW羍Q6{V;QҭSN>MH9,!;1D;쯯~ hHk,(X;EU,W{0)D蒠eɺϪx *l:rt+Ietכ(Ĥ䝅fvE8Q?n_Rhx !c c<>A]ǘ9p1QLs?V bxWQDݞd ]x 0FxX|MxiX_1˸h :Ҍ0Vy,Wn6Gq`ˉmܬC^s`vqHKz0#ʓy="etbemon-1.3.6/.git/objects/99/aed79225d97f591b5d2e194c5293779e5aa6480000444000000000000000000000020013212007540017604 0ustar x]Q0})$h 0-\ 헟X5x!0mV Xw25#㬟?F+]1W@KF޻;Ll_tljqz2ix2[}eQ/etbemon-1.3.6/.git/objects/99/d70ac264f4d32d5b9216d9e50aa88ee21ae5c20000444000000000000000000000141514014616652020062 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3B(GaVvqlrNfj^I1ó k_>v 1ٻ&_HIMLc.aKji7Ȧen얖 ȝ+K哊-APo1t6P5~"j./NoAh^qAj2lḵ2=_9f>Ԍ Ym9v+hA&!c`8a;K\t7!'8/`V) n ^q2e{yES(DEiIfN1üow>hOz22Ib"#>lYetbemon-1.3.6/.git/objects/9a/0000755000000000000000000000000013661360226012650 5ustar etbemon-1.3.6/.git/objects/9a/11f2f0e6b659fec0c0e731ca49bafcf491645c0000444000000000000000000000120513661360226020213 0ustar x+)JMU07d040031Qs fi^5W~˖xbd\kܵ•Teg0\&tEpf~F jPEyz)i9% +^vޜ+58e3\w}HX=Iy O.fHpQ7yUZ4e3 ӬԤV$30h_or=tdDRW\Y3~s1;i|XIYNf^v1Òb "ղ]Gl_V9IQA~q <"sSSRP0MZؚIe6e3jfb fͭljsh2?J7C)O,I`i]}W鑮i!`,Jetbemon-1.3.6/.git/objects/9a/34c73e22524ff26bf1fb1ac9cb0c68c1dfa8c70000444000000000000000000000120613617253305020271 0ustar x+)JMU07d040031Qs fi^5W~T`}2{s$0lgWs jcU0,[QEpӾr~ WRPYQ saÙE!^W6A饤%0t\(zysƶV+k?˯Ԁ9,aToGJIM.٨bW|W^Es];Ӡ8IMjEbnANj1I+&?<ߓHHL$uy%9@/+Q0h7'őde3,y, R-utVkCmcp ?xg /w>M]Q.CxC ٍoEUl{x dUE`êTU}޼ϖCʀfU{nKK5*275U(*ѤٛTVoZ;vo&@Mm9)̦v=6/It3ԚĒ E{0':-qFU,]etbemon-1.3.6/.git/objects/9b/0000755000000000000000000000000014174476614012662 5ustar etbemon-1.3.6/.git/objects/9b/a21b9b22aace9ae47080f8dd0eb81a8e9ba2c60000444000000000000000000000072614174476614020363 0ustar x+)JMU034c040031QMNMIe8;?nN|:/wrq7jMMJҊr2KĿ2sIt#A KII-IMM,(HMK.(`uy&؟jRtW8t&0j=R-77-G$5fö~wSzڦs'g*Nz 19_>w ٜo~tTqF-|ۖIV;fY ΅*+@U=Dv&J=#< fZ̀OLI,K!몣sbm6 V?3c>|*-@x>Dօ82ӎm8ȿޔ{n֥Ô&$զj2s:]4Qwo槕%fcAO債ySTU}x5 )i 0(*)s^5LӐዊYetbemon-1.3.6/.git/objects/9b/a42a34fc06d592c52f5c9110f3a5a6cbf55a540000444000000000000000000000216414052407207020042 0ustar xmVOFgScDKBŅ8!*+]E}Lc{v{k&Y>e׸2eǼ3Ó{+viyURg?~0wD0P gaj~9 ^cdxuszզ#{tV$%n$L)ۊ;qץmHʉ6@OVj79Myexd~ @i"L23,)DRiTz}\w]cSO): u;isKјP'bLg[ekhpT;7yB 9z~Q 6yeVPuEzơ538Z*#d#_nkF_y Ri: qnŵ %I^mꚍb9|YpȿҘk1ɤ2NR-;Bckf05VPzKMGEbFbJ7)G.+ybAPo> E:v{hJ "ذb63xԴŀsEڶ N|1Y)sdV]6Czcb刨Ϲztwq-z qHkR׵m5d ( /N0] p ~T+ǎ?ac(%]T'?1{bwџn*FF2݀1yeӮc,`Qr5P+%prbP(8K+ͳ@'6<]U13hN686j_etbemon-1.3.6/.git/objects/9c/d5ef77644dbd279aad7424ba16a005fa34d69c0000444000000000000000000000141513325263254020142 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTPv.hMvZh)TIIjnANbI*Cպz SD2d`َϠ}Qxށ+7$vAds2SJm0] )5*DEJjRfbCkεMtjK, :# U :Y]Ϋ]@dSKj]|.^ASWCǠR}q+35F٬=@Yݜ`XDk4+I Fe_K/^h<+ύ!9ϟmֆ8d^~'XڹjڹŸfV00Xroi[Gr6 CTh1_ⲥq 9y۵PHapk2')ck+B!*JK2s%A{Bԓ9-IPKetbemon-1.3.6/.git/objects/9c/d9a4e8b957931a4436e567ca99218911da6cb90000444000000000000000000000031213216421171017660 0ustar x5j0D{WZCzh)АL(CA7FD ʅgtjt:b֬AǫFB&QUB#U(0f@ggqAėW<sr5G)xNBpGZ7kfg.M=+Ss_|OR,4xTWc2Ǥ?Xetbemon-1.3.6/.git/objects/9d/0000755000000000000000000000000013604573556012664 5ustar etbemon-1.3.6/.git/objects/9d/0da69802772557d5c03a1cf255ea5f8394a7000000444000000000000000000000126613212007424017554 0ustar x+)JMU073`040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35ݢ{%\\q7tW)Iy ǎd/ڽVmMKu\P 1l涁WܫȦ$3rԂO/R>mƲeP1tOݟ6]۷Y qL}Q3,XQ ,d^~'XڹjڹŸfV00Xroi[Gr6 CTh1_ⲥq 9y۵%9 ÿ=!ɜ$Y 1Vetbemon-1.3.6/.git/objects/9d/575721a1201505f6cc4d9ccf70539813bd900d0000444000000000000000000000141613604573556017566 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d`|z3שܩ5jϜS 5yBds2SJm0] )5*DEJjRfbÒC2>4r8R ?3nSXv8!% s+xY{hz#7?aޥ?4l\v޿"{@Yݜ`X<(gaI&ީEs5᪀'= RcY;QcW\/s];WM;wSԌ Ym9v+hA&!c`8a;K\t7!'8/`V) n ^q2e{yES(DEiIfN1üow>hOz22Ib"#hVetbemon-1.3.6/.git/objects/9d/d617212767f8e06976f5ee06b04f9bbdd7c8870000444000000000000000000000100613462026443017756 0ustar x+)JMU032c040031QH,-KNc[nF?[>i%Tx TIjEbnAN*HClϜH݅hrM o]a!Nqmw^]U~^qF~yQ2􉏅J7}Zw!Θ3pUM @!3/D/YT{E%ďݓ}LSrԴ.}㇗;."d19&)!ɺGͣ ɖѡ8r&(:6&=u98A+jUދzug [&$m/~BBКKm\YLetbemon-1.3.6/.git/objects/9e/27dd53c9959728ceb95f8b34e2e1bce55c31ed0000444000000000000000000000262213455033406020171 0ustar xVsFSlN cId[S~zJ'j}wy}E"]-.#/nq$_B5悰erN(f 8JR5>C¥Eɹ{m:3:P՜a]mѵ^N\c9ESǚh5{46qx5tĥ=]r-8r6޴ڹ!ʙNfwlF=DX ]áe+pTԟLoҥp`aBncWhڣ ̑yshSvyt}i=ħړbҟ]:=Zd:LirLF4 DZ(HOe lh`CFei}hkۻU_/Q:ю~R=|W\LkLvsIF/Qqgo~5n毛:ڪRzWMFբZM]W֨T}w=֏EGH,DH79)Uxd>UwDvh(j`ϒM_AULTnvz 3aJMV¼AzAi ~! 5JOzґp.zOݿk=;ޟґ_}Il KR@D_ IC/[TEک6逺^KCgũL٦Qyh<LuM[QuMF:(o!QԏDZQEFS,\x۝Ͷ\[ď ꎏU A.S1r/6=U7^y^KT, 0uщoo*i(9>jˆ!Sjc{4/_ ~ϫK몃*L_?WXNmYwH峜;1U)etbemon-1.3.6/.git/objects/9e/3e35fb4eeff1b492dc86e9212ab9486085f6a90000444000000000000000000000132613216420070020101 0ustar x+)JMU0`040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35ݢ{%\\q7tW)Iy [x^RQosIϸwҧ@'3<t,/<O%D6$e{7\E88 a@γf,mDT^+Sr."$ؔSaco$K3UXy[s{pMi1/t.64*s锈jcVZ)ݪaxc *'ҝChU6ӽ+ T`K; BLB2F.6WzJ8\>  V#މi_>YVz|xTC `ĒCg&C׋JZK(²&,{p(A_1-˾٨3R9}O界T.meZ8it\bs))S\+ 1l v[b2w0`U?= zYn3jӼt#.f]nJGE7n:XecꓬSDt =9Wp1܅=wtavr8oq\S6{ʌ&푌Kx() R|А:1tъW_~Cq]O ::>Q4_L?ͭ_Lrj1~ &%` MF16P/Tj}XٝYN}qw>ndri%ūV\d-{yvMZ6.|9qHYu1/N m_=dO:&aTHޗw &65E/(z=奄0W:Qck~jN7ڽ1=cL3MFb0E $z^t<آIJsxp _?O K9iW%+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d`|z3שܩ5jϜS 5yBds2SJm0] )5*DEJjRfbÆw~On;A=eVVdj{oMb>Ȧ$3̽&Afwlg~<{ҰYNry⋄A4eussa?=а{ &DU7Nz&4'DzvN,s4F 5_+v.vlg'@% .3rVܵMB.%pvLl鄧oCNlq^v`/TEe10>R: ., dZʬ%uH "]eDz-W"Sy|*⮔WkM_+D@StrO94.˰`;\0"ѕ|Eit+jӬ^G(#Qy9R*Ѵ?rcdU FwkQl2JD3'"iDJKJlY`~@'zgǟϾ|=& ¥*I~}KZJ0^j*+N QD%{@?Jrʬ@4:ԩ`^E2Ap-&9"L ̫<֚s2%z~p蝠pyg1`0. fxE)3]gwFM,p}`8VVfGqR8zCҞ ɄR"A*dYLSW̵S/[B}鞂pV:.*z j~pf,?3T3} 6hu+Ъ.zL4 !0WM%=ۜvuhenqa8͖4_8Lm MT`|q`Dw̎:Zxe NRe %_=.C[.hUT#z!efADwborS&uFgumy{Ki-f^{T\xqv["1/>|!Y~M9oUetbemon-1.3.6/.git/objects/a0/0000755000000000000000000000000013661360226012637 5ustar etbemon-1.3.6/.git/objects/a0/1ba13663934a5fd34cd88291546ce7e6b34b2b0000444000000000000000000000267413304753620017717 0ustar xU{8TipljfZVd[JĘәys3 VQ*t.6ZFIPQ.%uk-jkCvz9g_=ALgG7g5'GUP Ðڄi&5̾E뤎S۟fB  @|ƸsCwUQ Z\yAAT0Ha#nͷfLq"/;=B>Tdey?Wq/C25n:5G\#C qH aR*c0C'n1ڴC%XIů3i9<H \*. /z8G託BO٧En+zIN-3߷kl{#߻!;o= (HgHzf_ϫm.i={J1x2ZK5?SDTt;8F2P; WL;ҝL:B%% m iYk57+/8.F}IYݎ^j::N-=J=6[,)yf~a,S dugKtM7۶v<%GL -_-2.PYe=߿6yMW-4;(~O].ne&X.?`d(vG'5'}*Ljg ,Tdbn oi?\ZpEb({%F]H״"w i!@xCCڈ.詈sbR Uu×vhwteȞGZt/{v9w((*ZFխf>Q6EfKHɚO$_ O\>{>}FH.T.??_8Ų^w'0͹H! +_Q%1w^ߞsy*(b|1S%14t֜MWzS|[O dY**}em'% YY}6^uM[㪆5㐈jNAiMK{MىKpR2 (_ΰqwuiځ3dHJ[0 7ԌƔ[Vqʻȶo=UekHē$e׶Y=VlAgKKPxĹ3 ~qu_xf]zgy Fe>w0~UoRlU!L:m7I rAb]c!)J+*gS}} ]`7/j /M9BH,Ku>=#o6z[MJL5q )yU }oB 4>Nfpw4HsXG>81,PF0<+I!EBH9}[=/lӞ0Fetbemon-1.3.6/.git/objects/a0/bccba9491eb2680fd67dbf80e749d2699a0e4d0000444000000000000000000000131213661360226020225 0ustar xT]O0s~D˂@[ Tm 47uEg CIIlHӞu||wQmn/=o窄NkY4-(V2R:Dtzy@ >_if˫diy4u8);'k|m5rk絼`ϳEv ¤}+󬞈Ty[}VC-orZkQsKo|7>ٍ0P&aN(cYdFO؈G:arQBKD%7q֐4$Vυ2^54x}}hhS@H^lxguX v˂ kAY21ڵef0tLh/e-]b *9"GD,lgexFG=e7&'3K+aS҃6 Zۗ PBDkJkU=RNOFKDij3SRes1]eh4edaza~eȟO ~ʖT @@DTO63'$'k1i2l̬=+B ZdZw-XhIg(m zx|D~3%{J"W4@bq7l9\_x[}xetbemon-1.3.6/.git/objects/a1/0000755000000000000000000000000013212012604012622 5ustar etbemon-1.3.6/.git/objects/a1/741ec392f52e8482b466d515e94ab2f416c64a0000444000000000000000000000033413212012604017623 0ustar x]N E}fi MѸwϠh`۷|<97'R2êw"@ ɑݢf\"#W#PZSej'Zx$vH*`HA!*/In7xms%Hen+K(/^bs,WE@h{j#ETDg n3.+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d`|z3שܩ5jϜS 5yBds2SJm0] )5*DEJjRfb,vJA?:y'ǡ MO=6eW"Z0ze_߱mv7r]zJf91e/ ONy;%|}Po÷઀'= RcY;QcW\/s];WM;wSԌ Ym9v+hA&!c`8a;K\t7!'8/`V) n ^q2e{yES(DEiIfN1üow>hOz22Ib"#Z<etbemon-1.3.6/.git/objects/a3/4e8f790c3850f3d811768ea61ec0f1284570d30000444000000000000000000002610013661360226017564 0ustar x}vH#{d@qX\eXDzϙ3I@U}}b} hL/U6%3"28Hҁin矢bҹ9 jZk<3y^$&|x,ٟdss"7f43y4EYfұ9Y ;_Uo_ 6tMכF=Cx-6^Nb5O?~8 |x~&چ0א0~xt Ḩ"6aA-s l`]H,D8Fz$Z**z]i xhtyEK?7};h`;Y }'酳 h_^xn C E]27uxA et<]NFJ .iFnL{$%Hۦ6~k7AT3·dyΝJp -B@Ɓ6;!66[Xk ,P,. 0R!Ѡ0(sx=a8 4'yR<0G/~4Aa4'^l<;^ٻnwb%G$-.s$LQ|:yi?tH87΢H2vU%{7OGLDdBxMIm@ UaS0FP`?='LtA$*H %8Z7#13 @<ӥ[v߮SC.lP9h fTD^6rmπ=.\L"6ǹ/t)Jc뾦"E)I`\@ MrEN(v:Q4x,dH6(GsE2ر ,*%L:.9ʭ de< e|7U *UԇY8b=je~+)1B17lhE%__O's`/GhX}t=h54DFvݍ䄺]oqM  7#PAJdPa!LFX3JldZ\C5iB=L'}&K@-j-(vCtz'nvFJfp4(BϢ|oV=;E\ԗ) Ny0D&K2>6B@n淄#s0]H},gclY< ?o?O5bF]|g[*7?KB5BZչRߘU#球Kd ~cg?BvRL#x)9EZ%zS~\%= V`(2,)HVUa-߹)h%N`fJrr]\#1s9T9GfgeЄ' @ӛf4c%G##WH#Exn*)4uT)m=DGtISHj5Jz%qP@=|CSŤm A"d+y "E%`t,ʼBeYJr!S;`qcDxMu7])BlTK  rpua1DB)zx޺U}k;ɖ4J%zwrfL.(l%W"L,-f, Cq^)Ex]gV^z.%o.vȩkKk:@@6xOㅓ/dZy@.[ ԅCA,#'7ĉ* 2jj^ǡyw~I^QDO |>6Lb+J|iSI8K?SVҔl!a~ 6p m {Y`B9B :qp-PbV ^rpS"e3MOIWKu} ~]ĽuG}>mǢFZiN{gTg'Mu M&J@*^uhq\F %2fXdXBVobֵޘ2RfJ5@**rZ'մ{S'A9Y܁Xk0,Ң) O;oHTh@{^n倎lWmֆ#)BL\1Bdpp *ä afD4ntSMr[a|lAKKq,DdX2p\pSv"VoIVpYC)ŒpaVx` ]iV+=02 /F-h>~&s/rw%f2JmoM^ȶA8v|!Ǯ8щ0'MFHWVޟ &bOZ6G‘4&fo 1lfh A*v)KmVRop<+"z܍yހa{JM4{NzN 8Ck63q¢VvO! lJWxHOAM\wϼU᫼\܃u0˽ 6 5Wیq%8,Ԝr8͋Y?~ t+|-WO=fIy4Tw!:@(I>iAYS{n~c Xp~y?L1JMG.ʳ##X稟zz?F;4Y/` BB!kbSz25&e S!++i}sxaO lLwG.t6pd4zB'eD w@X*Q,?E%Sf.( ofB؝Cs<řC{^Kn!ӫ 7!]'fɶ/ NmGʺQ]9s#ibldyR@` m_ T& N9In ;ھ*o .Za4|M-'2:fm Sv#n\j]D/-/mKu.3lakgVn"ik,tFx(^V\mr.U.5x4V36`#gQ{k1Ce>-ƝW\a[GĬ ~ g^zϵkO絮cwۭRX{+^"T/a^/n9Vylp)>RZOdm|Gjrx8v%FhIY+Ud\D6Nl^03:( ktA&։m|YpqK$ ~ì#BPr,ApRha'&K%pHA<M橖v.(đ'6bF2n%k^;j L%tndkwNTҴ=ryjvZZ4p;uխy1ac(2=+D8R,yyÕ%#1%mC&NynRLZ'͈bl8\]`@2#ˠ<,·3Bm.%] oz֕K$(HA7jR`VùVcG8V)?cJ 6h,(*D%^E e6u` OXjmC<l؃b(ɇI7_`T^qga* kԦ mtZ$Ly7gm"[F< x=^o5E܍CnQy`>纮deHƏF! qj\O CsȤ6WhtvsM?vfStڲ!y/b(@œOuE.r7W;hnJ!6kg}]~ 6t%kU0G !0R"g3__΁{/E`+i5gu," ),<XfmR m0?DAqE2Jg YIZ,#<זfbCQźtͭ$&jDghPŶ2K31p՗ b?nkI=]"`Пҵȹԅ0q.~G`7yx;H)y<}C3F܅pOeqr~[:š/yAr}Ky%46"ΗNZKiPxlîֱ ѵ͸G ^ɿjKiW S2p/޼1/>BV$^((#e=` JxxSi| .3ßg**X62N9k&V-¼l:EL dEA@K19k( ߫C`2 ,q" B:Ei|+̝-xqcN"nQdd1=il5(+_%4v,XM~ )z[1b-<ij깯N-a38e]=T*Ϲ;XB<~P,G)7 #=- ʣ܁D{jZ cdHDg|JL70I|+@JCfaw/8c'?*gz;f>sfDfc)R*Än}Cݳ5֘l~[^!̀/ ̜2=O45˻(rI)ߛv8Apz+xwy;P*i{3hXocgsi.quI=pj̿]4LԞ-k3A :nZr1uAB%ZEt3T,@Ԟq Og+0F  :kiJ8d`E#E Jm4 wDG177qK2ƚ*1;'ՍX; Z0 cΆmu*ѧ8+2*-ld6p(I-wxbq>CAr 4-+Xqhu#mf]Cꤘ=z~~/Ϥ 0G8Uck!jqQ :O!OeΥw!tm~S[*U7sPCWgX(O8>ga}bQrӱ}46<[%[Wrr $4J.g~$}?P[!t~@cBMe BzuTWc=oPat#s]XiVFj`%hcd#:GJ+_ rC"YIhGFC! 8LRHԑu]PtJ/7ql.N<>@*v~&a8jgUZ'i41B`xɂp0EEd I'lq)YI̽A6hłT8/ ZF$Nɼ^2Z8U0X8'("Zd/H fj_,~J3p$ (9 AiGo /_Vӧ(ا/{ Nm)  #8nR[Cxvu*o!pȝ9u/G`JfQ+dP , *3>դl !`in !Kv>Vva̹drR_ɯbp>b+,X[< :,!;8e] lV@|B1WW >>T|2aJq\0'vԀﴥՎ+(szi,Pvw4[be\*Lcp/8'-@i-$ZlTkt$gNV!^͞5ykT89;n ;h>_N9{w@&ڋS*95? GP2aÏ`L/bDa ~-zr0W{;[Y+NQR"&Mibl1^}!*hg8;1! Jz1\:Ӡ0({$;U;.Z&edǥ;{;mџabY`cHjzElt0~A+ =JRMNtk)&Q/ $ݱWiˈmt,Xᙒ/>!F1av&dҮ4 {H`]Up0) ZYek~ORT:>~2iO7Oc2O?^#-c"}$;da9R@(IvYx*_>mD=֏B&=tFiԩa' ap,ҏU-fvr+^Sh1K)m׃ ȦkPqӭ&mMڞ.:$;Cz f{W z=̀ y) IefXJ4จN"Bu*(v&,%aׂ̠*(m*n8-G,Vv71= axdpLhR56žb* r*MnZ͓jsj_ 1__5qV .rܝ(~2 KX6!*g^V%di1S Hgm8N[.˧ʾ#$.tdտ)[: K:#(kdgDT^OmwM >*t`)T!*,3+lt4#rlGb]*PB^&f;8MKup՚fk*Hk[N= f t7pz(tg쩀ͳRAX1^=;c>SLYwWW)#h\-ym'jV7g;UO T:BAN_`y#{Ybv$#0t[(ibKg.b"*Hk^*j 븺Jp^aw3hx (q7']_uH !0$!%V"fJ=EV1ˈp<c=J&qtzŶf A13M,džF C\{W~-+Ug<.NpNh3r_.Kulv0>A%wotvFiߡ=ZW8fƐ1`O"ԙs F2枉sˌ/ohCdy!}gK_?c-?#zL-M>UG܊4 U[{[1Jk'QvN:$e:]}z_Iljd mfJ1C߼,Iػ+ɗ$7Qz P"RH焨*.?t-}6a:kt~*Sm^ ICCYh !Z.̲+<\FCɃeaeˈ*Px2$(}z ݆Ђ~R!f_FSA.LܟF0 ]OW ]_Fڙ>B ]!!(7c\QǺ8nd3Sk׈%J*8Or=;ϛXl{߅hnY-m(1'etbemon-1.3.6/.git/objects/a3/a475020f56f2cd9ab2da87d1dc64a02358835f0000444000000000000000000000104213324761275017770 0ustar xmRk0go! IwcHa+xǧ,Ǿ"e$9I}'{trNc9 |r|tDi`$2NoHKbH&4HESp"%}5ט)Eq_i J%%7.|@I&YTT,rOU:rt CGX` \p]ћ(G϶fյ;a8 8 nIڌXֈ o r #BKw}{8xWj5 ۩ ^]JWL N}<&)e%,%\kVCȦ ֘1W&62! }aۯ=l"6ʦڻ39'ڮTziM}'>a_]as KܳtON\^ΫcC5߱M *JsB7ˏoꔶŷW+),L(a۹L芰"N/z+ԠrRRKsJ:.V9c ٕWjp +,*f$՛ұz>AE-@V\̐joʫhrgY#IH-I-f`Ѿ")p{Rܛ.3$1'g,^ʀG[9ԝ >,,'3/a`jĮsʯ]j dCd?[SzghrU_ؘnl~(bcg *JV%(F H2GU4r{u;]ZMPBQ)(&-lޤzEֲS D31hjVIa69yL l֔'$g0̴.sq> nH48,getbemon-1.3.6/.git/objects/a5/0000755000000000000000000000000013513717234012645 5ustar etbemon-1.3.6/.git/objects/a5/ff77bcde5207dfb9db1897a143b80cac95bb550000444000000000000000000000141613513717234020307 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d~mmL?2< lrNfj^I1ó k_>v 1ٻ&_HIMLcj~kcsc;ǂ=d4ġ MO=6eW"Z0ze_߱mv7r]zJf91e/ ONťٷr-/t4gu}*DyY|4N73'F%iǡٶDv[oQWUpܭa[b[x|( }|? ^'{N''ߌ^nrӝ3DZ eMիjZ}?T⿤^I2Um0I`&3r΄@LI 3|f56nK̀%SIVRM3]$t)X&RxF ui*#Q$缮ާLth<: Sr|p@*Mn쩃AZ ŏUdp`cvC-m'FmwtG]{]#Q.n6 R)! X`{x. 8W9)mѕr913٢w;d-Mֳm =fYI2bq&kB;I'.E8$.NsUD7 |9A(|v{\i<}nޏr1Lg„XZ'%,ȣ0I6=%'Jm|32s(\ʷ9Sf^AC!?T5J w{]ea&"'_"u-*s*#3=l۷clW5/%/p~(ե. d*qkͺk[흿63Ytweݒ JZhȅ0r&p=Ъr.IB. x&3rLRT"V4NDp022_;w}w,w\)FX94u/]Bв9՚Rcd!9i܀wࣥb^2%ּ̍rzHvP/jk!x^NݚnI J]eeW6张M{p*!5%]@p,&U2Wg\V˸ӲQ1y\o凴:}V\Ƃ eKʣ'Ȗ-'5i<{Ϭu [^ lgqn%) 07yQ)W&=}zY<.0SN=w]U]նв^YQSeg+riN j⥤ج2Bump l^A}ql{^ O^̥F.yOVɥ̻`wwg ]S0C/0`BTK?&BrGj]sIvpnK"WZh@\mk1=١~=8,-^*fD٢֡HD^3ͥWC2"THѐ #1=*FD)C.COYz*[xRC>Ҁc~%XʕQnl}OX ;\GE*.Ec( gپrxJSZT#v7_Ƃ&{ .[Fr=|o>@aG&rG'>B9-%|pjZqITY|[%#r>* .j&5RJ){Zz s39dl̈ul~vo9݄2}6$:{"E-] ~J8\աI>_ EIK V0ʸ{C=EmS xUKb%+CM8Cřk Lw`eJZ;g.ezr.t,X9 lͨx? eTj=yؿ HG>? rDݸmIWetbemon-1.3.6/.git/objects/a7/0000755000000000000000000000000013767516617012664 5ustar etbemon-1.3.6/.git/objects/a7/4c82d9db0d7eaa5753a97e185a52f0f3bf9b230000444000000000000000000000120513212010614020122 0ustar x+)JMU07d040031Qs fi^5W~>wu`~V-:֖0E% [Y'./1Cǡئpy%E9 Nz/\Uƨ`)Vʢ˄,Ҩ7A (7?O/%5-4bEΛ3]Ya_~̢bORY)'4|^2d5 i6 /J,wAq5Ԋ܂b+WMx'N̽H2Ksre]Ψ!nR3e$e9y K%T&vU~ZP[$E% ^_"w'LX8 r?\ n818IA6]a.&]fA2pnfi-m&Q 2 ,^i qQL\_3ǣhCY# ilppkFt4+5C45,I8]&LUs |c2MԼoWz_+xV ?s Ma…UV{F~Z6^aDП\G =eSu>4"H+pu~, '.>3ǦV7\NuF~Wkǫ،af~dS ƑOϮ|Lbyir U XQ4G/ID$?Q 3],ͱp,TFxl aPauV1* h,}dk8<6Ѕ\Uנ|Cc<1di:IX~4-f d,.4 R$ M8h`#D'^irz~-4sIg"n IN p.3^Π朩G$ |̔A`/%$~-` 94:,=, */A k 8 Q|4X::ؘ7Yѫ_0c|_3:Vӑ~8:`:MWp!Wn/Yf0Gu:ͪ< F a )!hbn4(ժv`eg Ȩ˕X(מ,PWm`vx.EM&YpFȘg`}\zvC?5‡&LDh$昆 1f)]&Brv)`!.%pyE9\뛠0{x]wJhDx{  |u %c \>ŘOO ,#GYDZt}&J @ca!</Ĉ TG#D>6j ^ GZ\$ auJq2Q< rfĤ825X(  x>8;e&^ftQꢇ r?#Jʵ1>KhKL q8XB2ձ&j}55fET%23 )c|ڥYf BӸr4\IA^bQ#Q~fa_H?!aꯕ:-q,=ʭ42P,I<o*b(J,Zz$cxt=}*c2'XIp)GF06d)Mh#DqI?\% |mw}Qs^b Lط]g#)Ne4L s:Sj>hI0Ő8LX9 )(J%epq% yYջ\+:.Y-vbcm^PxJ *#ͫ?-Rrd5;$e@okiZMN{ S=Y2U[Cs cށ \`̢9j'̫ƈQ߹rB&>Wޛ6f+; EzRתƬd&2t9VdW zN^}cE-&i3ĽFɬtyEjzWGȄ4VrF * |9֝`|9ĩ !TrxFPϠRįHa>0>5"D#a L?I$zx&eQ>ǔk! j/^|+8K$h;XriqlyЦC[ ƕ%ŬR۸?Q6.=)\XFTFDNY\c<:zj99z-~!/)],*-~l 3G,'7ԉ)<EyqY^c{ |5ǧ pA!h?W \/KN 'v.si0yUڠ5K#Yf NBRnfc iȫ8tJ^L("|+D)1A'YDGĻlXSY~]WLyuB3O0+LU;JI2hS8#Na4͒ڜ+=&`Ŋ_VZ+WUN@RFY-ȷVkU[ֵؽxVy12 CO"9rڽi5R~K"$f|LxfǓ+adz&)I<#NmLW}F# &H[d"A=?/oՌN}p[I wqc{N7ˁp)LbM͔J|O sas [0ZX/B119 !+YFPLCsk(V=rvIK3̓C!PWeתX߆Kz1Jv5 ,yAw-Ee1qQBM^ҏH i;0},k?ʼn=#"̛la28H'x`K+J#i""uăFU~Х0HO]k_pD Q{0 ">nt;&<T"~$Q:3 4X|l!9y=,<9a=_y5^3*H"PXkO y'Z0P݌] ѸgV- !2D63j=0BBL՗AkJkI^DiZ1X&8]ś$ϣ`@Y*v N溦>E 9K|Uol)nZw/_.?8Ejvݺ]Rs;E>W?V5@ͽ" Z&vZ Hٰ[^|Mj "5-=W;NJ6WI8NB/KP;SŜOZyB@r?hXy+z#n5_1f5Vl!~nMPE1œS<_s%ϯ!Po9MN-2Ic빹Em*^E,HA ;c}z.&3q[7wB`KHb&Gczt%攨z!ܡD|gaxK>s{r'u+pL7'_`$UӎzpRRM4\oi$dž7w{KǒQ" 5 cɘ^(FہڗV{`1[hC\~vk桪Q_0'L /aV7JJ8=i)@ħP#I$~G)W􀮶Ub'<]2$^,` i3e+@v|`! !DCT.:4 By37 dqj˷u:Oo\#8sXrs>^|Yp3KX> ؝M0 dÓb'\ڂ̆〘 čO^ WVyLR3D>H.2)]'c!/炙 &3[&JE&wc޾BpH&\7 H~:6NN֯?ŏ;sK]rz_K-4{4~4ЋA4=FVqxK| y"xpq;4zj[k=;BB#Lb֕ ڣ=0 |SzϵVמ+(?xvemn̆^lvb[{O~<Xmz/R$0H&ձ5n87 ;ZE7,f»ymBВF"A2`'8# S]4 9AAځ.06)<W :^ ɦ%p8ZVm7ZڹASGny:H.+j6߮a<ե|Zv+5Ɉ))0]+ ,\4f5;,ۊP?#x̳flм k4DrD%(inEa^D^wPs cr6dVU)& ֓|2$^0`4GAyYzgҿF\OZ$2o{֕K$(JA7jR}:V݅VGZN/TN 6FƒBt[ .Z@ ^[kQGx£+lBذ ^=L>lO|5Qyů )v1!M!L_5KW5O|8? ` KڳjfC8o.(=u%3!z-rXVGtزj빞68*r;sȤ6dhVcͬ?zִe*C^H(@%%OKZ| U';q|Ͷڙn8bt%k5P\TeJBjV2gʋ\b˧^YnNJ@ ŠgԻ¢Xh3ArSYyZBU,Vq m 8? {_ǤTÅ!KI e$~ Qc KkqdvGlgպi[a?,,Ƚqڝc$0֎CH ڒJjt{B;: umzۜ`W#qMwu)/1)jduٶzIfRfG+tG;eK +\yEN7}iQw5l\a3f/nJ m&kO-t`)xs`}?.SNGksHI^v(r]:Vj@u=>Mdܶ,G[g(ћ+r?Nsm-zе]0 Z*sn! !LߐOarӈ@J7|ʭeM{: pܲhz x?-NQE E^fм\S^~PG)Tc,IX09i=mBق2_qc9PkGӓ⻄buNW[{J;?7>BԖ4pK/gp`% t0Q{rz-$U nVr1mAB%Z^L#TA,PvמqB O{+N j"ߝP~c&"Di̝_mޓ!H~M}@CmVY\B8\;AYW3tj5DY<֫Fmƫ2%־~cOܓ5f'8V Npi|y )"XLdjMVoY!xúq'Kt|)-bR^&{SÉ MQ:_NVxGЈ&*9J,-:BaKzTPK1|B-Ut7hٽjcs!nI?RI$u~[ UE=O\{go3mbG rOj[I3;VaRV~Ywh$SJ7MNDA-*" [|(;2OĹwBԭX?]}'{*c$IS3Wv~N [ 㔰~4x_yv.QD1 dh _,~Ԫ2 釸RU }>>?{;ы,?[3k. GP3G18xׂHT/X_',o~g:l5)x$ƹtW||HtMVP{5w4dC5Jh%!(#٩Rر5w!2)#nGuow; Q<+ &d2khT.1x V-6Zc&&I3U?), [$'~^-#XˇgJG~Lq3C7OP#,fכ#v9GLCNx0)gE歽y>IY=lԪHۆP}p&S2?]#-dFE$lIDt3e"I. ֳ~~9owu[?fLFxZ Fݧ3TNѳ6 !8fd=X! % jq\TZΥj~wtYdӱp%Pqb-'m:]ڞ.HƞcB;ywuIV(^LMa^MGni>ϦB %&5a׀tY+AY{QHai:6mˑ,KS黂`uHvvˡ< t|ZW}46`xOMyY_OpZmjY +$`݁X%p("ß%I ^/+ 24X`)TI{|&i4 \m9k:!"rKlȑUOA2=q'|+ǎt(gzK y|;붻9097@; @[0IlLRܥ.ep1Q)R|F]=z4>eb&)(OyM%mԾu3nv~$zvtF쮀ͳZAn(bDz.vLF32Iς]]k,@U;jֳf_jQF*խڞ>W ޸[,{c lz!#( ow(i#\Er Ezm؈ -VJ༴ {O8,SؾeC|kNIAW@+$~ăb2HN'%@52"]CLptAzöfk$"df3ӄ̒u0o6^ I1&{+g"oq+#M#vBb}WB 5;-d~G 6Br]MXD}`}Ź?-"f{3HPH~V|8='-~}QSbS8X1^B5bġ鱹§: DH(=!vRwZi ʃwB2:)j#) =_~%0؞0ph&T3 A,?2W%&KP%bUD:'dUqwټ ;.).HLNpЯxQĻlNg: 8'3B$5z*nM|"zGx̴SXW*BWKYhh] Z*-@ ӷ+dr9{lڤPUŹE%%9p˞k潺%Ӻ}LBoH=XcVU\u-z#BLN4DB9%ճ!ֈM|%pڰ38)kLf~ ~mRTo9s]qa$Ojò=^ȋ.ú-A)/E^r\D=TVetbemon-1.3.6/.git/objects/a9/0000755000000000000000000000000014032545161012644 5ustar etbemon-1.3.6/.git/objects/a9/3ef03214374d04aac37bb98ce16b400419f10b0000444000000000000000000000141613767534207017701 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3B(GaVvqlrNfj^I1ó k_>v 1ٻ&_HIMLcجx%ScJ3uf΀*Of6>۔+_{ljI2./1GU;K봥VnFn~C9kC>\Ǹ#"fnN~rb0,.UI?]lz]$b QQ\ g=lǴ˖Nx1l BUT# B@}5c (-)f QOX&ZWdx@ZVetbemon-1.3.6/.git/objects/a9/599286da8379a4abab7afe3ad84bfae9f83ba20000444000000000000000000000152314032545161020373 0ustar x}ߋ6b8pnq}KX,IJ~8J!gFӸ?>| cԲ!ɍlz9m>n( EN }ƲUq*x/{Φjv66}I>Fb[FXzޏZ[zI~^)2$ǰH|eY<>u$xЉ'",܊mS>Nm3{Ѥ+|_?w;Prf6A#%zOLµX:U|1J_!uͳɇTXcRYDug3#eT(]ig8 `F䰢oN4fqO6W"`ߟp?1w⫁,ktLi/2/va|8í$1KH3Z΂EB_cJqUJNxNvy8lr&ާzg|F2tKkUdlҜNj;vh1Yݍ>MwhFpR*u>("IM3!wd'Eo`l"^o=@: -D%S*Ch"GCev7!E 4tNa8f 0bhR:VO'hrej"\m_^yuYL4k$59 ;W$\|O#"{3e$0+Q0h7'őde3,y, R-utVkCmc=?9 syj_Q M]Q.CxC ٍoEUl{x dUE`êTU}޼ϖCʀfU{nKK5*275U(*ѤٛTVoZ;vo&@Mm9)̦v=6/It3ԚĒ E{0':-qFd&/etbemon-1.3.6/.git/objects/aa/0000755000000000000000000000000013764407340012723 5ustar etbemon-1.3.6/.git/objects/aa/63082131613ac3479096ded34822d17422f4000000444000000000000000000000031613764407340017315 0ustar xKj0D)ztB`nӚ1,#ɋh>唶3ɷVEғAqYR™g&v&P^'Ts0dꉦu0gg#\(˽r $Qމ~薭7KG-rrp`vFǥ)[믯3iAetbemon-1.3.6/.git/objects/aa/aadd29e178bf8caad093d2649fcdc7c35f9a4e0000444000000000000000000000044213216421217020515 0ustar x+)JMU06d040075UHIKI-*a.wJu[s0 UY UG%"ʛo9gKWPE9PUl {]nYWhs{^KPHUEnATeJiw6|o%j^^jIAb:u?C޾\Ȇm硋Ͼ1F*,DRv +P ]/?3Cmw?ͽe[;I%JRKnshXf13{Ō7E/≁*JWڵ=ko9bsP68Betbemon-1.3.6/.git/objects/ab/0000755000000000000000000000000013325231224012711 5ustar etbemon-1.3.6/.git/objects/ab/9b316f27e93f974a576d42b9679a0ff895a2330000444000000000000000000000141513325231224017663 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTPv.hMvZh)TIIjnANbI*Cպz SD2d`َϠ}Qxށ+7$vAds2SJm0] )5*DEJjRfb uL׊KdTA~2fZdw;Fvk[bM-Ifrvٞ=6x>3O]Fn~JI}߷fC4eussaӴ$-\!}- (@zYd>7&<[@c Rxe|Xbkiv vQZTP2c9˽-n>]$b QQ\ g=lǴ˖Nx1l BUT# B@}5c (-)f QOX&ZWdxQ}etbemon-1.3.6/.git/objects/ab/e3c578246c0682954ec2241cda773ce5219bda0000444000000000000000000012745113314346054020003 0ustar xܽk[G?EG Nf&;6I8^ugy6:Iپ@+O?Ov2wv<ޣgO|_A0٘OGcfr>'keY?9'p:aTѰ?$jTZ#N+MX4;Yqm}?x98^dڝMBq6̧GȰۺ1MgڝdcFf>_ywz{#( ln><ذ:,ӯ"Ϟj@gzOֲBv; (u,;rt'y/ӸY<ގ?ƣ^w|0Gkut\|)XDٓh_kȴ5d$ f_,I^^7V]w29<y`[)ۤhAl\ZW`z>N+Z86Ї9M!1B6FȞ"Gg}hD03dscZv`ϼ2BD) :]gCXGZx%@xĊ'jP/Z@d ZWPَ.LDz#~U@9H8ҕ8%2Oc}`Kx` 7 ,SpY;'ONYۑyɟ#c'6!IX3ɀ,vL+x) j~T|>EvC6]Ť֊$.e\=D;=dA&$C؍I QxTzuk0=bz Z/1I+$68p ҁ0N9ܣ)kt c)e}-y`0~lkF7i:~#q}Hˌ04sߑ`7!TJ9Pghy)H)1/tl졚 3vм1*͠8p@5 4i$M DqkQXbXHH2=UB+=hmQCe7n|ݣٛh ;Z̈)f2_Uq]?t<{al+MwR|~md٭ +G ُS6XdO%l!i*]R p˿_gmQ@kd4uǽ쫏cz|ݱX)c,++(K  F(jk  ([xW؇iv:Oƭ۟gfn}M=NAɓGy?e6٩7Y4KTAF_G`rCsOT໠2ZW%eCD􃜲={h'@{G3&nT!P gH&319#݁cz-ӻ 37گ\+X< )lp@ji( +0)gxv [fC}~l>{wnߘXQ=< I rNkqghvG"HܐR̃!: ևsqcVoM8 6Qh/#Ǝ2 VZll=Fa5xr~.Uu~uF@[һ98R1o:}zo#jٖ=|cZ 11 U@ْN`wĨ?) Xl⥢#`^M|na؃ԂUg"] l] '$`;$ٕ .V W]SK+F}]nQס5Pk)TȤ(1OgN씋`X{&!M A;<6V9okMj3L Gk*V:1d%M2% aK#Tѩdž(nK[II ]i.a 'TK;S]/;ۊ BM:<7Flc+V-`N%1A*`ݝo7Ͼ=Nk 6 |g8dtW ͱetyv|&oKVC vU_0va)Kg[ !|hE9nxGe }60#D'3=.Ժ_sc$Ŋ!I \ .#)T61CAjaZXRq@G]㏳?w| `[Z)xf4<4(oo}y߶omӿ/ok}wяQ?<{?{y/~şL?|s:^^__wN%Ĵd@lw0aYqѮ|t&B9Sܰ?y)$Rݫ7z* ӉЂƟr:E?tHb[ٗn%SaJ I4vWNWV7ʤTD!p5FST(NMIw+bU[2L =`9kwKZ[4'7>XJ.+ w'btG"H-{vO$͂RZ4j<W #D,*V -_u hE[Ѫ |2;`gwd'77w8^SlZ8pRbVрJ51'Brslc_DYhVb0X)v ^ 婩D` O IBb C(tz NvҮvhun>m!3ψ_BQti5ZX^PeҮ]U#Ғ^xUW ؤsL崇 .c 6 G m}g {d/]*w(/ͷV#c^ԫd87N& qmNR%&#{ַX2ӛEiӼ;X1rƾR[GQo!U'X_ʊx2ۖ)$=Z67XyoݺGM<T8 —fd?f0Y_~93ȴ- 󶕄a?9;܉%8^i/:]𭯤U_x$OC&H^ЬLȸl~wߦޒ=esM\n/Kc2Hd0Л{&\^1&krö]ES'!~{Pa;eI/;\ZY67~OlgGO`泥WfKjҕwY+a?pOE=hUvJ#-ߨO~ ;"*Asd'yXT}O~FkZiDE^_mqɷׂ Br:s/͑-n/dD&ae,v"c a l#Ae x߶k6̨>k+)AǑab:1dנp&byIXćnfrEafwc~jPcwI"z@S_ F /gXU$'PG,AUO994cP +yb8z{GQX$3˙F;qo<6C!m@ y.&(%|bݿj ¸2#q{rXCWh5ՠeϑ &rԂ|?^s:5M,b_<|-)fl!$#xՒ hΠÎVz-cm)xiJ^^@Ylh'4Шyb!]X::[8Zse vLI4TG4ޙi;lih )eKD>QZ}J1] obM7gޒ xRFY%7LzR(AMl-`O4rRXf9hy!Ʌ4N콶Otz"f!H<ēҌbE#bHAe= g:w SDhK 4-L>FsA5dd2V| c+Xkɠ8;ȷ0a.C¯gD):,oZkFILWL>UJU! U^Je!T^R~wkgґrh v-W6mqؔ5;n=J%q{iߖ ^Y;(: h n]g|rL{)J('i\~GEb֮E9rj6q&&†pY浹$E]pmPb^. fXtv/Ï@AYϩvEwJЧ0D4MRCMqBFm gE-K%ZaYji]iP7fd5kGPfr$ۍ~wڞbP_FHaU.ښ:$ |&fQLt6nIHuљYy'_/0'l|X@C5_ +(bjffzFE1ͳ(y<SHAm3ikm5%sU|d&ql27TC\7ɹ$ɦ{]z @,]*{]=sKhX -H|dV.Vڠ*mFKy_:bOUj+|iSYycU z,v2-+ֳd*fF }q4'}j]_di: 2A0" `t/GAZ *Xj**oICFP12Nq(3z.ƣ9H0( ôWbbi'/ܫ*&30T‘kgZP\E?1%U!ғy !Oh>B ÖTL_A;ДšvYnmUɰ̹("o*}٪}hm~p$(R ,L0yuN0NDл<:žفuĚL6lSm+t|¶o=*h[b0x)7mP\XL#uAt!Q꺽~`At'/V  Hij6 =5LƟqtB}q!3|KuFK7hAVeiMg| P$HCQՇ*80DB@AH09Z[b^⟗e\\uV\1_qRSZ^8c8Fs\ 1ߗ?jUQPZCFJhD%")c^1*/5`Wq"[۷9-J# DP’$9K:MMjq⒨ȹJ_X⃮T2[Qa4F3Lqnq%݃* ^ ;Td24Ba[3cT+<ܬm?hLztH`(9 v-EA^X; c? 2=&@8=9dڃd xHG9蟲wS CŨg%Anj(I6G&vBmC;NCR&e-`CMHgV/`UBSN%)+!)tK#Sf3)dwy#jJ]<Z@|Q8qؤZZjpi|6)cf`:,U);h|1jDPcR$=` * ;)7BF1(Z*Z$T^,pX$h ST%ϬmtHJYvDYVKP3:2` ֲ'=G{)wѴi<`S3r2%ߕMʂު/HLLۑ'5&J,4쾲ruŠjKrTJ%8',WxY*qӄWǸȃL3{Wz`$>c)} . vw2\jyE*Y_vn)ͤfҟ4Dp-~!`h Z* I ғqHl$Q Is͢#¹B3+#}WƝ?/tڡo].V>0fBd1 )abJEn !Y(<[*X|Q{c ;f˔lS~=˟>gwģhWzě?Ţq_l-U'L5CpGE>l!ƑߒTf.{R=۹ݲŃ-Z'V9T|[Q@_h0RyU W8(om\s{л=W|]k8[{oM$D8 M&-c@{AW6bď U`A>mϗL ZUMRpLz_ax7ىO889q~kc6Gf(C3bz Bdz wR)d -{múb1( Osm ܀$20 rYr'( cwܾW1fieíIe ,jrˬ \;ѽf EZd̩ƺ ^Su9#j{W -j_^wb7>aqmv/, tvDPQM^J t% Ř^ ʏ?ͭw_ ۡb>?d<ވ͎oucGxxMgyxd)=]&B:&oe31P9jh`Ob&e8B P^־B\v!.s;ycu\ 8]<0!CbQxl;U@2V5C˒SZ;z>oN _^{lQ r5uHŞ Fӑ0{(okb63Hf -&>xh%C2UL JE%`uT,Yɖ dGeg_FcՁ-\޾|5U9v&"ܑ>⿱rŢAԧfFsV4 Ҏx+h:lMGe4"ԍLZI &?~AV>dP ^0D ( uػDf($xiQ$idx&] +AG9Y(F#]BM $gt&xͅͅ M#nԚY(+\[CW#3ԺgҸX>iC`sjAڼ!oG̃AN >@mεf`9B>FkٍF.(#!WϑM? (ɺOza%̦ul3S-G@eNt3*ű\nO涕Y5Y,U\5Z?pDf+X[-[IbQM CyZ7aGoޜM}_wO8$\c36/lT:$|dqu7%ʭSHS8Q3RnHQ>[/L["J(kw#?d۫)lqs(Ѷ:paXtNu6/ ĶYivli@AV?FN+s>Y ;!׋o@_熼~oC[([00!*%\Vr+&')XxJ_?lGY?ѿdw^^߷9}brQ+4aJ/g[FxTڞ{mH*j?$8fB"ѹZŬu9gndTZ,#:qBe[c)I/%B5MD tq;e/Сjq!F,}R*{ev͇n}c)ѧk8N$^jFyҘڽxpi*c+wn%ݫt")|6hXk2h^$a󝫭`6=᳸l<;.\VOOY1*ie@ 4 .v4,ZY6GHE2uʧM_G<88a5V\nsSb<#CAn3ט1yKj=z$?Züc?b9/#j XڡfSAI̲VpcmI7Azd˃B3رk)F Q78SRLu/R,f,]ZJew:iOmx积wU;k9}T"|L^* PRW_˷H58!mmfS7"YkӸXЯFb+>YlT }‰>25 :_oD7q*rPo0u_xAZ @54* '4R*V';HLҨFQ]fAΆ"7~\Mr!Y ;\*g4 Hva qɿFӯѓI3`Ko4ŠFy֨@֘X)"H5 ǫh ۭfO[>޺ͭ#H%xɦ).t% <:yv` RbT&Bj0 ' 01UiŴ΄(q~݌kV^></Ⱥ7JCu~Q.=CUY#Aqw]֯D->Ը@3.X7(-tlJY aLK_ívg(s/ jauM%ͬ5V?.O/g{v\W[\c 0}v Ok?9 tS\[ 9S9{"982h`]]mgfKG,<)}WeFH5rr|-;71_T.^<볰Z um)GajtF? P:S^'*sjO>)ZmFg\gg{z) zv qjn|n0Ֆ m9;OWX7 !S{$Ye~KQ8@-?}U7D._LPVWBT$H֥ ^KETU&? *RtAmEv/]og% @CX(aKYHz{aW"R( L5xada5YFD*Z3~doǠoiOkYԯdWR)s㋭]) {| gYsѧ"g#[kwדG޾N9d\܂$ba{ȇ d&5EC68fe' 菞^v`fOx_D+X_h|ՠ[K=tYNHnI &uΆ!i4X? Ȃtf6IV zsQ3EoT%=\zKJII}`N~j0QVLr!=T}/%O"~LϣgMm7h``xn~s8;}Mxfncx[bGuce}mD ]KkQAg:q48C^M8}UL\kCZEt䚗0a9| EQSoujsٚauu:>1B 6Ág a pq羢(L2 g;pW`HiT)+|9T>$ob(. ֢V[|@w*ʂkǨ0:A |k|Xap%gaQxOk94HM ̼~1:v %r7 յ# ØPWJ m~D],ucڕ ݵGkP?֒7Kv|ώqzixža>#I=f8uŘ&20Zz^Yƀb^3A~#*^'*hMֳtC·W]}zr+ eZ{tj<;ٍBqmS4$)7Hu/ "1~<Tprn ވFilK@>SxbMǣ&8eDD,PCcFDII/&մMɸ.wwTNG*ynޙm{BN(4%H(̺պ —c"=8sQ)AK X\J#ߓBAw޸4d&$nam&7bx^zP)FN/{}E6|5!]{Iic^zjqc"|'f:2bgvF!`BΈ-q~PrɏeD0Ƒ3U>!F<}}Y: Fi'I9/D;P^, K5~&N!EMuuA8a?V̦@i] N.J톜'^#NhSoͅiy֨Aw+ҰĔLu$2  8{dQOy-oE8mJWT|;蚂Htd2'b;JC +$bP(~ސG.v.8d)<?B>&ZMl# 6ud| y'6~նhP[UC>%vEeWlm“,#,{f[#S<04Ȣ,DKݠbL֢yh 7ufh\lBnI-pBΘR?iЖ(lmFQ4xS8rUm!#B*"քWn*WkTI : 1hܛRիGh,W%ڷZ1oYRhu[ޖ} n Rڄp5s(q.1V*X?U'szy=ǧy-{lg?=;yXovϞ?y}\,eT/Z6ugGAk8J=xp&a{w630' 'u"έU*44eV]N < _hx]E˻t)AQz @'tս x1첥 rtAhsFN5(/j;/C V^!#+C7jE<3C5&e?t'Փ9o iسbxZ )]dSʲT ٥lmd 1x-n%eXT˛3f kp)er7)cl}Leե% ZCE0[KaUFײLVP%ƴ0}> TK^1y:I7t y>3cgh#أ_ku o65̗H'!nQDab |.2=y"$ݬrmnj@6t"Ysiֺ*^'rSNWeT5 M53)j4G*GBOƴ! i|R}Ӈte5>P6{@D`D2Tr/QqO9:x F{Mtz|8ǁU\N\|G =W)hVQzr-|ncYw^O1X{%ۍ )| '"EK9]pXq&(^0Q' ON&M;0T?iPR-b3Rl$Ͷ3qkby΋i7߾ +>Dtr#S=a=-`>RNjzJ!w?@ HgeOa&ieƅ-W(KDdxJh7#1 ^Fԋs@SըγS"4& B7Tr !SsWEx\,$YܚSvO`IÈ1*.`֔Ǯ~W8[\8Go \klIZڸ2drmn$td& иL',+!眵 <->!7$m(:PY ߷ iEQB jlrܮ,I o8 Dy9u~!SFXB5;^%Ī͔w+ר?$k-PơulՖzWkA0qe~k/a{t 1RQ <܃"t38=XVb2M,Wr%.D$W1^Kz`R_8gbٰa0d1JۑH X ~pmнVT(Ps<~(+h `E*J33u|Mu֖K3(.qo 鮑SU%k!&+WR>@\zcsT5}=clFy |sx~G$,yQ?Jo "壷ssA4Xӯ *$"/?@_>9~eo6nyɚ 7n屴2;VTȯb}`c+\͚nn*W0#Xn,I`BB{kUf$ Sy258㥧5ysrc%Tcؓ+!O60hvէةf @6K2191EĵĆd ^'̀^D>_5yc)d-# 3٩]]\p\gܜ |n{x0km2BBK$vIN#"B$%mO)jQwdX!%R/POdfAS eN_ #{! E}"Y6 VdH%2$ -DNtm](C BzU  S3sG&]NoiFv* `U j}{g1:I3aޚxBP3YGcN[AkU#1nθuJ$[~BҮ%1Ap95 /*1I*e.@ʝ/*mKU[] 2 4>|R"1=+ƫk [X6I@w5`:;ZAw΍+tEzz%5o.oͣ p {%TI|9sύrr j\F*@^ŅbbGfe1ŜmmvQ UR"ɀ=*ecoE,9g=ߪ3QEVWm+̺vg6jvq )[.'hx64U_5&-$k^zjmv6)X,VZ'<=8NX =B$~ZR5&S$BeDG =>4,~ۆ B`JM5/H+6*] ܆5+VjXD=.k /'!ơ45jJ\{t4 0]-%'3Q#Cqဩ'L̡;I f=>E 3V_,C iA}U)9l)!fQӝj;a*,w!E&(e6A $6-Unjth[t z8t`3s 2~Ԋq')0Xjxj]3W1CXeBy`:i c?x^}dJesEVSnzg<K]~  3ЛuӤ}5Rw]P$_[  seC Zy bavArC%UQ~2n.\h A٢XD!BׄxnLdžFKgj{u[K֖cv̊(d-'6!{6+:Pt&Z*!#nV搥=E瞓qG"V9~ [ #AF&fH!/pv |0̪Yy7o`!4%͈Sw7E:s*釫["-pPҸdWb+i&v9~ |y_Ēx|wycUb R6,Q4K2L҈<09]켗ܻGҕ[w=xQ}zw?iQ+t߱7[ m܀ +!ձQ~=9@}xAn#5!5!Ǯ.6VSw_wٞd\+yl%Kw粍Sq7,80xN. 'NEXV _R[dѲYt]ꧩΓ$l0m[,C,‰ v.FgBr[1 h4"oPLVہbabP:E!)srIf9q O" q+ `FJ]MD8Y˩X ~P+ap 9 &ǽ༌]s&{]eO!7ײgwH'NfE+ P]YQ"G3讥cTKV)OUJiȜV{^ {ieI"yO]7KJcnχ E#y/sI%MYtņrI'д>^zӈņwBw!ye%;>Ű*>}nc+Y*.뵄t7BOʘВzѺ[<8CH^hʖ8NcY 5U&|=L2lCXI/X2wּsLj1B6}]jʠw0h|aeV-G )li "#=yei"F|͎cz׼tkAW쒿V6gDuy~Ks 8uVL?ElAHQFnLoXk+w^83Gm_3bQqET=G*4JvB/MB"<TW ~{ ,vCbSf=N2rُBB̆;sC-ʤw.QW[BŹϯ$DuøDbXKGR),7'ɏ/X_ LvȤ zf63' motpTe᪋ꎴD؊xJ2R'cpfjr"#rfVǍWv'2ߢG2vMg,DZ(ӑ%lHčc`89 Sv!6ep^-}gOu] x nӒOO2ZLEl=/PBy  *uٍ/Jp28+#yb=_un}뻸_"Rd#S_ۻ.^w s?S.8JGDK죚N뜵NJ]BfZ7]1R@|@jA^w J-_HR(؏&Y|ou`aa,k!i\0Ŝ<=5$"(9GѥJjrTElyH /eL9:6ܵӄ,JnNEc$$X,E1;JgSۦ:U{S4NCzל_7 -*]sCh ٟ݅L^b+,"޳.=OFY}8av"4Eʂb) ~ʗHQҝ@ ]ݢ CpXyӃ9?r|3D%gPI܊N@" ArԺlQɅ&tT[ô{si2A1޾202(Zև[1'工==KO|79C|[RUD:Flh|p W[a|auSE8fhr:Hvq)gzUkm=RVZ!Qq 9gĆ8ʠgvaɊ#ù0aE ]{ZhA1jT?dMR$&Y Lj0j'=nv#<)e:0,^X8?d3 !@kt#a1M j8[j[]gҳ;9ԆU)Upv_Z@wC>|4@86%ߪC_]JL&x/sUM f//ՎWL4GQ*z'Ky*ygxr=oH4B7;7\gUOKp4$[G6a.Q"DmťUˀ2`Ztp@I[>̱"*xZ z3^yINq;+o<^?j>J~nq3l#~ %ԠH54daJ ydUg}kw%/!vf,o~DS8xhh1pY(r">:EjOYrU 6fbzpV)2J 8e z,0c!zPػVLk-Bk΅%ڮJ1V|Z_ zS2k8W[Niʼnʎ{3{Bh#V L4PBKVY8hEhISW 7bUY\= HwcRVmHځI1wlk(ƫpq8K\nr{g~~~Ub ,srg텖H梦i@I>KAǮ_rJpf*G_|s04rNA9ѐQ4gDGj92%\捏&},^`PCB3eUNdK-'=L`C9ڋY^Ӣ&/V[L+al~v:Xs\iMqZW+GW]R Jgٗrh>9L'M*\DtP7YrA2W5Z!r{IU |B@nK7w6VrlYl9fP͢1ԝl"]Pe @Kfu9Nڼ^]2`;3_.OqԻ,IloI3P״(*|ie8„(X:KZ2audI=q'X(OrDF΢4ؐvyl˩sI繙{ڄ.2ZװmJW-GF:`9DWhT.ƔMn t X?L/ѾeT%Ԣ?O*>|!_3k 2vIϭIH;x? >QmR 3n•K}}lkrom/MFd(ZPHAS_p ~oUX {v쐜J[M=X(mj-ϋ4H!@)2z%P/Qif$:5yL}gJDڟvdZ2j?f}pE暹/ayjDԙS Oǒ\הj{{+2b ,Fó\AL/5ZlE ˯wB,tSH N6]8( 6Js?C0VM#;) 65S%hHm:1Y~Al |R+ꨠ;$kxS|l3|Oy\=Uļrag1Q! ǙΜbN7? i|\cLII֓n=XX{F_1Ef_hU!+{ rblbI.8)VJ%{$}Mwn̎oYOX5 ;q=qV f+y?lg)= A>wŞ*DoG$1!URhYt,, +1On;I9Dg+~{bxbC'=ѓ5JinL0ޚ B%ƚ_0bxr.Jr~ZԶ]|<9U5lvg=%ttıu0 [jkO@"nVvwb}fm> ^زaZq&In߄#Rs$ז-LT_k'NFf4O<ƗLh/ :`}nĨ[1O'LץŠHdBTaN:Sb0{`(@I٭LoRkd3*GkCq7>N70=;wҟ彳dySnBh0ڃx PJ> )텖n^=cc"R0yZWreSObToX0XS~mDsK*3./ f,rĪZ}]cAdZP>]rU`0^#| P @Z9uZ)yh{)9d]+(Jx }LÞ'P.Fq pÄ1Kk?4W q'g'AQg`o?6:S^veӮͧM8Zax|,nݒ?IG g:US:,3pЄYgVEl1&?H ^Ż.E$B(f܆Ӊ3QbЦDaPqi{~\{[bRX\rO\)ښi7U&Y}.$lڔI~NӒ􃸃"[c­[i>|O>W;ĔB2jz00hI(\ڑ:dr/n^喖a/MUz(v 1hNWwF0:P8Btթ ٢BLy;!XSNf;%+nY|*U0 Z] Bޙu!jYٙ)ٔ52/«27E[zXji$BV&N"vpS|s\wSڠ~Y$ODPxvJ.5KLpZB ʰx0N{,ה<)`ԦR Koc62 o.xA~{u9Z Cxxd-#4J !_V?@M,q(6?K7cZ]1BkYQ[qInMꥍPgò5@QU˺Wɵ˛pMY Qc!NM}saCt4dE ,F>I-0wt_ij|< )!P$ڲwt*PxXs܂Kc3{`.a `d_`>b eIlaUu̻lîR" "Ar|zQ NBCQ ԘE8R&#&A31JQaO?JEҨvqPkX󅸴Y& QX+1 6"t\'y]$b33U0|?_`aKJ- j8,䱍8XԂ3&=q1yc'VJX`YX[ȤYw,[Y~~EsWb܉[|M ηUӛwd[4މ=T'IǧRڵ Um܄*=zZ0~r$šeI[},ӯȚ7oC̏}{ ju> )r a6 hTB*jjQZ_:'E6A` `.QgZH%>Um!!oi2D^1%VEג?p7 Zcj~Qjd=kK0Cb: UVi,Y28 C+ mK23>~Fc(ngJK>Tc 1?Rq fv4p C-.je@F(W9Rm$uāU$|#:B%cCF؛4‘ԪKUX<~;W~\qc"p1g**6 !Sbby"_)F,QW@\F#G#3=4T˅1yY*& EPo, hB(;ˮVZ @9@{v6*{j0,dЀkA+fhua< 3 , 9 F'lj+ [tG^}rFH+%RP KlU;+ȶBO s>DȈR $vu^j6lsoڢ}3Pg˯Q 5Fj¼8xX-ME"EIC9ȍ?|WZ=tZc ~Z9Cq%sxqg+t dRw<;1|̙Gܮ=ѢfwP44V*0t S]7ifx#;!;jˁ]4h+"iØZ-#47]8PZhIO5ЩNٗ.̑:5^׿ý8,s*:FLf`(ǶV+O/KWɉ[r"^I &7Uջ0כ".a'\P0} q]qe]AGDn\D^d z;.(( Eg+UGmaYV'lyYQroοcKzG^l^"1P)D!<~u`9x6AVS zvn'em-2/#%u'C͵Z 6ހzl7m@ɟ~*@:݊hj686Kd}M4V$?t7paB`xM8|>7efqL 2iTkn ;}YFUƋRJ1ǹ-0dływOBgvnSR#/簿$9#߉vuB]T'}yy Y'+L,R<ZPB=iŧV(fU] k^POQ.gd,$R6D~3!#0qɿ'7_ϒ'BD]~$}TAJ.\J8BiұH 2Eف=g&/%c-| y]:dיJNi[^I['C:!;lDL5{}-2Af8,~id}"febY8~ }2f`0kYڣN#>}ʳA0* λ[-uN~+Eh 0d4X0 㯭y"Ak{I>:sNV>Qxic;wL"ϗ4Oh|ւO*e`['dJNO@Jqcӭqg\?u#ͦNxn7Yz.Y.WZk a}(Qa|1f˹45(?~~ZI31rK-b.FO·d9dDs3أf3B_ 0;r#55Yll .U.]K)Mk-_pXj᫶,UL%Pd^T̆>}^^<0(K3-$񻆎6(}؂| hSm8M5oscY0VjpKhp%Q%ZnbqTzldCSW縉=%'ƣgośKۘ:MfW}QgFrq:5ʢYjcO "FfXV"%ki'}o!;I*u(Oc!?;S+=;If1Z=Iq9s:f#s= v)E iB-js)H3+YyMvS\'eL0sK5\.BYo{g` .2eu;Y(53[dbFi^-U8X.h,'N3!Ԇ=RJ04X˰d*6Xk/M1*jnvi,݅8\Q"Roy:e E쓬7RpBccDw],EQ]%Z2^%EcF 6r?KV-CJk® 09ڱ+3%GP޿[m5:B74V[Ub )CQ6`;ˠ/ "?c9=>9w{{ߥh{,N9֦oD} ^-&zR! 9JQV/T/)S;`KϚo!'b'٩F4&^S(EiD9m~LwQK?Ov$@pw<@mQCi/:Wͫ' ngyI^> ߿]:~Cl<3'g${ iM>lSx|v@5MXJ-Dkfqf?W2[ljO?ԍ>1bG^S@\tF<3.I^ dҲ5:g|դl^y'#RO_R.=Z?QnFVd24ri dVxSTb;# 5+S^{WoTqo1[e“dlڡ\k(BM C7M7u祠v٬B.bt ξp?j(s=}9**UʭT@Ih H'1qE 꺏ك ]Ly9x5s+lOm_vE@7eioգ2mjh TLgv:r 7Rr0G z3&|ЯG6.mç:VWΛ&զ%n,ͽBywt+?-}U6Z'D3i5I3("e$Yk\$*!¼]x&J$a=vc߯ZMi嬞Ǣȏ,O ;/Ӟto-<a?IYza^)%;I8ˁO )fbvDx Ei2bL"mCJҧ8_$qvTN\N܄ڀκ1_g˥T3cGgڏ W3#vulb`j8_\R AЂ7Qli#7p- Q烺'b͵U._v'CE\uGdS1+X:P)޽a2Enje_y% >gϻ0l&Ѭn-`!VH^;l`2KMa?ff5jOh`xmYl}~Nʧ>{J)#^ɢ@z^C#odCݻ՗Ag6dwHݎr5tq-rli2}h6>5x$ur-9%~c Cߏ@a1Wg_di]*.9O!-+ټD{,LrRvFzq=ڦiP5-> ";wBNfH}EyN,K̓J8*s@@ +N_|Mc3^d]0bx*F{=-4wmn,F G4tFuXYи;ch}06)Zr{OiXSFor"U_nbqv:eyk;b]: yB+O(83DTnkwS]G>`;07t٨}ïgv1^#CN(ҘMh}(߱k78~bZBAzu}U|h:cd/ β% µt?_ܜJrpLy ]XgF@xa\ć`PQ*k A>IQyh2ۍAcUWOAbn`Uaos cElf j,0I88l#Bϲ4L0LJV<^<{*ݗe+9NuW">Iє\}mWSK3>{*7bmo.;Q5g.;EʒɊFd1ޙ*+k4Lk-2boK l8BܧiKF\X(kF|#7a7:b _(AEh.2^OG\?bSF72v-|#d4u&aUu-̅Oŕh#m+e\~//brr X<%LmHHJģmCi2Yp5>PI^F}}n*z:; d܈tymPP][ џ*W}#o[eyY ""z 1 }R%EKx(*DA!HȤA%>-Ī Ȏ_k*dvѵwKԀ]51r DGNf]+ALU4S!~ٝ vB !Ϗ Ug݁!frTo?koN JfpzJDҔߒ5&7^l0#'mS[{1Fڧ̷^ݺ׭ޣ[:HtCzkՆm>nHHI|X$+zqfO[d*wkC+DNb=72CHC]o1V9RsKC`En@3ל.4L;΁N{d6 V;J HׯfL 9[X/$Sr+˘kW` D3}=8B޷$ToV(-IRw "&$HSȫʖ%KGm"3LDE+S^g=X +` #>#z_enP[}vѳ7, ($$+GaoI ƾst21~DOvJ 'Vc^pSZIl{q>۽ٶtQ[Alw+ ηS,vF dq~%bj{aqŬ>8PmR{S@Ky pf1qVK:BXǩOʱu]q'3;=[ϔh̫6SͶ)(7 oȳǘѠAMCrlXZOΤjΏ |ԎNɑ+s)"RT;^a  U},BƟj͛G kfoWwN@πog]l]UD5l '8.kA:C;5R,Ž+n5sWLsh*:)Sńjʮc!+ZB#lH 3ee^KBdqݙ~5:%q5*L5v2ܿ+ȗ=Нq l{[ϷmNV;Yh eySyVޜS}_ I{/o߹}tZrl},3Ph6:*Ť"dLJ/[X%F)w :puԩƝzԍm'|e=ypV'?V B`@vwxvbu0;-(Ek2^IU՚*5ϣ]d hRTk|RƧ_ e0r!pX+b S,nqTzk1fFJ?GhTo)cRwfXìKl†5DǶ67&@kHB1K:qaSn0ݭOX>ibD"Lu:;Uтvط~BYuA7}7j 6kIG9YvIJuo{S!Z>D)]EGGkd^3ps iO8\Ÿ-[Aoyb ;PC?V2KcӠՐXM:rC9_߈Mn\\z+Rm;0F`ΏsyY)t3GXyXt4h]ό¤?ʇjFDvLx> ]E:Rpf?%Fmp0)KGP S:z3NL w{)aüYFuzp8)uŶSˉ\ `qsP0`:|+PLF4K{`=%` ug[.녱zX=?CXF X~%G-vhncKSylv%hHS1Br3zNHXvjd˜s_E1ۑ30%--t; T WQVdio1]bm+>"&]Mޱ:G-Z/Iח) 7*NiU^vX1AnL?GrO3ރ1(:pu`X3dhJ~mc] Io.8yqQ?P9KrE ;Bx132E6 /ж:a h꺱c7bk&E0Fæ喢h?*\^ZR[ ᕢA#Q=͛d~՚c9ݝK(:gÖ(pXo2}!wƝYzG'+D]wa‘6Ǻm-:mX>>ӑb;fHϧVCW\V8So> !}4̈i7=j$\i&<]@J/q|D+٘zʰd Kb+FUxL4Ndj~7 $[a?2>5Xxë__o׿՚BXߚvj ~!Q|8Y=SM)z$7/~ A{`2֜0xs/==De2\kT+7LɧE4u2;c")0[3Q "d{@lq6A"̥y(Yx0V{8ɾhޫm܈Nţ=`d0 ['[Y_ CqCRT gTz_?W]/솲k 0ױe)IʾAȅU/D*y7D"1bqLz٨~p:Alvx0}G) P_`-d&UV'9Io_lbw.3) r1j(z5Eg(& VrtY(o0pU'-H삸y%P+?ߝC]9ޣLJsPO0lc-zrpM[Jo*`j<ZZ~\鿗o_W~ϕ?[9P7#d ,zÕCzV99 a5G+z?NjUhjnḘ4NiRg+g L~o~#!=;5.m#E5U (MUzNLzF. Ah!}Ř̿zz0% (Աj ]ʅW٠㕫hC \ &쎉S AUI蟟2g,'Wdp=}9g3T3a8i}g2Rb <ft!b  ,tGszY)Z0Y6R#I We-@?m|DBt`/h fMby9V]ډIZIN4I) VB"PS둠{R;̐ bal/ ؗsɞRމx)B/^Y S:*BJ$'6>c5_᠀?֎qȨp8=Lq5Ge2sGč08;R"?4SqH=5fo^#q\0ANʱJ1kmX0K  o9`D ;VeC BuuV_8%_ٷv2N;fx݃*'֗AA@StaEVF<*QxօYcmP :

Qws#EK_38<4!˕vѥ?Q+ށ>oTZZv K}KմZ.>t{o` F#4i%9Qe@ c+$@?̷v ze H]{-hΩRUy 'aBk1pG>L}ZЧo[|]O[tZ s)n[O/6 <(r(V%3ÙJ8d#hj7Jueσ"#Ģ#Kï:=sM3HE C~T͟': 9J|!uoHHLtʒ":;vHY;_:^DUJiҨ7n B'g&Zl.m+Eb/C|qəB翼Zm !hݧp 4etbemon-1.3.6/.git/objects/ac/0000755000000000000000000000000013216421171012713 5ustar etbemon-1.3.6/.git/objects/ac/3ea8a884d7211c709301df2f7c3ccf088be1b30000444000000000000000000000004713216421171020120 0ustar xKOR06cHQ<<D@R etbemon-1.3.6/.git/objects/ac/4dd3d905bf24816faa5f1eb59f0430e72dc9cc0000444000000000000000000001325613212011530020260 0ustar x[Wɶl˜h>3APp|pUdp,eXNt o?߷wUwϹ: I=vjo4K(nOtdKK'g#ʓyl~fIf<3Il"IOd28g43,4:b44KIpa`2p01yZ~>x$P9iɸa( hz0ZP7:.U=Gv˒87ݖeڝ;^^_&nihi2&Oy0سx L'8!Ɔi7fuU?2i403 ˝$qLp[]D Ib_R{8&HQc0 @0|>o&0(!pz i:*$[VrqD DS5" wq @dS[n>yةB:Hm/3M>A ppj.*@6a-Ӓ- (vVl]_ D|*fƹ S~aRt [a0HA>783&o=Z!R_[-Db  ? We2=OAiԟ@*ڀ9N/1pJCTBy}`^q#3#w̄#ىd+*p%: #,(VK~_Y8f 9o|| S>H .zlTq, ѕ(ĐIO*~*H\e23ZI`A% LUBSx\ʔ (4ʞyg'9W?'11WJ67- )~CRgo`iƣ\Ylkhԛ`$8f&PjUQэ*5Qb[c4q(S%>-fnH^~?f^f;1ʩFzūAp'?g[69e%@ .?FVʲe`P'P(4lfST2ed׹=FyMLǧ2D+DdQ3"cBV[ UX^U Q8"TP9iT AaCd1әDYc( "39-. ϤYݲOd~,wbs3m~ K>ioirjޯ#*^zQ t9SF5nhVFhCѐD+5]D7)bpCTdET2]_4oGGG`' [g1ԡbp3@ܾU[Od.`?5/`hۭԁWT~CN`"(G@Nu3QUA~6 ~pmU4MB:̼"X8ON б~AblŔ*HAI pB:{ G| 8#\(RfR18}iqlqpWF#ypʳjeU[^dɁA(yD=zfc -;^N6Τtno ɉJ+93vY g/GhMIsӜ ׷vXK/~Y):r]lYd)JmjjtSQLѬGe8\SS+TI0^ jЛڳ~ןաB5j"Q*`s`>j;xymR -/pKC39fmf&ڄꟷ 2Wra1ur)zhBqYVއQo jr0j=C#5᲌G??~LA0ؖ'<,;jL:+5 77h8 &V#RcG51b6ehFDP \G_@ *j9r_I% d~pLG{8W&ZHUʼ.Z?D>ʾymޛ예"_ݗucҬ~̶VP*m$v0`ōX&mDNxlWqQdHgx`Ut[;tɀ;kɣ!1pMm&q( %phփJZY1oB:$Ji* ^JraR4ۋb]*{mJ3 Pm9ݏ1`lI)Cc"SoW3jLd%AwFN.*o6&s3Y%.P ت(1ݱ#gVuru|T蜹M]gGr M%W܌cSH.[Vqj* ,z3%Y=/&:ai#6M|}B v] +Tìk紁%K0Z2h1\}Ծ8Q8X/) +W{e',@Y2i LA"eR).g1bqI>%{liB?+ɔhU58y`Li0B +zQp$ x,yC; ,r~.}JD1o}(C%qh|fdW"$^M@E=SH!赡ؖ0G 4ica<QGʡg0Mmxe~A^LB*-5"PpF:xj_ҷ{^YWonshV}6 hɅ [rO53CQmcD RO3d3oPJ>KKw3'v>C )7jxK!#GגVܝYId)cshإ6'g<"uRbPƀc4jH9ςӉAWokB/I@י+A1Џ:,/TV+@[?2l,/q]\D%&Tng^m43jbᗘ],aL4 _re<#s+Q*y5 &yQ>FxADp9LftfV QNuV"56q#$^!W^2PuyT]ԽdQ%8HO3^ϓE3Y#GrM'WLW(*M)ݷ5s|\0DFЈ^gr}@8|}mJsJ "KTQZp>JY5/ $?5]}v nݾH6D.y ̶\8). h1Fz*Γ NDNqv eUmY%Cՙ' Oetbemon-1.3.6/.git/objects/ae/0000755000000000000000000000000013212011615012707 5ustar etbemon-1.3.6/.git/objects/ae/3da47b3e52c67d29a387d358a6ecb2f111e2e70000444000000000000000000000126713212007675020141 0ustar x+)JMU073`040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35ݢ{%\\q7tW)Iy uj^&ϛ2<Y< btm#W M-If8q-]+N9W]~qq{ ȷ 1tOݟ6]۷Y qL}Q3,XQ ,d^~'XڹjڹŸfV00Xroi[Gr6 CTh1_ⲥq 9y۵%9 ÿ=!ɜ$Y 2,etbemon-1.3.6/.git/objects/ae/6ad3687a98173e4a268a8471f433d61fe436230000444000000000000000000000035213212007740017562 0ustar xmM S̺RAhC2@I~@:)gi:_uKRS-~L5=2t0F,f&Ԅ'?̷ HqR epi/} |GJ Ԩ!䞛N=؀N%{՝(k~('75)H\Yr4k7T7UpĒrG0wrۗe†hnnl:2ǽydw{VBSq y*etbemon-1.3.6/.git/objects/ae/b5ad029a7d9d3414c1a03dc166fcce9d2954230000444000000000000000000001332613212011615020113 0ustar x\sǕ_ C 㘗IK-bx$P*3@4V^8(ڹj]nvdsQ9 Ac,ϒ$wQtއp4hgkkgAiE $8YOlV.Y8}"rՏ2] {iJ dĒ(v$aҍz<atwT~(y3Izdzk14vue ,s$]utxȋ&%`B a ?tB]In>78|<4k8bwFVivOq6UhҶcv|g#DԤ$7cI峋g3rRkab=ŒڌAAhCe ^ 6O`|bB:xO(Rad8U2dp6}Iሁ#l@ ZyOwaÃk U3針\#نA74<SP~ 2hH+״׸ P'5TS @5 3A7` 1 2 3x^ U%,# tstKC,wѹ',+G@Z~AdF%%qCeOOOQ:D\ ~<_ rP,oV)UU{japZ *N`P9S'2" 27|B"siPof`s3N @ptԅ+F S},-dH98iչ  \^Bu^1Q3&f(Rzpp4 :D) G-C罵||ÝOLhPR(F`y&/ݳqfʈ0;CDj$P<^ Qځބi|Kd+'@;H5hS4)[!PeT*}C?t!7el*mٲ$ d錑tկo7P2MrzhI&d2V'w<T[!9PB=Y;1282-'(]t |Fmm0e(.,?~Ū~rt/]RnxpPF3 ڴ^t7NȂ8lDe0Ӭ]fyWrJ GF#4;*8K뾫:Fy OiQ;s4(VI.dcp41pA# p@JAtyM-N sDݗ(Um //任? DYE%9JPY}a`h aTӞ w! 3uik2rTcu:K)E"RjհϊCAm1Wyb?K81p[6J,q| S.̗/w8_"Z L+1xQo;h@yB enҚ~9!H2 YqNGE"|j,}+;(3P—«>ptk`IzdI6Ve2gV7Jɼ[Uv:6j!C1Suq *}M(_sd֪Dq)v}N- ,5kTMYiciYΒ{L.ԂzlJ\Q*}50ƪ{lRduf%z)A8"P" #241>;s)ÒiS5񹆖{N+MznEW}c YF!~|5Az ̴.6@X⏷Es^?ׂMmw{`!A݄)ph]~f]37ޞ"\p:WڴvӸal)O*l|F9{1> f6 ܀WMýܼbdI79voS\3oe0{Q4Ze-Y2nvaB!2tJXo6\g#DFۖz]cABw*3S ϒ"ނ^@q'`aEG._&%{Rn^гR`QʾD 欆'&a4d2#ڀ~|ٕbQy;BƺM;J(h|l/9|10ڐ&֌Ixh0( S>k5hPZV臠U4"ZT[x덅K uyUc8}7!n^IŮTG˺x ]qp:Qp<q;R?jP $55`thW@3$ݚ_LEnmюaXJey~YIkq2C  HY?ㆋJ@>Tks9{i;͙F-uaK F$x amNK'Wa}}aT* ˢ +A7eJ7;CLqZK?Ut..Y?>vZW\c(`ziN|47bjlq!lf߂?A mʢdY%m5N렵btY#-˴gkdN+B]9nsV n&+[YS(R}2I =֚ u}P*0!Ly"\Z)wghk&1dE5$!a`@Q&׋D篿;g ikTwC5MՎ/2+2AT :4EZ}NO RճXU,eJ 9 n*nk%m#f߯5;ڕ;Ek8· 2[mAyr9(o| CurtTyH~(pzSU'HU #& 4-uW6uE._A` EIx21'!4%U|Z¿8w)O =0 e#`9*o U&~+ndGº Cދn-7շsZUti犠4W3qDbd)^yl֝d-J0ŋf߇PLBw][ӴئФ!4Z㴋+Rݍǔ,V}o5J ="9QZE#.J7u~afh eŒpe:Gy®$j*:hjQi4w&k#5LQ5zSOE [<Ή4ssn>&t-H*a}<wE73-[>7lip S,@7N |)(d<=[t K%]u\eZ Q:﯐xmM.7|/I5W4Bce&vz/eE@//x}KoUe?>1~i̖7@ffQz1.W.S1dM]Qan 7Wx^62kMթ{l,#FK FX-pvطw{Q}< pup?\PCUZ ʵxP2~o>>NLWY!$R3m(3kf]>5p~܄fgN^3yjV=ߣrQ:NGHImVsO?c*eeYYƏo.hlA 47?Y:]p}UZWYzҗDk.lT4=2zX-,JdkHlkF*}%L=œX[Ol˼#=͑?i[ ;jyⰥ TMlfd5ɘ 8rlVQ_i^|Cckjg _nkwUsNZ*<LH5.Y#kM$²Hy.9A,Z΅1{ ܓ&zw=̵Cb]7-Ƭ}^iۭQetbemon-1.3.6/.git/objects/af/0000755000000000000000000000000014170644171012725 5ustar etbemon-1.3.6/.git/objects/af/5eadcda580c3952bdc4c9767f8ca94c265af900000444000000000000000000002550613604600005020310 0ustar x}vF%{dGq2-'qƲ=ݙ^kh@ %+}yb}{WŒ^ӗD" ]KmtdSTy0GAhygfȋpDbVU}?&j?ܜN&33eiߧ y%QMy\F4GIdvoEEdݜe s3²;3U^Eǘ,]"JL-ӬM1 >a'o`g>[fڃk inZ#[hϫش|s̠ك1lMjvfo=J6E::_nD pbssZZZ$gGb-*& a5Y8QcUg{z[;5^܄I 8 ;<9zn$3a0V/™<^hDN>Z 0H)DTDI[I g}hk496APmJ ڶofd lz4 җPsspqH!XfMrӄ *1J$ lNf {$%Hל䔹@An4ljK>/=ו9&TqsBk*o9wJGa6AG0sb89 46:_ZmG ؇+D|pA+aNbc qd"G&hMn1_ώ+}u~_ 1]RyI2UCw QJQ"_2L$mFэGQq@N$аAϏe&p,SL?V=0l3No <(&@49SLl5* N(ʄ$dI8"Ni|s ~ *:>7#&Q6r\|+< .x.U8+lF5}7]ȧHLNaIgi?t fQ$. 4bIG" ?6r Ў&SeAh: d'*So#]w91H'4aC?ypd88/!A"}t{\bTD*zckuxl-`%el2q?\X,\_bilLOХ(tZ@N) J .\SNE>9"=UA15{[^Syͧ63gu{F2Q/ˠ X7"U ɦAt.V%Dx &JG>ƛj~sgP1p z;Je~+)'r!pUW]?6ax$]Ǐ(NjЉR# 4rTǺNn'_BB.%!#hf$.+}08DX9&h=V2^zÎj 뀘wa .6Ys"]46'E4-;!iԗN/G Od }m !r7]D. a4YF<^L+Xҁ,>|o[*TP Ve7z'0 |pAX0[;DZF,3<,gVIq~E4Vo*WI˄hk>bzUx-q\ h9N5XPWf_M5b/ӗBC,xn㌓ &B-4LNos6q)?4;(\("a@6x/xjy 6-SjpE;q1veT&ӏ3zj}<6Nb~@by|.U0/`J6݈WD~|)06Z ZtО3t )`MU\$jZL``gb)2CೌᏈvtqrHz<'ZU/}){4>6~p¶(rEߪ0w:,թxYTΛƱ2 ^g 49SF %6/ot a)x[w3 /Ȯp0!îq94!g^K[0ޟm>{j59 (3DћjU GFhU[t)FH+W fnPOkr ߞimnm(3p$-=?jG$WgHl~G|0wmʔW u@>2)6zi»m5E,U 9 痠 ʥx~XcNsΆmz_iz:iL2$g&=nyDԩu^MoH\/5rd]<)aaݭo^h\,MqTǖ8tNL{1Quvg+͂e!4 fWZZ>u{2ܓr03L(,HR!a-eBꐛF?OQ9_E3g) zj߁)N-hVqC&A s~N%G;}jvS N<K!jǿ:VN;ABJ tbFKe7pa1&w̡?Q9oIomHO5tz%9wNB>b)1z# Nϫ5e95Qu(`x$m~YX NU%Ft<4ꖒ D| ?bPHeZص;),Q+ZD(*KYΐpLty%Ȋ17A(;90R2s ' yg:m.zAd&Jo}i|>JQ" ;I5\?hO1#&vldH|؝M D&',P=Pd~7L n|rF}ˆB55ᰅgⲨ:a8I&ЧW^ 'p%X vW,H738VP_`(^0G%H"RfnE0Ó'D!'!Due/VSEIzvKW6 n({ C@9/Pjpi͑Ϡ VlAW:jK-=b Ώzl?L)J]\³#ɂ3O:ns|VGb珑:Me,#PؔYKP`ꞇLϤ< ?ղ BmͰ=16.[i(ށ7vFK!]+%3'Vٵ2c"MFiyRD#Vbn.Y8X{c eAwfN!x "ęC{VKaW3ﴦWC68SQv%ۺ( :(rDwH'ϝ Hrvnxy%RR PrI!2dhxdצxNOڃnkװ󝭫;[tR _SI}[:fm Sv#n]Ĭ*~iKv9x""^;8X QYf^ZN ll^\*]*x4V-Us<zT」uPn}/KqVøsU\">B'f.=à«0z5:ZREGo=փw),Ċ6s z89C 8*o8ȂKyO`vJEZd'r}v 6sG5iw9=x [JRֿJx[9H!#D"wX0у8ʣDB2?:' Wx..nd]O.J~!Qr,…a%j@Y XY#M橦v.Q(ؑ7R A5o>$rG\}Q*>wQmFhECCѺ- w|I& ֣fI*;`@2=Ӡ<<3Bm@V:LH=u J=Rƍ*;Lقj9jHé9OSUdp<.jc]C"Ct෸׳K ZgI\[kQ!FgY6dɱa =P[7_`T^+$;4K-*a*wk5mX$Tyջ7gE9(Ut\f-n\9:; YAP"\Օ츄kQS bzoB#4o\0WrB<BnoBbdRo`SX k4kzA&z8.mYy/"\ vŒ2'Q>-CkE*r7Vh^nJ!i,\Ah6]Z|P 7di\w|5Zy:V" _NQ?H58; XǤ(By  26%Ş|n6]dUt`b|,CȞ/ ߸xJ'9-ˈxQ濸R 1i赡z6YNC-5q멭촡Ԫ 6iqbhk[aaA$%r"iQѰƖ *_QZ 9B67Xp\A*]]I᧏?ЪUK*6ŠV %Pg=eD\ЦN˛zМWT0 Nuʼ, zbAvuɺra,;UpMMyܑeheD!Ζz_l2^qce&D6qVs'5B> F` }sJ/NmtD998 {`bOa<^]!gSo }DT~+/[e;kRöв%̛e/zL^0-(|i ۸Gy`-J]j{jz=!2"lw|@JА[l<,@[sItl8&KӼ"j%@*]%.HXmY"/c ULqQ@D]S}uoY (c5nP&m,{~"Q,C.W4 # md;T+S ִ\He]pD?|FyN$NG J!8_p EOdt 0s))kW"5UlER <* 2c\1ӧǝQ5b(~K5zEkAO:w/޾;4Rzt2y?ȵ7臐 j1>:|Ґό!K1Z l.!>,C38G% @#cP"lVĨGp]N+\e V5ER]WkhʵNEs„.] ЃRB0Gf=+o'_K~3H# Q[s{JUW q^efCm] |ѥ\;dC*`DY<իt|lak_ؓ~ӈ24L\bihVw-֤wCkn''Nlu-`<́a8B.Ѳ"L~8.6|)-⢱J^&ӽicC'h~Ӡ_F).4JUI 4e8dbE#FEh rA+>;Ts1<(W.Qa* AiW4o //{+abuy eOFҮ-e$7'p# 5XC^A1lܙSr?hrtSI*&ks(B{󓻙fu&CM4[ߩc[@Cic/l3bKVZw3 'P`e ݲmM|u a6XY (2c!a.al`-]pTa {3ಗ`(iPu˭T߀}e G_]IdhU4cG ^N]ZQF*)L4@eXz7v2+\e:3u'>0TZ֧֕9vs r?|#hӋn|C ;䠯w6+,YSF)az,KW6Ol`>3*hD86 ~V,4EʌMJzŎ͹K~O)42ql}辷Sٖ5CJ䂍jjK4~C)zR$)'E᰻$䪗AQZ)zKcaNҵgoV̶Ymg1>Dޜtڕa.T]ӊ 4Fk+,O@`pQ%P<2O?\#M"m$:idaR@(<ߙճ:~9nwZ?vLyZ4FnUxv!8op[̤bnrYiK5.6DM߶/I!D[wt=]:$;⃱ z{Xe ˙y) IefhJ\F]DPE jP(MXr®鱖W<:"A-\DY]ީAg(itnk%~ZAWDtF`ҁww)'h? R n>UbG(*^2' *4^כuU:Ё0*Y?qWg.&Z&RNL21P{+"Wڈ617':ϭ2vFLZɀ}oK~_ڋ?cg(␍{lFq[BjKa*9F*5:beTR4GR6++Fajfd3 X%>%nJ(A%(AU"9aTCO?~6Нf~~2 N?vG'}r=Hˮ17 }'%#>X Pٲ)5Z'@u3I4K㇨}iM!=U4"ÿqYr}ao+a H /oH{G+qxtƊ:ƁW>Jbw튨:r_G9X-؎Mll{߅o߫†(ѣ etbemon-1.3.6/.git/objects/af/8dadbc925d1da783c987ac4ca1e439ad122c120000444000000000000000000000136713212006701020256 0ustar x+)JMU40f040031Qs fi^5W~>wu`~V-:֖0E% [Y'./1Cǡئpy%E9 ,65j1ͨR(3=An2+v38C4ͯlP*JO.f(p~(eSdm_tRK +9LWˇ`Uƙ*sRRKsJ">(OȵJ/ krXN +,*fzy`nMBqY57%YUQ*ذ*)UUF5AE*f7/~92Y{6;&-R o LFpWcn_VX^-hBQ)(8;6`GA\[ͷٗ>u>6:d L=wPOJtM#}h1etbemon-1.3.6/.git/objects/af/9c364c7653ccf3cceff1170bc582cff083f4660000444000000000000000000000130113212007641020213 0ustar x+)JMU01d040031Qs fi^5W~>wu`~V-:֖0E% [Y'./1Cǡئpy%E9 Nz/\Uƨ`)Vʢ˄,Ҩ7A (7?O/%5-4bEΛ3]Ya_~̢bORY)'4|^2d5 i6 /J,wAq5Ԋ܂b+WMx'N̽H22KRR.H w;^DQU\`r,sV7>FR]̰akXHlb9[׮UERT_\W\°Gcx#&:.\ӧt6\x6,ȪRUI2 *R1y-Qͪܫ1Am_Nj/}gb  - ~U>|k彌Ƙ*7_Zg qnh9oε|:o}SgcCA0̴.sq> nH4"TOetbemon-1.3.6/.git/objects/af/b397874d142a1a292b1d636c00e385faeaf7060000444000000000000000000000120514170644171017764 0ustar x+)JMU07d040031Qs fi^5W~o^g!sTe@*jmwLP[WӥK*hM*Yd-Q;pM7 P6knfSC$PVjMybIrL=wPOJtM#k*Yetbemon-1.3.6/.git/objects/af/bc4bedb72afbd15edab985d43f79526ec7a31f0000444000000000000000000000136613455620411020523 0ustar x+)JMU0400ef&& ~zyz =k[7\ RZB:%3]Y-Rj[/4*Ǡ^̹9>H^yUeFfDO[,$faueP$6U}%O&93g̒b75Lcg_r8J .>]w|h˹Q5$g3\l^6)<[$Y(لܣh Ks}#.pZJS/AVTEp̰͹k{¦~675UFCq^nAJfqvqAbr*\_l266}Zk%uؖ.bUϵZo9h:JR&z{?ţC)S§yEєV͖S@cק:(!pg㋜]V9I{Tu@g&&3cXW׹ۜߧ+wjss ֵ\cw&P%%E%+(a:iWJ;RRobUW.8 5mf,8o'o{ J ,4n8)KB&|=CЀOݨd3&v BMZbfNiQj1PaBG:X|~$e? Ba1s@E3~l}M9g[W0~etbemon-1.3.6/.git/objects/af/d109077cd1c1693a91748ec8230d493c769b5f0000444000000000000000000000060713767516617017675 0ustar x+)JMU04`040031QMNMIe8;?nN|:/wrq7jMMJҊr2KĿ2sIt#A KII-IMM,(HMK.(`uy&؟jRtW8t&0lK׹KVz|%u3Ҁ>).HLNpЯxQĻlNg: 8'3B$5z*nM|"zGx̴SXW*BWKYhh] Z*-@ ӷ+dr9{lڤPUŹE%%90k>/yvg޵_ӐVR CG? ^Ou;PU}8*1=`P8URRtj!ӳİetbemon-1.3.6/.git/objects/af/f6e1474a8b858b286c88df24ebf269563e17890000444000000000000000000000243113513716435017770 0ustar xVn8g}TUZ;-'.6vcH@<,֐e:&D*Rd׀,q8<3sf8"gap!eUJҥ|:/drS{NyF*.eIE>ˬ%uH "]eDz-W"Sy|*⮔WkMR"I )JpO94.˰`;\0"ѕ|Eit+jӬ^G(#Qy9R*Ѵ?rcdU FwkQl2JD3'"iDJKJlY`~@?f(w{"락rl@~dV4|S^R({:HezGH+eG(ꀦvPgzzL(sK~k3p0J P{ZkrvTDNߟzA׀\wA3{(hCSS]UVpxML"uXelwf)&`ǐ~$u z7k{S}f]yZ05N5 u‘ nЋDqtۦpĪM;1=3L1z֐ξ4u~ocMV8W=o*5w[#Pn67 M9 ‡B$J46z=uϹEFQ==pE9\od1a ֝[Sbf*;Ǚ~sUÐme~)n2tʮ3MX>ڞB̍庘tEo ?ڝ1Hn,&:&Gہƒri#&W=Ẕ>f: q>5Fs|Rfԍ:Y@Kqbmh5=<̎q^۵=?KIǓ ΣEV+q;`\1k}^.urA=…C=ᬈu\TA X~ KgfFzzqx.u4JҵL|x| أeA*eIEɢ!u %]ɄZPDZTN!4m-WkMR"0MqePUT.o2hOErIyr#f׬^' Qe݇X&MhkNk&h?=LiY Й'4+QCI7kedZ[ (+Q.|x~ѧܡBⅸ&˾Tִ4)kPD"[HD:N( 'ݙ\t&eQY8,1-/v`Zf8("eZ㕡Xqx0 e|W4ApE[/$X)oƳ8b2I.XpF.Sk"]y5-D^ě`+NS4c H t-h\ CNZ3s@N!"Yb ڔ!\XXU]65(;3zO:v6a) \N8G(d0r<6*"Jwst4QLcKg~FvvOۜ1t ["/ X庒p,~_mP(*{|Y2u<<ٍ 7 )1; o7wzrI|waǟeM%@ ̜ΡNYuM+.df q[Ȏ_f]5}'|5U}p!ė&zxG{Xh0D*π> ya(@SkJf drU1l֗|vP5%TOe/-42VoAm্o7nHdFJm5v9YTU*\av2lކSlWfilfAlgl~yn%Ѵmޢ-Q|o~wZXqowfioz+y[\!-qtQr"^SÏf5DZTwew_Jaٚd>53!pqm;ҡZ\ Rm 7W.t3Auˣ6K;yLCEy`fVY{qعA[8b#/jbW|W^Es];Ӡ8IMjEbnANj1I+&?<ߓHH ge$0ш&ٞ;Yiڿ%͹.fX5X,AZ6蜭k*")*/._^5?}\x6,ȪRUI2 *R1y-Qͪܫ1Am_Nj/}TdnjPT g] P6knfSC$PVjMybIrL=wPOJtM#(etbemon-1.3.6/.git/objects/b0/bfd9289f24b37209e22a8d0bdd73c75869cc880000444000000000000000000000120713604577005020023 0ustar x+)JMU07d040031Qs fi^5W~/jbW|W^Es];Ӡ8IMjEbnANj1I+&?<ߓHH ge$0+Q0h7'ő.fX5X,AZ6蜭k*")*/._^5?}\x6,ȪRUI2 *R1y-Qͪܫ1Am_Nj/}TdnjPT I [7f,vF5L @ڬsRMzm^&pC[f5% 3aOB=u[*=5;K*etbemon-1.3.6/.git/objects/b1/0000755000000000000000000000000014173224277012645 5ustar etbemon-1.3.6/.git/objects/b1/1b74f1eaea0d7b115293183102a8c266fe8cdc0000444000000000000000000000067314173224277020044 0ustar x+)JMU057d040031QMNMIe8;?nN|:/wrq7jMMJҊr2KĿ2sIt#A KII-IMM,(HMK.(`uy&؟jRtW8t&0j=R-77- T= ZEK|{3 tKRs Ju:nh46H:12;Js2J+PU?]ŭRD}3`Sg]ut],͆gfGq/P0|ȝ(mgܧNSg*N;nL@c17޳u0E%%9p̜*s;M9ݛ0i%EHaPaS`m^TUU'+^BmSS%%uN׫i2|Q1= Tetbemon-1.3.6/.git/objects/b2/0000755000000000000000000000000014032545161012636 5ustar etbemon-1.3.6/.git/objects/b2/3b68c0eb6dbcd4474715e61229a26003c374ca0000444000000000000000000000141514032545161017671 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3B(GaVvqlrNfj^I1ó k_>v 1ٻ&_HIMLcX\y(%\P^>jE?=Mv굫8dqke: z>U)r:`|>@% .3rVܵMB.%pvLl鄧oCNlq^v`/TEe10>R: ., dZ6nr k>Ewl#"ܬsu50D0 `!QQΫ^z8CDT]Tp%@O p7s 0Xsy'$ɲ+C4*4^SKi=t}&F+6&AP"c*%;1(` SMKrdPΦ0{ދi͵0Wϥ 0"ZF<-x>-u]XEL az{G=7 rk&%OOBC=F~vsL%W/()kI\AI[yK@Jmfp1E1d/U9Y k_7g겊jw 뉜-ﴭf l'3oՓ9%җ6GkΙ8!DRx } Yf3F 窄I/X2mSH8LLae=' kn ;Tp\ɐ,?NQ&cje Kj.e֫]F;*0jHK:p1Ǹ2oa!@8C&cz]xNvYX3ń\k9[VQn{p8peksYtW] $f`FMw䪰b/TdjsɂaKQ.D{0`ę凇Q\1_p( B5OXÆa[,h>E.OgeG^̙wjKoRyGw^ ?S`rJǺ:W&X0w#CBבJQ+nevϓ쭶}D@"k /-Xָa19G $"ZƜFFvA`jHӊcVB+1?1 Fx7w~§_ýTYw"@-L ӧFs3Ŕx8,`\bYw睮մS$bI@~,[ϣhwL(@<,CPr<cֽ׸6+:138|%3 <0fW)m.M!T:c;p@|Um.1J).g.PW BH,Mt><"n5z]GHT5=z NջmB4̦G6Inp$:$%ᠸwSvP#MG{ kHd X(Ӈߙv} m#-,`etbemon-1.3.6/.git/objects/b2/97aebc16e009b973d32d0051b7daa26e1f612b0000444000000000000000000000050013700752540020021 0ustar x+)JMU04b040075UHIKI-*a.wJu[s0 UY UG%"ʛo9gKWPE9PUlQ^~#U(TU@Ug\g 2EFAi"奖$\3D~{˅lvc B$eW螰0Q Ъ)13TYqNbr6?uI\8]͓ c)̓;0o/og7yxo$տǖ<*I-.z٪Wa3\T'(~jZ&/k;ėketbemon-1.3.6/.git/objects/b3/0000755000000000000000000000000014200452005012626 5ustar etbemon-1.3.6/.git/objects/b3/18ebaf36b0b13bb8d2590eaa75a0f7b7260e170000444000000000000000000000141514174476517020126 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3E+҆J?D޷ 1D69'35ܵ/Pj;]˯BT&e&14[gp?ױPsrڝP u&'ߞurŲw}|M-ʊ--c;Wn'[$c5'qmȡǕk77`yV ON1S'/ X+ (I #}T~MNCh^qAj2lḵ2=_9f>Ԍ Ym9v+hA&!c`8a;K\t7!'8/`V) n ^q2e{yES(DEiIfN1üow>hOz22Ib"#zWetbemon-1.3.6/.git/objects/b3/2a50a3a5d235333fe71522eb696b5b732c99980000444000000000000000000000120613767513464017571 0ustar x+)JMU07d040031Qs fi^5W~/jbW|W^Es];Ӡ8IMjEbnANj1I+&?<ߓHHL$uy%99 >gJT8Ǥmaq$e9y K%T&vU~ZP[$E% \O6^Y O@SW|vcEQ#>YUQ*ذ*)UUF5AE*f7/~92Y{6;&-R oMMJAp4iak&,Ψb&(@S5zN ]ϡdn`+ <$9auў;sIwK\G&-etbemon-1.3.6/.git/objects/b3/aa304a94b16b80b45a573ab30d64268dd2402f0000444000000000000000000000072614200452005017652 0ustar x+)JMU034c040031QMNMIe8;?nN|:/wrq7jMMJҊr2KĿ2sIt#A KII-IMM,(HMK.(`uy&؟jRtW8t&0j=R-77-G$5fö~wSzڦs'g*Nz 19_>w ٜo~tTqF-|ۖIV;fY ΅*+@U\LEkl1OLI,K!몣sbm6 V?3c>|*-@x>Dօ82ӎm8ȿޔ{n֥Ô&$զj2s:]4Qwo槕%fcAO債ySTU}x5 )i 0(*)s^5LӐዊYz"etbemon-1.3.6/.git/objects/b3/eafb3ffb06c27c7416e350be5143338ca8cfe70000444000000000000000000000037214173222403020204 0ustar x]MK@ ]hKA/=Nә:7Q!o$ -\k9f 7Q_7ٰ[RBJs%d2PΉ@7>9Z&8Z'#,aN&/$0baR&!ja G, ؅YKF &lvCHvt/u 덙&* ۂ=(e/A_retbemon-1.3.6/.git/objects/b4/0000755000000000000000000000000014032516006012634 5ustar etbemon-1.3.6/.git/objects/b4/1c04ebd8b7011891915b2f507d502f59dd18220000444000000000000000000000055213604575712017554 0ustar x+)JMU04d040031QMNMIe8;?nN|:/wrq7jMMJҊr2KĿ2sIt#A椖&uT]s7э93N ͍Ul2%βD[Mb*c3!Jr lrC؞NrP  8x=)b2x[C3]JZt=~<{oV,>?6@RZQZ*# &d7(#&.L{)ϸ_U+ybngJgbU҉WIbȌ9) h;Bɔ5&Md2%J92vx{#pб9HU wsOG/ &hQK3x)W."թl13;R>O2l5̵ NDtvXhA ;`~pam Wz˗KZAXDXWo/h5)[Id3?@cԣi] p5\t+ k(kL4`wh"6ڇCqd CU}joj5֋p-TSM* ->^0"bEJZO{g M 3*o \ozV;TXx{~2@M`:=PҷM^.vqhtI}*Q@~; ۪D q9v0hq'֥ MUĪtKJ۰@vB }$j*`NPٮ TKldL?i`B[n @u-zp3_u,e@08O2]!j_&VgVNn6y f_muk;ǺƸo/P&hu+wBʽetbemon-1.3.6/.git/objects/b4/de3947675361a7770d29b8982c407b0ec6b2a00000444000000000000000000000002213212006701017542 0ustar xKOR0f04_etbemon-1.3.6/.git/objects/b4/f04c17e4121c9f58869a7dd9692e96c3c9e8e90000444000000000000000000000060314032516006017756 0ustar x+)JMU00e040031QMNMIe8;?nN|:/wrq7jMMJҊr2KĿ2sIt#A KII-IMM,(HMK.(`uy&؟jRtW8t&0j=R-77- T= ZEK|{s2J+tKRs ߮W)gqL0)epYWKoaQ\8Ti"`rg0Jz6ӔoYsJKr&Ω2Hj#L'[o槕%fƒAO債ySTU}x5 )^LON9]iE,ketbemon-1.3.6/.git/objects/b5/0000755000000000000000000000000014111113236012631 5ustar etbemon-1.3.6/.git/objects/b5/3aedca2787167e7345a12e83523bbf842101930000444000000000000000000000124213212007740017536 0ustar x+)JMU00f040031Qs fi^5W~>wu`~V-:֖0E% [Y'./1Cǡئpy%E9 Nz/\Uƨ`)Vʢ˄,Ҩ7A (7?O/%5-4bEΛ3]Ya_~̢bORY)'4|^2d5 i6 /J,wAq5Ԋ܂b+WMx'N̽H2Ksre]Ψ!nR3e$e9y K%T&vU~ZP[$E% HwlO{yDDžkFSW|vcEQ#>YUQ*ذ*)UUF5AE*f7/~92Y{6;&-R oL @ppWcn_VX^-hBQ)(:6`GAlj\[ͷٗ>u>6:d L=wPOJtM#>eetbemon-1.3.6/.git/objects/b5/5cdea878c1299fbba2ee6c8b0957764d39e6c10000444000000000000000000000063714057336772020204 0ustar x+)JMU05`040031QMNMIe8;?nN|:/wrq7jMMJҊr2KĿ2sIt#A KII-IMM,(HMK.(`uy&؟jRtW8t&0j=R-77- T= ZEK|{3 tKRs Jg/2vuQ.;5*4'3UUܚ*E,7i1:?1%,npUGl~f|"UZÇ+zF}4|+Ģ.tk{G=6n;SVR iG? ^Ou;PU}8*(4=`P8URRtj!ӳ:xetbemon-1.3.6/.git/objects/b5/d180ba353f895a99b7dbbfe59a11c3f260215c0000444000000000000000000000120414111113236020034 0ustar x+)JMU07d040031Qs fi^5W~>wu`~V-:֖0E% [Y'./1Cǡئpy%E9 Nz/\Uƨ`)Vʢ˄,Ҩ7A (7?O/%5-4bEΛ3]Ya_~̢bORY)'4|^2d5 i6 /J,wAq5Ԋ܂b+WMx'N̽H2Ksre]Ψ!nR3e$e9y K%T&vU~ZP[$E% ^_"w'L]UGfd!N,& /Jµvx~I<\.[hrb ,dy6`z޹ɚ"5ypl|?`e^dQ877i %E*S"̢8]i^G8Ȓ(̣"LHWW3Ѣ,\\skN s Angq5HZag@4|^,2NRVV37j5NsbQgJfJ!exϡ%$N͗F@&էxO*?H V'A\]vzV^5xfXWzN=O]Ce|z<ṣ V 3I.n*sEᴀ!] j2ɢ2}4"F#_a{-[Eڄu  %\ŘO-BXFN,'R*\KL@4|#U-[x ^BM1Q=OF Hz xk CpcfAXMi|T%wssSĤp4QC?˕B3xPxy aӡ[KnSlU&G=15`)\ QF+L q8|B2ձ&j}55GHζt /$M0aɯ"4"CczXMmf<wHt4y,nXEkNKLp\FЖt'F  Y:otO 2h0 +ƣeVȐ9HʇCM9<0 OmB[!KhtHxX'^DKu{0u%V,Xvu6E*N= ư>MVs(Nj01j&y, Q#&r;aCN'E7[wi|zPVm7f( 7g+>`o~(?]Bqa&kYP6:h9Z=l[a%#2f#>J)4ಪp?5*4LvC=z#ց*3] ;Xg2mł ڮ 7E,P@ z8KĢxrK8"P-qMwg%Yx|8 *ILJ/U[ANsL] Z4Qa1_ o !1 Z!qN.:JCoWirB)Լ ^R/WtSթYT"w$fL*gO)q,Z|+lvܪ.WƳFHEEϫwXL<T iM4VWs.Z(|K0{*NO;oh$PtN8OkzNR[Q,f -pJ4jځU3":8m5QZe7qӽ8~´, AL'ˏ2a{m+0ZX/B1n0%Ì%+YFPMCskV=rvIK3-C!P7eתXF+& O{ K`2h˛]â8 -dᅌFC8Ј=r5_3IRƠ5O‘4jo dA*(BFRpXIſ5 a8^!(qؽ0(c{zAḞgFn0*9Y &hh4I\2L1y=,<1!Ix|О\wfȼwS<2$ZR!=Y |KPopsG:cj<4A1tG)585bc|O7Py4Dt'5A:N aho>MBh\yIHJ3j~CBgnmL F뇐SdnڶB5 Nk2Kqf~ 25UhVoC1ޭMM+}dJ2~#C$[-W[.UvN5t;ltNnCtB"*_!1 b {wibZ!) E=[L%B+¿]ڣ'VTOrqv}ԟ_]xd+|ʳT$K`|a+I#b[g OwK/ZTӟ/YI!~yC:Զ9[~AiBdHP!u'pM'ߩ`$NTN?pRN̈x&.7d\ 5~F CcR:+IxnҥOodLvgЇNc1[hC\'C#l*cRUyI 矴aURQ:MK)">ŀԐb?7Jft{ɔmp8,y{؂tK2N̔)Y"<& 4R\vp\8qt\<3M/j|ߺD([qz`Im̹pf!bFM/`E2fG,&`w.4i(`=LNgE(p]h 20Fb&7>y1wb(\Y0o^iE6Ѹ ˁL2?$bl8ApWv.L`r&z !^ip^r۷p_P(!^100OPK‘0RfNM0OmShMWܪW)R 4b$ד2:Ыq4=FVqxK y"xdy}i3oHy) z3Ri5X $TpeuGlq ^H=g EOT ^{-NٓTlaGA9h>XG]&`eȈA{@Zh(tMZlH8Bf m0Xz!gBM% ‡ Bm#R= ?&Ń-4a'eK#h 2GVٵyY1rif(|w@XjQ,ͅ?C%SO ?gekSs:G -HC9fy=J`SuhYB`۱㉘Gx_t%4-Yl,oD] lbLo<%˽ dh,`خD%szt[kW;[tV _SE}KIcPǬsldЭK͒🛘C ~i[fU` KMơBl-;«nKbcWmN8RuR*؀hЅ[f"%qø* ۹?$fS.=$ZP'aF-/y{Y۝I#غW>۾XpVb.^/O.Q{/R&4aENv^DZ $hܪ]r ռplFhI+m h DIE؜ k@d˜꜊+І^qi/ndSώ%p8ZVm7ZڹDSqO@|'m&(m14^Q`QEhrgvYFQ GGvnyj;SXlO~5Qyo )v1I RFm zZSV?hJ+O7^^0u"[EG_Gj6;mQw㘾5jtž̧B\ו̸Qs b >S@MЍk4`VNQf\7tk/#ͩ,ol5%0o~(St]nMFTǤ罈Pj KH$%',۵"cA9N74wXw%^0[ݽ{q6JjlUu3@B6o*SRe2^+/Npvh^SlE w>ֱ?gb䦤xq]/fJ],2p~@$ȏI6Fч C֒Q^|BP قh KQb RyKm ߹kg2{cB3vnp>.@Vp Jm\'}vX-)###RFm'DÚZj]]6~;@q|Ŷ'XH\A*]] _Mvh^R ݑs u6E^Q$" =DpV|,hdo| WMlu&70/^?jTm7^'lZ*=n#RbJw\嗇>זfbCQt$&D]:ԹmY÷P_.4EOA tA?+k̹40#/T?)f.}MSnl)E[V)690FKZ<.u63r~~[Ћb͠e. FPZ% CFwR >9{[z8 x|]ܺ<< )iOT?胝?U;󝮰e#=#UöBh]St JE@KkV=9,ujmBXtKq}G! n<¸5gyDkTơw5I^74_v]4(+_BrX0 M~N@ԅ=P-CIO45WN԰2FQdp*A9PK'@+ bVg-8R{ܽ$/ۗȔR(SBd;,@" ot`0-ޜ4lZ epRY] X \ ]Cv%VSqlJ ء",z*5Ƙl.T; xY H..){/XGw_K5-(=hlcos. 椚_yj̿]4L/iIr#:n\fLNB%Z^LTA,PvמqB;qw7 ni|<ͼeCH{Qt?9dr1%5 l.1}X-8G'4AFƠa5mVGpG4{V'Qe F5 )eWexOnӲϢ9c“.^ ;SB0O{ZNO&"Dmfk) {F$W_%yf] 6g%)%b'OS AY]Cnjh<m,}wK{垬1(!T(vKClDϓ`xfNYf"|V֍Gd8Y#Ko eW2ys &NlVozt{h1ņF4QaUgc=MIlnbG JH,.ۢ˿CG 텸%H&9n;C_.WPҒ!dsq7\΋@b,˨pkRtl8X9>Z92Ԃi>CփGnua9g7i Dͺ2fԫbyJ!0CU(4ZmS źO%;dΥwŶR;l*W, RߓBy:¾8XssM`]>aCnmӭ+MoypIr -Pj VK#UG1J~F&D?K)ҿ# T9zDu ubH&T2K9?jPQKf@sوg. V{ő|6f~}ZQs ÊbNRH֑`٨3/I2|lS{|Nc;L> vնNfݤ?Ǵhb> Rl".ZzG*u9MDS0Y trIw׎4[b9+R}aIc8ـQ1 [dayHy#__:ط݉3&#a$-};Pki-~FA+ZbNF`с{wi['hcg<ɬpZmnY s$x߀Xfh("O&aˤ?Dp5/ 4\b)\xI{|6iw \m9{>#"*rHlȑU>OA1=q/|,ĎQ2Ug o@T^wvM ?*r`)%rnC s+a ?k-vTw~B y\=dkwLf+/w_QTC@WuY)w J^SEz۲ug dupxD}sɲglvW@Yu-V a T1^=;guNǙgﮮµp y:5Mlds@5( z'{w%``OpMoDƒtD5~%M|ҙXN^H Qpu] ז=` E8Qo`\vxw64d 0|B*A8Lw )I<(&Yq)*}RBZT,#U<,?d[wNDlkֺF BFLi83M,9P] @fs Uc'<08{rF 92'sf$U8B>h -л'C%^W8aƘ1VQX|q.fcL k@|61L Xo~tQav?)=CܾU!F8l&7"cR^.|F2SŀrGڛDiAhM+ǿ]SաcWDՑ O?rC`w;XnЁhn߫m(]Nnvetbemon-1.3.6/.git/objects/b6/0000755000000000000000000000000014174476610012653 5ustar etbemon-1.3.6/.git/objects/b6/c94b77a479aa76012e803911fbc41bc185275c0000444000000000000000000000150313212006716017624 0ustar xmTo63CfAH!@QcH'`Hʚ1GYI6eǻƅ.^^ c4! -,oH^%DG8VwZ|qC.y0' Pw$Tk'!ww7m9&j;~4F|{RmLOaϑiykʲ6x>l@ ysM^nEN,=WXI6koufB.ww`yH֓FjϮT!yC;Lts"g1)z pYEQ_%A?DIcD!خyf~Vcq#ZѯiWL$`P '30c1wA3ų*>< Szxj임%ߟy3O d Y|f78*%*pq @>]T}׍mC *P^NivgdC8(|`WtQym۴._~xu!H9`Ap=u󀃀!'8fM3 'E/$( %HI&t#kIQ0A)}!]1%Y;2[)C"LiNit&*İIrG)yґKܥ/9.p8Q-8'yt!a<rs)SwS"֦[l4ƈPTFXWKwX! 0?.2`{tc[+.D&ǐ/킬6E|n)?H7%zetbemon-1.3.6/.git/objects/b6/d14e43dd65eec2e28b4586ff81d6b2cec998fa0000444000000000000000000000060114174476614020332 0ustar xuQMO0_1H$[ˁ^|^WTi:ьS@P~;cz{ތW_drytrl:&δH*L:+m`+k`lDVvSnl91X+[tvq8m|Z&]n?fZ k4u d$ |Df)KT5> H8AJUm|ƇgKy\$?S"I 6?~1.XX{+۲Y?(nzMˍFɡM>8|_h]xSg4b=mTIݿ30qZGKgنB&@ѱ'M a10etbemon-1.3.6/.git/objects/b7/0000755000000000000000000000000014200452020012627 5ustar etbemon-1.3.6/.git/objects/b7/d86251b4eb905297716b714db403b8943d07f30000444000000000000000000000035013247732012017477 0ustar xN0]) #Rck7A;LԔ款p辷%h;v$\`CHF94^zF}z"70Kg` ][S5Zӣ:"0.XFaP*K:O6$o|džUPpd#"F}Uj}!y?xѷݟuSetbemon-1.3.6/.git/objects/b7/f6e08f147adb53971c83056cb1ad4c29aa622f0000444000000000000000000000027414200452020020035 0ustar xKj0)z2Xm>B VkĶ,? Aţm[ŧVEi"5F:99kτ&uPsxI#t.MGcc!ZAW?OYW(R;v3LgIaTaWCN#`]xi@{~$j~fU'etbemon-1.3.6/.git/objects/b8/0000755000000000000000000000000014052407067012650 5ustar etbemon-1.3.6/.git/objects/b8/51a554e847a0f9efc9ac472d6d9a0795bb1fd40000444000000000000000000000363114052407067020160 0ustar xXmo6gctbe>Linu1hVٰKg2q%A.{HJrQx/=GyK蛧}~ؘpJ1ujO=*Zt\)r|IZvʛ,h:)x9LZʒ-&οQ'e 7U@PRh˟^R*, l h) oL୭M1۲qQP@ӋUfmcslTM?__?eTViJEVKӆH"aMYh:oNjTL)_AkR- __cט[,`ɱf)Tz+j6ҼL7d6PdTZȃKI %U%eɵPDHư*rr@n1'w,fIs`lTJ|T*k ` D lcJRUC'Vi?T7MN2G)ߖJjBzMwe]Π;"6»FU .شGUrH =Cj҄zMRXNukUhW\@o.f1/vwz'N{Rɿռ&b}axhFMr{tYK }̠-Ƚ(7#b:JmR}ԑ~8aˡsYAjaz)F`1[pvQVQoK_Rpmlb+|k0GZsDd?gku},Tq>xͣSV֏ePgXQ 6vN173TfǑI@ܑ<b2עg#(ܸ 8ɯ$q +(Y˄Xa+`k𜃶#G1[JJx9‚Aê++lG2[[˽NH䇮5t0<䆽PkߜUܔJpa5~7~E]$&=pf^ g>J'ZFS`Ģ~*E/OzA?{l./GaGg,;aWG}Orql5&!3±~$]t9:+}H/T-wAwitxqY`Q}Kmj6E,6(َ15ʑQq{e:$nۨa PHÄ,`pܕћya E"t\vƷX)9x__kjyr"g ־k?bZrpG^o"~+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d~mmL?2< lrNfj^I1ó k_>v 1ٻ&_HIMLcD*^"KṴ~Z/zž2(byljI2G3vYl~#Fn~-y-{g̮~f[k5D3PV7'?91v{ Jj?mfZY*تWRPYQ saÙE!^W6A饤%0t\(zysƶV+k?˯@VYT0sI7#c$}&ϋZ恬&?!-F!Wi\4(NFRZ[Z}ER>)7I]f^qIbNúU3ԺZ _b,'3/a`jĮsʯ]j dÔK^ C':M]Q.CxC ٍoEUl{x dUE`êTU}޼ϖCʀfU{nKK5*275U(*NTߊEׯq(@S5zN ]ϡdn`+ <$9auў;sIwK\G1*Hetbemon-1.3.6/.git/objects/ba/d42613e1c9d963778f7a9da460aa1e8b1fb3e60000444000000000000000000000141713604576061020150 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d`|z3שܩ5jϜS 5yBds2SJm0] )5*DEJjRfbGj:oEze_ MO=6eW"Z0ze_߱mv7r]zJf91e/ ONŹi=r{n+e6}OpU@Ǎ I)Ө1\h+.HMf9pb宝˫;) jFiPA ˌ,f~ wm1DEq 0%.[:ǐ[]+ UQY N/ y2ּ?)$3a^r;'D=b$k1_?@Z=etbemon-1.3.6/.git/objects/bb/0000755000000000000000000000000014173222045012715 5ustar etbemon-1.3.6/.git/objects/bb/221ebb1fab3a8e7f437c153a7ea17a6039ce0a0000444000000000000000000000132613212013002020221 0ustar x+)JMU0`040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35ݢ{%\\q7tW)Iy [x^RQosIϸwҧ@'3<t,/<O%D6$e{N,^ܵsyմsg;?;A(*(a`pޖlҏVmr1(.$cڿeK'<}rbk{!*JK2s%A{Bԓ9-I(Q?etbemon-1.3.6/.git/objects/bb/888a49217c03987bc18201a9c68197894d402f0000444000000000000000000000067714173222045017447 0ustar x+)JMU057c040031QMNMIexwi_EV3csTT!(X/7?/$A-3D7).HLNpЯxQĻlNg: 8@$5TlNǍFߦ^]'^9Ff~T}Nf^i'5UYo0bLu~bJbY:tݿ0X̌(E3xW%biʷ,VPUũ` ȝvlA5{v.47$$6UCUeyr"'T{6?(13 *~*˽vdūqPUHQnz*pz0MC/*g:|etbemon-1.3.6/.git/objects/bb/95d4671d6e63543b03b49b48a3bcba1a5475280000444000000000000000000000141613314346054017711 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTPv.hMvZh)TIIjnANbI*Cպz SD2dǰ7!aMw!9y% 6}RہĔg\~"%5)31a׶[ ,2*`dAʹ 2w^ -ָ"ZP={lv_}f<M苛=^1ofPh''âNQT[Oݭ.[=< (@zYd>7&<[@c Rxe|Xbkiv vQZTP2c9˽-n>]$b QQ\ g=lǴ˖Nx1l BUT# B@}5c (-)f QOX&ZWdxpUetbemon-1.3.6/.git/objects/bb/b3d68fb260977af4f32e5b3198ad2f4bcfc2db0000444000000000000000000012744413314344640020367 0ustar xܽk{E%,q&!1b3sKڶ&OϾ[-lClεjתh?|O>\?|:ǣyv~IgQ>ɦlПL;`tMӬ?|5{I:jSmtrҝdn6fy;8˳aMZypਯg|}??j'vp48<~:k44?Y+̲ ?ɇ Aw8$&T21pXamGw0D?da]zeY"{ϭɴ;=vlOGȰ^غ1Mgڝd鱍SΙlm^Ƽ5ڧYui67ZIolBGtWwg ?a/v5Q.M=gokC`!OdVi,OoG dd{~voju;>F::NO7^a>pzLq]^c` eO&g4 0 k{37[>*[?2Iwo179φ tĚ(!s? {cŅ-}vOV'g8r=IqzX#6zHgSf[Np?eN}NZ;UOi~ &I?6N'`^t_q V ->mƓ*XlFvΝ?|Χ_ί{v^PC@x  >ks&T 0ޭ!G|zNhh:e|Lepiw_RONP6݃\нiPa@݉i?Te@)gotvt,M GlSS3ٰi@Al*Iw>cpj YAe0RSc?]BG.EX^jK6N/ӵ[h'Uwa[hJq9f3aL&< K4;E8rjv9ԙgi&cCMsT:_4|'l8?x=Y4d85ʘL\$O?0,zHX}I x4AiБV'6 @=_s#㓂dk,\? QHu4~@ );-F}L`;=YpVP֟X^Φ &#MXF/ @,cE(p+T鱤n5|0:5gB4[;;hBDPzbizYM#N`1 5 ;8~vbjiQ1ǎcZKZ&]X AB*e`#- 3hf\V.imqI N :NheѸcظ=_AXQ F@!DXX@:~cv \69,76aWD4e"Džl-{p0 g^!"@a]!,#-}}=xQ qR%j <kpb)\''Z|"! b kE#{~ζF#<nl&;t-i^Z*axLl0Dv؝КxKFBP@F g#Bi2@t" R G Vً!夅(g3^YCOc΁\%F:i%dA:08{tZ<8} R4alz9eAb=̺˶ftߚ1>܇.~jM` A3 vBK\) `p6M-r ڊw>3B8`[ T@G@.Nv.%HL$S*b܃v.n5$P6H+{;>~([UΌxL9SxŒU]aw;/d[n?ﯗ7Vl#|i_]`>X~`T5@"[|*aKѨnO3P钏"_[}EM(Ӱ/?GkMb]j4eHt/9{'xt4Q2^,3l@_z:b^dj?<}?[w~}mܹ6>-;%O >N<hm۰ pwg@d!{,PEChZ-=S.Bk\ Uisrʾ}BLw?)[,>R5[<@ق!4Z䠏we8FL:+Th>s V;¢Ўaxw7۷-NsUFfU4Ax} u1M~qq Pru}XSM^hBųj:݃ }yWژsw, H?6qG|CoL\vy$Rt9E58`4QC#N$nH{)ABBTJPù1Xy&HtI͇(^cGB+[6O#m?dzo#jٖ=|cZ 11 U@%ْN`wĨ?- Xl⥢#`^M|na؃ԂWg"] l] '$`;$ٕ .V W]SK+F}]nQס5Pk)TȤ(1OgN씋`X{&!M A;<6V9okMj3L Gk*V:1d%M2% aK#Tѩdž(nK[II ]i.a 'T+;S]/;ۊ BM:<7Flc+V-`N%1A*`ݝoϿzl*-8 *!p<0yAc '6 L>ߖX쪈 /`S/wa@Bкsh8@m`/Ogz\].cu|Vól̡_䓒+$5 r$cHtSxg4;3 'iUL4cmKaw?~|g/o]Pj, >?v*;:)`9bgE=mLnRslR^P\Z@ІvK]Fv 4Ӄ3_N'rv~gA 1"me_ܹL)A{($Ѡ _A;_Y[ݨ+RTÕ0MEP86%&Fޫ+m0Wg-i]R vSo`d8`E(d&rܝT4v:; z `!A<9’6 KkҨH4^i+XX1|y7ӣmVF&l#J$ƖSuj>xMuhУIZG*!ĸcͱ)>td Z%e(bD)xa?4`R>%< ,($Qz +;NQ%8]HڭՍJV~olP?#~ GNХjC`{AYIvepVA~>.BJKVz NWM_A/Fb2*܃jlR U6Ю76?`#;5'i_tܡ£ >޿@(-t cgt9$pie|~?^gz׳{7?)^.JWjze =c8<Ń;|U+}|>-jvdKSyiX,aQK29?[FXJWIk%z}Q%  u<^`#[h_ȈLvgXDF \u{+-m5#,:̭mQ}V7V,`'S#tb.ɪ@ M,$381$ b*|>-Eg-^ΰIO'XR)4r~si| /V"xp5թIf(3d w@(y-lܣ!B \L1>Q4JL- ˅qeF8<Se䰆j jA<^ HM ~tjN(Y&<|-)fl!$#xՒ hsgaGaUqٖWp4j%e//\ rPz6WPpHh<1ݐ.B[,D_D-np-gqՁ2bgaQ&TU#MJx̴ 4Z4`הѲ%s֨nή71Ϧ3oIy\e ),ܒ&A=)} &6 CpN0է[\X,n3ǼBF~X^'D_ rx3$iiF1"1 ƲҞ3;P\)}"%dC_K܌&SX\V9Ƞw22@Y>5d^E[\0M׳C7Nr$A&^ *o%*/%q*/Mm)T^?{3eX94KɄ Z;Ԗ+cllJn=N%q{iߖ ^Y;(: h n]g|rL{)J('i\~GEb֮E9rj6q&&†pI浹$E]pmPb^. fXtv/Ï@AYϩv/DwJЧ0D4MRCMqBFm gE-K%ZaYji]iP7fd5kGPfr$ۍ~wڞbP_FHaU.ښ:( |&fALt6nIHuљYy'_-0'l|X@C5_ +(bjffzFE1ͳ(y<SHAm3ikm5%sU|d&ql27TC\7ɹ$ɦ{]z @,]*{]=sKhX -H|dV.Vڠ*mFKE_:bOUj+|iSYycU z,v2-+d*fF }q4'}f]_di: 2A0" `t/GAZ *Xj**oICFP12Nq(3z.ƣ9H0( ô׭bbi'/ܫ*&30T‘kgZP\E1%u!ғy !Oh>B ÖTL_A;ДšvYlUɰ̹("o*}٪omw$(R ,L0yuN0NDл<:^žفuĚL6lSm+tx¶=*h[b0x)7mP\XL#uAt!Q꺽~`At'/V  Hij6zj?&{%S"bdϣ/E=-/ݚ5NFZݖm7QC# GW֛XT u - @\jVo]yV.qqYY5r|I"OQ<kQP.{l>vS ^ؖq%X_VjUG@ZXz so S(]Ih9z{&f* g2|]QknmA|dW(-ӏd.QBKKD4D{,6Y6ŽK*"*}iIVn_ڦG^Z0 řgt.Пcz),pt#RzpfZ {`BΆoŽaJSKp&Xr71z!+l8hI{R zc.8Tl0<"?`x/i*2!Y^gM%&i$%kS cӏ/:s AHSZR }$^7-#}[U1O9XH{sig,L\^-Ϥ94' *tj%9E@ajjkYTMPOPa٤vN8>zrT AĨCŏIud,$ŠlhDjuRPyڲaU>4L%R͜jP4U O=:eТv9wxgi^/v{dJF zDeJq:>NW\OPrϠhzՑ! :*QL̓X(V7)DQ\~'yz|Hoc!`V6,Ec? !aR# 5(~gs*ūj/7oYc :.ǶST!3l\3,>eNź(yW+/W;|}-*auYNؓh:fMf La坣P؃݇dl#dP ^0Dڛ ( uDf($xiQ$idx&] kAG9Y(F#]BM $gt&xͅͅ M#nԚY(+\YC}W#3ԺgҸX>iC`sjAڼ!oG̃AN >@mεb`9B>FwkٍF.(#!WϑM? (ɺOza%̦ul3S-G@eNt3*ű\nO涕Y5YO,U\5Z?pDf+X[-[IbQM CyZaGoޞM}_ٷO8%\b36/lT:>I#Wl>o*Kݕ;4 dqfsB ܐ |!^ę(E`!_ Qԝ G~5WSؐPm?t ð22ym^pAȉm+2$'i. ZY1gVDV"}vBX_ yބFbQna`BUoKI WLNR&&Ǖ4~4ٲbɴo*ISTkeKsV*.i^ζ=KT,цQp$hQ/DsYsάbY4Gt*4:ːRJ_JjB[!(3.$]u'>鎳v^CbCZY4Q* UV'ՙʞ(%ROCq H1õ{(Ҳ TVJWERj/m.Ѱ{)~4T_ol;ؾ\`;4([5BUz*aJ*ݒ} D=~u8BǦԞ:N1Zawbh {8wҠyaV=h*ingu}׭Qty2A?߳sz4BX.mpZli$8JLYD$ @kujkEV8+4K\:biIA+Xn.>47BrېmٹZ>ЧrYղGVH^xlSL9 S[32abי:QEuPSW~Im3>{z>8߳Ǯ׳>OlгVXm>ގkT+pv硙SmkЖ##(tՈu+XX8Gq?\]P!/( P/9$K#?~{?߁q< o9ZibFS%ZQDR|͘ppB 8vK'%NxT0QM@s6 -OQ@l4OjЛ)}o^/UOG(Ozs]TշU.f _@/xy,ya cz=\mj @8sK+3#w+ܪ?}KVۮk#"bf?_Z "<%D4% űBh A'bz]^@,Wg&׼ U-z]ȃ+U/δߐo04DԮ5DꞜP_dM҇n]XιT+%z{4z[p6K&4ɃWų5 48$[o+ dk-\&hG I1JOGt4(Qz#\ɌZCbVd@&e,Ȥc*n.;l"~04dm]#9MK&E%p*X9301:5j+rnD&| ӎEf;ҡxY2U? Q#*2ekqfe*@ -]v'd 4vƵb0x 4{]"Qp-w8PоF@.|8XFXnͶ3ݩ(  n2=aEgd/G< ##7-0AC$l-IaCqDHr3> _Um# Gnv`nPӮL]D>XB̌Ei\;vke[M#h/4a L #O+ 0w_~)rFֳ2j[рV8>WG@[(|ϔFhr>:4ӓc_I8/ڣS | v!܉nʬk e!IɨG{ykxG /w[e[hV4HcX-)G£k=5AE,E_%"Ҥt`j3E 꿜wMJ2|1mrM5w-Är:U ΄n˕Xt*'Di(ɿh>E E(f5֕-$]fpq0cwH ^ƒTW ƥ!S6! Up k3+ҫtJ 5vzً+j{ɥKJԜS˷D1OcS,# -6y`gB[ &tꌸޒ %W^*Oi/=o9#^YzbgAy%I`]-vBJEx}04Zc/< WjDR]TQ䏃Fcli Ԛd"Iny5d`hzQ7L֟~'8wb# WmKI+Uu;Sb[Tzֶ(<2bg52XCY(\,j BJ J|,d-JO{7F_pSg &v zi Lٸ֞4قp g(I,6Xm"fEW=,W^~v2"$R,bMxƉ1rF;hH6L)kP">LqU}(u&\mIٷ0ֺ.EMW1NqcZlJmQ(SUz\mϫ>'J3fLHLVR.Z̵d-Hl#t.fz'{ŋ{هRFkZkS'xvv[o?i6g{E: \Fr5 ^ 7{2O_ݫЊsɮZ.K6a!Pr&+s2`5E=">tHQ|?HQ4 S>:o89\cR)sH|R=ƀ!= -VG쮕5L65,{ّAś]JhϦFSځ7ONRVEe@ +0iJP6qR-wo=TP]Z5dQFX[at-ˤku[bL'쓹@Eni3}CiLpʘ18:vF1k+ŝsGhyڐELRWL-FP >'Jh` v}#@CX`[R'}Ցe ; )70sXڷ ߰;h j<;G&I=N OBC!B*gfo̭ViNW,5f~Zq"teQFUPT3rުIsr*$i)kL+Ґ'Ř۷?{OGnY\%`XK] F$L%g-݁ Ӯӏ`Լ`F;͇MXE8ĥ|wTPI; /|f gѢ6e~gdC/eڦݞtϋDM`fUB*aDhhK/ j:Ta^,}*/N$T_&Zs)"^kQQĒ+nlH!S,8W6(*&^r \3]F@H"Ԅ:1m@~r:6!hޱY·?%'FPLȿo0Re;^#pm[u~VZ~͛@HD(7Bo*0e)zYF/#뤦|Xpi-B(VO&ډQ{a*6nH@t3PG׵nU-4Z㨽UBJ LyCZ ֒1eZVmYw;Mn~[YQg.akJ 9Q;'eȓ=(2K7ӈCe*,_ 3ܔrU)G\@DrU3%J'&q& C48ʀ0kEo 59-*bZv ^a V䬢<33~\W4Y'lm;268YE|PBV{br%-476@U3fKj8ɦoǡP7wD˒Uq}DP,X>z;7h`@5*N"y闆fVẪ/ppP\K+xjEEh+)6rݬ9Qre7!~` u]Nftk"*J V-7#,<{ޮӛy^Ҿ16뭩'5q4,o _5[w $KWZ.M!ZDnQ* 7>ɜy]Cɑ˙X" ҦT٥`,@_7/!#ވгbVPle$Qy,]ck utk KפgQrϩyIRĻW뚹̟QgDZ,ۆڽgIcq[J#U"(+r}r;AwXk5mM-t&3S4Fj TZ':Bl@TUЄOmؘ+R0k mw *ڐl49vs4G+oBm*% <3fR>6<6ZJ>cW۳sZ˴cVD!o9٫Yi3ЂV iq2,):;dB!d:O\2251C xSVLJQeVL:G3А}}{ ѧY,ֿ0mFԘN-ҙkTI?\=hi}ܾ73 %3[Y H87 X_Dcr47)4NwJĥ,GYg>PBj;؝#P|Pcζ cCq/:7(RIHP:S3zK Poc| >|؍و"x t-&qQE?sr!{hⵎb<$QfO<:wenb P+ &ʉ:sk8n!  vFp'^tzBI%6̥W'. ̲\;/Jh[GX Q}"3Bd6RyL/{|2Hj.que Bu AužIV[ndlnnGVz( W` >{b|n^^Dk*H*kEg ~<əjAڶ2r&`bp6/J9-wv+&4f,gj;P,9L,YicLg(dcN.9,.Ea5uëC'o9C%,^p!Q<\2c$x[[C2Z!SeYnъ}$&,TVѻ *4kDA6FgZr{:|@Sjg^'%v;^ZYejS]RRKaqC@v^GK+\xtEj ]a\()4l4R|jΛbs)W)ir2,{Y5P D \KO ?Z>JlgsUGAʿd!yr'G"aliG?x+QS^{A | *aB씊J\%eg@7-NAt Z [vV^ >p\4w{}~ƎF',yKl1 Ųy_[jVz-!=4σ񍄴2~nݫ \ ~ !$ek.4keiL5U &|=FHw|\*CXI/rX2fƜqLj!A6}]j0h|ae-G wli "#=yeiކF|͎czלﭫtk1쒮V6'7Dody~K/ 8ML?El@HQFnLoXk{s^:3Gm_3bQqET=G*4m"-MB"<TW ~{x% ,vCbSf=N2rُB̆*sCӥds.QW[vBĹo DuøҼbX+GR)+n6'I/X_ LvȤzf63' motpdЪ,D؊xJ2Rw%cpfjr"#rfV\Ǎ7t'2ߠG2vMg,DZ(ӑgHčc7Sv!6ep^-}t; x nӒOOH[i0ZLEl=PB9 *uٍ/Jp18*#yb=_un}뻸yHW"R"SoN$ۻ.^w s?S3NG\<+샚N뜵 UBfZ׋]1R@|@lj2(„.ܣR2n]fK̄z܄uDŽ[lothc#adH0-N24D/`(7> Ss~fg\Z @(7hu=!L#!4H|'+av8V}BU[x,2=!H򵿰Ftn2F3$bWyjQ ـ9].|6!OOT7\E 0wנK{{Q(>-@,n}ΒQLaCSCZ/"Npt)yݡ'J@5@jY昇dr/Ɣ#cպa4weϐ| F,>\ߊy8&+hhίu\zs$ޒ%& !|5\g5w_/EonpLw ۇ* 1;ǕшGʴK9CmjїRnB ?CH)8#6YT= KVνiTO,JXzKBPQi'Ӭlj"_&rRtUj3S9/?xX˯u ʉ:<#:E Vˑ,g2o}09f!ep)[R [&>ab2^b8#6^ ÷V6 *;tѳ:簹-88vV:0ٵW] @`^'ϲ/j|r6N+ :.U&=0uMXulid翯1CE# G bxbgǘrgBWu\åvjEU:檽-n7gUkjˈڞA{B_k%.KQXimGZ3b2Fd-JnQ:k:ɾB'@]^ ͓d>>;`+-kɄE֑%Pĝ`9<JQ ;`C居%qfNH'iJZh]V^)] GTKp=Z%@H\S5:SB4Tk+k +HbH0QFWP!cP<@j^~n';&#Q/4c1MHqbn-lvyz ך_,E]jz^Q<s%(k@(",&!9 {PըZ0i,FCSd( n8+^HujHϮ?ER* S7d~Tg%tVɻ˭r^^٣<լ-DU}3G=%)ըywcAqAgs`r?u3Kw?+ח0&<QƘGݧܗB}5!.x2ܮ.><*Z\*4<{QN2ҝ;şqB<77 A~Ů)a(S ,fokv ,D1ƈ_׌lf1bwa TC[,qNL67-,wMd+UESg!|f tb8k-:Y'?XX}%]q xӢ~O6sa2^cu &p?oKhd+dF ?|!O?^_,M,1U-r 37r"GzƑw8?tl_UL6'zgS+)\L*zI痵8KH ՛U\r9qZmwb.1gZtMnZ[,*.߯5g+VXDH$sbT[Dʐf7t7ZX- ؒ;ĭ[.pp&$0{]hG݅U-dp0il[qmԚAZ8Dmz ۮX-%税۷~\[b/f 1dmsTDzmܷ ΦgfNPǏ(πeIl \tHV&>@G!i- Kh[QFւDn?G?Xyhܳ9%Ӑ+j|zy$MsQ ɸ_Ǽ^$iH87pYVV̂mzM{ l .Fb 4%![w~\"_'?b/*&4쒓b%uPRGڗt!p9QT U`us`7mE` o溢æx3p5)NJOHyDR ~;\ MrYhJ8+ʲrCVCp◵hQd ԦZ?2v42c奧|z0f">F{a# sQ Fe݊]N:\Ggp.VD"ctbs9g^@@]o$vjOjnugzϹIJWdS []{'Iζe:eLI hZ g(@~N+ g?Z&`8'Z6yLo\평DK i[~so_-j!^gL!<цFQ-Qcy`MF-AXL{T̸_6*$!j3-;ģS[Ds(ܛcp$"H}2';<Lz{n $Ǡ*es<bMrg"ui}CvU= n{1@2iei}B]dYLow1SP &8|#qP::bk0zk썦8䐹WtU6@w**8>D/{VNͥT LPd9S&裏q&%0v` =ģTSAЋ'Cnt4y .'#fg՚%R عAYɝ[m{x(i.H3; ^4 ã Ƶ%99SH.Ka>,vPbI >Ӄ+`hNm}vHNnSϺSY\.?3:˟ϟ$S q'E翀Q3raQzO l;՟jkdw\a;EPUG*#|hOj.ASg GW"&EuQ! *@Fɸ8VbMl歳Mi632WtB99ݧ-$gYg_9*1{Gv@d k\ř+i<.X7_5\MGγӟahzcݴLyeWM^76!hMHqtKR+K$[$a6CGTOAf"yZaƘXPd"=6`&PCxi1 hsN'ΔG}~XBA]]jsm݊Icqȵ>rhkeT7BdiS+&KʗR9IVNKk[nE R~n9=/_CxSS ɤF]%(s5kG=z[Z^,ҷ6U%N$ک?tul4g3)MםJ-*ċϝǼ;U=Xad0J\ss jkO%LJ$Щ/)"FPQb Z C!R*ň:fR aB*mtA7;GLc=o*/)t˱z?b1mB@MZoAG%WOՍ_Ӭh>Jj*t;~m_p(' k02a$Js+[5b$T7^ )rKwEjCpb8i7LjJ JU2x.kl"i?=by39~n=@;#•\CbI6 !(3a-WX*׆dFĞZujWXKgpz&֡TKMawfTcBW^\KG0:spcb&@rQ';RZ@g_OfACK+!W;.V-K4;3%_ECxU}F7h+ZoK^B-DiC߮ntKnJVt֖/ NZɥf BS.^KvI&}iEg0,9Tb-bLن]!bw/on]X Tx/2e{F)a +gSJ@pyl]j81WLv9Y8B,33$sȾ墓1g=]{IG%fډTd/. AL' C48V0/IJ@lJUX'UÓ2wqIֆT(5EygfL:~]T1\k+Xh-ޗ5{+.6ҳIQlX(J5cYwU=6~y.)ޙA>r,ĩIvqr rH\=&>{H²w!Epq;XrB'iqnkxǣq!%>W[:Ne /Xܷk[0{ `lf0 kTP "Yb9RʵNymUJas]d8^Oo w!I|b1^jd$6t#X)*)wSGZ..*bk8KلU: cEqY;FFdN!u0#DlVqfƱJ,lIXP E<GkyZ|Rv9b°1>a6tJ[IL8 k 4ӂe7o=دx*Y;1~p2 P6BzzW{lz&";gJd:I470~VK!_C/o)dgr?|[&05d) h. ,?2'0`ܵRil3ekEmkcZH{ Fm?E$29n䀤vИ. $?5o&S#_0 d'DkOtAn#2*1;}˗1IY- @6LQ C 1/؄=<#jO9Q11yzy!/2ÎnbQ%g)Yqt1L!Q()Wݑs"Iz$l X%'$ WL{NMDEUُޣ/VR@gPi1Ov-zUck7 EOa/8-.Iq|mRG'!bPcp4v2Zh݅C \i$aX듍<-"ZzƗNI ;u*6XKTٹR mU`B{@tHAHfk[p+ с%gxLt ,52DQsVZzpw-Yqᯘ5vB`oսUmKL?ЊƀcR l69ҒC̏T fD~ ܨiiÐm €Zl< Ua|q` _NP2|Iؐ7pd#'pq`+fU V(*N=W؟w̙bBxXl 0f"=GF}e&WVعВ[@tc'YC]ѧ7MICBI1 qm mjgOqC\Ǯ {D.7ǕWn2 . :"%0DKf i) Ci(\x[)/E캀׽= Rwtf #"Ȁ|0 h}s{d_xТ}*w &"kVŤ္H*mQUU\`gcJ+ÀQ?((~'ΆYe|^m p-WPwA8hE=_N#LB_a!a(M@dn ~@ΈiC `vjg}V#@tr·QJ.Ϋ@xݔM[bCs50JWm_wSRH8)b(gǖoJNkO4g`(v>,xa#;Lngg1/9>ZtƞJΖBCafb"<͕ތO`d'dGq9wE2myVesW榫<J5B @0! :u)Ѕ9[weZEȁޙ L}ejiv*9qKND`ڋ|0w[ھ~`yzD٥"B |F/!9kν:cLkȚЭk8|\rY8ToR\eu9lM:,-=k?JmylUB4c(GCfw -|\Jhd %.;EHѹ6UlE-ScM^UgmC`P_7W<ƕK4Ren9|w2G4T')tiW^aYo{uW8{  NmԠYt+ds9}{f$fSJl>paY7 H\RyNO%Vopk_.URJH֛RI7/j_dʉ%2BP' gn5ȠgwvRvڲ)0X\RG2T\ۡ bc X|)o짲4SKۭHjlfÎc4Lk'I9McEC{C &LOqSkmp'y"Fi@ꆨ C;їjTe8?,q! CV,Ȟw ,dOqf <-5;+zK#8"~{-oW'$Eu0 p ׈j W`aАu"s8X%V|Z^mq ovPEе ` ,urF"MB(5o!It72'_?y"ixs,y"dMeJ G*9IPg!ZӹY}/&XΊ`Q+3N[X~o2܉^2v[מW `OCA~䔶5ᕴn@|r?˸3FTXג -d#BF6'mY6.'3`l v J=k*qG/:G<+i,s༻KXBkhQ`ls?I&J%-/bj8ښ'^/s}@#>du1s$|INPLF'm-Tr_,_A6>pbAD TdY?F>*hw\w^8l*p/(oNb?pe@kXMki޺ևplV`Kj]3Ҽ]XoɟDX?S#7^/Q Тa/b$|KA|M-L47=Z/no6._n:.ӟۿ#7B^C_c6̀RTNҔ܂_jk 9R4yP2ME*lJ si4s"NM"kjlѷ-haɗ6܆T6G;3_`ĉ'x^UL!GJ,Nwʖ<?N=4uSBpKzk<:P|6Yid,xEŚ~&k.Ws[Q,6 adh.qYQ¾v3ԡ^RI!4#j97"#d)ړ3c68'h`w>_&ԢO?$>`ng>:E~R #<tPu="u/gqF k8b-SV%Rs:|QaNEƋ/NlT 8_8!=ARE\(9x43BmXOoރ/dcM{ +z@i_ )z`w]C5,"S0X/K^>z(%x( /46MtWŒQ4xX\QR8%UR1;fTI b#d29tI]& 2S]r ?ZV#tz@MlU%22Ύ1eFט h9*36h#+sס]lm^J Nk Fbw 5~ TeB2C ۺDn9{`{+vɞjDlb~5z_D~QPLñ۶PtaQ>dlGHw}5dFs%ݼzv&>9nݱJ7t3o||FDm϶҉@&)-\1?mC|IHWMz|h(XwB?9"{\,U<ң6Qo4Њ.`UnI+A#&}H^oE7uN%N\1"ظPr8wUG]Uy!<9NƦΥ")Դ ߰=tstSw^ j*dl#ɦ].e}cN`t'gS0yݒur%{jurs:R.F`{ &o2ӗ3Ѩ_ܪjL% P o ?j~w^=۵kɔgYWsl>_Rpnq\zSf=VOZ=*o&y@5TJxqf's!ip3(E)#P:\n3e9؜*gG.ng-fBNBD<wI D  Fǩi4 >jxgFfhO G.gF aqa5ח6g'RU$a U{◮on]ˉ8jT>'+.ƞ/f v<|AgtCT~a0msAIL\%n+LvWqѯ Y%@wi6eqt)-4x <8蝳}و~)WiRiloƦʐ&R> }Z! uSyii91_ߊa6|c~1뼹+anbJ^mZ |+7{G/g]e.$뻺1"« u#|*d!3$7Jұ:#ݚޒd]i! kuMչ4j; ŢuA3`%+>^v<EztMv>_Dv+;/m"S:?=8-'0HqR)9({_(\k?[e_}R8\xYw4LVʹ>c1mk>h<]~ K ]46kFZG]QR髭s njOZN6jՌŸ` \_ na-S޸cfVï~dNf^ڦ֗|D2blQ, 5D޽[}Y*fKv,!gHHYCgܢ)ϖ)އfSgM:X'(.Sy^P70 iSyuEծҲͻNrϤ-(e9ndJأm%^@,B1C~!t`'!ZM݁Ѽoty E|x̾n 0jZsT5&ݨ41f \Op4޸=`$Yux;0^ĆP`6"t,k|N|<>ibi}^Tq~%2Σ'$xf|vGu;޲,ߚɴ 6Z/3g yY?Qz+şn%mjڧ9@ ZrZM2zOύh,Q@'7v UE ir|՗9ƻE_ ) 7['^bP^b8oOLTjAZA܀屶b*OiW]{YD !U/sl(p@|Dxd6ѵĴX>J+q0W?Yn꘰+m'R=h;PNq:l֎,G.f JόfTۑl x{ D*Mo-Y3iPب~ƻ 3rɡ9꽵c}_|/խ=ڼ[om?`;~qlK7Vmxц4jTMM<htErX6;BA$ֳ{(37dc%A͝#54]MY}ᶩ=q͹BDڡSgHi` pJ tjv̔ RsB ^JO29%GM҈K_ v6I4)7܃#}KIefڒ$u (kNmǣǢ\}viYU}QQf* D +w!C 0 {h~ !diLR=ɼ|q?z`2гno<9_1}FWAM0+yF0yw㛌P++6o絹S'޸:6nj eO$ va[EjAp\YRP3Z}<5 ""m3lY$D+2O$jOTxZ]1Jx]y>u؃h`0@9b.ɮE]ug={rBLœyd/Fdab;;G'Hdgڱpj%1F^ 7eE$ͶۚmJgvwK"`|k7*igIG(P"Wz܎+ոJ 8~7o@NP7jV]3ge+ρЏUOZ|JYePa-{2c#P\Lj`3kKlOr>|f n&m|%y, vUNTAZ6p8>B3Z#u"XsX:w4CK_O;0!YLZ<%>†0YV*IJ6ܝ :[#S]WY+Xc'ۺ|鱟| +޽|d Q'75(gh,O9~dzw۷K.ǂJ:C. l&jȡ\L)Jx?*Bf|UbTr 2`WG iܩKݸAڶ}rWFɟW kkhn~#mU[Oz 1dg{a(VӂOPt [-#TUyRzy'籡8NZTr#xCQdŔS5"E6,teP;J;I:pűfsnaPӎGٝ)y[;/pL8ʤBP-qQu-=s2Qx3:MWJMJ:WNm6\mR8E=1)%kUNz4{ v*pԺ5ʳh/+eKyjrT*"?e z޶ "9jR`cQ{Sx`ÇcpFtl9+"?V2>ma8dL곛C%,QtzDJ9 7 iY۲Ǎ}/ ;D_#o%J{4< Z c6MܷnNoѳo_% NГ<8wZѐm=|818a%W61ȗؓbi'W&;la+pgf%RZGjwoEfl?!?2OC;g{O}W~qh1J7m?k&h`/ԷThL.SMr]#l,ޝ,—qO⅖) LhUlNշH:αE%@A' ָ ;|ߩZ7<ʵ@k}DZ;vOuv%l9Ppc\Ă%VT ,rr- Mv+{Ǵy\ρ:,pCMRn: "eiq:S~=֙:^~{{.CynFROJSGj(և\ V.5`̊IE *QD#]M:0K"=)Eɩϱ֭YҿK8~DckP],s`G5&>4ʺ2Mn.T!Upi'vP9+#`I茯0=rڑɍ GO+q(ĪG1(!&/go'CHZ7vӂק;oZ  +tqmM'*+rsigg9<53 FUU<9+L )UV6+ʶ$YB&NXt:?Q̬Z7;?ڛ %v4YD͔*#GN{EcY̳ ~$NafkWqdѵ]6cov!a{3LAٽ۹,sH_jA P  5}9jMc5 `%k.mjgaW ƀYy|:c~GjYgwY&l6Zj`[3iմKag 6IazS_"RL[ rf{%|}oL) .!Q"˜csݯO?0|rahu!.@Mk"3GLM[<]`Mn@t FbTU"3BWq%AڟVᚸ1=vaEq&#b#KdL5%KG)3]$nh0WOZ匜3`*D7"Mc B*ho;7Bm&JRn!+BȈu01,5I2e.>ø:׫p\o-K;3UzlpU-%& cd6;H>H7sWEZIK#6(L|fDdg$SpUS )gf?SmDQ tհ=7$={nGb{1;eTR(ZWl;Ej~ ֱow=Wa=JuK<c ×%4iTAd֓XAX |Rw咚;^CcZ{0EmW{bG&945ȶaGZZ45#߻*9ЍڏeI_9zU)+8Sә_"BNJ@ “jX_j,8#AƦMJǣY4v'f.s5AXfsC-!׀,;MxeKw[]WMDWz:fΒ&W-eE]UޢrNgt\z gz~ut6XT9F`.dK$I`d\EVdר~6dUzQ8>E ɭo؃nO+,PsʂX9T!C&ׅ{ٰ> x/{@'>xvCFQiBB>]֟t_[d4T!VHX2@7VfX^t_חhl׭WdVN*/'gh wD{ݡX#94W]o >ՋAo}VW4H7;htz\Q R[&yxi@(RnrFJil!刖-} %?<u;,Y$]Ung^q{2˒I>|f'{c!(_K9r˖? oK Ԅ8d>NKhk͝Lڴ\xi͆SB.@VXSXPe~6O\WSd {(Vw2Z㛔=N/-n@uWQZGQEk\*7Pj6tv5@uƏ^i.dɑK.%نttZvXhJE8Ig[6o 6! ztPthQv:}f7i+PVtF(8q)w螄]nn^OX(jeL|U>eA%ֶߋ_#b%/Jsd<2D{}rJ ;]j:i Yy%9y)ys!4=7a_9CƩ׆1:ڥS7=8* ;D--Wϰc,3#0H_~WTQm;mC~;#f`R?`4lZn)c%8 ^)jD1߼ M~Q=ݹr_y:6L)osB٭ІU9M,3in,c$|jM]=te>ï/'MÌ&ï /yAl̕n݅ -ϘG4@[~:? K)$r)iT+l>A34Ow_m@b/(_^l;go?a8}[)kV0ae3ՔAzB`&a 8CT&Uz{Fi1r=|Z_)J_,8.bڜRkWz-^kdX+\j cfˍl_<:٣ O[qwA% QZO<o+?$EHpM7je3qn(6P y{[\_KwC/RxK/ D9Zӹ|~hg7qsZwBfR5ql iy:lO9!Q*~;<TQَj)sr2peoHV 'hpv8;C5#w&#%ƨnFb !<)|RO}:o#e^?^ѿ1pU6mOۛ*DWhA@?Ȱn$ƛW oU.0Ds;`)d+m U? NJ,pP>) 6|ͦ}Y1? )ј띈B+2+Ù9"/z*D{"i3V5 hc- Gٌ;3WT*3wD#%I=E$_ScU<1W䤸ֆ>BFcU[6!TXGiXb}k'?{cQi=XQajrBa}$~8UNVdjξz5 g](?*5OiԼROG_fXi>d;ϦvՂ.}h~7>6yh5ޞVn&8{짟G.GN<+z:-,{ZƓu!8$P%: F<ѓb<oM c6X.-:'$bi b}Lq 4x ߇``:18 ydـw%Mf Cr٧DRJЯ`~_]s_:GrMNɓUlx$ x S"#>k>mW$˷ G!qWӷM#l"_T:dW"Jy@?pe4k6O8dM)⭷9zF78UrJH#ny?QZw5nz?FQk챛E}w؋s*z{6I2 rиmZ'`Gke) -CLh ZC7KfaƂE<)_αU^]0VZt-XɂȁdY*ܕ6>`:Y1^ {7`Rf\"MXKo`?pe[Y/Ջ\1V's"H"ymsn7(ĭ[l|mQx1)iH߳&?{yѭHgҦu`CLTOxspiS)g.^2핅U.Vbۿ6x1J,2N }bD޸6'$=f (G{]Z٪ [| ֊< Gy!@ˋ`/Pbu`)I'7.ala9RbTn$8"g~Ljϴl~_JL`ccY5g'RuعpJCӽ> p{ /?-D/EH*׹42U* [IC>D{dPUyg-5,ghd#I(+F^YJQKRYRWPX U8kC'ǧ(/^M^ sRAѯ# O;@&sd.b"JCG5`OT*Sy1J?R4įEIpn1aC¾\i?l]x{F(ne74݇>H^QZMkH@,MQ `0*HVUvP9B 4|k@ 0@k'Y{T^qхׂV,Nh*Xu]Yr&TW zY?znWJ}@OEP^ɊSJ3^;dGUqizB{W{)ZD-,y!`4N[ sET)a {*p)M~2}~fAq={Ҷ]4z*?Dͷ͞!k)7kʭ~h} !/etbemon-1.3.6/.git/objects/bb/c3ac920075f2e7cdfc1bd6d79d650f2fb2eacb0000444000000000000000000000267114170644171020512 0ustar xU}4Ti1RID^ EXyk( 3{ݹqwL:T^5D-:*!T*TΖv9sLܿ>=ϕ`tqvwqv^ ݰ؄f++a3Tlx3\.1(A$NBDK2-u'j/2F8x[,Wx}di19, 5t*-ځ~+1u);+emf룲V߯lds0 qkS | &6` FȘ* /7x4ĘϊEފݿ{GpD*crj8dnBߢ\TGb HHcN̯QV+ ^Ҽ~C@ J2_" mI~fHR6%GPG %gw'}NfI&j?b[cZ'ASr3'sEbd7YְPK̼M2އe/t?ʟej9HZNIpx@0o^Nݲ.5"˂MSMANsMrqQz'+g%^哯?҅ Ƀy#&LU ɒb=Qݓ~17t& O  BIjپKW#9TFB?\Yj-xb)"H{%^Hz!vCBEw2sO^~70:Ldl)EZ:x.'O21;n9|@:ݾN{ƲUMxQ1¶YLԵ䔗 =מpG/E'CPW\,bFn\"fL|a=0p)j\!Zrv0?ӣj|X316ܽF[szJ̵t! ,#Է_tJ>.n&ff_$Dqf)9u(HTV>n^۴ zWM]!Z Yg0 t 0͏ȞL eyfZS%n[dzg ͏P  MX@zcyGj $]OcZiIKv_AX6֠Lo~sJǦ{cA#IQ&|T(vx?ar@qu R%0C [" #J y@kL.etbemon-1.3.6/.git/objects/bc/0000755000000000000000000000000013212012067012710 5ustar etbemon-1.3.6/.git/objects/bc/2d240a6150cd00eef463cac8920f80e50feaf20000444000000000000000000000007513212012067020155 0ustar x+)JMU01e040075UHr Sr2K>0,\xqc- S֟*etbemon-1.3.6/.git/objects/bd/0000755000000000000000000000000014174476641012735 5ustar etbemon-1.3.6/.git/objects/bd/21b92c34606f1ca903231bb9f8c079dbd48e190000444000000000000000000000030714174476641020003 0ustar xKN1DYl"=lpʈ8=9?܀eUUjnSO`5 c(Fb*3~{` fLt~-ʦlQGNG$mFqi _Gt{&o!ϩs8^Ab#'xVJJ1rLlmv'ϪAu'`*x@޷'H[etbemon-1.3.6/.git/objects/bd/a92a000b71fa6ff999d1740786cb8a752d7e1c0000444000000000000000000000027013221737410020056 0ustar xQ!D)?Zʹ &љ8㯹ŃWq-en`:*hrL Y5>Ij*KL~5hva$1xb {fRZg%g/p̧=ˉ+Aiy8j-['ǫKm< l`Qetbemon-1.3.6/.git/objects/bd/dd44b26f941f3f817c6cb54184b5f8072619f00000444000000000000000000000132513212013160017712 0ustar x+)JMU0`040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35ݢ{%\\q7tW)Iy [x^RQosIϸwҧ@'3<t,/<O%D6$e{|etbemon-1.3.6/.git/objects/bd/dda681ddc6bc945d3c602318686ff5b57934b90000444000000000000000000000130113212007540020060 0ustar x+)JMU01d040031Qs fi^5W~>wu`~V-:֖0E% [Y'./1Cǡئpy%E9 Nz/\Uƨ`)Vʢ˄,Ҩ7A (7?O/%5-4bEΛ3]Ya_~̢bORY)'4|^2d5 i6 /J,wAq5Ԋ܂b+WMx'N̽H22KReZMc;oEUqIbN K`˕ʋCZ?IYNf^v1Òb "ղ]Gl_V9IQA~qIf^q i/pMhrU_ؘnl~(bcg *JV%(F H2GU4r{u;]ZM(Br0/\U}ۗf2W cnjPT |i >{?Xcu#vm:זfmyOM)Y0Ӻh9$S%#]ODetbemon-1.3.6/.git/objects/be/0000755000000000000000000000000013604576061012730 5ustar etbemon-1.3.6/.git/objects/be/6eda331615951ae4d1377730541474baf68dca0000444000000000000000000000141713604576061017717 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d`|z3שܩ5jϜS 5yBds2SJm0] )5*DEJjRfbGj:oEze_ MO=6eW"Z0ze_߱mv7r]zJf91e/ ONEjfYUQ*ذ*)UUF5AE*f7/~92Y{6;&-R oMMJAlշb#qQp\jb fͭljsh2?J7C)O,I`i]}W鑮i*etbemon-1.3.6/.git/objects/be/d78b8418402d82ddc4aa378df27a4a963dbb040000444000000000000000000002516013513717234020142 0ustar x}vH#{*x'UcRcI>gjA"JV>ƾ|_D&^tL_$2Ȍ4zGT Y֨5f-xe~:?xz|qzf]GY4?ɘY84 Gu E$ޘ.|#btQIa*WDy9(̳ty"w_E3_ǷDEeΘ|1ٽKDYf6x6cIa<]dQ^þ<Ϝ/ԼKo̼7CZZ٘Eth"1u?Vu2$/4z7%yIaeѰGM"c/,,FB jxY:3yx'f2V, GF>&A`)Jiړ㌧UȏqrcE6kh:䘮Cc;U8bͣdv’v%EG`jñiy.oq<48%L('30Z8BfgE|ƷN A.Ӟt15|s/*% BV0K4T@ƼaY<02Aq4ίƏl:\nwѯ hrEN=,L9t7 L= am @Tn˗ db&G9h3 FxΣ(Q 'Vv{zJ_Bn#ًg5*"ƌ(ʄ$dIg?p$1:ѯ n2/g&pQT=VPyF#v8.x.Uqb?ǔΖ4u!82y:Grv}&LpF2΢H]=.1pw˅XD*zckbxl%26gqB/S1ilÙX}KQX:HjK@pf WtJۇ#,tib1kΣ,-@U{F2ʑFUK Q X7Q*Vd=Xr+E4Lew7U 8Π,>pz9wAPWWRN6BֿT6fx$/K˗] tE4WrI &! iHLgcbHÔe\Ng)(rTh,r),^zÎ `-vktim'hJ,jp4uBm _D$4֝Zv,Q-ʇ/ z'4:ޔ%"y &61el~-D. at~G,NpVz"yGV#ewᱥ"ߛ>fgypK< T%*U+Q.I @<\<[[̏c,]qa&g)1EavZ%zS~\%-z +|}S8 ހ0Cܹ $N LEif_Mk^ ?d,G =ifQM@ PZauzX!V@` ~ ;"z>"^$IU'~L՝"VyAt4OT0P**mݎEeX)\ F.Y inh]LDa]vUBa0.*˙0֔p&JyZUW f; 3~&}46H%lX6p0梬 l4ݞ߂.'^Z% b Ou@gyAs_pZJh9G 1cQry`tTKT6͇/Jߞ詡Oli `Ix7U x9/ N'cSd&R)Q\mf @:wm)`u*u.] ? "_s"LjGD8S9$=Ws`f} ~]mAf<ϧM_NK"nUV 7:,,E"D W٫wMVBDy-!dKϷ^omQw ZkL!~% >_ d䉳(oa9vD=h_:逭ȇYZsߓ2| 5Δ> Ή6;FG:kabi BY(NZvLhDD% AGI^ڍ9t/͇f~_Ld$Ox@%,-7e,hdʼn ĸ03܅5ZͲ6*tjX"@ɀЖơ2 k=GK]p DAxJhNUUFdM0x~ۖ+&4uvDl#~3{(Nt$NFH\qr/6=5jZ GD}"Dћt"B {PJBvZ\ęQk1DLN(@lx q?6s+30ێGtbېBleiqoWye<zqV,©WX%N LHag5_ QR !N,NY$06gq  z ЙO#p͏I`dӝ+56Ja&Fg e;ϡ0un꼋t]z1BBv5n&,7g)N(VA\YkV)4v [_k՛S!1\!!5C=NFkrߞievwm(3a q~MG:yB~P8y]8s[Nݤj>bl"VFXO=u6\?C_p^ ?BT j5Z`*笉a3b9\ٴgH4:Uwdd;׉9Cn,GEf #&f}eo >8|wHulChD7[[(&,ph ebx^ii9?ўpO<`ۙPXBnYQuG -e y QwVj4?"F,詈~ q;6Z5>J^U?]l[S7 ֠pR; FP9er@"3^* 50/Bznho,YHO5tz-92wB)ħw82W NTϫua95Qֵ_~rkQ@|ub1UK-ef7,K9J}a)@O}@Tmb?RvmV0e%/ыb.'a y%Ȋ1đA({9P4\9qh$?x<V8bCT͵Ao$= j;Yci5@ق`H= B ZE;:-*?މ?c"־Q,ɂ3/ZvWUΞ#Uʂ]=,#ձPa,̀%(`p0C&gRBN ‡jt8s[1}GQEip6c+2\ J-,ɼh6N$K!4CE<e`)"TF1y73trs,*h04AQx/0#П(RgZ-y rg>jMB68CTEK(EhX HDY#⾿-F:pi΍(o>G^ hbLn<$ɽ574`IDeyFˎdDw%I&7{E?JyJKcej!;}˪9?l#*a8`mg(̓sܬ0ntsm]a iP@۫)Ѣ?W̄';_xql7FKaIfxwfb^nVy>AֹTfX4^]DN6N &p(]2[VGNk͏]JRVJv 'Zq+N (upbHp#QZ+x}:-l(xP Aɱ JfKMaf`ey ɛJKM\Pȱ#oJ=I*+j'k&HV+^^STJ_OiF6vǝeyiQS}<Zoޙ5vj"[|.1sޖa^E"(ʼ֍0eӑz oLZ',}h9$?1 j˿|?-`42@TxIqKHP,6Q7HUAcVÙV{֏~84)?cJ % PmѼhPdn~Kx= yuJڲ]:0'4Z5̲!$ۏ kޓ %5I}K'ypp"{@`~ |ZaF7hLKOBOo? w{f{+s뭦qH=rt; YAP KzJv\+QQbQ=ķcd!57nP+[9]q?A**^c MWڼ:Vd:zTOmlf }@u@~+3@< ú6Zs,ʑCa)[9Ғ~-5/| {."Cr|+7HeU/92:h[f⧰#W$j‹Q$B56Ep\|,(dmt Wl PRy:xWEo!k:dUR@珽bV,;U c_;93ƖfbC Qźt͍ D{hϡmqH/V{LOZ9$ax>Ag|pm*rn!5! ܆OaИ{oGEK;uɗ])x+ Zk#h3@,Ih?pqpjJ[}g zŕhMMm=Z͝7|Z@Z%GVMF6Ժ 9xzptK? {bbuJø[!$)BNޟ7K?R9/pe#;kRmв%e/zLQ0i-(|i%Fz`^{=5^ӞN" BE)~+ԢMxqgb#[7 yMEpFKT].֙ ~`B=P-K`DI44WGհ2VQq[.y`OH$D G L$% PL.$[r#} uō@ %*0_s$uu4xƴ.jS(,be_q EOdtf.qfG,J إ,`z▭{oT߁*sxK.JʐEqԃQn TrrB9k81?XTC ]c|樢aBu XT)/!9In cʂB?n_Mܡm2 S{k8dZy]\]ui>(  wύ:s%tƘwSX(ix7D[#,+zh]jsj"ͫ}#/G\{~)Py\/G\CїcV]}}H}8GX3@#cP6+b#.QN숕Apˏ[mv%revհsQ0a { ,Ax W9U HBTܭ~RhBxUBb^ڽ&w%\sKɍ@w~r3Tj_(kq+@WM1dd K|?^%ƞ\'jL#:к.1`ihVg'̐i[s;]zmiiDr:K|)-㢱B^&ӽSGdžVltگAi1zJUIM4%z] LKJUZ%\*<wEG>7d#5IU>ǫc{"hxWA3Y=eu'*Ч+K }5*d)Mrtdq`5q h6Z<㐜4Gͼ2vbr__z75]EK qT*Ad̙b΅nom"5U`ӕ$&',`n2V,Bn:ؚG!l+mx={,JptCD/8/DNAc+<~NS)¿#N(@] ^0hum*tnzNKi fUk{Ry>C# !l%28ڤTgu&L(GFCU 8tRHԑԝn*\~|;[Al7n0l5VN3[NqPV~i$5B`lx΂00EFde[štΔ}$" Sb\||?{wE-D Iph+g>lZ*-\jpS*oϊsjaLMyC828=5} "`nkۨDiW4o[}ّkK Ђ~#55gkZ'21lXּhkvrt2SI*&+sI)Lx}ᓡɺ7[ߪc[@',83bsVZwӉツ#L0}PA}`v( ުK5בB4݀MAda/PY,;Fo~2TҎƙ:@J1l@)-lOBaL Da,[KAD֫ٳ*o#grbp*ϋ`yyɇs>aj-2o+N+kC#)ÎM/n; Â89SA_lVXg#S"&MIl>?%$*h{8;6 JQb˲kO Pf nJVT+vl]@Lpjzз[{[mfY`cjZEl;m9z^R$)'E᰻$䪗AQZ2"zK10D336D+fێ޶˳>>ќtڕa!TV')4Z^einOB8T>viS 3~>W1+948:*&J"H-<#ճ*~=nwZ?vȫn2[pCU$=s:yY([ޒf&Kl7;(m jR?z3ՏJ34%?lM !TP(hmMXr¶鱖W"*"A7{ \D#X]ީ»t#= tn+%~ZA+":#05'h>!RUtXKxެ۬|TR(ևa*[#rmG|Sʩ_B\&j?uJ8Thk|JMySPf(qMŜmԮ]z頻pDmвՎ\|6{+f*+`P6Z=;es&OƙwW)=h>5ˇXֳrfWQF *F f(f[wGhc`5УBm"G.֪ Exk %7qur͠;O0,Sek|snAAfv֥$>} Q) N5zeyW.@oY֬>&E#F4 z % 07k,<ʚl'6G1#a|W4 eFCWz g];m!?b7OXȄT ,>\>)b:|q/P-Bf@N(( ?3>װ͉sQ/k&-ʃɀ}g7V¤{hqF=TQTQV'#fZ{A;Xu̓-7vEH# 4@Z_̈́l˛Ʀd|Ar%X%"Utb|5]YPp7?ڔh>B +$]eWopu}'%# O>XC8\k#XO6 *'xn?DKk 1593>*JqYr]W@^bH;'(Е8t%uߍ}hգj|ejܧrE3eH\Zl{ׅhlY. m(U5etbemon-1.3.6/.git/objects/bf/0000755000000000000000000000000014001503033012706 5ustar etbemon-1.3.6/.git/objects/bf/157a8f53bf9eee483860f8638a3c621cea597c0000444000000000000000000000026013604573566020117 0ustar xM 0]o/A7n$(.go(OӣPzSK`6@QHK ji.}ͮW;mЦ(Sjp\$A)dn\.KG8g,+xo(O[$ral9Gdmhz;\ǹN _NBetbemon-1.3.6/.git/objects/bf/e5912d7b086c40dc8ecb18823f51eacc8e36c20000444000000000000000000000141514001503033020201 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3B(GaVvqlrNfj^I1ó k_>v 1ٻ&_HIMLcvnI5KG꬚4 ?3nSXv8!%@YelrRbwdy $ 9r,Ԋ 9ɉ9ۿ1oKkXTiX^WO}Dz]_ryVm+8dqke: z>U)r:`|>@% .3rVܵMB.%pvLl鄧oCNlq^v`/TEe10>R: ., dZ(֝C==Ô>wz3ԑIcnL|t (` "#>  p, }aeg!ZrvIKڂRHoab??N*Y V',!Ny쎀&T`pDHv==+ў]y@k{/.>68],a+oRշ=C!oQ(+v]fU:F[FtSN]t}jҗ>_ipJJ&vˡ6|W{![W> } 'f h-zp39|38O2}? DK%Vvw7ЮKm{;wM]v_>n 5AKf~H >(jaetbemon-1.3.6/.git/objects/c0/56baed2021c98f6e25baf371991ee08183bb980000444000000000000000000000025313455034667020013 0ustar xK0)z0-ɭa`n ##s8Y ^r`F<&0Dv%D{oB1%hũ<;8qɸqD!d"3+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3fS7SkԞ9j*.&d3<`JmSkrUԤ<kN-MrEBw[ MO=6eW"Z ˟_P#? PՅz#7?sלĵ!zWcހZD3PV7'?91b?H8 a^$],h *|Q*ӽVZ[_@c R.g ǭ|&T7fV00Xroi[Gr6 CTh1_ⲥq 9y۵PHapk2')ck+B!*JK2s%A{Bԓ9-IRetbemon-1.3.6/.git/objects/c0/dc9eb01cf46a1daa71d33090ea01371b1e9c600000444000000000000000000000022013325227421020061 0ustar x+)JMU04`040031QMNMIez(;rf.+UTRVSZi`qeSG'*r)ƢN/oO,aj_~U[0 z/쿯".CBetbemon-1.3.6/.git/objects/c1/0000755000000000000000000000000014173222513012635 5ustar etbemon-1.3.6/.git/objects/c1/4e84c78e3c3258ee606b09efda8ecbef02c0f20000444000000000000000000000341513733114071020277 0ustar xWksFg1E%dKJ)&cǔb)dI]e;)<F ftzvRd'_( Ȯ`ڐ՜z#ٹwIFVh_W9sJeYlM^6&wc[SRWDVYzpzv+LNowghBWbzzf2.^+ FSDz*k'pfG,/cD:+t*\Z9wuh]~xN ]%h^rþG' w1!Lt=@ȍtCx`̙m^k[Xw?v˴;~5 vGGTfܥ AuQo萃I6Oʥy Š L%|+ ZgQ.Gm5N&bL|--b@ n DQ|j*1mQCW`nhÏ}{jc3 טGoFg5hS[ϝT[cmCD;W]րz0D<>E{;+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3B(GaVvqlrNfj^I1ó k_>v 1ٻ&_HIMLcجx%ScJ3uf΀*Of6>۔+_{ljI2./1GU;K봥VnFn~C9kC>\Ǹ#"fnN~rb0,Z6OҞ9KrնM,᪀I߲HڻS.۪meW\p9[8nL3Aק*EN5er{[NJ?Z}I@{؎i-cȉ- خ셪,G [CA܅+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35ݢ{%\\q7tW)Iy [x^RQosIϸwҧ@'3<t,/<O%D6$ĵwџ8\^u91 ߂i>?vP[Owmj4PO]23yGMϘ(b1G4@ Rxe|Xbkiv v8 er{[NJ?Z}IF@{؎i-cȉ- خ셨(-)f QOX&ZWdx4betbemon-1.3.6/.git/objects/c3/0000755000000000000000000000000014001503047012631 5ustar etbemon-1.3.6/.git/objects/c3/01c1b44c6a02e13a1340d8658ebe0a9e476a780000444000000000000000000000127613455620411017676 0ustar xTn0|l-vR7F[$@PA%J"@I%1{vMC ]gCn͐ ꎗP%dR FE cpɭ4ZI"c)\Tl$בgL^,`i;L &|1ocZE\4!ĕ>v0ٱ1@2\8N%I2ec[S[< f?dIH/ʄ!{MlakVʚӘQH I3u{[Oرc].uNV@e9aoHΣ Ks4rkʁɠ0;Z8EPH VQmnO 7da5[^QX AfM ‚:/J]e .2!!D/Kajʕ-֖gP;*Lq1>K5Kk?梨z5U`>UUlR{|JdZY!hԉܑh/V>@a~$ʇ#}I5Ѫu,;Aܡ9n@*|6 2txbGg|WcRaFӫX{Wᡙ]z1v 4wJSmǜz~աfny]oYĢK}yěj;ޭ?{O~Z|SͰkL ^0>[=s}etbemon-1.3.6/.git/objects/c3/78b23cc7ebb2740694e8efc26fd3fbe05f88840000444000000000000000000000030014001503047020142 0ustar xKj0D)z7XB 9An ZVIfr(գxPhD -Ao2'L{mʢ(dcQ#6d4M(ӢB\\BNG2YJ6gm__*%oR{3I1rLxzW8#='*x@Y7T)`Yetbemon-1.3.6/.git/objects/c3/a1a4c6931a558f8bf568f01943dec936bd9ea40000444000000000000000000000027513212010216020056 0ustar x[J1E*_ ;\@uӝ&u~ n*v ɹG/!$漮rE"dw@1RF'/*ghTx/C+\|N?v[ZD3)ặ,P2?z m8JvXetbemon-1.3.6/.git/objects/c3/a6e5405cfe6ffacaad96c1d3077e9caf91bea30000444000000000000000000000120614001502275020503 0ustar x+)JMU07d040031Qs fi^5W~G$0lgWs jcU0n)id)m3o" WRPYQ saÙE!^W6A饤%0t\(zysƶV+k?˯@VYT0sI7#c$}&ϋZ恬&?!-F!Wi\4(NFRZ[Z}ER>)7I]f^qIbNY3~s1;i|XIYNf^v1Òb "ղ]Gl_V9IQA~q <:6/]27ī1fQTƈ@VU 6JJUQ`@P͋l9d hV^ jvT>"sSSRP0MZؚIe6e3jfb fͭljsh2?J7C)O,I`i]}W鑮i -etbemon-1.3.6/.git/objects/c3/dbe135272cfdeaceabb2869c2d5cc9e765c7a10000444000000000000000000000156713604575712020452 0ustar xUMo8Yb0(frXlke (P`Q,l&Jrd=$xUܾggu\i#+uũVh0UmI?l8zȯ_n_] ϟõIL`5cQhduHGKpimP%dH>o:EkI !/jks 5@8UZ%-ɓH潭L+}+rltU#ZL tvjm1}wCձ3d >Ps@Xj6eL_/wޤ׆fAk 7DH8:-P:H5x&5ܷfKұw-֐NM,̚M_y5Kw3in(,AE,3IV/@6QZK׉rX$~g':ӿ>N?]2˻UOi"4 9羼\ߒ.kN;ԛ_8u@8^*ꊱ9bB*s,ZbG8c@. ZvUaFsn&m§1%stNLJ\ QGZҊ"v0e#axu 󘇓]x .9ij^e [|tӆ"n-3$-{qLy`A7wtAG=5(:x+T{v^78 yvFf6ܬC|ԩc`VqoȈ܅ߎ>aF8wN}E|etbemon-1.3.6/.git/objects/c4/0000755000000000000000000000000014111113236012631 5ustar etbemon-1.3.6/.git/objects/c4/1dca7e58ea0e6756f8d15996bf5fd424efc6f10000444000000000000000000000133513212007027020235 0ustar x+)JMU07d040031Qs fi^5W~>wu`~V-:֖0E% [Y'./1Cǡئpy%E9 Nz/\Uƨ`)Vʢ˄,Ҩ7ARK +9LWˇ`Uƙ*F饤%0D|ZQk_:V(AVYT ;ݲѕ7&.YM~r1CꚛN]Zv?HjR+s rRwH \7G:E2f",Ka8!j5aš߶_k~zT:U%99 &,/W^2+/ixc$e9y K%T&vU~ZP[$E%y% {;?b5}Ng+eoW}ac>͢o(lX*"ϛ?rUЬʽZxti7}& `hy_{M/\+e,4T?|p~Vt F@yt-y:C@Rauў;sIwK\Gl@]#etbemon-1.3.6/.git/objects/c4/31491c2284a7d384f411f7d1f8261abed98ea00000444000000000000000000000141513304475530017715 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTPv.hMvZh)TIIjnANbI*Cպz SD2dǰ7!aMw!9y% lcN!*RR2vmu0jkɂ+8j*OfL .s|Ȯb{K % 5].Sf/g橫ۡcT)㕙OlufnN~rb0,*4Mo᪀#;,5|C@c Rxe|Xbkiv vQZTP2c9˽-n>]$b QQ\ g=lǴ˖Nx1l BUT# B@}5c (-)f QOX&ZWdxk Qetbemon-1.3.6/.git/objects/c4/8fbf6a60992c87d39953ae9480431fcff10a8d0000444000000000000000000000163513767534550020044 0ustar x}TkoJF¹)HW!WU4/<*^+ֻfwvfv )=;3gF <s~\o+EPjڙ{>aVUf 8TU;ͷGSX0!C8)ePˌi8ysv#\InfR+ V%26Ahj[v|˓ZXH ~2%ulw.fhMmajH [~ ckDj@Ism%U\+sBf5K, - b3'\JX׫WeX$cEA 3db}Tasgs9 n:& 8g8'GG0`:y;G ۣӱx1wP*Jsi!P¡!/FG.mpB*d"Sb~HoRI'V 5 D>{j<W8)a)pSW1|C ? 8G.^r2& |"1xao_Rk^rS,&%"'&LJdj?N6ֳak *"c_~8=[FabL=w}2& ÿ.ƾ.HBPݽZt*a^NJL/{T#  _jqL}$ zEdZ-:;(AONn1<^TtԇD'Ĺ*+ L|o{F{N݆$GAwpԇ=114IHZh:^e p6G_̷.I)7!$) w7%xKw8 R~Ojkd1tnH\?أCd.Io~;;6DHetbemon-1.3.6/.git/objects/c4/abc367da965d1580ab462797ca8194b5c92b3e0000444000000000000000000000216114173220144017776 0ustar xmUaO8s!mlw+,\nc:QV{cpB$ϼϼgO|B;lW'JDž,2-UbLڼNAA&dsJR<ЗK2|%YU)Q 0-|RQR,z`Ń4$2%%Bi^Bd!O$|aGP24Sq^,K5O-]U,u]Ktb0SD͖$m((UNQ j1a5y);tzD]hYԩT6Bbjԡ06OoZR<%l 9zRYi-BK#c5gQ,Pl8̄ʰu'_wcx2coe.tvtA^asG Uf-z8FWI=GPmҶAgHRF(@Rw|]F:N}:{ngWN-{*R o+}u L#k+$)3=/BB$ ̚vJa,b:@z1)8[G53I/ ޙ-:1R=x k jq;6MwkZ!iyg8^A&ߢ8Q 6yVouŖzš53I8Z)c#_nkB`6quNm ,5<0~n\-I hkQdD2O}/Lz) eز Z>J#9vi#F< jZo院IwX$6)*:o$֟9z;t_ρz3C:uȕ^3DA>a$7#G)l GNTit'pm,ccS#82 **mH=0s((V:Q;s8k)p: n7_wq-z qP Qˌ1r'w3m ot x$cЛc Tӄ&+)t)Hq0Y"#T&V()>؄h2H4 d[`L'rXP"0R14 g=m5˵>E|ƷNk~ȃ\=+iJh l#c_ѱitEXI2q,rpLqصpbsy3G\BK]%"Ck4蚠կ7=Z؎Βan56^^Ǫxvi\oi 4-8Cy7 Mb23Orgz j S9B/jy`i-ȉδ!xhtl~߿cTv۬l ;͠1e9b4he,6NB bk ܋Gdym%6ލsO&L eEqsa{Ol/ܔ怛S\/Uy̹S, :Z䅄 hSaqfMVB9<3gqW H ?uH ]{Jd>C 4Ș7LyѫMPk| ^iݮl1\Qyie"Rr@Tn˗ db&Gh3 xE7 D2ZYڹt<oNώe&p,SL},yluNQ6yD!}< PO㌳Zk0U )E%QF 5IȒ89,p8Я n2/g&pQtywF "#v8.x.Uq0ÔΖja@i1ӿBDdF:ՋyC0s4$pq_Ud !$£NzP_9 hz pBF d=<580S{_/S6 oc(X46KVe!$zOnK vr!dsb/ 9MYJo⿔T@'p&֧s_Rr:VDN "dB%/\ ƚ,di۲|9kDw)93QtGUM5,_ˠrX7bc$DbVF)Vm  xm(0Mg%jȫUO%h옠op.v\|ȆOIpHvNsd)5`@z@8 E vb4Zqh_~W=SCن~AIx?U X/ N'vcGs*eAq{0-ͯF`V!s} )`u*u.] ? "pċ"㳈v qrHz<'ZU/>m]mAGJ}>nmdFpZiNeTS͊:oc ^e 49SF %"fhd-oֵۢ֘2BfJ5@(8&֗MK<2=0L%d' ?OFB7\L8SM(WqVn逎lWuֆÔ.&7@ ~Q ? 0!шJ`cR7Z]ڍ9t/f'_]c'-<]7.e tۗj[^dt40a!'w^700L+SOhsD.Ĉp {Ry{齄MGO:yVppv|i'Iu@MC~ݶ"Ja39 Z?UP.5j5Z`*la3b\lDt{$|^b@*;WKIc빹En,^ţ< j}{\F+Og}eo I!8wHulCh/D7[;hg_, ph ebx^ohi9?ўpO<`PXBnYQuGZL$KS@FHPXFȓ=o!}QfhVU!V%3@Ij# q>~ xc)Dw2AccD}(C)/>#쥲pZ;s(d(W7w; PN%0"c^BQVƏ=Rpz^V ؗ-3b ^2V>o !*$ӏݨ| FRR ?Ln2n][,Ld <⋻Ee҄ )Ćcb+@V|`Ȉ!B!y=C]}ˆB5ᰅgxwa:Dz8INO= ?x~)?]]X Ym_pNpwP_`(^300GMÁ RfnE0'D.'!DueoVS5*rQ񓘣~4lD/m_ PF3;s>?p<V8%P-7מZ>;9 3idme <4U3\hg з:x zͯw}ίx G׬#Adg^^T=HG&`uˈAsu,8&5%s!K3` 2L5񙔇C1Z6!빭VҾ#fQEip6PøD !]+3gF޶E1bi#f(xýG ,Ed0b(&fVuNySEN+v'y<8$4"5q鞪ՒG*z*dSi;U.3d[c1@#e] 4\eQboT߿r7@(YM Օ9Yn ;l]W0x [3Ӷ])E74JncV_% *F*Hϔf,is,ts3hZ}EFt\mrWy4V7`c6}b l>[`ƝvQI1p uhџkKf絮;xqlFKaIf6xwfb^nVy>AֹTfX4^]DNN &p(2[VGNkÏ-%)au{[Hy48F艖u S=,p9A(s \dWDT ^_GpqK$ ~q(Xa%j@䥦0A,M湦vP(ؑ7J@5oCxiJpzZ v""ېꘊS63)"o3B$kcV;NMDuϥ3&pN4][U].‘b/+kl:h]BdLJ_QIDa^Ɲc@2#Ӡ<,Ά3B?l@:pܛ'Ǻt %be)pFNjTl@m5iglHSKsSTx\zͻEහד+ ZTg -۵cxBU3,Bذ =P[ĿorW$;J-*T$ I.MO+, PtI^s͇3^zVQvplt.Ap6Wj Y` ZXsUW%_;D!# q\j68*t;KsȤ2VUhtvsM?zY;!mY\ vybI ʧKQZ~ʠ؍U'xEjn?|łal [+;~Tn`3\⎯^]ԯP @Wcيj8;oM+n偸{&2HlJ*=VYwȪT*X =/co\F҇Ӈ-ˈxQ\ xXh蕡z6YNC-5FS[iC5rQӯpp qb?-~XUPWkuX9r!,2pkGZpf@ԯ>?bBw½Co{Hø˸T6hXK~a :h[f⧰#WUI *Z9Ijmസ7XPZ y-A3 PRY2E/^L~[ڮN>YT.cowX5KN闧NNEnلPc-;Bb.w`s+H*Ѿy^ZsbrKX0L%zvH=j.0 Z*rn!5! ܆OaИӕ@HQ7|ʣeK{uv<ɗ})x˗ Zk"є6 YB(#b Q?papjJ[}g zŕhMMm=Z͝d7|?` oKmuAssJ/Nmn@A98~>"xuBHS^7tNw_SQq~h5hͲ=ͨSP d4M\qR^eOF״'C¶Ӿ gFQ} ugabܙ,F+d놡w=f2=i*~ JWпp#R:_߰³/LZũc)V (鑆߲6Q**n+2LP~_l DH" 9LpDрHj ĎT{eamVriʺF o+*0_s$&q:ZWR_\%s:v X[v%^1(;QD>]YQWYpXh7uOIj 9 =gl,`y!9I ye巋/}! 7548EK qP*Ad̅b΅no]"3U9(+;IL'{Ov 8[[> a}^⭇3M4smwT܀ˤJ%z)w~)$r :?P[!da@S@BMeuBzudWXAícoPt#s]J[iVFl*w8JoQBu&#g#}`!Ū}f$.(: e6' vM@9|l?n0l5;mfvà2?DIk,.a`PGEa'3e+wԫX0?]$',MYCQ$I3Wv~J W\ 픠 2E+ES` 2AO 뒉RÏ>]WbFJJ7S5@m O uyxDa_V`up05 ˞][HnB6 FjtkpִNd` y!b690.35GS8J ^]eħTMvW@Q@{󓻙f:'CMo@Se .Q]Ƕ$сN:Y:ę[Һ&Ϥ$LN&AeQg#[lk;pOjDx0a9 3Iܗ+L&&X& OuGdob\.Jw60TU>l@|B`WW>">T|2@r؅( ީK5בB4݀MAda/PY%ލIx#J?W*iG_pO[C-6*j5[3)=No%WgUZ;F-Fζ>-1y:ϋ`y~ӯg CUkyk]`}^Q^snNAvmzRuׁoH/_&}7Yaqu8%ZFN ӛH7 'iԶ+QA$±m,t^PGԊa˲kO Pd nJVT+vl]@=LpK`=DʶO]3DѬ\1VYS"pƳd`u:(v#IIQ8n-%1D|;vFR,`=>)Q̌ ъ6mAϮ1G4'v8GDC:"L+h ִWdQڻ擐OE4FwCLhOUD֏&<4FnUxv9@G*43)젣\ydZ4DRK,"R f $uxJ{kip\e9{6GT!:BGf삸%zN`wME}E/~]/ÁכuUӂ @ U61 *[#rmG|)t!. ?X Hj%Od z5>eb)*" ,R }OG3Aw70zNg=TeA쭀\A^(mDz.vLF30I{]^1ZU7jʇXֳvf_QF *Af*f[wGhc` УBm#G.֪ Exk %qur͠{?,|7lv onm (H#lҎ@4ݺ'Xq!*uRZF/#U<,V*r ˚cR\0bM3G4^f4fq _YfpW37x]P/wBxЕ…dNgw-D~#L|{j^ECև8X}\Lg/80jȦl95f^E9yn6u ~5W(b[X^TLPA@C6§[Bj `0o#`qʹ˃xawGR~vEH# 4@\̈́lw?_W DUMI$)@r=*$;l>p֚ ˬ N9.?vG-Gax%׃/ .qԢdD` kcQ-=>ʵF߫zT`t@㹩v/) c p~TTq7Ō W@^bH;G(Е8tƒ:w+l-]zT-Lt- kXރxb.DcN6TTUQetbemon-1.3.6/.git/objects/c5/0000755000000000000000000000000014200452005012631 5ustar etbemon-1.3.6/.git/objects/c5/28b4fd0a1812b621f3477ceb2ff18ca2bc58a00000444000000000000000000000141514200452005020101 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3E+҆J?D޷ 1D69'35ܵ/Pj;]˯BT&e&1&{ȸ#49Y3kA'3U[|{mG=D6(+vcM@\[*Tn z#7?sלĵ!zWcހZD3PV7'?91WxM٘ݰ%*j3oZ%}*k&1~z~sS7: p1z t>|}Rt|P3J+ J\f,g4ۭk\!*K /q O8⼀Z^b`|05tz]XȔyL%9 ÿ=!ɜ$Y Wetbemon-1.3.6/.git/objects/c5/62a1856bb224abb6386aa65d987d9431ac5bf60000444000000000000000000000050413604577005020001 0ustar xR]O0u&am`LHD1Ү%khWv ޮ /{n==b.1κqUY 0\.|Je1/ޖ /#4!Y #S <:y0B!@Ẇ\ykUU`p:<,`JM/fOIԦ%GY |Ijख़^nj1!;#yq]8U&" r)T7K'3RHݛ PAwDwv+͍z[Z;!D(NL~h/Ց>etbemon-1.3.6/.git/objects/c6/0000755000000000000000000000000013767545131012656 5ustar etbemon-1.3.6/.git/objects/c6/02ac4fcbaef530ce8b616ad5bb19b032d508370000444000000000000000000000141513325263254020172 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTPv.hMvZh)TIIjnANbI*Cպz SD2dpμ 2_dW^6\ZnND69'35ܵ/Pj;]˯BT&e&1T\(Dt03P ie8[qoD6$e{hOz22Ib"#IdQetbemon-1.3.6/.git/objects/c6/1da090b5d7e9d83698cc66f0cd2df607297a290000444000000000000000000000024313767545131020030 0ustar xA 0={J6v?ؤ[4VaTr5pv¤,'AfMH0Γw8G(%U <N^}bd)(Y۵Tˢ]+O]*8ر{Dk&˶j.o|[|KAetbemon-1.3.6/.git/objects/c6/28bdf15a5a7ca83fbc2c01f2c39637736244840000444000000000000000000000025313212011077017703 0ustar x[ 0E*_(4OAw3,MISou9\TylڜZe˙FS=t69[BK&2{=Qv֑D-=K)`L}qoRaط ..Qh1ZY))q0sy3`\lk/+Netbemon-1.3.6/.git/objects/c6/5949adfc1f5c0f9cd6e3aa8d28b9d3174b1ae40000444000000000000000000000025313212007434020275 0ustar xA 0E]d2MDnA:bk$MF?e v% |z$k c M[El>ˣ@LN(Q| !:j#C(h1em* t 3i9(2V[WUQ_Z7Xc;3R”NsOUetbemon-1.3.6/.git/objects/c6/94d2caa0a041c3cb6fa30df4779146b028a6a60000444000000000000000000000100613212007424020015 0ustar x+)JMU032g040075Uc}SIt^򙆲GߚgL:D!$C/9pؗ)dv$Jp *IH-Iz}\w)^úPSMU W7lpu;)mk+//Jf>POn2sn;j"T1 K<6t 7^y_}uLnN)fgrV&{,V j٭O_޽k<޵b>ݞPEy% ^|-ћJ/Ww,$  ݺ$$]+wefCD-&܂dZas3WT,|Tt1רVBI(+"S\wkfgZ WrddMUJjkS_?~[a*suAY43?/̽a5-ǝ]scݪ9R*u3a逕2 cnox[etbemon-1.3.6/.git/objects/c6/c61c6a17a18abbad1386ac83ccd289857e0a790000444000000000000000000000130113212007424020120 0ustar x+)JMU01d040031Qs fi^5W~>wu`~V-:֖0E% [Y'./1Cǡئpy%E9 Nz/\Uƨ`)Vʢ˄,Ҩ7A (7?O/%5-4!ӊ\M4й&D ̢b閍1$ujR)7I]f^f^ ñ Qi 2]c{ ס*.Ia0a L~B\\yqH#).fX5X,AZ6蜭k*")*/.+.a#ݱ]<[s:M]Q.CxC ٍoEUl{x dUE`êTU}޼ϖCʀfU{nKK531`BH o{t̵^j@cMMJA/-wku?8zLb4NܜMlm7Ͼ|3 ! KfZ8gz}UzkoQetbemon-1.3.6/.git/objects/c7/0000755000000000000000000000000013775160026012652 5ustar etbemon-1.3.6/.git/objects/c7/6d07382fff4ad265bbeb812e19c611116b93390000444000000000000000000000132613212012067017707 0ustar x+)JMU0`040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35ݢ{%\\q7tW)Iy [x^RQosIϸwҧ@'3<t,/<O%D6$e{\zSLh+.HMf9pb宝˫;) jFiPA ˌ,f~ wm1DEq 0$%.[:ǐ[]+ QQZS0/9۝iLS?}etbemon-1.3.6/.git/objects/c7/943fec996641a60e09f83cff2b1bee720146970000444000000000000000000000141713604546650017752 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d~mmL?2< lrNfj^I1ó k_>v 1ٻ&_HIMLc0˽{`gogdf߯*dj{oMb>Ȧ$3̽&Afwlg~<{ҰYNry⋄A4eussa'({Y$<臫?n$LhNJeFY Ch^qAj2/ρW,w\^5NNP3J+ J\f,g4ۭk\!*K /q O8⼀Z^b`|05tz]XȔyL%9 ÿ=!ɜ$Y '[etbemon-1.3.6/.git/objects/c7/ef1f733818c922d82a134761f591f8b51b2c900000444000000000000000000000141513764536707017606 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3fS7SkԞ9j*.&d3<`JmSkrUԤ<,Ytt =~zdj{oMb>Ȧ$33y^N[j[Po1t6P5~U)r:`|>@% .3rVܵMB.%pvLl鄧oCNlq^v`/TEe10>R: ., dZIf}tOyQ<'3E(䛿*-ܙiHjR+s rRwH \7G:E2f"+.Ia=W2`oN>&u'm#).fX5X,AZ6蜭k*")*/.ǐ{~rO=ޣ\x6,ȪRUI2 *R1y-Qͪܫ1Am_Nj/}TdnjPT I [7f,vF5L @ڬsRMzm^&pC[f5% 3aOB=u[*=5oT*etbemon-1.3.6/.git/objects/c8/0000755000000000000000000000000013462023003012635 5ustar etbemon-1.3.6/.git/objects/c8/41c87bdec28a4c96587cf2fd3a0a220bfc195a0000444000000000000000000000120413325231224020201 0ustar x+)JMU07d040031Qs fi^5W~/jbW|W^Es];Ӡ8IMjEbnANj1I+&?<ߓHHL$uy%99 s4INVwZo~s}$e9y K%T&vU~ZP[$E% 6fvڃ/cQªF7%_4uE /lg76YU13U RUeX#Tby?[*UWkc⿺.-_T ϦJo;Q}+6^ E&@Mm9)̦v=6/It3ԚĒ E{0':-qF(etbemon-1.3.6/.git/objects/c8/96d5b94b943a445f4a7278400064b7917e9a1e0000444000000000000000000000025313462023003017504 0ustar x[j1 <{zF!;d gfusH[>UO-O9ePOn2sn;j(de0<_a{:JUg]`O`ЄC YEz&HZQJE39+=[o݃PuͭO_޽k<޵b>ݞPEy% ^|-ћJ/Ww,$  ݺ$$]+wefCD-&܂dZas3WT,|Tt1רVBI(+"S\wkfgZ WrddMUJjkS_?~[a*suAY43?/̽a5-ǝ]scݪ9R*u3a 2 cnox[S Wetbemon-1.3.6/.git/objects/c9/0000755000000000000000000000000014057341606012653 5ustar etbemon-1.3.6/.git/objects/c9/0c6735aeaa2f3a92b2ff1413f162f081c8aa280000444000000000000000000000030613276746471020052 0ustar xKj0D)z?`>U6HNЖ[IJ>Q *ŃSO0[4vA"H]0[qQA`y٫ծ(_4R^rpDtNPo{ *|<ޠʥ~BGҦϽ"~Yetbemon-1.3.6/.git/objects/c9/35353b6dd72ff2cac32e93b58075651e60918a0000444000000000000000000002754614057341606017665 0ustar xrɱo?E+/8Q=舒}&$h@}}}}Ս8v!ꪼYyh.t4z4,'"9tҿ8d~weXp} y !l&uѲ?-" i>y4p|Z?,6`pV[jiXiϳp6^4}gfyXh0-2M8/Q9f^&߾:|xl6/B2&6['i~CZ-|Xy:W+|_ޟNgqV ^k4FwD.N$W)DdF"Ԡ "i*$ a6>Ns`rL 3˅%9{o2$y_t>Xt—c\·HQSmL L0&y:ɳF'F!}h& Cx7UxNm) U2&o+2R.2N8]nHsG|'P=5}| y3rps΢+겐\4LHy Gjx«,f^-8#YaM%`?*x&V ,+ P" Ox" @x\teE&-Jd{"jc*R:.Y VuNe\&$SDNp.XLje6G4G2r-nPW†a/!ؿ(uX#va`1ODK xH>&fK Ed!]8HmJHȌ=~Y+'ɑ<[-o: eҭʟU8_/z4't] r._%'&L9"&U%/>yS_̓x=,ϗ@d=1}P6ΗrwB(+fxiÈ 6)f~*V|3.sY;k}oHȣ"xT"P枑C(%][:peDWX(AvqMA;zQY]! B{yjuPoڍAi7jWq#te{gY!9{q68,mw߮#ÂdI<O|x(FK2tjF,y^y7 NL%Wc9/jK\g X+jRRa#JQ̭cEQBUC:f=F'[,KIS<7om&kaHa0QI/sM(AJj!y῵ںU}µf\A>'s}gGln%W&KfU ƅ}s^!E&]VP]T޽!rye+\DX*j'tcz B7ˋ!1*Abnѝ#YF,OnT̎Xjj~Β=Z+i(#.XQzdž @$N])0JOtb<0% ymA:w(/rRp R؜8$<R+CvrYF>"2xjwO1ύꬻӬ5~h5{f|ew;?%}bQ #p9AK"Tz=Ou|cwzw:+5%jV4cf8(xM/(l0Xȷo웹sX7zcˤeX礢&Q j,ړqX]=w|D,s ֦LEک7J`5%h^cL++Mh\q^}hr-mֆcH5UGzWh`V#˰+4jf(m~ obZq$2/ʬcs[0FY009LA+hc_-BWªx8OCVB[: [Jٲ.)7Śm g?32ľlFfREŸowJ K؞ҒK>"v]x$K_?ܛBy>XB-uI7-e[@mzlZ0=SNK5s! tw &/m,Z9Um p(sEN@W5ˀ^ "Qi9y Kۭ2x2rҿGVo6v9*qt|# >}x>wd:{>y{qzs|΃[lT!}&ű3"hʕĄ-"hL^dHD*K|&Tv>nCSzįm< ,\c1ɜ`blC@-[?bNP*KDzNJd_7`T]g}y-Gk1ْ𮐅H㰸qKn'."Oދf+4"#`-󱵟78-"\ +m ltf65+oBAi+yXn;c |$ yX)me:FNSQ.yfXpS:at D^5h3kv{][ٚuL 3g8D}ggQbFI_crvzE:B:nIW=s )tpʯNjlڷf96_y_Jb+iѫ^TTP1zb)v5;L]Db+)vR4-)O1ْ!`R^+UR# bnA+R W=.9d00YXs %Ϲw"~8-?0+e|p liy9N, nؿd#E6h4aMJ],ДH[0`+lp;fh ?(I7/5[>Sj)Gl4|m)Gcq'LA&9ž^,e|l2 r);1$l93%X*^ii3(ɭX)?a(zJl!5j{p>O&S_`z{{;.e Ewǩʦ\:~6QICoksq/6})[x`vuYsGOqT-J_ ](~G;4Yׅ8Ǐ7xFսb? ؔ՚AIc w"Ig/3^|/ݳXEsv.IFA.t36pV\vnG,Ա%o ҡT$xDVT_=U83B.(Mn f"잆0SZv@\Z{z˽~>jP۱9Sem9wiEgq,o6.`lKqV9ug;] YD9=v}U5ï?yֿ8cʇPԏ0Z-nXN[M}YiYdYfzrq Q,*cdv;rb]qJhIYU2-"؈A;^0=@y9(x]] 6d\)k!X[H m€vj(9( q"Eȟ#,)3 }sy䥝3 qNXf?$Q:)VF,ZVDzM%n(ȭiegN9]Oxtk-tQ]+C6?FmVm!羐|ƕcKhņLvkDÊɕֽr1&${-/? £{36pt3-jiM5 Z%=.RHFMR!ۘvZ#cpYiS\*72(@mjWXP*D-qѬ:4pm[nLG 0F'M[#Խ!mԃDxՒؓϛRj ȮUa*HQӗ3)"f;V\-$7yw7M?x,>h>XvL?Fgy5*Wt]يː|ZɹFG~{A1qEc[r%?ӆMHF @27z :ΚZ{똢Gն8M (]@3 Os]W?eP&u!5z l_L8}bfQve[U>p~ r oU a3"Wp5ZuF+h" ]psu9u*꟧tPؔujqU.;>U*TX_~ C9n+$- ?OA* ^7kM9iwu׭lw:ըhQ}D:bS8W#6~İϱ@ڻs&Q?Sܯ*KKLzY-.Ի|wHV }\*&qO0K~|cuٶ[I,NQG+cWwU uE]Woh7!%r`yiI~~}:>^\?l7Tmg߬k&Xcx5O S r/wp{\[F-BX>Ѳaĺ|卝[IjL݈[kC6vYVSuˏa:1ɿ?5dfC+"][!Gx]nN?nM (y)wxNK}Ewew~Sj%Arͷ[,h[#+h6"6'oI6 NFKPĺ܊ֱ'Iyo͝W@>{e7H _] <~Ee4"ܛZP?`oބOV$p/4*ç1>>eW.Cx^Aϸ_Vtb|\E&=XHUb[b fǂi34A]u<Ɨv6-9k( ߫>8Dd ,i2>R7R|+.c))5>ĩʛߐ/=?3ojAg Μ2ZwQhR7BDq<вVxyT^*ړHz\LB1?1 jNX ~Ա~7=t[8ZUʍ܄Mv]X`W:v`Xͨ, Ӹk/8lX(d;xt@>;56+^K_7:+cӉrzikxg/|GؠW|wUp+fM·^>k۶7C"}D)qb9?y|301o]ᱎ}ODtGvX@#Όh*~┨A90/ge 6٭r~x\kmDZp21i _%Exj5kO Gq~3@)BT|j6:甊AGq^͎ QyQG29*R;uyNK7 Q1jUN5bcIo@Ÿle9s28X}1B5;;֊*V{?m< d`oᘍ=̆{NĆn>l 9hiJ8d}c~rRhZm4 9f[twehk&#ݒ,{䱦Js:I-X{ dhu64inrJ`e^YQ17ep9wjy{1޻N!uCt(LO8slk_VGb駓}jK785QݺZ ŕFy:jHvSj!t[m^NRU%@ RݓB}q)n XVیMC~ַ+M?޵gWX'RF ʮr LJ _)qY(KG 2>~ [|{lBŖBH,cak\vj`ÃhcT#^4!Ê+رnH>#GEg"UNr(Qz!PtI6My|@M@l7i3:jP{]ںM4KeWşs=CNFfp Ӂ b&|li{F6 [p9}_57)N4v^iÚ$$*߆W~[ښƪruߙ, ބ@F-Ab:T4BWb5 v ʶbO9}V:|$u -e4ѩM\!H:ٷ-m2xCmḂK`Js^u JBv{ߍ*sMU9.ѣ@;S3-uq~f4Kju GJXRf-CM۱y: ۂY/wM޼{ma٫lDfT' /9ObN b9L/:GcK⿟iPAʊ_ NjNhY20.n<2?.C4˪ȅX,A钜p /ELTRnm[v'^-#fX cL/ܐaMJ] Mk|"Zay)X?+lnڭ#mɷM|K ~9 OVlI;ɶHعLhYU>?~m/v'~V&y=L3jl?-:7"jņv^xJ8aJ;-x-O:Gˆ x|8IGIN:w7i;*E({Iv@nOyXo^ B0)s̤b_f,^><9-.Y?@?P~6a) &*\^ Ki7U9jybI)]ur] vtik-~zA+ڦMNFPA{wqZ4 <>96cĐ/3ż..;S )Qb[t˪,MfTɊ>Hvkk3tف #*"*rlɺQUoEc;*LLGE},^ uLێYuMatPiT2 @$2I}@HڶXL%=.2]=;D3 :գKut0jMSг?:R,ږ]㧉f`t7pDP[n*lpԎlqW@=YU)v ҦWH c%8?I$DsQW)#hĕ;jV7gmͮuO :i a?`üY2{^܃=nD=*lvQ"9qU!xlCe#*[޾NvwL>ðs·.7ޓMܮ vF_I<%kn(0_cH)c2$(=O@+BYB1m|+5N;|Q P:V^XfفmX}MG}amN_ŷV9f'Q]v 88Dڌ,*Vʅ. }PWwxGT JB|!|i-+bȹ3Ea&+կK]^DwE;/n+QqUHGbdZ&oa^n%HUJ)%X+G^N^i~z_YOEA9ČW/%Yf类$_B Vi@)K"{8?|Q:taQY7jR$޵K/Eђ!ZEW_ep㡏ϊiU[F(|>UȐkFhW pO0oGS!`X7= ]#EW_`~ #=C 6"DB(7c\Q'87YN.6w #mwf?y#o``o~m:Vс J%zrPetbemon-1.3.6/.git/objects/c9/7a7f3d20c84e2cacc9306dd2efca40bd9d97580000444000000000000000000000060413767545115020320 0ustar x+)JMU00e040031QMNMIe8;?nN|:/wrq7jMMJҊr2KĿ2sIt#A KII-IMM,(HMK.(`uy&؟jRtW8t&0lK׹KVz|%u3Ҁ>).HLNpЯxQĻlNg: 8'3B$5z*nM|"zGx̴SXW*BWKYhh] Z*-@ ӷ+dr9{lڤPUŹE%%9pJ~yf) ?r槕%fƒAO債ySTU}x5 )^LON9]iE,ketbemon-1.3.6/.git/objects/c9/f3256c5eed1b5156251c4307e485880464d18c0000444000000000000000000000266413212011530017476 0ustar x}VoH__1%1 ͵%)TQ{|~o6$Bfg̛7фN0D ~aQL)-t85u, dhbZc%7 6cGG]e4W1ŮV C+$׊̜O$5HM"]#}⊥$PEbWL' P2Oah*/=@гlhj 3hO8[H$CJ&!Ƞ)ab s0"rnOLU& g) z6- jxӿ% #AėAf|5B+WÁl2]aK6od Qhi*3y@VBR&bǦ\17ϣ2ѯĆLDBjL-%Sf%PV¸sRal$r)jzUaUURk8 keIZ֠f'5ꭣ1BJ"Zl 9ej{P~iY#l%M mD أb$1aDA䁄@&"`*s1^ѕ >&_t\Ơ+\ .9a]FmS"0s)dIrqį)Z2zC"fSAsvz(h-i U$&> pC{FԹyϝs3zh[Y) B YР)F;M7ti@ F΀n]4\7ls{(>Beδ>Kr o:)~:=Z3kK)U'a ~>+q sz[ $ؒt WVh0QrX ;DfѨ6ojpi۟W@ X1^P(uo{?0UbzNmBi7O\~tGk` dK1P9 R)=P4CT#8gݳg.3܋X oAUWc*Aq(_ZlI8K.OzlBK,j<4^A3#f$C_n+<RbB(+;S_/׆ L>k _#^4gWOm|:vI>'g1P1Qī[PmK&db2gziaSw4@XSs/t+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3fS7SkԞ9j*.&d3<`JmSkrUԤȦ$33y^N[j[Po1t6P5~)ރ'}~~>"j./NoAh^qAj2lḵ2=_9f>Ԍ Ym9v+hA&!c`8a;K\t7!'8/`V) n ^q2e{yES(DEiIfN1üow>hOz22Ib"#zS etbemon-1.3.6/.git/objects/ca/c8f604f75130f3463b0ac4d39b1aed003c3e850000444000000000000000000000025713604577014020041 0ustar xKJ1]|߀ AL򘗹#eQ}&@OP(I⚰Trފ5-T-V2|h V"a쫋Rd.3U3_c|/.<%o@!FLh.q]Ϋ_oʹ5iuGis[Qetbemon-1.3.6/.git/objects/ca/d847fe91661a84eda019bd166ce2b35d4276f70000444000000000000000000000121013604600005020046 0ustar x+)JMU07d040031Qs fi^5W~r(u܂-,ӃjPwl^[`6a%KV΄+),L(a۹L芰"N/z+ԠrRRKsJ:.V9c ٕWjp +,*f$՛ұz>AE-@V\̐joʫhrgY#IH-I-f`Ѿ")p{R܃̼Ĝݳx%*fmcRw68q9y K%T&vU~ZP[$E% \O6^Y O@SW|vcEQ#>YUQ*ذ*)UUF5AE*f7/~92Y{6;&-R oMMJAp4iak&,Ψb&(@S5zN ]ϡdn`+ <$9auў;sIwK\Go. etbemon-1.3.6/.git/objects/ca/de366fa72c94d84e76147ca2325266a2585a1e0000444000000000000000000000266213700752540017726 0ustar xVioFg,Jֲc;*,[h$6!Җ͒:(~l̛c4US:>~wSݙʼ: #X-cseQE;(dʖv mECLP'ijTΔL@4XJeQ&5ICȲHI8EVܧ(d' )e4Z0qLfNI$"iKMf${cL1ZQ"P9[>YugqWQUAdIc+slx3ؚHhqaHS:S.G'1ڱQ| Oc:vt;O4x|I%Yx~k- K&>{t+\ K:83-,5=Z('-e1-i9Dp?y8V̐-]\(Q1MeLW29J-q1 R+` ](v鑐Xt/AJGyje%WUה˚FaltN,n:Dp[fEz=_܆Կ.VŽ(lJx (kP^Ptp5/dB7cӨ?gW1nǣyhX!(oDZ-4@LZD鎅b&_W]Rϝey?Kq`gy3 %hFiROXfa{txx:N(o|Lj0FЇ&5(:"Y P0<|zKaQIA0IɍXaZGKBcݤ͞<ߓ{r'dVg'g{*C$0ySc\TH-rMKIjYo5GR|MK|T6G 7Iܯ Fg\9+8`Nن kHn';ܻ뾭:cNlf 5){7JZmpEϟ\Pagޤlsn}9A5D]σn4:ge)fU}ޥVŒɯfMGdPy;^T\cKۃeA'x =TLk_t2Zci()S'U>-jMK {zm9 yf*MՃ ַ_ š`\ SנDM5hMmpe pCZ[$"ܬ#ԨXI;]ޘoNËSFq~Fџ$etbemon-1.3.6/.git/objects/cc/0000755000000000000000000000000014174476731012735 5ustar etbemon-1.3.6/.git/objects/cc/9a4ef7e600093f8039458a632a413cf07221de0000444000000000000000000000060413767513111017631 0ustar x+)JMU00e040031QMNMIe8;?nN|:/wrq7jMMJҊr2KĿ2sIt#A KII-IMM,(HMK.(`uy&؟jRtW8t&0lK׹KVz|%u3Ҁ>).HLNpЯxQĻlNg: 8'3B$5z*nM|"zGx̴SXW*BWKYhh] Z*-@ ӷ+dr9{lڤPUŹE%%9p˞k潺%Ӻ}LҒ ƶ? djoF.qpTDIE[6 YY͋OrR{ l$S$mEf*!2gIs|q[:\/\RK<_&`+\V/4竏62@:[\:o@@PJ;E f\M}IcDMB C4E狣BeT`PPvGVXzBdņ!\+n2$,]4I2ǻĒa]ep!J12)gQ!_KQ ufy($@0O:-uYF$"/g 4vA(g63%ݔ0ED .[KCdt+3ZI hqVww-}MGR+QZ#ZZK@(IVPڡ꾤t=/+H+Ԕʇ?5_Rj\4[BRQbce+8[՚L' YIa('vDV6g1"Cyzf7"o`K]6M-t ܹZQ; :t%rBy#Ɋ[>;b"tBeAR>^T+`?e8(w;aQ,%Q=>ܮɺדu5Y=a$:.[gUfl6_'}N~92lwi^/o3V }r][<"E"U{\{*Y㧓_y!: M^JA9zVp}4ف[vtDc.mh݅RԺ킾Q8$Y ~H9ɭȲubwcN~TO ]8(Wܽ&H7HcQ`7:IYF9<=L.U|κ*U0X#-cGzc}t&OCG4)rܘZ14ZnL 0 |.go`gRF?L$`~CލalX C`ScLwQdYF&ctL|ܧi @`ݏa`2% o.(Qez`هC[sۦ,C`4` a-8<::!>hMx3 2WGzr0&;A5)q]e1޶XG@Sb7a}7-YψW@:!3>"eNcIa2wv.x:v*HבNw1ǜV'V^.TTZ'e^F$vߍy$ I*?^^~b-Z 2 jHu-rCmO4Ib6:7onzpvz9qϺ'(&>0gWsB<s K|3R0 q !N&A?C BӍe#(IEpI-zk'aD,m!(yاgW;%j\͌|GHm]~(W]?D׾!{~wQ%9!.Q JHCaj˘1X[(TC"Z&5v0)4L$fpTb \?2\#U(^>ls/ދCh?Ú^'+<~n~a#@ cs@Z1.񌦘bj6 W)FMj?_p(%=?;*yͨ-wyo ƨ;PYh؛>Ae*nv.` # \C`E i`J`LFW9ڏctL>K0-=fE/|WpHe DVB}U`š :kki/m^ZӨ*L΅ /f' 9UfJ׬STd:02 b*<+9<3PΏ?kă܌vy 3QƹkxghI#qQ.W)ǃb yMd yx,G,'TZy?8Sn]}i0HrA+7]6ZZЭӌ$2Cg3e2k29a#k6C:_K/$î"&~qR.\ qjPDM^ ;/Ku%Co%(,Ϣ mαJk*(ŤǿOk;IP =]nE0֛=qgGRVNͺݨmU5l:mVNDQ s'|^6 V=3kXf3Omr DG6nN*r3TNHDH +?4ѕ)WRrHompר)K HoZnp5=>*o )Ci2l]櫘c I+\j)>[BtV4߂9f-D %B=ȶ~:\Q]<6rhi:)}Y}ew}靁[ժy(4_K:%N2&ȶX 7#LQu Cj exќ$nO3T :;C`j/8R6J_tEsTwkahy5S*w};} NJn3S J|:R6pSQ}Qro2W7dXާI&81㴘VpW#vKphoI ɽ :Y6NxokC  Gm ۂ\ y:=98,A0e۞_-cYjC<$ )*6;.v+D+?ˎr :z:P.C0h e=[_ {m{.;=j*$luY1Z`On- '8_ZvJ H*,;XMokt{#.6Em #%fd {NsrKj֔<蹒n 1DiËo6,_|Ysگ@],lw%*K^W46|2΋.&t*pa@.!K .}ƀO|Ñietbemon-1.3.6/.git/objects/ce/0000755000000000000000000000000013604576020012724 5ustar etbemon-1.3.6/.git/objects/ce/6b487922391b6b20f983f7425a190ec765f2770000444000000000000000000000037413276743241017534 0ustar xJ0])f%iF7"Ifj/K }z.*;hQIadRDz㤄Fń%G;5E/6:1jB&ՅZfLOI;1>ڇ Vk"[)ZVFp/6Rܴϧ/g B$Pߔaj\x/ o[S4_KfɼR׵=(C\Kcbsetbemon-1.3.6/.git/objects/ce/968c1ebcdb20dd013b358ef2f7b04c5be7f81d0000444000000000000000000000054513604576020020354 0ustar x+)JMU011d040031QMNMIe8;?nN|:/wrq7jMMJҊr2KĿ2sIt#A KII-IMM,(HMK.(`uy&؟jRtW8t&0T]s7э9>wu`~V-:֖0E% [Y'./1Cǡئpy%E9 Nz/\Uƨ`)Vʢ˄,Ҩ7A (7?O/%5-4bEΛ3]Ya_~̢b閍1$ujR)7I]f^f^ ñ Qi 2]c{ ס*.Ia0a L~B\\yqH#).fX5X,AZ6蜭k*")*/.+.a#ݱ]<[s:M]Q.CxC ٍoEUl{x dUE`êTU}޼ϖCʀfU{nKK531`BH o{t̵^j@cMMJA/-wku?8zLb4NܜMlm7Ͼ|3 ! KfZ8gz}UzkBQetbemon-1.3.6/.git/objects/cf/96c768aefbece323fd6f8edaca360a6f1cd0680000444000000000000000000000054513615473470020542 0ustar x+)JMU011d040031QMNMIe8;?nN|:/wrq7jMMJҊr2KĿ2sIt#A KII-IMM,(HMK.(`uy&؟jRtW8t&0g~ktu>4O Sa0}`X؟b[d܃*+-I-^WwkFN}ן2;aSJeVhj) m-k_AVˡP~7vwVPZZXFACs2v?FXetbemon-1.3.6/.git/objects/d0/1b1a90076370916659cbe91fdcdd90187348eb0000444000000000000000000000141413455034726017647 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTPv.hMvZh)TIIjnANbI*Cպz SD2d~mmL?2< lrNfj^I1ó k_>v 1ٻ&_HIMLc;~+lYܽ2 ?AP3-tW#g5-1Ȧ$3t9lO]Cnz#7?AS$fWfj>[Y{!9ɉ9SH;V (UJƜW[/V&4&38xrUΝ5er{[NJ?Z}I@{؎i-cȉ- خ셪,G [CA܅\݀ <ژr;ӎ8t!as֚^RY}x*jj&Ietbemon-1.3.6/.git/objects/d0/95e1f79bd5736c1e6077df2a61ed4f88577d6c0000444000000000000000000002622613764407317020052 0ustar x}vF%{D~d,$vƲ=ݙ^kh@$%+}}b9U @Ғ^3Il(N}9Uشvb.<F<5$/qYg0 z?9eaIQff'Wf?͢8o"\b&ȓ,uRt )3&Ƹ,E76xf86g&H i.& ߚi8 q9Né:&]&w~O&y:C2 3,ӿ> ~#XhM*V4֨㏺7Ӗlm%ķ*CZ&/atfNyv:S|YnԜNdrytb ((>x-+9Qi6Lu4AU"7QCh Vp^A,r$兙F1nIeoͼ!EFՌ& s]_Hp/#aS7 lz:BqNNLkV 939*QFcI%s^3,hdZ]:+ͫ(`DmM'@n:)[]km)/o_E3~vl)LL<~2<1f)u` ?:Q`2d [h*͠p 8O=KX G}CB$$ӌ`\ϝXw ]Yŧ\uS1պ0IZ{<4W1~>177QYu^`[Erd?&N^NkK$Yq21 j-UWAߤT"kBa2"ɣo耬-B7j CfMt!v~bFhE4<,0YyT@y R `lx߫:M/`^Yy-|Qmg_7,XCLQC+u e=g yDpIxSZ{Xur^C!5PM8Z˯›U..lwUC@/E$ˌQ<$'qg^ɧ+,PςODxzW/f0(Tj6Sy4l))f(HO[Fn/75ZIB7CbuxPmý?{=.Nj{Pe)av_BxJZ-$YOCf$6cL;juF7ft/{2zc29<kWFuG>_Cc'O:|!jd$-0S lXʿ!~§p4 0QR8Җ"_FMi CߺR鷒$5 //<%*C<(]禅5`xp/f&zn-R%nY I*M+\=Qw@Z4U.-[ל3d-B,!@.M.Wa>(T ]F!Z!քV#cnB{-ehU!Ny'Eco4>Y'7c@z:rnxZ%Xym۔`d)#MO26rPA:#kQ÷s.4.CIC}5ݷڥEQlwj Rp g`bTr0Qi {7AX΄Ps0c%9@\/!@m^ >'U98N[[P p@]T3 tAc͚>ȧPLiki?t`zSx&^Bm#=4UZo:Sך,ÈLi1 Y4_gm(eg#w9 H4QC?dXR@ 21}v$oԴ) G.h f47xF1 ?X#QS_ D7,QVd;YVn%Dx  Te|"Tb9fҪ$mY0}Ԡ}DI98Ԕ/Uxt2%B??~<$< x92F}^ Md:]o1g17s ܌l@L- e ÄE\3Jltz\34aoCL';:נZ,!ty&nb[7IhނL6IAoKb!g1>7ȎW4җR(Ó,0!AyH!071s[x$47Lp1@3֧z<6̖QZF i9FDeg鱕"{[ :!5Py\io*NQ~G!d7 F^|c#K(5$]%#;^(:,)hVUI/ǺX@c8U`&̔~5:\# s9:T9gfd1A5JJӛf8fB鰒Yï| #iUD!< |U:1U8Eճyat4MФ aV3KWD ݿOvMռѳ-Ry#nm'5vU`4AOw B`,l( KM&/zWn_N5Rޝ^? }DJ; ֕%rXux"1u+޺1t{6~Kau3<5*,! @dÉg"Z9B_Z R$-K¡AqE:툀 TK\wGqB%'{*dbM`#0W \/y; '!s{ s*mQYnJ`~6 `:(r-*(ZJ!F;@\!1>WʰH\'ZW/uC)fei&ߜILt9@K"Uj ѿ=,lxYTGMqL$īj}-pQtCF0 mz͞;um4&^Flѯd]c7C}0zI9l.6=ιd:PkD'YbMlfv<F\{-E3%O q^n倾LW}VÐlXn\1-dpJ4*`R0F3"z:mQwZ{sƸn7LOX?|)w)@`%--_Z-Ŋ'`j #3ed'lQ+]Æa%x%}Ж2ȞR6}j wK=RyE.ZUfT[wV=Ee1 Cwj:v`~x_`WT'GFD V̘ޟI&bNư3O‘4&jo 1t A*] ԥ6'T|~c "+'!ݸ{Qv<ߘ'%;A`Focthh,D1:[9~L^ӕCؔoОU#yGye<zQV+,'ۄ&ְ˵ZfLG/(F(gq Rs%z2̳e4E\h @o`D?t杬ڀM$$X1CUhйCtCoڑx5=0BBLy|環=51vpX 'Qj~2Uhv N4[t҇HV˼%hQ@"Iݾ[.uv˧wNlt1`i'7\9OB"'*S܋L{omuZ5c $ag|Mn^ "5 `E;x{$NB/2cAvOsŜZy{is?F}+mۦOj"vFXCwnbX-/,1ҳύ~] ǚRu]mUsLݖi r9 yl"[NS~%$4PN%jTgWm4-0uKh/zl)nއ;! %L$3cSܠԱc]4QODIe|tb!#q{{J%zK1E흙|Kf>s{r'ad,XJO=t:Ĉq3T_ \ɉzuԾ_v&BW?z]ŀԐ"ߧR>J6v^2e[%J7wMˈ is)Y"<&p+}`\^Jr ۱Csqt*ę>ys 2eduk'ⷾ/|9o]Q"8I=6\?hO1#&fldXafE& @d*)5\ڂŎ〘 čO/(߉pef8l+)k|&7Au9IsO/Jc)/sa˖3[.J7 M%J}B Ly^2,H&:6NOן.Vt4*r'?`m_ }<ɽ2矑U0sһmשp =[F>$MDOgPɖJkllCW&K/}b gU ~glAry??JG.Nٓlق ԏ^kzZEbL`-"#k5i)#ٚn  Sp;o/ksd9^ +2{|};%䥭\½^'?T 4Yp)ϩ)W {]Odw[MV/+.=rn^[8vFhI+&A2`'8# Tg؜ k@d꞊+5ɥuM?f֩w!,9^QRha'&KHAfyٛZc-\Qȩ#wJ=JH5o7ɇp ʸ-ˈT+0P&)83NiPy^M.Q:s KCmV}rO3s,ja/e2s) wz?QNFdkٸ? j-|2z%^(m㵮\&A)ؼGU ڸUTw!p[mZ[iq84)-cJ  mѼ+xPTA~KzE e6ud '"uyt AH|fSß0{**\62No=Rl+man{e:EL<ȊƗm{r;j,̩߫;v`ضr0(JȐ[l<( sqxj$9yCEh|G)]IjKłY, n.jnqffxQ@TSS}u܉6MUJwSP%m,z~P,@S8¯8Hz $$TYdѥ<_#Mò`Q~;сta=r$ epRY] X ʙ^A3ǜ6plJ q~CCȏq. V`uayC7@b찀Aj ڬЏNjN_w£_'x)hH7(_dp/)kcݶ #]ؽ8N h A@xTsD8/2?T6 ;h'\ tzg<~N96(zՑ&(#Xbh1? &f. `pp59;͡57Vo{VvHܲn}&8"ڸ[T.PEOWeT8[Rtl8X8Owjyt;1d=h߸|{:8,:6١u^,qr0Ҿ5U3v?UBN u'WH?Ԅ}/Z^ ڋ~Нa6H%)]Mp{H3t|k-~FA+b>NF`с{wi[?Mș4i5O2 V_G ϐ',kkFyܝ~< JX&>,FwpxYU L*I1XƐDZNVj=QٗͦYӃR%v$L 㙢8Kf4z}nkZQH H?fa㶪=V&Z&ܥ.ep'[׃jZ)R|FSI zh|ZMSP?t5X- Pz6@VGD۷:,>}fw4lUb% v&FѫaLi8? ]]DиZ6J\fszjlF%aTQ-{w%S)1Hxȣ"@?螠\:s)ګ5b#*[=ܽoWl{`OP{"[GT 'lҘ?\>*!_qpllI4AB} F2s'm_Ph P@̾cW/E%b ?F8T#9ײtQTYq+@Tmnmc(%Z\+CAyN:)ZmtJ`=UFHo9byDK|$K]5k,<(CU"9%KE?}~Ø{0]]f{*Sm_ MC򣇲sWj=(2ˮ1 7 }L^lQ~B`c2!|k#O6@ M qr4㰙В]V{+(/KwUx:_ŀrG_<]Ã40ncC73Sﮈ+U?rC`ovobC_DsEx-%ftMhetbemon-1.3.6/.git/objects/d0/fc942b52a12a750b471c2b6539f7b4be8f76880000444000000000000000000002631713764536707017753 0ustar x}vHvm~SԒ%-Pɸ;-wvL{:VVIH s}b* iIL6Sc}Ndh~SE4OZZOzpYh9qO2晹"eQ&܌pnn|ffIg&+.ۏmMF$,3YUry}1_kdQ ?s 0?~4?O[Sh?qd&iep08GcOxeY-t27a<"Y/h|"X,1fq[E\fņwZm1 92?4p-< 3l~1 '{mQ*"֋E›2Bߣ_bS/F5I\l &\#Nbl]~f \Bz5 L~yz~I A) 2!d&dHbzbP̘ \|kQy!U9D "EͳF!oi\ŧkA`u~.dˍ2-U ,JL`> \PBР0skad*`cI JZᚃt\ڣox1\h,\3Ò4nI1VG}+p]|Sa}\# g`bT)r0Qq {7P%Kfv@qpCyM~JLT+8]nAnU {Cq.xU8?f*am邆5}7ȧHLLqx:~>%8wvx %#D4҆W kDU^k4ӵscf1 I<]m(eds(!q K5oF%k-AxY "اC%~[}%H9rE0c%aDk| !u驙@gǹ/t(*cYkAH"{mz W3E}XrE2NvPG4mYL5v<,ۑ/ ec9hd;Yv+" < TE|"TbUHi8bȍ\v#)5@h3OiB[!K@?.>~<$< 8VAbсwsǦ3TkHN668&u SAK|:MX9")ɨx뀘6\l& ͛&"HmI,$9,'p1DIsߖ HWxt\j#7gFLd@ Y27]F .`d^ EZ-L%)FLew鱕"ߛ> BuBjZޘU?C.  ~c/bXvs S XKl1Q2묷\^1(B4:F1JF&ԧ5^(:,)hVUQ/Ǻs3,YC8`&~5:\# s9:T9Tgd1A5ZN&Y'7hOJd ӏ"}GFR/G xn(uucpbfh| I¬&BIgJ.Ax)*g5Z$17<7FN+LZi0J$4PbPL^:Uel_N5Rޝ^)? } 6; ֕%bXup$k+޺Oclר܅tzbUXli Z|ȆOYrL[B/oAPH [ 4C!,-u :ۋ lOTj>6ILJ|iSE9KKSWiҔ"w/Vk Y)Vy@ &,WAR %/&CbOX!YG;V5Eu:<׺z2O0+M=6~s?&};XH*qFt网=XO4KHp 1IxY~'WE7dȘᑱ;j # z)k12Rf~%"ߌ (oasA9޶zh+t%ՁZK'J6Jh`<0sɕ02| ǵ͔j g6QtgmE9< ++0"C8%j%aR@|D :*j}&n}{0m>1| ܥ8 ~:ܔٿ [+NTF$g0.l olQ+]Æa%~)F}pLhPzȞR6}j w =RyE.O{5gP:>ТŻKXT(M,mtF[!m{vNeqy߈=rX܊13=D̩Q P8&dO-0!&"A󤰄N8g]b~ ۦ3@NQ5}*۽VYKeOQ$) E=[d%B+¿]ңہVY]QgGI[f,#jGqA+~O 9mn o6m۔W } YM˞~nMQEcœs<_Z?T.SEZԶ9[7~AiBdHAx-opGTAɲ.$7b ]+~6aZq;ڋ<]ۢ!Nl I147(uChODɠntb!#hq{{ %zd93Pch6y8Ҳ~=w'6\. 3WBQAZUE51=,MAkBnJ"A{b@#6LNF}i)@ħP#>& ];*LVߍ]"24ao&Cڜeb+@v|`! !zb4R\vp\8 qt\,SH%yHlh73uIFa|:[-v ׅ 3a8 fq 5wb(\Yݯm4<ҽGmqK [tIKpKBL`ER e{ɱBo}Ash8e$aa7Ha.G:6OOן.Vt4*r'?h/Qe/HC*nϹ~z6T-WWSO#fjz(!>ȦOnJw$~\6\Rlqx FZi 2GF޶EQ1ricf(|7@X6!:X[X:Y  L' 4JoW9CP ؝cH9JhE1=%U;U7ӄ#dc @c1eKi>Yj2Bn% %}EulKk7z]om_o .G!Za`4|M-'2:fm Sf#n\j\d/_ږY#g~/$Ckg6a*ik,tf]Pon bcWMN8RuR*؀hc6֪2[.VxUeޫPvh#%&1Ue@{!Ыƺ5zPʓ0ego΍{)Ċs z Py.^d$0H&ձ5n97 ;ZE,V»ym؍%FWMd2O,p rG e/,9AAځ.06W:W`[+Kxq+$ ~ͬco ,9(qD_$#"Ȳ7ZڹDSGz8Hum ꨍeRrzZ 2" LTL03; ;$?rh_B6db'1/wz?QLFd+ٸO? j-l?/6x Vϔ{㵮\&A)ؼGU ڸUTwG6.58pzi>0*u2XW@nGAQ!-O -ӵ#c<f q[a=PۓĿoj7;K/*a* w5jSӒ6AV,]y׼~sDv6ʎNQ#< *Ϫ[MQwwT5:a]S!PKKQzJf\@z-rXVUHMЍ+4`VFQg5mp.T+6)/#~ۜF7 +ɬfŬ߿mP;)5mJ-af$ӿv|ˠU͍]I>ĦW VwoVŀb1lۦ: [ @!7pR) 2ʋ\D n;-fQD+{/'8`+)pvhM+Ea@=$7%Şz٬׻mTUr`aޖ'E~ (p{bR҂gGn:HGdD[@/]jb x{4`;ܵ31Zc=4p>.@Vp m\'}vX-)"##RWYB~I-5.|O}~Cq|Ŷ'ɫHgU;#Dm#HWeK +ԪҋIDzm;XZ 9BiY*K8&%Y5'UK{'U"/vZ~ypm[i6)6ˎ%YK]IRmNo_:mq3r|+uP~Ve?σ.C̯m@e-=!V#՟npvz6R ex:&^| A}Ope ~q[ЋW|͠E.~`u%56"m.MNZOiP@W\Xv1Ԅrf3 n4s?% G(o%j]ksn[z8 x<n]C&$v4 vTgw|S`T e[^tNQB7<"ob} KJsj4:]!,2-.ŭ \ CEir+ܝ-x^9qcβ|ݢZ7 x"k%Rb,%O7l p.jnqf&(@ Nz:wd@=T J6ZB=?Q(KD G)W@$J[dѥ8_#-$ۛ#g*L]fJv ~1b>+t0Q{rz$U n6ٵ"5cڂ\ֱK`ص f̃X2L=x*ϛg"\/˥wupΕ,sz?Q</tGXW}-8=­ow^>gO !=(Cqr^_3L!;ƹ$F[mׅ9ؼGkbdd Vfy~wJTj4;% ~Y`t_АoPvLo$^SVnY48gLx`pJ(IxO W_a(Bܭ~°hA@xU")f]Jo{MJSJ)b'S{!^549edK}-ƞG֘Atۥ؈ 088xwĚКQm+;Os$nY7>mXpY:SlR[8FcYLHZAѭwkN"ZNMTrXY0XOS!ՍZ` 䰥T=*%x-;Gu]-:Z`von/-G5q='vD2ڵ`@{yIuqם PXIWeT8[Rtl8X8OwjytN4o\W <žfeu#]'1f֕1;4Nٓǃ/gT*n<rGCܪ©zϧf2ҋ;`[7X[*B%$CW{X(Odf }DAXt.c>ݕ7<2\wvt\A4RU(Hd< yL߱  :j/,aQ]aGn~ۄ _t)O5=TsԩR}6F6/Kt"YHD>'_ylܽ'b@Ӿ3un|=.,: e6'<>PM%@;|0m0ga [!2S&ߟy|0Y٫x ZE O>sOqin!Hv>UVvQsEI~dxl2`m``AV(^Bf*Gn+AJG'YtQZ!WEŀyb;ཾQ`uq蜦4`),: t$һkGi^I-kr\*k`;Eo(DˍBc …mglWg]^8Fٕ-A 7H<~Zr*ύ`y|o?ʽܵT}(׼n?/8i@d~-zrpw*,Y+ȈQS"&MY\ٌ?A%"g'SFױ4dC5J\zAa(* 0|Hv;vl]HLȀDž;v{{maY\01$VES"tsi:8~A+z$i'tk)&h@of|;*mX|xdzG1RMLIҜ#&!僋w+)Œ"YEkaOeO@HnW>9+<2U$lIDt3eő"I.)[Nm!T0ᩚ0O .N;EϚ0F~4 0(Yk*-DRIKwx, @q81薓6.@cc/ĎPp3^RBjfn nR?z1׏tK3<%|(PBiNRD@BAkل&.k{%3(k/JEB7{ lė#Yw7 #p[`dk@|kNIAgnP`$ăb2HN'%@52"]8n%) ,~(T:<[4K&dۆ/ GP8ԯV)g"o\p+#KءNvBbCWB u系mѹ'E{Dp­p#X;8sq?-2){3He2H3q:I?GlB;/=xQ ,ZA׈j$Z. *?nE "mŵ١INWe^W:9 mfF5rOIr(7Yy Q"ZEsJV<10a~*Sm_ MC򣇲sj=(2.1 7 }0, hQ~B`c2!k'@w҈qr4㰙В]V{+(/KwU6BIrn ٓ&[+H42"-13(QϿN9m{*՚6#旤0<={*-3Bxo!K;8#!xglshxny jetbemon-1.3.6/.git/objects/d1/4cb849fe012cf03b2a989e93e79b256cab41bc0000444000000000000000000000141614174476713020152 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3E+҆J?D޷ 1D69'35ܵ/Pj;]˯BT&e&17ly%$ڈVj\8UPWmro}_)W,;}؍26so|RE2<]s׆}\Əq{GjE@Yݜ`X^$=[iչYO ~!7{1*k&1~z~sS7: p1z t>|}Rt|P3J+ J\f,g4ۭk\!*K /q O8⼀Z^b`|05tz]XȔyL%9 ÿ=!ɜ$Y ]\etbemon-1.3.6/.git/objects/d1/7497502e75a67badbedb3b763723a4679e277b0000444000000000000000000000026413455621462017740 0ustar xj0DsW=$EBν:6+#_A6 oeҪ*HO61c jRUQ$ f? ^Ȳ1Crd!EN#%dlS+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d~mmL?2< lrNfj^I1ó k_>v 1ٻ&_HIMLc0rv$ǵ}.ey{ ?a۵~_}ePԒd%,f.ؠ) 2G<[,*Z ]S:GjfnN~rb0, DՖX5g͞pU@y˚b"V%.; W\/s];WM;wSԌ Ym9v+hA&!c`89K\t7!'8/`V) n ^q2e{yES(DEiIfN1üow>hOz22Ib"#FTcetbemon-1.3.6/.git/objects/d1/cc17481f430389aa68fd21df03a8b1da3c860d0000444000000000000000000000026113455624302020040 0ustar xAJ0E]$i2-m#i ߈7Oq.TJ9bb"yCeMҼR@8R4'(zrH:d}]Z?SI1 6!%£ED3Qه?߼ozzA9!]Qk3?RYetbemon-1.3.6/.git/objects/d1/ee10db4733eb5f0a20e3a255ea2b55ced81d530000444000000000000000000000365214032515751020170 0ustar xX[oF~ũ&T-Ҡ/tuE;@(jdNEg \;gfHu.vW/Μ9\E^.W_|ߘzJ1uj*Zt\+b|7IZvʗ,L-tR ֕%[M5?_Q'Ve QƀPR,Q/* l j)7 o5TZC፭m6{!(cumY:1F9v֪g7X돕eabfйVvҴ!.iOs[K|slʗ-*irK~ᘦF5& hrYJ354/55<`RBIUvIYr,-+11 ;l=Y:e2JJ+5lb6)[*,^ZՍJrvY,Yf-hS*ѦAĶR^}ـS:8&YI&s`!Nu@`Ecae_ lj5QY!/Q65>K^Yoz[7魑#$hWq*M<CU27rˆ~/l<< Zv /%cUrԝ!F t{\! t""Bi]mFUs.C*qE =Cl҄zۤR;՝V_y(޺Bys0aq4ؑ ЀF^]]P#C5rۣD^^}mB<v! 1~'*Q?cޮVO YCXS}WCgW;Ak/19GV W1P]UhԻҧ\<ݘkљf<‘\1 ŲJ΂wX=:>vf}(;=ƗqsLvJҌI8ĉ=0@ϭKOh<E[0^'m}/ f.b6)6̳wʯrv4(o#Ka\sgҿHc&|%!N_8_m/"r?l2bM oBWܖ${9?ҘY4n@3'(#2C{՘,b^B1顊#(H2<1wGp:uu#QV=}G ,vø1f;DqTٽΟ!>c/K]Q{G^Z&E'4_Qz\Qㆀpi˗} K1/C1^_+qz9܂Jdr[0!`q5_Fz36n-Sr{Jos"d#P|>HCoyRS^_0h(9HsuV ' " )w`!Z.W&j`hqlc`m"Yـ犤7[U1wzۗzq={x *7">hg>Q"㞏ǭ딬9G0_V]pa}_`2=౪a\!cݙhn6Czԉwø#%f^={QC;etbemon-1.3.6/.git/objects/d2/0000755000000000000000000000000014173224277012650 5ustar etbemon-1.3.6/.git/objects/d2/1be9bf90ac543e57e2383c64054b173cd277bb0000444000000000000000000000204413455035510017766 0ustar xVMo83-5âvlv N4)MjIʮY޾f7>p8ohm~jX굑RG?!JI:EJAW2iEbn3ɇHŢx{nfd^J'~ U]gAE8P M+iߜj,pUHn, R.em[ecleuG;)qwzwI9ϣYMJ4v#)jVA#qG< R"VGs:t)ާE^-hRDֻ 3nC2ҴWMBWi -޽+Ō8#胙Qjd"xf %FF1IkeŲ˵6J'iVޥ-팤RTM%|@v!J:Zk[!5w_>P]fGZcDGkȝ*#tz5\[ Kxrp=VϨZ¯v ::ZpW l;N WXA./irq2I 4i G.gr~=gai ne aQ9 |xbӳ4DAAQAt,]j C̣~>|yJ' Δ TZ/rcwtJNlFgl꡼1mxq!M# |0 "v;v}G>HIzb~߂eN%fajf60sAkH:=.~$s r2u'J=bL2vetbemon-1.3.6/.git/objects/d2/6c9bda6db636def02b1f1252c56c97d72f2c740000444000000000000000000000036513513716505020145 0ustar x+)JMU04c040075UH*)J+,/bw%>ؓs \vXUX\ W̞abƋSnmr8'3B$5z^ݭ9U^ OLI,K+Y,y{}Z-VC :Onɩ56yp÷PUi%E)pUT.X{=@UɊWj}鍹;XwLtp{V_!}etbemon-1.3.6/.git/objects/d2/a1ac0a49c21efe93610aa5bcede2856328b4c70000444000000000000000000000141614173224277020203 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3OuKjXJ)ԼbgLs|B@bówM. QlvS_BͥiwڏB'3U[|{mG=D6(+vcM@\[*Tn z#7?sלĵ!zWcހZD3PV7'?91K>z[-4Yiš=w઀P?׮M44&3\[+LJ+nA(*(a`pޖlҏVmr1(.3cڿeK'<}rbk{**ewa!O SƾךW1BTd3Kv'sZ,d-+2<Y1etbemon-1.3.6/.git/objects/d3/0000755000000000000000000000000013767534207012656 5ustar etbemon-1.3.6/.git/objects/d3/6b135ead1c89e61149ebca7914cb50a8d96f0e0000444000000000000000000000636013731654650020152 0ustar xZrF+:WQ,S(K]MTC`H"0`@V[==hJڱH`'H ֳ{<,>HHiJ!ƒbڏRg!>-Jg:O n6PmG'oAtK oҡԱHf &aVI@"#G/ xddAX|3DR̄J2%I ]XR2$T!4FgX844ǣJf*eb2&Ƥۍ套I A:Λ<5̶i( ߇i4T4MedYfd'AfeJcF#c7HQbqEB T^"7WɈ]; Q*Tt]믩8 ڦGR l'-`-DZг)wS"ͥl1Q:L%?[sxu;Q8otdA=_]H߱'F/7YepUxkc)݇mia7ǡ+2D Gk nI`}5ޝףyl\6.aYlۓ=yiJ `)hrӨ_'PqꁄM/F#8-YZ3_);S+Z; V+"0B3#5E)"_~rb12F$iU¾)"xiRMvD 3ff0q@Hx[@D *^(l+0vD `vm"JJ_!f+*DGc9qR{e"4ש0V?6F*1XFdI#O`וY!oA2[-ٌ.'2 + "i=jQ:K>(!0` /GqRBDa.gh6=?e˽JG  Ɔ7񽕋Z`~-ԾUV76؎mV"dIR`^ÏBlY~#1?vޞl.p/]g5TYV)O\va'w@ڭ{-Ug "WG_5AstKkPBaAH]J3${`Zs eVH:̺mXNeW A^I?7s<=}nӚ؎gdO ',ցKF@xG$]@U'LjUD{}^j[pN4qz(EZy a)En cC5G2O^>L.)do? `Gz*PY<ӃL.0eW,5-`$rwim/۬JzȬغoU<)bDxbR3U{BcYAP%h*ZPd$֐x͖k Q2d–YSΖU ]h=:@1jz%xybH<dѯb/wa-+%~aHT9n5Z3ϳ91rvuNE=co JlE8ًz`pt\̙0mXVQIXiw'[&ۏ\P tގ嘜w:Af|ca$D\qEp`+..M nhIPʻdϵ3Tͽ(mش)lpsr5Euʷ2bQb9@q kUu/܂WްPa W"|0c5 ᴸ)n`<4u1[Vg%Izyf8, 49eetbemon-1.3.6/.git/objects/d3/827e75a5cadb9fe4a27e1cb9b6d192e73231200000444000000000000000000000002313212010712020027 0ustar xKOR0a03@etbemon-1.3.6/.git/objects/d3/e96d2467c34b7335c75d158333610cc838e39d0000444000000000000000000000060413767534207017526 0ustar x+)JMU00e040031QMNMIe8;?nN|:/wrq7jMMJҊr2KĿ2sIt#A KII-IMM,(HMK.(`uy&؟jRtW8t&0lK׹KVz|%u3Ҁ>).HLNpЯxQĻlNg: 8'3B$5z*nM|"zGx̴SXW*BWKYhh] Z*-@ ӷ+dr9{lڤPUŹE%%9pãpukݙw槕%fƒAO債ySTU}x5 )^LON9]iE,etbemon-1.3.6/.git/objects/d3/e9c7449dec0c9443e5460bf5c17d0b475bfd3a0000444000000000000000000000465313212011530020132 0ustar xXsH__ёI-TxN{ W~J>Q,$N&<$wnwI a^Ƌ$=/E[٣0 _^FpJ"9~}9aI$b{4F4p⩗CfMF"Hb< .h4uqBW]nl'gy?]{O,v 5J做5ZVxKnc;SQ, ˼Qu1bG]HpL N@{qyI"K u`6 `5u` JwL@trID "y6KG+X˙Ez$>j90N I"Z}dH Tr?p;zFjL>yTbgBѩ4`W}v.>^^P}mO.=XBƾr :3?cScs aۥsjYy>A ^:G!\aS1D4t :p1TW;~Imy ¤Bȃ .L\N*.t;PwGln›?" BmFlV7D6 qrɟD_%+YV<ѝHnI&^;qz~>8^D&qg%*|ǝ]{A>?oUPv_F3z ,܆1~rw5Sˊz|# m+2N\}V6[TF/cDWȲ}c86ZpC2u>?})[sÙ7*^\AC%\!)$ ,c"BHvY# I Y;>[F%m:R[ O,XNm"ןu6K@sܔAV U](Tm;9]*q8#v0UKxaCYл6hC9N$ՆpoΧ-7xY3|wíi8Ykb9 苁51IA$Y /"N,oDE5Hb 8&XRKC'ݒ~+yeK6r҈6F ]nrhb4$0P9TViYcqݐl)H3LfWٵ6Xb\}JWvbt%J~bLA^Yl] Lxȗ2^=};bpv e^j缭 Z+͋l/0SQ3H&lt7.ꯁetbemon-1.3.6/.git/objects/d4/0000755000000000000000000000000014032516006012636 5ustar etbemon-1.3.6/.git/objects/d4/5c5a8b567f478fea6b1c98636f42e4b4439f6a0000444000000000000000000000054413661360226020034 0ustar x+)JMU011d040031QMNMIe8;?nN|:/wrq7jMMJҊr2KĿ2sIt#A KII-IMM,(HMK.(`uy&؟jRtW8t&0lK׹KVz|%u3Ҁ>).HLNabƋSnmr8'3B$5z*nM|"zGx̴SXW*BWKYhh] Z*-@ ӷ+dr9{lڤPUi%E aPaS`m^TUU'+^B kSS%%uN׫i2|Q1= ᮔetbemon-1.3.6/.git/objects/d4/790d260c1fc5454de07e67267ee5dd784da5650000444000000000000000000000141513455621442017743 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d~mmL?2< lrNfj^I1ó k_>v 1ٻ&_HIMLcsr5ڋ[r tBR ~]Ÿ[;[W_,M-IfPRQ\b. /scŢ2e~̀5߬stKph'':O"sC*X* Wgy(&buYS~߸ p1z 2>N,^ܵsyմsg;?;A(*(a`pޖlҏVmr1(.3ȞcڿeK'<}rbk{**ewa!O SƾךW1BTd3Kv'sZ,d-+2<wT:etbemon-1.3.6/.git/objects/d4/a4b476fc00b9791531cbe75fff9b5745126ea90000444000000000000000000000141614032516006020006 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3B(GaVvqlrNfj^I1ó k_>v 1ٻ&_HIMLcx|s-Zyi"KI!dj{oMb>Ȧen얖 ȝ+K哊-APo1t6P5~Kz_$t"Y*&u\SbPa 3o9m_WOpʿxXyd?5-G"DSb?L}YE|jKSetbemon-1.3.6/.git/objects/d5/37cb4ab183818708a0b811bf63481c285b6e170000444000000000000000000000120613513717234017553 0ustar x+)JMU07d040031Qs fi^5W~"sSSRP0LƗ=估}슥N/4Ys0ڼL&PkK3fZ8gz}UzkR(3etbemon-1.3.6/.git/objects/d5/5ed4ef0ffc356dfd7b66c40628bd61d75152100000444000000000000000000000141514173220716020060 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3'}gWuO=%RlrNfj^I1ó k_>v 1ٻ&_HIMLcXyzlr_A'3U[|{mG=D6(+vcM@\[*Tn z#7?sלĵ!zWcހZD3PV7'?91  j-] > (I #}T~MNCh^qAj2lḵ2=_9f>Ԍ Ym9v+hA&!c`8a;K\t7!'8/`V) n ^q2e{yES(DEiIfN1üow>hOz22Ib"#=Xetbemon-1.3.6/.git/objects/d5/6a5bb6d313c205de1c3ee4898f306650807bcd0000444000000000000000000000141613276743201017775 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTPv.hMvZh)TIIjnANbI*Cպz SD2dǰ7!aMw!9y% lcN!*RR2>~ϫmd… P ie8[qoD6$e{]$b QQ\ g=lǴ˖Nx1l BUT# B@}5c (-)f QOX&ZWdx$Vetbemon-1.3.6/.git/objects/d5/87c772dff5e87998896938658fd530c8afa5b50000444000000000000000000000124213212010171017711 0ustar x+)JMU00f040031Qs fi^5W~>wu`~V-:֖0E% [Y'./1Cǡئpy%E9 Nz/\Uƨ`)Vʢ˄,Ҩ7A (7?O/%5-4bEΛ3]Ya_~̢bORY)'4|^2d5 i6 /J,wAq5Ԋ܂b+WMx'N̽H2Ksre]Ψ!nR3e$e9y K%T&vU~ZP[$E% ^_"w'LAE-@V\̐joʫhrgY#IH-I-f`Ѿ")p{Rܛ.3$1'g,^ʀG[9ԝ >,,'3/a`jĮsʯ]j dCd?[SzghrU_ؘnl~(bcg *JV%(F H2GU4r{u;]ZMPBQ)(&-lޤzEֲS D31hjVIa69yL l֔'$g0̴.sq> nH4ג+etbemon-1.3.6/.git/objects/d6/76705c56a54b5aba5f01c2ec5f569a079e000e0000444000000000000000000000122614057336772020001 0ustar xTkO0Kф1$46mݤJJ\ۥyv: &-C>T}s= $ogEAq8R$jWSRכ>R03No CZJHg`$ 1 {|I'пMx64kZiEڴVVOCKChc,6`} 9t,(6&w)rͶˢ}mabe !|yMc?&[ǰw|9Sb0 0EL*'RSP$׵, 1sDә u{)ҒUJD1I:6[I=m;lx oOME(C0: xS|b,h^q~ b8̮ll<$K_3 ?"최tYwy;[0uqC_8t('YV0Gpڌ WV)vhH2'1`GhG?wbkӾSdU11ÿ-woe@U)lhoj}ui525w4C/<'8C˛Dl[N(r1eON-O<\՚ Gؖ{ etbemon-1.3.6/.git/objects/d6/7d094048e0bd0a986834beaa409fa5f53dc8ee0000444000000000000000000000141713604546740020156 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d~mmL?2< lrNfj^I1ó k_>v 1ٻ&_HIMLcs˞˧YrlrTA~2C]ɽɷg|ݦ\pjCdSK^WTO ; ^?Fn~ԽK\i,'qqE 9ɉ9PyPLS,kU7Nz&4'DzvN,s4F 5_+v.vlg'@% .3rVܵMB.%pvLl鄧oCNlq^v`/TEe10>R: ., dZ5<-Ww3㴍 K݈:GgRxB*1tʸ|..@wblsT> d $e0 뵲e#~eb=f}p]'1G=SO)OlWU3l{!2}rI=Q 9Z\Wetetbemon-1.3.6/.git/objects/d7/0000755000000000000000000000000013731654650012656 5ustar etbemon-1.3.6/.git/objects/d7/0c70bb7224ff9c67807f5478dc3afe951264230000444000000000000000000000036513455033406017660 0ustar x+)JMU04c040075UH*)J+,/b0$g?9&|#)TaPcqAbr*\1{e/6nL;Ea=̼ ݒj' Z9C*6>1gw3Lu~bJbY:\ 5\5.8* [ >9uƹ&yc8?(13n kr>YjTm/1w |.Rxy ~|!etbemon-1.3.6/.git/objects/d7/1d6b3d4d0c23a45872b96ffd24ea1c25914a110000444000000000000000000000141613731654650017770 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3fS7SkԞ9j*.&d3<`JmSkrUԤ<熧Ԍ Ym9v+hA&!c`8a;K\t7!'8/`V) n ^q2e{yES(DEiIfN1üow>hOz22Ib"#4Uetbemon-1.3.6/.git/objects/d7/a449dc5d0ce269c60cc4f97a0eeccff6c30a9b0000444000000000000000000000025613247731732020451 0ustar xAj0E)f0e,i @nSjGEAwyr]ׯ7Uё=!T3zѳOCA i&a'/' dC9E b6Gmp߷Mn[\^\AOY3 ZsGe?K!.(GKEeSOetbemon-1.3.6/.git/objects/d7/a5d89db9b43b8890b2c4f5137220e5b3bca80f0000444000000000000000000000263613212012107020046 0ustar xWmo9C /NBڊMJ夣9NcűWmon^HJW )koʔZ+j)+[b,9rk?>Ԫ}蜫&6PHEd7]K2~B`agC'L@ny5TS.0=|zp3({0`6_a'$_hW(oR{Xm#&ђy#LVa7Uے!+pϝ]6o&]8"(_H15ϟ`/il^FU2xdEd?m# ^n߁lҮ|>*>t8T}ӽ<g`4 K3~zb9T3V(hs V^^攱`~P@okx$X+1*J 7_*l<<0>2CV_tI/B[C"5Iǧ)';18SG* NUDXGw%(zݏ DW(_q+uX"E-ժ?w;7Aetbemon-1.3.6/.git/objects/da/0000755000000000000000000000000014173226615012725 5ustar etbemon-1.3.6/.git/objects/da/04249e849f8d99509b7c7be1ecae414660457b0000444000000000000000000012220513455620411017740 0ustar x{[[9.~u>ŊLBLdB8@Cڏ x،mBg ޷.ņ{P=LiluG٣mꟼzy֐Ot57?߳؞Ȳ?ǣq,qMF$4:a6ubSvoe4^'xz1DMѱx6{A{q4wנphO&bvd7<#nOᓬq쑷b XjYsHm̢Bl7st0`Ib6_^=ַu}oo}OP|z:Ǟ럝1h(9>!no 6<nvpwz@uEN٠`4<WOq6Mq3 EsC8/e[΃_@^;hwzKAF)#{e.euNFLܹs)kmo=_[*Zx" bj6_ooYODwyuqokJ m??Ɲ]q| jϏpp-Cك=s6u){/m㗝>M&ݺpb2cC B/{Sǯ9vl> X2{^|"<Ѹ;ѧ`ít_z =aW!hU }9Mx2:?eӏjb2νSRi7=8' Zi󡕼Ǡ[le jn=ڝNOu >g]ha?<=i'[ δr~aMu=V. |mu[x?@AȬnRo:ŘZIm`=1ތZ\&<0OШ ::mO 0K?:s:nhf=h~fK ?d ['х؟:ǭ Օ'QY{g?5(g&&ޙ"(0Sȉ>o [Î=*No2iqʱbؔPm=9VX=AqC )1g@MI$hQ6_a l}0v߬0h4Υ38$< e-iKhbT2ʊFwLA->e?2>89'v^ˋ'P;;PcxheFO2?^)Eu3r!?TPZ:ǘFR1Z`e$dbRXľkכ[Uw4\bw"Ԡ}4u \@%XNޯbXQ@13G~`赁3, !ToJD21?s#߻ԢNrE} s9ZIq︇qd-ehu.Zɠ(<tmw(F^,-ہ;UY;HؐsY8.OS0i/ Vlj2"BJLqi9W`)P)?D" 2+J&0'kY_}*/M'}U9.X`a/-ud? kLu W&^Wm%qta9|?2.RAZ@1 Ih>A;x|7m.^ 7b%MIE=OЃ0 !1Q-iށDKm>?>q}gmUjOX(SIp{;yj}/pG/5Fr)<7{U]b"{;lolZV:bƁ rd1f)haݽj ˧h~imeZ~߈7c<Ҙe $UB/!Ɖ:f-)`w3ihhJ_SPae?]w=(흖ys}cs YHP[5k}->."ԹV){-:o?NO{sѿZ~>kkd޵Ч3:;> auXgk\Տ3V(=w#]A.h7Q$ˠT :{zI_Xc"nJhig%AUT+-UVb 0pJ Uc6/6:6̵s8!Z4N,E;!%0,頯Egz}QhYKqxpL:I% ask=oe+4hE+^vWQ1?~\yeͅa &iѠ=On@}fPgMq|-eud WcU}w^b')"%0<~ eL2YwUIC7\JYf]-_aN.͖ +ʊ<.*;JDyE8h ;vjE2RJI凡c v^w)[]\4ɲJX&qCi,D^iAN[{ .W1iGbR'Nl(auH2 כx C8Pu0~yaZ\Hѵ!(l31Q;:@ǦN^ba(MB?jX 3<DŽ0gHN hd>m4A;B99st d䃃Yhlw>Lz# ?}K$ԿzW3iwCNZjom5CH|>.:;WR{Aw;ۊO yoMd-b.بFb녭;{4t"pQ~쏰\Xj|cAlXmgm' C lX51'-%^,eiwЃ sxD[(*-UF w;4/DuuwuvOzu6s>qdEwf^g݆M HtZ5ڲRJYA81?ؽ;d'O&}â̟۴eb={LLCѿ_ј-__ Sњc8ҷZd\>zu W69䛻)QEmm盭ͽMwΨ*ߪZ?M٬ɦ/BՋ 5"-|sV iQc= .ʒ_%isF.t^~uq>͡YՄ f(&x1\DE$ X+Dp͏߬}A@>]g[ۓDN7=9:v,U},=>Av>p$krZSҔM ı*-b C/PTybFi9^5ɽo7pxb(u&2pN:ZŠ W,XՍWv)gξY6D{!\,]$[xD Cuо*-AD_ƽ)v+EvK!9Z`gB$,?"C@H/iCoހY$2H[6U- @FZ935' 5 |9d0u%>f֌JcBJ Te[)CB5ٞ#_b=%kqp)մtfZ'!LlDGd`l\A01(5A:ne){!YS%O%IW/XEw[OᚒG,lL[ XXkueY>ke7,Eg~ǿWl.f"GU%u3*p'\ XgCHYŪWi\Ui2/S컘576H#@jA!T^`:! = 6gGEQ;BWYL+MR<,ml֪[ n(YYՠ &Qp/Blg@Jٛ Ӎ`z[CũE74銂fPa35аr7woެ,N\(0uU7}8rlHaWI-3# 62F`MHrXJ%3L7t<.lrvP <o().ҁqr3 9P$%ϴۖZ6 f$a Rt>,|stWY}0iz+%lRpM.#G.J}*˱|so/ew8Go 6Ns)R4&uz@3:^m u8b+yvY,OՉ*aJ'ͅ@ƜDN9rkEf).?o:R_s kKlՂ`X ζ# FNǯ<#VŹKDj NAK$(NɁ3"Ge|A3Dde9K Ypƃc Kz:IPCo}eobVIKt##HYy> ngm": {6@0Sa% D V"Ԇ8ҦRt:!1w+BЗo0])L|w$1ʆBtbW`Dp}ޖmƴ!rr}7 GheLg0}O0.tXMTfj҅%@z6v6\6[A*TB FSXZ]ˇʥ#2"qg< (x-)ߚGhBrjf[׭o8ԥJG`z3)g!/7hTl:'S5Obe.?Aޅۢzي-fQC3/m AԱc |PJFΜow4R#i1B(2, 'T$HV;";O0ɩaq<]&D&XLR9ρpј;˫VQs?E~AӼzwdnN@(RA EKq5;"5i"7rEc&hFzHpcN`X8~߽󒚐xU55уHl4}-ܽ,`_J%P%\n8󡶖 %@Fk8FGz$~AxO&"RBHz3BXfT ~硚^ArqQUU ${{I 9 [&Et#kSol,CРʌaPΔXV չQKzwQF;/ң*3K$;`$G6Z]UQcUHf [  j d / fh~Y6UQ"# (GUc13ay mFlHpM \nNFA]f5&}lZ'i)1NqZ_&\"j iΧpfZu)n)<2vƄ'u.ۃ1xNV:ix|tkF|&@HΠQ\H [dm|S c?eX\U0nEW~G|OI2ar!:k /o=螹䥞$9oE.Q H2RhsOcSɅCVO#$ӆF4SQ|XU]ׅf''?cBB,l.IV,nhx/iO{ K V0RP@K~g6 ""Sv'@>~.G r o8+|;EeWd)BS! GfGU QUgb 1LX(c9sP"h=2uٲ1^4&CfaJtyi}S9|*6 妸v"w: ,>uLVք=rwĎmI%I@eD<}I)b'$?ʃ%-]g`cld[$V_/+<] cv|%V:O o͔Pο#/D<-Av:L+i?Ve8AU^ 1 zÓihInyhnUPgS'IUUC'cDF'{?mm5f6k xtF~lB>ׯw90ؓY7@òQNW\pI: !$zWI34,S;QǙbn˳ƣ y M8i8m8IbGRPqqI ~NhWTRxju`X'-)䨟pt($(CSJ⚪?}./@(q]RJjqGA-dX⤴JL6Z sVu '? cu Zo$HjjdA)5]*ge +de:ai?g=yaHLiLqhƸIߢe-*ߐIߟI8d8_BҝUΙS֊}e2U(`i{#p_MI7hP 柀dtQ3+q"\yvBͽU3dêQɊu nLT$-O_r{Oy$NwG"OjS<=2E_ ^R߭JHZxzfKdF!ʆhGXa[?L?N} !O `}9C '},MnCF>@UZ+ZD5O!yu^r@֋Y)*;mg6fogwt\0 +NdC8*yD$a*h.Gfqq/*ze /|{]N$vr}Ļ׫ן!0&+tM\%D< hI!=BcGC/Ev'7UCh =whN=Yv6 @y,&zs[)dnc5`qoYft*S pva%ߤPMz&N7I?ՕyKl.<~VOt%ޙb"2cH!V+ܲlu1̭I#@#xzH=݉ 4(ڶ%.i Փ 4 arBVJYٯ['I*+8%Svi#_JLj<SyL(E/&(? /gH?7p۞u¡BzB.6)v.1l#R2ҲerN]uDٹ17RU|S-356b(Tj'™*nnP7nDoK ȖU))SVajwt ?Ԍ e1u1RzO;7P;یg~j .9֐O~k-6dDdd &ONiCjU4n&A/"%,#*7M”؈rF ~\E5 ;JM%~ "Wčfⵐbern2"6S{\Lq _c\[Ô'Auf4k翴涘@v ᣲe^39mdฃcMTQK3۶ jzPpy6 aN6}\)h/I7B3e읐Hj+&P|^Z &6W~)٘)lU@`H3׈-ו+0-'~x T(ȚLD "MMgDa@_泣Gt2>b|:>S 7WY(?. OHBZBv9RPIrmF/r|)*+ئ t>9֖zkx\Dp77Kp1w so>G yqi\)~vEڭЧ䴥]`.N 0qP=T+W(8o/P,B10_sOpf:'à[b3!o .Ae`l%@"DkE҄$0AG`vA* ٢ő`=_-!j8وiIu_r_GdUV0:^ yl {`☜3GneD4$^ //2)X0tH({s#y82g̱FË#)#qe%/_C抮ƳxtJ-tyּ) gJr+&Xv6նn[("7?Ar5'P^9Ԯ_v70^:gW>[^]=?Õ;nvGQު8 0\:AYQmZ3^FbuI0ϤoCh븃ȉpsR{H66 g5G#&R8qsZ,g"E-\vTA>' @#%,֐doN :b Қl܍*VWNJoo腄>&ٌq ZVNq& Xn=o XD@MKNTP:Yi|R2yGbkKo!(!_&^Μ[s-!,hr_TfJ0EHiJ$H2Ō+x೯U %dJ`ӂnmCD7 C+&\{ g6,L :RXG+֭R[CT#E"5}P D&} o)zHuZʨN0 ذ<7/G^4\7``p8@]#Z#Uds:`xEB0k2jD4q=W+aPъ ȵ-=ȅnM邘[ªsTL]&4sQojrvSx]ҵ;ggE#2C(*6-LT'zc&C:fIb9# #=bfe r bZǡAfYAUr*?Ô;2sg|Zqaka \k-c딪~OjB3+ |8bQèGb"y[LBbi҇tP11&j@7?Vΐ 8e ᱏz .{ĆMVXrurF5֧ R17V(7؍BN n?f腒_;eoܿSQY]8_Ֆd;sB!-~U[o!-. 9õF:F".%یaw﷮tJuT>t J4Uv9VÎHNHmwn;C-69 e=0\%^> !' 2L UoڸG]!@1*+6F}ell&Z%r$|"pg2¾]c߁ R緪Qo8ކCo\dHWl l74r6n0,D~%Iw gnsoMQ4%Bh19_`UUs9nF|JIW7v#|&pDgK{9ѵ<%$V n|dž3(KM`8T lb/=~ε%*UM .k.pM>r:J" %!z+1n/ِ֟CB@T"ADmIؠgoŻL'#ۡ "J-!]vgk\U.Yi(ޢ?,$p>2cCZ(tv- h.sXL9 @ +J ^VTb9D\V4]U8um6@_(I* DwX-_4>HmyQ(ʕie™rLg6$ɛG|nC@6qAqTpsq:+,6#ЌqTk4DcAߏ+.ɬGK@$K<<^,QSoX؀&R"Eu23`9pM{k6c&E =T}vp+#&x@.KO%+fMR :rSN4(%a\j J8EZ͠n*vEL eJ{OtBy'YVwK}l7㕜Q^gdJK.k^@N"ϱʋـk,,- f=L@W>aGN|K&:Vpnza18|"_#_[H\>l$R;X ٽ8;8v*7dZ\\A]ܹ"pw $N8:Ⲽ~mΠ_˾6smu=V H[Fr?_?gnorjcݺac/R7P0qtDa% k_7Vn1P5Y~$—j"2R>UBr/e4-qQ~Pme ?q!pUlT!č\1|á%Y:S0 Lǜx1rIە ds…@[;۲P= q֟1Ȃ-c8$f^I f#,Ta;srR&G(^i70M3*VOBBn@a.ޓj%Q** F(K8a\;Y ƅ~T`;]H(`L't/e[&ԉOFJBtQT4kf!86^)m0gCWp;$_ OBrB/E!8б\Xʵw bxKᢶBOXV=)oC_txRBnQ=PZ^ÄT2{JRD%BK~4ps.Hg<c4ɞ ג.S9ngW;o6q.)p eVO2L4p:Kġ,wر ?ؐ:Έ+6\q)dRCJ|1|8HfR.L$G]OKʵP^+[ >NMk/_$$0P1H )/axrDO* 9iVcD mI]X̝*-0rOSŏ PDa62Ѥ)7֤j"3\ aa WJg_Wx.Pы-_e/@^jb|b8Y!·9@+$sCCbkր%/ԓ)X~$Iwt=˟h+\WhVVtC-V`ߙmgeD٫2?ԭHVTyq$.qg'FHPv VL!IH^y Ŗ)ْXYQ2S{CWohFwm|lB+Ϝ5[Pi6vvyʕu ,$Inr6'$St[KdG.] [ȟK&R0NzE [D{=D |X\Bk1X?`:qTy/70JǀzXSH,^i5Jk ӂެJd \!s%r%8wX\|&ĻҬǑd2wgu!r.ƊnV`ZN0wCXVʌD,5\$2HHNP1dr(R`ub"klU]!=YkݱUZFCR7d %]yDaC3 G?y%! k5 ʲt`'2y;N'ַ8CXIkj` BF܁7r e";y rM/nh R0Y*jפ+ R:*Mt%+RgLڦY>Ohΰ.T#Ɇ89ў*_*XCB`Æ| jA$5au#zՠT2Fnp4zfNC-0@`d;65K}:$h\Gd$wv_z~3n*#]9m'ĝͼNSu8,?}>uK\J=Hj opp;G1@V>˼Z5j"243Tge HUK7!Et^󩪶/|L0K-yysF~H> }:s.~1.o"f{vqgO"Dˮ/pqT Y18J1jP+/;pȳp0[%1 +!Xĉ c AX}d,hŽ#*)KIdP&PUX0.||hUzpn?AWn:npm&Q;ef 9i\WA:^)R5oڥlJ)k?Nn8t ~ce  v,S/X^Zybd"#{P,gt˗{2ﶢΛa"pCìuDžGs0KZ@A, ϖ =:\hXzvo3^Qv+m Cc"?%c܁0V.V| .7u.*?vccs0znY {[/$Y<_ÉBR#@tbac3-.K(gl`%掊K}/.8;aШ+EjoطqT, WAw7M fwP:rC#f̗!(RdGbfXW'ndGT*::AhUseȦ7D.& 'hdEh&iM]WJ:0O$2NjZpۓ^`b%@! Vt?^29kUq/r$EԂ&wfp! i}F6 T; Dk)+ƁU4 -*cQZ]ق7P":"V)zL3Z=~l0ΰ" m2j72jyL%zF[DY6bc=!2x$; 9Qe5D"9RnBdadO%Kf`Q^7~Tel|tvu_i_xr6[gO\)$D*sEMۀ#5JK.Y!at<8xփ~X,g2oΙҳ UOU+ Yoh2b ڀ| 0Ô*_,O'ZZ.tnz5zr]vs&sMHˏ:b$jRwrAQg}o$zԱL^'YCX aR{qA:W)3T3 ECK@DF+ UU5p@n8 zKL_-DB)Éo6*Y{^eDXb]nlj kEW$lclM>/\Z>Xqv~f[Jf@ 湹7n(S q.葞[AlB2uFk ʱE Qw8KRĴcRsNg,5b(t(m (=* Ñ lE?  [_7 ݴǦ  UAҠ2 ,vKNdk3RH40S1 TM\wڭFHF(.j:XxH @`b~rbTF2BDaKhMnIJVJF &ce?sSGDŽ̔dyyLzqYߚ$vDgRUg"4YQn%wZyXZ_;33o !+4}Mkg[gj_w-sظ͉ŬԔyanV)R0z- t\]Ri9Z,}@H‹ G_i`/|9hqƾ C\e4o`UfL5)RZnfJ5qSp+Οde#d.4~K~M2#z1EE̔[DI 7"&qObAԹ\zftrT%\naO[kS:!&%KZeHaB; cܖ8Մ& 7tFp6FwT)k2*?l~tK;%ZViI]S" M)5(W|?ۡ7bKZS7WX]Vs*'U n%ΫsqȥXi~>d, xWTZQ1dgS2 SRݯ?:;H&Hr_|LfM!w]i ~HYИ߇+rN OsB[lCwߦ].IpW߈uZ{;73WJ26UO$q.9v[sUzO㷕n"7R"b _9sń7>M&72>Y%cZDHo ZBV(J;MN5_I̊5U_ Ӣ4Cٟ^^)RK zrx6O=Y#\9f>aru{<.0WI~*]o)wH~6`M[X`13X !S% A}T(m;Q"ӧRE,6ٺՃ\)Ba"B24>K~*庋Qk-𦪖ԕ+ )\tqd]?,h| t/Ok-ˑ&k6y6m1%\ERю|=Q~^+>л 4MO"H1dk ww7Vdg ک4堵 + )꾛g1m>zƂ@l)p''K;dw¡ :%Dc{,߫e{P@Y`yk Oii ;B.%Rmwsx*?X(SwmQe]n #`1A;~'~dxC{~-5Pdp[ީ?Je76G >\Hm= [c ?~Ito5_lM1"_ 5jGeq?ɩ 50$NQC. j*1M JC9N:kIW;nOFtΗ\,25 $7cv,YRisԃnZMwUzsM ޘ6/b;͑25bd!"mtiTb"WQh`TzL0^ hN!Dj?7Ay"|<\fOaOiYîѲHFtЁF<Å)C,JM{'nc~c\X#\)؆j?@1F!E2CW%O~sf 𼰐$s$F![˨xK ox#'0W&b<ˈ$d!/Y2X^+ڳ:nGU-gk:޹c 7xޝ;kAYo$T6}ȹ WL|]䄖qsz ' u?mL/0V4&S.0ګG5_y7wDyư\;_OҶO9NT]vl.`o*z.1}BB4 Ȍ9<"ʂQ=I 5$s?} K1Cbso2c :E62o. "xzp~uכ6Z/M;sW&]-vc2 W(0o@\ ʟLUȶT2 TOAn7iiȣv' kO &@8ߓ42PnF_yq89ɍ"M(n`FR8@Y#QIRnSOPZ炯Wiue /]7,p5![}_}zy/UBHK=1sՏq,o*LқxK0Oj+棁 3xS3g;fP (3.M5u: yLĔ'l0%)?I#3DSj)l}JCf}vlEYt\/)g2.T_w^oak^,0jaQF9)+h.KV:2ܔ@Yg'eHִ-/9qfDUUޑb`Yp͕$^}O̅R#4xZE&H!"5)4%;N4"??}6r5sVfX]B C֭(W/`pa߁ #[bb M9>:A)ABaKSm]8/) AZ6ӥTaI]$aNl5xHׄGI2R/;8uJ)lk 7hdT%(,y|G^6l_{gM9kɺd[W *c>;J9ukRv E4#dqV"y6}wH&k[u jF0ݥldM٩v0D`c&afj7M$7ե%-O=J?E0q/Lr`Oy{cYŏ*͉w\ŞE:4_k0,0|mndo߼YM6erG9CB (\7VYH~-]boPŘa&%o9/lwᾙr%a\$ny=mh81q9M5D(gsp7[>ZLaCPP–ڍB |0>GUg5%y(-!ylH:6fgb ~'^p'yi#%(+u\MʿTQғ'‡Z3}1=h a8` Kze!I[Iyx6$Lڰ  Ɇf޲`8le_[Sݾ12lpNXTe V~N\Vd N]}ڋx!Vy%m8ieg)>Ц}K@0ǂkF_Ͻ*N\ٻ0m%BZJ)ťâƞ~TMC2lPw!>0[9n :9ѼA>LVcY g˖CX. DM;H*uD#HσI6]*|5uS>fJ#7Hŏ@+GT;^I!1'48yմ|ͽ;9LBW:zb#,9qXXA :{0M,<KQalfe$jOT7Q(UnB{a) M(~12NR&ҀB wJuoomllb)&7o)\n'eiy+~ ni}?6yʂĸˤ'.JI\:T Hhj4""Lͅ4zZq KL[0,9xRkͯ6ׁ Z!t=O{V=!Xq~w9"+)_g M/mRd qt pUY#hgz'DvG!- s6G"-P-B <;*". ȸ@ԆȮJ=7^g &eMB 4I|sx,OZ%%n|l jsGVN.JFئ} w(W13OZnU"IL\z?aي> 7H1iNß},袰4M780@rf-A5c36%fx;-ޝa/eEalr?IU߄$Hio}9&=X&,"PRN4ky;oR!Xu=SgP}_G&%HDHk7K a12"Ry I,(3C,̿aUAFl |Ky U[&e~/JvZӚO-8][C. PY2@#fC Ǎ43N8J0%tc0b )+L">̎sDWu14\_„5υ"!TظJ{I {L\{D/MQ.qv䳻"AR C$ _H8z=r\!nd\ZW䏰cd`y2eE q@X0 8m|8w4O7 `^\|£C@l|T2(ͪN.ćF BR'H(R#vYS0+F%Y@/Q+D2 h鮉63먌:cL*|FbPC͘c(岋*,4M01Vp'4FcSBkƹt@},ZCm HRkU7xgή ]"o5^<* cKIogRf{hXD HaW|.NZsֹwܭқq;PnYA l(,SO_ lŀ3ѝRǩ &4#KİC),g '-MK=V*TU"FA292dn/@>GuUQ8ec"`*tFN)hKM!۱G|Z%HښuM*9Nً _&}5.ϕ@.pBw* [|`$@8)pX$ rI/ 9mEɝG֭pi5IuA16 X‹[LG)I Y b1kX_yrZvx-ȴ\ >Qֆ1`M;C`%t#8ǗJI1nnԼu Lj'v6Lċ >F`@%l6g*yߘ :Tn߂17nR/ M#SE g{\U|B4\}j^{v8Xpb+"8! fpȫRֵ?s0GD5!g'6KCe`fSO{s|8Ͱ-` ƿp"&T,IHwDw‚a< Y}BxܾY_o.~}Zrlt#B@NMw'TMcEd {L3f]{1|ISY$Ǯ˱( `R3Ry*N Z{6l4g1h"GjZ ǕO>P +,D"4CE0B}ٸzt&)XsSNB!#kY~?mK3nFm#g0ֲis{0u8:="CC_ؠJ2rgٝZn5b/>#T;;ᵨ8 B[02XC2cOlxńs+aCsZ'C q>K@f\3>}j P2j ORXnx@p=emO4"{&I]F켲N8>1ҙ.a?2|_!D]=qػe)$xj԰P!:4w!:* ]ȥ;93f|}=ѵ#8;RNvR' !\ҿd-C̉ (L2Iݭ4԰G u6')l>~,bf&uIڬ~[A,rW7x`|V$A&>O֮U(:- ijq / B͠^-lYq #v*z"r$raӗI7҆ F++t6bf1]ށB$IguU>n?\YVϹY|rk[9'z$'d= 8rW4ALsRp/s7|*Y7D&E5$!wcW@Clh~tFhN(ueV)qs +SIex@N>P!Ū*3oAr|m  MP]1f&\#~bt N./(a`r!\4 w\H/i,G_ٝ$ht AwǍUa৭lۻ;?vpoȌ6ӋD|PͮwW 4k+5n}xMǓzu$ zWk0|?psl!,JyaUy %"38ܤr<ʂe0Tg!vvW u-Azʃ_ e ٧IP/a*|Ǚ(pn [031tBC {SC%DcHvp,oK)b1kn=Sj#`#ֶJR0EH|,Un_7y-JVn/}LUg%l`Q,q$ |uqoa muX:&$$u4qnB0P̦*L?KQ.6N!} O0Լ3. =@t 7i9hDR!\hX^A1J`G*FU"dIdQOs;,*0ʋ=ܒu(JyXj;Z^@.ˏL$#*$Α`gt,:^X@yjx*W(#?*8B40Fk#h; Tca~2r[y h?h1_o*ض@!RCpx=ۅ9a[O1fq} @4mR*GY+um6|:մv$_e!׏U_5"Ftk4l ָqƔ:f3 30#5A? yI`^2wƓӭ6Wqu2yҍ.mFߵKQ׃ Ųe;hgv}PZQec@tjYxM& 2^\ejE?K`+ NZ: R^I6R}D8"5ᓵ4' ƈ \QyP&x\V)gЙM`̍4i8WD V52AKx==?V&\{[w*Z8cO:+ ZB*|BX=Ҝ/Kkg.l6m\h`)%n|WL~Rc(X~ֵSJ3L&đVM7J^>a jye!v$ד8sN 豳]అ$b$6a?Ԃ@`v(~? >KSkB `۠[E cdB*!_!$"VZO\@@< 0ȅ֮IJl PSӺ}IbΤ\&v/PBEnD\)|[#BĥOg8߸wfaK;e_ӝ:1eD=D"@q+AXIJٷ|)oV#^x,Ŝ1g_-AS,!"lQ=hƬahǑ \lQG^ȥw@k1/E2VyiWJDn7`}UEqSđ2l)ӮXl{,@-NUI.m!yD!sJ{k`"j V6_R|Sŀ]9~] VIH>ӋShg\ycR=)` \wjıf=^%[ fB 7;HcpJJWxfVq)N&D!>k4X"HeU#Ik L<iCpj;610zPk"<=1p,S{bJ3tkL*ye$gBuޑ̡úو/%hўDžyQP_,!wŸUIe/oMUOƋ -nGW+={AuG gB:P2#sդ).অa%ԿR x@h8ΞXDbYm($َ==ONp_eE5;zNgoj1Q ` l*U{hnpzCl)y4jM|A!\P}hQ}?~ 5:V yV86lPg,cGbV/17 C{Ի8JTz9c |`dz"dWҩA2zZԞꈺ<bM5H"6(C^C tƒ=jp gPUz&\\y4-E =#V4LE/lZ1_ͱhnq)@)4<,j!2D|=DR"xLQEDW VsE+*$b1,hP8 cn!1h#٣| )pѻbݱ ʽK|#zy\T  RX1/H-1% ,~Q! AʷWii\=s8# V|S=}u<`ףRѨbW âe`d#@4 k+" A X!}E,%]W\$|#(Bq:ӮʁrHwv((v|-zGZ[Ĭ̤*>C]`k_԰5vV aa"1M8:!˯'XЋf^GF@px{t?^*,lŽy\~:e-ղۜ g݃37oqzcE# ) EZgMyI<ļ !ɨ9xDinhlDn(\ZV]{D3&}jOBV/aVAVoHhȁٛP"&8K' L{Hq8#Q5S&p#I% lc_[N`M50?\qGRvҙ&J:Q [ 7Ѐ:VB0FY<=,7>+$&;=(w3+NړV$>6X|/~bc{)\:`ZtWMJXu]~8#U uc m$ӥ} AdVN\CgŐIEFHUJMWb8ŒLMB ?cS &>7vHt3Ͽ|݊jߖn׀ٽ4)kn^40ne@w?,c&Th=gvvA_<Rpo;48xImn@KGc7F7Ԇx`y+Eqqo56)8f_%w4,'ֳ Ӱ:Yǖz4|D Żi@~_YKG4XJX+庸ћ2OsI9f*Gк)KjS کtc?lKݑMheTQ.yyOÓ/"NYaj ;;MlAT7' vK{.xs/J^jkAZ7Rt5&bR5-bPѻFɫU6oR1n&õZ| øZF9Ͻ L^uiuZG42 Jn'۪r̔xL-eTjdl2¤i'7GN-<% :Ĥ`.:i(7̛aQQw5`-j nᙵgp9-@hI3`Vukxek8fW̱V1hڲufLQweN/]F_ BKC('C P9՗9[tre}6I+MZ@GiDahq 3UAy[nßu_|Yޫyr'q"LI $E|LF@JaҌHgv@v 8KInIJxW) b&Մbv}&/lJ|ZAmpxuYG]N f}Ǥ@@ iYňQ aZ!;dqt1~/r(I}Bը8 ז8b+ g3&A3Sz Hyiz]2T_߸#66GG|w_b.~A>-3lxZ {!Wj(5nU.]QJvDP$A,!ɾhI.3a; 8؎b&!=MV M(:xiS+W `&h*rFK1%"Md+ =$RKه!Nj]L8pI/}_<+=4&YRpz%.Z0.'uC`ОA/n s4,t-[q?4_<v*.> dKyĚ

a0"GRFJ"Pⲛaqʢ0[x X]w#K9 &5Ɇ-oUwgʇFOu98wZIEL!QrNekUt([὆ ڶ=e!1CmV5&ݫEB-i=cUpe ܺ.3ghPM EQ`ɷQq6ѳ4\_V=[$g|Ѱ _AC0ȯFI1C2Dßg8<; ኲn{{Xs/(27] 3/ * ^L =?H8OV݁dTpa蜡]HMdOFVopn1mťZ[+&@g*wl,`EͅTΓr]Oo$,Ċ74D9O bګ97:>GbNaD02dctؘ!$sc6!V_&a9h-lc.X@i4>3/-4N2 Oa6U}WFO'Ed7措Ǡ$ bz gɨKhvx~Oaoӛ7wm`[>`i*X0vLۑpE lJҁbWV/€(hq$OoKû&p{2hˈ;. Rv7<"Ar) Zm؀˵5 kk vƧRGl',w3Msr1P qǓ.d{{,k/OF 6(Dp4䀝xcd2C[Q9?ZZF:h|̅2zJBDu״vh5PBym %O|ulmܽ*P_«C7M6ow7ؔeA>㱽,+\3٦4_ DT;ւ04B)-UkI۞D Ŕ.k4/ENn!fiz^O0CXQ+ p\@0ehWNXwR৛*\sipm )^ߊ7s&xo@wI0EBZzAؚEN Rٱ'csG֥nsz Cǃ';feۊzs]'h7wej>vJetbemon-1.3.6/.git/objects/db/0000755000000000000000000000000014052407067012724 5ustar etbemon-1.3.6/.git/objects/db/224178a309622544442b24c0f8c8dfa98e41b30000444000000000000000000000141514014637241017547 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3B(GaVvqlrNfj^I1ó k_>v 1ٻ&_HIMLcXrTC.Dng*Of6>۔+_{lj PVniܹrT>"Fn~C9kC>\Ǹ#"fnN~rb0,8^</XOdCjٜZjZf7|l4ƂOr/Q}9'UL0HG"X,0_42<ﴟ2kʮV"4,sQt_$c!O -]fӐt>OzNrc4@0X{tMF4mLQ=}INlQy`}t4q!^*xt%7пOVX`8fYm< 4M7rhãG9zz^h~k| jI1,稦cr1["wug8q ?,|awjsgQa2DOT봯}nfl:[ݩO"6ՁD8aUTD ޾XaWƃ<{ƴזnڝ, [q1OaFJ ir 拹NꎧK>*1+kv.ۥ6ɶDmm1)J$1o mXjRjSRBy2ىKh[aVi_7sM_jYT,'E[l':u7H?M#|b+-̘Qbd]s*{l7}wxmKz^?:E#ןNx1˯zHKx,ƮXuP;eHb * Ķ૿-3NacU4B>5bv N7MfL ی&b9c>26=+\|"iOdU,up1w}ɥ#nRRʷ#_[oI|W.$f%+d4ΧBƄs9TFʥ\  ! \ _&*ij GVѾMA!ozYd|y]撛]4S&v/h(C wSYx S/,_hS1OrG!I wC^&ly\ctyy/a9(-= HifɅZc[9is83|L3#NY}:oe`#3zԣuyQݕ?OyA\ Zf`$cmlڵ{J8))xl.x$[B.V("i©XjEFj˂=Nr抭s双I޲+&W|1QXuc%`L9U%/l?9~}򦾘'3WzXR mY/S <(KGPOFxwB(-fy0iqc6)f~*Жf:] N,]FLN2JG)rfr팭cWh   %0..W)hG/<8DVq/Om vcqiڍfܫhI!~684ms߮-I[ӑBxNJ\m/LwY٪V;i9b1ZĹ 蛞ɹ^_fY1k62 P6;>ALʃ:xڣ%DP݆ U \H*Ɨ@bWVtG֊3 XT"݂4n i{\Z?\,V8Ӯn8r#= $na911a@ 1X(kN.8 B? tYT3Zg1㚟n[#Nw,` M[1ɹGMOCjL>HgV92~Y|gL`]tf%oVQƋ%ܤB6pt+, 6Dܣ c첗.p!iƆQɠl؜8'HzEϧ \-<,DN*>P*A!tk]<3lLWSqD q*An-V/U:x኎BE6O{:}iibyqa^ & XU*ra֍-"Ye[͠CbY0ѭSIJZ N2F~fPb9jK=OP$oE¥2aՙæٟʂ6L/%y.t)FӁh@6m syoIbB_., ҏ@~#qW>$%FN #[ 8xqbhaA>l`mh?ZdCl<jLn&+0`ޅl.i#E/&|oV-;St^xҚשorXΥLF('^ROAܖjH Zvk;1rLIG~^+~uE:TOmT`@H\ c]JyST 113?V7l;6da#{iX2, [$D.g)DME `%5FUI=TBq)ۊ[23_}7_cb9)T9Kdtp j4t^;kq 'VIB6=VIy?Nl !:LR L2vvo_B?U7djM{XR N7oֲL%@~N\x V~f &ڮ,5R׸z lx ![BZm]>a3w{ #}26+q%j*J o e"FEm?W."V>lx-|V%:Pj \Y_&y2DZ>:A##hW[T'E6p$XrTKTs'oZOMG~;yqW'mH7sd0tMG=,3s«fs܉jH'EHBEԿCGrTʐ](#ghoI{j}qnTgeYgVG] aWm㧠/*f.i)CR/ ;MTg%͊ x g% ^eV2I7"J042x-ߕj7M9[T2cfF~p2hOauff{mlmy͔zZAѹW+2~+56δ҄΅ՇvHr]gmX9T paJZ8Q]%h? !xD$Ͱp[ԝ恓ڟ\-ςWBLK5xE^ulNc("+;.!!g0.l W˨Uaz)kЖơ2ȖTts 1D!'XF{eqfx]e!ylFyYw W:jFC™?awh6g:#y-\g[=jt]?'xM*{oAtvK! i<íS $DC 4 VWBď!<)%stxռ&g~LN,Ԁmpk/~6RR3Ǐ\̠>pB=G\bq !`lX&Z`W8f0$=]fиdjC^'l2YYx> /|:A#zYw @] +t+2KNVTU}* Suj{՘=>)vw佰)%#le/^dK)fyUX?Xn zkD I;] &s3 >Wb3/]>#8دT`aFap;G wz!?K @Ȟ9H`};ct͖)tp_!lU)(vstm䗿~֕êٹl73WGnT>{Ԑ }@\m E˹:0vb`&Kzn(Z/5ZaCM y-VIF83"BZq%g5B^Y\2{%~s>> ߸P6Gs}B8)Q&+K6RdsB3f݄M ZElRk\S] Sc-*k5ք#ţ1иNA$9B^,ell2 r*;1$,93Y_i0(ɭXɷ?`(j l!5r{p>O&S_`z{{쏕;\–PGd=?5*r'?1ֳ"F~" U|*eϵ8~~2hSRRぃe-As#b Ҵ86QlF^ 4QO)F8r&!vINb-rz9o:|j`_JqN) Bǔ!!?;a2mKМṭ$Y؋|H 0rWDE2xxaeaɘo16yQ7bbK`6q;Z33w"- -Us#*P.1gqvHvU hEuf8{d*XƫMM6M۾(n/g)"pYĜ^ ( =oEѹT+^]S39q Q,}TtNJv}s|um+6$e7fWjʀhFD7:ܱӔ DׅbC$8X:rjk \<fN %g$A6W3Vz33'PțK#OQ(TNJI-Nt5!ɍRO\54h՚[jOP,GS[8QMg%O9]]Oxtk-tQ]+C6;FmQm.羐|ƔcĦ3XIbhX2Ժ>Q.ƘdcEc 2GACxq{?bIW:8Ӣ6tm.Q%Xb,7nIUj5q#.-qJq+UJ)Tq go g\4 2\ۖFQulH }#$"#8.բM%) r&7VX}lLeD7_5`0YkcԍɃkpCkTa)Q.~T@kI$} T,Bcxlr5\BTF7_21̻ yqkyf~gM߽iu ѣh R ٮG YR{9ծ2(Wm޺acla^PzY&:mfva[~F[VBnq،Hk\^UΨc ZQJ8ޚkWNI@Ξ ZM?e:'Rܢ9/c7Hhwx#7)<(EEB2Q bLW.CyZ=GԞR0厷6B9*Jb8赎8ib7ህ-(vs$%rT UҒ6^-=~ *FA!="9Bwb \.VapNTm%nU^~< ;awm7fA7+"\[!GxMnF?7]lR IrC;)"ttB~M8I>i~Y9Cç.?ދ%g1, 8#Um Њ%̛e/MQ1BR Vb _ڽ[O+|vwMaR>M u%%Ϸb$Y@p/F ٺ~R^(=^hQ$j[KtfٚnR/ rkC=8L%jxaLI<4?5nY\ء*wp&u_=q?I$b1‘~ MaP UHLdP57@?׏T`:1#ڜ#Lpk?ر7C"yD(qb9?y| 01}ItǪXm&38գЈE4˨G(D΁Y G?+kO])0n+4Xn;%+NY wH.“VY{ZN>OS"M2Vѩ<:PG5?ʈrjv^ӎ:ZqLpJrrTڗe/./ ?ѫu5baIk_Rb\S~>tK6%/ZY[+Vb|6[H;gx`z>cl8Uʹc۞/a6s<NuX鸹pyN.I@5: iJ8d`~`rTRhZnT s#h9fGTwhkF],}侦Js::-.J0dc Mʸ[YrVViTl)d!0 ;܋Nt]Я\WN %l9Rptr(QA7]ܫE%6}e؏"Ȁm&AuݹT-t7(Qp1B0K |BgA ݁Ȉ E+3mwdC0~ sӷY]sDc5&3RY?[Qq[~ſd择@l6a/]*d\J v8]wv0Tr;U6 _h"qZTѧP !_wR&EyNm[ui!AvGcm{r~?~bVѯwocDH-=EGϪu{q:яBX7&5w .Hq`DDαu ޒikԏ[1~1QjŴ4rzQy{lr8 xqddtAswdg. t5zyz5 MgQՋGєzPBĴx@fw{o’METo$lt.'X6]ޥ,i:x Sjh7錠J46fg{7 Vt,}G½~>Q x?YǴ̪jQHYܾf{ixVa-*6scH5`#M0Vɫ_U.5r^lYJb_+i3#Y,U:Ca^n%UJI%X3G塝X-$-27Bi>kA fxN,~_(2}W5%RJOJLP UR#= g@}Xd ڼNw)=#0!(YUQ*ذ*)UUF5AE*f7/~92Y{6;&-R oMMJA0U~_Ӓ+;]R`b fͭljsh2?J7C)O,I`i]}W鑮iR(etbemon-1.3.6/.git/objects/dc/0000755000000000000000000000000013212013160012705 5ustar etbemon-1.3.6/.git/objects/dc/53fdb88a7fe8ee0bd7ff225e7a0e79ba71c9990000444000000000000000000000363313212013160020400 0ustar xWr7W+:RVxl'YIKi%u.8`&F2ss!>T9h-lIO?o_ kK4I}@3\fȈHrZi aeDE|V50JhόQYQ[IB%JQHv'~/4ZrڇD#H7*Z 7:@4wZF*t*¬G\e\_M6G`db?R:&g&G!_JSR>D *Vq (P9~Nlvށ uDHlfNJ{TE EB?b74Ҹ#FV-8CޔH qAIAոf{ 7 ;c̥-0Z}d#ԃIUI$I@)"A 2W6ҔmPDͤ^1֪,>"iʍoƮЬpVFJ"L`Q .;WK$cQ$`0)5_YGr'>uQs,ɩk4{,\B+2%|vK‡Pgr; (:A;''[Pr-d\"ƾ߬8fd(AwHZ@hck Bv XTFJ86TL%bB{6" tPDhƾONf~8{=9yY=օt +ncy9czuIۣU_@\~x{ȯV;SN K^wgC1~wsT+q'`l ȜSV!rfI8cHнJ+#Eu*ǝyZ/fiޑ^!n+~_h 3Lr6߫G\$:P*aEame҅0K}%n jnn<.c:īĤ{^:<ZQ@@uȻ<.~6C~< 1;0!1zF)V?s?f;y˛?Qt rς ڭg乒 ߠ,BU"6jL7߻f/^QkyzGF毙u+t.S,;lrǗsyХn?@:2%YV `#ԪRn٬t?巳7Y9i T9K jbL..'h^։oeRqlzؕ7[yaWG^I191|%oˍРCIY3y]OW8Yέ6IAgsiڐL6_-~_̓(?/@4@{)+VT;1}殄 vss̵MJ^Ų0ݴ(?[etbemon-1.3.6/.git/objects/dc/8d16f3360e1ef50c57e78164ba6331cc178f3c0000444000000000000000000000027213212012101017753 0ustar xKj1D)z]գ^;h1>]J)1(*WC1QeUeetbemon-1.3.6/.git/objects/dd/0000755000000000000000000000000014173223022012715 5ustar etbemon-1.3.6/.git/objects/dd/0a6e86e6f9e00d24ff476f66055213c03baea80000444000000000000000000000141514173223022020047 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3OuKjXJ)ԼbgLs|B@bówM. QlvS_BͥiwڏB'3U[|{mG=D6(+vcM@\[*Tn z#7?sלĵ!zWcހZD3PV7'?91J9m%UJx|-*k&1~z~sS7: p1z t>|}Rt|P3J+ J\f,g4ۭk\!*K /q O8⼀Z^b`|05tz]XȔyL%9 ÿ=!ɜ$Y *RX-etbemon-1.3.6/.git/objects/dd/ada5a9894d50f79b7fa7ac4b29add8391c35c30000444000000000000000000000276513216420070020312 0ustar xm{8TipaR˄\BdD.Yb%3{:sY3gΜ3BCJt.6Zr[r) f=.Bv3y}{D(wVurp0 .R0̎rnʥua&3,Qh@ `H*p+^N0UCҪr"BDJW}s`D31 0!O\RPi6((}e,xWωkt6O>W¾ ۀJe7ҋiG] a!Ch":-Z2 thrC7+r:%ρP3ݙgf*gs;9 |ڣRcnfZ:y؏sf  bĐ%&v0o5K j&!% #YtV"S 8!^)%ӲN=b%}Og匃KeBPLi8}ɑ<܉Ӗv5g'wf^5gꢂcW̤t7Q¿0/k. gd d&=T>T{/oHwPQ?W5Gt3oq @#oQ3sT?{3υS`sŤ|:SrL sFMa)\{(u;td^tQn X/˨K jbR T%29((c\Cָ92~yVA<-פH*m!س+I&{JvK-jUVu85/6" !=cQԺ0Ӊ?/@yu+ovsG]Co WG{5_ncm+??]Gy!ʼo(4dLqxo2k9U9x|F׼'\<7L\@H Hzo}nr,ӮauɟxOetbemon-1.3.6/.git/objects/de/0000755000000000000000000000000014057341606012730 5ustar etbemon-1.3.6/.git/objects/de/69240ffd9bcd75c150ac23088cff426986fc1e0000444000000000000000000000141114057341606020153 0ustar xUj@bXJJRq4--- YZK$YhWn˿wf/d9sv=KV3g/^,Jʘ1_Y~l\ѕ8&7}S\xeŮ/N|-Ytw52!pzl11VX/{Rm`bgm i(%tQW0m5ONٸ雄|c{$dEibK0Uy_Lal1F.ڟz{hB|:ɣas|F'DCP6Abp 8`*4&6BpR@&*u(bƳmq!r^u" ['Չrubַ$kMJtĿ#vwxǯkR-yX)P"}~)?cxz7κ(=&ّb"Ta"78EmPBgז!N5,;ID6ф֎ߋEf(Cګ~K1"ZnծҨdwhc7jjIj`HF(nFEQqEkT6>( q(C9bد '*g[+a?ZHfetbemon-1.3.6/.git/objects/de/88c6fe2f70678de1136576067ce2e82f12d0ea0000444000000000000000000000126613212011615020006 0ustar x+)JMU073`040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35ݢ{%\\q7tW)Iy [x^RQosIϸwҧ@'3<t,/<O%D6$e{+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35ݢ{%\\q7tW)Iy [x^RQosIϸwҧ@'3<t,/<O%D6$e{hOz22Ib"#3etbemon-1.3.6/.git/objects/de/abe507ca177ecd1aef15591b5efd3288fba7ba0000444000000000000000000000141613767545115020525 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3B(GaVvqlrNfj^I1ó k_>v 1ٻ&_HIMLc`(Sğz͹ ?3nSXv8!% 2L9?W,ӖZy $ 9r,Ԋ 9ɉ98YUopOgIKO9;= (-88򾭺V p1z t>|}Rt|P3J+ J\f,g4ۭk\!*K /q O8⼀Z^b`|05tz]XȔyL%9 ÿ=!ɜ$Y Xetbemon-1.3.6/.git/objects/df/0000755000000000000000000000000014173220144012721 5ustar etbemon-1.3.6/.git/objects/df/0134aecb8f7476c500c83096eb9756d9c1b4550000444000000000000000000000074114173220144017724 0ustar x+)JMU033c040031QMNMIexwi_EV3csTT!(X/7?/$A-3D7).HLNpЯxQĻlNg: 8@$5鷦Ŋ6vS~q֓vPO)W;?GqelM;+@uUܚ*E,7i1jzN~bJbY:YWKoaQ\8Ti"rg0Jz6ӔoYS(+(;؆kLMf]9LinbQIrI\m*3gʪNEN,}-Lm~ZIQb&<TT.X{=@UɊWj©:U4 etbemon-1.3.6/.git/objects/df/d6bec5a4b759233584d415d757096415b1105a0000444000000000000000000000136713212006716017556 0ustar x+)JMU40f040031Qs fi^5W~>wu`~V-:֖0E% [Y'./1Cǡئpy%E9 Nz/\Uƨ`)Vʢ˄,Ҩ7A (%?ȏej0M]%.~9{Q PH-If.3]M/UgKIMK,)a)7I]f^f^ ñ Qi 2]c{ ס*.Ia0a L~B\\yqH#).fX5X,AZ6蜭k*")*/.+.a#ݱ]<[s:M]Q.CxC ٍoEUl{x dUE`êTU}޼ϖCʀfU{nKK5D 0%gC…_շ=k}iZy/cy1榦 E͗H=[1'nۦsmi6߶Λg_>r% 3aOB=u[*=5ietbemon-1.3.6/.git/objects/e0/0000755000000000000000000000000013767516617012661 5ustar etbemon-1.3.6/.git/objects/e0/31ab1ffd56e46c601781889ada6c25a86912460000444000000000000000000000127013212010753017630 0ustar x+)JMU073`040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35ݢ{%\\q7tW)Iy [x^RQosIϸwҧ@'3bXu߱;oy( M-If8q-]+N9W]~qq{ ȷ 1tOݟ6]۷ qL}Q3,XQ ,d^~'XڹjڹŸ -*(a`pޖlҏVmr1(.cڿeK'<}rbk{!*JK2s%A{Bԓ9-It2Setbemon-1.3.6/.git/objects/e0/679f570f96c298a614696320e4421023f9d8e50000444000000000000000000000027713462026461017373 0ustar xOAj0 ٯн"mPJ^VzqWKP4a$Mi~@/iA&%->d*T2%ϲt(K5 >^x,p6?*||eRx˜-0,t"Fހ-r'\M$:m +tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3fS7SkԞ9j*.&d3<`JmSkrUԤȦ$33y^N[j[Po1t6P5~]$b QQ\ g=lǴ˖Nx1l BUT# B@}5c (-)f QOX&ZWdxUetbemon-1.3.6/.git/objects/e1/0000755000000000000000000000000014001502275012633 5ustar etbemon-1.3.6/.git/objects/e1/0b680da83262ed8d495a069de54294f69f043a0000444000000000000000000000300114001502275017632 0ustar xVSH_g*Pa͆bDP]"lJxnW#Xoc@]`ͨ{{ƬlEGã5>(u>XI5؊N] un"n#:aUTTRYٶ/ȴLIJ䔭&R)nYbx_7HaMjbgMƣވN'mObŲ$ry)p8$ ]I͗8,DL%|OdAp Rk%Bm*dui Mߊ.jGhFB*Bn)4i7 pt.\ :P,FEe*T z1h,FTܗN,#bf ]DEI3u"SYtw] P,;| l[7]%c7#8 JYNBBM8 bT6qe^eePAD z:35-{%IvLŒ}8v3pG= PYtcބ\Ci[vsXb@,7%yK .-g-i?z)5%֍.]y2 D,D3rf_K/ ].iMb1\lzԛ}Hz^`N*VX3p9 >ulC iq/KN;fg>ʸ,,-ϝkM|H}8|>=u7ׂ.t\8Os@ չ{\$3V2.Stޒ=9Ȟ"@AðƤ M `l56qGYNv܅ER]BwǓ=ؖ\AAgܾ~DYMjdTX]jװ֑Ye=[n"KÛcz$5(஗$Top6ύ֗ύϪHK̎8~Y;ċ| @nS'*\7;DѳOHAb.¸GiQV'Nze{囲& ѐ/Eo MuцAлHߌ^Nּ7febq_Fhu59+IwlmKߩ%iv-OƠ,E(U1(WưT*jH|e[$<0b иq޹W\.qݱiq,쏛Wu6MZ.clobN~*M~LU%9Owb7n/k"n F5!'|zQ꿥F=h#s𬱼Ӵ A dwe񵄏/tpd/^E7bp cڞϪ* 叶c/etbemon-1.3.6/.git/objects/e1/44c47cfacb8217c92b7bf3465e3ca1b160f35b0000444000000000000000000002665714001502275020131 0ustar x}kwF|_QK,ى@|d,[Ne{,3֬р$( JVCg?6{S=^3I$S>$VhYh5:^YE_2h/1ߙb9Xܖ,m0T50qZF"L,^Yc<|^E$uvE87|YFG&_4f`o[}1Ced,חnL$.Ixk>3<[.׆e7fg0&#G"K˙<ބQ^F{hrdj~i[ dby26_ea^D&. -Ųljnk ?1T5XBwL&P'1GD5G[-<E> N+7riOdO?+!5Ф<2[321M6٢tA4K_fKȶ ;;dy&qA|jerɦxYǣ8=ߋ x]$Ile|a &Q^ގӄ;rVMLvmN:UDߠ1"ZPr5Qy$"+"(QY#ĐWѿ<.oa`5 PzDnd& 38^`[B\!y#S6XToDJq8QjȭjRIaє+hXw"rx2N&8` +]`u,OHpU00RAS$ 'Wc|& =5h>/X1{@n0ZIBW}bdȉ4#=lgMzmz8XJ:K4Ƌ/6oԢj%r3#U͖e`2Aay.]3zfL3u19\SNRVpqn|_.yCrtE| 3(m:66_Xo[J G+|h^TY6|8z$cU)<ɓy4'k}Η󣕿~/.<^k.^Le|Q~ǗG4/ eDtiPB 05|3ǛIR `_&I߃ zvivkKIgeJߩ>Cp g`bT9PQI {7P%)3;p q?$36/3}4`@985. `š8Cp@s(-4ko:ϑ""HǓft(Dwi6g%؊:rCxJ_5 h&SUA%Oe-"ܘpІrk]r E1,MOl!6!,L b.8)NMK r"=`JCKe(Ek!u驙-u 08Ee,cMT=4I|.MU\!t&hBKH ꘞƽ(өst#یgu;5HBH^?V"aLf$Iҥ0[FVi&/x^r#h J@RhIӄEcֹgTt9 f(ϫ҄~o7!%|%1]މ-TU$MEےXHrYOMcl=c( HiAxtz-㽄%2yx 𾏼 %s[x427Lp1PӇgr<6QZQaQ#&r;J-~K-PVm7f(O 2`9[;Dz#FVPkKxZߤUϽFZdAQ22l`&hÒrFiYU8G r;-t9ĩ Va𫰯!Hѡϡf9<$G& Qz4:)@mFx*>V@p K~ o/L3fM!2^sESSz6/&ْ!`j)JpH@>wp5!E%pt,xF˪$&B~@K!nx:SlTB]J֋@ 0aZ5*cv̚q;sM.1l%W&Ubƅ{"<۳[:V^F>TPءC[ց#Kg2MbA][$ŭ~l B,'7ԉ&"p T+\w'qBȚI \t+.̗< 6ȉ]`\AœJtdEr2H-xw=Jpg,0d) I^\K)Լ 4h W+Vxr RoWʰ\'ZW/u}){%!Rf1χ-,Je]RHGqq>Y>Y)MfɛDEի-pQtCF0m6~WܝҺ6/#}WRQQPL'Eyu 6S7Kg\2]5L1h`sɕ02| 5͔jSA䈋K(d6ɆC2J18 ~Ƹ*p[f2n)V890"9SpaCVXqj55V=bkQ  mjQʦUMQn G*gm8yڛo%*@]UAux-]âDi dᅌ좻5 i;0?x(+Ot,%C#"̫|r+n϶sj5yr-0!&<,Ar+ e`S~_=% r!!LxZ.<]y zKPop}Zîjq35ARPNB;@(9R<V~gcۦM9}5DX팰9 Z2_/II/!~ ] 5:Pۺli r yl%N]<y~iud]d ש9Fm*xyOʰ-̞q[ڋ2ۢ!Nl !4Д7(ulCDɠitb!#ށ-R7)C853$Ҳ~=w'{r,׿[ EiQ A*h؈AdyJ^r씨Ci)@ħP#!&v`Ʈ-IlDG(i|QT7^!mN21B ;>0KTĐG^ne= K\.a;th8.L8g:o.~AeY/Y\ډxׇvP;>.棄Bو3KZncO6 3JH "3vBX6ML]he8${iծ~pu-l=@9 W׌6J^6Ѹ @&x~xqN~~?ޕ XvWܸlr'9V[/(z.Dkg%H)3t<{ax]P%D}U=?\tdُ?zvKbԟDž3PY 9WO/ y'l 'KO#fVD ( ١5g:GLlܔt{?ewQUˁUx[Ȟ176^Åω!kI e$~ Q~;eA:*$C zRT[ԯ[psK-1q뮭쌡֨Т\7lpqb?56~XXPym: 諵;jIa9%4j3!R ; a!wJ~^lst6΃Rx?lxvh^\ճ#HW%ӋIDZzm;XZ y)I?f?;>{T%8&%Yk[*n-RbJo\^#ĵn٤c/;Cf.wuc{+I :ѡydzPY<A^}9'wIEv" _!][1ʜ[zHC7 N?)7ol)E1KËߖ69:KZ.u63s+ ~[Ћr͠U>Oy4-#KjmD!Z\,6p{_lArscP޴8.@+O#p (-+!#𻁃{F{Ɯ? S[p-PXG^K=`OU`<<Ǯn]B&Dv4>Yv\'w|S`T e[7^t6NQA7<"5lc}玃5zjmBXd0l\[p> Wdpwyƍ9)$Enz%ECEhAh~ PJWҿ)v`K󊧛x68QRX{C581S zxlC '=s[Qi[܍šPOO"x G Iođ$y٦jQnC5-?1 &ce]HD3>|L;9&q yX+q܅`*T w| K`EZ"b)Z*ă; ¢ E:gc1 zmbA^8skѺCBQhJ7eqApz+xwE;X*i=hXocgs.qI5;?X104'K ݙJ7&\fL[:u VW <8 yKݵgcOXy]\YyI15\yW\21ǞQ5b(~C=Bktoޚ;4zt2y?ʶ7 U2?;xgBqsIxۮ scмGk`dd V3fe~wJTi{%=f!ߠV/|I\{Vig1Iv/cSB4Ϛ{^NLGfF6~3۵TE#ūݯʡO4~m9+њ0N)2(N戝< ڗ\,pU[N|PF=Яb1[ղ(a˩؈}app59;͡57f'hVv@n}!8"L~;t\[kI*1{N;b ketr:/J,yߒʦCfSK;18pH&T2Ar, ~5N >xml3_St"YHD>Ob3> -ȹ{aꁀA}g$z ]Xtj/'m.y|jv~&ax u4c'eş乞&2l#gdAѢ"2{פ'l-L'Ia# Sb!\|x?sPyDK6kǜWv~|8@)aweWϊ zQL-CyC4gjKJ ]Ō"\I.0mTFOV˳:<< eOES[HmBmg{Zg2 LY Ks =ܺʌO-ڛ\{>iC/0/D:.Ǻ@u<)3H",l3b VFw͇S9&+{O2@(g`K'n{hGϨj*+K8\<,p_Q2b<|V6xSTa {+| %w(T=rT L_Ip 8WWSN}Ab?J0Oӗ;jT9Ӵ{L4E@g.Dzw8+e-VsKea88glǓ hQqCh#!E85䷚Pj[;QveKMArvF<=ɗ7>ܵnQķ8vԌxGpL/Tݵ%3 oѓs7?Uaz^qBAGi<3+[K7p>B$wd:Lv(FK\_41 UENzǎ iI2p\~|öW(Cb՘5*b LVr#abLE}Y23^wmwM ?*r`)R!),s֕ ʄqZ˶$TS?҅L.~; <˝"Wk<됔GƇ̬T;5COD^SEz۪g dupxD[ɲglvW@Yu-V a @J z.vLF32~ߛ*Ւ[5ֳf_jQF*hh/y@AqyYb9nz&V-#Jۿ> ptH(}{ h!ߩ4s!n_P#y6Zr64~xe⮪'k{D1`ľőf0Bf 4& + ~dQuYI˜7j&w Vၶ`I?)}etbemon-1.3.6/.git/objects/e1/47cd5c91881696e91e354cb0f5984cc27d3d830000444000000000000000000002471513462022676017704 0ustar x}rHȐ=!JqXTeXG#6V IP21%U%Ds%d`f7Q>fF5_<4WLop,ٟd"hP'&i ʌl1 W&4r6 ӕDs3[Nx1(̄idY4daI8 n9i23Y7s57i|:s<:LfhgxԄ|RM8ӳZ:~p#x30td,[F:k4@t"3Xp~>P Qˌ,\̣NF9:,eAo F2e8'Nm,!19 ﰼuR(} k#Rr8¹Y.SmI0"Mnpˬ O 3Rq͘7$y{Vyretj$8j_kx[-\letl9]=mc!'  ˖dvāW矿;s;,'SdQώ.7̟SkV7Q%܄$ ؠ6Urpv7i\i{ qEx^@*dl"g)N23$N 4 E8^|#Dħ1X(J3#L-٘3mH>- (iE1ZFՇwn,!NlUZ>D,f;4DÐ,C1Z],3S7g $2͓*EQ?ǹ'H\mWo&H{d|݇& QޡKU[-+3Lly@J1]ged#ՋyC0 qE"F z7OF@B ^uփdPʁd@;= H;f'2UK$< xؤ46X*@ ,/ !A"}tK{1pw*J:Qxlya%elRBeR/S13N&֧s_Rr:VDN @\P^os3No"{4Mrkݞ;r$ljabM9H=ú:%q#X: r+"P K%=`8L'B3S(ˠ4Bp(XWWRL6BaaM_h*0Q<﯄Kӧ}:*ZrzrTIh-i݈æ@3+q} @q}K,!B!LF) e^Q.gFčJX+b(nB=LT.;:.Y-vbŴ֛tvwb1JAo~>qUˎ%ewH6eAoAcޔl Aé=%<2>P' ;Jgg5o&rn`5b.K]-7[߅U(P Ve7z'0g"dAX; ̏c,80IN!Jz+:^7:FJZ&\5Q(l(.pЀ0Z@ܹ ̗s* LEaK&QB! 4KR#9LD1ҙߨN3-a<؍N+~ K~o/(.ZBF/u૤|T )mݛp:dI H>Fr+8K(hP;XQivlCyP ?K!n"E/Wk Lsw2_|tDwCU8KQq Ou,`skJ|8Q3yZUtITN”ɀ~-bc$`"bVz)Vm  Ŧn@A۳[eHqW1Aߪ.vXA=99z//k)],*RkT& XgXOnSFW T \w'yE4>gNc~@by|.UУ/h4Jbi+"?|_CPb[Ac0vAۅ:*u.]B -&K4"|'pSnmaQ2#b-UY['`Du>jY> S)E"'%p hUMN XT٫w\SO)[BJ[; Zk^|e5+*|^ YHvqʡPu7e4_逭%j x v|hzǓ2| _=~#ΪmvlWuֆÔA[D ~3z8 *d@ު:cR7Z]ڍ9t/f'f]2W'9asMarK_$ĸa,"̀ ›e6dfUCa%yK jơ2 kCܲQ*hn%XO l_sU /ta)x#y!Qx F~}=f5Nt"LFH\q2/6=5jZib}"Э7KFKԪ"x΅{\cJ2=_1+'/2bu!CQ! fiq]?8CkȪzۀc093C܏M>g\ەɟ6:^cېfAey~oWye㘠tq5JUXt5Vp.c:>-pGMFge;O0qn꼫d"cZVk8/ LX=o.P׬C)l${ת7kd!k\!.5C=kV{ہ'N~dw9;ƥP;2ŜO:y~P8ys;NݤjAĘDH-[sH?m,b?C_p^ ?B TA5j5Z`*ln3$3@y npBmLQ6ƠIc빹An,Zţ<fu-]'Mg}x'd~h{:ġnOg"u뎉7[; Y;Bc(0ixSG{n'u0 ѝyfBaAJ eE5-ZL$KS!GML/40h0$aME[s7EߩEͪj7ddPxUm>|D#k38XVxoNjǿ:VN;ACJ4vKM8\os(kwnw{ҡS ܈cDǼJ>ǑѽD^l_/[fSl q'El\pJ-ef7,K9J}n)@ħP -/i,!~Tf][,3<]E!eDQiX@$.$Y]"#?" #h/%s9С9p4xdϸ!L]Ԏ`ʘƈlؙK[sB<Ōر_ EfL!`w.4)Q:{LQT=Pd~7L n|jC}ˆB5gW;#u4teqRx~x66R~*o(9XmY\8orgp۷P_`(0GMÁD `''OmS aȺ*Q]nYxFE,*~sOIFey wϟUӞtp[W Q-7Z>8;9 4Twk @j]/OLW&( WfN!x <ęC{VKaW3ﵦWC68&CT"%~l`4Xv,p$q?#`@,s[,B4Ln,BH {M!j2oxdצxNϚvհUy~-p<@) )^ ɕ 3Ӷ])E7KbV_% *@U!f4nŹk^;#"Kc LגH,wRmFh$yMC1Z; R+=$wRKT6[K;W!GU'mTl&oVwU* ËQIjmസ7XPZ NdzBBvuɺra,;UpM&D y^wei?WQBfb!G't1<(W,<ÝfeyE<9Kb j敱;䓣W_..N/փv'(jXZkR :O&Od.wRovw,WaT$1Q p}2e u8'V,Bn:BfW`xL[6[[]!$2R^p ŝ_ NOVH-y8 1Y M1: B0Ȯ3[zBF]J[4rXC6G[%7(cd!2K-[ E"Y:J䑳{G0b@n_um|m#ubPksqbɗklMð +vqJeɟɦ&N\#D̒YuȈL^l8?OܕD;\dtpU,Ogu{ "(e$əWv~J W\ DwhЎy*n.Q15 dhp zjK&J ?jbFJ 6*0}d;? 2Ϙ9ѺOH'{2vm)  -8k7ѭ=iBB` ƲGSڇnq;AJO%>Rw𓻙fu&CM4[ߩc[@CicrZ ֝49p& arR<$|6AOU[&_݃C <|BV'ʬLØMyYI_a2bpR6Yxڮ8*Ȱ@ vp˂]04l`*U>l@2…$|DN}2 S.R+2ߡJz`v) ީK5בB4z ,p ލIx+J?W*iG_qo zhyDBaL Da,[ɥ "Y֎Qnemrbp1h>/eWO?ߨEuixE1fnNAvmzѯwׁoH6_05BM^o~gu8e7nN}eJG|x KQA..Lv;Q,4DMJjŎ͹K~O)42q}f?uE`chY5*b thL6ߕכuU:Ё Aÿ4ajƪʄm-MhZk#|J92]B'3X\)Z䉌@UL7e"1gj"h׳ t qD]вՎR0P~V5`PJ@s29Q wW)4F߶ʼFMz.KP4QJE=n3}ٯ`znĂXv$l#0t[Hisgb"*pk^*.Bj q\]W4q=poI Qj \=ٌ5@Q 7hfXHb2+\ENJVep,/ˣJ&SnfY5R\`fi̒zme5x&јa|W42#AЕ…dNgwG[1dG,;dByci Y.`{q1jm95f4^c͉s˔Q//4Au2 vٱE1i<#Zt-T>()@Wm[)H%~GX\3=AyN(VF%E$e`GۮiH̀@`y|N軪)ɖ$7xJDUHQU ?t-m6ktFe%#9nk(Du^ "o/rxK(?6eaEɈ'jDD(}ʵF_=nCDM㇨}iM!=U4cҸ,Um1B70$طb#FBl ݤ5qn-]"\W}:@񾉍m;B;etbemon-1.3.6/.git/objects/e2/0000755000000000000000000000000014052407067012645 5ustar etbemon-1.3.6/.git/objects/e2/5242ac0a01e70e672806d25498c51f62a7d2d80000444000000000000000000000105113455033406017542 0ustar xmSkO0CV"i6 4`H`|b mcƑк];J|}}tR Qtao8pd㻬s%#?YlA*Sv>!MI|*QdĬ4i™|"t{^y`(X (Ky&6Kǻ]x3GJF-c{ίTշ/ OY dSr)t) uh_#D{.EEMz=(~ʵ($|m|칔R('o3Fwm2C%bmu sIpWp!wRȚprr}zu?8_uDmx~V)wZ֒4)p jM2bS!I4y48h5LrA![!!nsDa4-T< a)-u%J׸lm}õRMrOetbemon-1.3.6/.git/objects/e2/60330b9ca808a3445807de2b9fc1bd426edd7f0000444000000000000000000000141613462027016020052 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d~mmL?2< lrNfj^I1ó k_>v 1ٻ&_HIMLcoǺx/‚v;nUPWmro}_)W,;}Ԓd<,mOCpEe^ޙkYZ ONCf|sV (vYPL겄y]$b QQ\ g=Ǵ˖Nx1l BUT# B@}5c (-)f QOX&ZWdx{Y5etbemon-1.3.6/.git/objects/e2/c3d659c68dfbe43b7dca832f165c5a890b4e2c0000444000000000000000000000027113212007705020216 0ustar xMj0F)f0B)dMn0ҌhlY&7[<\t}&$ɆdL l\$/9EKPjv fLDxV&zik|~ # _\O@;Qxُ^}_~(kÖ[yt)XR4CVetbemon-1.3.6/.git/objects/e2/f138197c703f7e71eb6356761712bcb958928a0000444000000000000000000000141514052407067017524 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3B(GaVvqlrNfj^I1ó k_>v 1ٻ&_HIMLcbkqeO]ց*Of6>۔+_{lj PVniܹrT>"Fn~C9kC>\Ǹ#"fnN~rb0,|"$3?mVLiOx WxhGj5X p1z t>|}Rt|P3J+ J\f,g4ۭk\!*K /q O8⼀Z^b`|05tz]XȔyL%9 ÿ=!ɜ$Y Xetbemon-1.3.6/.git/objects/e3/0000755000000000000000000000000014170643332012644 5ustar etbemon-1.3.6/.git/objects/e3/8166d21a3e5f4b0a4cb036e5a924f5ab773fd20000444000000000000000000000267214170643332020051 0ustar xU{8Ti1RIVA+DDUgN a1)s]Ej+s /R:%`RW(sU^'8K"0 ,pC[B8(_I604d(}&BzC2b qDzO]'\0N.n4>wbȯ)p=q$1{gVg=yRd ?E6gڗ4%^霊 PڥpJNN3I($T#-4)MQ~?﫯_p<)a7-zG&ۙ"E]"fv6W!|n}aSÉֲK#G ?N^ b-VQ!_#r<nM8;Un1p.D|3zYm6t˳4£|~~RUE:f|Ґ]hISCh/TtJwu-v%BH|^gRխH1w7+< \a^gy`0a!); ǯV~"|4~:✌bm:kN{EmIQ> UG^nJ pp1o/qSQT9*zY麚v+~VԜdݫO籹Ξ1!YˏϗLl6I*0t'9=0p)jZ)䎙X` <*|X})#欹 7%g#)CkZ3ES`9Y^S l`i&JA"DZK:2(u[DAjEX_aWyM"`sЙO:㐄9.䰖eтv0>Dz}/ ~r`_8DHc,!u1Qu {\- )8]go*W @˂-&7wyaDXa<GP=rד|sy.ې`ϙ60netbemon-1.3.6/.git/objects/e3/8192e456129c6477f8a687093279e3049d104f0000444000000000000000000000267313514461057017324 0ustar xU{8TiAjIVAk\r[1Ǚs3 QKE{b]RmJ$f JT "KmmN3G!Lqrt\ R<>D4gun;uCnܘ&(øp<+iTL՝A$HEYQ2dqʍW~mtq3O)0yBRj_I1\]P_JT@@ʦʵ!Rm7zC!ە‰B^$P)1AOX>um[MB%&``YPMֻ wx\>&$+=>8m+\Tj/_a<\2ݬkkQҖ'L"!!9?A:O -W-ݚgS֨ߑvZ={ϧ,*]&(i>WeՒ!ҹ?kϫ8F}N[°*Nj&Vy-=R#yʩT>ppP*I#NR# O[tf~eȮ+(r$XlM=8YA)`cR+ef0a{jلG6zx᫊̔t; &Od ,Dpy7VdS0^ Im#zU|T1𩋙B H i/j*6 )s=N:%AamLYɝKxTmQC~$B TڂXoބ5we+L=s,>YE-}E2< (kZd^/DDcBa)ʖ93Qa^ ٽ1 (Y,hAËyVIisZd0> )|$*8bD]qP9" yoIq/MJzWV\?wB4g%w8m+i QX(3!w}7Llrk<:*H ᠸM1fo K;bq%/iC0B!>nxmh3^-etbemon-1.3.6/.git/objects/e3/d993e093e161e6a2a509dd70e561045630c9120000444000000000000000000000120614032516006017462 0ustar x+)JMU07d040031Qs fi^5W~͢o(lX*"ϛ?rUЬʽZxti7}@E榦 E`85{mYbgN1\͚[='Ԯe2 7nZSX0Ӻh9$S%#],etbemon-1.3.6/.git/objects/e5/0000755000000000000000000000000014173222336012646 5ustar etbemon-1.3.6/.git/objects/e5/8b80dba9129b5ee47f57f4515974cd1741ed370000444000000000000000000000246013455624272017753 0ustar xV]oF3ņ1jE)EF@Z716q}H;h[M;d)7>vggfW&'OA8JgU8I[UTzS/!2\aU*沸_ߝxKZc08wV{eP'3m-xjw8] U*;XȒronٟ߽9{0sJ1>)rD,/=, ;>AY2Q"dDOIMii{7]H+ISzGB!ˮCکRZ>Ә*1%1X _J$ rIBSDUn !j( Za?de]B/iwaXJ][wLjYLA2aaD@BaјTcKfgKM34̭CR9zDv5um,Eb[9@ &ocmFa<d3P4@{U* i#rx;KlNR",'+.iݓGxHfaA&FVbNK̆_OK>'DzcJ`jCP{sYt*MU}IT*Iлl ƫJtG]Q08c"t`}|vřb_ݠ!uNp%&1sXh\,CRDpŸ~yAGO?lEbX`YZ]qeYZErV1\19o3y~GbXښ?| yJ=zq2NFoQ>ַkWn_KF#=jmrmR aV%q8i=ʰ{kiꟙ@{d0afKgK<WIHKܞ?w^DJYn+"=eOiػ?4Kc3O`q<'s!J6`+%8 W8Cn)8.k9V!1};0j~!Xp_8Jۍ=q7K}e8E-7ɼ_'8b,&6sr.?RB.y#3Kmr$}1a}KQ;I9bO  etbemon-1.3.6/.git/objects/e5/a7a458f197b2d0c179ab943f5b9706af7dcb6b0000444000000000000000000000141514173222336020151 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3]+ꅉIV2Bds2SJm0] )5*DEJjRfbó/L Y2)P u&'ߞurŲw}|M-ʊ--c;Wn'[$c5'qmȡǕk77`yV ONlrg_v~  (I #}T~MNCh^qAj2lḵ2=_9f>Ԍ Ym9v+hA&!c`8a;K\t7!'8/`V) n ^q2e{yES(DEiIfN1üow>hOz22Ib"#Wetbemon-1.3.6/.git/objects/e5/e22e35547169888b18bbd338809622fda184e70000444000000000000000000000026713212006576017530 0ustar xKj0@)fE!Ռ-ɂ z4!Yq |<Xځ}UHSH>1;N@f1ea\e("N gi ygk%/FLG)GkrgISKc, 7OhQkzUC>4^p+[S/Retbemon-1.3.6/.git/objects/e6/0000755000000000000000000000000014173221203012637 5ustar etbemon-1.3.6/.git/objects/e6/2fb208b129ab0085bd77cc096ad2698d4e05450000444000000000000000000000023114057336772017722 0ustar x+)JMU04d040031QMNMIe0Ż⫺E}+RI*)J+H)H-K.(`S&7uj)߶A&$ +VV;jW<7a1AW)lpz}W/.-?]VXzCetbemon-1.3.6/.git/objects/e6/538f64e5aae15d3d02fa251cc1a15bbee4f5ed0000444000000000000000000000027014173220327020333 0ustar xKj1)zlrld 6Q ,+j}2h2Xr)%B~?Ǿu[\ ?sx\AH>RaV4mާ̄G?qj۞<ch+Setbemon-1.3.6/.git/objects/e6/5a8fabf0bd151817c457adbc6bc61543f263520000444000000000000000000000006013247732002020035 0ustar x+)JMU06d040031QcJ ׻׾#i,X{etbemon-1.3.6/.git/objects/e6/7482efdc253496829c196811f2aa9fad6bbc360000444000000000000000000000141513276746454020037 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTPv.hMvZh)TIIjnANbI*Cպz SD2dǰ7!aMw!9y% lcN!*RR2vmu0jkɂ+8j*OfL .s|Ȯb{K % 5].Sf/g橫ۡcT)㕙OlufnN~rb0,*4Mo᪀BQy6h6Ґ mW\/s];WM;wSԌ Ym9v+hA&!c`8a;K\t7!'8/`V) n ^q2e{yES(DEiIfN1üow>hOz22Ib"#/ Setbemon-1.3.6/.git/objects/e6/827ce66bdde0e283fc2b25835a8929945656280000444000000000000000000000033213514461105017606 0ustar x]j0S{~,JCnV1-#Оo;;| m[hiZDϞ4ff9;71I~A[ATJ#A,Oj$X# tg.8k  \˯8o GGQiHD-['Nj{k^@-xZjbKޡeǑK Tw.^Ⅹ[j,=Bi etbemon-1.3.6/.git/objects/e6/b0356dadfbd3c82286c06164efc39bba9377d50000444000000000000000000000036213314346054020143 0ustar x+)JMU025g040075UHJ,IMH-Ie+So%h٧g~@%g2~|B%i![6OgB(IMa0{Rd+bvf6U_"T%f3<)mwAPeZfTǹ'oY%rF 3dvig#g3L]^`aV /71JD–\bj6ga) <C\i etbemon-1.3.6/.git/objects/e6/c08f28e9623442e353ad54abbcdfd0db1c64510000444000000000000000000000120614173221203020112 0ustar x+)JMU07d040031Qs fi^5W~sn)-H,ar==8qy9:|6-+)a`\ydzg˄+),L(a۹L芰"N/z+ԠrRRKsJ:.V9c ٕWjp +,*f$՛ұz>AE-@V\̐joʫhrgY#IH-I-f`Ѿ")p{Rܛ.3$1'g,^ʀG[9ԝ >,,'3/a`jĮsʯ]j dCܬnN|bw27ī1fQTƈ@VU 6JJUQ`@P͋l9d hV^ jvT>"sSSRP0MZؚIe6e3jfb fͭljsh2?J7C)O,I`i]}W鑮i-etbemon-1.3.6/.git/objects/e7/0000755000000000000000000000000013764536645012670 5ustar etbemon-1.3.6/.git/objects/e7/7ddd8c10d147af996d9fd2c409adb527e8682c0000444000000000000000000000141613764536645020206 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3fS7SkԞ9j*.&d3<`JmSkrUԤ<kN-MrEBw[ MO=6eW"Z K3s{:m[oAйkNڐC+1nxoH( ſd$0/.iU4\P>[U{wq|q}[u @c R.g ǭ|&T7fV00Xroi[Gr6 CTh1_ⲥq 9y۵PHapk2')ck+B!*JK2s%A{Bԓ9-I[Tsetbemon-1.3.6/.git/objects/e7/e882c4c417bc6ae30439e8cc50f9cfcf83fc790000444000000000000000000000132613212011021020224 0ustar x+)JMU43a040031Qppsw KNdi^޺^hM4U/1'j@=R ~YVU!8ݤ<ŀ}fUԘAΣ*32&צڲ`$5 6+?H& /y2ȹ=0Tf3 g;Cwʗ єVIP t1aerЌE_Ν 1=3/jgI"BA7&5(FSX_q#RMϝz *-*H elΝ],#N>6 P4r R2 S$of+͔񘴱1\.G,ö4pO|WM~3AӑVRX0q!,j=NX>+8'?nT?7<:H >T %E .3՗]Ĥb{ *C:zT{w.TmzN~RbN1C/+u â^/v$#\$_($U7Qz%% S<~J[~GJM,gM,ߜMTuq¾y@Ղ屟C 'E}I^doPg3lƑۤΐA)h>sҏi3lb_ Nfnetbemon-1.3.6/.git/objects/e8/0000755000000000000000000000000013324761313012651 5ustar etbemon-1.3.6/.git/objects/e8/516cc19baef1d5fcc8c77a82bc282a94e9d2200000444000000000000000000000346313304753620020230 0ustar xXmo6gvb](M)Ik46` Y#β$T^f}IYNt/s'rF?x웭owSt[:5FNAERsCU. E*\ŽN r7ֺdKI۳W2T\ҢV07#J99}*9X_ʹ+m32J᭸JK(JfgUڂ1$v8.Z_d>4ƨiA޹@$IF8n(4|0 pP9&/=aoɖL=8,B`-$Xͭ UeSXwy,U]Oѻҁz?ؤ w7ʫrү\o>/lo+P볦?Լ*|`xhFMr{tQK -ȭޖ0W#1 P6Fyxjt! b4u0c+cߙŨNjӠCd@1[ptQVAJR6@Wxe.ڴ0sDDGsŸ>N(a8 b 0_|j<i:;=$JҌ8!"q{`[L>x,y7⋂0^'I6YS`31xA 9`9;m^!57n}ѕ0.𹏏3 Wʘ Wc#l#m˝f#$@܁xKil2b$S SƓP?$螯NO4;<̅Ǹo? JɑMjL1/u#(&qcH܍!Mh9ey@&x 4sun:pc,ur\E]M"H8^P[]:Į#T-j_{!=w";Vlc?aCooo m֝O Mϙ.|<8:ԣoapFHL1R/O{ ~j?5vR%6SNU7A"x}|Un|)zP0Ö39d4͹Fsuh  %7'(_ojh JÍK-n6`hZbtNИDm "T:etbemon-1.3.6/.git/objects/e8/cc468b8b8f51612618072cd89ed9bb4a8e90610000444000000000000000000000027313324761313017744 0ustar xAj0E)f,PJ!nzhܔXUBn_ޠ=R>FSEgU8fLI❲zsӯBSĕ| 9̞0JF#>޻n\M+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d~mmL?2< lrNfj^I1ó k_>v 1ٻ&_HIMLcH88Mq%lAJ757MO9 ?a۵~_}ePԒd%,f.ؠ) 2G<[,*Z ]S:GjfnN~rb0,.R?'>տB)pU@y˚b"V%.; W\/s];WM;wSԌ Ym9v+hA&!c`89K\t7!'8/`V) n ^q2e{yES(DEiIfN1üow>hOz22Ib"#Tetbemon-1.3.6/.git/objects/e9/36853e484f76507a3b4ec997aa73a2da8a5ac90000444000000000000000000000120514173221067020017 0ustar x+)JMU07d040031Qs fi^5W~dkib_* \m NchAàz_nW_DLP꺴*>W;KlzUetbemon-1.3.6/.git/objects/e9/9e5d583b897f72b15cd562b9682b56180c05d60000444000000000000000000000032014174476546017623 0ustar x[j0EUhÖBK7PJ70#-I]~\uѼ c¨ 5"Z۰pj=rQ[Ú?Ɉ( SmZyY#߹<ijHk5;e;{ yksN29{ $\>KCoMsW@؞-LX?a+etbemon-1.3.6/.git/objects/e9/9ea4b5157a8e6714c9bcc94dcba0582bf861b20000444000000000000000000000023214173221432020137 0ustar xA 0={J1D.Hߊ?8 <; 7^=ǤyB=g-јg+!+M^,z S EYT'L|$DPj,|¥>8:Go-Fetbemon-1.3.6/.git/objects/e9/e743e53f1d4e99170787532fe89527687464c60000444000000000000000000000120513455033406017414 0ustar x+)JMU07d040031Qs fi^5W~YUQ*ذ*)UUF5AE*f7/~92Y{6;&-R oMMJAlշb#qQp\jb fͭljsh2?J7C)O,I`i]}W鑮iQI*etbemon-1.3.6/.git/objects/ea/0000755000000000000000000000000013212010753012711 5ustar etbemon-1.3.6/.git/objects/ea/00acb5bc4ec6dc39fd4ff717b4e761186f64490000444000000000000000000000132613212010753020216 0ustar x+)JMU43a040031Qppsw KNdi^޺^hM4U/1'j@=R ~YVU!8ݤ<ŀ}fUԘAΣ*32&צڲ`$5 6+?H& /y2ȹ=0Tf3 g;Cwʗ єVIP t1aerЌE_Ν 1=3/jgI"BA7&5(FSX_q#RMϝz *-*H elΝ],#N>6 P4r R2 S$of+͔񘴱1\.G,ö4pO|WM~3AӑVRX0q!,j=NX>+8'?nT?7<:H >T %E .3՗]Ĥb{ *C:zT{w.TmzN~RbN1C/+u â^/v$#\$_($U7Qz%% S<~J[~GJM,gM,ߜMTuq¾y@Ղ屟C 'E}I^doPgȰn)ghKNjҼ.=PS t3P|挥w_fֽž?ioetbemon-1.3.6/.git/objects/ea/f3d06d92649f3dbc0fa089780f6a7c71c5fd730000444000000000000000000000027413212007560020147 0ustar xKj0)zQm} @j3dq&7⺮KcKo"685'$Fy6 Aydwlu%EcȡGMs¨))LLF{+:x{mp;]Jk}HufrG Z8+iW_9Zl羔ʱ z~(ޡΐITetbemon-1.3.6/.git/objects/eb/0000755000000000000000000000000013455034520012721 5ustar etbemon-1.3.6/.git/objects/eb/bad7e4dcc49525eccad47ce17c1c9f71f3b50a0000444000000000000000000000141413455034520020505 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTPv.hMvZh)TIIjnANbI*Cպz SD2dq~ñys;?в5ZԼbgLs|B@bówM. QS{Y/g*OfL .s|Ȯb{K % 5].Sf/g橫ۡcT)㕙OlufnN~rb0,.R?'>տB)pUҮa1'rU p1z 2>N,^ܵsyմsg;?;A(*(a`pޖlҏVmr1(.3cڿeK'<}rbk{**ewa!O SƾךW1BTd3Kv'sZ,d-+2<Setbemon-1.3.6/.git/objects/ec/0000755000000000000000000000000013455033406012724 5ustar etbemon-1.3.6/.git/objects/ec/5fecbf5d35086a7ec8d2395d6192738df101fe0000444000000000000000000000017113455034657020164 0ustar x+)JMU04`040031QMNMIe0L%nm';rvA$e%0):lCo۠j*8O-PPBi*b=0etbemon-1.3.6/.git/objects/ed/0000755000000000000000000000000013764422031012724 5ustar etbemon-1.3.6/.git/objects/ed/018480f8da3ddf767d02408e06ec92306e993c0000444000000000000000000000024113212011025017705 0ustar x] 0})],m7 "֔4-a>4*X["!# "jnETSQ|ۈmڋ]Hw(&y+Z3x"+pZ/` A8چe݌|u_fHetbemon-1.3.6/.git/objects/ed/18213f61204716f1bcd912e3fbb3031e2c8a720000444000000000000000000000026313764422031017666 0ustar xKj0)z?0BBnZedަxu-w/4gra}&VsĘ㽐ě?t  %$MfkFgmvL|<}$r sftaÒ!fhFڬ :ͰI Gyee7-<ã”DNӛ7< ՎOߕe*ԡ?F_q"CVSjA)]AErg1fY0y[=f!Yz𮤠ҥP qΠ:pjdKPXAP`e(8ۭ)ȶ$@OeTP"0R u@ ̓~kʵ>|Ʒnn˗L{VvӔSӬe Ǡ4:k>JƶE::[ o] Nj.6Wo>y{kZh Vh4/;=h7vxhG87D*_\4MV˿YmG>A߂cp3p#y0)-F/3$wfAz ɿ"~§PHDm@DENp-;S%-U-h[Y1Y ;͠>e9b4pe,6JViB #k ܋d5 u@SFYgw3A&I ҁA{?A%K=79&TqsD74=ӕ*o9wJA:AG0sb m*l#jc<vW(`hpHX\!vJ.7%uB? 2捒EFCs{ߍ'k~gu;^O6Ϯ<8ְsU02uL/% UoL2L8m(F2HF+K;GC)>#q*<ϳ<.D6e;h}KaYN49S)p 88{񉭵SRPĘqfTPC,\Ϣ ~ *󲊪oG9qOG~o >bwR.ʏ3Llc>.S(LL`qgi?t ;7IPUš{H@BK"<!ɀv7( BkfapLSܓhJ5H$]|tf3LO3B,Yf.N >]=.1pw˅D*zak^D^6 26g)qJ/S1ilÙ؜}KQX: Rj @p++Ѭdi۲|5k>w)9m3QtGUM5,_ˠrX7"QvAt!V@!+i/L(oAIBYFV*Sbr)PU"…i3OeC[&Gݕp\~xrZ!lN a@{P9jcCY Z~Gu7vC,확~]B 6#Kxa!LFX3phi(pB3VZ/W ng?yQԢڂl:xL7;P"1ץA@m E$4֝Zv,Q-oS_Z=htj-s%"y&ޫ#n(&fl].az$^dž5a̭) GM$/6*V|i;KWTJzwvLᇍhlvpKxyX5p8l l4ݞ߂!"V>% >?#'"Dl-!/k)]rE@M81cQr`moOqQ/() e !q >Ug, `N^ :HS"n5*0d7t^OhWipW,A`E#^ht exDv3Cs98תzf٧hka7C닒i)Bí:FtY烖=PRLOP4+@p 0Mx2n(1C#C?%|N#Na]k/#dޯD]COXx!9^(oas.ޖ(t#[ jhtYbVYzd$ 9{uͅ3%۴sΉgvUgmY9Lb"zP7)SI6]"R:IxFnq,X`3gT;83xCoځh5>DMzֶ=31vP8W /`fy*+8Vqz{EJCYM~GӠmvPʎwv_lλJV)/9FUi}Ą E*<!|G^ŰeJ~jly ٭b &3`ZaV?p%x#.ܗOoKv39uL1DVsǝ<&U'|d6Rl+#,ziwjbX.* sĘ_s-/AKa6ض9[_oЃv0ЙFO1 .Ay6m"=>o>o1MN+Y%٤1\^#K}q^qdY=.z{QsQ[>~l;:vġigg" R͂E,BtKKz:s=p9ݙ? RT-+Ydi H^rS ~7py"mĹۢ"jf][2aed( xUm>|Dyf{c8X Q; FT9}e(%TgTvAk2}`ar^Nrg!?T#ro(<-;I5\hO}Fر_ EfL! ]ѤuH0>-E Յ #a8f'/kwl(TY!BB3@.HX"tIE `KRLjJ &c Bl9An/Ha,Fg 6ǟlXMZר(EObN~ްֳ]$zi<ʼ2ψ*hypt[W{B^8^L=|DϠ-Q/- Tpet|K߂904[/hS֑cwxJyq v[ ϪcJMYke: ^’9E yLC遘SP--6 +i(h`>48(oE !(3'fѱe1bicf(x7@X`*QL?>  ' 4J˜&( 3N1xp9Hhj1=U%U;U<0ӄw*.]GFɶ. Feb"ʺ}1såib;7y)f)-rM!j2d`xdצDNOZNSym<`~= Q k o!?!13m%nМYtZ$6bU=k[R] `䌯dLi6B77 QdDwK7{M?ZyZKcej!;}9?l#*a8`mg(%٨a; jm_a WaP*^MA-Ls#o=΃w),N^L55prC 8*o8: 2۫k1i_VTf;}m%$e;po8=Ѷ=wX փ8ԉY; "eDhAxD'_ JE8HQ-06D^*Ee'o*5O5sB!ǎ)x'Ux[n Ҹ^k ߋToCc*Nԧ4#;R $>rynuΆ7p;5խs>Θ9t RoeXWQ'?3/t#/;LY<h]BduI&W\zGGfIJ{#wLo( .D e:MZrox%,{[9!RUPw t՞#N-y OR%q Tu4[^Ϯ1hY$l׆ V0lS$dC >lM~RyůIv^WZTH@]үVX6bғPW\ |SswvK8osVR.yT%rXTYH VFW8ͰPۛL lq*Yfn6_j6D-+PB ٮY T,)=Aծ) X[uiyѪ+X߲Xqu<,MVa+p_2"o \⎯^]4Q @ k8;oM+n偸{&2HlJ*=Wh:ȪT*X =/co\F҇Ӈ-ˈxQZχ xXh蕡z6YNC-5FS;kC4rYzw ahk-nA$%rcX d6hPaK | ĄjoQZ#9Bb,j.R٠awO-DmՒꛉŠV\w \@T /rD4}yqQos*A3 PRY/ _?inN>ٔT.cX KNNNEnلPc-;Bf.w`k'H*сy^ZsbrKX0LFqH=z.0 Z*rn!5! FŰyhڃl (>Ep*%ֈx Fwy :;ˢu/Z/.G4%hhqG$ʈXCT-z_2^qcESj~Vsgg Ww -ã&ïw|%6z ؛7^ ҁrR vqDXg+V[x6s RXkC587,jx\!%=s_w`J{(T/{DX$&]8¯h@$bG*=|0.T+S ִ\@H_cep#sJLׯ9f8+@S5pQBa+c;V(z#s#?`$7צ"5% ɢdp7 ELQܢuXcnD^9ay~{hj~K.ZʐEqԃQ @4 /x'rpc.ſC!XTC ]c|HaDu \K,Ԝ$e1eAFtlgVᯀ& yKgmO2¼.X.:_ ca3eqW}.05#0zK5ֵ;kP ^)|:μC@yPd_Cigb1p۪ s̶ oգb &KTnb% ~]Ԟ`u_O@v _k(Дsu 3]ٻwanN {VNDWf Fz*){ (WJ*e5;*ow-J.%7 )l'P=QrWe6^Wdd K|_ %ƞ\'jL#:LѺnaf`ѬN0!Ӝv"|hf֋/+-+#b×9.˙e2 x: tlhfѫtwp1FQI* C6/Vtj9aIjT@Kؠ ]QʿME ݫd#5IU>ǫcG"hhWl2+yaܕe{M( lzSKYl$ϭƐ~c\wZͶ,8$6Q3ݡuN^}}9kKMh vܳ5XC^͎ KLͩy9є뷺_r9c:WW$wǕ9zPnYпdЭUlKTױ- BftCic$qfŖ0ɛҏ&'{2@0a1|)ۚ6lD3>Qfej7E+CX̓L% /ƆcɂvQA9` Ɲ- UJ W/\8JG'Q CP~\0;vեՊeHrrn ,KƎ$[b CqO'RZV‰5m -Œ YnKAD֫շ*o#gMrbpvE<7o? CUkyk]hs#^Q^snOAvmzMt߁nH/_&}Yaqu8'ZFN ӛH7fiYlĿKm6L:/v(wj0eٵAa(2 |7%+U;6.R&idǥZ@k>׽ʶ]3DѬ\1VyK"pƳd.`wtO(v#IIQ8n-%1D|;vFR$`=>)Q̌ ъ6mAϮ1G4'v8GDC:"L+h ִWdQ{擐OE4Fřv?UD֏& f $uhJ{kiq\e9[6GT!:BGf{삸#z^`w>`s /ÁכuUӂ @ U6csLniB;Gjڎ$SʩB\&j?X Hj%d z5>ef)*B ,R COG3Aw70zNp=TeE'쭀\A^(mDz.vLF30I{.Rx-q:5C,ٸds(A(zty"h7~ٯAxwY"1v$l#ڧHi g""*k^*.Bj q\]9woz (qXdk|snAAfv֥$>c Q) N5zeyW.@X֬>&E#4 L0KaHoYx5OlgjbF922eN(3SB잡L6V<`ޢ+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTPv.hMvZh)TIIjnANbI*Cպz SD2d`َϠ}Qxށ+7$vAds2SJm0] )5*DEJjRfbîm&Wm-YqeUGQ7P ie8[qoD6$e{+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35ݢ{%\\q7tW)Iy [x^RQosIϸwҧ@'3<t,/<O%D6$e{V_NwFiYe]WP#Xv`V;wEletbemon-1.3.6/.git/objects/ef/0000755000000000000000000000000013212011530012710 5ustar etbemon-1.3.6/.git/objects/ef/5fdc9fe46903b3e8f25ef5b8a3707870abb6a50000444000000000000000000000446013212011530020223 0ustar xXkwHݯW ,o'$x$Ydɰ}ounz[y^˱ #/Dee4(iȈB1 H҃kQs}S K.|{~Ko$KAs7PY"7e]=,jJ(#+c 𭩠bq~UY+JFSmAĕҞ'C0r#pj~RFh$>Iƾ,Q;b% ʦdʧĵ'Sl w5yB ;rr&lw­W`:|<I}}h_?Nw@[.mGA{t.Z}~ Vvڃn@6Q{@]la]K]u/~kw>j)cK7px;Az̵f T-TT^+W_+(RL"-BnQ☪o޼.Ж9f]hM9P`ͭP"ɶ|(tGq$8:M#1WcK$zعM<\\[Hc yE"hd4GA8H aATK BPފtqy(T8IVu8)١I0:Ntz2y{m퀚GkvTx+V"9]rhg:[ Р}|YNߧ5/n=tQXG Ҧ(+r*Փ?#rĞCA ܶpE6(qڴ&&D.' ! Vq.P۷KzBg5Jރ5DZZ-VO*(fיKG!+yxDRrTPXPӐ9R/*wVwdg!(p81 `_`| #ސ$ 7{ ɜbvޘ]SVejɞm̊ezNBu6SX7 -NDN{PCk2M$GNFI|u|ER,1!竍|Z4[]<~$!Ù?o>NUxN2Gw"\dc]E]BԁjT&1.!拹&jAR1KwZ[!s jZ5_ZA ie[_pR:gMuRo`mo.3z *f$O&sf9`4]CTu'T`#Xr@F>e=`fkRYfSy (7\+b' ZLoF /{w0 74>4٫[= 4`b$'4F oD ##˾WE/W p_˗7F&帥j*  we mh>7Rv́;He*#U(}$zͱJа=XXm9y8jkjqșSl^qQ^٘|TDa n mlxAHL[&.-xaPnro6uqUjN?0$LΧxWrȱne`XpoM+clt}w1ӳ _`|wS;I bc|/PZ@mUYSmԶWJP&q'ƕ7tYy+GAM2Pctϲ2Αr95}-Z>ƥ:%A1J&N 1QW86Nm<{ H>sp6w򇦁U * PjR_o 1VI[)`L|q,3Y{U@ЮZH|l b 3']F,]x0L0m&+B^a4I抢ޫl 㝙 ,Udغ>~ۏ[6T&ץ:pYv2N2p9؝Ɯ:? ,[s<|OGZE;_ߥ0zưQ?k0z?Mw6r~o|!(c$/[EƑ"NGDAE=G55|eMeetbemon-1.3.6/.git/objects/ef/6ab82c90ef81af52c7629f8443c47fbbc63e6b0000444000000000000000000000005513212007361020225 0ustar x+)JMU06`01<YI&ѕMi'0/߳metbemon-1.3.6/.git/objects/f0/0000755000000000000000000000000013513716435012647 5ustar etbemon-1.3.6/.git/objects/f0/32263d45d775cd7070ffbb93f9a8292c93a1130000444000000000000000000000127013212010171017622 0ustar x+)JMU073`040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35ݢ{%\\q7tW)Iy WۏrFgEjUn*Off7 ̏8,_x^-D6$ĵwџ8\^u91 ߂i>?vP[OwmgD3PO]23yGMϘ(b1G4@ Rxe|Xbkiv vQZTP2c9˽-n>]$b QQ\ #=lǴ˖Nx1l BTd3Kv'sZ,d-+2<'4etbemon-1.3.6/.git/objects/f0/33daac38a1acbec0f1d955d902558ae50a972c0000444000000000000000000000254413212011615020166 0ustar xU}4TiplIbb5V$ڥ1{ݹ]3w{'cHR^fDmTEI"PT^jCujt;?y~A,;W"d(@z㶹|nK |0sxyx<1(A&#\2&d~XxX *CSJXn}o+v)ʭp{\E0 J:wM0C kÓuuJ)zqs0K= .7+DGΖ+ ,Jw c2iܶ>jC b5ӎepMEMSN1娄@ /2z2_ly=}$)VqL6f88%h=$ ҙO/5ܪ1zLk խQȷm4]םK }()nǘFSմ01h]fUnL'!˶Tk:rtyPlB'$PWiK&cך8N;k4,U`SoÅN{L4N"qaf2O)&|c>i_B:Hx*.iOsވAm&rGYGES}9=JVrcÕ5L]!҃|oTz0q"Ppqxr [t9뙄me+.;GZ{wh2왈ʅ53݆ط"MTwU H> 5ӫ?36piUn! O9Ž4([o5Y.pҨ$Խ7"W iaQ͉c*e^~}tZzi_êN)Fetbemon-1.3.6/.git/objects/f0/8296e1b82a78c72065233838ef1cf75855e03d0000444000000000000000000000251513212013002017476 0ustar xUiTWD DT D@HE"-t ddf"I n7T\BU"j ԸSGe hQs2g~}}CW4!2tX1\E >le &(0 ġU(J*P&QBz:$~SsSc9)e 'e4v;^uvj܉pKS0B}g.g[vY'zluȘ7 0_Z )&]'sdR!Jk~v4f8.w S Mfտ0p]Iz%٧2ɀh>ޝ8YSB>N aAda/]JK kRK0ɠ!ޣ0\qmKU}Vϫ)Hb4ϙ>)ϫ޾5x3wOL!&VttI:S41Vc^ni?o7s3L=`She׶#)%F + UzEuB]ybGQɥfn: iCcqSyCA@'45X0)l:a? r)IoN81"n`!#3dH3mT(SJv~ːfRYm8J::_4\{VNjX1;О`jdٝ[gft8B1G8u^D&2 M*w5A-OeǙ-X t1F}mU͵6FqO)􉱿>f] #L XlBk DI<Ɇuiwf׬)xmʬGhH]zI{ڻ`U"jw&ISk-Llݩ )V;qՐ|R i?^e^`etbemon-1.3.6/.git/objects/f0/886095c6595775d670cfa8e36388a1adc57d9a0000444000000000000000000000133513212007145017667 0ustar x+)JMU07d040031Qs fi^5W~>wu`~V-:֖0E% [Y'./1Cǡئpy%E9 Nz/\Uƨ`)Vʢ˄,Ҩ7ARKg_u\b>SMF#iyz)i9% V'Zlz|闄5U,'Je3H+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d~mmL?2< lrNfj^I1ó k_>v 1ٻ&_HIMLcoǺx/‚v;nUPWmro}_)W,;}Ԓd<,mOCpEe^ޙkYZ ONEB-*D_sT|mc*y:2STEgAxL"ͣ1ev%$.1/yxI4h-24p\ɯYfe.rQ"N.M\<y-& hdbҤ"kɗ8ޚE-^ yMzee8]4c4hd~30Aw~|?m rf9X4i0T5N{n⤈eaeBDIa07ai.l#¹E ;D"7F"ǛȌrE,fϣLpb~H*%=h%CREdi8 /ܹ8_[iΌ/\6 Ef g\fɢ|&y ˙ o( /|;"xh|l2. <2qq,e!18`69-ZEr'7ſ`oz?eÒhuM w<4oq y>G0 yՉ,MPbf0 u`bc:N^S1Zվc lTAqT-YZz0Mxi +qELDYp[F\*f1K)iŶD.,)g%N$4IyʓFmK94~O{ˬlklӿC:ICXVS!-Ie&2ώGqr)\&$>N&55| dQ| D(8rVMLߊ mN:'9tр7bo1nIX7U=(< /M m$jJh*TqL Z'=mBuZ0!LWK >g juⅱa6+ ٵvt~]uCbY4g4 `cĚ`%GV{D! JDY戒 d4X';{) U,NA4Z)tA1twikA"qQBIbġyx*ҼՔY l ND DwxS*O=!i .r!%"c(2?"Jx -fXHhP+R1jMdVPo2 cB1cDS|k.C>4 oDgy4.5@Aj PzDnzl<- "{+q:j||$^b+!.hy#0CԦ-ӣ/ѷk1jȭjRyxyvM}\QMu't](ȹ06H:ҋ\H}1  yp<̯U..wUC%jډBI|BIl%CwO *JNa>oi?wګw|&xj5|_vcځ״ke'M ]=W}"'p 4ٷqR{,LErt5Ƌ/6÷_jjȒXHbUe~)L7AgDa׌D~LJ#2zc|sxoO%;5Ny3548 ?sm$Ij̖e^y.*t7!Uxui"Bbk*GIZ^Z4ZA`5g!$QT ]VP@5ui>\SNRVpqa|]꼉!9S< >Z셂Y@KŁ&Kq BrE\ba>, Fjok>[I<cU)<ɓy{4&k},{] qLftH-)^l 2RG6Te(&9d3Htr|!r54 5G GpK${P|r'985. `š8Gdt O\KG7QsLtK(u!6j ^MJZE߹wf1Bž2lCwGcX|2JYCm! CX>}u\X35-A*ȑ.<+ QRUhcfF6p}5QP"EK D^Ē#/a uLO㞖t*dH6(`ݎDM-// ,nX$UfAt)3FVi&/L/PW9P 4)H'ctXr e#޿&PS8V!gƟڄ6BhOx:>q-92FA Mf[֮P ,P. SAK|:MX9&h+pyFE@Xk`2^&{~u")x^bxꙸقMU\%ay 2$]iP-$$4#;^Q#C|˻// <:ޜeB}m ,ߒ \;\ 2mV ԣd=oXDԈ̊Rsvu|@NH T6W}c#+f7iyd-qyEA7hUoȄu7|0AS4Lͪ8Z—cRPL%N5X 3U_} H@r\~5KdN2dh%JεNJ\yI&/Mw| )m=FG۴+$m=Z %%PO8]j.AZRTGGϢWhJIb_n"yK3E`P^2W KM&/5*5{w|f\P6cJ 6L--,: Gc ^)E۳[ZFVX}Trz*IcE.vPu @LpAdÉg,^:B_Z 5]j ~l B,'7ԉ& nGLZ84O?#*l5`%x?W \/yAm\ sUڠ4%+j4dtƒrM*(ZJ!F[@Z!2Sc~[G[V5u:<׺z3O֘Mܻ З4y>maQ*#r*E?';Hy#:+3i,Ց6ybz5^2n(1#cBfSZuǺ\c d X'Y簺`3^{r*t%ՁZk{8,Ң) 'W7|h4:'GF9'U0$V[W` E~ 2pJ4j`R0F3"zujn=>{7v>q=o6[R ?]^ulp[f2n)V890"9SpaCVXqj55V=bkQ  mj(eת(݀pP#XNF{` :>/ѢŻkXT(M޾,]tF[!mO {uX܊wfg@9'yr-0!&" 4K!ܥ0HO]jsXIG>#2bzB܍G=A*Po̳z~zay0u#7Pɱm: `4su>r+?2)ОUyGyxOù#ue8˽ 6 _RkZ-o3#HwTRC jqYũ9crO71H"+Ǐ y'+`ZI] x%f(ʌ<ەwѹ͛$9tCoځx5?@H)rJhEa@taeexj zޚ*8Uxw5]12o;Z}n M[=F-}ﯶV 2{twҗ9XX 3ǬC j5PU+wO:vsMXz,{¼F'Ilح/i2_vMkCwh{}E.!F7wXG@'bG<=9>ʃ@^kw6mڔW] YM˞~]\i١"VV 9 _s#ϯ KTVj[܆m1z_iz)'g{$[r`j["uMAe ׉9Am*xuO0-̝ Koi/zl!nއ;! %L$3CSܠԱen<i:$ Љ{~J& "L冗3O=ܓeatfJ(*HR#K}GFL"2P򚐛G?O9/hYʆwnsسb4a<0? PI@uѽK>A|Lw$Ցj"ΐ]XEtY3-5Y1 EaMr;߭|7ҡS^JbDǸL䙓/{ndL.Ws҇tJ2wߪcІ'C#l63׼Gn>IkR S (XO _Pb^KaST0hjcזJ$S6U#״ Z1RiLdH)6,S^)DE y5LVV CD3|jK׹v"}ќBو3KZnc'x 71cۿ$#䝍AfE& M̓c\my۹?$f]aH*nMA/^-sU0w#֍{)ۡ 5<9\` ȂKyNM`vH/Mث"xb' opnXwn~Xsv' Ӆw+5BKgxZh C 3"lNPv 2eu5ɥu6a{7/(qD_$?No'M橖v.(ԑ;Rb[~HF2n-8Ȣ;5&#)83ƙϊ:eZ49ctڽN&Z I sj0l۪:ǀB6?KU&d)/Np5M츚E}`0|1Q[QCCk]πu,"b ),<XvR =/colFч C֒eD>G񇷋Q BA2d -.MyZwyIx[bCž}\ rܲx~x)NqKE^Qb3hUOS~ t:ȒD{VK''M(W![P\Xv1Ԅ7Ώ+P>8J\BJ "ANzn^*ч޾5z{jk k3b C!akH"iO`|%#TԸld{jV-¼˴u"y/Aw;w+~6VwҶ+EöQȠ("Co0ni^̣[Tơw9b1=oh!/JJWPZ".bi^t&'u!e7TsS3ūXr'zc+jXB6 a+UC6Xj DX,!pDpHH ;46UkKuFs{d2F!dk0(/Ta'41a8d!p=V<lu$9K}DdS2Tž* E:[1`z5)gNX{-Zw}׻PZM`YEފ6]JkZQ{0(g>])jjv ~ⱨb>fKLԞ/^h3Ij#:nMvH͘ Wuld5Hn<%ڳ1N'V9 ,W||VooxY.}ؼsdΙchb(~h{zř/ׂ3#ܹí$5w`d4~mo!F2?;xgB~sIxۮ sc 4Q!~ 4͊fj$J=MACʿA٭:xO6ViٱhpΘ0`pJ #~IN`(B޹ v9a|D(D83jO;鞴9+њ0N)2C'3NmNKem.w Qt-y>(#Xbh1jYsHDElpBp59;͡57f'hVv@n})8\%pP[8FcYR&ýiĆNnOAk)64J> i*:d}cEg9l)U j ^Fj˕c #d.-07d#ŚDRJu̞X; Z0p2hn:S b,˨p޷pqԒ-> 1d=hw\Wy=V^xszHYWЀzY̞=~=??R t0xqB*'>l?9^,AJJm*W&]Ib<a{66<9&{c1rӳ}4¶e lsn_iG𮽮;B:IeU.Xj/DVAc*O~L9*e u&+lpx#oPt"H]ʱ0iQװVu*?woF<5AJ/X *D>u$ȣf#=C08#wg<.,: m.Ny|jv~&ax u4c'eu7*?s=M4FΒ>ɂ08s&=a˞o8'g<8`] 9@q{ :Fl2G׎9OZ9-ljU2x_ G?7aj@cu kB៺>X0l߆ޠ4w-Zqx/V3puyeOES[HmBmg{Zg2 1LY KI$:({suZR76>iC/0/D:.Ǻ@u<)3H",l3bKVFw39&+{O2@(g`K'n{hGϨj*+K8\rR_(`1p>a+xSTa {+| %w(T=rT L_IEq|N}e+Ƣyb;}iF:9MiDS0Y trIw׎4[bVr#ab4*d@T xY5-ȁ Hl/_q[W.Hw+?k-vRMJ2 p{+/wQXCR=2VS?yM%mԾg #ErXPM^G> f6Ϫk m`#Zss&Xg4zIwWW4 WYĶM6 T#0*PG @{} ˻)vvC$A%wo|Q+dqgBŹ/@4R9 f4d_InL|kveǾSw6\ e3-~F׈j$ZV. U'˭(R5~*ʎQJVZO0;tR4%)~`{*6fF5r7%WIz(K,<(CU"9&KEO?~10a~*Sm^ ME򣇲sj=(2ˮ1 7 }L^jQXeTWC@ѷGm8xn'~ۗ)$Ḧ́_F0 ]U#k{D1`ľőf0Bf 4& +H'6wM}]UG6Rc?|Fހw?q}{ၶ`I?Aetbemon-1.3.6/.git/objects/f1/4446c026fd10234289da5beae8fc449cabe7f40000444000000000000000000000120713604576061020141 0ustar x+)JMU07d040031Qs fi^5W~/jbW|W^Es];Ӡ8IMjEbnANj1I+&?<ߓHH ge$0ш&ٞ;Yiڿ%͹.fX5X,AZ6蜭k*")*/.KȶE*S~:\x6,ȪRUI2 *R1y-Qͪܫ1Am_Nj/}TdnjPT g] P6knfSC$PVjMybIrL=wPOJtM# (etbemon-1.3.6/.git/objects/f2/0000755000000000000000000000000013514461224012643 5ustar etbemon-1.3.6/.git/objects/f2/1e8e5c344f2cca0e69bd960c31cfde546864c40000444000000000000000000000067113212011266020136 0ustar x_k@ևR[!imBZ}$FL3ΈvwJ0̝;sLvu7/)9R~has1m >sTQG"˥D1>M%Z=,]7JJnK<FxO&}Rr),LK$$M*!X^;!Q%B+d'xEV=ɵM*o0'/׵saea0z02a黁=}m`:Tk=6bJW,h% fզQQcF[9@Ș5#PԙiH\J?՚]fŨ a=jMrԄgh貅-( Y6a.l|mMLn bIP QãSŒc*x\34͋붚IAUq>[z A.Ӟt5}YFǦE2V?$cgƱ#[g]2ճMeο|}kZh ˖d]$sh]f|@k@?5Βan^Ī^~xv7i\ijÍT&ZQ$nн'#h !%uփdPʁd@;0zP8&1`~{,Sœ o=(X46DVe!$zOnK vr!q"/ 9MYJo⿔T@'p&֧s_Rr:VDN "ĒdB%/\o"{4EiHFU96Ь~9nz,uߊlKœAnQŸft JD)el8 pz9wXWWRL6BֿT6ax$_>\ (ǫ%@īhʑ6xO*G pl(0 PoIFbBo%=ҏ!hf.+}p:K@qsHgBH84`Pq P+"nǯ7zOvm8]PmAxਉ䅂z޺Ve$]R)]3P6 6FM,-febPFȽ1t{~ ZN\Z.TƎ VbOu@Wr=o򗵔. r7=0 hc`= Ǣ;q1]E =SCن~AIx?U X/ N'vcSd&RX=~n#0 VҹG@{A:q:.BEҟVDK nLVYĈGDlxBIϕd\g+M=Hi<ϧm_[\*kydOZ@uJ1?AѬHm&86QU@#xBfQRK=6ð,VAKKr,gXq\pSv"VnIV@kc0]ؠ,+(Q+UC߃%Kg@[$`D/ur 0w3=b(zYf;3W^Wu}lV6^ܵ/*I/Mu7Qx#L~3{(Nt"LFH\q2/6=5jZ GD}"Dћ%%t"B &0"5]b24"ABPix>_y=G5LA@g>J7|oz] ָ$3i^wLTNl`֣Lt>gy3@c(@mfCKߧpO{2\Fẅ́‚(rˊ;jh1=,Mk@n*"Iws&' z*B)N-hVU!V~IfWG;P_>|`5[-ù34Ԏ':VN;AC*+n~ChM̡ ?Q9o$ҡS H`DǼ 䝣P*4=Սjz]}žlGNMum藟Zyj<m~]X AU%eI1Gɰo4,%( -Oi,z?@*_Yص;Mp~+Z^F/*M CZ2D +>KdGAVr h..%sysH3xdϸ!L+.jl0%&1P6̥j` ˭͹xF!t7c[$3@d6CIDat2Y̋r Ճk eA'Fèq̈́ǍOP(oP&LB3@>LX")U'ac/竲 A3[8-+u. |  5wPU7 d#5r{p |8yaLd}ɿ-~< `Ⱥ*Q]nYxu\T$ k=[%Ka0=FTqO{ӇC Bljp!h͑_џAMCu',m@([剧AB˾hAYS{n~ekhp~}L1J@k;|TxvD8YpE׮ꯪsJuYke: ^’9E yLC願SP- +i(l`48(a\v"Åy΂̋fQo[HHB3TX#P"2Jew3:C'g<Idž" •Lps<BG8stOj#q{=Akz)4.]gFɶ. FebG"ʺ]1w.KpvnDyRQS[|:Ar)YM Օ9En ;l]0x [3Ӷ])E75JbV_% *F*Hϔf,is,ts3hZ}EFt\mry4V7`c6}b l>[`۵ƝvQI51puhџkKf絮;xqlFKaIf6x wfb^nVy>AֹTfX4^]DNN &p(2[VGNkÏ-%)au{[Hy48F艖u S=,p9A(s \dWDT ^_GpqK$ ^:JPr,A0hYA RSY XYppRRS;(rțRwR }!f4n%k^;]AuLũtfdkwYJA5G1/ZN^Yn&u8'.A *.HWn ~)40ZP>(drťwz>QlFעq?41/>aLP[Фe)DZ.]"AIظGY ܸ Uu)P[ gZ[?Ҝ*U28@^GnA!-(Akvm8:h 3ˆl?96A{O6$X.W pdM>E$)[H¢nаK5O~8?,`e Oks뭦qH 9:Aϝ H=Wu%;.\?J[1( FqaSBo;L lq*kYfN'h7W3[і(M {]@l,w,|[jUn:Y7мhՕC,zUhu,l\fӥU%@B6@KVBwd).Nw|5Z~:Vz ~VTSyk]pD(3AbSRYy|ʗzFVJ&VR`~ ~|2SÃCVe~(_f5ɩȟ1ݍ0jePO,֥.ln6T%7+@xUl[Cz @ Ɓ~"SI?qآ^[a_!\+@E-<&pBi>q1sv )yt^Lpq5"^}~ [T=y$SIO9^;A^-F '1(;QB>]YQWYpXh72DщuOIr 0/p'hYCrN5 Po˫}E!@@p*r ~&ajwڕZ;8AY-eY]: ɫÖoO*;g>qW}p éW`.>z=HN{Y-D Iph'g>*|5@)AweWg50!Ze뒉RÏ>]WbFJJ7S5@m O uyxDa?\V`up05 ˞][HnB6 Fjtkp״Nd` y!b690.y9є5;_r9c:WW$wǕ9ФPnYпdЭTlKTױ- BftCic$qf03 GP`E> ۚ6lD>Qfej7+CXL% /yG,ek: 7C.{Yg %;*U7 _ p!0+ SFDa*|>}?Jz`v?ԥՊeHrrn ,K$[b Cqϸ7RL=4}r%p0TZ֧֕95aGЦ-UwDa jrW{;YSe0tp&+Mmoa=RI~(1eٵAa(2 |7%+U;6.R&idǥZ@kNe[xhVz.ڬV[`DY2x]ۺ;GK$T(vd\@">;JKFDob)0(][~qfƆhl[۶gׇ#NR#"!䃊wr4Fk+(OIJ'VC#m pq&/ק*fe^~2GGgZE$\IuɲâPy–ZzVϯgv^rpad#wbIz݅ "t<*=P %LJl7;(W5M>QTv=. l}O^2N4ՠMJSSdZ|0Vo{9ACG/ruA&)Pd116y 5GzqQ;TBit: Z{kAzȠʽHmdr^1jw>\Ӓ:GA5]Z߾VPL:.Ec Oi6O"/t ~.;+-^d;(,Pb(?yYŧL7 TdN@ism:8n[,&􈊺?DGp6y]Ȭ]Dt>UtX/%_£Be8znjZQH PaU -MhZk#>IrgdO6wִ{.R|ZmvX)n jpMŜmԾ]z頻pD]вՎR|6{+f*+`PJ@ 29QL^˫4FKܶʼFMz.KP4 (A]^7ڙ>Wؠx[,x m lxA6zTtc4ȅ3WtZq Qp8W4q=po C41%MwO6qȷ?76\`6iG In]J8Dpr:)T*X^G+{LN ecR\0bM3G4^f4fq _Yfpo:)f o*‘y;Hb}OB u-D~G 6 j^ECև8X}\Lg/qJElȩ1gƇ:]9yn6u ~5W(b[X^TLgDC6§" H=rT5/ݡ?}DiWT]4@Lf~' A軪)ɖ$7QR<(AUsBTC/?~60fz~2Sm˟CMYPh#0AE*QvQG{`YXjQ2 oZoտzTQat?)sS!j_ZSA,HܟA0=PQR3+柾ƀFڙ&Sr#T$=GHd]xΓk_|N?qKmt=ZT=#J)ְ^E/9CC!@`/jcS|3gVetbemon-1.3.6/.git/objects/f4/0000755000000000000000000000000014032515765012653 5ustar etbemon-1.3.6/.git/objects/f4/363ae6682bb7e4d8662b8ac59ff3d0ec9901660000444000000000000000000000027014032515765020026 0ustar xAJ0@]?IL7N&FtxǃuۖǻDMS(gLrDG.dE;S).U_d`QA p4lE, 98V|˺K/\ O`CFkNq^_^iϫWx*o&+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d`|z3שܩ5jϜS 5yBds2SJm0] )5*DEJjRfbC~PZMaoW,*Of6>۔+_{ljI2k?d}}Ƕ'ڡcw+ <../HD3PV7'?91pڴ >U7Nz&4'DzvN,s4F 5_+v.vlg'@% .3rVܵMB.%pvLl鄧oCNlq^v`/TEe10>R: ., dZ*Kx|Uޣ߭Io;w?7G`CA 꼧fi0+Im.)!)_ZB2EEt|J?6▉ЗV:6"l(STr%D'<cO#+LP P:f2URՃ*OjJ7+%*x[<1r1{CZ/N7 |ƍFUY+R5M~5Է{?6(etbemon-1.3.6/.git/objects/f5/0000755000000000000000000000000014057341606012652 5ustar etbemon-1.3.6/.git/objects/f5/20d7c9c94c1021985379fc2d4765caf46fbda50000444000000000000000000000023114057341606020012 0ustar x+)JMU04d040031QMNMIe0Ż⫺E}+RI*)J+H)H-K.(`S&7uj)߶A&$ +w҃k9z;e*B58S^\w[\4 E?etbemon-1.3.6/.git/objects/f5/d632698cecc1dc1e7deb8efd6952da4b7673d80000444000000000000000000000035213325227421020324 0ustar x]MKA v~E-RRD/e`YK=gg:h 9ד󱃻n~9+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT°i=b8w_e~kQ|6sSS܂ĒTu9% E^)^e1+)3B(GaVvqlrNfj^I1ó k_>v 1ٻ&_HIMLc8C̿_N;xnC'3U[|{mG=D6(+vcM@\[*Tn z#7?sלĵ!zWcހZD3PV7'?91==E*%z ᪀I߲HڻS.۪meW\p9[8nL3Aק*EN5er{[NJ?Z}I@{؎i-cȉ- خ셪,G [CA܅+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d`|z3שܩ5jϜS 5yBds2SJm0] )5*DEJjRfbc)ψk]wKdj{oMb>Ȧ$3̽&Afwlg~<{ҰYNry⋄A4eussaqnZܞ wM>},\Pq'aBsR,k4|2W@c Rxe|Xbkiv vQZTP2c9˽-n>]$b QQ\ g=lǴ˖Nx1l BUT# B@}5c (-)f QOX&ZWdxXetbemon-1.3.6/.git/objects/f7/819ae5c6f65c146236b1da0bbcdeab72afeb080000444000000000000000000000035713604575712020357 0ustar xUJ1=)q['zoEaH6@6Y&I{f矙θn/.&*Gva;?$>g>I2mB2'dr-TlFltևTh>S/[xp%fb?s2(ʘ[dB%9a̒\3H3S@褵0GSaZb@CHtO^NQ qQIjKYU_3Y_4n9zN[װy6l ţ13*Jbetbemon-1.3.6/.git/objects/f8/0000755000000000000000000000000014142105442012644 5ustar etbemon-1.3.6/.git/objects/f8/0a118ec7b151f491808c8731ca415bd2b207660000444000000000000000000000120414142105442017533 0ustar x+)JMU07d040031Qs fi^5W~If}tOyQ<'3E(䛿*-ܙiHjR+s rRwH \7G:E2f"+.Ia=W2`oN>&u'm#).fX5X,AZ6蜭k*")*/.ǐ{~rO=ޣ\x6,ȪRUI2 *R1y-Qͪܫ1Am_Nj/}TdnjPT I [7f,vF5L @ڬsRMzm^&pC[f5% 3aOB=u[*=5*Tetbemon-1.3.6/.git/objects/f8/f3313e60b470ab1d965b5bd8c0e3d240cbefb00000444000000000000000000000120614014616652020173 0ustar x+)JMU07d040031Qs fi^5W~AE-@V\̐joʫhrgY#IH-I-f`Ѿ")p{Rܛ.3$1'g,^ʀG[9ԝ >,,'3/a`jĮsʯ]j dCd?[SzghrU_ؘnl~(bcg *JV%(F H2GU4r{u;]ZMPBQ)(&-lޤzEֲS D31hjVIa69yL l֔'$g0̴.sq> nH4+_etbemon-1.3.6/.git/objects/f9/0000755000000000000000000000000013673303227012656 5ustar etbemon-1.3.6/.git/objects/f9/17c28a18d0c8b723efd9c9fc0b71d61e3ff6070000444000000000000000000000263313673303303020154 0ustar xVko6g[@lL]ZI!V0Pmk$h߾CүnkL0`8\MbJǧ':xTJS%iR"];~=~#JƼ[;PDʲR.5,Y!)+r{ Zp 4"P7TeLH81-'?*9܊͹$@scN?U?cI"K"֤qtI<iQr I$W %%\i[֎VoV-,N.2d>iX]96m=I˒,<JBSߤ/{nvE 䠔\̤c&9U#K$y" -"v`3 l'pȄ[s)*f9,a5MELW"9pQ d.tQڦK\`] \-kHp0 KiXՄ+Ja(M@LF/ G7jUCl wsOzQ&b^X܁L8QzWPbݜtq; {hпhx7ގDc Aq?+JfQ[fӄ#10Q mB}hw5K|n9;^uI(/ORG.> ӳqD0e1i\O Z\:GGG)ݸze*2  k" }jX$-260ynJ[0icėx}'Yhuwwc7{to T{loE op.Ba &,VT_꫗VgEAصҫ&I zʠ0^0Ds xQ&l|m+($ύiDa#qDŽ:ڇ_#5[f fDT73u@͎Fe%"ipo;Z USO6Cul;k1  FSһ;[Hפ/_jF-b[J<0Z d^\؟25^EZ?Mt!2AARu/o/VICMm3yk8求kteX4qOkR,/ڏ!Ͱ7V`6&4@`H|fE*ql1B>Fr37 wL 9d6wVraLװb DZ.d+`Msmq!~u%7鳥.]n M^ ZuS:m$jGCm1ĕL5{BljuI`bKJ+QmGUZ-lF$hϣ6eyfp~yn%Z)ͳYcetbemon-1.3.6/.git/objects/f9/96644a06ac185e85f5c0686bc236dac5f7e10b0000444000000000000000000000636513216420065020015 0ustar xZ}l{g9_vBmHJh8!N|NLas[]9߹w{AjaRCZ?TT!Z54@*mɴ:P$PJ73Ey̼yo֓ܤѹK}ipOӔ:Hu^(3 [wڥ6@&^\TzUz] pWZ*XqBmX7"n3BS#.%ā Qg^::*BIVP-X aGq~bz LzL-gfںnrv?[q!QW9@jz/oC1w\`?t9M6aU:oIн ͸vVU0Nq.eΚS01c*eI(XeLY542o ߢQ#ad`L.k&3depT*:ѧvbl-]Pey.d>Z/x=!ݶ\MNjԞ%.1Qݲ !eŅ˜K.^hx1r?վQWZKI3tPU~v#9EJ(yD{@ .3o /|wtOVGk?OՋ.ʿ$[㝦6b [qӉTiv'QT2\IqI a}?}npT{>e5vH7 5Ul}?\*-Gхk߆Q8ssp Spȧ"wFJb:mD^xwxᕑ^s x>w^Yxcdx(]9-7}Dȉܙ[i㻪o/j3CW8ўH̆!\:mJV{ A}ӠcY=qC=d:aué 3|ĝj8AE.`ާ"`}i"5ut|:q v] tB]흐jIG6ϮwoLjĎ,MKuDh[vK{li*+QHHۏ jjgm\ՠ/jXSfmwpK?=8qf-aR !Pf15M@7+@í[S:@]X;j4\:e\V ցZ>UjÃq~ } _vPV<tF\>u;~5&ڇNfls42:_Ycc\qe 닌ǎcp WDPC"D̊njފi9_,[HrF*MdicQ,j$4' vcv/#2ɤw//b%…Vl;4%.3?YfHpKÓ4>*LR*VHptj坚SfFvh`.ofbdLI0p22gKsJ9{fgM*'"9q,G t,.1*9.,+J?}'yP'k00^&덬;d.JncV7=_*~c/oxn+籗Brn&?r$!L%n豗ЃO=}ax4))" }+t܄"z* **hU;–T^e9!ۃ:w{om_޿q 豗|Vg{S܈O_6p 20b:0»]r^^ݫױ"wz <8D#wPེاYfAݦjxxD/eetbemon-1.3.6/.git/objects/fa/0000755000000000000000000000000014111113251012706 5ustar etbemon-1.3.6/.git/objects/fa/9fc8a4db33a599df288caea8d7e8d00168ee420000444000000000000000000000024714111113251020305 0ustar x[ 0aa2i3 L҉{ݿwდizn [8lED9GI>;@`Cc$j\d`"eFk2wXBΑ0@6,EuqT%E/:-@<8u4Pq˭|\/muw)7I]f^qIbЋgJT8Ǥmaq$e9y K%T&vU~ZP[$E% \O6^Y O@SW|vcEQ#>YUQ*ذ*)UUF5AE*f7/~92Y{6;&-R oMMJAp4iak&,Ψb&(@S5zN ]ϡdn`+ <$9auў;sIwK\G+_etbemon-1.3.6/.git/objects/fb/0000755000000000000000000000000014173222403012717 5ustar etbemon-1.3.6/.git/objects/fb/c310228781efec5eddb7a13fa2c598a0fbbbf70000444000000000000000000000433213212011530020411 0ustar xXSHOZ66lXq!IQQ<ʒwF|^뙑,!:RuTi_Ok hH^5[{(>AqF4 GF"^LUW5)7#~Hh ( GrNƏPZ+cE<4M" ;Et"#w_:-젵׬ uk\u6rKԾQI+#h6$n5`KHL|E3]IwJxK!HE'٦y$WI,ȏ Gp49*eh@" ߣbsQyh5=o0Nwc? It-;mXU1lh++0zNhCL5N J'AЧɇ NSknC'ǟ=݃N/_/Û'Y0 L6~ّn]yx'GH˙v T~l5%h9+g*Z:o+3wşvG2@ogN*$ ysZT4 1at)-FnYY"]:.G4oIx2nçxIH./Fb  1hюh@8O+na hz=%a2UzJm1G0ԮCAV~%Drdg-$sL Y^.]׸] 9m[atvRsul\IހR3:{Кƅ=^CrᴙcԊFejnT`$Z[0Ӛߴzy^~ֿׯ1ks\3Oğ&nfrE7hd eN[٠ AQl^rV|npM3vÚRo?0,xp"Je-0y\̱\H:\ϕ=‹]c=b( Uam &\JN7.g#PxoIZoi\s(cW f̓S{2peISK҃@ [V@zmX +PB0 ra`I26wĹfetbemon-1.3.6/.git/objects/fb/c6d3a70103ca9d466285da4efb4ec66fa902940000444000000000000000000000027014173222403020127 0ustar x+)JMU024f040031QMNMIeoC5%b:8&(X/#5 H/oO,aj_~UQ6V&ڂu/=#6g PŹE%%9e}`eNmʫP)lpz}W/.-?]VXXetbemon-1.3.6/.git/objects/fc/0000755000000000000000000000000014173222066012725 5ustar etbemon-1.3.6/.git/objects/fc/73e1af9b765ffa04678d9f639b980807be7c010000444000000000000000000000126613212007145020025 0ustar x+)JMU073`040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTί{{-fg:`sSS܂ĒTu9% E^)^e1+9'35ݢ{%\\q7tW)Iy : /Vp~䎅k΂*Off7 ̏8,_x^-D6$a\#/W ۥB"gFjFAi>?vP[OwmgD3PO]23yGMϘ(b1G4@ Rxe|Xbkiv vQZTP2c9˽-n>]$b QQ\ #=lǴ˖Nx1l BTd3Kv'sZ,d-+2</etbemon-1.3.6/.git/objects/fc/9ff3c3b5f14a27b89eca2612e4b27c99d97b190000444000000000000000000000025614173222066020162 0ustar xQ 0D)_lltk֔4o0<Ϗ JӮf %QbTHC=Kp\ )P]砣Acc)yݧq*0*:m]y_\X~| ¾HцfY/n+Zah*2.Netbemon-1.3.6/.git/objects/fc/d00bcbc41ba9def932919887cca4fb76d3620d0000444000000000000000000000141713514461057020304 0ustar x+)JMU03b040031QK,L/JePgՋ:ZrUnJ=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d~mmL?2< lrNfj^I1ó k_>v 1ٻ&_HIMLcj~kcsc;ǂ=d4ġ MO=6eW"Z0ze_߱mv7r]zJf91e/ ONťٷr-/t4gu}*IO„椔XiTe?4&38xrUΝ5er{[NJ?Z}I@{؎i-cȉ- خ셪,G [CA܅+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZT~W&嶺 }= .Lh)TIIjnANbI*Cպz SD2d`|z3שܩ5jϜS 5yBds2SJm0] )5*DEJjRfbC~PZMaoW,*Of6>۔+_{ljI2k?d}}Ƕ'ڡcw+ <../HD3PV7'?91AJ+L6Nwk9[*IO„椔XiTe?4&38xrUΝ5er{[NJ?Z}I@{؎i-cȉ- خ셪,G [CA܅%20]]8f&)o:@Q^RpA/2)82/=:X,@od OgJY^3È-<i~4 xm0Fg'!H#zFNv;9Ԡ'`ZeVP܃P27V ;>0fetbemon-1.3.6/.git/objects/ff/2c7ce9639e988d549ee49e05a8316a21590cef0000444000000000000000000000124213212007675020036 0ustar x+)JMU00f040031Qs fi^5W~>wu`~V-:֖0E% [Y'./1Cǡئpy%E9 Nz/\Uƨ`)Vʢ˄,Ҩ7A (7?O/%5-4bEΛ3]Ya_~̢bORY)'4|^2d5 i6 /J,wAq5Ԋ܂b+WMx'N̽H2KsrLX_e.W^Hr2o^g!sTe@*jmwLP[WӥK03}¯Ǟ5ݾ4sZsSSRP@uKKlZ$ӭM7mӹ4o[ͳ/| }luH9E{0':-qF?Uetbemon-1.3.6/.git/objects/ff/3184ea1d6fe458d0ad58fd3aca7de0d710c5620000444000000000000000000000120514174476713020302 0ustar x+)JMU07d040031Qs fi^5W~)7I]f^qIbNY3~s1;i|XIYNf^v1Òb "ղ]Gl_V9IQA~q ?ABEHNNQRTVW[[^_`bcccdeggkopqtxz|}~  #$%%&'*+-/01223569:;>>??ADGHIIOPTVXYZ_ccdeghjloopqrsuuvy{{|~D޴g{ }D35lR,izR>eLbQcόe,rޙ;560AjF2v9$T՟{ktE'ΊI^ia]Vz;(b%440K6m`c RgQ YIlO({xnil5kfoM? $6q<1GB#,XXeAr׿dU늏w]۳S)9źцBQY gaʑ<7@sʡ@1YQ=>~wJزx~PEik+uATȴCpt..UN껵T[[\&L# )h'Z/Eum'/õ 9R x ɳ :v 9O 5ܾ7Cc| rR!AU(Q?! 9Wӹnx%oU U,1O]{C~< pj=;V0 y *Gr_y 4I< \s LȣEz͉B }$@g⏢{<`s~Ȍ7ky!M_ea&hW *&(бP`]YChTϋ D S틱&! 1x{<|rCTԋNtKO48:O#_2]'Gaϵ *0]tdK[}t9܃!,bAz'.AZDV΢$'N}7mH)#XǶko. ܋[yؑ4TF Į]V}/qn+}'r~ >ysU C ~UKhi,(t~0M0-8(vb[!Uvec*kcir /TJ(7԰&I'[mu8?ib6 JOZ_Z[ ? =Repk!P?ޙ!(y"$P%Al{|XXZ"N.ZtJFPKc@t"T_voIҘ/:#*2u$婿&.SM#|[U! X#"f6"_^!f$ L =%<5/$xJo:wI.b!$ -n&JPq/x0 $Y`s$ɣj!$ܺkE͆ ]b $:1lv%I Ha &tɬVW6 &,38Ť,*yh&OIj 3Uv'}g򴠢|1~voZ(~l6.Uƹvc6Z(+nLGf_N)\>kzx)_Q epSGDYu*8{_,Kʡ&p>+M7RD\2+Is25;!rqhV+$Vٕ2z0j- On+.k&9[e^-kKZu,H\R-E[Ƴ)XӃT%-t AwBJ8>.K8mOa$/i WſK m0I!WlaL&W0J ]^L4>G1-EFE+4Qcj7^wsTN5`] v' F-6*V 8=#W86t(4!xa6*,Ng[+ap9ho[nD~z:I-ȳV04v.4{;qW#-)S%y=N<?E>QR^G}Wee} >U-[za&(ԩ?+W?$CW ?c0tVM+3@5Ȼ q\UZg!A o5Sܢ3!LCBxU~Sٿ+{fB{E·Ą_hC2eoU;,E Y`D&BELR`-JIniEuۆ@dMEG\zbUMTHF|)]h$ pF4/RHoz/n.#G^#αDLE@KI{HSw٭2Xu0IM9v!9G:6Iur6ƅ7(0fI$H gl).ZJTbϻ[uA?VwJu^3 d1K=`d' m|AhrbH,jK}ЯC,ikg3Kȇz9=uWK{5iJ3&PLW6f`޲NjL ʺcGF]"MPFݣ-&W ;]MeV+#A@6>M'tMisP} ' Oh-g9 ԗcK;WTOIG!l1TO3KZhXv.Q+4G|Vx)c2GTp$yQ,,I=Gcdga}QNJG P9ɗ9HQIQ.ሊ&Fy Q~,1VZ}OKRʯ|$VknRvKsPgXT|MaEٲxĘ&*T6y#9|.-swV˓Ti!C.dWA2˟.D>jW_%<7ZxX÷Wr7#Er,`XX-x9_&Б;X6XګxL"(Xw`m8Ԃ,tY;K 5 [,ǮSOY::pN~7̹D[LX|e9F%q[ƿ7 @\07E0@SQ}]zxsx(Ÿgr@]-t,̟G!8]"E.c̀vk]3=%@S^Vʅ(m/BY"^C>>\0S› o],`_iL5e3xscr``ˣ-#XH|qF9Ba_Pi'qIк8ybUk"Hf џbέY\L0JQEқ=b;dC"c(*[\*Y4]fzd3MJq1D d~Ԭ E}QgT+nүb#sf<l]8GY{VgHvoB(\TAb3!g BeyHG02;\heDO* yiK̃{AWULgZj z3qWPWjs/QNv,kOk6ShVY5uk!-Z(skҳlw-cal^-ڗU'ɔӉ9\~ l+ TƊ){;lD$ip&XMUlʂjkМox3x:nbTX<@a3n ^iٽޭ%Ƥo)'$ؘ,",*o@4_հlR8aF.WaM$p5 dފdXxpw>6hd[pO@JHZczBAHHRv!GplMZ͸>w4 ٻ:n2MYy* +Bҥ(z%%Rr$67zlt1/>[er [1zÉ"8;}H(Q{Ot?6U_GIF|F]\8pmfA] }G6dS :c}Ꟙ-XY g~l mk%~DŽM5iϨP=Y~2'B_ư~Blk_%<ϼ^"p*rs{?{l=`C۝,(" wjL$ _Oȯ/Qz_AE x&+41Y9վ1t"J5EhŒFXc v*扄p yX .&͸V۞/d8|SӿمtzT: E7+J ]/ QFü`7F+$H$DY?YթC k|'ɑGteJGJd%rW.CvgL ٭ф5 ҈XLtEg!AݩhȂ:,nhFJMbЊB1W]kUM康fg0GK--~ %:QGKŊ.!w:I7ooKHg+S/ U$ DkІLS?h9^x᪙T'؟J;^ܼ_x ֋jib q0CdGԴ)XP6+:$qa,4 V>_({6{mP`X"f"^EO_{ckōUM\Q3&;zBuv:_'UFo 1I}M\hΜnx|e8$rûtq ||Ǚ5UuG~$TmSƺx?'fzK$m0_L4vgOTH&H 9 n,֥kU4YVo̓ ЬAyH{.Ycr._Lc@V `כ' Dj6]mGbD8&'M \埘(F囸R Ե(8JjoBTЇ;r'e$|?_a'.Պy'u<Ϛ$ œ& < N}#ĚK@H$0.[hgVw=recW+Z䜄9b8!➪Eo2ՙy~dl9{膨iU4~r0h+o ?s[I7}C_Ŀ.ߵ)q}tľPq}ll-v$!Ѥ#fiD\TJS`{aŜ#U=S E= N?p ex>,$Ei\0kF?Fg/x2Հ&9rXIܴxsyGFlW^.o!={,*DaܩWvr)vNn4MZ]% gx/%SXI8Ғ '{­FyBmd6a ycI}_Pl\aULq% UqDla& xK¯]{㕋(E6]2;@3*=a^5m=vɍ*8@45sJbm"?b4O'zmPר"WYM>\z|pp//m1+Qu녵O ĠS,=m8TIJYL y@ *C.u,(˾if,IEcۀﯓfOXA/k!s#L9z{V0hVϿ' )@f0.\jaQjr7 v:YHރ)^ *3}e 팚C,O\OxֶH>VIyKdzݾ>)?:22<Wȿ[8&Nm  }U?G\OBS\ l_"9Um^iL[ovoϞP E-Xijb2AB *S8ӧ’k D4k'0F2A<[IerObÀ]2{~A"bÕ z<;4ŧêzd'(6aPGï+}o|Ld32e4YS^4ƥ|XTSK̍Cdg>Xu;̜H:VKtWN(h$u{uS[1>d9 >땘e)ٓuѻ6Rڝхo \jFV`7:ڻ# GJi4҅~"!m:W_ X\l'ZIVWkcR6m0sՌzELkR0$,-:H4%U8*|v{3m*5>Mm'8Qڜ`h3UM 1>~2>rdjF MO .96RVCHGhzOU#3r}6qo&r+KCFJ XbgVU_s]lmIYUK+kkLad7{p t a~o -:!ѵ6r+VCr3/,is/³_ړL$䦵dZ͒sW`K!o/Vku;X14*6_SCC*&Rk'Jm& vW8QqȾ4<=e= /J}&e<ϦnUIt`z2َc%Z.|I,}x7nɏ^{'\ZXN&X*[mդU &:h91k;==SS5T`FQ@E.@`Z뢤8qSyg;҇+YcQDHk`WcU4@kҏcl^8WnB"IVCquhJ.GKFϧ߲s-Vj|xErsuݑgL\ U"8ouN]j.*O]R4F0{r2+&Nً~GDmېzGUvbHP"ز>Ԁf6xA|9îroGLE<`^ib1)X) +=י3l~>Q:/ l{&?>U 9VKܔLSDOb:V;lms[!YfZ z@"-]oѰB3]nGu9I &{n:] w6>'cr'aC0wNgXr 'l_s| LGEPJaNbd$~=Db/Q>xk;1ޞJZR܊fU(*:eut Y t%/Qp+_tAnvu&(|UJu+F1H! b#A;fJ1Q82 *Ǖ9/JnjyU$r11Q`_^shNVϿ,DψvS3F:aa'}}: Psr[ER(pc-_ܿZs-r3 *W5a$9o55Ow*7I,Z!rq) .%se^dR%72>}o(`,֫5f&GIBKP R_,l IuS&[QYNs~O'ڵ0Ӊ5ݤ >Ē*>gfSn>yO]zPCF7H4W>v=ePEgh>ɥ&' uкϷ~ [,"[;Wssm$ir9m&\VdHcQ%Y(QEƷoũNWL2`Hج,ʤ3TG!fTǹW͸dnYԇGVFxqYJx{b%@Zv6vl&q{riο$>s;ڇ=5`WhoβL[aȨ 7T,kP1OaW6qߌ2ẇ樽[a(9"l]Ԧ?+/Y8vfx>ڷԽ ډHȲHfevz}wǎu|2{5dm5/pVi7;IBâ5H%8ާOC%nJʨoV.~ 2I\RjEFe5A '1cK4w d ڛxshI)i;)9+7‡L%4EݵH( "-<ACߗ.nwd > SE@a\T]nB Iѩ|ԑyW1θb0r '%"+@).yhף\Q$ N)# 3'HސͯD76.QVSb =r(qw+ P)5'm)sKx(|~hq؈XϛaR4fϥ·*?]Uش ӆ"|48Y܆ GwN;־[0"|G*+kq y (%*  7'"|+ py'+LV'  P!3ͨx<.d +*$\ 8~٬ԏ޿1-X-ԨڴC!5!M%WYwF1j+L4 S i":O.+1ۖɃmdxs!٪#\w[f'uЏ@(tO yQ  nl)dEZl&d) ݉C7B.Qdw)pbN/B]& u=( t|~"T>M?R /Netbemon-1.3.6/.git/objects/pack/pack-9e260c810f753d281e029ad8efcb20c2ff747c7e.pack0000444000000000000000000141427513764422020022566 0ustar PACKß x;!ОS ß [1.ł! 6{k2lC&ϑ0@t A⃓ qѦZL,:i4G!Pϵ)_8ېs׳051 ֘J::>`W#a΋ l5"7^SCTIuY #}u\pv/}I<~Wk^.]v>ECHyd}63}7]BHy#NxN0DU(m۩!|koҕ8P Gn;ڙ7:'H)ddepީKl`b胪Nu,6AzietBٸ/+Rڼ'xZ(/!JaP=L,i >E#PsX0h8/-fԥ3 Sȳڱ7!_0'EǸKR\ຕxMS èGmVܶ!՟3>D=O_*vCm7'=UxAJ1E}7t*nQt!St23߽ 󌌄lc()<ݖdRtf@Å!hLʺbH=.xO'\+r1˖Mt\_ ?/Dh1Cۖ{}p'ݟ]DLSVK$jw,9z~2Ttx˱N1 =_TH.\Bj,ێFKP?FJgIxQ7$Y ݂ى.u@d4EdR%힣.I,IɣGG\u+"= O_f:k m+cgnu&X[-+?O*|vE|3rS{ x;!S ca!v) a~,EGgT k&P`$UxGY҂hsOfK 9$C \ iM?&[Y/)԰ܞ\\(*m%T?Bx1N0 =B;qSBLHIGWޟ0?UAKPqMĸ0V0xŮu:T@+&N Y=G,s\[KRsȦM4XַW ɡshr2o?}ʭ~o5bx~Va4p21ǽhT3x=n0 @]^ (2d:2$he'@o}otU֫'e⬸‚\u(}@gRl94 :ƣuQ .kEU^i;|uz;ep[:6uy3(_8vb^[L&xMN0@}N1Rc;+TQ`ˎ =jcW,>ޘaJ*̔qq&{ ! < fnظt:ɠL umѸ\|`>s)3,N_CƲt9Y0g!b];t\jQnDL0~c9|\V o/ ߯um|V= ?u\qxN ;O1w 1zf- ^˗7A̠@Yac1ygl矨6)\dl9DhY £/ \K92|Vrl:^[CpШJm򿭮6?g#<M7x)`_zMx1n E{N1}a<("m`. ;[|zz0G$=aNIu}…)!4JL.hΫ ~"5S\<Y.)~Q;|֞9Wxk^Lޑn/vUUW?{ѷ | o"7P}oS ex q۶bV?J 5>c'k Sxn0w? Ac_Ey;l BV޿PtFљDaR; ] -JƜ ښ ;!Xy3XтgV+I$%dx0HMWà%M*M{{nk}Ƙ[i2[ۻiJ\%H9VJ7Ա]\ '"*<DZn;x u̥de x90ޯv}[BGEbd9'i(()ңv6b+M9 F|x}ꓳJ:ʙ4G*V&e8(\H}ky)KlX@J4Vi$D9?[K"C|qAxxqى\\) \FExJ1{b"YIRJEz1Ml*m^ 3fS2"jvbU6hJNEme4Zf1{DWuV Q3s*cb2%S'֣% JBk-%/FAq"yLҤR˷83s )U@k]9=0ZJѩ5 j\&cDIz+v+IX}T!(%>-ᣴT๖|)Ж>.'Jz5G.8gZ_T{[}Auv$Zh~c WxJ0y nIaFt%noo4)i>8):ojciUN74׺эmm NQ,90nbm29b$TMYHhPVsHb܈Џ\=wcxeʴ^­TR JJ_zGiaҖ}z+gƯJ}s L WI7`, xA ;ػ, vi9 7~!Ru-L>b %F J6ń)!mgA,DL:`(Le w,*s^qڙsQydI5[pAr?:C}C,x˻J1>_13yL6"[XXh#yLր,!)!PQWMnޖThXE9'vS46"Ԅ9Z;HH=&|ޯERqd4S`4U֒mOy53Cθ |}u_ LxA 0}MҤIDDЫnjmJL^AaVE EcUcK0ҮG(խXeiFkqHc>  f:p Jí=J\e#p3O.,ce_tݛAG;?+*[kTWӣCx 'l+cQxN }b7^ PjѨ˳2"R>cW.'o/zb9Qb0ґV#5A Uf&))hli@mhTȽYfcܵpx3cy0]=Сtbq"Fetp /Qd6р}0`78 i8ct/*iјʢ.)?=; aZ( w >:s oN) ]RGLJ x1!W.p&X; of#LSM&:/AJ)VY VB ԇ\y!L؂`r\SI1G;~}oe,1ևFkAOh@cۜV%o:#AxMj1 @O]ji\B"‘a.BBo qEd%bt+:&\l>[O磕Mȭ後]8*毾/e;\GQhy߁o ,{PƑx90{b{$>vĎ,"͌tKѠu(yħD3mc`"DJYFktܒ)(% nR'=c,[o 4Mg,u-c5Sju=dqhp:CNśxN1 |{<7pgYE@=d[0|X9pcl4yWH=X0|N6Dž0dk CW 4eVMҸ1g9g9gCh6Q>qܦ}ϣr;q'qJ/|>R3xAj0N1MK!H% 鶇Ƕ4ׯ{n?kULς49hĮ'DԚ;U zؓb؍n <蠵Ga88іRj*r~0'li}2$ʧR+5 Z]˶ku[(噥KCP2w[4hHrП8f .8o'\+ǘe2kL\ f8#!uͽ]Yr&8`Rϵ<.;pMg6`0Vx;n0 ]^ _f)52y3"d%E*,QIJD -zDuҐcxNV:.BOγ(|h~q\ {+g~qFGVk}ۜm~\g)E^Lx;N1ާ)k:BQ z~N,8ǧOot33/*L(lQ&Ϛ0(FK(WH%g1LʜWrptzmV.RizqVJ 0aXRmcϏ#/FJo K xM @=oc\0T-3|_`X3 &[bu 1Qv(gD̓ cN"uB>D Z1?}+ jpZ]y>+[b=bZ+nUס~Cx; 1@>H/hfFD,B }H܁݅HzΠ1V#'rh$d ^QrV:h6DېM8L0gm[KY'GcY6ZA˕2J {n޵a.tJx1!@ўSЛ2kDKm,VCk ~~o``ܘ0輊Yȣ )FcFKB "h,:!`_6y-Wy˥1fyX2O!m>J5( h[v!>DFCx=!{NAo3, bfƕ-wo`j}$@.>^L&FD,l O -LMT)x- on\0SK4K2IV!Ms:ùNG~v~4rn`*b)"bAq;tu.; lIqxJ0(n5mDVD}&`4]||x1071%#ӽ8gRsmLJJ1J EeHOPSGzF%cjK>jI傰rcD2 *'f*v)@d1'Ƥ|)C Bmn?^OomHv5jz`xi[aQL>V/WRk)tv7-qK]9B*x8c\C0Xp{ӊ#F1/}^x;0 =\ӤCWԅ GQz8^f2%$gCdI^c)bP#!' dS1ϗzd"G{oFeGYCu)vW 签nQbL]@8ad[Қs'cp}oG+x;N0{bWDv>HQP!u bGۓ3Ўf7f3UN#o-M6d1Lީ#6.͂i6y0gg%xkkؤ‡@xޅ6Ibk^LyZawWw9; q0;Rh[n{-қegX sO_k<鵍$9?AaCxM 0@}O1{A (t+x$3HHoy 2J!D . $~֢UZ߸tAF&0DQjɷ\KbpY3-o!rmZc:8){1Ϝ4ColH-xKN!=,j_21.! Bb&4gߚʶYޭh b'gwI٪'M RpC8SR,$шpVt1fh_97T^S6f}ܢm‹FUm2U+1k}͖n+NxN ;O1=6@Y 1h~K>c^D.r*+@ sd6|:YMڇ`Vx 0@NRW6_UEYdsUX͘0ck}HC b]iGυe0"4TPES_)#i;s>oJg ͜xN0Ts:]r%rߨ>6$^׿䴹Ie߰g˟ x1 WWеI*D?Cf-%DIzsJrS P|N|cڲDeITTZ  HJ¦Ӈ}Ѻ}8M6Oqc{Xb .9}ۜ6{mBgxMj0>@7-Ŋ,KJtRh/0F-Y ޼o~x%םNRGhɵP30~)TbX`tӂI*cF2b jm931`d)lj+9B^h?Qɭia.x!m5`]n9V=lKO .<`4ѼEC{[8?"C ^pxj0D=[,9^{+XVYjKEVIaݷD7HJ{ֻ4I3M6ڢz@BQE+)ko4vFz:| 0qw~f?R>zaxZZix.3Lccx2F K\'r9;+vD#_ W`G-q4!3x:MqeյY|{YiEɣ$ҥ̈ʂ.X%O19 斻D%V5Paq$Z:R*n/2Y Os SxZSڶ1q=oA뗰`LžxKJ1EY'TO4E$//@WIAwo;pvщ@:K^'SYTF,>HMYc2:[ pِw^fǹuV+h%)p3nyxKk+•a[:- ~(SӵR26?As9qmQ?!OWx; 1@" "WL&kJ=+ރ7W$9f٣KXI/ S{'B8bӒTdmĕvjM߶VV"Qck),}x߶6W7MWExN E|[L-&ޣ%No .onιU"p$'ta0~Q9QQmSR[ F!b+BD%.&TWnm^mbJ׈3g$mr z%b Ι[e[ \Mh+NTo1'ht]c=cOUO{k;BueT(!%s'F{dhxKj!нPڭ0 dCh}:iĹk@܊жiFL{ *-̘Wd)ICMJ~;R"eג]}1Nm )냥Y1'ч7uZ>~ڲ)+;VHx;n0 @wcˢE]z{ $ }e>QX3iNS|ⰺ;wNę''AάʤPv|kŽ4)">Z.\Ooω>zD'm}a Ga+ËۍΥB\'RGx˱n =_j X:UnЏp1$DJU?{sAd\J1oXp[,!.yɞa焤dFU UИV سI=E_u<_97,x340031QK,L/JePgՋ:ZrUnJ !=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTPP.LOGf4DCT$d3ܛ~hRշM1mEBT&e&1/K?w~+?m;ľ*Off7 ̏8,_x^-D6$a\#/W ۥB"gFjF`nji>?vP[OwmgD3Pz]23yGMϘ(b1G4@ Rxe|Xbkiv vQZTP2c9˽-n>]$b QQ\X /q O8⼀Z^Ғ̜by|ОdNe|EG"5x+H<;xkwH&+V~I#YmUٲ%W͜9EX @ˬ߽7d&(]:U" $q}"⇓l98}}|>vǻ]tk =zuM=.>/KC*o$nr#VYmkxw蕖nN芦6qBKݙ{ZX5y:sLżmG+ :%*Dss+Z"6?@($ nV6|ntƛWwy7WytR*B'˳728ۖ>& 2ڏD$:L蕈~^RYOrԮ۲Q} ⭮'U6uɤ:˲N4 74jwhyO]2mf|X_fiQOtyϱbsQ7cWС/yWTD|1!+Z0 R\sSʌFr:t+d@">|mr &XPYV; ?Q:wx9_-qiӂ)L.٦W)hUeuN3ayY cw⤵lULJRY;~cnP#|U}CL^eN*vWyEJj*z9I^/҆=IX~Q̦M,n0"c"&IpQr!^{趟mF<b_RjPպsj3$ZSv"-DZT@ؙ&`me;=51UgOft|*h?>czq~%N̤䦎xr5ͅVw:QUNⷨ+hv])D3?diCn6hD -m<-NW$A<R!6l>xNMZqHa`j/JvvN~]Zt4sQXg.s~ RDEDeZ_$F÷ e,%IԚo Qf4#?wO/_<8?>:@`e ,AT<{ZsA[-n wIb:)|x<֡gvNb Kvl+͵?%]3#]2?Dy?xxtFצ64Q_f+p.*]zIoj]w*os[\a#qL2)>p)?H1B>۱*8y*]^&B*lUbˢ|[.ObJ󋃷oxMXY9|t-S-ȑ|"\jFR7HѣiwpFTôS.-.H-[`P:ɪSZ~nݔ;QeY-4of]Ӽ`2X(/Iol5M dޮ&W3B8}9%Woņi]j s1IO!dJ1ohK7,贯{@+I ,Ho3蛜VWz(aRc$j*5b"knpəAf Wu`(PHd:j]0JkL ;k+g"rsA,H1F?` BrN Cdn-PE"$IK6bѣv3˼bQGݾOae䕰37WZA1=6G>\YILzO1v4ÙNd7z5KFYXϘE#Un~7 _)^je&bARjV@0jԊӰr*d&n6bZidAGOj.%X3x0⊘CSn%m`\h٥j7TAXꑢ e_H4#*nj&ٗ<SD M~! lxݟT{glb^|i$5tP_^QO&0$SX+a@#AvF#֟.X[dD51l5]d?N֬k+gE4ˤHfym'u_J#:'Α.YDCjf&"qٲͫG i̚\uAH,hJ& Þ˦ /Wx7`Whڤ-(fX͞LE,2*^'WL㇣GOo);߭j v]>ߊ%;# )f&k`< "6:m=񯋒hܽMEC?K?k|Kv=S'XP_ 1jGfhCZB %X5B$H~Oh]_#+ U?nxK+w "γO>x\GN.NޟbVpt˂#lM񅗙=!"w,jCLnں .j%)]YCŁ_e!6+DxchO"J,!2֏8|fhb5f:6HU;uEzQCȯ6D/^);@iCˋN?hYSGUz@UsTA9HTFl[G5Ϭoe_'G4yA]Mcє'DtF~ub8JlXAeMbiͬd yCZ{/t6[FUU4PD#P :[+y+9 ./j'o_-CA>8ꋔ?l}q& xujY ~5Ė6rKĉLb(RZ:^?E]hnh{۽LI"e8yNNP+ |%`&v]M7uf)Q .҄Z\$2"*0=li>$xĝа+ ' 5n<PѪcW!η/|tO}㼪MqU8!0zvqjdq i85*6| .v/j)/'iΗ'_/h%(q9$7Rhk۳^d,uȨof AzZeh\`3-M)vt+?oU+a:'9o2UFoHb0BbA<3\60PCU#ڙ[~d79#{/ |_ [sڶbȎu!$rIfs8Ws0; ,6RKZF-Ơ[T! 򴞒,kvp5#"e3+Œ³ÆJ 3WloQR+6FrB7Z, `kOlkZ":.֞OІ, /8iStٴ/;*=|6ݠ|U1xAls?Je_||{^9\Ƚoo߾{u|pLF$heԦSFi@ )KGK0RI R)j0UPr\mV܈9|hƈ1~e]`~Ϡ/#UDЯmTDp%i`N>T;wp̄+Ĝ,dCYY{pF)`8Qs:iLWL)6X 5֏\X wS&> i3PƙPpZ` Zy&HQX.mp#!&4;I$B/E8eӌ$7zcQ*wFϙ@V6 z斢|#Z/OJ3V7^ctirGlUSf1=E;-| Vndb)_gG{m_FdЁi LGWHƖ(T`[xBc)#C38;مb Ò%Hlht|5H֘쐴]_Af_)}xd4L+:[JWډbڐt#yl7 4Q"@7῎/vr1m)a٣i EЪF򤩧XFG([z xڀF[u& iYu-Q{ [{FٌqL h$`RiL aT 6AֽHK{?.4aNmU|{%2u! FUEF9oV*c_hzޖ)KNad 첖NB/\`؆k|(!$SF2 lW8$/4~]GcƎ$OɨRR%r `#RI@썡ZlWQ)Yhq@,>0+^)&BqnPaTR,6@o84%ה!:-ƁY`f'D)Xm,M}ЩK]/žIO>~sKzn"Wh\( 8*z^| D8|9#Ǚbzi98ӄZnoDi<$$zh1|T68.w?H{et |C]mӅr!JTR5]yCtMp_V6_jkX)_ )$HhN8n3ͰO\Nnp?o>3hk66pq|F鏠z|n f$P!@^{?inVLt͈>Hl4ziE&F>z1p *3`^.>CmNZ;/ Խhg~7yA|$y{m\Îi_j͔z?^eXt3i3H 1}<:Q7|6hNiuKbQl*?;[1B\d %c fG1{6_֯oOK"͌dڇoϏ?|t?v5u/>xX}O(v"ZeB%{$LpPV\- wu>fGr|g|@ / $u8dҽ-z yn| 8Flxqd}Ԇtfx'ܬ +%+`6Ii,Kp($9Ë4ND_WuzK"ŢP2֣0Oh(`?~e>E]L -w^SruenGWƲGrJ<=~ĝ1'cH )r,Ҽ kRC3NI0 7 H< C='xvS4V-wZ3!X iK+jrf=]%j~"WrT{.JVp_p՟v7+D+ޟ*c-s.6sb -B9Eb ߵ ]>7El| HV[h~.MQ77y*ٟ 5:*d;O?rX\;b:3Zf}5]:ӲǂY'"YZmA4w^AFU[_٫Ek7diӛ#o,0"~( 䖶dkQɊ1` ?5纪[$|n}ZȃMh̢>T>! NuɼhyBI4?ũ:,/bxj%H3<]D5>)|_5>Q=P  W)r)~vճ?T?voی1@wy|cw&?Xd]^ zX,thW,]p~M?ǴoK}^ZM'Ƃ=3,OwiņH ƨ5 &r5<8Ĺ2{đ[ &޴gqN2&iF)w`Y6ഐd.Ok/dw\ 8"(hJŇ"B\V PDvryg1-Tuh NSQFr!9Ub#@N4금R!%ȦA>%gß%,9kpy#ĸI3+aZc 7qA IE* BOi s-)I4ۗlI8-_뵈x؝CvF8O,Z}% _+ !b:^Z蘵i,J,Q+}<`-ϘK؜}s֤`:E2֥\^V.]QlkY3(> ob5ro5l0-:TM It285<])'fq3΀=5Җ1/*IHm/4p s}:t:_!mΛO7%'Eˋ"^>1=xƧo-W˻;BDS?Ou^Wj,?|>@1|@CȀMҺRAOnJC)j-j%ހ'p1&7RKZt9y|9ֳc7S6+_*ScIW|H,2>R`}iW}XpKU:!U4qGPz(4֬{Gx9% kN&{|EJHv0)J{zކN6bD^ߛVG q*F,~pt|ﯤr4z5/LÁiqAk^zTHCygFkh x>H(s<|?]Ls#ɊkJpYzTAZ s^WIIReZXGl8Y `9ͻGgf0B89̼ܗq̏6rI5^9[(#.'مs'RFE_M2h*4M`ưh=4CH08t:7klȿ}Z,L"':X6pJ:EٍIIՊWmu*]-\UP*D-v<IJ_{\DIԍUHgZmx" WԥVx=!3 `|%8w>.@]D:A*J PsYW#pg_ $vӹImݵQ)-W yh~'JAncfISE/tks}qV_-g岣& nf}yGcb5I 0g+dVG:zSzS=y<$G/'\ "2"1k2hAbYU4rlk Ng+qm"CZ ^\e|7A0Kj-@b&u Bmkew Wn-p؀l_`˵*@Ĝ}wR2ŸWAs};| %K1#Ut,lI3؂g'f1gb];%nYBB-ShRuIlq1C(0mTF;g+}TӅ6*&a7p-ki@U)VV֊:2R頯C͹͔BbjC Ifnح B9t@Ph) EoNY,%}ڿi"L+ 73F+Q|[%dVGPi043Jl)hESSɑy?<$PH=#}k 726ў(-,dt)蘵UP86"cEG1L418ODU2N{U[87!8Ns`7y uW SRrwV`^TO/ tݐ.aB9_v3?yru^u3 sxSdU_SpүHKR"dT[fIr1Ak[T5O@NZ+"g0=;2[9%A3񛯼(҆POћь>-2cid㪜M2GzG$ \`|%p7}ĝ& Yɰ&%7Pu߀p}w ׿YYxG6 q@ <8M-}6BY\fWh3F%>6- i5ͣ`#6}|xCYfd+%zyj/G^~QjAFhJw+X5хv5% <&웱D߷L.5␰B>mNŭ9YsS+ma j7%V<ҫ!s>!5UJM|:^}@AnVYaDeօ,`jMlg8bJ V%*a^ CW.α#nO/s78EKZmoeQ(Or"7q˯hָ 5X,%' 6J:A:Rہ͝qT Ճ7!GhUV膝76zu_}7@5Ln8M^b@؂6=RaJ zR|evҫz"%ɽV %XoO" unWp&vKtL~n@e졧UYOX H(D&V>*]t;d1˥*iUMT  *uf<Iq5 ZVv0Hi_7׺!Ls?\ O$*fw4HQd4Ŋ˝0`~eE &Sс1I _WRzYb06d'ґ=(R$Km#) QA\#;+OpO Պ2gﵡB A͛gL7E{;Y]Y$gaY퇗pH)| T+Ԛ\eZYoYko?\\1u— DPZly{~VgFU@M<~~*S %528EBCyy1L>UZ)q-ܩ^I>jm>[Ul`]GDeՌEڽ Ir?ֱ9kǟDI^8Oz,ͷHe;/~FiD$m"atZ?:M+sl̯T(sx@>y ?lDzRBj;bKHVEzlO:NYze0u)B1\QAilV bmA$5ib&W"BT﷠q˩<[ik‘yosǓ=Tkwe/,E8|&C pAĊKqNNC]#[JԅK|775PrNFFldxa4FMYaKZHcwK 2b[:f3i{.*DH )xqKP/h!C3tmo ]{8_hӶͣkVRiaa ޯ%&Hd,-$o{G6(~"q@]B*# c:V۳N {Ɗ;6SX#Rf' qowշjCoC$'EUE13`QK9cϟ> 3q:z3lBre^`HpWsLuxHH06G 'ߘCh-;xƍ B=>s|y4´w}{96جF`Y%GY.Ze)3_s]:(O&V%Qeb}<:9bJG`m݋i7Zق[{kG'X'U ` +ڜ \WuQׂ 6@96IZ* TUo<7or؛}玦^bL%Fꖱ;rV I b*ID&>s"=2س LL@*.IhK^QD,6xywp vE~c]HDӬ hߴxT$_\A*G G}fN yGД37R-#w:r5E0oD P*YkΣx52gЋO$~ G[JIoΉ5OK|v"v2,IWF MjԖ9<"PFwS0QaoBW" @Im .p< ]$LNf!Ցjb¨by)ŭ34e֥5ܱ䪧M<}p)HGÖ1ѕڀuǁ6B0) %vQ_تzȰը$ kEZYtĚ^X`9;h Y#svhX# Zj炡(܇1ay~Rk5;QרB/s w$@y xܵ{iIA"Zpvvդ cżW r]]dVߏ-LlsBǫ}>g],P)-u x VޞK\j-o9:ؼUA/@8pdza2tN<,:Ѷ ߕ+q狎,$r=?ObfcE0q K'(0:kH+=@ l\TLG[!*HI;Z>FTeEΈ/l%V ݦ(V|7vME> wfJ_fhLS;.u io(4~ZeX8Ns\ibY^" rʷ"S0n&Jœ3MXU9Xi_MV/2SϴH9{ V2}`!Cy[(dN yBKyk"oIaSຽ90 JixDCnF'DQ+.OG|EmZkt0Hl6yX֯=f㱸{̕Ξ'4q@@7>S+Jdز2ey#9/@CbɷJ0G?'xi!bbYu&,TopW?nF;kvCa8o5:y{{9iU1jL:EK)^zts>2e-$'NZMM kf Itjo?d?R89/>ч9zsb W\KL(WROtIFdᬐ/ sFlStTxwdކ`t:`i%R`2:3q, xTk, -@"[ ْę]zH3jɔ`* R@o}>k!8ʜt\Plkƒc:PQ%WTLo~FtN*8gYiYKQ>Yn_aT J4W|U_i0ͨTJBi^ i+k5i<$F+Ѻ^)+knz!bo ǟPjI\KI-=:R@1-xjAɆE"R %Y|:}/wւsC9 5$bE*]*j`%[ƾzJBD"QuLUѭ4U 4Q3̄d^QQ}8 ;k{iRTzEiJ׌gR [$!]Ⲽ X5]rK~q:^UαEEkWIΗ_g 8^dº|`x/q°oFƬ0//nj(z^1i+?ܢ?T8ԉ#doiu\/ s8Qs/Oۺ5UKl:s缟Xv4[EțaKɮ^dE.J8@D- ZNh#5+Gס^e.y578t6~}3M^m1(Phf9*L0h&QDW/Ȱ0Ğ&$j KuMnZD%b4[hͫk}F+r lL>:!ds+%]VlCwC}۶*^˾$(bg_1T %6[|հ|mzo7SO=i,|J9H~hMv g !&Y3-@ dJQz2 t-|jҮͭ;%*[Det^Deh}_Kn!ޜm9vjnQT#ȭ[-:?BRI$wz*#\̔5'r`&Kppf4% (SQ.Dѭ!a)Jh}dQXq;j*H.I,z=uB*9&=AEjҼ(ceӚ@/Y}}[ Y12h E Hj1]\RHeh/ʥzȶNS,as9 V;sq.zޡ* jݽVRYbmy[3m$?@_ ݋rkR&VE%_{U= &jtziYޭAh&l[\q[w/ w/tѲs R#ͦ <@'`8LtOFqCDLea~ԛ&ȨK0+Taϊ0/ZM(`D{RC,W@`-7=sw@2w~\6/'Iw(/ HIiHNgm:-7bG q)vqpS~mxU32=ww5B4GE1?3;'J|1rdw?_N..O}So s %覹 LvXTxU/bm2Q虓` |.G5kM6Hv5ookl=Tƒo'ϢRx\"HPZ/KR?T7Nκ&6&+-J,~P[j@6 M;"-ӫ0 ûZ[>wOYzdܟqrc-&s@=f bYY"MA  Tw`NY3i@i.H:H@KiPhՆ]{i!LS)[Xh/u.ֹ)4SgoqpϾޞ^nH7M溷{OMհ8^R"ap Gf&XOLc@b'Tx4~tȝ_.@,N S]~g{z}n5z?Vi4zp;kgNlv񽶧_1RrU7.5Ojh0" 'TC̢tZ<Ԃݒ1MГPT2*A"+Pq5 6ujQow4fhj غ{趟{m[ϵS8ۺUxĖ5ΣEvjΆaIbƤM5# ϣO/h+-tV8BO^ٱ4KC_zK%jZw7Z}QX?:`Ӱx\ksȱ#TTs-ok+*J,&2%);X/t |xsɮ-G}u4}J^y߿{w?<㻟u]ooz}M|=O`ܿw+MF{b*~4>+ͶʞW>:W2FOeVFߔMHk"a1)}?SF?$zd?.їޟ=_~j[_S6 ]zN XEf*5D3k|t̳)ыrެMQ'UZ|Mz[6Z?O3 .*_MkTi-FݬMJgK-[zd >mCaѰZFI,ģՍ%mAU]ִg-lr>gިVoH&-w**]U M*+KRZГr|\1ln^f[}ͪ#; [t;l<-x[-̰ǖN,{К+SWƤ $W2KSUI`T֧Ü=݋4j GَN̪؞H ^hi-AZfvuh/sHSAzA'S Zc*qFzOsD ]WBȓVM $g˧3-jm浘<˧RH"+IlHY LSEJoUS`oPꩩYLi禪S0=/Ygu(D%#'uȖP_ }a҉ 9W:"'Y NOu;f: iGF J++HCW{be:+[6$Z^4I%vE*AϬ2PTb0Rh`搖+]ҙfc?3K8R'TH~dNMH/sLfr|v!/Oha1^$0)N'[PІD;S,ppŵ5fQ;-JzB򒼻N.b 3J0ؤW@F9oac "vݑ3^9X|LNJ%IVyBkȖdHKr̅ "8]N לq -z`aD]nuMx=zEB7E)]pq=K-xc%;3ȉMd"{ , Y| 札Ъ%CR25EǞsP:fV:]ynR!mHo0BTө7c=<20y Tk& vm X@{=?`yktx?qz8|=^ct*9udaǼ7 جJ! 4+u;2GpA5!Pz7 Gdqax<' .QY={{'Y*+{jjm(io@tNtƼiYy։ͩsޔD9B*c y߁󉩜lI![$$K t PdI Yt Pfb Ŏ2>+1l$gE;:\eT6cJԽKU5ŞSH,ؘQr:~EE`, ΖcѬ戨MO WY y,073q>p|S_dU Z6(D󞀘t$92olcp1l 5Ey_lyS66/'ݥO60t 0 )ZYS*e@Zm~Hx+ޱuTtڧ)Ir%ȝ^1tMVuTRˍ0sGB3sYs޷S]U{Lٔx6zḸvRhk:BP2q;W^j^#J"&ҳ6 "`eKlYGS9aW٦}#Z r'O@ ɋ,˥A敂3CXϬ:ker$GnR֘U@ t /۟yD}AzŸPBj3$pV |ڂW#X/v ƅQ>~d/yLExs#l'dK_sg@1 :ADR%(:"Oĉu<>B&#w ?\4 kɨʀ@m+N+fq HmY5.U[܁!냞aޚd<%6(' &ŵv%>ҎCzGjwFѹ jGlBoS\&Tرƀ-BB+)x0L9w+m h!OVejAϟ^үRҋI&\tr``Zť#zL  B̬ Mġ]eJ__8JAaG TYQ=hE&5<] )y.}@*]?9ϩ~)E%e.+JOo'طB;qRF w=RH ?C*gktzfDv sfu D3@ٔ4H-~)&oWHiṕpMA-9&!yoQQHPbMw;|D\UFP[$D4vA"L"Y!w_<r$s7֤7jڴ;mCPYR.u|g*b}M8 ®ģ{8s`'?;g0?]YrVƧ.0IC20 WҜx)ğ9ڶRXrmzx?c7^oi:$J;z|t td֩HELxᶠ:DNdy8p#PʋwFBxBT!:V(!}pQg E]HZaLbQ^&c7yJ6ڲ7Kօ|4()-3( Q!/Sr4{57:gI>>X [W=rs:)duWɋe4]ġIlrk7&؝#Пʠ$72%yL|ĨuQϘ  +Z 1ݷǒY(\NӈΟ-;NkG9[J`_pEfڽ7jΒg q@'pԪ<8dxPg@g)AP vd0Rz_AnzCw2dt]σG?YcOZ׿XM1Ltr3m&aߑrpk#A(20i ܹAG*hysll{ՋW;r"otr]7daAƅʳ|^u?>8@??pbx07?4Hx'bZS_h锨]>_ ]+IsT=?i/ Gx8>1A ⎇nz0iݟhu~Q?`/NbDNoyl?z=2ƃ _gx@_GWw<|IFS޳h:1C7/wCZ7鈖p~xקM<'o B"B'rtj ]tA?A fp5~'i灓dӣ?`ex9?$cFz<=i tqtݎ>~hh?AѹCZ'{ B_Djt?d0ɩ&ZAJjg2$~1D%0y'!BߓY߉TȊ~})qbkCwdAk;@hi_3O#SqL'q3y$cP<_{{b9qc=$Yx%%zxCK]ݺ}ҷtze#(QprdƗOi~[s6*) wD`E9 vqA5/7j(mnJgakE9⏤v.FʀbפWH1Ȝ;ǠVX 10\`R] b_>7|ISrjQQ$Nlqx{>1cAg0\(23Hl]ϊu06bvŅv$+[M$onD\'!!ȿA:TBzFRSOe(e-3-g y.rV]E9c0{gej zaR{BEVS9HačX0S;){EFEȰ3>~_F!wsAb7Jp =1%*\/:Q^dYmeX1Δqn8"jb@6K#OJJ" `\V6Tʂ6$ rzv5:éwNI 9Va7Ͼ+UPK%Yi5`h1Lq:\]tU1dihL7ֽEiJ[8SU6r<8n3i pћđa,ÙhqN58gdZu8%<>4W9EC-bi@KAޅS#?SCj^]; &tхD ODpGb3cPAg! {Mn/K)$4_ԄsJBdn Kcc*2NUBA@N߾=ڿ_1ŭe09#8v<Ƈӛ`=8T:;< tݿ=?bo\XS04A ܑ@ʲÄB _z䈐ڨ--?'!8<-en%: #Dw3īWU2>Qޫ߉}6 KIfJU5ϻvKwu3YNdTBC;aP8\P*JQ8bC'q%L"ͤرB2b.T aN&ɹT<6*-\5R.[Yn&3tP3!"T\݊8@\C bhD䙻*R/\OxN띿=d-t 2eKP9F4rYSaVaߐ\.@E!_wQBiܢ:$`&1?jDe&'vyąËS6/zC`b࣪ f^xg::v^As,d%iM Cpb*J_!`s- %XRq_K95ֽ\Z[:B**xVrma2>Qq>"C1',sF,Z1T;[Gh[у{cG9p? F^D+yr O|6nJдxH"LY8V'dc}$spluDV|,Z PW _3r[PxAcpm|Y+OjExWlUxb<ʼOZw\8Wm=_[[Xma_2[VREE]-RT bW9-Ld悥͕^~1ݐ*HY&Y$"b}܏ZpQ(c}rv~~vο\~zymt҇$y# Ry2lZŴ bT;%K&3cI,yCщUEw|pڻ4IM3u%k}ZBF)>~L8Z ZzȳR%0F +.6Et鍍!TldINvMr(3{ʻU]ĩX΢^R`ZkrlQj̈́+$I:$D8_""rS0:a.Y+|ڧ0&ĺ8v#TS@LX0FSz].:i^Tƍik&\Q~ԝT $=OVD ׬R%@Ƌ=l+QԮnj55'ȿ5 7#c DB.K=0 b%ʢyŲb5 Ӓ^(kw<[nanP_- j!36MVR(]׭dBơQ'<{Q!j vTMfMμ%o1#ˮm4Fw$ dT*:/Y<=zlRJn,n& h ޳i1aokZ^ lbw2xydZK=I2dL".xcHہ=h-AOaiPdLNh^?x5 k,Y0ƪ_8 Vv^kP u: Ԩ]IhgBnf7ꘘ"x1tJ(Vi]ez#&Dz2?.)y W]U"uĺJ =AC/)۽>9\?Ј=-,񁔐)|hEpϿ} qt+۝sh%_쩕υavG1I!WiGT-Knmv/Z6ZW2XAn{0_J=Mz2`mi|PuR!.Xm氛뇅Ymk]-k3wme|+]kYS|S3:tj'_T|먐m2 reׂITvm~^L#Ճ\YY@!uy}%mٝ{ˍd49xذ?˃&gu@}U+9V.]G>\iU/XC\ǎZ!DrcŠUwaHj9 ,W)2^b>͋4xNc5XHa%'[U>}?NZG?vA;C'PGy&ZeȅkT^:kÉJN;簾)/'NNjYEp Cg0cjb2劳D=*Syc *WQB_x|Ua5mei2c:NTVTS9HXaRdkH^%C#9ܽ%4zKveþ'`4deI{''ճ۟NsP寃'ߛ[=n{ _ @'?7tl?>QĐ* wE!22ǜdDFρK@ty\@n7zjSZQk,FW'ѪWxDE6?L:2(v5.s@ q=mE SU ᫁+.Aw[>g?R-5lX}D蜎H FݡzGRi7Xzr8G2m˂Kqd#fL+b7ZBhOO=Ei ^x,U "\_\=|iSy⎪fF2X}ˬ Gn A4.UdA%dڏ@d:5UE9wQUȗ7Nve5/uZDYbQ`ίpʳizU*|4XZ9c^},=Q\cC>~/RH`VtJ7墨XS~ |;E bCd3 Pn(D T:I:)%P!Bl &7`yL(؅\HB.Ia9sYL-,B zDI'$?w>oOO5aI?R |KJٗ}x9@ /?q!?~8x+>]&_p b9USV,e||Jt( \& }ow3[f6;jɬI |2Z|28bL}ѽ+~$]>`#9Lm R(MT ׼ \M|ҫgJb&*빮T䌊PVQ*FL먙ʻnG7 L&QkC$|{߲qv*RJk">OU(4)MbղޫHJ'36 gN!?f/ɳwח8@wzu.!Lo?|b/ٹ^¢=SZ l憣} 8U|Nf-X{ȇ/G<_1H`pseDAd`XqtLIQߘS$&J?l8HЈDNN(,B;)& hIɁNG[?RΚ:.bP"Vq1{7{R%0E pk@sm\>vvz~9; ,WQ{IRsb? r8Mo%VᲜfqc^zp6^p QM69>qxbH2РA쉐L.oISr՝<:AjȪCfw6"*?VͬB)nvs#.^Gl8gGGA&\ZF~4d_[ƵqPsXk&|8,:G>9Be-dwJr!27/@PrgbW-hcnn=#D~BȮ[,rES-kK&QR||q$ڙ,\O# 165g\+g4ȗI<,HZ%Y׃Urg+b݊v'^- /bq#'>QJ?R#Ns6Aۅ$fE|m`+]>0+v'[tGח v1#XYgp-$d&4>ҹt(҇Ov H\[yqu?}wz6T|8#P4`D&fH'Ά*MbI.DV T*w}D >IeV,Ox7m6tᓍ,̘w0;w/1aqdoqn]s*=0úﭩu2"n 'mrz*z@L„w t$_LhL}_R!jP3`f_8AXԚczS*vH# c;0R_8pE!pI~UMtFf Gst=tdAU?ރ(ފ}ARE5P'Ohs>7B|pܲ\hI׭A98ӡ&Q[n*$Raz9v!Wi p:9;zu/H[{v&s?E}`[ :9jfm=`Wu0G8Ʌi [/mhL$y3u῔ERC| Tjܘ`?J"و4Eh8 n<ku/(V/uA k :²]4 [C3jX3X!w˚ƞR̒`{X:0^< s-K C`R 8QhG:rV֛%RܬDt0+ zaD9F-p7ͤ|juRG\I!Bb\@UrHf֋ G b^t\|X^Ds!r@ ŤeVi}v0q:p+ZvlMU22qzzo3*(B%1GvίJڌ8WtXꢠIJkgbIQL?B s&dIm.s#m i L3NG.2QA) ꮙ'f xBE\ /C \X3?33_]m ]ϱgBh[rD>cYm9 /}=O ,2#d v\ILۡs:RXl+s57%I3rK?pIn |wPW=zrJ~(FCo2K,*E.DPXky ֦p$iSܐ8o&тMhO6ݙ‡ \Ete€:/@'W*BV H,"XB8xCJm~l7>nw~,$F5eID$f|u?׳ƽuE?;vCiL@)|L\~ Hv\"<>`Q{?l ow*X CMmyңB`(zkQ#WF} Wt`" :M`z_F+%>=6?̜[LgYjCz% eyZhSߧV連D5+wo =v.]:y$]ea]ح3˲غGu_pj\gz0teRI 2@Wkۢ0>vkB+`lⰽ 4eZKQqП΃Cym`0kןЙ }!fC礁\C,woPTC-K2`RɵzKTUqT~`WU]PaT:/\{.g1Nq~QZI-ly̕9UY8"o cqjjC,l1{̘= Eƀx 4jYpKVMA}o.V8m p\%2`_[/ S%nO7w`s;loqn0'Ź8r} @ l-(T bBsk|m*9[砧MJ{rkkW(ҵ dӾֿue?n3ϦQ1]!9%+˚y(9!D&̀=(ǁ=J,L`G Mo^*u6D-zgM']S qAsv|۹{Z ŀ%$RB8/ y {Fw:OrgP7'NfΏk؎Bu>ܬS !c3A(lol)ЉVH>jDu,݄׋ə#D5 ,dWُϪ0P !6NΜXV.BqJBfdమR{'tN^%H1<ԕ%r Er4tBЫD.hqNud;jZ;ǯls-=H9kk·cRa14{ʩA^(4Gx(6Wop`A wY6dV=}]8O8U@ׇ7Z `:Z}# wC$lbA?9&M#.Lld*)# hR!Z f僇B\J,18zlDjoCR 3=JBF.Z\zk\ $#mv_tU401Fy$ (ldD4Hg)=EWN;ay˝~/,53ѡ^qJ M⌡ꓑreAlg}? >ӯK93 ipѝ|l `.f5$ N"ܝO-\U 3ͫཔG4 "3T+(V7yܽe{qH6:WQ=^g1B2{%?:(h @Pم + ,4P `)~uL-˃vZkl{u'~ըΎ|a am K o," +lg RH!+-!\2롺haj8pC "CxϡddL߂P-86rH  z'LLm~Gخ`X#lgq}w&*.օWkc֓FPqV).U^ bx:?_j]>)^ ԴgS9xUǰQ}Izc-㽓aWWW ͋A!L)MgRB9bfб^ʡk%po3x]Y\ރ*aKacEƹB"'Bp!yM2A/0p~U ,–uH&B9/8X7F<) SiǚV1THml.M֒sK=ٻ9TqXEnr݀Z=2\^`Q3AtkX6^`2[? !IRܜז~~8.B:a{BPyc$T ^3-՝\٥h[3-7~ l3l-:IdnbMHvUw7CKg,SWە^0#*Ժ<\h։˷2I:T.FTƟcYwZ;o}Wd&d?IE#oyM-'6יxzIOϟ'!]%Ip˷T@D<7ot\4;zGLtyߣ,bG|%/<1V;c#5tfQÂ*K^X x~!>JQKjڕ]D\,$]g+kQgӡ |ܙjآ.D!-ݎ9u|34-G Dsy!u! {J=aG6z!Ϧ0Ύʉ[l=0g?NF ӯ?7-1h ZJHubֈ~ul>ȣȤebz1ڦ_ϯaxMj0D9b[k$VHzW֖ʞ ̼gV)r{XF&D]bqTT@%e]ԀjU7vbwqdף8nF9UB^=omG-y<=HOJڳX%J䮤 tPWHBCp3÷a Fܶ{31kuFXVfx340075UHI-*+I-I,IeZW/SrP]t"U i9z` ^nxkN}“B}2(DDy_3gl*(713JvaOڹ- vvnk郪K-)HL3D~{˅lvc B$eW螰0Q Ъ)13TYq^ATU^޸n=,I-yUUZ\Ue~/y k.-]wG0UE0]7f)6 e~ZqxTmo6_qs dYyɦN!q aŖ"ek?~GҎ x^netweD-Ȳ0B&Fx2Tpֻ߭*s ~9C`+]0yt , #ӎŢ"dX͗% %;ߊ/`U9E(ZkV`+Fi^UR~O[`2*M2$:dڧiQ܏p5Ԧ)<r(;1/ ;w.!S,Wrɮa7 #P:4ukP٢r_]xV q!`P\U" GO9$gLx< w+'8aSqIpz.%F3wx8$vLaNf ]j 핧e\fC) rE;E$'20WK@*NsҏU8x`$NW0wbGA\\"xu @Y k,E[wN{ewA_^? _Jh N -6;6HS?6aÆG 7glhE j7hM"UEbD2Sos\qm,.щTEr$teXhA'M  R]~4`9c%q" HBI$_ɏ)2!:L*ΰ,B=nbdH oy"/ nx}Q2vAh`RKD{l5<o4WEb9`wH&l2 j7[tiFpi/hH 7-F< srj_:/F}m 7Lh::vjPoOCgC7cx<#axUPj1 {9M=`IS'!=$ AUj"5% D.9~P~Zm .Ѽܿ{lZJq!.'"ϑ+a)LH3k&$YD)Nw{^}7`G? lK'D))CBt,csFL}zmJ]E&h%F*CEuF9I3\'J8,s^ R%+p|q>Oq1.t69=_!@p<[LxUo6]U5v]f&|R(0eD=RJ]LI{wٰj*{ϩ`"+C}:5TT+NPP.J*YP]Ф`jKKe@,p24/SQŖ\ g49,Mކ T5eɷF>Y+Y+|[#TKgҙ#ƃ^G/W4zۊ:ϑJ,WG=~C(UBQ*%>^ffV֔O6J,jTIbe:t%OEmZ)e M2stKXNW" CpWz~u"nS nN rofVl5d` etlaDF4mhNW-nv}hV&^ZrQm!FX)h<WD:hpadf!X5Pp0{bsϏ/Y#:~l) 1i,%fv:?n)!P%Q}xG'ܚO!͛3er# u&e۠ :=j7gI7 cM= }>ߑ\,Vq.~<;&n>1G*QQ!u}*hDiƠ7o/O&^,CUϋ Z1Y?>bdQǽk9\pyG`(0 >ٿɯpgeS%m^Gڋ%[*6L4ڠ%f@[)RoX@B}4N{ѻKrڔrC$x+{3c/e ʸ| *|,wNw>b;/-TcR^+ܨ۞qGj%,Ɣ¤M&xmQJ@FlA tC  PImRE(l@f6'KE*Of6|3|3_{бZ0:`pׅ<0Env~; ,'y3?/77e.Q2gd%R u$Gj;0A0#@6cюR D.'DxuLpRUEq5%"sM!L&:՞T ,ÊmUtd4t`? kdu.H#E,spNyױ\4eSmoXz LߧD`$ ˫?]eRT.VэMj# }"~ ss0B~S/&_M!Z(23Lx dxW}sF>VS(9/Pqim$xd@r$zw2.ݽ< #N;NdRtnä2O' FL(xJk05`<4OU `6XYZ`\гv* T]A3\CjbwwprkZn0f<#v率 I"e70]-.r)y|$mY )X E4Ä.2Ni_u +-@=.Ts}\责!2/qe|(*>J OzMb?Fbr LakE,6"JLPH,Ҿ ):I,q{6.F`xn1|%%:=0m#{:׍#1,>6Kwo\,^fi}z>N%t_:NE!?Sh<^@AW+F eF1r-Fj5=smX`=zo4nXhb".&+` n6 =^M0. 8osM$X~[]J $Cjh{\un?c> P' #jb:lxt8Bԍ 7Q{FOoh9 a6/fl\ˇ߿d{KFG[2#yeXn[ta߅4j܈cP~pH&\ٰ!Acm'^ۆ`0[ fau8=Nt^i`b`ex8 >S3f)Ro6FɆ8=|A}y$4-lQNyY9OԱl&斑kP uoyaM-j1!kCF 0!CKi/f6tqR_WM,ѢT01 ͗к_gȎZʊai$Jlpo Dգ IQ}?Fmwk5u2}?9͒S&0u~_'yӁ^ J^7^g[7y#!r~u@2{ϥ9a"`Vf=yg~F =@$45kƘ5Xy/^l" )/[z׵VA)gk}h iGӷzJS9[GBspSnx?Jd%h{KC_moKFb5Not*N}),/x]A&ۄ`18--hAzR8g\]XsY?2}WXu(z,YG{L8ÿoT%H')=&cDvVkPvҙP?>g#~O\LVhPeV1υ(Bƻ͡sEjb̮_.FMb;qύ#\X' fMGCG?=SeUpp3VkIwqV\q5d.h?xֵw˛|>G,}#W[xuO=K@09?VZ r'(FYIݹ,,m<Rc}̛ξDjY Rpsh%Pu(T%qbuyǙHzsC`0q!&L8},½YQ Lȴƴ6\S-[k-?/I'?YT# cyS.[px{)2G8}_6T+>nLtq6kxmQn1'zႆmD(I%&-U*UB 'rw[E%ʕ ~ C9T7yo۫yF&(L# )T~)d3 I58pWR83:Pbb!:" WI&AD#Ȥ _@p:"όr PM8]Wm )i&R @JO$ a|6q%C\"p,WyEMВ R;@mBXGo>  ,! 㐇0/ fRi,QoIOS0!$'H+ vz<8'g$!rf,`{2lMA.Bngv`7ި!>Wh"ô1^%p/b/9]y5۝Ijpw/?lwߧ~翢K)f6j:{448fW 11W%ߵnZ?~ axSVO/RRVPLR(I-.KI-*)S0C#}3}KS+C +s,׊|Ē-%;;}yz9\xUmsF~cƵ-b I8x@H: 8; Ǿ<>{v)E{vAEZ;A(H$B5a†2tZB_1%I V -fngӇwy0>7Afapd/ |HʄXA)ZUktN۝wtΜw=_ L.~F Jأt/.Λ„I(_ R|6Dly AИI%آTش، ecWTBIKz:kSARE"aͱ/;$svuGh@Q$eM߲lM_/tc rY^ri%D7,MaA,˴Y`8|f=|v}ߝ3WtM+0)Cl$'Hȡ¸O~L{Wp:ѹd4q}7 -h^ɰ1U=,4)Q D8F/dCRW::CW/:7aG&^@H[DnPj~ӄ\*ytzn}M8psasU| ϵ `ץrG9ÝrxNQdeDl%<'cUuPja.5Mr0=Q*QXFl!xzXdOXX.<;-gO%a!&tr%O;p@kDumʟ)0Y]i '(5n%r Ttя|J"LPpkoހ\`/E=^lsPǸp\űO|C`E'zFFU9Olmo .\nG36. WjRGy lCe7hI{ҕ|MrcywѸ TqxTn^HET)M^ r؝}?~1lco`P [Ha+4! [ML:PoPmЂsЯ _?:b5x340075UHJ,IMH-Ie+So%h٧g~B%g2|:MֵQɬM:G_ BIrn ٓ&[+H42"-13(QϿN9m{*՚6#旤0<={*-3Bxo!K;8#a+O'_{,xVb,KE&@P] TcrJ iR<+7|YgxEON0W I!n3jĉq\bHv!E|<&jғѦ +=$6OC mp]ĭ}[~s˳y(ץBpVgTӈ,F#JvtH" ٲoŗ ͖DNqq_zoiWW^9&>`Ϻ?8InbFr:SOiYJx}i[Gg+)df$ab7iI t5-0e~=[mH`]]˩Sg,_dj/Wa:T+G G&g8 cF T > 3'jeywdxU6鍢ɤ(Uq_$uV1pǗ7X .'L]D)g.`al^0ק:h:66QKxN "7G?> I.Ur4?ꗎziH4rF6!yvh'i0~?:JYOGNlw tՋY_fq~*,q۽/R5@Qv64w` m!  \ ۲;ia(hxe`z<:,ă%~Ih%;8yrB0poР@~D=ѳp:`BP>p%}DZ՟dy2Mˁ6P{w^pÿOA}NWt7'};tuգ}X Z9Ђ^yz/8nGHe4>@6([rpp/xʲ0:jA/48@9hpX^Bv"vwNJ&tdY/D3>>1v`;,LNNPAq/`Q.p]!QxFmgRg?n 7 ugΘjL1/ q;J*6m1^ .;&qk"$NEsdtJ4:/'Sw`3b6]8@ HvAQ3eĔwNVS`v z]Bjy f4-h,# aJ8`L?8,2NAjvAj-8S0  ج41X*wv1|xʢhagBDΐ("tr $>h4)V1?7ۍ;h'1.BOOIA u#f?@Q% Qtr*i y&1y  $6䒶%8O'DADE)J\ ŕhi:m @B8 *m::7m ,`p>1ViijvKz\2 ˊ|TeAwi`3"oF (:Fr:rVӔǍUpr?D= OG@w{"&#!ܥ-`;Z"@a]OG+GytAbja0wa.-K6uj嫃G;G[<^ $*@t]AyB6"cZvJҳE&'aSxJ8'{\h$먝~.ǧ "&@~8Hqkm @<IR+i6aCW pC;̶P0qs qnYYb}e /x6|0:HB?F0f61Gq0Kc'Hild)A.5jg:9I!K-, hON>Zӧ wpfH ;p8:C( F|UP8q, <.2@0Ga|P f0 pZ|V[ML4dfX'r FID1Bob@0i#_C#?;f? .P~Kco~"Kǫ4Hhw!0D ~r exblşF!N!`| }-\4lv#XB4s#? p@q<Ƨ91,BF"ET\ kNm!c ?&+pfPԼ]uB&աOv_<}U`ulW5^ I(MLޢz#'`Zle7vdD #VƳ"BJpҖ]dNM<AKmރ?мo:!c,mA~w2Lg{0!|ޟ;c&Col:8D7{ц5@·4SM:{"S{#zWC8'sSZ: B@^,o.{zGx7L/6q>pGeǫѦ*]Z]=QzsqS0^!/*@s%/,ĝlBv5sBuAǸGZJ4km1)ddBLAoN3bkخA4N+GoG. Z?)NA2>Gu*\gCTeknz¬|<hh;zׄ@t c&᎜Xq΂Y8X K:X$L@գoǓQU ;|f K-~٨V YUHġ3q.ayv^tНm ǒѽuzn/[a8Gl?I7{?vwE??? ~cɷo狯_l.ssj?ϟ2iN&xOI8b;7 ܤK"= lb. ؕ1Z!A' [ ,g< ]\NYR߭M2]x& 6lv x̌BZ|4zG߬yf(Z#p{,c4"Xw-TJOpqR2c mt5^@; '+#z$:g#m$ :% :]⒋,Byq E6t/ b 㼼:`_Kv Ŧ^D#vaoWУ35Bbn4d&Y!0 !̔v-h57Dw24!>p,"(Dl,fW>X .Cmfh+# 0jؼWVlq"P[\#4ɗ"- [X4=h^2Q: &zYaV !S2]@?A[t"._Xm[C?/2[[_|džk"#'';IKD؉֜B/ ڏYTF(YŸy [֒ɉ;Q.Jgx$U CBZ {m^<õǏ+{uxWvȶџj2eԟ5@ p5G^b:_0Hцfnrܽ3{ DzA^1/%IL> A?s={Caׇ@#A>:i?c -qo5 rjc⒁'Dv&(CEױ#jI@zfAhxx] ݙRKJzœsNEN2/8{M|Nl%8 Fs| @Kb 7(8)n7$?i?`t鳧Q]1kbfW+Zѵ ']i4AOYȷ []jڢL[Ŋ\4N !B<& @-!; lHt,OinrmբIu^"keY2RG0V 2,vKbE6B.[I[J-V^ cQFZ6C)z T/ÜzHeXL[ܸI>y[4P N9FcA3Z0ʌKF9yIqV%G(Ύ$=7GVZ 9靌} tUӵuR[2@r196,BPgy\q=+`!TqA1v/?k$ >WO:t:F!bn\9/Ld!Cl$9nl['o?N1@s8ߒc4 +í&2ur|Ƚ6WD'ڑu xeT!%**+_կ_lm_-w^>!Q.OegA~)wj-o/-S!szZzƅBhCzt肚Aפ=?qּN7jF\xOQUALsrqq\k-̋,Q/ مPs= D2}A.UBU<`YȠ/8 &Yr)/vS.ЌIEuh&vߝ!XaW9#upMOBM[)Uh"ϖ3Mʖ?.a~i5Ҕ))  ýQ,v+Hv8ɠx>=uՌQ"JFEaOҹXx~w@RD1Xkv$>)~Ɔ;kmWo_[hr;}Bistkv{s D0D#V;?{`F$._/%NKPcA@SB>SXN)] J40)mk= s?kc^f# ky>O;}rBz- *іEul椐QRoujS&wԣ <.2V.*2ކWJDL!u'cTq 3&(J@'VxZ9k4G(}2%Uqi8a) X2''ߟH| Enaz26 i8 =A25/WHG*2Esfj|j{f) 1$ILS^ I'tbjGHaWd zѐFd/q6qv]D6rB7,}}FQh:(ƟڒeS[9OD7y\<ӥWՋS5qR~])xo2:ݳbGIFN<` :)L谾A6 ǚ 8T Qx,6#tFBgd~sM;C?; n?娀:1FE-r[x柄z]dH&azi$GyK}!%un9'Nɲ>43~pA&KF⦐5 _#w!{KjsXs9NCC3K+Ul8?+c Y4EOv_x#")] [\@"JC(9: xlv銲9:axZm7=' C6MeR-%~vy\bqå:,l[H@U}"gU$GoZv\TKWQZ lF֠lrcբ#_C@V-e,0z"lѺhlSl.ܳIgnk'⟆ナ1vjݦSƍ's~1۴nt6s*I|s0W% BIeH!$S HduEvn8b:#FMͧ9eyH a>)=QhMFvLZCjݬp  qMŃ,JHpiQZ@=w O-ڏ< 2rԘkyF 쾭{ "=8?>d(Ӭ8N6k'ц7W+k\m6>J,=<Otx 9z*PzڡhW;2&g @hVYB[4_s/▁%x1E8a[\,˅vQAKISd"o(X$LuSCλ[K{ hH9cfi(xf3+ ENg{{mJ_28:؈.pt8ZHȫ,~oEոZÉ"nt,3%g03 Y<"clѧT$ -4_o~zcPNWj{x5/mn)2Fg`ET)O|sDfk?b ԝ*0bT[Tt1v/s8>y4K - OA,xQAT;AzSe5< ߦ`i3/݁UsifM})8I:sRV!#9~PH'u-w"ӝ=>xAN5H9p)`}I~q )ǜt.S_9Pjn2=C.6^" V _߯_#_M﹡=[ w#`ɅU/r~SPmuE~K$a}8J-J t$M,C8Ѝ w=<yR(d I_򠣛!tJ6O )[.ayiF>xhf6EspE\nRQ\X.abi0@m+m>-Tnx ]HfbzRzGuiZcforRas0bb}n8Pfݍ9]F?䆖ۈs4 ׈8(]R˷q|PWEv(&g&7p}1mT담%B9N(FÜ)"PZQب{%U&Ut.ix2B]9wZB~t^bF[վɊ+qjBg,IZɈ{p^NML#8/Ud H.JjVZqU5С'XyBNK '?7 )ů M Ua*WRfWM6K1J,Zh6[93*bK tڃ'M|<]ǙLCK!k:4WԱHSXVHlݰ/Y@6HKm6uk[kOLTùgIe3_\ ѮeO1P"p?a(V, ?̲3ֻm$,X)~{4{lat} fR0zy!ƍ'p_vWUDUݮTFCP86,]@lov:\S C#vq2c:eR؞$J9K<m7,Ԕb'cP2`0IB $o++ph㭫^{h"yрgHܓ%1 }š]eg/An(6h176=8-|ds|5=Ǯ6Taj`ThpxszZ eVRy76<JI!>t6Z, NuGս'X{w\mFI)qp ?b7$ubD>YUaASER9yG'GC!j5ZbTZ̢XF-9QAțBk^Vu7 yG9ɮȭ5x )AìkJSQax@6O!,eg/4ΓU-\g}J]ێzF)Rp|`l`RZ9)]^AHj64X/~5+&*8o%heQ2?M}jv&á؝u,=B[< /IuGWjEs})JN~hIZYD Y\0{QR@.27MO [wt ֦AmP{%/JgQiOk4W,F_b:P'.ݱb83p0ʲÇPKW짓pH#s/Uu"r#wJAuaU +rТ#fϋ4q ;`G#GHeY| 0=IGUozÉ.[-sz L$:o^uT nO̘mE0"[ ^C^WSSfNTʌQ>9F#far #8},PBe 4*qPd|():AǢqo5 pC]W2ӴSavP u$\KYU3$* [Lo|$Lk=Va;8J)gHY \k"J͝oGq8f2߱Ek8`6Ѭ]Upa`ע֮b)rO6t̹* ; 5rScn*.\J2ReeySeǝg(uv|t&C.[շb5M#2X <2?Pl헡C/?Z0O"t/Q zYd KұvE42e 0^mM֣OyZ=¨:e7.Y͹KiZu} 0O$c':Sˈ"|diVۂi2tbfb7dE#NQkө$e]G _c\hz(Փv)joۿU$ʷfۻ4[Z:ߣ z2K#}VmVbS,>xCމug'*t=dF?l̬Q;!erDOmg}?BmYi\5Xk9p+.~eI%vJ^ަymqixB RxR|gp[P'qoxbW~}kwHcz{ѡ:}˝ߩ׻ώ}J=.|YN)E<7?yvVB/PN=_Z*yޗ~M!D4Wgai$K$g@y{?1"Ȏy:SowZfBPHu Fcv6@)칮pK#5)iܚS˖3A$}MwNOPfK.tfbg })]PGrR[cuԿ4wϮgi}U>JGuw]SqL$:T)5dv JDiΓSfӴ%Rfo8YxIq1D"I0~>9eM!(Mr×rUT 5>"oa"L9a5Z[/ŊtlLGw_V e:~~]b 3+ 2P?.@)itDŤrSVgUP<:=tsqU@=4&9ỵZsR`2ɇ> i>rD:a-@,Q  Q?%a-[6,O1V19pSKnHɑ /-}kЅVtOwra۸S{R'áC$%~g?]tҒDlӱq66ΤH-LamLLx@ WG;G0^3~9I@T߷ʣ-zCΘLy wA\M+{h0(1kR.v3Ě3g@HS+8'I5#M)՞>3 fuF~Cds9ceRbibF RJScmm4n;:z\rݖ\9=u둞^Utq-fOLygW@2&6#(wG+WkZ\\:o㢿נHpy|ͽ%Ý^>oq^+5jhVظ0RDXl'vBRi\qQ9\qDInM*02$0ZqzV\KmOEqʱ`WwEŐI3f{u\qr+pv5'NBV9GGU#'_<Tڳx7]ʗpbŰ~5^ab@ҫF$jjvCRCL9mL>΄=jۉ]fϻ( 54D+GeTHQ5ԡ:,y(mXK;*&b=&5r r᪮\52Ќ8x} Žqަ![(S[)B UT%R*z#a 'Yc#8M~}#1kԢX55k5sb>~DÁ;D^='܋Xum:}o U.a\iNתd@7 _U)LlWV7%s*GKF)˥obNѺdj$P0FФۥgO8On>xd7O\=͎fʕ=q]zV]@2'YAtTM N,U2M,?f"070!lIPVnk/NhmD#w4eR脴nN[mv&4ZD+%y q ^ljIJ|ò=yV:,Eꈕd$4D=Úc4Z=J2`S,&!NnmƋ:X;C0t6a%>;]/dݺ]G4Hmp8D{6Q:uЖa RLWa Y&LQNVt⎮,tYZ.NjD~h%L@6\r/&c]C9YU8]Pw% (X {e7j(E āxo#AV.MQ~Je^OSe~>@j|BbLjsZ,K0^`fC'%5 EY Qt4DL-0CkK|lhy)KvP#[Ɛ٘ۚ ұw)fIolȭܮ+ˑMt?={JQOvJX|Fٜ83 yT ZpEUs%ci",oTN,[^@-tٿlY>)`4)a:Xj\bn k׹|4SV0rΎOgv*`kqήKu7ԆAWi+jViܖ(VHSʷӒRJs<S%`06h:=,+Ű?CeekZR|rԲCw2̻ ?ёg ! ur{7 p53rn J85 a `` tm[ʦzYӲ9Ⱦ,Z|(Ѝwf}QX"˕]I(,ZW6~U/ B- / )Q9 : a9Aa}]0)H.CN1(v-t,GG//%4ƲǍmX)d:3# +Cr 0I~1IJ,n˶1vW c<ܐABX~7V]48Vk0saU>c2 %o/u[v8ӔfXWɛGaZKEسZ "]f9p- kf1^ @'_ c[wgy TK7ZDҋj:Århl5<†:eČ=aW&`ξauhm|M>z% v,Fc>v ͱ s*35hñߨN$P`c6O7AE'=<_/Au?' ?=<HbڂJ0~sC&(͜[\x,Y=͓ 3g[}t@VK>;rzi>ZfdS.ԥR0r)l꾧CO8/_Ppԡ>m@9ے'[RI2T r|w2Py6bfjw6KqAmA8f rhWC_lתtآRf,Ϙgo)8p!0KVZZ~5Q:~+j€7i<q;yx:򡍚~PS?@V9Ok ;/#<ʺQޭ6ho5൳ﯽ2 JCf@x'kՒcE M%cEGj>Pu3sH Y*|r^k] Y~AX?y|u~JÓ AJWIx2Dq0Nr]w.";߬pS":!n)mA;H95㈼e 9@zi20kS; 2 N>G A:x*~u^EuB2¼ګm{݁3sw :-<~~Tbӿ4+ugȍ XBQdJG/,u~f9z1;.Cd,reX%Xџ9tOMwFY3L|s{JYr %M,4yce83MHĵ"pc}Sd Cy`xYX?men^k ;bADnijaZ[(RMޘ!Xܙ/k%aNԌ‡wpCQC@,eD@}h[^ZC9œVզ_>#a>yioj6oB:# 2r3]"-݃FsB + jRTXL=~eNŤӅZrJh?դDXH)y՞dZ "0]!N@OIdQYnoFK`I(`GQA>1TSb\9{>4~ԅ2ҧŚw jlh+ܰ, 2$nLuTV5=Y>r'ZO:XJ8Cpټ݊s1|QEXDd)k,.q ^yh/'],&|wtiy梱k|z8xե]{]{pN=B/u ـ8Ji#~$<3忦otK }ps=yQُȫM񵰡(XX9dKk|pH k58n y!'I/òMNFK#8Ld0lFuPjASDk>͢#*% i0bT2"WP\Lb2իՈ9k$;oN`ȴ5ZP%2Lt\`Nd+q`r®ۍ7L#BoOoG0KG^4K rwh5+ZTvV\7{:ōc: ñ8t4ȶi0.He Ep@+oDc(`BI>c7L&n81 3]NUz5{mpOy.4ozQ3Tɥ7OUs돂D5bU3jEzn|b s Z<?ė5/[+ZcՈxT4>O )ښs(u1hjoyo#jc J-WQ-7GstDW4钜.,oiFC9#,e-8bStɟ|*)l11ELn%,qQl<{9gb߂'s؎R;5c j 1Wx@' 3{N NbmGv|5_'u=Qf4i~ߢ|m"Zq.'wKg}'w-ݒ8N/$AͻIl&fYYǓZ"w]8(p%i߅@IchCG´$| e/;/w1\uKV_Z¥Ku]< ]":mr9.^|ĬZW!.:r52Us t$$;-1=pޫ $68hU㽻z<:g?d2<B nvrW?g"PEG?:%֧8 G訇ҽpL:WU@}$?},[ չX5s\L:)@9|z^3gK#25L5O(R`~?K '5&,r,7 9tyCzh6u!4.QVݤ\"hs-se'rA9nwt€6X mʄ!ID9OiW'V^zj@_/&uG)e{OfQK8(^Ђl|*0ޥ7a2 X"WڊSPrcLJ硭¼@\"c}_(6aUY8<s{S.!a90UۧPa{T3Qk;,/=C"}IcvgD=ѳ@$:`t1=0>CYQgU}z&q*CU+ +7+J8c6fHnp{mX}%~nm2On~մCV04&A;ƳGaKȃU()HF] N9Git+3FS89 "m!SjpNL]IChi Խ̛B.cw+GmՠTB]qz"-JǓ@[o*nQq>董|X)+dU{D7b߷ )(&sLi^ gز)Kď4wmK6ȏ1|Cucr-?AwG]Q+<{:lvGtsIs7^ MSU~(qusp8 n6`9؋^fK.RAt5f9t0:͏Bo+jNvڢ0'-'G"d ]94#vD`Rz[4橥O7S=\h2T2Ф@PاsE3wTx ˬw/oK.߾NQ{m˶Wڜ^CH\rh=w6/ffEɛ/?^H t(WD+i"SOlGSδ̪Ք92#aQE3_/0Z BE6sOFVW a.<ꤴi#DGQY=t( ~[vQ(]|9k|OIIqVTg)`X9NCTHJZĭUݢרm5VY%#=F^-XƝymOĊqpR{}?*=nĦzPw2ڮes )x r473= LzhߝF3:6b4S׹W1f+LCkmJ.zא;~_ cks[14ͻ1ͻn^p!7R_h{k|kǞp%Ţ&^Cc൘5K`1cw7~P`8> (L>'+Ӧ4up 4{@>Ʌco~ހѫ^bkoj24]Cyz޳k*P#^ lA܋b5K4aZȰnA䴨"Yɖ{ㅏ0_ۥhe_K;97f2p85#ҙ-E{zh<,c S~Ї9ӵ5 tݲP^?M0gg> +WVs6tS:]4Q"5ǨM@O2 Q0bJue iQA)Mح3R-gRM5FԨ9.Nu/PUU`ZDfE=Rn YH(L!㖞z$3RL]Iq^ن&+X!@k沩HώozExУ g_j@+-L^)m`{'=f=WD'O$'Ā徙#nt ã绯_ӀLCV2? -5 s_;(Xi38fԒ$9Bol~dmD^tB47ј ?dK8ONwT0P԰G\R2&M7.6H@sZQIop xo4IL@jƟzeYx%ʝn}0L۱/O%W;,rِ`Dx2 R+ V%Cc^qԭ$S-pS 8 $zۅq#=Q[WSljvb~ј!{IQDiX( J1yE/(=^&6ޜj{!Oo`#„ jqcdYuXIl߲榕k2$J7-}6keqbv+؋ b*΍4τ4fk,t4ܿ\8ļ?Ж\ŌDG'I|9J&0%۶eLt:QDŽA2˝\ǫq J4W#b?P#̼m{*aKRj#ZB\Tj\iFτ.;E}Ad5d1cp1pBO/ ϊ"Sii S#XjÄn.I\qR&DGֵ3D,&w2sJt ^mhY9}1&<[Z銽[ .c&+/#qQ5NLDG؄H*wTоaJ&0?f[}m G>R3瘯r1o/q.|Baܫs֬Hv; zqkWcwhW2tr,wIOM|9ϗK9@*;pQH \x<\D&0LkTޞ$BrVAe:'V2SFܵ/ѽO0X8'uiCΈč,r^>w 1@xTbLI+Y' tH0(6eO-sҳ=vH9:z]+&hY"GuqS 4'Dt;CClv#řOMyrcr_t0d\Iakq?чN:˃ |D>oVT%hzJzR%Be TimfX#]9XgZ1Ne;_ԝOkn^GTgb;tj$0A/8:W5g|b>xg }?%e#%Y,}eie|ܻWݵ,4z iK0MA+JO=Mi->E3H nv8ϑ~u?jo)rZU$XA[NOpo||Lf~Nh걢 j|o޷ lkoD>ڕ4.݈G>'x'UX{]lbuMTJiC_ tȂJq}7_5X PUeuKɢl"#Jai{9^kvZSP4!$fľ>%L#A6fנK/nE%[P*tPEi6 5bMBRA/duC j7w t|2̸*8r?8*3b\yL2ܻV9~QqoݰC Ly"X{+1ךNP=]~]ܩ7LMHgF f![PGF Δ@7 ē]mkB$̸ >N]lZIL++AE%)$T ,9(ukk (# e @}7\%)tXu{!2[Y<.kU*H[%}(O2X<I %vrqSѭ J _si ϗ ֞yEj~U8ye>^ upũMUo'< ѿCZ8v3Q !eU9!Ҏ%Z=Mg(Ce&inK b#pPw@49y@ nfq#UprNX0IoHAWfXS~`{ P(W87nDM^B3 çqB6,˩?I8*1ƾoqSqZ4DzE!.j;A^PrY Et"3tkϪ$'Kx6]GBO[U]ّI@;z_Myy`"Jv5c:K9Mx6rFSD 1`*&C4iXUdxYb)T l2H Y]DCZ&Om'MJ=x9 }vr4_Z͢孋k\…u5 UnST9 '5f C -{(/f ^=U!<$s4J+ fO:IwMVOީ<ŬT*˓_TQSw+uK %ҷ}8.aPb`' 'S QfZIIJ [n1YF Iڟ̫~#ZvP+lvl:G1ƌG8"&ƫzECPKp'ū-XHﻚ,*j9xc,&|+QjG ͝qTW"¯^fT.F1@f\Z3R2H͋djĉb?Wd.g`&g"_?joDBvz,Su}?*Iѻ{9aj;)' O`{`͘нbq?tɂ ,r<)7"!}D@2"j>V*,s']=^8yM-_wOš;}>/LKr/z*%A$:xN}0<^xb%l֋NXa&* mt2,ǿlIhOTwV#>W4 :2}~i8w顣APC6iGYFiUB+;bw%kt jXmhNJ߇{70A7њQXzM&l|h'Z:’T}rLc莐RJtm<#̣ԾC?eC̴VYGlk; ӢfXaɶh/:N^0p-.;wC'f4j{I[[;T~"[03ߏA݂o6lR~>"~#ڻZ.lk*Mp'EVx>Z&lXh5}OQ}2-Iv?n^* }(]:o8#ْQs!"AuV0djp;]]-۟N =VF7g~-%ΑiPAp|:T"w(/i9; a Q`kϞأ6´x) 8tm/jDs\9+T#Wན·Jss솆jR{hk~z=W9|`J:uJ [o>.y+O;aAt :}pzB^wA Ȃ2|WTPK5i00ij z]'y$K$P+g߾B LabeSLe(Pui9Ǟjv`zVGca?f%fע 5 E><"EtkN.IQG5,iOQ˛?ʧq`hS@Q[PHDԱuӂӤvh_eA3o9AWVU16{ IϸL=AX|vt!!wbĞ. ~48e(mEՓWscf姪_.Ł8Kt3V Sl$~,2;>~Cb* dYַ91+Uc83@ Øc81Mȕ&ș:{ I3]Nm_»G櫠6"j z!;AZzѠk/ok/': "6eQ=Q+㱵_ 0ث1ܯɡAf zC2t{1"2WQI') !ѻ ɯ$b܅)!lS`)zuB~}OyoGtbJ*F PI7bthݯa>m@+JeyX;.܅<7[ڎ'4jEݣ58/@06u]ʶ<-KCDN^R&‹-L?L#Wg0ᄀ2SՕ+]]BynzCK_=׃Hj,<%w=x&3`g-p)yWV1zCSӍ2|S4=i榟maHW<9q>u8"b$BJtHv.,z`_+1پٔ-9f6J~]Vɍy8~6 O-FHSj\w)aiiIwl% >gΗp=BCݦtl)O?]=JCG|Bsy:gW\>¿<-ngR#G@G6"j^DOh^7jpЙ#X:UxwV/h)rUKX]!0V˯ͯ(*3fDVs֯('vCJ52y&N8sSEnxR}m/r1Lya M<;yzv[>~:>;y:6v[1OŬ1Qaen.GVM_?VdmMƊF3LoH0ķYīBar :^ {m[MC?ܲ.ě+/ b5LKWP~Rwу\Лm{  C2./ZKOv<ϓ_,D HGyhEy:diOՅ@cfEВxj/Pt6sqPt M@/[m!P@hQV{KhR=Mi{ӻMPN:|GfDz|e3*sD`ԣjLg@mqazV B5j<[\ ;&<ɡI\R9C(g300H'ތyZގB -n*2-p;Pm'|P-1z}_2IXOkFE\\[E>*i& K)zQx}q}Z9=ƣ֝+yn8Q,Uُ{\_'.s61G)u1E~0l/"YP=`Y`aw~hawG*F|ZKΩ kDW&![/̥/A_)d-)\I udK옧~L$Ѿ=]!4^"lx-cOFGiYM34jؿCt0q~bo0mj3k dO14{T sʹG4EQ@qʈ6&%|ڶ~FhN1MV4; Z?v'ⲔͲHцC&chOHY}tdhDaoZFEP >R^(7d^Z,&9|D̡{:X;  s-3>?x#l]\=U"L˳),xٍ@: lv#Fi::종u.MW#Q3)=V[\rE +W8kkqK `5q6 (DR<ئ@&CloY^yj!ok>RSf!BcW)s7ßA&kn'҈I*z6̼6ή-f' &EJ&Mx-$ ]e.]^--L@79@i$j$0%( SQv. UĪ1Z {|&9~ ϼ!.:[[>9Jǀ eIHIS y9_J'<^\6CHKsaqŏMYW\I#"zv 3 7?O%ÏO zw㐺DHױrfFe<[c՘Mjћk'O_ 4RKHLJU N]thc>c^ y14({ʦD]$s?ԲzO.,>AHF:{tq~#˜<4#8DRIz0 RJ6Jǣ/ TpaU^w U~4`yY)2$WqLL4oV0'݌0 OByP&Owf ]Kd`gV}]7! NHR$9P̩ WTmagHHqe9NOGci݆:_o|SBdC&?Kڴ/4 g|嶴kn- ٛo}r.mt8qSiXlWkPV2̛n&c on W3f(vx#d4m틗k 6v#z=-#Xwvv~h lks4yNۧy >l_tS2L(~ޤ:./O67s@QMcu;;zԺ;_7\~(H tRǩ}uTM>ڟ5`71C]鲠8w΁H*(g5;j ntcML+G%G9vui|([*xCosɏt$U*HN4i*f-ɠ/UvQr$RnQ+-)౦K'գϽe֡+Y:6N,QЫv3U>Ѕkl hMRWN=71\I&Zh&sxȬlqaN^qE,-z)g_cܹn#H)$KRH@8WshrSrwAoh.*Epx$كk磡VHVvu>R*QCX^JY< ?34,8%KDYlc p(m.Rg6z>~$imw#Js`Qpn1V$ԛelg6!2P)xŜF r8Kb["Ǻ-#bV~C}igU t'CL6&_?{Nuxڳ6f-bL iqyU}NI+u?)N6GCI7GUV\] ݚg.!t|3 ,~K˙Z_#f8.*@lx(C '_.l˭x]IŪU:B˸V2iY=a^ ֌ @hnot wD[⚂*6ReXĝ%ŘRÝpu idZwG 8s+Tp5h̼M"9ll)Se ;00̱M]-3/N^qaI#6v @;/I>-:G^q\76pCG⶿.lYL~Dv!FH Kbxڵ! Q:$5]~[}nԚU>"rY#KP4RK۵Ҷ}!CLH0lÃdh;{tjGKF'mΚ 5Nm%Í$OKx=3y놰8V`l`_h .϶ї`V0_>* OsR E$ɺРmuCiEޑkMs"C AJ 2M +p4ΘG O6aÎC_'uruEޏW.|e6!r(r:|k*I{tly9t ք(|P;&"xMAo44#Ԯ;]J kk;9^˜+gnWNt@C-Q _<8 覬}^ Ȫ CB68VvKEjN-E9eghvٞ*qL|FڽjH e݇HOOv紐(پX=jxX{sH;αXopI[aSid!KbFJEr{FdJEozݻVq/:j6va*=02@VGYR6js_T2~nL}'s#8w 9`_)4tbA ϟکXP͗@+a٭r$_ĠeLuIPQDf Vq 5[I2Fw(\̆h0, 0ܗ%ޠX0'a?~ׁ-_cBx$WX|6FSx ^"Z:ޠM>|pl6\(!"hbWyM(pwh:+ lx2?ڴ#|#jنo=*u(.H%$@IBc̫BGl=ٜ~O%G$Z |4}eHc%NxK1ux) T 7F ȯyNϛߌ'^a:],ZI yww> &30UClo7,=z8}^f)KFx1:;iPUʞr\(őba<B!tH*8VXx0372ZCKv]x;["jwK: 1Jj&oe %L L5:|sUܒ~eb?V3kW @`TE9de71ˇDWO{l*6RջٓI*֡<jJđ_H\\HJFh "5j[a故 7#ui9%j֮<^*TWHyN]Ot@FF[dΖ[aa~Gf >ܮhi҄Ejs6jPn+O,׈cƭ~.HD-k8#-vٱQ@|o]ߎ/MWʝ~3JsBӣzR޹w@s*$;?Ӟ"ᦞF)PG[EMbrYޭ ߅!$^Jn^.3;`1|3{|nF[$Oٝ|@{#QqX"|bDR:.)aZ`i@g׊Q]*+A9 r-Ŋ>DAE$5 qʌveet#U M :NP$DԚ}2OeYEJNڐq#yZŪLbW|)܁NjBD#Һ>JT +?J/mfd@W:r%-ޣV{J)tYX-O #lU7R{O<>ADkQ!,=|_tN(YYTF~[r% ѫS"r+ 'Er| g0 J, R #ݏh0 {kv#B ,8ۣ{|H(>ů!&WIٝ gJ2F[gdfj-?$th1A6:کCTjŽ_jt~D~Sq|dY7sbhGl5PApO46Nn/y{{׫_LILx&,uS"[!!l)ۋ1tBODy+%܍] 0c F{İRpE_ 6}xWr7}-LWٮԒ֌B٬H I3#o&q>` ӧO70/_46&J7bi#- / /ia zwteM,f" :rH[!+d&4fAFKI5LJ mҹU(ѽlPfʹEܫ.M$t`e9b?lS~DGFh֛O{vxelsDj9S.dX{iU̬XȤLӥC+Q 4"UZ5RI*EaXp t6ӡ P*"!3u?>\ҊI:Wԉ$&ː&99cÜ@T!8@HGk/9d0e2K&^Qn6׿m!)&FXs`"Х"H,YT 0񈺗7t ӹL-b+$gNWc\s?A,t]C:4.]u;ӰW'J&=d{J|2*J6ߠ (F!ŽD $(~\H#یvHM QUI=U^D$]E"@uC~ݬ&IK u>W X,.2HЈ$ B=b\,ɮ!##3hZIL̽B;{ : S3f`3 ՕP{efo/.E=5Ep=]n2ƕwDFfI܍7U=F)38wUnD5|̭PNj;W*p?WBH9Y+s'_Y _T>kno.v'$ÈY>. ŵvn_چ}itkitdW G:4-;p=|.{R5 |aghloBWl0A$R^ҚuP<n_`sdUNh ?>Mzko$ Z^ bAsɞ,gp7w,5堛|_{nDR|kڻ.wG%*fN/]Ks^1<yK(vOJ=ς]tɣq Ǝ$o]ʳ0 7YDg[vQj0+^w/Ԭtp:gvfe'GKT *τ6ոt  3UD%,LN+3p'PYo>'9E>5b" 큯#R 4Nڍ #qW,O6]Ų\1_Rx-Re6:0 K~'BuRfLo¢v$ xd^ vkx)3@ S;تwJHS|mе#|V<>+|#E]x=}۶KaEJfgmZvl%؞OՏ(5E$˴ @|n$p8?~YEa;K'DkX}\},̓[ '׹m]ۑ32xhX0߸M_pvv2QVvtz!/vj-F (XޅlQClMK5X,(Ʒv슻`%ƶ/BgFq^bGI';cLP'wK`k8[ĵ<]yMF⧓ᛳCqxt.jO#sK\h8/@×'oO?/?WgP^ O޿=/IsņўҔxNv(gf7s=vO@ 2"tDw;~7mA~A:MqMbh9ܳ0x/(FwBtZ[ϻ/x?8`n8';*vb@.J >ᇡ~ % #6?c;wvW P=;$F"V *٥ǙU<б'_0M\ |^:XF8huw#.e9#cl}!מ31Kc,OF4#Vm\hx]h <d|ǥ1h'F/rb) K D1jSTSwS wq'jN?߈}auxّg`Cx.Gv[?ZW(QE]ckݨ|b`H Ԡ:*TnXA}ĤDp3/}E:Q?I` 3+F]s Lcô:(;Ms<^S:GgЙ[.N·w{ioh ^]*`Vh5>ɮkacOGcV|[%e̘& 󟒌drTn},C4Q4^VP4~܊ΎW*1%Uc e|vc\O ()}Vr:D#B?= % !]!jFvD q0jaP6[-tAn9=o@!;zUswUXM 7΍T`l"wPri ט- x"nI@b$d-!(U耄G14+RPT7\]6.hvAđ0Hpi)A$4RB5cF0G_ѧcG 1` _S,Ћ]жn?,A* Gz-cU,5dasDaaaߝ9 Rzj /V\n9 ,H5{YoY{sie^X[sƝ'8ʵ5\8xX+5#(lLl(+i@Z`݀\zr( ‰% Q5IYS Ja/*_ C 5o+vܺL\!4"Rפ#cԍg~7wp!$`i:we%Rb'}-oW^?9n4oV=9MI3fES5r9U0K BkhwWa{D$C̳):\FjFh 6  !FY(X,e OaO87ZDž6Of1PCTF[ˡ{va5}IHЮ3`:`Bm++ЪPsZ%%9r~c ^L#J[+MEhNc@i,_:8JknڲvqT Vg)34Y:0c!S[E_>/;W:Led5Wؾlw:3U'aNm נj(BTr4s$TRJ`RZK9@rmmf5V1. 9ϩ@S^jjdfƚJ9!a m}4"`I <ݥ3bK~F oxb7(B|]rrڤRT;bG1\CH(HP)7#teXYNZ*Ռ,VvW2nI|$2݂K#)]}K[AS}_q62-[ƻ 2ʷV⚌CvGmW9k.~%,9A# R`L(e֦ 76ixzO?vϚ dw;a3ni RlEAY%-J\`e.mS tR>9(я,JEiɬ]¶3Gw^[?`t5 ʿ[tDu XFl^'3 0W*__8msf!/W\fjn 0R.BOg \nآMݒ)dXцB6VډV92SexCj5aÑNw#8LʜeXӚ!OKgh+nڣpsp2.n_„aMIO.Fid2?5 ?w*}x|ny] 2"2ū§Y4h3*Il6TWs؟^=NiCNu*¥;;A庑@0DfnڒBu++li[r@aK@6 ̇I15=J疛pw%"mg :7 "Ǜa(5r Ecf3*SvA ) uTFDGGxr `&7]`f ;Lyř2YX VhQoj%= u.u:kQIї #fWeVzf$1E2${yNA`w+5rn=`|+}(TS@iÚˀzҳAP=,Ȋ,Gox$$t-48u YBZ ;dSCYds5G[!kހGygK?P=1`ŚRQTrC v?<2ޟ|طC{-qtv:-?ha8VBs5E;DQk.gݷ3׳k30"{uS[N| VdڸS4ݺxomuOp$g/{^ \V5,yϝYeo7`ds ]Pkٓl~cՀb\RL|,AnG9ARuŝ)e:jC&TP" PY(X$ 28ȅ,߃CET4,Đ<|M׈qS92QPPwӱFu-&Pt`aof PىZO*Q/Jд)x s-6id_]k_o[;\<.IHNJg$0 C/弜fV2`hWIC:Xzz<3 C(݀RAO̘<(dt0-EٲLS*rSc_tc? ߦhiㆽ7#07RYר>`N4n?-0yxS4!~'}c0hٕ٩8kZjsE3b2Ưau 4jTz=SQ+M׭Ls7r+bIҞ՗Oq7HP3{i,:u 'o9la(?pM;H2Uާ%iTN>I&kJJǕoA9#fPг4(]-po GZTd(K, QsVV"OA`>aW>:w G`H9';;5R暢BF Xtu jnh ns/˭`6' }"8a$9E,Od&M)Ԥsb_={Ə񮽈Y@pd;p1AҤIG0H@$Hca qDKM~Rs\ے+pWcJs7po)t^Tm;K׊ҿLT$bQWHh-,쩢gIjkSfgYʰN>_ZV.d$"H'#߁f7*c(L"lrQ̀̔ ˔ɥ);LT#'A{:.ZHO̧lB#U0F ӹ8]e]s;4HRH6EΓS 3̣<ئB6}sLV˷cMn4m, ĉc~a\lQIjl 6(Tx /bōpȨ`f2jiM%)Wz%&=W\WV9A{HvtYm:p*WϨ!\\xH m8"Mơ=ϟ1w{Q#5wn1~{݃#$/__BnV߼YpYxRlUtQoE[!$j lW4&B_$篎}*r,> 6oZC{ B"SP-ʢ@h7UnXF[tvERd ݊zϐt?O^qO". 'h2qy;f21xثw稲2[S|V,v(~ׯloh2UrmE19 Hj]j1[ An=MJ+,(k+7Lӽr,1A x[M@M>Lxиd;ΖF(qna} uKZC9ӂN[Xd2-3(!v+RL( Z~7DZwMmQg7q}@wﰁ}ąt20B) k9xS0>Ox&~)A3`Ā&%+f =!LQ|Xu.N_K(`na*ALoFahTQ殰-r-dw;/V~;)S?u6M;~k`bXtIAgB\}U[ oWjl)&|+v>NP7`?;t^5HWm 4ObQ׆o\Uu?=%'LWz%Wo@›&F74=uOi+ɟH{nѲyg_,Q_~o8MoRG}>;_:hO?7SUGUm+U*u=% `?<oEQe5ŋyĝbd):ݎ|]EZ?|o~ӝ~ug R1P.9ɝSlDZ @y$3)=x340031Qrutue𮽰^Xns2BT$3t)q]cʳֻ+3h*((OMap~{oh66՘*gW1gbw%V3z7s7\xmTn0=_1-lq> pw$.z&G+TIʊzwHYv0 q4|r+t3| ex_\rbZନOoM<ПCV[#j2]Bd jX:Cwo!+ t$?;$6h<(k"'JTsζZB9(ZcEɍm wpM[|"R{0J`6omvQ*-"XU px:?`OW[CIb:Zt Q١o5"/g]IOd(bJ"c ֎[.`Dǫg.tmuĄ.VTyhY8~X] s_5em%5bƜ2KeIHbh뛀ڠ;oT`2n}Pڊ>e :@'-i7adD$_vkHУe4qJ(nHy:d,+S1?|cygiv /7?;A3C=IvXGV3A b`[xX{sH>Er#Lv/]-qSo+us 4ZȄJg$Qf2s Oe~+GZ4hGp#0o%ל0@`2=-XDkfǭfBkTR`AgI"iXT`2[X5R~M0YT$03y'tퟂKhvV0SשJX 8y=l%4$Zl s"Z-̆[AbHy$I<3GVXl$\0+k ja~]/<)0R^<֜IhEy.xȎin)m O5>CВlJ?gނddn݇BlW*AV())L6$߆w3>oɤ?}!0o&./йf>8;d>/p6)]Ld6<|ߟr2ZSNq'6dg fÜp w %.dx &U"yhbeIQ_ (܄a+qDX;Hċ&Qy9999>y~ p9c޸zu齃/F.3ZB1ZoNpMpX'<  |G@ d'(bQQqZh3GwͤT_ZjTH~ֽMj |6 Fo=kVKF5/\T; W Z9ޥd- yyFrH+DD\kJcIJ2Ϫ[v }A77;w( ѻ>:+5{ ߴ&BXCTYSXYapX" V(3~=;t}-3ڊ(֣H]bgRsGUq +$\cfs#BaZvWI(Ǫv4*dN2c Fkj%{\6U@U/PyzݿT\ W߃Sy~=J>Ͽ\3lu>M[n`Yi|CGw]7DfWA*fI ߲IA GX*u?Ӫ|`^BiG GeL7=u:3DBt=ݩg=џ4}W ,U|Ifⴈv4‹9h7C&eox)7"Wp8{aV+E_E/"'AV>3)5xBqj'+ز0T}wt'ݫbw9UAC3Z`\GWG`Q|xT 9#*__*RŚwU˜ i"Wl;M*DHY\#2;x340031Qs fi^5W~o^g!sTe@*jmwLP[WӥKA"3u᪙\~cJ/aV-@cMMJA/-wku?8zLj$уKtR2Szir /TJ(7԰&!u ܋[yؑ4TF Į]^h:=(ʏ1K{5iJ3&P$!y.;r'e$|ޤRxx]N0EK rؔXBpDSǍ Y̽9 iow%e=I<l#]CI,.P N*5 AS T* xtSR0ƥNɬ~?iS<jd#Ŵ[+սJUb/."s3F<:vb4'rڲ4ޕm|!mxVێ8 }Wy Pvgl dLgLPl:F7_3h$)vHfZ,%n4s>B{@ *2`R >J[kT΃2k?`QU' srep{PAk[Jv{uUc ]ENVc7mW);Yˣtcapz[ґ̟|(ʭ6*;.I1vZ8l=;:;ErkHQwH?&r m4*ӗGJCE8쀘6X-)ɱ-L$RN{9A>Q"r۞&SC0Lloj$_:&xUKKA+hDasP%;3:0^oU|EOD=c:3ydibY>UQR -dKIGXy)0-7#5|BRؙ|AF]8'HD\8VTUNmkP3(© @<Cg of(N}VpXM]]h7vvx)]ߡ7Eubx A @ }NaBCnuB:NJ&%JxH>筗\hAb.slV5p.p(;u×B% x\{sHr?ŔU6u,KZm*f 9xH^._(#_,=3 @RīTyIb0ǯP=o?\_LBDDN~X$faVE ~dbo$g/(J Vzހ <]TY%a%YTǢrQlK6"eH9Fb.SEW,=;)E*y?mU7<ݥOtOZ1aW"Dz \odOj+&Y]}`Ǟ] NH!x>_V1{N Ա- dWV,.&H#Vވ.i5Gwǐd n|/k)"fGmj׮\ObRX%`tW?{*77vckJ%z^u|P=oAߵ gEoE"`pđTXY^1 Y3}?k=YU˔݄Yʾ^dTanyӬu%ٽ@)19fՃ Ŗw>1;Q"9CJtE$R!|mp[4%:j)Dg}`7Y!?M-H,RB XӽRy:"},+71uM4ThReͲ]/BK]"E/Pߊ\cW7׽+4$Haje.btL!#5&P_[>wCoݽz (TF`q d簓0c>xV4\,*ϻ%uGE'C>)F.\#ɫٰg|O;1ai4m?CVO?*)@F !b-,`N S<҄W{TZgM)3sY* UaQ$#g;[xKov|~9J, t|mu==:VW`h˗9u$h+< ْ&3~[{2uȚȦf:N`E]%C$L<<Nxkk hyMܠXa=nbG8:E]<d=>E'a+ A([Ti1P* qx3j-YqgƇ p`Rl$8쯠5m~& XaѤqDC~+G: ǖตHT@yKȍ[ kԟ)AUz]2nu?xYĪS<ř >yH`fhXsws=7UY/.q|7kJa\Gx|lƓF=Kffzn#T+TDsʍv7;E6U:7UONp *ߠYŶ12Mr%qO!$ 8W\H'L^jw)>vdft~0&Qٸ~ۼT\9e"4nLuC \sazE}MX>m]lL;tk_8=ƵGگk"w<$C)D`@QOk "&#SbaW9$McX* Rbѥ^@I5(RM6!/gƐYNFdGѣyE@~eUm0<~NQq>ᖲ1eNNKBYC&"ic};p7z?ѭm2?:o˯~Y*1'jcMd3Q*gՔ-/ROGj^u[h9` 9)^NaPצIt:jlyLgEPߋ:հt#~D|1xaj%(䍺 V?OW:GZNj7 /`JGg*jqsԙu=WJyB칉m$;op #"#N\%B ƝPؓBmo9`qZ Nf %-8<:~Ǭ?^6iצM5nEz#MygMo("م7C}( W˝7?gaLJm42DNHU2Lƕ\NJt^1-S٠5f2uAA_aO#^JuGA0T8x[G/JN\HZh-sep@,柬Y: DM;PbGk,z(Z#wmm8;ˌ2R,h63^}smG?VyVBuЅC$18vJh?/vB wx-+|U :BӨSEXO?B]뼼[aT9&A$mHjD[{Q@`i$薖@b98očI_1 gd,!BGJ)8eCƩ(`թ }"0~^xA3GRv>!Mus̸L2^0EYb^&!QiEbpݝ\HYP 8!F]@[\6_SSA@ 'R3&׎IVgDZ8%|AU-*lN]JTY%"=T9hM#  LuijѕXHIxECL% )39bP]֥-dMe1\5Sb-io TE\T]_,BmSxP5-(uo]b]bq89=a"f֊%twuS 9gZ} ܖmF)u2~!U\YQ5_\Κ8J w {:a V"$l%+su_=@2qJV[Sh^m8 I1tq^\и3 ]Wf)wZwy_Ri2WjBAܡJsVW57 y\Bk4d">;q]:e H$pڏ5S`8sFc[>h(Gch`& `]܂ 좜/ vנfC>sКe ,EUrxXs8x^CB(xىJE]qosd_"!'QՑ2&|lH\0%u\Hf^8ZZۡjoii$v[JGemTHlÁazgÃodG kb4>@]tDvrW_C 1p&cpSHp'8R萱~"ά Yk }>ϲP!q-v^5˹$ jXjyb/T P%8qo^/*OJbd6 SOʪ_,{-evۂiNdz&)&Qx"3=Ro#pdϟ&guG<07LZS3j-\>xPE*IrP^.UQ:7uјP ja LERo2hT=+5"9UׂW=hrOY8B81}P :Zk7z{Zc2GX+"Tx9Yz4R %ʱ}\9@̛isІl_tK!m_R)3S,o& *K.U2xurKw2i@cr1"T1,]z jeKTa+CY鷣ꄗT_/)a1ga+-Xxj K1"UP(vw6"+/zC|1DKcB w`gx?wvGRSžKZsM98:̒: zHoƆE b Ck{ͨSLEZ`R͍&"r yzYM/j xx %uH?e1ͧɗ/WoGzN+Pp-n8g[~ 8 +jyM85B˛\"Koޢ\Kj4m?U/?#qfksiLS`-=C{S좮2!yVD.*%}a .a\+pljy 3zמR+%LRk&שGCF<#wi,="0<95Q+o0:,͊F@n ݩ(dkZ{ԫ@nnLj"SG^|UzIpj"%H''Hx瑸džl_>!TA&Cx{G9vS70fXӋpZQR{댟.F}:<t|vRcokAqF;tAB"_m 24?Ofs?+-!iE 7KA[{SQU:Dԋ,J=Bo1/<4uZ=2~g<Cwwmw1 jrS<ʬ,AO@~Ya-K͋*/.\A6\nBBWH¹6NǎeoQӗ{8&]'9b;LC*E{D\7N{v3l?~SX_1{rph3@&Ӡ_0s8_AQa[oCRM4jԨSUYHB%®@`(OŌ6cwjaeD51!%YڡMtU&(BCɲ^|0c:tlo?mTCAɏ,=!ZOVk,?jQ჎QmT(6k8sEPBFE/ŪܾB<Bb dޥe53/?G }#lbr m urEiT|jVRJmKmӥ&^oap!Fa/ 22xbF< C=#=]E&gldb5225´5 2x~DOx}TQk@~_1.Ixت>d; Kow6^[)2}|3&  Skж#n"H<8juɳ|1JK-'5i_P9[\aަ5HEcW<-ߞ9YD LrGShSq1ޔ35t뭨nuUr;][+7r^ݚT|!^V~J~ŕ r3Ɣ^؟?[n2i!JDItaٛYyz'+D ^JHwu1 ]whzSܢ/zGrTXJk)4FݓG'k$ZL&Rϴ87;SEJǰb{H@}q9Wo{2Ռ{YEY0#P;쒂R(A#(  b!&:9yF 4p_l :=A v!N )/a@[ʒ B5q{ F{1XE #q )4< w!J^l&f5aȳ" ;xsB9:;3.ԂT+b+}0ug ܁daAmއ2[Ꚓ)# )!Ey#}y}X Z<(񂎺R.nqHTy@9Q;ܮC~_ޒAi~7_=vg:I`C(^/wQr/ AA]5bkF}3~VZ&3(Ŗei0UGG1aAiCk͇_[}>|86 Ly&6u`8oOAUk;밲~z#isnӮt9̓ƚЖBH"܆=/ɩܼٞ/yJ=Q8\{He[wr3U$?lܓ nᆺR4L~V5߱ f[BfJ|9JQ:K+%|/wbM$| Yv31OkSf 3?P%/JR,iY*oo>\1#49PTYki8*Qߕ 9 ix;'yDrJ-+}ҢԴTb<̜TkRF.Gm&BEqF~yQ2íO_޽k<޵b>ݞ))5xuߋ@ǟηB/$1D)(DZݝK]&{gi|3?$N E%g^ '0NO>+с2 J|+]Jni¯͔m>7˘r@@SU>CuxbO}q)gW5UעnP=E!+wPLQeCHYX!p Č(ʞkV>ǼE~sB:]a: ]?W7sSIW 癟zksE$;v[mnS<7ǣ햶[ h|\m<ymr8XwY'Q!CjssY`d½\PQϜ+ƒԌɚnwwϱQ A l>sW[3xHJpaJfB#+2exێ0ɗ4m*@RAPѾ8%ǶljߝR y7cOւAdPpbU`N WR6Y}m92G SfT5SX3 4}n:W)ڀuCBmWҢ f\M}acPAHA:*OꎢJN:>i2 Ӑ&,]4 u8x8wWrYzǞY%ҨF[PT: NsD(  TF7ϧ2e+ 2Tqf Of5.Υ &G( /?r փQ%AMHG@kC؎=kFtrNw٬/ě|kԡńC57ox>> S[Rzjr&pr&M4R/yMuaՇv6.fbgC'=yhm` C? p{8xeRn0 +K{E:t-:ҪHDߏ8>>| #=N1d< oi.켇!Ŕ1 d࿔.Ӯim`TL[I@ >/"I<88b1h" > \hMޒL꣏<||d'ZRDf](ЗO w:nM- *áBׁ<|&N^#wvϋ8{v56yW?^CW (IOUޅ7F܌ۦY,5õ;ѢNMNzoٺ ^xkg0xw{Y r<C]NUe2ND \d棝y:9#'鼓=__̴x#KY\<;Cdх !Ш?e-+xmA0cCתJF" \9H^FQcfi7COb AE :-IpA*Z81R/Xֵ_"ғvo,X뱨".fCY b߃n ddg)  ϲKNO nڋ ZG"6Z`;8I)u-ngkҤV/|j@d\$?o$ߎFvnנjPӊE&)tzvo$NU9V=Fׁ9X~.ԡ8xq3*m"r۶h,4[S-VSGiq\>K>&kz6|erj͢ [{bHxκuWF"$Lkp xe] ߹L& 6Ǘv_&,AT k0ϻeU} 1ЎՆRɵ|1@Kxun EF8ߐ(ژ[ĄP@uqHssU4[Ң^Yud=7O/d"F6՞V kk tP ` ̔0/0x:J[̍7j-fR25^]͝t?ٞk>?q:UAIwbq;p boq^f %;z_MS5 _ܟx]M0FŸ}:Q3M 7cթxo!MjMvFN:;j+9Ip68 DLTMQzOd!_ #!ޙA(MY(O3:C(PzzTIH~i)t9"M>i-(P>U?QGq/)S~_ҽD4{2Cp@*y4$c $X$=_S)&¹ҠG(N5+AX58eZl nH! ;?YL2dJ0M ņy;/)MTIPhx#Be^ UUR"imHq2 s/rޟr2,t6`j[~J_ˋji>ш ewlW`ʔsq * 8dwoFW'GeU}N(!MVPctf ag(t$>QKOOl瀆qt?0,qN\J6Vg 2$'XQxD?FxU CCcuwuk448f,?D-kvpHa‡j ?#5xNWB@0я V9xo!!8&Ӝ4B$J &qK-v3x tp88M j!=60 rmd%P vؾb 븝l`>TfQeEu2[ٖE-D؎*/HX Oc?F?*R|!l-DS` /|'w8qH. bK3FQb-?\_qmcLBBEAllF 9]qIZ5?~#oܑOwzɤ+#?=z=U335C^ĵĄ,sK9Z;_YQrܶ؂҇r"'^4Cp8>'Q$`:1~ɩ×ݏ+~Kz \Fݍ"Sw3=!4c4elwFJ:p=Z{6-# iF- q0 cN(WZ+-o *{sYbҐy y'.նa).$T!=vApdhIi洸>ܲmUSsD?/iW KOoqR8sh$*#Eʖl4 x_6$;:r{Ml[n2vj[F%}[Zei^rXdfuvQG3][n"64r yM^@{H?f&+ly${`@+*-<-+{o9: WZocU[zV8uVQ\}Rq>8Xʲ dM/shiz8h^8zi%fsLֹe+3P¿t.M9F]ɪ׊'t{yU;5QSBB@ݱmt8Pf~"MOڠMYRsl?Uyl`鬐_U:V\vqw3?ڜ:Q@?p1tOjiA(|GKi^vp3( q]U晣՚%iGRJcd9R8 [ZdtݩqX2Hsw~q3[xyܺ<ܺG!,PܱDܒkB3pX15fYp"#vv/m8mfU|(yw( sim"J-ϥ1>\ܵ@:lXtDiӮ8F'pys~L͑ }eǹvi2 q3AnFZ20VTVI_0N;Ttl1@ֿx_EV'iFaМT˱-_5&r<.2lciH11yvЋrG].opuTmϲ̒x),ZWvjTR+:P6 m7z;MZW}9G646@iuIA8H v=ZG ܸ!M̪#CNǕf90Kn'k'7Ef_uiړ1b2@e]t3bUI>h^R:`ڸT,[lsʴaCFSwSۈ馶K6-qR͙m7ok C,7Lln&~& ` kαsLHi2&wsduݸj&aV$okU5\6` djVu~ d&Q({NO&J:ZLꑗ˅`r{~![:>ɖXRM6̼\te:/eyum=kXNyK2[T mB!-n8Ӆr}m“ {Tz6!:QiZ>= VD9~y?{cd l*)cyꪰO&cq_ۊBqlw?͚xm FGY"<?UedQ Wsԣ%5[zpݨ9@VbOq?\ =#)1[ǫ>)_8L,UgqlR$)Zãl3V;,o(qx/-.O+/W d&'g"I\% `Q2z=6!txUmo0[:E:4^@L $_klwvҖI 7'{Kog8rhʸEcKpƴPp)l\gL☂Ϙ)b&0h2=O&dDgqJ1!ȬP\ɹ(`,AbR楂$'`(keNaw1 v-\0+&|9jJ) :HHjf̊Er(:rPnio&}|5Bɖ65 Y8riwoFAC@~mAj) h|FwAx5V΢pkڗ캼&\!Z[F?E>c+N%$H\(ne$CWە+=*=paجB*ͻZ L+1:C<ȕ,q3Ei(|aP-ss>9-1|.ȇ\h̭w]Lj%QRԉП xjamSI%,͋Uq5e$O#[ ƥPYgۇ"Zk+f !NRuV`ͭ~tBZxo/0aZ6d%u򒦂lbas#wn*Gc28x;59Kn~nd3"VE% JeE9@!;3)вxPJ0||Ř hZ'" rk6pMJǛk>&'^,a &+QTۑliv\IO%U(:iy~ӭ5=9%+͝^qaZ6TAw|]Dl-RTJUkLoCF#PyrWHUiOHAUQϦϔuԃ}"i R$ۡphgj\Za`m1 YeHԄא;E^UnG&W:G# Lb'ίwG:pu꓿s< ,|_~W[CfGnz6ýFJוջy@?QW6!xeJ0؜Ń1+ k,l3mmRVYT"}-.Afw}Z+G^q!΢Ie*D.J?sq#掘iW_j9Cv m 2'J@atװ_>O.>cVjx*fu&j? ̴, 8D'婓N_h?5BZbAí}FLJk𙛰p1 B+dԝ(V]S.pA'%zMuru%3B~rrHCxqiB(+YũEYMb4QVNMWPRHIML/(J-ʵRP1TR*Uvqup p R ='x340031Q00-NM.-,MˬH-KLKc8BYOjpU7P7'?==3/]$_ȃhtyUՇߖZm\-=hRQ@wuaMus SuSRz3sJ5hG4L䢿'`\] v?B2SmS MM'.xfa `sS`T>Ż>o:x{W3;.37@8G1$/PDnʚ d#CGT*%@t숩Z^SP ˸EbсbK,=kĥ>ڣUOqnRNfq ^kծ9js}eނj+N-L-fhw{ >]GxD@77?O7#(%5/5E743'E7-'1X/%3-!T"se׷E:^>1H( DhDfI~nfz^~Qjnr~nnb^nNf^n~AIf~Ը%=O^)Rǫ-žUE^[o>YM%~N|(6q5 ݔb]%sJvb%.Ԣbvv1' XFhGMxQ]o@|~*e>@U*$) ҏ$8a:j_5*Rvf=;S&edd(t!@. aÕ'B2 3RrDo4vLsHfѰ>"H90L0@h?v'D]) qC 'wpODžWډ0PP:R"9 Iڊ;"P!y}6D\yh2Xhv7rK4_Q_POc7jƺ}FTL_ PRfw|'}re0ۋ `1@uS"n.׭7UӬߛ\MN'8 譼q{vpsC}E ;'wx)_J7SdJ?>#g䞿}U¡=xoo0_OqZ'qH5cS iA5kzZcGbIS(sO|(%PH,6.i"C6hM#d+Rc׮fxC+,k4j>hSs~RiPu oCb&uT%օnpXBe9^)RJS%25BRgMGDPZ^/j7AUz/|s=xݘQs6ǟϟbI`l$ܵשҾtFDrNwqІ%Y`jNkΘ$5.j H*S=A*2 ExZ̬36ϛkI1Sv\Bκ=}Ԟz.ΨF<ˊ(C_Nӊt V!ill۵]k]Y$DmQeYV^3 I6qBS[=u1X `p@wr$\A.L2;p+9XL-;Qdv}y"06!BfjH~C^BhZK|]PM}]UkC6o6!&B~I_oV3ooC!8c *Cȸi͘y>gDRCna ^+t-/&MpXcELOkDH{6کe~ˠlz=z:~7A͙ev6qYlqIbQSųG r $*eGW6c8iq`̦Hq,;7'"ay<y0h[ XD91"gG-"u3(kY OnLk jn6FbtnJݗJ]۪,cTwTOJUJjPr@ `Avv?8 /f@g9!;;NPΎ'@Jp mEil8R9z:j &~]bxTn8}biRKub]Hl#JV"JrvEWasx33 ~(.=;B8w0ٝ %=l #.,W7%mex W@Рra9X ٔ),!a&RhqtZ $f5&VZ4=IM^JAcəgtV˛E!EXb" GD/P^Rf(A7k=g(+FKn+z* N;/]SC !ù g۽1> 1կ3P*BB~-eI)֏XDbk5bVٶ>[1O^jfGAc\m{v8sZGw>ZǪ\/ǻU&m9t}+W+I fjZaϡowX>ZY-}YQlTۣ矟nW?faSoj +}7ifxPw©UFcjN6 xVko6\ hڒ%m#&y v 0e1DiwHɱnfذ{yxy9q)Q! MX{"/3N9+JHE/e< [fʤRM)!BEEr9R—ju RL憉aJɪ ~x="Iȫ% z?FQ&xa í˿y<@ B)'Al^4`o0|g 8o&o'a -` 7o7C]LO^{T(ik҆JX WC^̆SYe1-9,uH|v8zCc="]-5,ZiR rv_sǭW{C34 Th)/8I -l۽]2Y:*pŋOZ/H{B[*Sڔ8m3fvӲ%!Hqu2(LPa%VAj% -yZ" 9wD< y6f@re6NKٺ%; $q]l]=]H$"zp^|W}|KU1H88@Ͳ\ЭG}|GyG S"nkhnmekZ}vil1zv3xy*sQܪF^0̢mieӊ833PM&Qa=:tD Yd-op _Atߒ`։fע,{bX?kft UfF#'su7bOPvEi+sK33m d^@Gn$K;'%nЪR9Avܬ0ySx˘lF/++dnzu7|e \\5?tuԚ ga $rZ@ bHG=ܝXqu3AosV8eO}lku4AUN7D=7cGx͓N@O1 r^5E;NV8U>{w!(DZ?4>&0E[:U  -ZOϰK ܹw+mJr#5\I|UIbn"p!JY~ 6nVεeYM!S.sWhoWՙ@es¥8+Fb'K}{p39&B5Pou<-R75킻;cCC/sVa^HXN$94j4AQgiQhtN&ry>M7K ];!tu+2}QX 5P03TH7&v+Tq|yhGM;!VQd@ _Cc˷^\_z] JŒcѾ}7 lBcC;e,'yAHqmD[ SL }O wxƅMrzZW8݄ʷ8ߣat~஖am b} H-X4?ZOxSn0<_H-YRu '@M4H@Ry\]RS;5PC%jvwfv|aNXze#:(hȷSaɭ2Ei }d~!qN>n%9o瓉3H+L5\ܡ|,;-.$z#Eq~R̲QeM,;>dݳC&UYBٯ\Ii{"|%IMe$\'glq1-3=QFh4uIOCy~?/N9=? F!%J8k+輴T(>1)KiTI&r6z{֮ tsh5yk-E on)]j=/] B12~E[dR0Lv}\x193{e:?fhG;޸talTcnU~MjgO ~Dz̩~\/ HECV:RW6Axn@*Jd|N%R!wHv(OcbCN*2uiB %3K40U4BIa$zһ`6ʂ`RkW $Jrj;S:sJ)X$<*'[-S40~R/Ls Fպ@)їhYudZb21o3QԪ>at/ۊ3axQ%r^H h݀^ˏ?tIs$KҬq zQ4 iuݻoU,~/MG T9x`0MRX2OX9 yp3!kԟQw5kTH&\ʤ6*-뛋gWWp|f nfߔDXk6&BLjJtOM|GLncn俠<0G7a87xxoj.؝񯸟}xx*jx}F]w|h˹Q5$g3\l^6)<[$Y(لܣh Ks}#.pZJS/AVTEp̰͹k{¦~675.-H,..HLNK4ScƴOk7sM8"Rl< ]6^ 0MG~ZIybQ*Yoxt=8czJ4(tٲSxh q,BP5%3~6W_>>lrt9:3rR1D \mSq|P9I9 V1 zUػ{qrݒ|̒TD]CJ*JNy3{X`Օ `MY9 i3ΛI[}^C5C񖫾V_,భh$;BArn!ú.9gIVz/xBM1vK?ᆭ͜ϳ{}q+nqxZrG}&Gd/f 4E[Gl2 FWO_;>dV_@Y?XDwWVVVɓY,Yz9=?3gkcԥ&Y,BifwymC~~~WV>#kcjlnn$!_Y̙zekc,l+TI‡s&_9,CSTsgl颔t"sTd@wtKw7}%[*loD㛪.}REÉٮ\qPx1^,3.gdl+2*$MS~X:n߮;yhjyuiVq&HW5-wra•wC߭)Jו;G$EQt|^˅jܛV|~K[mLan0f–v Uw2o؎z7؜͚2!e[em ,WC-"?N\:zb]Qհ5GKpCmS'X[UmSzKT&ɜn7y$XhN "Pm͢y;unr+\p%h \R-}ҲzS|f?ߘ/JPu"$DaQ@ '/$nsUx7LJzMDöE7*pL`hjXKi6>_,!&:8ASYWD58966ːht9|U̕ MwZBa/|e>NMrRM%74MI7NBz|%7kM` [ K=p oa}a"k@ˆ'p=Sk\pқ•#9qp k*X'$pk`,t(wat;Nh$Ssv[QlE^O%҃~u6v]\xv8L[KY$RTgʿGt>1A .;y81\]wf7CtjtCЄhŎU3>.B<>ms717,mV/0 Qn$fmI.o|JsHOf^N#@NP(0ϼOt sfY+-H*034dXJ2豾ʵ ytɪvW8&8j,jܺAN բ ksЕnP,_iUăL2Z$Z?Ft!gse.F˞lpt9I>r0buϚCK=ǚꍝ-f*_o>_;?kqUb }PXDF&T=M𒙒2TՔƂ6/غưW0TH16 QpqNF\٩~TeUMf>EbEA#QDʁ|$FM.0DqqC;n E^=HM/ȐA>y&0Y|Ӫ. ykQKx6"\+x-$ u][LߪGU4ӽLx+RdXJLcCMa17ʒP99v Q_CK}࠙FS< t, z W,;3:h9=69+&I+6!BJ*㖢"^lqM. %Uǝ.Gķ PS2T+9d:AFs TU| VD>O&(:,"6rϊaހjT1I$hs;©व7Α( x--"ҟ]ֵu@jaڬf\Y_\}t_IMi}=㧷=yn.*Mw+}okް?tV%)Tl馭gOa,aI2*Q{ #E2fy`'WsYY屍-cڝGqCKML\Q>&f]XU <;^c#YPE(szrj#KpE4zfaß&}$mn,_; e=ѣC'-eD\ 6ڧpUvmB<hx.G1ЉueK扛k RRH^bObCVǨ!%qSKb2~X*}m Ի'o{kw\ q8:7W?]RY4UmY7Q[l߄Y_ʚT\-GRYW=hlN?i}S5#^`m,H9{<=Cuʴb"7Z5MI] :tn*IjXꅃ;qdJ>,ʮ-e_Dwv~}]lPWPٮ؍/ F썡 $H*J^ݐmEsMT^Jvӹu=Et1ڔZh˯5{"s'p@sIK w7iB :3Pc5([$1iԣVKWa{K (= &%`iiee(Z|E2N4lHC%aw?t+%/ϥ-6$d;4O3]`-"D2ŎOMjw87D 3T5ܜ<cܺ:o|F؊dxqX=iQlG'E0૪Ǧb \ 5~UG$y$R+eVz*>B2 dc?C- .Gf,Ï-AG H] ܒ60TڷcJ Uᓹ2լ[y!~e ;*"r,I,l[ױX\CwRMfF4ZԈ52 }Ž+1+ r+]h& ca֧>g(UJ̹79434قEsGd6,Vx2֔;n G$,|jRn]xlYߜOLB4)m|m=Ky fO T=2\j<&.Kژ#zGkZYH>lVR'}\)*b4Ӳk(_#G o`pN kWu)-v\|9-(l&E$3wY&ˆ{u2ŽU1i ~>Ϧۦv8X[?LǛDAeO<=}P[j![875V.+%砀=RjĞ X½sjK͢V_ Vm {vJ˾LS{XHJY@״:<ֈ{h-,W/ǫ>^}zfBŰP(o+U8X9,xaC#kGJ*u5&fx&ʍsȽd5}zFQh rjŀC;}Iox T/ݚnʙGn6 Sd0̴m)aF/)H^͒&ӟ K(τtKRG!dGI_^x㖒g/no닿~>R]1d"R ug{[ƻ-FL"%e\NϦXa>Rgʶإ,23p!ncSdcsȜt@xRfRd\4`ƝfQK:Gp#^JDNz) mfQuK@J;qzrWvO)$~xYdVh'<ܙI쌽~a9mwlMK.ഁS DIDHi!R,LMaydt.'[!r [&$%Ìnq)-e=q[yǑ4ޛbc/6'm ό{dz_[Q#B7FܪeL=—4\C;Is꼔<6 ÿ$Bf U@IYV}?)[tsBi; K5nvN]c׵ڤ'mN fi/r&8/]$̦zj$CzA3Ђ HA;M(XPU;ju xc~dB4/lϳ_^MF{FKbìlbJ_z5ۻNzKcL--Yf]UCLcbz+SRHAb‹S,r+fOBFx]N0 y v!I{ӸY8x|tC!Vm t,.򅫲^UyM =g1A G-`,9ueI?WnFNުM R:͹am$B%FL($K!A0{.E;$BaʠŨ\e3[Y]1ݰ$?V!jnXQsQ{m3 3Z2xURъ0|W A_;^ R.\q}u%'ߕ\RAZkvk静ƥGdJ۳r?9eg+2LR~?EbZTְ3 ET@'U2^ChVy}Vםf^2ϻRd0֔AřZ*\)n 6ڐ 9Jäs]6#4+.CzS=9IGO-_^aI3mP&yd4V3(ǻ:VHJejBS.sOXߥh@`րmjGNdY,0#z ڒ*ǭA갂:eumXMZ Ϟ?LX㴓݃ ľjxuT]6|X\ ҠwAE|}Ě_ )_YJ8(|2ݙg-}}/y{MЋnj?>vJ G))P˔T&]O[[{9N*"u)A4jֆ#*nOHZq*}_{+!΄l败X\5^ ,A=~[ן>ƇB]E](rbH@ȕ~ 8t]92|JaERKfS"4Ï `9i$W:A jQt4ECˢ }CoB"~.Zޒ.atE'Ew}B%[ho -ŋdGm, wa-xrL, "GRO馋j!`ڕ"wJ.M+Րs(9Ü%Rؚ9gxx>p b4:U mϦ;;=DyVN!pх]=SLk@UOWe`|T{;4_nu2ZתTiѯW\lP/ti&J׮]+[L(<ﴭ6j]S,bwv|NooM=u~yq9Uccr\/͝]ט6;-ԭcd׷ұXE~^O[U?9^ڄ_<Ghԫ_cn1 kpuuVCuTݝFQtGJZU6tt]2*D{x9&FG1p}[a VUc`:B&tk'=u B3{7px71цG{B6$;*^IʞP! +ڸ^QεZV{70Ï7nz:}x|zFo󍚵7k~'>1uZGHiuɼu Á/SNǧ =wwf"cqEm BЭrȩkSY(S |f\-# lͺCc /t.Ԣo$u e8{C4iP_8jan.A>+K ` ccGnW-*ڞ \({%BAFELh˾>קp7G+һSCaz1͒̇2;oWm\mZ}aX7LmjhX cnLNԼLLi!" x<"9{4V\> 3h&ULyzwwOh֭S7y.6S0Z g1zx^fC(1%vQbaXxY/F00y;qMMַ֜Bpim ]z^ŷ.8pS>mKI3뉱S36+xXc:B BK /`sdԩ*~IrzbAu Oy8jWhZA` kȤzSB+tFb pӰG``QFZb ?y7o~֕>i|va< b}o1nq`-eVg:|q8eud<-qǓ zV)tW`Qcm"Į(5e^&;D w}; h?*MH\{B%LP){\P?GO qɓ'OhFjgxKtwF`zײ909R2Mi4I7QW'2"ŰnY?^Gd<Ӵu؇ZG&}9uӋ!.]{` 4x7{X lmXPvvTZA*%vi;jLkC<R>'':愉,p:֔ AcdzUT4X$xHŅJ֔ħ"P(5@^U=HTG7l3OA0Gwɑ욪GiJ"1(~#UsO} lo:gDJʁl+:'U.t''xwW&XG6)PzÄ g2]֒2QA@7w=*=X3i]C1!ۖ5h դ@rG;yGRbJ%UrBk78?P8CkP􎊨_HCYzTseJSTx4^I)s6~I*5n$(e_R\hex0X ,:j2,5T @mAc.Px`d&0 m 2ƖnK:/sE-vѹT {c?dV lDڊ! 4Ga iI8'vZҷN+T5%bY%7PYŅS s-KךHn:ɐ)K+\$Hq`dU\84օɎԽQY̕[ X\ ]x8,|ΕU4.:En_Ftw-@֞xk1ݎ{8ЈW" B@$'+2t'ǖt]z1=G,Wmb#H8*5}i&h>lb4t[JO &žs7Žops ҲTI f)d{H )Wna>6L;eݖڇ IiJLŬ۷0.)$I*G GVZaHi2zcvbN["/$ɦ]!!w8&'Ma-%/kޜ`;7XkL׺'277m>V v~rBrNDۄB^QL[I45oT3]" Se5G!"\T_]̮_r80Kn,VI[Od[XC^md|*P[#3ZcLD grH׹^O]K2Kz&x1VDST'<( DcNL"T"'~K??MF(@4Ѐ NbGCD"kè29b*-Lu$ĩ0 @m{ ͝K._#;΅o@E<$&(_iGKԚ耓Qpwit2 *!01qT/'k@165lbl:\c Th\+5I*t*ݓ`Z'S6*WzΦُ8|qt"-(h-}}0O ;ţvM-φ45C4]8+ei*%ݕЌ2w7P1R{Doļuܲ#h2k9rhǽw'. ٠N8̛1J鄍k-&֢h@7Uۢ+qO$qd-4.y y!c|4p.<ʆ̥0G~(QJRe Ud^?ܒ, xsk.l1 9 S9z<p 7|IءUW//߿ڂKD)=XI ,AgCyZJoS(LPm3Aү6m4\nT#B(uXgxnR?;=APt$M*M96"@xgל=ьi=9ROEC:I x I3+o[G ^4Վ>$g>(o*i3 @MTۨLogl)D KR_,hdEQyL9+y&%ؙ5'g[':/wʠC5<0J|:5vQ3JbdkR܊ 7p-ļD.Y6Y~neH; =ݡL^@y,];n_PVҎ/Lڃi>扖/H+o7ˇQ弽M z#j% Kz˜ #0lwt שԪIC9\.,By&N4W1_],R2jIp -{@hq }zϗD 7]!GlҕoQE8-ra35C|H rwKhscwKԤY[]?-NoFwGϡĚѴɓd1oCתvlLI^6:4n񨁊Le9_R'y%ם(%sշ7TOnqj{EӍBr\V=հ'CޞkĆ0jm}I(ԅ|:_&]hÿx[ms7L ,/HJ~Kbfo7lIrR{)h$ ƃt폿p(ڤjNNI nt?䛣|.9y;-]e[z:o_UmzV WK(V i(U7&W+.UmcֺjZ]|Su>۲. yQnU%Sui +uj0ùkG40ҭ[Q3TZZh XVSn6jVeۜCzo$CLy&uUOZ(8&V0Mf:[ʨxFduaKJ6 `~!,*j4is5iճaF0 \S;5׶`\vF 0=@ i33pum 4h҆ oZ:ЮԉDi (d=f{Vc0xn23cr"! )#GDj0Hc S QR赍LمH~[S=5`(]Kïz oĥ![:Vt%D|*tj4VKΞ7~,DiMybi*ݒ AvisS 3W"ɭ(Nh?ʶ\ǰϬK'(i t > 'ېnF"DQ<\hL/H.I3U$7!]]*FnČe:cZVmah%#ǤD=wME2:7BMb&@UUv,!'z*mg&td񤓴;ȯaHy@[Wt%[]#x2#q . m6cHD"'W`[j6Ǧ{aeI'wOKyKmL폣Qx 0[1w#+84\j^`fmSv >r zJX4|~Ÿ~$zLLK7>@@v/GTò<0t'z:{?ߤ۬~Ixo]A :KyQגS+'I}(!th\m)MO"%@U뀙=/@S 7B|=#bI\ă)a8I&:l+ۄ-Ћd_+pb̍)vuK^9{͍)JF-5zTљdG0y `6{o/4*0uoae~NyvaS_@Mӡ{D!- ҒY =h5>IF܆#2&KxT.L)4փvݷmўXjnA46GS>y-!2N"l+doSMXk 'L0xH<.BvOzsz@%fxhk zuTM\CQb)5bV/2͆?]d"z]FR5 Rym%mzyQ[!#eA_iDZc{Lypb(ޝ@cjPeH,Xʟ=e||ZC,vJ:%p``382P$uC#Z~ƫFhg_M Y5 Kp2.8c9AId GηݺWPa7zXsrz N&"9VSjĥ 3:>N^:~{uEinK샞)(%ԇ-$@c/߰-o_<.+z]m;f jMaդ<['F70\|&+ƽ-(9/=J; l?!̫0~WΑg rTauJBlH/a:#t6E~&.su vGqTY=E42=$oja0 %\e;Zvu@eB"k>[P""|>%jUk)-^v*aؐި䟁|pHJ#4HK̸ڡ2 $!k%*ܔdB,MQGug AW={W1aGiN"i5.mHЧs:D iJDJblfY(i`BVXTM0s󭈺-һ8(DL:'!U`|0L'K9{̿2|)ξNf11#ޒ+2kPql11B6#ۘGa &*]]Mw'WΡbsnVjUMWUd;[}};v*ACƲpS5u6XJ]dPf9ʑ2͑!) vҐzx4,a 6@0ȹ5ߛpUƵd">f Lqju8$ɏd4{qWЫe__=5{V\W$nzOZԭS'D>7Tu庐zi%z.㬦Q :) ݜO%g~O.g|*S͉i;ɆڄfbkҬ+jѕ&p$c" *6ڎ\npvOIv,0zW A $ W*Wb]U Qx/YXzjޟOD:/{Nޟ<*< )ʢ75RWvfc`X=7A zqЋ{8b/_r+6MS;/w/87R/ )Zēa9u}4FUf:8oW3ŮՕȕ:jrד^}? H9īQk8JzGfocaN'c̿`:<R| hMhKS)d7enx̥bd񐋠o,?0lHu]-z)}1^uKsM!:ﴶ%v/gƪ6 5 |5&t$ތ82@cH8)a^XًjVdƍo뗜MyBo1>l}/mEK阚27A~Ҳ,0Fa>nDH$k;[Jc=lNg&Ep(.b9cV>NrN u6 | X\9)IVZB'pApsa'tL % [۸J$.\(inr; pCt^t4F@ ~c1$a@HFuާztxvzj$^d}IlrLMMX88Q NLgh$E:{2f ܞkHZnM 4RZI!);!yi DL(썤oA0+;pOoO&'GJ^]ɛibEW[Cy6,2U d_XJ >RZzDOBB`dmB@hR-^pNE^ Y2]/ 7KZO&4"S j,S3&%5wHrd4 z ɜn-nKhe~ɀ[f >SaW.IzX碻Kw8wLA%(F_]h*O1g̶IZN(G`(}R2s˗@KGBfxoicF|L'7t^ڊ Tʣ_0 [GkyzSSq5MQ=#WB~Rp'vULڀCfJ |w2Ʉ-$w4l`Yiit. x {Jcčdt'U{'[mB}2UF9Lb/eO!r珆 eDbEJvY~z.CQ_<>GT4@N6+,dą5fnqsp֯6ѤbɶI`BY0 gbT= `#8o(It2 9پ/ #rwf0e::a ]vސg/ӗ R cxc{sO'|;`?kARl|6§ps#AlH3)ysԘKxA}YD)aft/9 )??C2.tu;>+r)(bGVd \ 9R8C7$U8H:.+i/|RMv0Rb֙ Ȋ\]FȺltߪុf;J_RvPlcIp@iK_E=%轎޻ëuTf= {n#GA1L 8&Q_>u_0cW< a;U Zǃtb קh7m- \[xTn0 }Wri X^С-v;cӶ:Yr%9#xM ıCJuʹvVG|}vs>=Ċ` M ~S Րڒ, eDQ;;S{~dr>qHs^ee?Ao17/ߑJ hcO^[>_MrZ%LgN?QCmpk j|]Qcϻe ڙ8}Jh AgYFȩD@N$M_GgDsA\'h1gd6ILY 9)#u8KmԕW9 p@hƊ3uږPa1#*HN +B_zyO:-o)>Dܖ|ofm-ſ$tF |w'r\̗Nx~x}U]o7|_0iChTc)@_=#yewgKeE$wgfgG.>/^ݍv:}7Lh=E{}GǞ^ŷo7yuKu1<>(e|ȺHes[r g):*K#ڦH:қqxCz`^xAouA^Fw; CʒGyeFouR\rYLBۚ /j2-H{uDuW7RQ;;*S:! BR 4Jwdvy*9J^|Q(ϊ,ǽMc̥8vxg/Z!|D>plIޫgOtz":?@5HY sD_f|]|*L&]"at羢mzv%ϣ\!w>y0"l űEn!h\hXUȖ5i_O WiF st΀@90T{a Crm6]b;IlF#z8$҃Fk>PC f"fhyuz&kaD@RdSS}̻!Ms۸7bD9 H^fHU"`ƏJbk+CF8Yh)H?_..vzjm^{yjws)M8OJY1!jrP|wSڬM ڒ iH(.- ji1v5%EX=!^J[%E*u 񜌥~PLCgK!R1EԳ;hbC%ѕmtN;4dvSE#gfOa6 .z'azu !|=iHzS6!"x,>T^T:L4 YR;6WT(@h=qFyO~w\띾ԻX+*2 kh%36ZP Ek%зIUB_U /a:W{нjz+}Dj]V+e Jw).0G_tpSl2`-U5zP Y+sL ~2rlvuoas 2 l:*BgíuV݉pOgx+IF2q!a GS%GƐוLkZz1V8aV_.ͪj~y))/vw0~M#z~j3"*8혁FY X5N0å)@ 쬜}ziIZ~G+1f90ǡ=RÚ:N+ے.TbƂoT7 OE :Li7Үe^QZzǶ'SJڹ6uסs6HWH/͌8{!._f]xUgDr0J,Yj=.nc eDe.y MK1?h >g$ 5n(=wa%̈7ڲh_`[ (cDGasC'lJFo_Wi-մ= 6*o yKݼfo5ey;8k$KzrG (QgXvޞ[y .J c)lKz4o|PWfaY;{\ _?3YgȲcBBF-gcxuTn8}W ݢm &45ؐC|ywەa@g̹/5}mz];/&0˺|jzz\E?/߮Wo(W=~j} j;~#*://6*rChݑ:*&Ü4SgdKl#P7zSI3G&v/ZU}!ؽq`,QjT2'PDx[UyRU^hQM&KBs.M¨NO]xS/h^U ZsqD M.0,z}>}sM0D1!eB Yx0}=ea{nevi5&1i3Pl4P h2O梿Ͻr8b ad\W/ͧh@*I&(MbUjut0m&d?Ӡ{V-ՂaKFQ괚m&*yշa.O1lp?v#"m;݂q{`3؜F33 nUلXOd 7&M$la/B6K);DA3bPam\ѽcl]#A!HD`1 p(?݄(0dYv 0&!l7]mSYmkdOJ288xNfqDDd^4,A|6ہ"Ě9ƙ*hy 8&fͰe~AixTuE/Q" ^h*X2\WB߶9~1P%=V ]M$GJΦ7o:İ"cqUP`UV?N56E@*;ةm}7HRzM DoS@}I Dy̡eE.ACi5Q6 :S%a7̧ ?Kr0H&*!i eTa)Ľ,N IR ^aC5cYp|N@i"M! EPƱH.Rm )ZERI(SĦbT>&!L$)E6-$Q*;)è3 ScP ~*?P3yPzf=+[,c s A07d.&OWzO~I :fK Au,}a]0Φ$U C|ME^M?o=y.>H hرAa h)]lh9<0\RgG'X,[zRQL8|vY&Hjc[l ]Wnzcd=N_ٮ O͂?gWg*x@e%J l8[HrhH?z{~SO56/`zl(9tn=Ijy8YN\ vrH;G&nkj\sW]q_Q:N̘-hG]Ygy7.$*$uLypOMGlS1\SIe#  +ߴ{?]Yzsv}}=am ,0#唒u}&~%봺]1u}~Z]\_]v[u,jW\]măU@C6}I͖_f& >ۆ$GbELU#  URzU}zKGWN׺\xzvG_yql֚S{efIN ǯI`}r`xI2F~ xEgRb{+1;%0\gu0y|\Ý.u{ys}7΋7ZWj]gֱ4f.Ljeij8:@K ;TEAN 6? -ql22) MdId g!]J#s8*V @R e4uAG"O:J׭rpHE*Cu}ŨrD*R7%&>E&6DT7zcAA 7~0qfN[XI82-67ˋSU'>f?}FCn:0 rNx~}тI!Xa7y@sWB6WpUb#uMaZN,ޝW9i2\Uշc(e+u<[/j]hw^IW;Z@K[h!;/Z A,@P HTۂ9"ۖ/,ʔS^Ѭ17i:8Iǟ~}-dnh{kKR?(q] #*ӗHJm2d7jXN#BPQ9Tȹ[pq:\˦jK+åp%9E$E$T\8@"t}cM*m9)|f 1Z6yK TLOkhG.oQVX q)!xg4$(B ?Ic=,ܭ_W])x[$Dޭ=o#^ 8˖wUQ$u\HY)9<% y?v("f§N[A^agW"t.h2 l66GR؜f#Ųpi fy,DN +؉pIY_j =7J RagG p& Q wgU|`kmw{6ihf)s[*|ɸt:RӔa+O RghWӁVZc|쵰Rjέk9X]=3S{K^Q˫9S"GZ4-BUZ.^yYP2'ʧ3$~xQ +&zhvHgqXޫ9Dnr@X01❪a{8_2byYo/Vŏ]WVU\|D )~4?|Ǔ}n qFZijSD50{{#b@rbnPp/кBYQDq )K#HcLG$Cɍ$%OU#\]AW# 1Cr IJI+,)$c>zzz36h&_" Hu]@&]rK}?[]GX~I˵ΓKu(9+vWu_V%)ՙPJAkڶSKiF.YIL[% ]E4N(\+=2RCha\z'V:~7̓'ƣ_Ӈ͇Ӈ{j8[Xhм4wR˪lA8]*iӨiSAJ^j.mk`K)̦Z}eSߨZSj4g n%ѷ/ Iӯu(kXQV^ɮ M(b%^V amuMj9QnV*3]-fWKgjC KL 7FK{Q-Yo[- _ UKVdT4˪20Ii5";=[ld[Ui!ݦ2/E׶/J56-7bފA5ձ:y%/\ˀZOwpJclb7?{zWDzl$NaNgrkԉP6K'B|kO,˭oU[P+N͵&ܡt";n7٦vzqr0.Aˏ.9ًc 6?yA﫫wI7no]7I/&!J&>8Mݤ@a0~dw֞%H=""쉃Jh3jsxv:̍Zmn(F:rhXj=H,ͮZ^SrJK]k+ͩ28M=0q09CSi-2rujl\x{E=P3'.0{(l[f{TI^raG`(z/M@a  N}n>*rfKEtǍMGf5IN Ye9n6͹ 98]@DĶyQޟZ( ̪ꎠ2DZHF~$A# vDS Oj҆l9O#BTSu0ÈB5E0b46?{&hLш4n C+ $]Hw/S'|U#/84?_PhiYêWědjchcW~Y(RkKϝ-/ϝU75l=G5=Qiac!61g6k4ݮWX!S/kHTq*w![<*g*smHw*Ye~\o8f>OWC 2|2Kd*-fͲ労knP0e)~߽B ,A9!{JodY.h 򙃅pEk?8S1j<  0nكq/N }ϖ,$_ٞl&܋_LX0*iΔ<2+mM+D܎aSwA8"jU5<0v^ Yy)ծMF e]{.roчnP~ *@ӕRk76w>1J]V䕲)y )WvJuiFjɥx̱zgi=ٍ)D44^nGj^)~YTfu(j$ߤUhkk74ױQu1R+gs8ݔ`N_ƱdC. XJRtYjʐvEuJG|+sXiFL=?0;wz{n}󷹛e2MEUOձ,FS_oߒ4~-7ޟՍ~48Z)]jK6uN2+5y1;̽)3wIÍƅy4ߢeʎ6^bF+y6T'F ^}nxb4|bxaD&M *S&Ը7Og}K"&7&i?üݝ)8RE]gji]5埧dPGJ^Ȏv‘9lA1_IXt1)tTvj;C'i{Ԯ;EIUo/0?F',V갨g<օP]"~RYj9SQ BOodUc.Ճ|;x\Bjb DvH3AeLmYfY;xJg?qJ?dn_5{RW} uYN?}c*'!˨EZՙ.W1˭((לMJ8Q,Ű=~Y MOsc["'gs%y.Ib;%]a HF T8 W$K?7p@&:HR$VBbxa(VF><+8l3gy:Yk<}"F:IGiu8>KVȡOX 9f=ca\#hվxn*_90>{vXy22LdžMQyA־Dڰ 6|TGئӂ;qhWԍ'0Kcgm<LŗOc8\9=z|X-'w~_#&@KT/{ylA lEz/eywv=\ra*j /c Nk0)P^[ +TL#`x!^42!p '(_ZKnšg 㵴"Ln8c~[ "CDQ.ba wӛ)!Nng!;ch):֎1vhaJ@CxpWڥ1./qrg rNr3}%%'pVT lqփNyH>y=,Mѽ]C7;~!V[iyAN˃ܝc:.pX5*dN|jSeL'bq}z+y\=:Ѽ ^}7 6ˀ{\`))5IJ]<~xK-T'FTL_ij|::r%7L@ۺ0,|9]XQؒi=P!<(F~u%}=zJe_3Drʵ򌯨tn8\^1X.MfT<s c!W[U]gHnL l@Ez姡Edą( KSd+BJ~\]*;4! _}o$b/iR2=3Gsaz ʠj[x( NL v2(sB8O[ ɮɸP^* f=>4M'PtN4u64]2%j m$B IfYma -虆d]Y@n.I§QU]lmo뽇L'jzty/(-mS\eXzN<8q]ۘrV$|bҚK tP9Ӂw~~@g,זte`0H1tevZР2OU^q "N-iis`(##i1|J勥ݾq2pwC/SNOv^i-Ot'=.Pg<,qR?j&$JzI[PN.Ru*bB,I %~_ZX&NlNYoثIG!\Fjs=$Vt]O5о{F&jJJ}Ģ>FAoso>yy|"!7xo4'J9SbV{iHvVtv2Q$bchQeYL ¢Ω{~EP l8G2M5Eeg~zv_/W~zWP\M؝܄dv'95| !*up#shPy/0n| *`^R3cNA?yw~O#_"q&4V 3ZѩHJApFCivpbheoMi:KK.Raðhu}:Nn2w j4g &wQ Jw5< |u"^.yeF*< L>4y.{Dzmt[ISZouӴ It^PM;ӢmCׄhbo*խ.:-+[*k3_4سg]dWdr!Rve)qjH ul# oK,>po=-$xMOo1sٛ쭢"U{6kXxٱ7!{盝q{u+3 ogum׽Wݝ>A|;D~%_0! &s F=#,#8 '(8A+J{q'GXN\$ҫXq)c!R8Sv &b2%d1] )z:\4^)C:4YƒleMD>܋MSB\ǚW'CTt1WLΌ Zq( N[mX|#ɖegФ~8cȊMt:ɟK ?.Xtpj^hi0bQc>}ޯ4_#5||?_c; ]ʹ> o/B]8^Q@+]⛻2of͛Y] C$1`H'8霤l'.e~]!dWj1H5,yo"{`dpm$ቛ=SS>c8;kB%y@}Ձ|ȝ-i૳h DE,iG3cILWƘkdDZFf.ɨo;Զd|3F\\ @kiIZ+& )7ڙXN!6'w񻆿tcd"-0GAƶ# B 6jDWn9jT[\:X$iN6tr`5-h|\r8Q\oguTɪ Ipmqy&Bұ65s}sv[_Cc$ ڹ i:Zنg-ax.:@"5l !}::ݬz,׶i ٽ.Q?UJr#Qw&'{ZV{-%@#):nl[o;ZaJ:q2Jg# a\ : ( 2fEuZ{6 ġFqr4ScNt1W/Qi/ 1X|XshރByq=ǔ|u:%. -KNzgGNT0q)Kc`k,ͤoSU1GޛH^p:F+ʃܑY8lb^L>$T (d Ki7Ge* eͳsp[)=JKxhb9mBxυz%ǰ c67>Eܷ*TLMmZSY=hδ +kQsj?k@+2Tۡ4:ucaPFJ͊ 4yt2uR,QܤzNl?ŏ{r qshְM;Г} IG.Uj63=;^i.Mr*U|JF1]#Hs  sp$tWv'dGmy$Hkz@y B~>%| e|p1f E>x]Rۮ }+|d/ tXk=&mgr~vQ[[Z;W}wmcvA qJ!LMg)#l{ҔQn 2*rBbRq{x`B:ÿ8R*Q(\229+c䜔C /L.`3a^ 8KP5#s=̅&D>͞<~GWӳgm3P!~[//<}yhͦd7e٫U(aM- XϺmukU[ON S$ 7_]]7]9 ^틫lW?1?3 tooH]"vUѯ nVf/e4PѦGj6^.l^ J]`*lvvo6@wuSRFA80>P>iM/#Y4/7 ԁa&`x 8`ˆoҀ Gכ mM(y_3Ys{6Χ9,E ΠÓCD[-bU7{$r[e!5P8pkPj+k=338tnj?c?]eSa)cie%=C-G^:īEm~<ħnkf;zO'GN26u6 qc|wgp9/Y80c(t(t~[.<^2E$]c1"D[8*LA+Lg2+<B&\Y5,`qy"75˱-m튺_ogx= 2[8 }# Lxh2,硽1_Å6෸0@:ڐ\fOSpuNۥ}S 5׺/; w"NBHper| (j(`B πa u*dMV '$tm;0|Dl? D>+ ɒ@UJFJ'^Lk"eM3+PMAi=|}ʻh؏3Sap)@M ח- *߳2' EM`4,L> G^Q%nnw@XH.NA$%E׉DL|-4A(k8y$@X&֨r5W"v5 >AVmKQo᧳+~dC•@ҏ %c!}$ЍE-Z8"l]Q1;z+*ujrڣc?BsQk(Zm 4@a⍳  ^[D6Z qT9@FBrB-J;;'A3o6;rRN )2ZT@|uݞpb^%L 4 aPWW(&?Ι" 2"G<Uyw7T!dG(~5WgRĘ(T\7w@_;d\ DAkZ V5nM&StR}4ܭ@e=.CTg˘ZД~A؉@Ff@a-OgC#l^ܶ4lûò;>|beOb,$|7G;>H5u#(P!Nj̷ ШPZbk \ˮ|s}&JqBȻqw.i@F#@ ij~ (?hʼn1?u^eǠ0ϻmCO]ӿd;D7I&DxC( hK6[>+1MII=Ǯq#u'8=iy^+2G0hQ8޿~2m[_&҈Bء0ɢ mN˿.죁#jz2 "*^@Mwl%Lcf,m ZODUЅL6+QNh -"K4Yxrc/@ܡ!rVIIOfb̑]4ypNPWhuB܃ D&n ".I"Y"~ZU$ܳ]?`5D&؜%{(>$jrԶMh(W?MǴه _s؋LZ y0u[` / oFEs'pH/{utO&Sn {"k+gOAؠ{.Dc R3F!KzrVD=4PQ9dBLu "RF+1+eȂ@*N!@OC~ĂxF*Q)+g[lv%ë8Ó$M"|[VhVJu.=9$0WODd햢pyH$t8]׷_\0Hf!F]D:k"΋j!"e{D"B]q_?M«R8ۗAFG7&&LfA, s3VQU-0;ad3/$0d?6*[B Ā 0F=$Y@Q%ɗ5/P)$u'@*l%(KBZcoDqb…UD TEKѧYkۓcE(uAn+ 7-se__d2=,P`i[-!xaQ6&!y2g(Q;#9C ??|~ ;SL:%ª(猄rU; ǭLR-h @N~%%`Wg7uDDiωUˁ׸bid y.?d¼ }w8v߄kQf&9L8``KB~Q3x9qI%&p߃Ͳ)8BLRY{ NoLoǰ:!"nr Pt%D"I̵B+ (\jR ,V5 :TH|2k(ev(C.칏qflX5KWdjWD8ЎE\[frJ=@ѳ"g~a+KB,L`3 YalINKO_2;զiHĨĤVij,,}n­zL0V/Z"!O5OMr;jך`t]mHгqpЉZhqr%*y#C8ȈD.21Hb@L6&/bb'JGy{&BZsvg"_w@pp4aѩY<fiIU+h:,VLv 'D¹\GmWm=I_#x)YA% 6'bp?ii?8+x5Pb\隄x'Kk=afWNyZ_gg===~22r{t:}lj`GIWi(xzWQ(6 &kf4tEy 11q`!y\[ 5# :|:y\:HbUf.lo7 V fh$G˧bpDSG8A*&y{Z2NaWwRfUjNq, (6kalB.h8 YTw 7:)ml$ `wj5pmxbW篲fZ3<"J쎓Cb$yp{C S;Rl~ȩ`+5#<,G@L0M-2ս E0D |MSUdx'Tl@X87<$Np *Khlwf-($<=53JOV}'qJ{1^64\E S7R[.B_AeM s$ر+{hXהY~s{q*Ѣ&W3W";gZEU?2yLJBqJ+5( ?01IJ$^53k P'4+{tzeo  rŋcIb%!G)G[HN8J00(DN`0woϲיxsyW&@%t@җY˸(YPžij_dkb3/_xq2';dS(Ycx0DŲMf=YSj0Q:D̛#a=@sW }%Lcd*ql7,DAo,%@ 80 9>/kox@RmZ7ZIقjneZ&^v"'b\ct#+3[m˨^"t4Q=*0֍a2{ǧH[$;~1OfC`të|8睉6P'{0|L`w%ux~Oe}|'%ā:mdt83gf*۔"SڄB?R"|WnD"wE/ |(?>ACXfXJmeW1tGLI2h3fRâaFLDG"rqYamx|hGG~q=8* x鿽a#3l<{=ROV,VmY.TWrqX$NJ=q- .8-_FùNٸ}2'? /G`q6?oc0>BQbHFf߳As2pG. 8ĺ,^~aӐn QV5Y$&uxk"5@>pECGd hRҋMbz@p)!x.LG[wZ_ǞfѪ*0 ݌NbRQ[2c[%1k|\-lF- hU4\}S4 iG^*ṕ"sC S"7T4A16O\,HeŲq.{3;MXy'ê8idRiSC/A!ɛ+I%0v[JqEқ nxu[--$UcR%K}TUF~D` BNw8nY#lsPx4p*%)5!iSCp>Ah:Д#`95G/,(60eJ 1XhI#/dϹٜviRr()`/;qB :)12>r0]KX[Κ'Vb0?RL/DY?yS%f8U٬(R#I@RrFM}eOu w$KފJqgxBSK<(y{"K<MXSݥ"FD6ȞӉfifW66 VJ/EeF?:a(M!(% iRUe6pX_ , <λCyON4x[Z8͏Da  ,:“M>fdqkx-ȼ%r,(EYH@M̜u,dٕia4h zRKw'9:}_N]@nLlve VtYB.~uI ӏ@#f bKif3_떢 +=s:BLJ{ѓQPxH{UJ AJ-CiX[ 8_r1 3 0LyJs}p|=:"<5rRS9 ԩE55zYd@wR"HmMBlpRZqt !>睪u駠 Ԏ{" yeF5+j=]K˞b_e@UßT?9瞅iZlZR|8/Dڵz~~:j q,b4 Z^i 5xB=~crN$$96hF*:ѳkEY0A[&&BNbL&(D.ZfGd{4)YQ]7:Lzv,7jv@+ nY '3GX^3gN~sΐ0` Ü3ˉP+ޤBȻ^C:ܜ4 H CkI0G&Kc\H7khׅKC,?5s}@]m2S5Q=#v%bIӞ }Rm.=\SaރഛZߜnYH?_X=WU?C K.Wgs8$%V4#f%IX'{3"=B.MJ9l^e\܄leFRWTa%'6=hRm1!1$jYjĢYk+APNsCj{]=wW{r KDbQ'X +X)V8zm\ -(RŊa8(D>ƀ$K2AJ=Q匊]8pHOxπ2A:bǿIIn0I4|u"č,Zc.#hMT'1u X}ZC2(^ȽQtf 0lj;zOX `Cꐌ fO_Z*_  ȿ U76碬֍Ck~d߮W (-! &2?E`GB3/Ԗ ӷXؚD5F o+qZs4/Pģ׈7nnAthD5T۪Yce}E7iLz^Iu;X\mЌWm1JPm;qHMtTG_9wNU)H _:*}f2۔;} *{-zMy1Mj6iW P).Heгq(U$:>i3Y!ři6(¹ *bI0b8Cͧ$/ROGb冥)sv9HuM1+7gO\}}HfE$P: [04u& R عx^AE/yzn>?f#ٙٴ1]Rma͢g>1ҋH*A`R1@%!0 G"48d.OT]ԑQ8GI=[CeDO8:ՄA|^\9k RkЮ:luhA 8$.&&Gw,Bv%T,q US8nEL:AHX7P,%.w&`*= >&尷J؝S&`P~f_թמR"@+VhFQ ӳ,kCiaiOy!2HF A@ZQl~Kr}?QY%q#G 65ƞ|k#pbL)sPĵ:c׮ϬACj{0(W Qh,L_ 9`nq-4A"a6jQi$rŗ%ԩs'T!oACjĺnq~9%{9jm5|3qۜV7?#Pf`ض<+RŨ9Y|b%]"똞19K%a)wIY,q/K@Q^cW x6z (Kc LNpU[AOQ+y+l9ֈ_(-AY$t,K2k9y05cn$5$6$Lϱ7A,N(]_Wn;jAlIۤ y7q.L:hW-Sz^ fP/kAq,U5&uni>dע YSlscW [NI%pNO`>R+,(Xirà}OzBnH$Wp(&V͉[ ;8}|1%MmwPLlsBsxtU'-e;UE>X% * sDQ nK$UAmV_+N_eAe1bM\HH6&~$GX#UѦyW=ZW5)j}6UTFy GZp=YנZZ}~Er.6/ֹ2cXGys0iP'+&$% *$'  -} :ARԍ<^|AXO[tൠ1fq`M^+u}@֬w|)RWz+sH*MVA%raH>ÑjyPk]R,\[J:3%vE,+&lji3pڈN*M]|΋i] ZÂ|v]q0XXڹoox}{wPXl,D9DB#5!-:bx̯(cq6M6 kH$RSNIsXt\JTjAmto>A\ n{Q~cTNpiSnp3b"QevhD̒'Mu(6ֹ40bXYiSRq˴LϲNhսRlxN8L-GD>Io}Rh&a%<{   unI 7[h?p Ye'S|S؊DaAQ`#'g(s[% ˏSnKGZ$Ihd'4tJx8>7TQ \ 2#BHh$Ԋ-f( J#N&Ӣ;W;c.XrST{N1ߣKbnRt|܊;Di" ~?QeyQuacPမY>Z<;I y_3X-g_|$mbW`]DΨJF/umHh_Lҏ_u ` }' EY !mwRЄ96}\ ڒmPi]}ζ/@x//Axw/eYsl9S51U;\>bhZ2ۈ!@6^{6 x efn]%$T]m -VE]b㰃0]w mzu B1, |dWo^˰%o(:jq8nPRS ʭZE&5AT*IJr8æ>+A&*ukUa nSK|;]Ä۪'RTǢ+͠hG)i-le@48wQ#I-?Ns|.˴v{*@vp^Zp6$C3"p  6 xB'=t1@gb4N<`ÌXTƖs"SЉ/+M hwysfm3Pe:1+_a#xZm۸_A)öik\|ج-6oeQGR븸y!%eӴC2Eg$h"+bUA>Пu+gj%,NyS&vCi*G|lڟd׶t`nS5LFO^=esA$dρ4h] R}WWWCAz?,3n:_ܽ3e&D:7+ 'ߣjG`RNhc}=o6QPuz4V[Y<*g0RN6aR|`l]gb0*u5x63;6p1*P`{YV8Tz#UwK0W=0`]7a EK!jy( bZR7ATu+E^+h'%;k( J'U6V 88V$I; fHR)1UP?dz E~4fCU, ]FTkG|4 ]ZџisN>`9u ^|4!K9hhh n)f)"."H g8!{1jy䑷8@#!Sr=}~tw3ʖC\Cn0MUhGaA񿔅c%U2ܼje1-|P.x ^LH` TB21)nCyfbڪ}<4{EM 5P5.UJs"Z): T \QPOʔUaPrYvE\,b~eS`$/v{⪰…DtUޤq57bd l2*ײ7pUtefCvԡEMf3qc|]=&`s[:Um DdleeXd: Any6JFy H7F>Aͧ$4ׯ|b=&mK)V hW;r(?|k<pt``&iʹ\A$ `D3 &RAR7+il=xSeSt%v2*E6tnCq&t PbєHd>9afUJr]u[#ȐmB-}Wje֍#Fys(oH&e( q$!W] Qu+j H9BJ|딎+PEs862h]hVNyKV2O.]SJAgqAg"& 287 YXG$z+t)sg;@`uq@( `: ]6( ʧ$yD(QGP]LW%: c8"@@GCA,=7ZkBW! dy++?Irԭv3#b҈f8JS~'^ˆχ(X6fҙ&@ &rT}m U1?u&%ڋLN@+6D{ /Hht@cPe mz}-5B#c6%G҈m x= -̿'=SdkSZw`3Z;c[H /k+}1Vx:;RaُF[s6^|kٵ?Fn[-h'0E=5g֙4<; n}y Q(l5lMdg a%{|sU˃b$!].N([r<}R2o® QkX [knE$: 3H5utho5FPf>b.tw07j}.r!u4LzX.,T WFn)q ~T0 fX,|(5Oht.bDqM%#_+ }I&3W&B:+آO=׺]:`|_x~ua᷽.+m_Ү/{gWVɂ}|ׄ(~:[e:V`S Qx,G)< s<vI]I/5#t&~4[ _[E±xYko>b5PV@db!H;"ɩvw}b?;3- ̝>/|5IenjmwVo~wwgߟɺɣ?m+ϯ.NF>Z*7hdG"]˻۱H]BeUT.Yr˘~&3_Dp)9_N:{egAj*t:|ke2O䪴fDZDmB7׃]64xe^^ULƖ5/E_ֿءe4Ƴ|2R ZK HO2Sh/DR%-KNwQDP: [%~U>⃕eUY5Nc6sjNQp++]c)Ĥj:I)V^.atDx]ejxHzwƤ_0Sm252ҖR޸d G:dn,kSa}5)OR mulSokj[D7Hu:Աe GHEq }2rʕ᤽TAݡC.6qNPHs}" Ȫl Tjr]ԕh$4HBJamNօszs~z P)KO_)Md$2 ;U"G2U$!/tB(#W%O9StB|oQ&A>$3NqmP(_ۦbgҖb9T/UՒ|ʐ*ݭMAH.`1\@NrSك]R\٢QjTcvs Elt]/ɽTiZ atfB$) ǖ͵t)mAOVBNﮧ.eR?4ۙJhqh;BM縣Z_zV.ե 4-@ <9w(;U$#i& j1CLV{7:򌶹$#Й#v*Wjr6K/tJ8 \4ET{Pgg8uX0 TmYg{.\yvveg:;Is@OaNcQe eSɲI\ݡdXalx~=O3MjT,Ub'T)a8ݻsWjŹIG[>5{TD6fX^يe0 @̪(#@ѕ"SGIN/:#j zؾlO\8'GبpT>rRxh7urKenBlʹ`/Uw^ (`[HG  }]pذ,ȬJ=#_]Oo=yn:'k]C5Uy5icir3L"NkJ=znf*4p}]$]u-sɖ-F/3UܘP}~l|~v[ӷs"+a.UHIlOfj@hN*oaN`ѿHB7G9P$.dD{\C8m;R'3$hyD8GN(.mA#nw EέX' 'W&8H2½><$N/'c~Ţzsh}N_CX+#)7B8() &'SItM,g=h3`#(:h|!joJ-؈0wrcalY9:N֘u8TrQ]KbhHkO;[N@n:tJ{.x׌pӀtJ[:jcK*)Ozv|7/&7YDhi Zo _}ƌf6?~vL<$Z4*\ 露_O z nr93ߛʤ6IlՏu٬"x340075Uc}SIt^򙆲GߚgL:D!$C/9pؗ)dv$Jp *IH-Iz}\w)^úPSMU W7lpu;)mk+//Jf>POn2sn;j"T1P^rz&ⵢnN)fgrV&{,V*/14$٫B??{{kȯyG`RK ҊR%i#aZ,3"Mn1Adg$& +3fq"ΧTm_[6? %kvH@N=j`pݭi-Z^ɑiV4U)i >NJ~cnJK[w),OMfI>42ljwZvύuV*/K--΄E +e^w6,&ۍ1xRn0<_{Iq8衷9HQ+0M |1{wI5H,x6`؈ ĤB1Ҍp"' gX`pR.AO4snyD;f0kea29&<ƾ0~?}77Q$ݮ(84fRFXR1FXLrJLZR^O 6#֓ 2ڢ*ɹ+9ė#ϋ )4Kk¹}t?JC(0~̱8Bо߶dzBDz9hgW;hESCxnB2&j- chvcX˛(XÑ^J^!{1}g9~[\*eE$ J Qk7xXmo6S`)`;'kd &AӽSAIE"Uc#%YNlK9awxl C7Sr]Ŵ,JB ;tQi4TPw |z;?;SJm3͡,p!cd)lk<_;c&LXHa0H0KD@Bj X3UDbj#ռ!o/Q /2!qrL"r3#Bà@/%eaTA*yi HAa,6  NS`8Tnq(Z$ x.vSbv ;,q JMN`uM |JmXay*+1҈Qs1qhdM>,skW)n0ZϢٲL',R37@5X}m9ءH bd(xjX R؎ "lMHё QL U;.Kh\+x"rfQQ1ʹJhQ\2 dq.i<#~!7 U/`x;A6*^k5Y'By#C JnX InHrCP) #!:T6yZB{I}I~yr+s1HKsN[EA1JiKnXkG#޲٬~gBHP^l|R=t֫ A)H)=s HN+SoOR݃<",MaBt[c+^Vg+:,-zjlYV#&Ay!9$|=`Y[gV+HOCem! >=kd940_;&T+/Kn@ܖj篢R>ʣ_$291hcSG3bCyٿ,>DZ NUFdF׎m+1*K7*2mr^ ߪk|I`EւXqjc6ⴶUm֖ l)Xd뗕x7^hbׂDSυ%<.(^dt$j73iluǂakzc1k C"6=& 9ك:Z8eT^u)<$1f ( $/1sPV&3BDy].m3Y TjZqjnaw9=hmZdt{g:vPICCRpզޝrrx&9^ohC5h*|j肳}I{C'r,6g FtM`I]dz_3DB_zvrYѬ Nb LP4S]mڜ=cmYT1 41dN\Q=u Ŝl.V2jaA42ōګMk:fG[Xjj:KW 1q҅yt`װ햔 ᠎֪ji׾i\mk:tŨV:fF@SuSf`r]ht6mi?M`KB5,\:wwi`{Y3XwjЗ8V\">yږ]qGdˣ.FOuy.~!YxVoEVˡٵ4+U2:ICP8PTk؞tXZE\8 Mo@cEʡ=#!wcڱYY7~犭~E%( "`w ɺ5mbԑiH]l@[\BO$3ikrֱ #[ve-_rIR*4C]od+[=C @B5IŃ+=)5:*XXcAIB윒j\*WR<[<聫 <4:{š[Di3fv >Z_X>"$-Ļ7 I6yx'I!f1frB"x[n"e|az P6Ԍ C{c5pg73~8=c/B)a{loS 4:VY6#d X6 "gqVXX;z=Q̐^Kx:rh@g  CLr< 4nB 4rGmavsS-n.EXSz!yv]<2F%%so(X &}}TD'#l$ȺbZ2WZ_LKHN^.?~$*qY+ ɮ 0@  : =78^|hGɺ:^j3-ҝ'`W͓hDGW k 1RX{'odqWCg}6෯ׅ)0$(|!_ i86C _9x?EwꙦ?G޸Cp߰$>&X1Nn F<3ɎVXYf_N5x%y3t~2-_d,ɛS8:3a)DK'myj "pexMN0,XR;!Ҹ- RYPV/&Nbڑl*O ,< πm;X:O{zP[3/$TpȄ 2PfL(ϡt:ۉޏQL&;(i8<:إ[o(KFKh5 m.#ԋ5nܺQɌ>`]BX; %y :PDC!vժ}y;$$yF)¨L0Ô̇w̗L\:Db S"ͩn~Q> 5Y[ M-0~|Zt|xuWks۶|+vXȔGj{;îL|ID$hRrWK"{{ Cr6NrC)3!rME4-fReDoJeT=)nBZXL(hoGdrƽ6ڂek&7tP/F@Vcwj|h̢ Y#A Ȳ$fc9je[@C%pM Z n7|DX)Sʈ_Exu] g}.b0f_Xo88q0]c@\ aɄmՍG{rO.?~QW _LIc[?@n-= ?ߤ[ $hdr2NS\^LheB|gB+&W$DÎ)ǹ)* @oX+[Ç>йfInd1o9I ]!!P+ !tHpYKAﭫje״?PG<1VyeXr5c޻B ͔&YnSCAIn.c?ػ,tȓ=Y"T-GN4&]:FD l.*^'3px~vje\~"/ii̾E.}$,˂&9.{/dj&:њZ~9NN'G~9^WNg-JbyG4t\,%~85b'A${B ,7)'ˈk?#qni4e4U44.辝~\?֦}Jٸ7n[AA )^"|`5+C;]*{勋K :㰁kUFh;\to!pslɴX?e ^Coohǖ~e+M=vì:d.BGC[o3"eQs>T§&FF7We3.WKmD]SWTIDo~{we >lWp|ݮuY.`2Q^з| Yi"{a Nagdr|uuu~~̅-wpƵ< R[8TXT_Yݙ@? 2[c ܁EC^6(%<$SGu H4M)nF>[)OVI~ /O8]dچ(BmgxYˢU\6x_!*GAQnQƎ(ˎz\n/_S|,?X2l;`mverQ~×+YufC6cc6A=0W ^:x}VMs6=+b$iɉ֓!N윚@rIE-@*J۩C~o~)0FWQ;K6L0yxẂvŮ*vtr^՛/{ٓ 7ܹSp xfrM:97!8u=֤L뼎]_нattg=p]Q=WQ$B )[au`)gjٲW:W,J n]>GY,mU=kY,_W,{KF4G0W*\!Bbr)hFcnPH!.bkQ^i\!t~ҁ%"Y̖:sm$^lܨ/ p~4U(^&^H8 U=BB GcnKm+'s&TFdF?I BWMT-(j6gPL? @mPo"\|yҰFesQ[=<)BWIa3mav~]k&I/,SO$ijd%8'܂4.KoT*Ïn"/=?qaMe}qat+fMng?4&I=U1a2 g`1A)ǼwDn4!`;g×&߾^^]?X,oR<"gleƒ?QAɳ:.0B&; ̞4DȬ`\ZxZ߱ s%;0$Lp ,3Qݰ@ESP`B'{ڥ(c=jdV][n_`)9쉙N%ei]SlC# GTr!U*]4Mo-}5R T4ΉHδ0Z![/p`x\ԪC225z/zҁj^9 Ā 0ȪDFƊ3}ξ褆oz"6)]<)c ʼn'p8O)ÓDnz I>_΂?tR3wyH颴xmPN0 +,*hKhUE֥ҸJ@[=g;d8yo2 XUzm;`Iy/S#2:(TэSnE̋wT.j&KTo:U0 Q@6UZEzB|J<AO #;-<X.y>>\?H+)d5L$ikeF4x(r:J)*hn{?u$,tإ1teze.Sx}V]sJ}_UyTmR1&yc#7,`6/D8htO9=\t/ fKbսe/I61EW$g)C*[rݓ"k)$! )]fr1C| [LqaA;-(T+%}.]QQbKbЄ "1dTl H(.S?t)pGSb{ѱ lHywt{%:ԻsYC(Q}u?۷4sk56M?a4N${qO-J%83?%@d2xH<޹HX u~RR镉mɤ^ϧȟE媍qxtr/UN'l) gq bI@ bGzj*߀~r8.Q B-Ra\m eAY-F~ T81g=9F2j 'B :`5"'2=×cv'/HPiGMyD<?Ghȑ0֚e*ٜ_>!J?(<-r}z`=(Lk^uǩ ܣh:hh7A-Pߜ70S,4e *; 0jqt߁Zo|HW j!_5:';؛-2@| f܂e}Ңhg^͌3DI6cc/ȬeAQ&'cџȮSBݮ5W]~= c 2|z;V$q+W犽h^Zv+p|9ᳪ&f/~u瘟`2sϑ\8O9wq`ljmyhSê,vùYoے.fXy``l ̞ꮜ>Wf ˹x[[sں~V~fgt@9/SnŐOEX_r~YmmKmCd[[%/〬.ŁZ?bEoX%\ϙp"p8dxEiȯfaR;]8: 0[`xC]*nx`Qx5q3x!YR}J.y06ofQwlM3f!T*FW0١w֜8pM}+$aܰiۜi(Z iP Eޣw+2q4uc]5_LYyr>_+:əSi^D:#@r-k}&Lms֞bp+N oi˾dMgً9?[o5I({]fy#60?۔ Y'._omTw7'n$"wPV+' O dWXsmZU%9xG\D}Y0C/q/3+π_]a1ټkf='bC E*4v7knӈGU~|6.H&qGl X<>.>+yu5g"z.gwz-?Q^kMsMp6@j\gꚫeZYDlxΫM#aE@zxF* Pv쎸jf#D5<=9>8 ;G׊ T@q{"LZ*fr't!BOR!^׃k~-աnd#'d qgV;a#kKdpg,cyHL؊kwJ]j5$( hIZC`E)uHE$2Aҫ֌Q^_wg!/.;^hjejШS4GՀ24(ڇw#gg$367dfY{:wxj$_d[AaR~5~z}T5׀s$8s L$A6\ԍݜ9srʼ)PC17&2n0.#Ijw~y\W#~c_=kW+垈R9+,"Q*,hn1V?0QElpO ѐM|b'KD>2/U2_#pRoQ֔s9S:k߂ӻfՂdh{Yţ&y!{#`^~ -p}P-Y/7Uym; 5%jퟅZ;u1Q5͝਍J[xE'ـG!/ 06YE0 OAn؛ͯܡvUI7JZ}tSp ".)b%{i6'lN"^-Hy*VF0 Q(IOB\9%P/o\y`K9qq@N:.[a $ $ěZ|P<iG4[ PJ^Iۥ &h9ŲorK @b8DzdV_:G8{$|\L:S+pko4*#qF.@sv}xN #yGƱTڥPzk~=q9 أC9w9ǧu1rN%'93GP47-˴Ɇ8e+Ov$[? xx'n1h WKIpTB(q nџ7ZHI"ɺ ^-)/Q7y)6 xٴݑWަ_g}})q{Ћꃿ0We JD==([rH'{v -v8'N0g+p<›b9>V{ˠG("HQS'LU9(=6'|O[Xt~șa K^y#bᰧ>T`F--.HAn Sk|veza,Ȏ|?Qߎ{kg&I پٺLX5"kMKbIUĖ8"A~BN&F/10xVMo7W ˀ;Mvc @Aѓ@rWJV!4@.̛73{L?YSw"(kVZRm׶)ZkTntL'w"NiQBwy^f旋˫5mTp6汣CUZi@!.,\RXKR t=9)Qe@[ i kr4ېiGi szhcߟ^]Md&5m 2z*gV2H:YzGXy{vc.6]⋲4AJ)HEi[NMvދw YFKc Fr+L !]Z6+TG~Q=R+im}`LmcJ$&c[+T%^]I&-_&ZJг =Hg&T9 QvqC 5G*XB@; vjuU>}ׯfs߼y3]Ng/Gɡ-8,3?ZīLpþD!x  ^tˏ`+ZlD9Y>֩cspvhO1y%H{X"|2IF> t;\*l c.sQs-3K#%=;܏VTKѬuօj FO BA L&e̒1uj A#Ja|;Z53E+OS7$P>`!r$f0WT2':3 ݰ=iJtz+3r搬 ^(nQ-fT uܙEԍu4G(/"0ipmB,{ǭՊDxr>e~X{iTQ* !B?%1)MPtG{#J@ #R w+<ƵɉK~ 4.sL-vS>|:{Ô8veg4u#P "n*?O%g">F0ZaXcUN.JM"C$S#o>G2k)bMZY#yrd_S1xQ_K0|ϧ8mN7u Oc4 IGƾIj>(Bk'dn?Dg$GU^5hdS6^ȋ-<=QzUEAoAfIVW {iIn}-,;g )^S$&I{~i&\zV8/Z6KJevY H^F(ycI %&gdDŽL1_ cYTFuI̻e&*!nqx*{pͺ;qbhFZ$'j0T\*K:nk҉aM.H廩Axk{7(0DMݜ)rr[+ɓ<|ZdK1fM)ߺRsvygb BP( 'gt<OѓGO(Ulg*I?Vy噊Ox x f(r%4IFt?%]2󤿖N/ ?ºjs5zW[ͿjjQW(UUGm/G*d^N8VYzDx[ݦ3Տj s>cؼt t [ogA_X81 SP0or{^P~9u},4{ `L+n0Fd_+iqk@g(VLO~fY{p4U Fd r6vf_I]Φ4mܙI@__3t %M:%`~><9=}G$, hQmcuNa~K'xUX-;GO2̠+vohjfYZOExML|`Nv (hޣT%,s%>M^fd 3ˉ&]%t ysƈZW)$btl@Ly# /IF2 4( ΰz ͸$V=/eӮ?/xȺG |ZKހTga9Ӈ"K/TjВ ±NbDm$93ᶃwOȲƧݣ難w!bAڣ4#,چ0٣Uw zLAGlkjhTmPۻHRIe:Ob>oNNwO7o^~`*QbkYWo_c@/;~Ao'P 3 Iҟ~::qntxdOC9- 2}e"ΈVmbx n =+kkށyB6b߼;_#,ɬ>z~ň{3HOXhC46*[ LL_OD6<`Ln(^~>E10 & 4?,#J?X|[`2hw=] Ј [Fb/~u$-1?f}$m^vx51LoTh ސ-ьR@SM6 04c&dC\I#ɣYzm<X1(Co>M]u+.U #S7<=Z_ #SohWd.|1H@:q)H ~A|m3.Lpօx6 ; 9V6#Q+0;ɶZc :N\^$Vc>{ÉK]+6}뒁MN1/ڄR|`{{!Mha+ۯ1oʪ6V-/ӡ\D;[\fEe$-whY8tJ0KsRB//fAu7\$Pw-s];AzNcϷ~^5\H_6y,{xSWؑ'*@MMRQhPNRH<,> R3 .}g=<T`ض%KvxcG ̅M Voa j;PD²n-6:v;gur*\R@Ye8Mۮ># C^J'b(M3-GL6ev1Y$Pke;į;(lȬjIgb)Y ,JЖ²[XRX;^~//-άpqT٩TbЁx rȌq..=H7W|MU&СgRaF6Gb *o z-҉,] 64#rˍ[<^S!dFZAeA`mR؛2:zCōnh+'%Plwi .Lܛ>˞G|M)TlX#a1[PF+ ͺED8^,BuJD3BRv"]}ǂȳzBWտl?0-6+4yaY\=E34H| M!HgXqyFXا»'U=RcaQu6>a*ߚk!ikͿ$BJ `;ʬNtl6l9B|7Φs ωx ݩ1{(88sɝ7т⇹uϑb-y0Tnl?,Gy4˦XZvdAf=&, ިuGʦ@#A%fc~&Y&(̮kfvUkfnE/M$KhbMr-0:pC' 'q+`!,ǿӍ Z"#NڲhpY,B.~jD)ZK[p=hW`yl[ygހ]􂶉\~ =D( ʐ=S.ybjtHJ "o[#8H ѳu/[d6!$\QSc$xrt<(Ŏ+_,O4yMΣLe'S0*(]|LDtx&X(;AȒPL{`ڦwRhG˗!߆,E*4zd#}88R=-l;5iXbղx(jCjqaŰpn|}-HyԩUۚ!9 *ڞJ6βex>T֒}ޱ~"Q'4qDɦO1#X8TGE+jtZY A}$r1"ʪVM0odW.\'q/+Ym|T/p /g2pciRY,:`dk ^.i>E  @"N9a{q{ F6U9(д!v_Zb.IOZEea5WJ)M,- dVE'\$K"i M%C^F)a.Uٰ Ya/%J܋^42bh%WGE ECfdF8q}uxi_Uu/}zrX]#Hun=R"GhmNRm掗߾t㰂Hj  7䍢|xn^>l9yäC:,1I'92Sq!紒1f͘,hIQiveM5 1m5M;>\GDGW,DYDpG^$Z+}i?ڗ9P$Yu76Ψu@(_%р8Ƽ& >Eż-<(?3,6L5"dO^0 џZ8{?Q= kwS>fa%dBES$r I7R{LWo~B M}Y6Vaz[֬[ɴEGta 7R3S9T$ENX){[{ 罕p;IBi%Yd͗ǽwx5oBX=  %c;qH)x׽6^Q k4%N$@D և{@y@0Ď@eTq+~UXcZmGhۻ2ntBHԓߟ'VDj6wgx6. ן۾m^{9;.wQAZr^YOWhµ/!|4p⥗X[amK:_RSM GP6ANVyJwd;Qc}_R;2жPzYGTc(8ݚԍk)bε[OK昰P…+>51$_mX?*=wݼ\*$՛>[H[pBG鸄 Je?qnIRW e~wr!7ݪ@MR@' ;IU׏:wi;q4|۷6ZREf 2$MH=TW W$z!K#JT)@ Au$!\дlSMrh'kˋ36ǸtH'ZkGR?+4MUGR_MUI*2b_h+\4·uT^qG{ȾVTWd6Y񨶳1S B* A N1"uk ӥJLgVkĿB킂n(d,u$jV}m"ŀʄ="_QH5}q'жmnՠ„X nE/W.4?ԙ%JMSOX+?"n8l:w{Ke*kY>Rns>|6Κc>ib |u_Ӹ?ie Bޫǽzi2Mڂr/(y܇Q"4){d]B{,o '9qF/) QaI(eΧzAZm@B_lr4y0?mf&0mฝ֕(+tnaYUM f"10(n67oaxޏNԇܷu0-J:ms*L~Ștܣm'cڃ:>txƍ;88;uN%m,xK^PďAO] E6D&gm(ecy aAF&q?H$gK%1-Mj`g3)$/!hU.3hfum;{|nH^N R49ߎ?Ok+vJF1p:AuSoK.Gީ-l4 Y!ZnYcJ֞vه0G"U  Լ7aI +վ^.ǝi @|~j< $+?0"pajoۡiUSmO0ѲB-@ݵq`:~)l`:{(x05^901KU4&r0WRͧ՟n9R ?ї-;e -v\ 9qWco{QA5|Y*@ n.Gu93`6mԶ r=C2 6kU0N6}gG ig c1)(pU&l)X!aL;ЩП%WCT4ЅvrGa-fBW`ۧxQ Fɜ m??į ڸ[EƩvC炐gƴIaldV+)smYe /+* fx|moض?>~m1· U{͐~CWLQ°MN=4Nǫ ]p[[l^Aq=96[~*E;$Xj1R!)iU`S.Aʱ*#T^ac ]QM֙UX DKX+xY`.@t勐0X%[h6DdnnVa2P_GAI NFq4F|paxوT&U9lt͎p,MamDv)U.AҼRMK Ąy7qgtlcoIPc6;v1bK0:zsJB#]PSLTQCcbW613N4ȦVLtcA$x6c!W>"Pr5;ڠ ͛{&ܛi2WWSuhuss2N~bfiddSQBm[S5ue]\Au)NwL.1 {߱ CӆMEk#-S6D}<Ne9%9L ^V1ʂ2nX >H4GaMVg':qb؊NSԛ1j݆1&#܁Mwyoi"=!2 sK ŗ8hW9O\=[=<>\[60uKWϚe VZIWȕYƖ;~h 9Ze\-ڐËQ =ֺ_NoYNounmCB1X_ hHaeg&3Y)紀F-֩b,-Rx]Һu+upJCM4d%cfPBLe(|@]ϪIbȨCfe P_V$v1,NI%4/eܦ>UN=3˲R:9ӈ;9&|^vX}v4=LA(̀S'reYŏ*ze%g@մqkv+EX q{*FY:#$2&-RT +}gIx_[V*vuV/`B@9f;[//NWrf5u`Z2S:N7ª&֖P:*tSF,OMUENT*^}BWRV_Yͻ-N![18ʽVzʼ)vMrA30|X ]}t6[l Wvg`)Vj,6B.A:REXmDz^#Z-5\0* yP9˔~܆E] /XYT( &}G$`RUܖ=a/Q)5+0ţI~)Ėx#?MCg n7' xM*kH񉤰)2/syȆ5ql稁ytjF/Ѐ©|#Sw /}+Hud.gZ' 5ך5l`^mzfLF]Ǣy}JMT ygI0g&P3N0pڊyy "$޲E_Բ4sR?>74'&4 `#κR*Ai w0hiusUЦI(wyѧ(lsQ`_L51e'0so6 Kmb:=\!gfoȦa_Kcju>:rɂs8|dKxM=U U9dz']&MX7Vƥld IGhqj-#du%3/TO(YIIx?x4(<+{NQ/-a7!=|==u&k ;ĝn)^Džq(d 69o@",S4[dBh/N&BbG2!KCP-dt#Ѯcr|gNjR2J\]k\]@]ebr F6GGAOwIfTA& h#DquW]^qvW(͎ i[m axp泹ꪝ7IxwN8D\s0f{՞+,NĞF|‰+$m<+)wpxWR^!%.똓y3%BVq~r{`B] u1t"?] v՛O{o&Î2rȖqZ dZ ^\WeWUݯkD\2ЧEK(O@* Oര^9<|Pm^oͪ<{ΰ!OLԭ+}ݺ͵ٔUxRLu 9k5 v4*jr;YbN7Xcڨ>F [.[wr#]v_>VWHn`:Mo`ﴫN;B ;IΑ:zvM'N'o{X!W v=$&8ݵ&Kn{"+l%c8Ipr5jj-RAL=Z@ +v@jS_40ntU˸As$4?h!p4Xtk,JM_yI5F,=5 ū59Џ53~)ԋx63YY~qUvי99\Ly]BEQhcPm8ei_Ҟ*e%qwhK&'{;]J&( oᛊ,API$u #dv[g6b֝)83Qt"t]JdMc+ %,Hr=FηlXY 4,+ZD{3<X(sxQ C,*P<ڴG6y $ µ1KiLTqaU~>h5x6 FA*9z8ӵQ}?lqJ RQJcK3lil=~pN~|i" tr  4u(5M]U, }1X6R=JqpKu0:]$$Ό2ÌmF_".ܶIR969NđrL 8)rXVPl8\.w/Sk(ne]rXeemnrQl@[X:s&v nITrF-Kg0H.*ccj3 `6{9zfI~+{0wa]#%x =OgN.{_q&ܣl@+~g n Hd@'hL<P7L𘰐m`c imm ٌSBgcyI!)rf$rX ,GR0͊>w@J =eNnZ~8qan y{ `I>K61kEY9sXtܫMSh2rt|xڃd% $Q,Y+˙ievXmApyneR}t4UW!Bs8"#Q0Hl8F9W)}4{Jd F0GtQw#N_TNĩ:J/ycH3xf6n$˘DP',Omj{ <&H/Phqv=zy+`fS3SA99=<:{ ghs/luμXQ?ZONvsT?LSγdWur A>< `s'Hs!˘$X!d r >,B~!l[mZh-fQ%l<~p C3{B{L>d2%e[b6qqh<یMʩR9!t_XSbNWiF, 0rFJi"`%i9Ġ%:Cz]@TC^,)6naQF5cμ oh iN-]ʭۛB/|ђrir6ھ}Ne BHŒUr.#EbH`$׸͑1u"LG" ZOdC[o/'&H2TNS 9_ED؜RE*v_pR'*zdǷ{_ 9@/Z3؅SMO3I/RCeo8d3+'1ыh8=C# wbzuOgdkfƤ29ڮBFEE[@eBS`V`D' 4i?cZMR䉙D;d~\KĽn\ Z W]g? u`>Ņn:럀ccX:kp}crBRn'JTke^x۴~-#\riu笮2+1gzؐS6.6fܕlg'Φd})vݹይACs:qb aڼ~%Ӫ',` ^V(G衕ؐ*Gm+G`{̾2kE^VgPjV(IlB>* 'eݠK?l4`8U;(FeB;O;<g{ vs*%L76{}třQq;vKBxM 6C\q [h|=jKSf~' '{a==G6h-{ bu"N}qat% 95I.-Y"VQ,lYl]ZʼJ91c\d>rMq ʡ9$eˊ&Wsbv% r0еȝ3ߵpQEP +;s8 Uw,'i^;7Y+Kf!8f(XYv )ANm(bՃɳAй  BұX1# (Y1S!߀Lze(s,TK񿧙!Q@V.ZQ SKܬOK/ )~tM{v{E|iHгg8AP86S%:2sF(*_vՇy6套~GבbWHm2!̗ŜE4KjaJ"Z)q4b`F'D#x WKĢ[L*j Ү%_Nm) gB\=GjXoFFєtLSJM7@ʞ9Lʼ} iZd4g!:#oEط2Wbov߾?޻snOW+WU[ήX-zZBuueвqK(o WNN`FHn8ug??OӡI2pB9:j9jHov'l<0-Sb]jH*ľyY`0W,WߗY,/5%c*fa=2S W`6$tLeDŽkbAU02)W!3ywq,r:vt|}v\ I n\:&n6 -$JJmBU].AWP B\V;BU]ah6jB`-[' X0c *c ~*_\'ۅɊ 3:}mgcbSwtX"?V챋`o j.{*c˙ک /k"f!| [;͕jM\ 0u`4%Ə0#hJ坮)0'm~46}ݐ0h*mk^8 zOJ>^Ǔuƣd-uWg9Y=tT~(i\U.1Vzr- 7zxnNV651$AjO.7<~9#9%\9"Y L[C2qZ|tdg͠ìhS?HyL< ]j0dW&-?i-A&E?g=4Σh^e1 ՙx';?krf¬5I6q+sT8:,\ `T.*'WQ?7|M`8D{Ͼ x!6LIve yHn}by@'5P}6>TN}D}B6կ$'!'zz4s(=yLhCRȉ0ouNN5B\J EĸCƗ'Q+FpkdJ+044d4UGhhcuC.})D)8 Y o :<~:~u5 Cyfuc Umv>~S$D7-_Eɭc4 jp~葜!`kϹVkT͕\*;_ONˈb|@Ni:Nw\1r Vmw $ JH5Q}Z?w <^LϜa`#2qYMm _yӥ[X8:yݺ7R a>dz᰹4Tu)]O)|c* Tsx^k4J#4m0KqwO0Y{$;{Tl!^=s(m?س0 )I;s\:̟Dszv{c~yF^&F^7|An\]l'G鵔t>C-$i\͋(Sc `y)1L!0! fel+46.WHhzմd@D}aRf V:|4NoQͣyapx4l(DIUzpO0$^lq)Q m-0pԔ[>G^Y`Qz^ B NL TEưD K_?NVC-m5\7sƝm3b%ϿFc9cET;LVZu2|>:k2#>;W3i`0%DC?SO {UtG7'AU+ъo$'HAО]L[8ndӄW_auiJ3`a0_X|Ҫ^.x-ǂ RfhCuݻwd6_e7>9gZiPzc78)a?F^s|#v G/0viw\1iyx?n~t΁0QDņxGJnk~ƥ]Ǯ޼JaX4=gy:P~R7x\eHV[HW?.:g~e?==rE|ܧ_ʍ(*4.,ߥT"\#(#jҡ$"bQ"|O %Ɔ9R$k/(X@j6Ak#ԩ2)bLm\39CsL[^xe2>򔑐ѥÆqNˌ&[ 1\l+Y󬼲clCdx{]]caP!RcdJc01@!q *ZvztzXO ^!/Gl>d4 I~vTN(C ):%v\idh9q%궙n@@Qi2F` JTh5EJec,&ZWC㎌kQo:hQai]9.މ)W*zR?㌛傁ܩ9x6;"n] fj4$OVI" L;Ӷ8є<EӊJL#34WjRh V&CeqVX6Դˡ;zqq* }ÀF-PyQ95XnwBӺA2=O̜Џ8 ׆}9c{.b1Ka o`MīoNeJ]dNL> >i3ʂa'VQA}L{'-ޔ& D8E^Ҷ|%D;p/ФO#7x } ^ݟvq3z+Se|>L#A%`,G6]vlڞ.bDN _̱p,m_ E9K SߨxLnx| <%0&N $;<^ I6ޕ9.iO*P6ꩊy%{I`7I uuML Ṭ3r1RFg6^ٶ}?h'ϻ'?iܴAX^T|. Z3U+ #PtA>YTc=4qSA$7EXit>ĉ ՀCfW&",U$մ zi{~|\ߖfiߤSM!%Nk6Hapb- q- 2YjT ja1܋T̙@ކJv6:C+o*WUΖeK׾ӡĠJ*`Fr ]- t ?*4Z*gwYEdg.6|(hβES_ay 4|O;U8.}IFnvv6:hn2@n9̻>O 햖K(pԅU<Rb~]|'s1[6&ǂV:K0+mkU]4a. D(hK6ŕ+2{A-?OP%=E ۺj?m]P>- atf?ᑇ),$m/6jOKM7㞙S%U=u!(6\&XD34FS:*x N#:J_8C@+Tc=k#'S?(z"q&iӲLs RY>{CQ$/!mn:{ D8, au)pRd1^d Wz%,IePxJ~]PMCؾ+%'`ArЫ%)+n|?OfXe3Zz}ٍƒwZN7`N/wJWVNI:𖯅W!_~Cd?.#1ZH|i|s Fi[*nJAE3>*>o,/48{xzv!iW^귛 kphv]~F#PRK=}tjoi*N^gR~H'YLrd+α9zyϞT3Žat+"*1ZXen#'dTN8$z_ tZ4ݐxbhX79I3q㋥')K"ozdnl0|NlK gמ8sOW)^EӪN-\=7sĴz y-S:Y8ۡլ74 B#7~I;U4x eˆqȡϳR[K! 'l(U;c47pQhrn|n=bh0jSvgޅl*Ɂ5@ZC/zEySNjl mގx8½B-oz ~=3P)Mgrڤ/(S&Gh /gZ%ԒN0m~gYC$RY[J]B?e:UvSBcm6տ% -&EP3bXBcnXU[FwN޳ a=%>sװ*kְ(L`ad͉o0gwO$bwl}IpCYo:A_⮦&tFӴƲMqW9)x$#a`-tA'uB_=CP.3l *LLBE*srb::ӑoqH)h!]J'GTk d'}vƷ:sLzʸ~G8Ioue#O.FBx>-wͳOaclǘį5% L)UdFb[Ϧ_O\} H \+^F4H~[:qz,Ԕ:&̝ޢuAY]- f+v3b9] ez*9'SI((}(B07:I 6*0Oh8Ey: 42&H5b`wW >~ՏO?ghҌ`\:A/_C76ҔU]X7p-}{(GxoE&K*W8wSȌbn"٢) U ;:>ud/zʤ EOߋX뺖Jقӑk"Q_@Z}PXO( LbLHxs&K,ߛR'cXV[SS+RA0bG`VSFG A/6%ǞP) :^fbLJ!v qxap3bE%k]~)o %sN z\^.vc;a׵meLADa`${C$v yձnBC$a~'q1_n^y _{ Bٹ}^:-#`4w `H?I0I_+S-{LpwQcɛ]Ott}7&7XsC{rѶt rp bq"|6E^;{\>K9-g4.Р)$NYKkk2 ~[ 7w 9wZ wu}Vg!1n6=Ǘ uW1 BQJX}+H;ۅ^]S>ޑZYoF~CcO#6:AJaD&('\ćNya?4 ;%`$)&pHxb2Se9%燡6q{`{:9`*K!]'@ߜ*=\&UsY-B)?T9D;?8uPe@Dv¬҆ ~>i+,Ht?ɭ.G+,$eNx6AFs."[0_<{E!gH ضkqdpf]V1^Ǔp?I'~<6#DWjg#w4?5|t@,!.W8/Vo ;A'$ 6-.T{] h||W=H'C{_` Au{=ѧ9//F*Ԝ Y!#m%`̄Q@C(#دtk ~ȯ4JobъWU/lSnum?\yf(t>K٭_80,ڤS'H$v_Z<չ&$Z1EVpxS^TȥیX/;|o\xJgLȞ'Ix~(hxL{ɵ1 %n yŋjx:p$R.Fd1VPRhZt y9HJ"PIn B].A_\s8;#b˜粥+,Z2\WG=НD6^l+,6Vo]FHPb}r}32t#&Js:P'hwPMzVj9-)S+CoEI9p]cѢ:qg$ \ Y2cO<ŋ/he0R`|: QR" y@ f !"d,cAeusW אO/\s*~ H4A?}D#~g:/;<0u_u|0 C-5 t{Hh,dy1GYr-r8tXt:L;>čY>R4)CWEc4)33uX /6^IB@"&"K}F8L e̠Phh?]Jt3K&&Pxwp2Le23e&,YKMm$I~EOZ o0pF cIxsU:KjI~!b<ЕYϬ̪|84Fe4[%2UFE(ft [h*aҜs ws."kHL53>y`*-ܔڊ͏G 8NVTZ@B#YUY>IGe.L!oBeG2աiVklDYLj_ @PC$m,oi0/af4Ĭ&]\ENAJOQR7c`#wX(=|:>+_$bX+.F+Ē-d~4Rحw_mu2 ʉ/T48 =H+Z"5(&.dq;p\x2*BǏRC+j4@.gX)CD0PJtOjeeKe{B! q>De~;Ӧ ݁>IF^~初Vv.DY <ٍs$pB"7o]Ѽ78)[>(YLbvΚdW84PV|E`*kZJ^SV|dOͺg7V>[h 7_Ks"-;*m}DuAWfW vIB=?W:| 0D/ L1 >Nq, b"6cVwOj1 DY1C%IQBϐdt\(#]K޺d&z9SGCqXeٛ~xaqKua":!G2|_^l{oŰ2lU=>[3Uv;om^< Jaku{7{yl6vfWv IIQO]bGN(Si>vU7#eT-A/R^{߄{&+0Jnk/+hѻԬcK}踽 5mqh{t߇m\yV'i:|ᆏGP/s_:# >vzt|1KCa!v_\+2yMxMs4d?~ >?u>ߟ _O˻Zzm߽9<ap_޷1lX_[[f%L؎?Y=rXy_ zB>?̪ӿ9~ݽJ;qÑֶ_ݺQ;(XeE^ّmş@1Qt [L32o.x~u$ dVL<Mj!` ܂rLW<'ܠ6|vWE8M-.婛}ھ۽k=-fת '6.K?~`reF lt[aby* 2YXgI/\rdJQF34)KNK) &׉J\lOJSgW2)@lq|O\(x 4O1! C{S!*{䃫!4D6/iS}*{mTE-t`4ͣ0W4XV|H (Hp9u0vXo|J{EcsnsߨF~1ŴvSwűIiC:gnaI>=,Ё48k"Kgl4P%+>'sEO5'9EAbՕ h1ЕLEqÁ4H-0v#tƀˠyR E HT!倁:c$BX8Ȇd'\]cti3!0dէ3߆{W{Mwd([ 8x$S+R ы'6&-y 1>+69$ᓽf`"-3[gzO%D%2/ 8q\H #WlGq݉$x=< F! (9[ (qcH"UTJQez6fOFx~Q,+ =lS 2E iGi;MwM ^Źe!Ӏ[ eSŸVb 0Oao8wSbAO ť R^а=4C-I %)E`[JXJk!̽R 1 CA.2 m~R #eX}:3n_oT.. F\͵kiN""E6P1Ŧ6Mp뤰fQJ aQp9=3^x=b%H|N _D@a^=a Zd8F`7fLQ;XrP=PcuFmW9L^fc.4yhH |jMꜲs'k(F(h)4R+ڿ9+v:]r&C=_zG=je&I` F h6ŗJ[w7"Yv-jww@yoK J)dHȍo! IwP Z`)&hB{+X)H<*l8ٺ+:l{b-e춰>b hAT'̏%`2) ,<%lj; 28/^np!ilC&zwH Г'C[V{[&l'#)^;KꆠA" mu߯.5wp2yXe*V; !xpY;uwYk,YLVlM/f~BuaHt[ 9 a?Üm! ?p P"'\rVΞUP/qxL8E,dzw邰fB CEZQ9RfdGj),P@C؃+ J(_3<[.[I,z}3^Vfbmr6k^`kd_E"~ ?wqCWAEo0a>WpDo4-# j$=1SpSމpM"Eo(IE?֩+Zg&᝾# gun=#Mep❝uz}ɑ йzі1hhR^?_SWu6t8Lt(`m(!}=GoITٍ!2YE\3ecNo&bF/u0H&iDIÙ=AϟZxiy*Qы&·{+#kߑ$޵i,l]了!XV !Y {?A0اE㙂%>,'bNqpm'yx hщb❱MNm+Ytb^bȉE}HΒ㣶gTsؔojzl/@1}47Nĩ'ft%,i3cCg1"/mTSRSL{Hܑy7:(1i?:J%Srz׵ z{ VDq%Y,&u{ u4nQD*s*p\))LJ'&mO}XEQ~kjAawr(c@k_C5rbZs'\l#3^4I(rJEG@e|brK;Ȯ t5 z0 #CayAcsD熈&__< 2 !1|ON&^c0ݻ^ϟHj >g)郍RˌH]'}rŝ4 怜5OX;=k\7/@20Gp}LfP:#Zv{;^I'9 rYS<>D0tBy$,Y60TU 7啕]L5]SQZ"QrZ^HD}14Z7u7oI /SoL~&,/*2NП"x i gdr"?!1fd=O=7X cBgo%saMTJ|*z^U#vo>Y9S\fUXXӞ{}DɃO[fJ[= 0G3͑ 'F|!;e uս}ێC xcf.<@AJ *7d%*2p2j~M\]LgR5-XE٨FLc |{,ȵ@J6@/#֣_ z;3CvyǹOUe3U?uûC&-N|E cSK[@&I)U9Y&Wɪ?iwe}y;zUV6era*p!,0W2]ddR&\}a?@;M}l Ä5Bb2I9E;SooKZgm܊jD @|lN.{b9mnMZ{Ź#Ven5'=Fc&N2uw?fEt'<ńh1`Pփ@7*wQTd|&ٟu|1yu̸s\A:4 M%7?$bhI@C{Ph zZowzvNnhŸ-#e#_E.2P6pH܊)Dax$ У3^vd!<<y>MŶO'Wm _=ZoG{',$! 9c2D~]b݃YXfxV^AmY]àtÈف+QYncs[2$o,T|ո:b\#z:$4y35VM[)=]D8ӏop[?hΈxxU{4TypCTcj51Q""Mc\f޹wBh{LOKPYyT-VӃ:;~常x1€T(I(t;`ǽ}Ʈ>9..(2e0s%ոXeQ;~/ף "M,RmLK;3fK.+A,"5> ΣZ?әԉ.^C?an-ytlD8ZrU]BFs)C n?S.#1ڻVPwhRd@"bڽPa+}qwۏsX. o`F##ܖD(L@z^YU7.pM! Ad"1\}ҭݺB ñ !Y"ۊN]Ȭ@>~TÒ ֧w!(,Ϥ/w2x, /eS;9E{,r|EB[e~Gv-{ WgN|Vyw0XdE?=mYNօ]_{D@1/w3^H?=y}K5Z1zbC^ug_OWrq~vZYaoԸt ֢MYtjCa{{m3$e{xpEI;;5B9)sM9V1^6rd!AU$%hwp bT|q Vj[Sl'.)_P$R^6C5!1HJ+/XWo k߿ .Pbž1̬g dEǝa VFXoKF{ b3Yz豱g*CT,p(#!:sL87wٛ\rC:jց4%(o88ʒ(( 0ʥ&\yNWN}}/-8DOH1ۥ6D^m- XKT;ɖf[O?g&R! ˵}rͭ5Y86 q#|TlXe!#Yh̀R,!A K&H 9d6SY2xuQMo@=3bs0 VIcˉ,YɲZV"|f&+;p=tlβ{*/Ou;)x#. _ +^cd>X+S'HIsxdc!!ZEcL48d2;(P8B\ȄHHTzV/j*e a兄eG˞zz>BF 1S+1 2)u6u*KKC} 4}b JƐ5ڃI~dolh[퇦-v7tGcwӑ7Dd@S9C$. s,/uq=#6MR"v\k?yxX{W[>6xz[(]REeF8]]A29$VJon)ai̛ƁTA(  qA$9s:fSČ-h)ӇoO:nX_6̟bKPyQL|\͟خX ᳐0eZ,(LZbKE01ɔh1,@ҞL=A\wMYl˩䭧|r@Ų~-Y%XU('4L! twc֦JS0qGs- O#!'@p"!Y΄/BۃhCp2Q9H+Ēvim*| BPI"MB-&g+?#FòKEaCEIe3©Ggj!H_Zu65noŃ\,b*Wt.}5Gfkܺh/X͐NIrP- ,?`nwDJ"5g@n%(w'rJa8t$'A?g xvLeZElBȷ dŌkZ;1q":G*ꟴ43ct‡|X8|R1La}KufÒ'$MT !~Vx8_Gmnގ-E&y}\p0aF@7CtcI4=ì"QRqXz/lPpY/~(NkV_=є kLD*y8s}9X>WֳCf$5y z>Beȕ+!}-+ofvt"pRc9&5u(1;O @g1IMG,U!W=)"6NkLwPFbB]iJ?~$L˓" pSZ=Gl\&pZv~73!,  cO\ޚ=t@u QsW%8ԙowr'ŸS3#<#`%ۼ1Z搰=O켦ʶLFJѤ +B_쟷gCQrq1y9-Oz2!̖XpBF6(_-z0@<x7Y`dp ҁDh+d3W*~$W(gYJ?]$=G[c_ T>IW`rFʃ(^>pa>34-ɯE2H/osilX.q^tgjdK)])@jr˖Z'-Or7qtSmcny+6` 6kv'%b4uׂKjr KG݌r9 Yq9B{Q_<-/h-6u'ś"H޺?L|&F Z o41p Ŕ,wU `ڨ“Qm;"tE!+EB^Qдd^\JPev#XyZVע5zE}8+^0މZcFdŜ3  rfrp,BŒ{d{|mܤ8艿>&p=~*g5EX\3QoNȿxKh-x4J "b9xZmSHl 66$ ^rqX\vd+E(JX,9z\,Y#${aE~{صgIn]c"BV^#kAHq@ 'x$±m mG mKBaxb0\ۏil;#ݍ\gDa34ݡ7:7-)o1" 62~W4 .h4>$3bp*b}O0dY"WQb c1OAwL0pspMH^cmGH|!Td?!ϵmv?.<*Wl`M=io`Bdf09C^FP,)-'033K rxJ/B2ㄘ$I#"M:g;Lq(8*Y5aej-ȋܪٌ4ʳg* 90̵w.=v8'8W' rc(Mx:/)()C6 mam t:Yo5.)IEn@5YܣiM(W8ڦJZViW%o :[JjU(1S-0g,Xvлk|hEY~z6C# dڱT%8jjE$d|Tդ@s&P(spآ~%٧vеjlv>\6ũF星ʧ|NxP Z? YVVbitzT 7Si 4;yQV`E^`w79S)?+e`Or nQs2t`[|o-Փme=5aNzBV.w]V,< biZTR㦋W!$\ {4=DjЉJԘ~+dW<9"qFC7I(+sqq2.?O\` bEI22KfyX@@YzPP x$e凔5'Vg8u?˥S4d ?S.<ܜ <6OS PՌgGhK*Cm0RgZ. ew%p}2`GYY9df|.5+g BΤ8S}J|^?ЂC+ )$& xrP g \9ōky}U㐏!?;ץ_ 07(ޘ_|Sߔ-bEoo&_\ }hg-}-隊u wYY^1^%V{TrV~)n߉V,қQ9tyK. K rJ0.\IQUV][߼V@.{ W *wh^rټ#uUc>G;O͚zT.e UƆn+q|w)-_d.6rrbkJ|ݲ/gDuId+{0E6[jgK>7xD}B) ԕm>Ei_DgTEE9RDMq1?]bH¹k=yϲqYe}̾ɼ:sþ6Z94He*"\,kVRFelrF xY{s9>E{%&g.`*ޭsȠ03;ئg]3RՏ_?$m&2hE";K!(!@^"BA "^q61k`t< ͥ5eA`" NHQJϤI2:v#r:'NUx)da!%J:s-"ɔah {T饏53rF:IחEH+y~jjKмWDPC^0ҝΩvy'Tig;|tpRlZUn0Kؼ"cɼ'ꈫXDzl4BM:9~+\'I o4va$ N N)ڵI=W+fB^;Op'8A[>;YEbzB65d/3zioPY : ڹv|v7T *HOŒ A䤞ܭoǣQop68hUzw{9}3ymF)g 8`4D-u[\~4!_ vYy%$9QbY6՟U8 EC vS7XbvwCѐa:3,*הBiĐUUD@_Oy$jFX!PXX&N*# C89JP`4}4 4[G(vw:ZBD˅ ׮d8T9 6_1K/6wZ4Ǫɇ"Dj%'a|w2HnqN+.r}lCN{4F8ۻ~\?F l\cTze5Yj[rIG[:H<ʩ(42a֣{Gb^oߴ7VH:pܼ| 5 lxzWi|cY&)$ ^:|s*bʩh oG Eqp08lMr+_O?[)f+pd+1yߓ.ӌR>ѝԺAVPޤP ww {wͱg1QHz9܉B"ތ<ֈCL@U筏5jr5EdzN1=5M&+5eY{Đ%щ!6iq.3-"Mv-a2V6˳IhP: c3ݦYP%zl-rlstapoP,1o~@H] UL|"D|oժrGkR]?vtݏ*$f1x;v?dZoT,SwXҨr,:ףbڲ`-qe&䎲vm~]#ͭ'5E_hS ܤ7"EI Z[k nzKF7k dlA>!L3УT^Y [캟O '} f=0RbM;q?iX6dcOV8/VN%3̑bNiے"MX43kҏ6?Y:۬f)8abpu:Ag%CJY H^Zj kP_ G<&xu]k0+״ba6 y5D&I&UKب@=_#Au *.K L _HZ*6ӠQλ>@.XwURTh+b%$p#te4?i,ym̙T $%\G EQtqTo& k`LÐ8PVi~*y.$7ÝXi Sgb\u!]@bСkwjrgoaJ Mخo_,c}o"`YSJ%Yvnٳzܺ-Gwd}a,Ët *Ea3`9P-!ن420'3H4LOa<-F'L~QDAo &Z'ö\^;ŻRU7Jţ0F(\&eo^ 'vB;!I6f1OΚXvnQpP[ Na{>!Olys`cksssm_.XhDwFii־ o6nm?+y"ۇ_ư*6ax$` ޚo/A\K"5pXTjX"ONϏ΃Gj|d#v3M?NgcG&g&p|иkÏ She4r21='Pa. {71MSMW,zOM8+fQs-qƎL8ZD0<)--RɵPUPY1fac/ΎN/Ng> ?ab&'ۓ|؈iPChSFތ1J@M)`,d#n^:S#"Иl[#r`VD !6e2B3}H%9e8JZ~oz:4 P6 ®:Yw Mc?P0deG_W*kKb.tCLqq'R G}x5<;0h,BKd%CUvU@5@יMHf!Jphrl02OkĚCr ( Q^.x' KDҷ-Gɔ\-cuVZ.GF,%bH-$ 14 YoZK㑙pCނ&yhQH2d^T_Np;8^p;QH1nPT4(Ea4Z"1A` =QGƅ E*ۅ}mL0M?MڐHʛ8A1R._v8/do^'@ڄBbNKVjc&al)869 0xAՋVfn>8G#[7RF[b>vH "3rW #ehP"3/:j !17b-H;nELOM1+dZp6А^!g"ta*A}Nbf٨݀WYS^ Wb4CJ+py,-YO"iE6Z H^&Χ ߧ5BHR:XGVz=5#6)i"1֩Uzߐ! G}A=h|]vg HRk &NT6(/rz\g>ڰ! 2jwMp8m,gh^b KĔB9XP+-1! I UL^  .w&:7b0ǯ=N?9ni5gq#uƤL?CfS=Mb c~|=BEXzeD5L\o} !!uלF&/ dzvێ1LAM%{r4#!dl_e ,7[^9+b"4dWTKpB۰bPx-$Yq9zyFA讴[o(N9ئ5}Xp  <^BHL7smVo܋m`>CAq|A9kp9fqCv-Z==l"YIJ B$&OK5XݮGn p$_7I7CdM'ቻĩܵL3P:hʽq9&JG!]Yk&y4,e*bOm@Z3:lk"N"$T\^=ZBM-'!U Qx$ɐR}Ȗ,rCF+\QR4d$P#9 roM<31 9p5SsI^T^H(K|a8+;%ق!41o6 (Tw1LuG)Y-vm]\DUx#:=ֶ0={K1-ٕJ9|5`~IL0,#ze{7%DԮt{cSYU_мbjT5KID0: _ҨVIv"˶z ,/ X~VI%X%zf2aWڃg_ٺ+zm^":r gNÏߤ4r"n9vc-oCfZ2d!ͭBf%^YtRoɄH7QB;dmMuknbnT2pOdxLw06c9L+;%IAZ4)ʳPND!$SIa?{4MWcpF㏦ teXk=M{ `X)N&Mt!~;{)7(?k(xa- ΋B<7& D, ]io{Zۧ¿Cg2~io_;>7iUAӊre24L Nhϲ#V;z|rxvvr*اCc^ٷv8u_ZN@J.Hm}6UޯW-GstL! wW"0[ %<q %a+ߏj@WUZTOŠ4!<­I-LR/r}>gA R#3uddȅ~8iXdmW: @䕤{A laڔ U]/;8&c ҋ^59$d|œ ʅDᅣ1Ҧ!,VM!}ӾrAW*ϾkZ甑CKf}.*]!Hș[Tg_|hyu\EAPivvlz62(ĚKSX㪟Suέ_eM)il~3D52ŽB}„}e͂FQ4/$*г<`-D˃7f -#.F8WJkQܧ{@Ք\#UXW_~ٞgbyZ1QU@#"_L~coFeʫk<Kա``Sa~jFo{'|g[v{V2|,!6Y+*ܻ*xαY=Ug4KꕕåXa7?%ΡA^zDo+Wl/vQue5~)awׇ;%)r)2WյciXU_ծkG?/[3'WdYӾ`9%U2R25{vmٶ%pCxYksG7D@(FXZc=l$)\fzW 3Q~a;y[/*Ne]4t^:/)Jb_fIJYBK7G CA܍gBiJڣ"!u{#$9>H͡y^+lzu{{u3=,M9ZP󩯅&U*gZm#G\*Z,u#c A* ><7TRe ]% V/L$?ލ蝈EtOCѥDo\4x1zEn&OBb=G*BeKIjش܌O)Y6^QfΗP듌5yYsK4+arux`<n?AGahJqg+`x\Ocrxvt>t3O.c\O;D +tO_d UiYAЧ(nOG( };&L[ ʣ}IKT?Șg!6 80:t3 xKMz$g?Ko1Հh~dÎ{4\;Ζ\r ɇd8q-t>4u%+=y@NG?NJgvx=r8“)ΥJ$g3" 2ĩhR2u]im2 9LAL(FщQ8blTbkD uRцtCX88H!M"@0JhRrxd a\BR, tW)2_A<|Ywuve=s4( R@]J9E̛rvqk`p\gϓT>e!zk#Y6$:)S4+wji 4S>JM›PX>7Aݙ$ ЩJq=! e*7w*SṐfVڢSn#z. _{“v>0q&J0g3w-љxz%\\NGwwどT6CYP~9n'e|:, iwKrhׄn^{w`v;ŰY-}hX1 #tڽnם'γlwYt _^DePy{7{*Lܱkne ;g;7d'5*c K3+=ɭ$fm}<U1ROh/3YS Z &9enA 489whNi!z "1xHI4I3C=I&K'\XBuV8hϬL֭{nѤ,6sb3GYmt /UaʽKWDܲbaAvvtv;9^9 ;C>:0o$:ޠya`,qRoZlr^ cՠ|{&ziv RjXh ;z:__O8uj$QwDĢk4G|FnφnE`Cxr_h=Ař!Un6w_9ُ <"6c`8@ƈ0U52-hmF>c'RMQ+lBqb΂_/纣5a181|qm ՌC|m)%^b -&";\*;ecvλrqtW S-ڱg?! e"ΰ <ׁb0 ~Y9@MǀHDS]q&*0NM-  [QBߎ8K-ǜ-NB\p/&b:'I?EK0EnuAøĚ5|i֡V Wt(;(B-S{`*CesQ|֌R6) ZʦE X(NfE!gAɿ CԮ_ _vYS,ZV 7/NhlvWH!׺(/~l p}%MD ؋(Kǘ0?c-IzRLgZYNcv\M6΋b`\{G{J SQ?0s&8al3+Qw]7:w 1Ncڈ ;SiMFpgD^pl&20m'}3n#ssIYXh34FA 5C.3f6ڤҘnid 5kNf9YoכzkI[rmG;Eo>yi#AKc7c)BKѵ4GTu/vr=crv$ܭ"U bNow`X壘= V o9,h[Y4֓6`&'e˝ hd<<(G2~Ӈ*0ʺ}=Xs_e,myxm)zqT>條c%W|]cݫ>c⠙z$Z|ϻ9 g7}K4 T[7j`o/Z9,*atPV{pڍ m*83+֜n66U2{+«ojP^}M:±+G#:Gg[6ի{+ i|_ܺxXms9 3&P ֹ`;\@AeNy}%xΩ%HjZӒΫP vLX ߳<>LY-%\;`S 0Cc?bΜIy7E_,B/gZ^u_Hί\ iGP+& |{wkoQG+PPw/W_([>$Fs.a)ka/_g1,ř4a62| x7E0Vb 3XHgp ];pI6N5r8O'sLq Mt;Ʊ] ˰b\M(~z0qS($i'N.LB9|>#husk0huGM4>''l/X#vjvN;s댺{hA5uƧǃ~oخ ƴ-he'&:洌4K ѝܾaH hc/Wخ]٢yh [g8x3Pi|WK-iQ roֆc|(b7ꥉ@,Uzf{Rc4tE lgUJɧR>O𓱆=&@QuZ3URen9^\|wTa`!1P=Bi@4һp9!4؃2z[E-VCf~PVzy:"p)5CC[lIl1k ૏[X<*"|cVl t?{|eVwWϔ;/MBdS&6-l%jN d>kG"kJn*?coY(s9ET[O(#ǶC13TllٟI٘ 8~KizSKۿptWH*T>OF}i3ݺ{áa6[?-'C[=0J .mTlE۳(LIY  O6Hpμ -, !𠍕df0ᓮ+KNGz{j12/O@Dui4o"r*ƒp!UMkJLi1R XxlnlTf\4([13j)Iw֫b2 ;IW,uA]wE|[ĿgRQ_|>U )ⅅWeMU=6 D=6ԒQZ^M&Svw#vsڟ e~Yݿ^~P۷-Q3wȗY1/[J탂7孨Y.(*5 fY| u]i'[ҁƐVGJkϝ$~nSI'7Aـz}}qmUx<њK߂8gxY/!,$ }F> k[䈗&x 5%bG#2=$:OOC_)j@h%%U(ĔE|IJK/1Q1.Ԓ|BJK Y}$3t\INӧ\Ԯ*r}XefD'[r[ϸ!}AV)nSd;)``Ee&D3'kNGL,^#:]s> OckW_:AsLs*eGHc>~RtgG)#6ӭ1[_D(=FaR)͆=phW o  쾀 ?JbgxWsH EG!9t2n7G|[)璥fWjf0K9߯G] ~M?~\̈́ϫa(\@,l L fip  @ӌ * 0@F^&LRDd:,&S[hy^kAi^V,@XR@Ѕ֛7%?f* |+!@gc2CxϪ4$Y$K+ Wi$#T5>T M,C,Cj*=䒈vQ# B⾂[4~CВl@z`~ٌ8]4z q`S^X6i6cMQ&t!n̵tzC {'.iVXa2eT%8?!SG?zpϽ!NG}`$4aE2g$L c: FpBޢFY:"ڣ]c,1[87`^~x@o 8;f~#@jv[͟G=<(V0 D,~v^PwN.iE:=0Q3%SoOUتU 'SW pAO,z7T4^g201Z͢ <]!ed]%Z'JF)V:Z\(2JZR1M =R. K'WhBBE5R&5kF _ULb1Ap;'UIDLˆ2?rb|t4|α))*ͺZ)1UApsνkTn~%nv`hE,=<; ҊTw,¾5d"cr/׋l>l;hR)' p>xقU+\Ԭc&g{gcll Fh_H]1]q@V,ɁdW2|юKx[ұ2zG,7r<eV+(k˗PkVjƭV:I.j-پBXAubn>i! O#G0eۭ-l}xra @o!(55ꑄ8S2 SҊg0I#-PB*u,+ dqJNal^&o',t4/1K 4eSE<#"}WkSd_Bdz58 BD-i,Nrr?!Gj䘦<؄X.jW -V" {3" V (G=4ۃMZwx>0d-*KQĿ 9ݱȨ,3C7l$.݊BNO\#c`oNƒmU[*xV4 ")Ob2@6T8nT55fmU#Y!tyx^ZZp0/\&WuR naퟹXʆVVFeBIg\k\$-NbSKB%)vT;lõ9TmϗfT-᝴5+-%x\ b h׺lnt `p/ As\Ғ#SQ، ӅgTi]$@u RD,X+sR:^R)V:$[[hل%D7"QR.2XJ}Y:˦;Wexr4p{E=SUm5?PW$dY95l[JhnZj z#ٶAi-SU*Nt%TU*DBZ݉ɡUl]6:R qh^ -=v^ZȠC pzK{X'6t9 Θk<s<[t }ķWeU`#9ͤ"='卛CbA4|9;0,$/;6vK>Sn!qs a,;В Ba$eMl@-oG%nuh&0WiТv/^ :QƺDQc'S v:u@vZznB+`@o0 T#\| h4}:3_B@nr`=o.}vfjnuCyn F&PdmW67vɘ])$R,% 9bnы}X He U2g#Bc#A, 2JA,ӋK81,i6Di']a 9N DqG)0)~n!%AHSg lk27yakAW"AVasNyBۀ 94vL.]\}שJ o $ ,Vk`f74x=>o8#ǁ 0l0l:qFMj@| 2 tc[ s*> Vxp 2d@xi S<ڇ`P.NA 66ci p9z4dFٳ |v:γsKgQ8ŒJT(7F񒒭_.Q u+驞Wk̅cUCwB(:xFh _,@dZ.aμtNlTdR$OP!UȭkBlA9;K\[ }`p*5z9I-Cׇ2 y(,01U⚯SmC0$fz[}ղ'? [aoHIC\n#myPs@6*4.%M(I~}!bzt~~udjiT!K*\1-G wnF,ro컯>׽sfǹKEi?!hMI'?'z1DKj.i6/zDNEu^ jύT)_+Up=+>1+Q&,0RBQSжqm ܁=m.i=eXѢ1޾ZU fwxc8,Rh ŅT(O`Dfj/A˘C}#zXuxy8i=j,9W\?J:2;VJ/ d4zG A?4~ITEs$B\cq |Te1 h\YV&"e0`)Oq+:6%KCoH|Vk?U^4G} 9޶}45&_Z{1K&n˅!SDeb9jIG?=gr#w@)e3sc×ӓŕ3~帳|{|Fy'&(=)5P{f|qjؗ藋p-\r\xiE;UMkbxmU[oGfbH4MN6AИXT-AB"e=WYYڐ}M_VR*UB}~`) ϭ *^wj'2+xj7˾VO褮-s͙Wcii yHyN-6)E OʚX>Q0:B2~8 w|RmgLJ;U /F !.낣ldcg7xwc~n˵S7&!)Rpl#^\(% <{~И3mLOf@,^[wį7DH6(<EPfęR9jvToMCCeܖ"MTQP#\AvIĽ^ɶ}h uSHj㇤DN]"9R{S̝֥b zl.Sn}hN( |Q4 t4)\Ә(m?fu[-P!V?qnXGs/(룼=RI)Yql0=v ykMI(oJDHlBWϐ̝%1xVmSI r`4=DQIB&e|فôTMKGcP x Ӆ6j]R@Se+H3!$<8K`#L Ê$<OWχWMz|f@l N1i8NЩ{^Q1u.І^?\л.:5 ~ئ *֫0)&l1#.fHaf'$.+JAѐX?&}bgrTakK; bs3} kQv#B@g+9,w>V큁w߿g[cʰ{֡Z,? p@'WʩoQ8StII$瑆83 2"mQpRB W-h14tn%,cIr6bEtEq2EU+iK>n\aP=ڜtK̮b8" 2/JG7عFo,͸0rBGG*?^u=ˉV&aTDHjDGHRe1fiYKjV;ҩ2ܥᣃ?ۖEHa!c<xXsH EGf7҅%d[)s i%J١l~3#!lHk=ݿ~*{yANX{p11-]X @;숧#} V`D<6ZZ \M ᩸ƕ@f/Uywby˯a3Wj]Ka@Dm3}pPdб4zR b<Mt4ISBMxdȍ!Kh_Kj巫*?Bb )hZiRd_ oYctHV+ጱ[\"pn0QkA1&k-] /vt޻Aܻ /;8;#ۆ) `2:` lF1%o^H!>nfrc*bT'v<^"%*!X@1_0V!Z &wDts(n{+=@è^cj%׳ߗxI6_\z_q^L㑃d4=aԁChMXB]\NOÜѩ=G%+v1$>8Ó Ph ?-9Gh5wqQg14;Զ>g.V.$kȢo+x˲X˨փ)) M%!2I}S!@ $i X`(O0<ē:=x֙4x8,☣F+ SYnEt"43vO.l z BDXI *OO30 WSv+Xv詼ARmw孍V*tn٩Dv(mU@Qivܯ^]m鰊fÖBvvy;^;+6MVsWR(ʢ# rZƺG c8ffH-ui,*gvr {|08Qf؈0X5L tȠk.-(:MC狄 aVu9Q X(JF.*"_䩬<],ok:J`k/BKKhkrC1t `P)8Τmufi5V Sv3E"MYLkێr?Yiՠka8 Dlj, ⥲ yL*}! ]C <-L1[&%ֿ~fdigͫ?k]fǃUw]kmie]Az. zx3@{DWY_6ZoS5wSɥv)]h~vѼ!dT~oҝ ڏތSpd>NwAVN!)c?S'Ts3>lӺZ L31qoD.Ny4<Ėj1<#;/KRe&YQ4%u 4㠉:nmrI*lh V4%z&K^[u ;䔌v+H#c b4H */7C5%׵ތS%5E]pUR0K&T6`$kd4,֔oY[U̔7Z j-2-ehCtuCF.)Ti7|ʾ~c;YxtEnʰ^Wh f (+Uy||.0?z\x}}w۸HȒڛ4$ul_ig%HfMZg~3 %essn";oz<]EIo8Xiqcu]S5IHGŵ*I;j/)ZMt\Lpp2Ld:ELqX\L P%T&*QZO¬؍l4⨸SQN3zPAy4S!a+>_Di2S[iMqX\&9H`;8{NZ~_>9Stp:}vz?*45óI|uFqȜcP] LyB 0NDpyQH%iEH u \[Zovԫ4/]6nmmml}Jbak xzOO{G隁/Jq`%`-q{g'Aؿ֭qnʣh+;fGHOt2= D7: Im VV3tPRf^q,S,pz<83]ԺAu2h>-ڗKpO'J4Q˟yKkycC kvI =`%E!;M<5z^` ?d2ܘ$*@tpDjU4u@HIr!5O+RDy2%gFc~zLʟ)=7K?*f P?ӟ H/@u_#Z@$moh+CFtl QwrcWwѼA|^8͹-i@_N{Ѵ[|,^~|z:_1otbvZPBlk^Ć A;N>aiF~V|/^m!SW=́1DfYF"NzLr7*/[@RJtv%I|)UL\&k%;픮:gzf<u;KDYL2}Rٍ(/tAp8b|T C5-1d ̨QAU#+ sNLtҐ#ĭ9L!Z@&6Jf+sG\#P@νt2aqIe#`EH`sj 2;#c E5fxpƀfS 7# B``hBOv SLX <ND4+` UN#J$?An7g+ؙ Z>aWV `p u:sROoV^6j@9̬<8>9DŽ9qd :wC<$n&k} 308f!ͦ")Cƀ] KCXT?a&lͯ#X 4 |NDQN4%+Ft$7[% ߨm.tsX,,j< ڏmadWzDF8fSڰMYKQ:a2 -c>_5D9{z.eڗ8{/ Dfl"FlBI4 ,D8/ [v,0PFAjY޶S\:E/"ܐN`OemCց)54{fu?}!mec+Z;JF0esp -A91/; &}/NN UȸæI6 wBKʰ)suk90[ݓzQb@ mgG%wI8Ъ5c&:֊gd+{d\-\X.J;%o-Xꙷk,ImĊ31|昬O(ֳTg$|dU$|[`p8%5{&[H;Rb֡:Ԑ:ǐ[! ~"Ԫ$NC>vcj\N䒒0'Q:nO/ԃHtub>K]^]67,y.NOMlWp~6dN b.Ē!C&`DARNi6 flf'7hxDom̗4Mv%<~ marͱt̠O\z1`jg1 4,8 4XHgUAHZvMHF(WCmUƱKh}] tk_2Q;UGWaT~(y $gۣ}5ƒ <5 е5eВ2}«V[bnSN1焌oa;m4Nddy MACl2 vp#kNg(1pwM@ƙO$@31:#=I83PL,ہeJ]A\8^6Qt9;gZ~:p ;~z{~gF&ɞB c%-ARv6XT#?imZ/;#{RwnJߞ-,q ҃{? $wD7}0{c0QFlQd}B^F `%42BcCf87\~%A&[Ӏ-|}ͫ;KScZZT#Exe'w:1M;.wJ AHS#E6$ Q#+Fe$|gmIqSܧ*A"u`@Z˜M3T0S5#c.Y 42FŎ 3fWIgMsPD;kn&29nH©DWCH`( >WMl;j(.~Fz /u|%YO'K w/ ꥽E6Yϒ8cwLZ"5LRMf$~jlBj@k;6>cw&1~L%QnVޫ>Xagqpw9ļ1 &{<^hSn l*t~# bWhLQRDfE'ujIM~W'xP:C֛s҅qZl^&YF˶PF -v'S:Fvcl)TFm +ކz!j+ +IYO 0L)+ʵH1"ƕIV[ЫNuީS_=~CR.?{maW~b0 0)YxWqa !PkW$Th >8-UfB~},:%b64vݨ)=l•T}͢z{/䋿bDGt*̤0Plv19iJ]>9e4GLrrG^k{U6 ~9R/rp(3̷j#,[V͛Fm{m[l8*!额Vdt~SwѝN2zW m!#% -J*6smǐn,bHO9I?Z/:Y05h$7faZk{npXs]SiIjd\-xQ\0g::QY I`l{#:׎upD&Xt%pg/tD4}dM'܅([-zӽrr긼H[ _/OC>hTm84Z2٧48BHuӲRͦ\)io]%^L/@(D$Ȼs3$M=!5 MxfT hN7'rp*"Ue!5qG|LؗԐVzɫ j][b}ѻ赺milk<]T2JӦӆ}=hUT429ۛҭ{өvX%i`".u>0.W}Rr[R$Rk%rՓJ8׌2|IDwKvxw#4Hy_L`MfC3wQZ%p $2HmT;n*f2w% P͓Rqש&֍ d0s%xyʶ?C>~*V'DtI8IRVy5@]dV&ݕR ,jiJFDn٠wylDY2@ =Qs0%4\E?DmJJE Q? Z,ZKI~u"'zr'+cKl.L%Z_/lEr$[qx_1OʦREF+E&>\ƍH(S&4c A3yCXX]o}Sts_x ɡ~tz瞅| O=@%/cTHwɅt{XQvT`D=Z:I,"uvTZJlvMtq璝.Th䎽g:{>u@8.}QT63O! kgK Kt]JRb_b+eQ3;7*)A{ESy[N:=8;l3HM1JgT )p P4KN!n]ld| cbnN,|w-`N%&W™^#>Y:̲$ՙW.\IG-[oASvm*P 0:__݉U2?BHX<ր`JXɹN7'Y X=Mo4 z>4;wDEVդ,_^ŌlR/^?0O1 hLJX3N2x] \EB[m zfSh_Hزl9yqxg`?r7Y4Y$$!S8+` uYkpeOًVt,/3qt?WY͈-j˶iTw*dYvI`MoW5aO8ҹov;n_pi')=t6[j2Lc[5it zu*A5/Gr2%XbTؓ[o ?ʽ9=mSy7UȀ}sL]2ԓ41^y*r>@׎p>ۢc]婍4EF7PIGN0.,Y΂) 6^@.9vYj{fYef9I8~^!A%G8u1']{"c6&/!Z޸DԍVwӼ`*)3Fye>F0b?R*{1䳋:gZk7?{Q^ΝoxܩSYA\es~wG2eʤHǔs7:vleO|96K]4\hV~]2 +QmN  t؋ wlb6tllݨ*h½Aӕ"՘Z`]Hxbx[cR,JnoW)kk#gTBrU I=uMk O4aa!Xpn!T#{L`1QRY𵲥E7kfVtX\?+m*?b qD%OOpD[e]iCS_,Y4YrXO,;֒Lt(qU@·dYt8/+&>UX("J(e^oU&x5ME,Yd\sOpkޑ%3RUJh["qsEJ+7׭sgbJ66͍t\.5XMe^` XFG[ B4 ?. qdQe5LM`F#^5,~Vz{u%#=rǓ3ϮO| ƖU/v ʭER.}O*6bD*HZ B>#ԏ)jڛN R|i.x\2e;P Ӿ%LrgVV>1XaWӯ(IV@"iY.ʤJK$"X0Nw>+ſB_ ̿B0_!erQJ48̶`yĽIE柘 ىd_ !"ΒA/K%Bk8abp&× =Q"9ߕX^ZTE8L_+~?QψWy ٍ-p藊/9R‰_J3 YgR*-T//O?˙ b)r F5{M|-cނRl)BHHKc"tQrܔ&آ^ϵ_ok?  ۘa"h4> 6Kk.d M*yy9eXINBڷ p uyB^P:MX0q8+#c4m+UמYEF ু-1"05%=דVȸZ밠Ašoqƒ'iP 6f0fPIDA2{<8vę !Cܪ#" 7d-&C-@ޒqhzVmdX#lVil$qAx4BMG@N6`6x)ǞR x!-[1. d%sPH|([*Z2p:[WvzlQuիη?GT9 I sRu`~x5G7.5qÑw(󖺄Xj FE|B#`zٟLt8z7x4DɦIT5s}Җr:6i?DF r@uȼKn(ĹNnkJD4NRVqtԪ[tjAդ`<PVt&jB?su>JjNQvDǪu˕jDT͜~3t4OÈ O}}v䨅~]]P^- Ɇ-շz~F9ESTeV LՊb7ُ5R.t^rK9ONIJQ, +5rU.= P0Ehe~ Q3U0k1B:ԲiK9Igٕ8MУn~N=L5je,CE5MwpӅ:̘4BaUYG B){c\v BlJ~h[e28;_<vt i|/-zKRl Tg{_#:K{ħ3CK6_1se+їK ńܺ pĚS{Rq[BƔ?KUR&KM ߓt3oڹv:mMa[\:Vf\zs.j 1er0N} lZ:)oJye}6v Bu..ʒ)z]3@ҟW]gIncdOz0aPaǬo(ydy*2GdeȖ|/ܲ^,>?IW濃ЬF13\on 7#~_kFTk[isCȾ}ּ5Qg퇉Nj{"cj&Lcv"3̆ >4L΍ƥ63v7Zy0!\e]82fRK= yNOF͛8>ӫ%5n#UAI?y;za,Ac2dUbliC`F'tZE|KKz𒞑]?[y.3Bl<}eG'r\b?dB\'#G/uWfGvUi>q/0>ouTXZm |[/9&%: .S| O>L~b{lY})jVebf\T ~M:M Yb3g?В6"?byhIxŔQOPǃK΄EQM.[%it1qJj E-2<Ͳ{ϯ{P&ƨNTÐ/ȫ`#wHӴ D8FT1g!ƻ{-o#ˊ'-,hW'ݩKt FÑŎhPvHPZtXt, SSy4~3Z[-)reAoiC;?oäQa ֑E t9-s[gpmKiXQ FAgUi{1jqzз-B%RXuvbx5ł``i@ρWy_u.Hafjsv^E'a9 0ǵ4GVzptT|{ЮfP*ߜ9e].䋊Cqq=6@u^Gy)%]>ő<!<y63ѳgvrYv.OXWJʵ{j5A6~W'8ϑ_Aœ:SpF"({#-m;xYmwFl[k:- p9u#K`ܙNs_2x{!ckڣ&{DED12dJr1GqV[t#E"@"t&B*&W rU jZZÃ}pDwGcJȽݜ ^h~iBV*x;)?.-C|!D5'ԗ4IX8Y9h} )/ؿ)'䄞Ed*$EcwwE(9+r*<1L=Q /CR0bX)5"̅1Es>Y8p%/i4YSvaHZH1^e;лQ}lѧ@@b)436|q&AhZp{}-.!uz`W~oخ &4/x[#D0Kx4uv_Rq(4Hrm?0J!$k82Et fqttPwLItpX*DW& Njtټh[ֻ˶Ty!gak폺K$Tmz~ $< )E$1 ̘ H} ƾT@rRq{!SwWe"}}roϻ7U+WKs|libR4E($ee]^mFr 汓':L sp8haKEBC>wu`(b f(*8t:<95tR;%} a/ѨRcw[=%ܿ@o_͋>L92 s^3rUv ;*Uԁ ?e=` 5qe)Fvc$Z2@Rqs,]ȣBpϺ=GV5aȽT b~ʠ$}]ӧTkX$yh P Evvvh>EwUPEksx[F(F!xZ*<-K $.6 |ʐSsd}=+rc{ڴ,As,( LJ+Sg}S,MtEUo*bMXyz|r7 0e\\PQNeʤ'Iڶ+ۚ:!V6Ǻg[|îyf d*({k<{ג-vDߓ,Α`4ٓȌoi?m&&xS[ty6z[wϬScn`xdL2RCfbv~aiT q $r3_1Pk,-gu8D`*,|k:VQtMp)ro2,I7f AX, gN4 e@E~*j8M9iXcyN`%y7Ӑ+TVnO:,y,50utZ*< 1fĝ 3}+,-*3u!}Pu17s`ϻrz݀8~$Տ>,0l \f0WؒlJY:ЕH҆r i\ CCwbn]T%_݃J[7fzpx-_]{y:|KX,}PV_|(&7;qPV ԧau՘XL<k4i4vsi\qUcdHëFh-w=1N 4J$d"oTt`S13\ %9y#!qd(jNfrD,R?|1ЎsZɦD8@}&qDȚPv)%\_)$s¬! |Y"B)cO $mE0œ<_.}~7|7B g(D(\r2(+D<>9AYx7Yp.N}8蟟 zu ք"ڞP*dB7hf<Կh@7Ƞ1_|ސO\Z@8t {&VJ;{pu CpZw/1 mZ;.]2쑐hv{ ^WlJ%GgGa/9 *B"ubѼ-m֩TC؇*\'<<>+I;{M ''FF4;Y$8T_ )CNsEANg *IP^zA[Gt&}} PA~0ઽ] C0!?Jm2&߽MBUE>E <*ce%e2Vch gɮ$׵Xd@hZ C55뀃=2'+46JGQQ%K\ D^2kkŕWЮOUElܥb;yʭ4j Vnlx٦J\0QXPOPp=Y.-~ǩ)XMȢ fwP2j(`=% UoA1є,TOmW 0nwvթ|E?urT'I%9Sei1rH`, K Pxe\f~p*Y+֝.& ,u?UrEM"En.gBK[5TXJPat At]mmjz?2~%]JIq͡tʳ>=oesQK|7xQm7c،zH|sFaL2dLDI&A04O&~5ϫĖIJ'\ZKJҮ,VCq%}(Lsa{n0,C[Z:n׽,ܯ8ad5Jv =hHM~LB1_c!k'vƗ_;-RT+Œ_BdԳ-WvoŇ+m`AfYբsBNlH9ܻl}[vMkՆ5)%ng$u}5>K,445&gHm۝?<.7 M\4PzE̞J]?yT9'-7h ΃j}H혔mf)!͆wn]À`- s;x4Mj7Xވw/%C; XHktA)$ǘRɈ|Nk /Ez-"ۮ#!osj_\#cu{&)WNRȄ`vQ򀪞;_J\iiʒf ^DaYJH~-#wKZΊ\'WM~;b +SuxK/xs\qT@SNS ]!I{baJ$HMƪ4YbLrv/8lлagg6~].r{jv<=?<~zr>unOڽaH3wP00IT?qK[2B8|/CNrdxT[O0~v~tJY/ch"QT!&tv08#0./R3Fā!z;B(s&W2# E&Cwxb<8~UdnNf Kt줌g˯SAU Kj kɂΤbI: 0@d49g)"ܬJ }t׾7 LTDžTiiCSιLQh].|re A3S`40uG\v26e`ӧRN@yR7 }AqV;lP:,Tk)0 j+Q (rK,ao˕MMф&\>p&Nq{Hham.+ot|LDJN(TBj& =͝6aHOՀ;-X}sq6^?:^ɳw>,n|L2ڷ_Z4,R"WA*֫,WZ(04bP>i+L>9"aDJ%Hf%ͫ5?lpIjL.(E I&\w\kClnr*Sb6`#҅ fJc"J6TIU;fN-kܙMkk;\Mxܣ)݈LtM.ZE5k: 9B߿_ s\[ Y,8OѷA.`gs<&:m[@ՏXQyK~ll!`J& M)^&9Wop<^ݼ[!ex+=0L6ea:C×[dB4ftz{9 >V۔!Сi֠D4 =-H$z {h>w,᭠P};m=ѳ:%: BdwdODi!QzONpŎۇ a ߿C؍G3 j5]IAٷ+;4пD&´X5h2^_;[Bevh *^N#T'62LˆQ{ 4rE\bXZ^ucCܤYy 0& pJoqtE^ۺ zWB#5n]Ó6 nX7]^;BiȾqw`Ji-SNMۮјUSCU1z;QL{ r >^ӧOSM[aS.aS>#veܠzQy1`෇8ΐ:PKRc4xBeKQ<``_$z×)-PeR@~`!w5!"#;Šzn'Unau :/~&˃k-q]VY} jY5+kۅ`Sn|U%H<},JMu\qjXs,{ۈЃ 9vgy Km6>Qe!jv'3ֱ[6\Qc+M|ϥU; 4&8G+W3|4j%ja˳Y;Π`˕!mYr#e%\ŭvˬ;ŷxZ{wH /ˌ=$ $0gdrdkcK$d _UuK{!rwWu^w4iè9XkkʙđOʼnb5Й2u>3?U1:a$RGjOg89S[8@0$U4N޻}IxFx|D%qpbtgz@G#~^QU.ςx<)FO<50gg٩nD:sU-pՃV dAGE 0xӲGֿTqkHeLΗ E|0'$u [,o>F.16h? ds]h* pA\:UV$4)@o1$hLQ0Mn(*8Pҍ)qW0ȟ`˩VxoHÿ IʟHUQf>!RPw@,C)9X@87Ԁ`3OV=Sqh&[v>xαAOY!QN~8P(2UYW&qQ5?MXl1o8Fih6CFQ0⿗ugCd;fV(@F†XwsHw02"ŲW"Ju$ j#Z.l XJY0tsݩ0f.(SH%xxLSNp0?Q&!1T1E\KS cndk,!_Ʊj3, cHk"@W hj{VA-_tĦS'B?P`/EA0KmW=5HC14N6I1P#0aLeAZ7۬tڌ_11xlb-)@7@Y6mA7{a(Oy _% aT'JYTxh< } SFj4'_OtW]3D4K,ɣ ,\*VQQ[QI{AґNڟO 4$ d^xpҵ^*na7Ae O jgdc%:gxO) R*5`8{ +ݣ??[[{GvY1pSG%H𻝃vOz@mnwPk+XACVNB-N?j_hh5Ȣd`z}?k7JiG1<'EC4<7u!tpF>lyj񝖾Rn[O'gc`I=Hib:A8$'6yX\{u꣫U`A;63W^ujb&H %3G11%8dy  ` Z[YB(Sx#XU`5+ x I%HN:AOfw)V"n贱V"e3ӕU|KusbR @,Jz DzHⴌrh)QB (KIO8O62x@\ r&e6 qc|= 9.<]\CQ5Z󗛮`OdiszoqlvQ@>[a&e 1@D L]Og*ɜ^j(= ?3vn)hHĕԜYW/|؍wqu4 /ZUI^ءvsza'O$lTGawBE?$6ڊY-s"w-_Ѱo3icDjɯݪvҨ߯6C*]:a 5 (l *O"M^2FQDW+QLD7tVF LD$<Գ߾xŎN c:'4H-Sh ghdI߸5= ~5%sqGBQ+7ф*ȯw_L,KG6%2\V% J l kHѐ3 3d@]1%Os&̵B)-+I0奕ʊ +9Y|r֗_na6mc(6TmѣxZmSHUF,k6%%: xQMj*TC&59d DQk=[4Jfѯ SdL?yQWFj,,{4u274^JᆹU{Wےy3c%bMT: _A!0NTθnPv2{[u29WI_|z1{*\nv=HFMf̨}#JSoc!벌l6-6JfI G ^zlo)hMn { ,l#cT+rrw(2XUp6{ ۲r}8TFp#vy'|n~l cx\9/tͺ 䩯YB"*h!`hQCԳC@Ԓz$pw40B, #j +.9NZDυ:: ?t:;ᙑϑ+of)GElyc9'ČRZcXRQLj6BܧmKc# 7q%i,C%8c6P5B`ݢ_ k>\VQVę2|95FOǁ ;A&^gJ~M{rL[>O%v_K^cHJ/LOL+Ǟ2t3#rt_c/Z,~ܭy^)Ep=ӗyP Կ\9Rw2tEW̄^e$'q5G?%rͭ4f֕K?Ekmvh=yh!, ypV`&K"n>|yF} +)y×[GRXإneC~$&%ԙ#%y<eԇ ڏQeBZoȣwia>z8Fa9 $pA.y.ygo[Xux+ ;W*FJ}ۨ{9X8_0vP2m{y(fԓ_HU '*Cj]~QXEɥv+zN/W^%#eWNݩUz`2Uվ83e/<U:զ7, J8C&7d$2AWsdIgq j #p 0i;)JHm5'WOT RGS_` 7O=W -*1i\mس6QY /DEU~*vZʳ M'_޹&"og:ٽM0//TƶUPZ*farTl^"0_ N4])+h̬7Z#M|8xh^5߿ZbUDτ;kDHuPk+nR4y] θ)ލrP<Qz75W~ {֏!wdy=OIyù-JsØWFuer8tbɇrڗGDYYP:|} /JC˾F*g ?!BK犗:#K۹9>:~rkw$w֕2w]c/#kǶ[f^]_%QCшCk5nu,%NIKgc^Ϫ4=u`˜:\wqzTBhmSVkZ[%Rr{/bJd௶K *X‰Yjc3 Us4z3,X.INPqjN\@܆Vu,Aޱ.|k jk5yI}MP9v"A27 xI[btnkUth?_)8Ar Qے*rfݶG-T/xYw `6iWoHr!.F;q+!0nnsgf06WK;7.T48=9ȧK$PNxEܲ9?VFVXgdѩn:XDtm [Rv4UZ!Yނ~8s5r3ULͭHL bix,ɳ+X y>*C\̤vAsi(Pi*\d'icϏX< yX}.cY9b0txvr7|pˑ3S~Ãߵ_[Ѵ5=;䜋K/HtՐMV|yz78Ɏ@yъ ALM[ sUuC։&)6WSDh J?gιyΨ6,7XזÃcK> wgFߕڵzm==kԟ75я?>Ճ}-jYPh=k>ՃFY.Rwۖ[FSrI5\3P6̳ lr*E:;9??uN;F#*|PS]9zKT HűxځQ0Zá6\ 09;W3wgߛ^/I䬅S+PЛ͙Ks[ǙHpzyVQ-tt? %DQ?<|ͽ <ڹ&$3W,Ti`4G@C]~?Z1Bэ i6Q/rص:TUֵ-%7y4r-ऄiKxp80x5%٨xtUW@?`hVrr*~NWlRNP ;|C+៍:҉G!s= 0DZDyt8ghAqf4 |ʁN3 T +Í="Wh\FuƗ |xLH:#IHg0+JLS{ 3q!n)C56سMh2[EnZЦɊ#'P3p3 h2%+bSsap!-,3)(ǽF$v+og9}Ou}[FZibL.@]@ßqwZQox 8mP;aqOg.#Imy 5'9y 鯷vlrXl.9T*TXaävx(Lz` oŬʠ8v_'V+%| ҫNOu[w`ο<0` En0(%o*+څv8tNölS}juAD'^9RhK;c*zЇ/RR/\әjO}TOzE+#"_^/P(ό;\W99ƵCS֑q=P@YeVfZcJ- QhĀwAc Z2)Vݸ-&99) yv$H.{4Vǃ[% g6!ԍD5@6Yzga@_UP[\捱+.02Xr}mb3/לdI*e[6XdLp Yl^@0AU*ju9_zȱ"ѝVJzEZXPKag1Ziü S&\%t;8_D%=jƓ%xzo p.<2G1DݩqƓǝp LT4~*:Π2D]~M(sٻ36m>z=w^} Py PM޾U !%zHJ&ʅ&{B,v~5ULXh\'xt"mld`ȡw&: Xow$'*m4} `J`Lf6>} 6 3QgF x Iz "+ S44Wl骄&㭭/A-k) TO6jndF9Z.'ß\ƙ$.]}74}1J8(޾u־C?Vτlx7d`~dbFҽdi_su@WBRJW nztkу|-1F˯JysqջP(h3<(./ks"y^́mI ?􃈴i }PV&yV FЕ9I'=f+}F8x?mW~!I_vEa%@ Byçœr^lԜ|WZt&ӊsk_R]iǓZ?7B[^9 oDrJM4ĸg紟_m{7Wטï^|2ȫgm|Rn]47 3jvWF{z&RxZk[ȱ 0,Ɯ1 ͜3l2d<,筮nI6<]]]]Zl؜'qs͙g٠0yn((/))oO(ޓzS+Z)H0E41a,t'];ޚTgfd'eF1xϮn.c|(( AEA@%14q0 G,D!5Q diu$35>Iqn@ǒ cJ&6{YitL&&*UyE?:DZ SZ*7WD;u2&ٯ#dMML'ZQm̢$O7cDH8] ҂ͮh,+yh 0ng,g$5=mdv ˜TP8, f.|.Xh#E@4o`US-$iN(w.o%K"tN|OC0S iXXx%]0J8Liσ j+k! ‰ࣱJ h*$^ qXhl4͏Rak~.&aQ<9{H|Ŀ7ض8D 6u9e`~$;6P9"p~6`;tGyneuڻ:GƿL#I4U^c ǶYR0p񑈬L֔myS hCAY#Azd4?h<̈6+[a Q42SGs_ ZH|X IⅆMpT K'lB!ˑHJ { (D kL`ІxFjPR'6`:XX?*ИRq^\zPM#L|d` 7:K04#P/Xa@&$np8QH8a MJ4-G3n@q4}>PSXbPK> %1ZSc^x &=s̡\}\aw)_|{];F[ֻfk;7J9RP?\G==҆^s͖,&)UljPrSqYCh2fEi2ڲ-FuMib뭏[B"]͇?soCx$ 9a9FH!s1ŽBmw1,Q ¦B؄kB/lq%-8]KlrAN .m9P~]_7::G8|Hx83g4ׇX;8;?Y<5w}svx{޻1ʁyZXu:A$;'ٴ9BV> l )l\]%-h؊:fK詉AnFL7\N* ;3VLy#jmz{v6!Jasq$NRq~v%]Fdw\Jlh/L~Պ vyt 3˦O1P/'C014W2HGc=[ :iLvwOMV! ﯋ 7ʹjo2Hʥx{eH[s8^kMch{J#/αZ(w91@i*PIB@g#. J} :%4vG&Q썴q٥nt0hb+NJأ~p^Іm zRnek D<٥W"qbVq%}8DHz".V%P/t8 ==1cl`yvŒ(2%;ـݴ|]u;ƛ6G(Zʨw)_yt83TQ5C@y 䏰*+Ҍ!n=UOa V.&\UUHA]*}wX\' Fx64wX#3_?K^Wv5ZÃqndH0#߽6ĺ^hf8Hݑ$2Fv̈xctmgk(sn| "5j7t݌27 ȓ`L %OM+Sf_T6ߟ#g%/Y.3~z&F"r[&RXɴ9wZK#6F]c+u&숙j+?Fz0bUt>`M`pJ2V*:]c~ IWeb_%y&s1&R U3`9;tQAΛ/D4 Rt%}|޵-GRG(A n%IU:i*!J~u &ӟxmMkdQU':eG57“ff2ÙsP$[ONtم^%/jЦa,R{8Y;+8¬4)nn!BiPOd4qȘ.jK]Ji:3~㟥D~E"zUf\1%q*&Vd3hX, u&vI%m3 Wzǂ]MN'JV3r V-Ϣ-~Gv5+0WoL㢗mm[Zƙ=Kok{6;-F Y!kVڊΪ+lj0Wz p-.E^ᾭƔu~[L)^G0+oF|~?i!/ ~R..dt)KTZ_&qg$}.uGkDϭނ96[oֶo )IKn[&=uf~eN*AŒؾ4E<-J:6$)/?֨o,iDXqE.WLig%Kb@> 5 Cʈ5 "WS Y |vm O瓴Z7(̼ۘ _^b,eycFHz&=͝]yD/җrSJͼJVW W/3)*zhv~UH9,Wή5l.:egK:d5kw{iH3ld8Ji%6 [$y9oOr Kf)s`~T&3(ȾI2Tb0YYSd>bB[vd'T6bP-kDJَUk{AYNtg+79W Oa~HM*fEи advc;Ywdb&alN7SyS"(BoET8C7GDn쑡f/oMN2)oc흥hDtn:̔d2)#l⩟ۍ$W^}B%Mo;8т\0ѦW7?mn^nha߼7 ENhotzcְv{Gusvs~/5kكˣO4EAwKcAQR<چڠζלa(?Lbݦ i$0&c赮RG_mmAX]E-\K7[u 4wj?>Ͼi?jZd5OLfM=cNY>& 㗏t$c}dxPaCߺUxh)|]\[ضvʠs5!^syKE%=) Xc9ն x<["G?;EnE'K]sLnyf|oa@nrgTWwWwW:{= : {tǖeͧQ4|ωan T{-^=ˊ6, rX[ nUp"pB!RUv bxJBB܋ K)\8ԏ#MjП X5=v0pa:0   PpP $v;ՠWC pDXV.=s݇U#'ȹז#/;"3Q#;~]A ^$(#5ȘG@ijq^WkTtC~!|C{"`$f$s"buێ}Sky .4% #c(V;B8B H8@Q֑+` BxPUp;dmŢ6Lo*rEKG ((zȳIz>iuNZd;yg]Kp%+:GoB\4?(~F4#VmLp<@-kV(ڙj^XMÈAMpƁNgP,pj\D8Q579~ &1J}8E" s5A_a1rSh􄋞d@'SrFL'gQLdJ3dj>*( 5+dEy$3G@B+G [TKgs몇k$vj-[[4{W? O0_]U F-nP 'I-R f_'Xr$Ӗ0l[o%j;"E# GD?O #1h*FJ8w&ƚXe 9l/Gbl#Tsc.x}z]%(U}*C& =lǀGba {{'?U˨3{Čn"AQѵ {ݹAS^GnPej淘:u`+nڝshuuv}~SS[NTU{(x> D!V}D q<=tFJ<=gYe9-eVw>q1ܫWG,>^EjbR卉̀i/:%QɅm[x޽M3'j[ӊ[\P}[\<0 i kPiu:!VᗫZ>%-c ';a PÄ1y41K`ۡVS;JFMD/gbx9EԼK,-vBgص;d!ia2vg #TLG dcrbW+ !*!v`Bi-q0Ѵ5jTXzL$=q2Qxf6E@$er,1f((*d$R/#-~ՅdM6"KZJn7EVd)ҝ $ûwOzIF?5(Ifvu?qw.W^o):9< rij9 IFR4c[ny 8/7GP;YFG; BC&^f~/@=6y^MXC}c.0V (#(-o̎;s;Tv@xgy,.ihS٧5ŗp8mklZSGtV_C@z\@Fu."uRF-蜠wp#f(ѭhp2޺.p]PkucL-qQ+^qS }n]'}"^ЊxNV_1,:3UG_))e4%~ȪJ鹒 PA]0>W#$m˜mԚ=G$C7KH4$p7\E"Z;np, (MBl2Nf䧻[NZQ ԀGɣ Yi}5>ok~}9jd (n~h߹/Bb/ x_zkp "Uj&q_ ܾs  *5+㜒X2t e؀-mnw"O$ S 1<HHj- %@a~{U _7ԍ*DK\eut n!fshe>@FʸMp TY~_9"4/:{6u ؓP UznmsDs:B<’ẒQӒA SՒ2,[A-@Ö`ڒ4W a *mɱe0,@Dq2{ǁOx޾muώ,]Ci$%uyނWշX]SUL.niV|, 5Ŏ`~IU^䫃TcƔVjzI'J9`P zN2L9dΡ_F;Z^DD4`xf+mK<voʚPvE46J%\8B j #\ھL$\Π@^Bo(pErW2X0~ ޳bVY'׼:|qW8Gu:k^_-',W,ٵԾwѩFU|QHqY 6h4Uԗ7C&w/fI^tY= JK* `^^.WcGjO ,1ȖdkkV2EԨcmBHTfJ7pPC-9ŀmNܗN:*+ӥm|]pzD=/WZGXwzW"dLYoocR61\]]WVߤEQ &!4t_1 OPD33:lqzqR^nX"<$aʻ2\+m˸*{3y]e[>]  oNȏsu_pnEUlvk|xWVa-J%ఎȘ ϾWJKϳ?`ǮL Mm挖0P}oo q*K{4X$ߚxͫTE5iuqʪ07lӷTɀI ŷW~֦j[2Ung g=f G_i訸!$Skaq8Jلdi,^-;E:7=lSAI.ɰ+wdp)-I깪, *;( 6DaYƪ6qC'd0^l%dnF7>=zڵn{by9]3}|A+o?F#ް^'瞹4Ɇ1 $E;-|ؒ@*΄4h$݀94&.85%@V|"FMrbuaezE ½QØd ϖ>h..Y]t|SI%#RT*$%z'' u@ RbpI*".g>dzME#0-,}<WJY}:SO4&~Zf)P4/>meK|vZ%7wYt@UaҪ&!7N&$S3nG\ F]gG q1+%osL_`Ew|QsI{uhu(WܣA,i-hbk͵3u,4m7Pɏ(AzBXzpz>q.Ф}%V" ? ;2sZ0$1u ͙J"d3hn0N:"'f )#'[^k My&`mO80tEާt(n%AMiij?c"&ߦ|U!.U!H)䌼=:~Kk@7mqa-lv!Rl+)u0_Fό]n)X X:* F+\i@Zuզne] K Zs3$saeyE he*AV!ƃƑxa#+HzM!3K,l l-xDiVSӧ1uSw8^;NtV)6SL`)|Y??>㐺t۫nn7Gؠ#7lO]T~ Mhs9[ruy72aa=m-{TiKSmԗ~JG4`M|twX䌭n=]Fl֚D. Co1qKn v{dNX>?蟍*(YJϜJ~Tʰӷo[{sgpݙ/*hK,q=!W.Cdyq}1'ip]&xZo6e`m @5nN{)nIn.d< Zh)@;TH\}~cg__VΔ>,[}zSh CFT"J_ +SBE->[KȘ:\h!T:64wBjgI[neb!u)}(L:Lt𯵿"qO\T%NZn~G\LVG_^#:SaRMYa(3Iw^jKUwZe "JaE'{-IAZrLhFX!!#EN %sS8 goQ%s s,Ezj!Y5aLPe䯕2_ˢI^&.13c{%e KS6+>C-\2C%*$xMLUVydݖWSFBI&Rqm1+jgyJ#3ibͱ4#)=lLdeP*:l^Tfʑ!RHP|eL-52Zp-RVfk"JxKb5%N6rODܡ8lAʵBWduH;$-Bh3%@V622_T 'WHe QPD-@<y.䬰?eh;`UJł u^Z@X&3\iQ.O;tt|49QM[@#Bi\\ w^pCi7>1XwF,5d:U (\2]ael[T\/..oBjiYz~;vf59g;& О eʾkԐ1&Dov`r6{) - #ݬv4}uu3;z;w'w5qRsz ƛ+\M:M/&:ӐpL7c< gˉddۙv;<@yՀ@?dy2eoCԌp sL#b]s !>}K<,fH代'' X ~7Y~U $kjaysF>m6Ã_GZAkk2m@A cWo:۳O8nٴr kdɔx@tVpHPߤAa׈7k8V|go{^uH[dOhe6j}K~Y R'WrފV&h]k"kIwt)j}B=UG:}et'3[)5rԡN^9-0a qaE!^Cr=eEގus6z.1a-6 C!X˫˳v 1oY2 "[57i'b'(c\hM=ws̵M?~k9 4M[~/Ӊ7ŰxWmoI 2J-f 7,g:vb[EqjC;/t{z0oÝwoS/O=U]U|6 LtV/)j42i#Jb%)Nz:Әf MUF$Δ-EI(1M8tjyRn5=lJ|xxD*Lbݨ$ohjS4ߏ \/@їd$_ 4s+50I6@jw呠,@D<葨zROT[ %0 2wV6͠M"MI VG I&dSc1s]9abE\hb8xL}9,2}6< A63:g+é:ؖb_|XH=jHV)X2cX^%IDղ9:(j'ТXaF*uM̖{vEWğsnZ;*Wǫ,H5mfw)뿈xk۱fòX"=tIXC*6hGaQS3R"N7[O؀kN XFyX^6׋ǫuN>E ^  ѥ*L|:~Z痋ˋg@/ݳ~ίzԡNopqzs]g Xkf6^Pm݆킀HpDSunb- ~%aw -zP7"tԠxiw:]F@vEס"A~IlƢ:tj6Ã׼;v^mP%{~D"x}vdZmrn&arZ^>ж|VjQf/;T*&wc.R&`dڜn0PW}GUV9|$靴KTsp.؆Ê(7x ^-m'hur2-_㭘hHp4g[.c-ncoD84XaYI;BXCcDKy_T܏F6i,d[|& IIg"v۸mW0e\0Lv զTya_*Wfeg5|o @|U5vXVKiBaey\ʸ<=/ٶBm:N"2Alӫu]]u=aXrp+-SUc۸GJm;16I3z2ZR|j2W`sk0RmmnY> ś9+/KUxUMsD4$4da7ڭ叐jשCkBh$ͥe2EeЮ1i~ &'ý8OݕĄ]7w^ߞΕB:WI~pzS=]{ʊtݤ^9~P9 JyGq}`\^,U*TK=wx@ysm|dG-v2tixpm12b̮!9p &l]@z@"AqR=Gz^2Gc& G 2Pnpq^MQrZ uyL/)zHiL-F@Cc' \|5;jk|ZG1Uur`>1]3< k ~J+5%͎ {ߍf+[-Ty*yT?츎 "f]mV3z~ؐM&curۦnJV|,>%-hR#9t8TjgІO]LxZmsHE8‹1KqBm|JRtҀymi8߁}CyD<͛Ac GM~j^^A3y|ݯj6LgpՁ(`E4~Psw!ii(˺bIg_qZ@)Rl4C'wB/*ojS\_ {CN;}9u?wy i-uS;콽lEwyGÿ{8zpg=:q\гAoH H_]ɼ}p=lh>6be)GB|!э#tp (LSh-0EY85SDbKf~9Kk^g~܄9k={mР;vF0kC.N{9":w#'qv;h(0F{^GH:>hw 6`DV G062arRN3X <fx"9 "?n aD a*ؿ$>П7ʈDSmÄ.]r}&Q;*Lp:y 9Jm#EYG?Piճֳ h x\,g1^/8dy?'Gy 2S/Xs*ďWxkCq4Yˣ(.ڰH QTxJ%.‡E&;g4|>NҌF8`JZulZ2p8>jHE(#g7dMT =vbg~IZ0I Wk,mJ" $JN$>"kʪ)Z$r;++NXvr)8QKD$PRbi֣ m}Y֝0 t Ʊ ՞*։0F5fPz5s9hTs%80#>>ו>+Hnxk.?8?ޭkBM lk|)zSY}F2Enb6r Q5Yfr6, \5gDJahx;ᛰŷI?(KͯˆɖrpVl #YYƾF;*MC ]THue3kxHyUu 8NJ:+q˺ڦiCErOea'c31d@umqz>"임S|Jv` snHW׻p THFRD%qg\dXϑ3|hNM+9D 3s5K^Z̥>!cXX zF hjXߴEزn~R: `EPE\>%yGIBmdHzZrtd]M)D!7CuqN@i[[:%kߚzVp6=e%;1 ĴyL!6GK`Lv4{O <3nRya8NWO'f&1 N)@1Waw2jQ6IW Jj*@J]f_yA8BX8Sݽ/Wqð$d&_iHAs; fՍ=O Db jUI0.WW[Ny4;Rd_;9bԬh}G Xʮr]EW;91CNT2b,d,^Ì_yB`RԹ:[ۃr>V5:am5}D7 '\O_LI[j 3ۭo=;Rgnl{f<,j;g }a뼃hnpf=ԁjgm)Lm8l,5 nE,ꉐ$(qﲫޓ%>X`Nz5= -Mr~7yH8$`>hvqI[' !6n9|18HHAuUff=/AE|n^Ѡ%h ovMŌVo!8a,| i yH2_,Vete/diJ b-r1Yͷq'^qxTo6]Sli%AAҺHvPÀ)&*I#einݻ`!)4_4Y6V֏TVό\(KɤZ6V&dؒU$(S&"Qgp G*F51SkZmT <K2mTmk%%]Q/L"Z2-(A)p#0+.JiRSjik=U<uqHŷ;޽7 㵴KiӔ|'+i8"N BSBftZjZOsOWt#5pOU[[O9:e%v:dEs$!tjeWћGH8ZR0 ⷃӷ. hXXz}񆒓ߢgawV'QfJh>SQ rZº< ŕdpk/̮>Y(eJ8t w7@,Hmy +U}F,]hL]-dDJw0u5y h'ϲwj )[y[Fxqr7=}Mo&W x&8F@CrzNZj&vt0UxWMe\o`}JJKTfol.>hkve'N/ʷq Tª;T_ IY@h׉9$x+R9IwUa:4yJ SL^.i. N,EE*ZEcyaD]zwhZ4*X^go\ Ĉ8^6(* q[t&>@a+,&뱙[@h$٭kkC!3 |U*_6B x] DA~gŒú*\L#š\xA 6A FḷZvˤch96}4ӛ%d ow#$?X,d䵟=JPCjQLUMd;* QNq%naQO&b], Φe >[]=,.fGDQܜP(Np'԰{nlXNOTT<* lļHo4 F'TyV+c0yuxzzF:iƞAMKxu{7n.G؛`L4_a]WL[(+:!͒Q^hABXz,CBp0~gW03Qľ55_o= E״յ"䉾(HKϝ 0Fx[ysF[Y C )D밹kHjc$&g{ݍl瘭8U ~/'QX~}!Cϲ^23h/<8ETZA0ìD*`:H0rH8Rg?Rlߧ@x<s׋lP/`yq5L^4k{)j|j~'Ӈbw,V;ŢrC˚]U'*cJ)kA85k& 5 I(IC %Fq莒X yณ03H~xwy#Iu2ܱ8wҏ9f# ֜8 ڎ.3aAVE*0 C,h^ ώŵ縐WIv,$9&B牑IUL?n{QÏm֧^*`|Ṁ BۏWA8Ǣyot0gW}w|s&@jR ',2ӑzQJG9#fҽC,HG^U,Cx"b sUq*C nIqcHwׯU6byl6w q303݋Sz{P0C[5~Wlɢ6`^#sU-tp]{W8fAHj JИՔ2ImCiGy+"Ųz^$"S0=&a0gi0r ]$\`ou~Fֽ%W;ƃ@fpz{ޥHNUŀ$‡$D[L`@x=B|u+_iGuʈ]~sVd-)/1R~?|8X1-%vkDNċ{xdPuqu).zn]ZC&iT ji7/~c40Â^QUJd2! 痷cP:pobKS|!}C#k '9P7A}WV*wOD)pd(Cu3[y -rdZEJP(n}uQJz >^ F_9XToBɷ(0w(Ua=)v9\bD>@p%_,"8ki?@N=bGE"ac騺Cĕ𪔢z۹pXmVÜʾlj a,k uV<ďuG/+/nUpCA@0ҞKɜP֚hA!i &rږ/8Q|xJ)U\siBF  D&L!7\xzM98%W `\FD>T! Hc魪B7+#9)PUI%)yIpJBoT=u,W1n޼Ci Cw[[t|, yr 5#RwZxR*d&cTI]E4*c=Svq)DvucFM*T Oa z(;9O~럞˫]!'>#"ܜùƊ%@zedKZ"W]J8kL2VXς bD"@/yH<'4`*cVcYg ׇ̎b%dy}ƍU߲>`Q*Z@m~"萰իw2+[sTM& gˊ3C v@UbҬEȏJL& `7fPLQ9ކyg-*MYJyBFB_^|mԻ#$1ZUq9)Aallo=޴1>ХOy1Ny9j_U? ud4UMcuȤf5D؜s:E5kI4D L'額Z'^CliC~?)AAf ֛,  NT"ꓑ(QUu(Sn*mruc.j}v ͬnlb .#iDI+3M5&v0aa5 naaf' * sU&aђ#^{޴ij@/g2w_{ExH#=su h w(ґoɳNaRfie3JP|Ͽji@|4F\ >4+ ҆^e N봡6B24ϝFύ :I 2>=fr}_hz,)O-r,IIxe`S>U;d)^QQo\MZ=VL%?/Z9Vbo(.}{F(5U*&qp@5`P `.q@Vs~dƌ m&>qSc iLo'/ULc_QZ]kVVAQ{3 ;+dAF#rC WnY/X6u4"SzllvmG=llku!VV~b6Fӻ)r?{W,=#҃XHDA^`^dꋮtuhMnܚe'z#USRF>]B'`E 둤.ljOQofznoO/Ono-+1?;1]OFK85tu H}i̤3߈bI;N|R3?n:SW˜m: OycIA So4,|3!auǃͧ.^{hUlӽ!_zkSFۤ&wȽz]եe0kI{<$i tِnÚSFhc=](2ϐƒ􉞭MU[w~b^4KKY}'"S NiNofhP 'Px}{7{OWPq(L1BRx,o4`.~l?(Ք3Ov=Qe9Oc/#F-}@YӜ4 0vhD> v8M7}4{OlHOh1oom2|k~loe` 2Oǣi. @ׇÌ5c{hVa,hH> ƶN_E|J}*TNVI!4!V$C28 Zq/ʸx[m[I,t ,'D1#\c&W &ݍ/aTU@&OU:uXVFazL kw |2۵ֶlmzbaW`kXX(I7ݞPӛQTS~gGFi]YGLpiXFc=qxSPơ+oe_ܺvNρ m/psn ~5Q eIFcLVF/oÏ%V+4uszw򣚂ɷ){5-n-Q{s}!:'P~(FjJ0qA9ĉ"(~ ˪$/ $/>G409-΍^`&?Ԫ@j E 4ޠR##Lhp#18U@Hf1H>>܍ވ[AKbzjn}a@Qn\׸AUe ]U2 ƌC$f0.RO^(|9;O`cwCè*fb{7Pg.!j"1Q(!t! ҠОLFcqJ䲵!؉*t`kxT]H'L=vh?(~@Vt˃8=~[e*xf(, 3XHroHJ 2МHC ߿$ %D5pUM2'XRYfYv}`;*01φbJi$XB9o]*OĬiҍA \9&:,P̂r"!~.Ipɐ^I$7[ :;=`xp_ݖa K2Edoq05\`D=CfK&{Wĩ+TQ?([Qʉۓࡑ I CgLB !A|oz@/ݛ) hvLeF=SOq-A3Εx'Q98Qh&%A7I:$. $vA/nuc&шQlx&TشckK4 717 &$坋Ay`|jեhu>_[]J9r>} Y1m#i=>9@><촻]qxvuqyuҺWg6¢+e2+<`[+$Uz}1rn)K '[Q/@,錑*s" aZw tm&^*^M\JγӃUSBxr*"n(˭nK{ xar<OiBJ>TOTj5ïhO絣ZE㽪![lM&S P\ј?:TBX5(ypgJz5r}{Kޘ,eדJSׯ:Kۮ$mrZ9< }>dvVr>3hUD oC+ipeEaFD|'Qq# }! ^ny Gz/1QoY !nGdl;o9< B~ fR K.{'cر8AW-݇/@C)ޠqδ}>A 0U-V8T9˾ 殊>oXNࡴ))G!)$K!?!1 9\}W2;N9˔#mai]{/MU?$3yހH_-BfAHKhwKo]dY AJ2>kving[gO'mi/Av**=ɞ }|$ FB䉋 6C\^Qh]̪'ؔRe(XW,&М ʣE1ﴑ-T̢,cuY3.%*CQ!<&KT c"hL"LBlDa"yy#{P<׾W555,iFs+,~ hڐR.:_=n)ehJɟv^%](w]f,Z?hkI'F]ۘҟRQi16&[RTF;`UuT*W*E6jL92A9FLY>D/PqR4YΥJFbӲJD ,%5W&'s馯0ұN[Y3FQubËfrTFYlFkD윧Pz#lH`WP䉘Q l-3?05ZYp3+g#fpJbͶ_˾їwVg =j \wAz;a83i$ #P U6t`sTŁ6F# /Ualei)FBvr R}sV3ɼTC F\wJPԉbŽPhwgJ=:N14C֙?B]׋ >j$ct$"[@*3Q@C߀s#ưZwwE *s.^ԫsj5hdҬ9`hb[T٥8KĜhIG&⺶QCKk+F#4wuĥVWKY~,Lh* VS |"98nwN>tZ|p9+j-YYLk6 c@FKzTըCͽI:ytd%ʡߙ9J3Lz7;Eiքeƞs%RGmOGgy뤐Kx<<a޴Ӓ]* jFٵ$2wOEkF27oH]I#ӦXr<<քQ4!5Mׅ)b^J-lnR], 6]en8Wl((ʀn9 GUh~nƿ7ҡL(ySlo]h5*8mo%_1o/k3IᄍN`^ړ*i3Wƌfaᗏ3lqە=*M`\(gy,Zjn:F-ʹiAk:y.LG]N-A$۟*]_gESihsq q1w:͂KqwΥS,|y(Ex VwsY V͂Uv,EtdY< be~Uie=ɵ0bQ82Cu,L5 %JӦE23u4mqG*lI~&35&IBcnvH ɿh_מ(o`b%NT/1C1Nޣ?טNE/rD> Q?:G4 /^(5^BZ=cHװ9GIL3;bH% Kd:-~GbB.*%gipjq&,Aa Z.Ñ2i!Uc0sBϸnc}JeʫLmJN5'G)(TEɜ:}=._[eHmq*`A|89@pӘ4j:W8& ErLٜSWў vc>)3XVp l30jKӛE/'ܒGD|ҥS.3\7 R Pmh"mevKѼ*^jSjmgÂ&vDb[PNWXӛP`:=bZzu"#,AGlLP鞬5 _9Lاv6BhLCms[KCsyv`gUbqo:x^J)vUdΗ94Hn36CeC+[SwMh{ޜ' 7ďn(\@kR~FR )}f;17l꠶G3kwm׫7y*_ަܻ}xTmOHL~SD2y#) B8W!U=I8z D7NxrHg"ͩ͌tZٮlcd TQR*7yåfȔ6X^Xj ͢"5u6 8䶒X*<{n;MMszlpC$ fJcm_xM52h Xdg 7oѸ\WDU|'|qc#sR'TR{tZOf{c'o@psAʛp!rdZui"jf~+U $4%<-!L,R%b*ZȄ4̂^v`sb"&kqqk`F9gxg##5IM5KZd, :^!sr=M _Z0&7 SBӬH~ 7u®S &Y*ӑ4+ĸ<|E?^p1ήFaEod461YjTB3723!4ǜ34"'wL FԲYDs-?+څA*A ~5q {Z52[Y/DǍ#Ë:3Q-57ػV$=Z|d -wӒ@_V;;.}^WdXp_Z)ҩ;K}Qe ^57Jũʩ[a-bSA|wZ.u ( ,ݣ֭ ʹ?r֙_ 5TPbo] :2n_Q^Wѽxks6+`Zi,ZqN㤾qqtZ$&|x\A@}L+b_X.3\bxÜq{"AQ+٪) °B೬Y^([ $|@eIAD8/Az% [^,x:0Q?Qȋ(]8 Meʈg XH,> ED89b#%sg"}soh~Fs6mTw5gB?g}-%CQ~++ԙ- a8/8g"w1Vl(x $*QC!h~/)*J^$eszy{)/}XьE3jXG}(!Rd@:(,3Uپ^Ez%_,G0}PVȃmZ YyK Eqn8Zw}IoWxŎg_\_>&GeKbQ -AIϿӳӫAyه㋫ӟ?_/><0viHL yD0fb rfH )q4:fќY鳻"{fbINgbWهv.WHٳ=` cGQl}<pgM/oy pppYcxU`Fn; *cz!S#ciMqt!B~Z@(|V 5sla^&_W"X2TD)=A $XLAy<'(ہo{6*YG5:v; L%+b=>Z{t|WvxzrtC&ޚ'{7'>5TsN`I/K vb_'3Hf9쩐ϰ3@/}>=8y ̓dBŅ"]ק6(qt38<K BI0WW'MPCp.ZP[,\3E,Xh_wϧcbŞܺނ' {=1!J$xGswOD@~oR=&H"B A-"=#"hI-6# Zoxw(8H0[)'c iMR^-(PfRcK?ܑMIqʺ ӌoK9j'GEQ½%8c.:#d1shA FF$2 Z%P~O0<8$K ]%6`PY]/dcVsm*Qvr>i\gj4d8CȺhgZOr֫Ү}Nru=A[[u ~&A U*jAr~,E[l=-ak@ Cm4'\~}9|>BsM8129SSڷT}?ۮ,rB)KmQ۵Cіѵ8ơ$-UF'`n1aUf=@&YQ[f:!x.8PjCNepG}{×m)ޮf1큜jyJb=xd{q l (ȑQ,( a@(cJddnn^.`?riEAC<@Jc9D] 1BD } z}ggk_ӋI5rRتDDjLerE'Uػb1.g5bMhա0BP2ڀM>[T6/@"A=qI^j\pMn_4.iҸ/ 0-esIQ!rD~)K@~+M8jk4b.%>dR^{tD-UZdLfKF!EyT[L|v.,ZTDs]ɛgWyK93sar*L5 /8|I]iDs\|TK@2n}˻kr|u}vzyH&ukE i  d zjR|n sj)Ǻ*D5b % ,u/LM}c080n x{op*- ʣ*3I× LQҨALvHϲw?d$9 0]A**Ԋ.r#t DCP%Mj(Y\}.ɂ t@" c[)>Xٓ!ĚPɏSkX]'P%stT ,i';^)EZL7C-E>{Wdz`FD,y & ڞj SLټ4@fiIcKUdiR~7USvŇpPՉܒԆkLñ gn}U9e"Y鳌[΍ϵaj!p]N|mzin͈n^==?`ƊRx@8z K|u GCVQ˜] qq`a[EE7)ε'w:09/ul?X (W >xS+)a'2_qMo*DW]QGm6/@ئލyY%o * (\?(&"[ >tdPz fF!Ih{H@R|6:x~K9-ӢdxA!}5UK@*ED[ZHo2=hvl]ZnX{6Q7"G7"G߈XA,f* 7Nw RzĴ|2$NWyc-4u+DC4 KNl{Z=PvKa @8Z.mj'Sx9mz7m{Sõf Y?XoޢcMV3=2GTIci,f#v\Q~ۺQ>@ս6b]K#.m2-B̳ފ&yQ^Y;PA ?[w ๶.E-8lldgB >;lv.Rk%$C,WR6;3 HUWխ?tyֹDe8MH3*Rz`DCBQ0[c(F*SLL%E<#F~iBňi#EEJr~6kQ5GW#л (JUEJ(JF&薆Q6=a/`T;jnԟ?35,*11#¬3?`8PQ%ǫRiv+p~uOmץ;[l띭v ipN!t0بOכØ8A,1wAUy:,L,2FyE7UO6jp)4 U@eҡ>De&:|,O6P9GA)HE&";wڶ-J3M 3*aCktFf4ni"lR`atp~9<8|b%u4h<#Іp3Ƞi]~¤3dߧK:A../GD}Ŭ)MʖA*(K?cs{Tt}d?o&ir+bx]EcŚ@-%f`m)-O[-z<= v{#]:;8=ok|)qF! ؅xٻ<Ԍ"*鸜9Ql>7NA5H"hYb?Qz#X vQLb/! x9jOѰSgh0vL4ۼ?xy?2|ԏz aTyLΆMq7!bu3 T^8/C|3? el b,7*NzXARN)T;M% jOj1+ٸٯ.ZęD-Df%so]ϧ7ys5=ebN.jNxMDd~3]ʁ¹ɃB8klHa]\?hFbf1C~]?hrslo̱!s?4wDP^ ahcx?Mq rmtc?5%Vߧ9T4Ye8=?ǫt'ȫyq @]ܴCQ%Lv'ۓlmmh]c󦜒)zEo ỷފ8=vf\QGZ-IF)2HiSMm%cxm2x [*ɑeJLO'ē|ad'M3wG*ʐ+G΀sq=2H0ozB%\~k0VǦJ5)HP:#2Yjjal: R`7ZU%Q7&Լābp:^HxLy-g\H*m'^ĩFOy&h$NS] M~A9a|J,MbH0! _KԌl!}xH~i)Lxy6rP'ӹB8`E`Sk8L3NWE8b׫{SQ)`ijHPqXu2\4.]zr~(._-В5.5 Abh$=1gC tiijJHLc>)eLl`]e"vn)n,= c̾13\W ÄniagsT_OmAidnL_IrGfLE6`p]Y y0f0d]KvJ" ULrc.a4>4+zb$Re`Wb(*lf3k%&C, ӘD 0r'@NGfKWܲUf;حM=0.z)tIB[e~c_:F2xx:v\ >_zmt4~WvZ˞Q"L{m7.r۳z&M}T0bg$MnwI|я.;9_藳Og lip][95Wb' vV1z65io40pɰ:!^("qa{8>܁8Oj݇rXbN}4z;Z@BQ|eXQU,oŊ\=msi%?I[R!,e5%u]q )~5,9Nzk H2`iуq!5f ze4A(&k,!z;7Qw{""͜6%mIc(:L#ElA4q,Ôf#e$8E˻}NkH إzsxntz ^Y@)u=#a/@odЯva9Kl60{^BI#jӫWqr%wmS-7-,%sN1j5M%YEuzfjEZ3̶Ј[ϺWd& ~$v5hePYVoeYL^YHSb3Q kn0Go@R+yX!|cs;.NR#2'Av@Ef속 )dΜN-;Zlr(('m$ɸL /_N.? JL{XYɍkmүYV1}:11>I3m\~+G.~`J VC>0'ZqF>qd@)Mֱr64~l,RxO4ce=dJ1rTC woG TR4鲺mmWϺ !t{t 6:-zX'g8E4+;ϲCbĬgF'e!*aS{ 0 2Vi2J&A5c?G:jVLBWGÅU΄A'/T`|z#+ig'XyOvek; }ښLH\7?D1B,b+Re٨r yP4cI\D .ͅ2Ag5+cij2xn0>b.sESύK yEn.GEWGg$'WpsEi>jZcl7t&(1ҽ\>wSm;~t_D(KR뾆Yz.#TX)VS?=kbrF7駳kCi>0֊3zt"W/c?l08gu(뺭ÿ"xs0dKdѱ+YQ%7XXqjbաUŐ>czuv cQrr~uh`stbff O9squƾ 3p8i8`Gj^Vçx^*6RD5މA)E\*ÌVJKzDXY]a@4StSrROd QͽXX KZZ]t(XQluѣucDr5]~]׹rA,PԯQ{(umQ4dcdˡ%h唽/Oj{@r^trٓ9L2efd9 4s)}1dE\p1)Wưifϻ͝[L߄.׈1_p`W^ð(YtN(r;rZ=oፖ|m4c1/ 9½WFmw 3nrV̰v{ʝ\UOpX,$NӦ({W2qo1/VV% ?KAA) ;T6w7Te[ft;͇;tQ7`MCmg"l'ncbMm}ee:*ԧEK_z%A=9½s('a~]a܆-se. >`\=ZƬ ϝXZr2&8*kmg8my\ z@vO#vY̝3̵,oŚcǫgtS/EkOϫܱg@!$`'Įm̙,- YbOJ`buK4 P_QWgժtAeHUb'FK7b4ԯXmGSl|g04 rs=ȣ KHd>=j?oIk Yasይ㺬hkR!A=ctXǬA$Ƅl4TٴVЈs)! _?5_-d2[^ܱ³砥'd_ڷ¸"Ǚ̾r[eB' gQ⾅q n7p~uG5ļ$Թ}/+/ = Fu-s!ki/ R)(+GT9cT+cr蚀yq\E*ѝc9x&J B$/CӆS7?b}!OU֝p$%' ;V1׈Е pBKʅ[^YzU9vj+M}LlY80wCmT#5զQQZ6S2{u"۠4jjI5)Osy\X i( {j2H8w;2`SgHį%D9 3Z*\uʼnm웕yңAM&4eoז[6U&ut爿x41 7؈TAfG:uhP9l,G=koN#V%Ƽ^S*/E6W+V\U{~{jYWUۉ冭' ӯ'YgqG3Ui\U ,>N Thbl7oxYkS~8`i&-6dz:^cYy%쾺\NNcﳻbO4֭k?l͔UkQ$ҔDN{Kc_kǓI]u 1: |Іr 9t04N{qx`8?]tq98l  W=J? 1D <8w v#\;Ґq(mqh1Qbӽ?Ⱦ'.6J?t6] S&Om>Eq'ODNr/2ލ±Ccĝ =Z֪yC@*p}+w(KD,!L(!V\y5|+>X.hѷa6NXaNh mf?9 :H =CzVr:v#8^=8bl^ዱ=͂A4LƘN;SdMLFs[,*D,cl2n5ܒe!h &^O{ ү QIh9sJ 7ndeۘ5O'Q7^vkѾNo8b3J(k` +s; ;fˋ0r'C֘(X7?MyE$Moĉ @0dm:"MB2Y (fρ)%LBSr"JtUA%Kᇞ{)k5-: ~:JߨɭUq&å_V?<0vvzH;DL -|NGW_ǣ D?ӗenĹ1+疵aЊ%7'UOP- B38:,D}`FЦ;s›dbӻ 5Wd+kT ATJ[>ҷHGE@ÊA Zv . kdE@kК2dO?D,H:II. dM^!95 xAɣ(.2+,   oYI5݁st $b ""\,0_G:T֐67*RIPQ8):N X4vlL *E 4G{ x3Y i |>Z,~SGobzӨfZa jzÑF)&^8Y+$o,#Qv VS]SPKh9G56SK2@2\#HwTOuE,]3O!"ȝFV,7ܶ*?щSn&W`^ԢV^uFF CPy6{bbv;_2=N17mM{[;,-si1r]ќi&İqr~dSǜbm8!Ѧ='\Odnn\\„THq#jjS|m O|=)l\n!pgwV*_ \5n ^XVVCg4ե& hy,ƭ}RAt"Ykw(RVRA1d3lޗ3cE;džbnEMF ܎{CIZqzMy%O G=.ˇV, 7Ce2+kpeX&[EY*kU`$F P+Q䍛MUHjTM4£ \)ۺ .0K6ES1FYVК%:Sܰ;HMܗ!լ*\5ĞqͰ+2ЙϢQ 3^xx?Pc0%U@9{yrNei%?^'s<~,R)(*WaLKݰzM ~r .LRxd*z4Ar72=7f-zR^uy3hœX0,L3gVrP<VI ֫ɱt u `xVoEW$.AP_6nMV|T! )x'*;Kb^ACpA8s;s73k{Iqͼ~o}|3WY6-h@] G<*<"غ[&C\&ecv>rڇ џ;֑ZblR6ḿ}ӆ5.m%u!qj:5*\+6l7wtZU1d`KGyZ=7^xMmrKӞ/4'T[, Fn]s3+l?̕K9YX̴h]2 dY!jDaL޿}HZ&cUԕ}U?"Z)D3B 2$wb }\1(hN1'M3#yl(.(]9]e>=[#`ȝ3Pp' a 7/{rP )3f59UH0xu+\]L&X+UgPxz,U|nsyN.r#(2#9$!?[@H%]uX|Y?EnICxlw*FmUv#MdHo5>'͞rI`83SWx_ ZU7 i;Sc" K8"LYtcA )T"3"f]쟰 mFl- Y5}⟗Fu+5n[ Y Rb|{MVK[3wfvRSǓSL&f1 τ͢/mG),&E$Z.dluZ#] N//lhr+GW05 ^Ydx`PY6^Vx3~O F~[Sk)0:zQ{5Tr!u.Bq݂>#YLH|mFą'?[* `A *$ R4#<P>,72~}7RƐq;Bﴠ|aT"2GRIԤH> #H\ oOsZ;#xO 6ho? 5O!qHF=0Enf^ 3{N5" >k-Q5WIt7o=DS"֖g%d kX_[a3#\oǣ7t76pmQsVRP Ų/u$mJ~!s)z@GZ^+Th)>w6 {/`=촻 q* ğ660p*Î$hR؆@,s=*Kɨ,8p) |3_.HBΥ/XXPFf&>yZz<$ATYj[=8}ڝqÓﰻ@spWqc5w=R/']+XE`(h,ݹLs Mh֒ퟶ]>>}hԃN{gׅnoqt9~}>BsvLz;P1UoKφc*Mq|iSqewU]=P|SdP $DXys2 Pi[ӺELD~s㴑iH*IIQ4G#om[%P`u7Փ9G9=64nqHΨa gtQQA%*  .j͐[ִ%rG3wkNg+kSpÂP& B4CiAOQFn\i^gB5N) w*ͩ2g9ټM)<nV%.v.e*ٶPX6rYIGdqY^ q m<'y :~y4-r7X3<fIjCɕr[%W4m'>hR88((@,,OGFYLJ._r_-/$?plJ_%oJ^")Fy<)N%2dNù-a"wxM[ UGLEڪR _MG,DA-G+lYy4:G]t5R^;z't=&#NBfD‡ZUyK.,LlId6Thgۗ%u20"K`hp]xS5WJr.'ӿY|7~_ 3^Ăpw6*bQ-3osq8F,LjqCB_obH ,SD$Uhu9' &AJj| 1i#I :Wakz ZVl xsvMONrvqt7R OQMw VU-(HM.W(N-)-ҙz\\@eV0I..*^L H?iUSEYSA7_A.ȕgY4Q!9( \=x5j0~9I ҆B"m5JH}e'-÷؛-~v_ASOiAٮmDO[(H l{H]H~>JeRU1DGv?xVkoF]vAG Hl YZmӪBtؚ'gHEAs}+hc߽ڱJJoNkoOI}B/p8p' ɧ3M2NN/|NC+Jd<ޜJHš$"NIp%䉠K9TL1Lš]\vGt^D$>uτbAԌ4YRC-d+V nOXԉqtˤš^..2)yڸ )N2t/(X{,N pGMi,OѐM,[v26>O"r8(=#'j/>T}!j`@^tNOףuo<&0#O=CT= 2f-C}o!#y(S2Z'Kwt09:.қ2Ču 5^U]z+mv^5/kQU'Ѡa9~)f[blc@IX mC`ZB1`+mܓW1oaɦ~bR]w`L9ۃ. Ƌ>a>  (dB^籦CTmH)O&L[\w ˜7tf"fuYٮ-2OFk6(ůl\dlA?Q@`}0r{*N!cX1aKOyv_ = h@T$2ׅ003T #,m@Kes_6CԈ7U&z9޸ ʀ:ȤѷjUߣuk+/bRC MP(+V] ]NvE8YEJuwǥܜОNM^~uV`ovl̠2řbD,t>vRa ز7SN l^o5vZ[=|{f>$v1sc?1ʹ3#?gҘcSXr&5# -n]4>]?1r|J~t`n ڟ {rez0x,|6Þ!Imj M8qLs cX2O #TL4s^V޸{0lj[#n\:v}+D'w*oyn\L-u<*԰=g_ųLm#|#5p~TsױxVmSFņD,CtC I$9K+;h޽; ۄ_j=k-؇ø HD :E;Cy _Evն(gEy'yi|?֟WP"l HDPEoDLĘ+-\q,bPdDtQ.] ,j.xB!0XT1,(sD2#󂰙rڗBh 55fq<  EiLO|?k1paoȊeJdoxRTyP?N^Φ]xM{䯳vq/˜8L;Qҩb8&Bp> _Wtx6j6 &hIOl(1jsk*02B*||EA2HQ]H-e_<Qn$')Z0A/a3ETIe0N >@xtw_f늟*FM&)n+m[%HC?EmG՝j+j=߸rksmgdmckn3V M\Tii%ҥYgLIߧo}i[S"?pJZ=W\þtfJ3TBTNH6=ba|%.$Q4):!Bijv} d]5^]e4n~ C~kR,Emo:q>{ϼiTHx o|h%ܔ190ߗ')"O4E,Gk8-dS-Wr~/iwv*cDC)Ud (Nɜ ꪘO6vUHk4d6HKmh֩.Rӊkj쇳ꭂ&gR)snPVIX69gALחԊ*Z;}6I 9f.,ҨXٻ\`zY2Gf}MRaY:Hz) xDg5Ũa ƒFȻ. qJ߸sI6/s* GR䴥{:߈f>t/1NxT]oF}H`6 OA*!nӨ{w5 ;kqmٳg>v.A^~EKϻz?w[nk0JF?aQun2FUj5< s*<,k(\)-Z&)F1 c pL] 1O6 K"TTPbLe#x ȻcXn쥱dDcIp)QiM36W) dn_w)vE!+%γ Ƥ: <,L^`6L>M*X8S <lHRB0h> 0x`M_ 9AѓJ:jLfCHG$:mxX&ŪJ' JF~uðS.:!L3r\]yXz?_A=gѺ" t?pOt)?^f魪͒hhpJ_(#,1袄Mlia $LԐĺK iyL٥D8mϲ v` Şvo;INE@W2BPfDq<}|6'8LFGOC(9\8Ԟ7?{]h'4d:;;Mlrr|Mt*8Q`|'KԂ 703(. y #=QQgD͝Я:$JlD)n *]+K/vh*3A'#ϧc<{X0"? [g?NG+IY 蕱L7+"-|]bU)D*Skj L;=VNkU"NVltB[P¹ 2ߒa ڳ\Xдצ p{qY4GYޫ ҹgO\I*KlLqT%UrQHvHQ)Ͷt[~MGgfC 5V+gwj v 0 5['>]2?kt ty&lQs4+hq6UPKa~)dկo~dl+( ?ŦG.xWΜDR3f*58_%Zu|1E -_RJ-n Gb`\~6292E0'ϺUu[Y@7U)xY?VFUA 1 IJJVznJrrokll>:Ld E:8j{*ݩ_ Y;\ )*Vܼ5.AݑgvPt[(  h6V*?!˔s <זR/K_ `qv [ڲ ޭ\@YJG9u&ez6cчf㣓 nÇ\6(#RNo01ե ٨Ȼj9p=-@of]!gTپe,h4ZR]z h|B 0Y;[UWEQ 5n: xqY)U1$؟5XZ Ԗ{1!Y9Q-&S2.+hcsZ*ɝY&2sv`;uKx340031Qrutue8>'|ET{ɮ@:H x ,VTĒT̢J=.~ dx340075UHN-/.)fx8i~ߌu`t.)1S`  %PI{RAAŴ/A#+HBldlSZ aRZO= _EH-k<;V-7))ZU+ϩ)\z3u跡Y3ldU[Q#yFӈ0h<00fu+J@XcȘB4nN-M]4 T aMF44k}rĈ;Xպz:k`KZ ;mg/M_O훵YwyF7:\3h..73u!3*M]^7i!ԣ梜uP,73cw8lRq7!}?0:Y=BKo6#_a-Q4UX^j߁;렕6ҿiTӠtʦ^̭_[5*PXm6? Dh&y^R-$Qc<"QrI>^SAwͅWuz(2 x~ݓ_ݓ_ߪ[%47N.v 8>}N.~~ gG{_wiWDOp{KTAb .s$[=P-RиAME[!Rb%|iAoÅBn)8 nF(^81JR v;/]Xymm N"1Zѝj153/+{n IVP}^쎢0yAEZ5 T́&ο)pGVސR܏ȪzcdNFZ.>*?3ڍ'JMaRj{ߐ>C5HP /ߣ q",& 3Q߰~yrտNO`j#`2[6ayv7}{}~)Tk47^ Fuc߽&^㺸Sc|Tp6F#BrY&bЁݨ89^+~\eTjA> ?)yǟCud`1#v,iR4L + Cov7A BjF( Cﲦ.-{Ag4f'{q6(nQ673*{~(U PǗ_g&*tfhvULkЇv-ˇM]>?Fvq1dӓ{WL^%R~( v[!v^_P4han 7B l\8ǙhU6iWmۀ# I=}V!-j poqYNPk)$ H?‰ n@N{JCPq?D(٤D8&܋бYqOkZ=tQ:Jp>ҮbBr+MP頼 $ u8ߢw0ƽnW42BY`8P6S"4'4Lsܦ?^ߓk3oZ&{?_8GN pgGl PXX(GD[stĄiT_Tyvd@]ϋ_Ljs@1P+B'Z7I$EƨDf"ϧahWd>*9N5C<mmAV u#9 V@.%i[L|ࢅ"P 1~`L*\l3ΒFYpYV/E _2>AO;#j'CẊuY_onǧg=um`Zԙ8ia2CGK@^:KI` Ωh*5"e5 &! տxtC$ 5ʹH ~ӁNHyTK%iR2 NIAYbx'JX4 J{[7`frsjWJ˗Jb:;0]/m :hmiAȯrtB&mx+ÑF!GDgi%%:U; ޼9oh~}{ٸܩ{﷗[5?ed1F+sQZҞ ve=>֟ffi LДW+ ?<fAwvU'p[Ţfv̀k)EFύ`.$Ѹ4K/dE1!SI5")ާDRPMx|~ѣZj}(|NRPpYD`lpȖ{??\짔EŸŜ7?TaW֕.WP]wGO\Ӂ8lk CFdPhX?F꿹Ù̮!Oo 7ec2z,q:pm9lVwb+G]%5Rz/:4(jf3'I 3T<2hEqe ` (jbcbi/Y9BXsJ6#fJ{~P×(0<0(4 3RA3+k>X֛6eXY Q07QU\&[% N8EJcE.PNa1X?Y(QݘNI-h&Z![*u֘ST /&SX-6MZr NGq=!qzp(c Z\a0S֍J a1MvY;8 9q =@ 熵C0:?I꦳dK]-d67\F_1T ,#EFV #@Z1nO5cK8'BKsKNde94/mTa , .' E.shDXN5rϋR5țrQkHRbh&k.ݐ ,RZ85%*,[߅t0E;3u-ϐLC;;g+u0&sS& cenqYi9[[p^\T`G-rp6+ƙ-{YߖYpJ9 &6%G5&SҠn5hqа/gϙx9Xw'pyX7h4L1⩳[w U?rU'k_w\;&,(dl$;N3nԤt<Ҿv*kesKHf.m-쬌ܡ]ڴ* yyjPHPk3 hɄ* 6IY6ɡX{nPay{6Ԛ¬HA AC_ j;Q)qG=)!*J5P#=:%;@0,{&tgA> q%.u03;8'ׯkSi;>Xou ׮ 3@.4 K6EC>SSiw8ͱ\egWIAR{NJڈk[zsd#}2u_D񎥔 @6A_&ߵ6lfmL˗dd_ko$K4v9\_&/s{Hq6$I^=isL]AF- #C>Rb8\y|@֣.džʒyIsQiFctG\/G*$Ȟ?\NUYW^EEܥ1x=0.q ̒IY]3c(,;qS%qS%dqF'X8 Scd%Z {bЧF!#C ;VǴN]~YV݇Mٲ%G3pyO\#[Z%,VG$,;Z, ʱt'?c%?:r{A>Ž"+IN~v+fV!vr,l]zl<0L=3 DbLS7E0|.j \# QLM`%Ңu7%r815s7zeL3'e+Pa IpQG%i?U>a4:z/βjsǵg:+Eir\UI6C<%%ϛUK.Ya.!SPQDuِ;"B$'VR[QDΤ"tSZ>r~&p(!t)t90z!ШJkZJD]6w쐸H9wSx5ckbN€1`J^6趷tck*|mIp!V Bǣ{b S[7ާ_.ND|/(i,OKQ_ ^SD.fPDr y쟟<6dJ\fSDa{οqZ޷6%5tOtʌi nH 0|.i5lRG'z1У3P[zn/W8‡_W?x{طT,|'l'im:rӉ3?D!WH5d=O'["5+¿ ˷T7_ok=JF,F/#*)N!!E0]HyȞˢfjY{̟Ap9!F^K0ɟAaAM=5L!HX"u$t=P1s~>+~3x40غ2F&ҶZWjգbcVħA뙷n0SIvFO]mi9S52s>'L1cgin%>l )5s-?A5˵˭([6yGAtz|uڛ]lRjo .<nv'6H$m\ܩӝ2[[Yq 4r Fo15AtJa -YںNN/ WԹ#b}z+eD@Fq𚞸g_j\RChS.PSXVnԄ.Za*6 ZQh$J_]0vȓ k޹Uy} Q?"`g{dzX yZZdiS4q  ˍJtS0㫄Xs)GHRO,ڑ.z Þ|ԞA[{Nik&K.prL -V-%ꡳz_r& f(Xݭؼ/Xã8..F'Uvy4͗tcl[\MU*zWchU;O]@'bϬgdɘ6|:(nG+ç]q(G)=rM8Њkx;zuvFW%,ԋ3۲ͧb x(h$u{uSﱷYIx;zuvFIo6zT뭉L.ғ|ӌ̌E ix89' H;#Hr{uV4F0{r!fT5xb '31ٱXlvar|Q-x;'yDrJ-+}ҢԴTb<̜TkRF*x!Ĵ ޗ_3|J}_&cx9kOk6ShVY5uұQV `כ' Dk>yx}.LLv,V]v_4nWxyBsbNƄ)4TXbx!PEik 58x7!ѵ6r+VCr3/,1A o5Sܢ3!LCkNxq|>L!6xsFӍk2槔o Yx!kҏcl^8Wn#b5xkgogXdR$|XUg&o⹰ƱRc ?ixq|F< C=#=] MP WW`W5'gf\$j`ledysr9x!WA2˟.D>j Wx8YVo̓ ЬAyY5`] v' F-$c7xe5>[/$-fϤ߫ ׮,x340031QK,L/JePgՋ:ZrUnJ !=] Jv {@ SaJ"=LW}|b7gbB3+CR ҿ=ki{4(3$A:Akc+tuI딥R/*\]|]>d^^N&YItBeCU3:s~+*NVQT>5(ߏaݺf%v_|&@ZTPP.LOGf4DCT$d3ܛ~hRշM1mEBT&e&1Zr)W\WA'3yG\ N,^ܵsyմsg;?;A(*(a`pޖlҏVmr1(.I,IvLl鄧oCNlq^v`/DEiIfN1üow>hOz22Ib"#xkgogXb`vm}akUKaq& kx˘##Qx!T՟{ktӳtjxp8k}U T`%]g<19C,O\Oxֶ100644 copyright4F0{r!u ܋[yؑ4TF Į]y.;r'e$|?xsB9:;.ԂT+b+}1H( DhDfI~nfz^~Qjnr~nnb^nNf^n~AIf~Ը%=O^)Rǫ-žUE^[o>YM%~N|(6qeԢbkr[7k+^`Wn x;ȴibL3Ĕ̒"̴4.dAY^bNjQ 06ŹI9%r (+Jx- 0 Pcw(4ȤR` ݂;5!C8-R!󂏕E6W1]Zn!̘+_Ʉxu?B$Kx!C2eoU;, }PKx7~wJزx~1S E= N?p Xx6ٜ:@2pyright: Years updated%+yL[,7xsc̒L^JjRfb^~Qf W2x;zuvḞ8\ȲPͧ#exkgogXm9dh`q&օ#x9qF< C=#=]sMP WW`W'KspN?XAeQfzFBdjbQBiAJbIj䃪9&W2O/nZ`d`h$L 6cL{S#x!lD$ip&XMUCx7)sax.Q1 %:QGKű|xx[?l eE&޼iXxsB9:b+}x;"yDr'fOjf&r x;zuvFk Y/6biFfF 1x8ձ$UN=B_tzT: E7+!ux[?, &(+2歌U>m Pn9x¸qBt<.'@x;zuvF3s3z GD$߾ͧ w4x4l5kfoԱ)aj??n|M#%x[?q, 9eE&޼_^x1 0 W8` Kڄ$VWNy+bәz3 1%HV;RKD\{Ƌ}ZAx]\h.x!_AE x&+4 x;I7}C_Ŀ.1 %:QGKűIyB_xAΙ4N 9.@' 5:57:48 +016 C5:18:38 "Je+Px*Ιߘ2;>=9.7:00:45"JYx!2+&Nً~("xkgogXy55gϩڸS_x!-t AwBJ8>Hjx;7q ƍ}t+x{sB9BAjQFэSXe xS(/-JNR(HLNLOKMM)-K-*KMMIMH)H-M* RR, x;zuvFzO *~ʑ9!i2Oӌ̌ b"xIp~ʽȀ!+KMI,䱷IZnx;7q F< C=#=]<87>:j`dely  x!ZDV΢$'NN7x8)ٓuѻ6RڝѱY"$P%Al{|XXZ$Xu;!R\x3d 'g3kNnda521< n!x;$yHr'fwjf&i#x!rsuݑgL8x^6B{E·Ą_h100644 compatEuۆ@dM79\>*,Ng[+ap$!yB(k)x5 LU#+2x|C x{¼yF=Ue ;@p"0 C rf#xtqI Lx!'fzK$m yxkgogXKˊVk66-3'U(Ԓ/17J!7?713S2sB3lJW'?`H-I-I#?YC+91O!)U!-4/E!3o9,_IPc>dwN0qq_`7x;zuvF} $.R89CfZӌ̌ xx8jF MO .±ܴxsyGFlWxx{qžFV/ ongq 3x;ss<&1l<}i yx!&,38Ť,*yh xyB 椖*+))N|ɚ_\R;مѿ,Ӧ_.V1WRSOOOA$[kQJKScm͕ZťC 65 x!(~ÓCze\lJ Ax88/cuCPvVa_Pi'qIк8y!fkMx{qs c!,x;qc±lh0y>zc8x!<`s~Ȍ7k!C.xkgogW040031Qs fP(_ے˞'x{BW?\QQ!3xmN0 y hql i7^ mMUnUv@o< cVqS]g>E)| xvbN<`YbH`Ž"(g?ЀnAU*_NA+vS zbͦs_ >HbڬdyŴ*^n*W9qƛ^ps{~p_e-s@kJ4;T 5F}^rix{tiQ̂bļļJԢbMĢT̔ʉO)Fx!tdK[:xkgogXJٯG4Θ>i GH:r nx{'7?OAPH@x"uL!:  ^9 F fVVƦuX;2<ix;zuvFZX_f kjaV}ӌ̌ !xkgogW040031Qs f\Ӥq{wєڨ wMx;zuvF7 !_Uߥǡ4#3# hxkgζQ! x!Mٍo.ӟй3R|hHxkg6QYDE-z/+*ױa Lݘ 7x{x'7?OAPH@x"OfqB~BJQ~AAjBAbIrFjB^~BAQ~Yf P0RAQ79?(3I*9;1=u M&1jJ((&V**ZZZla (ux;zuvFYv'mt d.fԢ̒'%X\ 8x;øqQL%: nI F fV@ddm`yfgrE =xs&nC.ԂTX7Pe 9x;zuvFREL vwa\Zڿ4#3# Dx^>U-[za&(ԩr:;xSRVwR Ovx!]j.*O]R!rx8.K8mOa$űY8*s3s,21+7c5 ;x;q«Lzf nI F FV&FV& 1mv* Nx˲yC/tqjQfj1˪2k|c q8cp xҿO@`ÀC iiZ[ڄ G&q'WW&n8gaɸgS6r7y{׍I7:?i?N"J5`e ceRb(QUP70\tdCz5N$&o͠Cg?g+?\iVpl'oEJȱ:2g eAƶ-d3ldK/<+Ցtdz[8uƅ;:;lsz []x;zuvFlgS>{5JAf7_2ͧ& ex^\,t_( )娾קr>x 1 F~NE`UNf/IYۯ2Ց!zaZ^g YZ/kY !EvyW80F{0x=C( #x;zuvF_nwLU 絞/;[~iFfF1 Fx8SCC*&Rk'JmױYnbTX<@a3cAj-x;xq‰L!: nI F V&V@mӘ6;i ~x 27]{㕋(E6]jxVmSF\p7! BH6m3I}ESNOB{N4PaVc ^RKk&x$Q[e3-$=x1V4xzmcLT腐=8'Z/"S N%$T9bƽ(K:eS-{?-KrsN7vIs!xwTGWB.LhR(QȘ0zj_KP3;/_g K KE~aM4^^7Cz]/K|MS>i ~Bo}^O BB 5?bS7a 3I8! D ;O`0hn= %}#ANe mYpp0G25B(WO|X}ȉRK!pPTr: (̚g5ްdz*&P@${ ;s~y*|JLA^`bȥs#Eݒ Ӕ"W恟$/4Nڀ;ߜy =C+7OI/, Qn:daxK#$L8>D1 i} ٴV lp 42Wr*I eXL9jBrL+d\1A :b[,Cw=im AeF+HD{]͉Q\n3,PX@T<쒥՘iBAm8yj;-ɻm?O--Xc{'4m@OG'o0*z1<Nޙix5\"FY4˫00SZn/UޡU.-Ecn$;NJV8$|^N}`33 XJſ6w`c`Bf.S`xi<#W㨱k0zƺon< IA6'S#a4EXs4kVӌ`fPXrW?mNJq "ƛxΝ{DT>V&)}l PnxDro 6|^A@l#nWKs`ݰriQp[p@ikqz׉5,a}'=6d\Z1pc!2? R54fV"Xt|ǦRŦ6KS?vᆮmXc39n_} 1@N&˿SjRxq…ɲiOx!rjSv$r= բӎij.x{vmBwLx;zuvF2dˤgW9{ cbӌ̌y *qx"YyOϿ' )@f0܋%gRxsBFaifNyBJjRFjNAjX\@`b1G~njAbz,o4#3#ځ jx (+nLGf_Ncx 27#fiD\TJaxXmsHESy$Nb"cⰱB&8G iIF&T=L줶(==OhoXd<4'zqᇠDipj\>=K? bۊ; &qk2Ƌh"КY9W^{DYI"so9ph9[vC [aJj]mԖmՖR\uA~7gvXm#uPWk۪^CwGa\E~ 7 |}cG˃>7,0.jЖ1b 䋥?A,)k\#k.PFي.DVȠE|lbD?`P׀eT}m5 `G>F p@0桿2.s[f8nCߵpbٵWq9q n%pDzh.j[=`R? }_x +BˋVLX _Žzr!H$߃KƾHsV,6F< +z*<)rrfG;+Gj7j⨩lUhimU;z9_&ҫBe`ag.yA/Bk8ȟ Ə#Y,``"5eaa!nR($ǞÒ,\E3 xr.<0_@heP5ib`F"L0JYohgbRLL0Q,A&ˮVE7Z"xŎL%4mh욻.D::ݰ#8y&6hG rٟ.tp10?Az`GaOABj2H9bs:ݨtXZ7 *ia 6hcH(|/jjub"58:]81a<}q^jj[OW.nvM3I(CF? fm4 &5b{݌5S M4ml;TBBBGMhk\Ere+X<ȃYQnQӅbRb!YwŨ@z݈3bW9N1t&VdoW*|%!H+j3I;;Sf]u!ᐑLR3 p ƬQ(RV5[]?bB&G)Rf)M esu[i؋(ɮې{B"m4-\+B"k<t`q[yG+uuä9DyxP{2@Ӧa.=zȆX)-9_)^ؗ@H=P~\ ų8tO CT2&*GQ/RkNxQMqo4gRH'{EuStkJȐef%zLěӒ$Y<gxq{rK?)N?@=}DIM"Ui5YHeYFAHk/Q+UʜF`$]T* '|{o@s&(3r~*AIEIn2ipg&rUuݽMg㨲Z p\]9-oXWV,V׷xn.~ sWŬ! l[֦jm Wҫ{W6V3$[.ƹɅp/Y=8Ԣ-(\y IRcA9D @e$fBeP) "xa-JjpXlBOL寨3XL 4phLp8 ҏz>3ZNS`Y&4lʖj}ZtQ/H',:f9{#nyWe9bUQbAOSg'ϡ*{03jJ=OFz~x^cRg\Z䜡Pliת36ڰf ~7;f3~e<8| .ZBJ5r []|XV닳7 #Zm^ڇ>ķeK2Z,͋rj;+_dS 1=! N<5?έ(3d-y%mZۺg Jflyk#'\!-!H<~Jv{zeR',FSV% xC9~kNzF֞O$pL >aX`WNY -p:NvDไwS2*Su2g|yFb鑚VHLCű)frqf!+4DJ`}[YS KMmKB1p`3([<;OY0]OPnBt\P- ZSPi2C4溙#lΗ1RŨ4ؖќCI 8a-M37w}Gxhw|4D\cJDOgKOݹx$s/gtlw'w]F8/}_^)ѱ!xK掠/C=iXTD7 Z! QcOc͌6 c ̚`Ć߀ nhh=sS|!1'=z"VPɀYte:549'B57lVmvvZ-Zmؠ;F W)8'F*L5#x)OvјP#sN*~Pƀ|Q0Dؗ> 1 됄c{QtlLad1PEtKfJwZSl칸9s l$pHYEQ]*@6'C&^#Dy?\ű#A RIOqV$G ER7(~Y]ӜJOiK}1=GRĝRmkq+ned`V4}[P1yP481ʠr,izO5yu@f$i0m`=L&g8$cd-!٠e.9jL燧`jz E!DG_c+t{y[|\(_K!sGzDӌ̌4bxPJ ]/ QFü`7):2;@3*=7 >7?4'5>91'W"fu&ca6Li|nb^Abzj|bJ Ps^ZbfNiVCϫ|LS4(N.yvٕ@NgCHs^S{ʾ bj9eÒqO?,SWrn :6pxgmWoO0f`e&ufA5jMv_YVlrJ%ƂbĜԢ1Uk d7H^C,ZP}7gGcY{T;z{j*M,.Aksڵ3Sm.<_޳[P}ũE B}_ m|LuRkxuA 1 нwTPBl;LfJӊs{[ C]&ZJ<@&bvݶ.d8dLj}MT~DsMitKN#VeSjCʝ}reҼ7lh! x;zuvF:'p5=iFfF] xPc _Oȯ/Qzw1bέY\L0JQEқ=5=>=N<?E&!"dx[ƸqʉwT'_Ԕt+Q04TpKMR022 L̬L 62 9z7 hGx;Ǻu &,Zx;ǺuDFXKY4*Α~aiFfF} [x7c2 kM:S_)w1~l mk%jZck&x[YWk3xùqsc3l{x;κQq%?%& u=( t|~etbemon-1.3.6/.git/refs/0000755000000000000000000000000013617253434011650 5ustar etbemon-1.3.6/.git/refs/heads/0000755000000000000000000000000014200452020012711 5ustar etbemon-1.3.6/.git/refs/heads/master0000644000000000000000000000005114200452020014123 0ustar b7f6e08f147adb53971c83056cb1ad4c29aa622f etbemon-1.3.6/.git/refs/remotes/0000755000000000000000000000000013615500633013320 5ustar etbemon-1.3.6/.git/refs/remotes/origin/0000755000000000000000000000000014200452026014600 5ustar etbemon-1.3.6/.git/refs/remotes/origin/master0000644000000000000000000000005114200452026016012 0ustar b7f6e08f147adb53971c83056cb1ad4c29aa622f etbemon-1.3.6/.git/refs/tags/0000755000000000000000000000000013212003645012572 5ustar etbemon-1.3.6/.gitignore0000644000000000000000000000000513212006100012004 0ustar .pc/ etbemon-1.3.6/CHANGES0000644000000000000000000014351410631517211011040 0ustar $Id: CHANGES,v 1.3.2.12 2007/06/06 11:46:17 trockij Exp $ Changes between mon-1.2.0- and mon-1.2.0-release Wed Jun 6 07:45:35 EDT 2007 ----------------------------------------------- -Bunch of fixes from Augie Schwer: Added RPM spec update to do a "chkconfig on" in the post install, and fixed a path bug in S99mon Fix config parsing of unack_summary, added docs for the option in the man page Fix display of ack'd services in mon.cgi Fix -p/-P option problem in mon.monitor Fix nntp.monitor "-f" option Allow snpp.alert to "use strict" -added "-m" to http.monitor to match header/content with regex by Jim Trocki -added hard timeout patch to msql-mysql.monitor by Arkadiusz Miskiewicz -added fix to ftp.monitor to handle multiline reply after quit command by Arkadiusz Miskiewicz -fix to fping.monitor to correct parsing of fping 2.2b1 output. It prints lines like "ICMP Host Unreachable from" to stderr, but to stdout it prints "(host) is unreachable", and the regex was matching both, which is wrong. by Tim Berger -added -u option, "UnexpectedHop", "AlertMessage", to traceroute.monitor by Jon Meek -updated output formatting in ntpdate.monitor by Jon Meek -added local-syslog.monitor by Jon Meek -added --okstring, Cache-Control http header, --debuglog, to http_tppnp.monitor by Jon Meek -updates to smtp3.monitor, --alarmtime, --maxfailtime by Jon Meek -fixed "disable host" behavior. if a host was the only member of a hostgroup, that watch would be disabled, but that host would not be disabled in other hostgroups. the correct behavior is that a host will be disabled individually in all hostgroups, and if it is the only memeber of a hostgroup, the watch associated with that hostgroup will be disabled. enabling the host again undoes all of that. the behavior of disabling the watch is useful so that disabling a host in a single-hosted hostgroup does not inadvertently leave an empty hostgroup, which will generate log warnings when services are run against it. reported by Ed Ravin Changes between mon-1.0.0pre3 and mon-1.0.0pre4 Tue Aug 3 08:02:35 EDT 2004 ----------------------------------------------- -when allow_empty_group is not set and no host arguments to pass to a monitor, the interval wasn't being reset so it would spam the syslog with lots of "no host arguments" messages. this is fixed. -in reset_timer, there was a chance that _timer could get set to a negative value, which is not right. fixed it. -fixed the bug where lots of mon processes could accumulate if the exec of an alert failed. also fixed error handling of failed alerts. -added "show failures only" button to mon.cgi to speed it up. by Ed Ravin -small permissions fix to rpm spec file -added MON_CFBASEDIR variable to monitor and alert environment, which is set to the value of "cfbasedir" in the config file. -removed unfinished snmp trap handling stuff. it doesn't work at all, and it's misleading to people even though the man page says it doesn't work. -added monitor_duration and monitor_running output to opstatus detail in monshow Changes between mon-1.0.0pre1 and mon-1.0.0pre3 Mon Jul 12 09:12:29 EDT 2004 ----------------------------------------------- -changed README to refer to the new, more sensible name for the perl module client, which is mon-client -applied eric's updates to INSTALL and added a mention of monshow and mon.cgi as the web interfaces -added eric's rpm spec file (i removed the patches because they are no longer needed) -added lmb's syslog.monitor (a nifty hack) -added 'alertevery strict' code and docs, updated the README and INSTALL to mention CVS, updated CREDITS -incorporated mon.cgi 1.52 -minor addition to alert behavior explanation in mon.8 -in dialin.monitor.wrap.c, return the exit status of execv (if it fails, that is) -fixed path to perl in file_change.monitor and smtp3.monitor -added some rcs tags to identify the file versions -handle_trap_timeout now calls process_event, and it works fine with alert/upalert/alertevery/etc. as shown by my testing -received traps now reset the trap timeout counter, and fixed some other stuff wrt trap timeouts -added sub process_event and made proc_cleanup and handle_trap use it so that the alert mgmt code is shared rather than in two places. i tested as much of it as i could and all seems to work well now, especially upalert, alertafter, alertevery with traps. -added per-service "_monitor_duration" variable which records how many seconds the previous monitor took to execute. this is available via "list opstatus". if no monitor has executed yet then the value is -1. -added per-service "_monitor_running" variable whose value is 0 or 1 depending on whether the monitor is currently running for that service. -removed gunk from handle_trap regarding the various TRAP_COLDSTART, etc. processing, since most of it was a bad idea anyway, or at least as far as i could tell. traps and their exit values are now processed exactly as monitors are, which simplifies things greatly and adds to more intuitive functionality. this means the "spc" value in a trap is now ignored. -fixed some args processing in call_alert -fixed a bug which would prevent alerts or upalerts from being sent when call alerts is passed the "output" argument whose value is undef -remove usage of parse_line in trap processing (backported from mon 1.1 code) -make esc_str escape spaces in order to be compatible with monperl-1-0-0pre1 -added list of all possible client commands to moncmd -added --community to set the snmp community in reboot.monitor -patch to traceroute.monitor from meekj added StateDir, TracerouteOptions, StopAt config options some bugfixes to config file parsing reap children to avoid defunct processes added timeout alarm -up_rtt.monitor added -r to log individual rtts, better error reporting for tcp and udp check Changes between mon-0.99.3-47 and mon-1.0.0pre1 ----------------------------------------------- Fri Jun 18 10:35:18 EDT 2004 -removed nonsensical unless statement which would conditionally set the op status to STAT_OK. it should be set unconditionally -added "strict" option to alertevery -changed protocol to escape spaces to coincide with the change in Mon::Client Changes between mon-0.99.2 and mon-0.99.3 Fri Jun 11 10:55:27 EDT 2004 -------------------------------------------- -updated lpd.monitor -added "watch" parameter to monshow submitted by Joe Rhett -xedia-ipsec-tunnel.monitor now understands the new OIDs for sysObjectID.0 in the newer versions of the software -fixed exclude_period parsing problem reported by Konstantin 'Kastus' Shchuka and Jeroen Moors -fixed a setlogsock problem reported by Gilles Lamiral added AIX to the systems which require setlogsock -added "clientallow" restriction (trockij renamed it that from serverallow) by Ed Ravin -added monfailures to clients directory, contributed by Ed Ravin -patch to fping.monitor which catches more error messages from fping by Ed Ravin -patch for minor *bsd startup nits by Ed Ravin -patch to msql-mysql.monitor to support the more typical summary/detail output format. by Ed Ravin -patch to phttp.monitor which corrects the uninitialized variable error by Ed Ravin -patch to phttp.monitor to show more detail in regexp failures by Erik Inge Bols -patch to imap.monitor to report the usual summary followed by details, and clarify some error messages for a couple of situations by Ed Ravin -adjust for some current fping output (ICMP host unreachable), correct the docs for failure_interval (which is currently listed as a period def rather than a service def) from Debian users, submitted by Roderick Schertler -another patch to fping.monitor to catch ICMP Time Exceeded failure, submitted by John Nelson -MON_DESCRIPTION now supplied to monitors -added "-f" to etc/S99mon -taint fix for perl 5.8 in monshow from Roderick Schertler -added trace.monitor, and alternate route path monitor -changed ftp.monitor to detect no ftp server when socket opened okay. submitted by Dan Kendall -updates to ftp.monitor to show detail of ftp conversation -added irc.alert -added dns-query.monitor -mysql.monitor - fix for deprecation of _ListTables by Aled Treharne -updated smtp.monitor to output detail -added "version => 2" to monitors which use the net-snmp module so that they work with net-snmp 5.0.6 -minor documentation updates -fixed a bug with the CGI invocation of monshow which would yield the error message "premature end of script headers" when you "drilled down". bug reported by Hugh Caley -mail.alert includes the service description in the body -fix for alertafter timer, fix for upalertafter feature sent by Adrian Chung -fix phttp.monitor for RFC compliance, uses \r\n everywhere in its requests. Just \n leads to a "400 Bad Request" on IIS 6.0 in native mode. sent by Erik Inge Bols -fixed reboot.monitor and asyncreboot.monitor to handle counter roll-overs -_upalertafterinterval typo fix from Michael Rademacher -fix to phttp.monitor for EINPROGRESS from Erik Inge Bols -updated file_change.monitor from Jon Meek -dtlog a bug where blank lines from the dtlog are being output to the client, and the client is interpreting the timestamp as zero. fixed by David Nolan -fixed qpage.alert: Only the first pager gets notified when there is more than one listed for a qpage.alert. The problem is that qpage returns 0 for failure and 1 for success which is backwards from what the alert routine thinks will happen. submitted by -updated nntp.monitor to support authentication submitted by Kai Schaetzl/conactive.com -unbuffered monerrfile, maybe it'll work -fixed trap auth problem, auth.cf parsing bug submitted by danb@level7.ro -updated mon.8 to explain how to set environment variables for each service to be passed to monitors and alerts. also removed the wording that the client handling is iterative (it is not). -updated netappfree.monitor, submitted by Ed Ravin -patch to fix broken upalerts submitted by Daniel Fenert -patch to dns.monitor for added functionality Added -serial_threshold command line argument to allow the zone serials between the master and the slaves by that much, at most. Necessary to avoid spurious errors during zone propagation. High thresholds are typically unnecessary, but when using Dynamic DNS, with zones that update hundreds if not thousands of times an hour, they can be off by quite a bit but still be OK. If propagation completely fails, eventually we'll exceed the threshold. Added a mode for monitoring caching only name servers. Give the -caching_only argument, and then instead of -zone and -master arguments, you specify -query arguments, which are of the form record[:type]. (With A records being the default type) So you might specify '-query myzone.com:MX -query myzone.com:A -query _servicename._udp.myzone.com:SRV' Every server will be queried for each request, and must return a valid response. But the records will NOT be cross checked against each other, as various round-robin DNS situations may cause the different servers to have different data. Fixed some error reporting code to format the output better Changed the script exit value to be the highest count of how many servers failed on a single query. (I.e. if three servers are queried, for 20 records, the highest error code possible is 3, not 20 as it was before) I found all of these changes to be necessary in our environment, and none of them greatly change the original behavior, so I figured they were worth submitting. I would just submit a diff, but a context diff was actually BIGGER then just sending the whole file... submitted by David Nolan -fixed tiny bug in the cmdline operation of monshow which was causing the unexpected "No non-switch args expected" which was reported by -connect STDIN to /dev/null upon daemonization even if monerrfile is specified. -added the "monerrfile" documentation to mon.8 and explained the "all" directive in auth.cf Changes between mon-0.99.1 and mon-0.99.2 Sat Sep 8 10:06:01 EDT 2001 -------------------------------------------- -fping.monitor reports the error when it gets a return value from fping which it doesn't recognize. this could have been the cause of some phantom alerts reported w/empty summary lines. -fixed comments in CHANGELOG -andrew ryan patch to fix checkauth and some monerrfile fixes, theo's fix for alertevery. this fixes the "cannot connect to mon server" problem with mon.cgi. -andrew ryan patch to open/close dtlog for each entry, renamed open_dtlog to init_dtlog -updated KNOWN-PROBLEMS Changes between mon-0.38.21 and mon-0.99.1 Sun Aug 19 15:18:55 EDT 2001 -------------------------------------------- ******DEFAULT BEHAVIOR HAS CHANGED FOR THE FOLLOWING FEATURES************ the following two defaults were changed, since they seem to be unintuitive to most people, based on feedback given on the mailing list. -the old "comp_alerts" is now the default. to get the old behavior, specify "no_comp_alerts" in the period section. -the default is now the old "summary" behavior for alertevery. that means that for successive failures with "alertevery" used to suppress multiple alerts, only the summary line will be used to short-circuit the alert suppression. to get the old behavior, append "no_summary" to the alertevery line. the old "summary" syntax is still permitted to help w/backwards compatibility. ************************************************************************* -cleaned up config parsing a bit -updates to up_rtt.monitor, added traceroute.monitor, smtp3.monitor, http_tpp.monitor, file_change.monitor -fixed problem where upalerts were not sent for ack'd failures -updated the sample etc/auth.cf to give examples of trap authentication -updated man page for mon to include better explanation of auth.cf syntax. -formatting updates to monshow, added "summary-len" option, html fixes -fixed problem where server responded twice with an extra "220 ok" after doing a reload -rewrote fping.monitor to return more verbose output, and to sort the failed hosts on the summary line. this was wreaking havoc with "alertevery", since the order of the failed hosts in the summary might change, even though the same hosts were failing on successive tests. added "-s ms" option which will consider hosts with a response time greater than "ms" milliseconds as failures. added "-a" option to fail only when all hosts fail, and "-T" to call traceroute on each failed host. "-h" lists options. -made nearly all monitors output their summary line (if it is a list of hosts) in sorted order. -updated man page for mon with more detail on the behavior of "alertevery" and "alertevery ... summary" -added xedia-ipsec-tunnel.monitor to monitor site-to-site ipsec tunnels on a Xedia AP450 router. -silkworm.monitor recognizes different brocade OEM'd fcal switches, ignores "absent" sensors, and has a work-around for the braindead behavior of swFCPortAdmStatus to detect offline ports. -fix to msql-mysql.monitor to allow --port to override default port. submitted by Adrian Phillips -stdout and stderr now can be sent to a file by specifying a filename in the variable "monerrfile". submitted by Ed Ravin -updated dns.monitor to output only the failed hosts on the summary line. "test config" fix, new authentication directives "!" and "AUTH_ANY". "AUTH_ANY", check and warnings for hostgroups which are defined but never used more descriptive error when m4 is not found removed second definition of disen_host and load_stat "alertafter timeval" patch, alerts for period will only be called if the service has been in a failure state for more than the length of time desribed by the interval, regardless of the number of failures noticed within that interval. submitted by Andrew Ryan -more verbose error when bind(2) failure tyop fixes to mon.1 updated COPYRIGHT mon.1 is now mon.8, and references to mon.1 changed accordingly update to mon.d/Makefile to use $CFLAGS and $LDFLAGS silence some warnings in rpc.monitor.c add /usr/local/lib to standard search paths for alert.d and mon.d, and updated mon.8 make monshow run under taint mode, fixes view directory to match the docs default server for moncmd and monshow is now localhost http.monitor accepts a 302 status (moved temporarily) fixed --auth in monshow reboot.monitor now uses $MON_STATEDIR as the default state directory, and "reboot.monitor" (not "state") as default state file. FD_CLOEXEC fix update to monshow.1 submitted by Roderick Schertler -fix to pop3.monitor to produce more verbose errors fix to reboot.monitor to add --verbose option submitted by Ed Ravin -qpage.alert accepts "-v" option for verbose smtp.monitor has increased verbosity of failure details submitted by Steve Siirila -re-wrote Steve Siirila's mon.monitor to use Mon::Client and put it in mon.d -patch to do proper syslog handling on openbsd, MON_DEPEND_STATUS env variable passed to monitors submitted by Mark D. Nagel -added "failure_interval" functionality. i actually re-wrote the patch to make it a bit more proper, and renamed the parameter from "alertintervalcheck" to "failure_interval" for clarity. submitted by CHASSERIAU JeanLuc -netappfree.monitor changes Allows the monitor to give more verbose error messages which will handle multiple volumes. Instead of reporting: "1.0GB free on " it will now say: "1.0GB free on :/vol/" Fixes a bug where multiple alerts from a single filer would cause multiple entries in the summary line. Allows the monitor to handle the case where the NetApp MIB isn't available to the script. added na_quota.monitor. trockij made some small changes to it so that it will allow disable and enable to work. submitted by Theo Van Dinter Changes between mon-0.38.20 and mon-0.38.21 Sun Jan 14 11:55:06 PST 2001 -------------------------------------------- -merged in Andrew Ryan's mon.testconfig.patch to enhance error detection and reporting of config file errors. a new client command "test config" loads and parses a new config file w/o committing it, and returns error conditions found. -added foundry-chassis.monitor, detects PSU failures on Foundry chassis devices. -update for up_rtt.monitor and added http_tp.monitor from Jon Meek. -fixed OS detection, patch supplied by Roderick Schertler -tiny patch to freespace.monitor which lets the user specify a min % free, submitted by Christian Lademann -http.monitor now accepts 401 responses as success, a tweak from Tim Small -documentation correction from Chris Snell -added cpqhealth.monitor to which detects PSU/fan/temp problems by querying the Compaq Insight manager agent on Presario systems -save sum and dtl into last_summary and last_detail from traps, bug reported by Jan Krivonoska -patch to correct trap decoding problem, submitted by Ramon Buckland -a trap timeout now clears the value of last_detail -dtlog is now written to upon reception of an "ok" trap -patch from Gilles Lamiral which adds accuracy to scheduler's synchronous operation. this should help keep rrdmon happy. -added silkworm.monitor to test the operational status of Brocade Silkworm FCAL switches. it should detect port, fan, psu, and temperature failures. -fix to http.monitor from Andrew Ryan which prints the HTTP response header even if a timeout was encountered. also fixed another bug w/regards to timeout handling. i applied this fix to the following monitors: up_rtt.monitor http.monitor ftp.monitor http_t.monitor smtp.monitor pop3.monitor nntp.monitor imap.monitor -http.monitor will allow you to supply a user agent string of your own via "-a useragent". also "-o" will omit HTTP headers from properly working hosts (Andrew Ryan ) Changes between mon-0.38.19 and mon-0.38.20 Sat Aug 26 13:29:45 PDT 2000 -------------------------------------------- -updated some docs -http.monitor checks for 401 status code -fixed the buggered 0.38.19 release. damn you, cvs, damn you. Changes between mon-0.38.18 and mon-0.38.19 Sun Aug 20 14:28:23 PDT 2000 ---------------------------------------------- -fixed exclude_hosts (again) and tested and tested and tested and it works -patch from andrew ryan to add checkauth command -included phttp.monitor from Gilles Lamiral -changed some wording in INSTALL -first stage of new config buffering -readhistoricfile now clears out last_alerts before reading it in -added -t TRAPPORT cmdline arg -merged patch from Andrew Ryan to support multiple authtypes, including PAM support. Also fixed a bug when the user is listed in auth.cf but not in the userfile. -updated documentation of mon.1 to include PAM authentication. -removed non-portable sockaddr pack statements from monitors. -CVS has pissed me off to no end with its anomalies, so I did a sensible thing and converted the repository to prcs. prcs seems to be simple, easy to understand, not quirky, and good enough. So, if you notice that the ID version numbers in the sources have changed, this is why. -removed mon.cgi, and replaced it with a README Changes between mon-0.38.17 and mon-0.38.18 Sat Mar 4 11:24:34 PST 2000 ---------------------------------------------- -http.monitor accepts 200 and 302 -monshow changes, mostly detail output -"list opstatus" command shows more data: first_failure failure_duration exclude_hosts interval exclude_period randskew last_alert -fixed exclude_hosts Changes between mon-0.38.16 and mon-0.38.17 Sun Feb 27 20:18:46 PST 2000 ---------------------------------------------- -added "SELF:" for "depend" variable. When the config file is parsed, SELF: expands into "currentwatch:". -fixed some errors in mon.1 -added exclude_hosts -added exclude_period -removed duplicate parsing in read_cf -"list opstatus" will now accept a list of "group,service" pairs if you don't want to list every single group and service. -documented MON_LOGDIR and MON_STATEDIR in mon.1 -changed how args are split in client_command -more enhancements to monshow, esp. config options and "view" support. read the man page for the details. "views" are meant to show a subset of the mon opstatus, and be configurable by the clients. for example, each department can get their own view of the systems and services which they care to monitor instead of seeing the entire list of services monitored by the server. -added protid client command, and store PROT_VERSION as an integer for simple comparison. Changes between mon-0.38.15 and mon-0.38.16 Sun Feb 6 16:45:55 PST 2000 ---------------------------------------------- -monshow now properly displays the "last check" column in seconds, and it also displays the description, and you can click on services to get details. acknlowledged failures are indicated. -rewrote cf-to-hosts to support continuation lines -fixed some documentation -upalerts work with traps now, thanks to Jim Farrell -savestate now produces an error if called w/o arguments -a patch set submitted by Andreas J. Koenig that helps with some of the documentation -silly "list pids" output fixed so that the output doesn't have lines beginning with numbers, which confuses Mon::Client. submitted by David Waitzman -fixed problem with acking non-failed services -config var that allows specification of syslog facility to use -detail about how "use snmp" is parsed. it's now a variable in the config file, and it still doesn't really do anything. -historicfile is re-read upon server reset. -catching a HUP in the I/O event look should no longer produce the "error trying to recv a trap" message in syslog. -new config option "startupalerts_on_reset" -new client command "list dtlog" submitted by Martha H Greenberg Changes between mon-0.38.14 and mon-0.38.15 Sun Nov 14 11:20:23 PST 1999 ---------------------------------------------- -Re-wrote dependency code, and fixed the "no upalerts with dependencies" bug. -list opstatus output now includes a new variable called "depstatus" -Documented the "alertafter" behavior if only 1 argument is supplied. -Fixed a bug in the arg processing of tcp.monitor, submitted by Phillip Pollard . -Disabling hosts which do not exist now produces an error -Giving an invalid disable command now produces an error -Added "list deps" command. -If config file ends in .m4, process it with m4. -monshow now shows --deps -trap.alert uses opstatus found in MON_OPSTATUS or -o, and correctly reports it using "spc=". -fixed problem where ack'ing a non-existent service is not complained about, reported by bem@cmc.net. -"use strict"-ified the server. -monshow now does CGI && command-line, opstatus.cgi is deprecated see etc/example.monshowrc -ldap.monitor now uses Net::LDAP -summary output of successes is saved in _last_summary -client output is hex-escaped, and received traps are un-escaped. install the Mon-0.6 perl client for this to work properly, since it includes the appropriate changes. -renamed "reset" function. This was a BIG booboo and it was causing a core dump once in a while. "reset" is a perl built-in, which I didn't realize :( -tags in traps are unquoted and unescaped in handle_trap. Mon::Client was changed to quote and escape all of them. -added "numalerts" per-period variable and documented it. it controls the number of alerts sent for a failure -added "comp_alerts" per-period variable and documented it. this var stops upalerts from being sent w/o a complementary "down" alert -it is not possible to specify the binding address for server and trap ports. see the man page for details. -fixed some signal handling and terminal input in moncmd. patch provided by djw@metatel.com -patch from doke@conectiv-comm.com to correct error reporting in msql-mysql.monitor -long lines may be continued by trailing them with a backslash. read the man page for more info. -added "alerts_sent" to opstatus output Changes between mon-0.38.13 and mon-0.38.14 Mon Aug 23 10:48:42 PDT 1999 ---------------------------------------------- -Some clarification in INSTALL procedure. -Removed old patch that attempted to fix the "no upalerts with deps" problem. -Added recursion limit for deps, and the "dep_recur_limit" config parameter in the config file. -Some changes to "monitor .* ;;" parsing behavior. -telnet.monitor now uses Net::Telnet, which is more efficient than forking a copy of tcp_scan. -freespace.monitor uses the newly renamed Filesys::DiskSpace, which used to be File::Df. -added asyncreboot.monitor, which uses the UCD SNMP asynchronous API to get the uptime of a bunch of devices in parallel, similar to fping. This requires ucd-snmp-3.6.3 or greater and SNMP-1.8 or greater. -Ditch stderr in fping.monitor, submitted by felicity@kluge.net -ftp.monitor now sends "quit\r\n" -Dependency bug fixed re: $dlastChecked, reported by felicity@kluge.net -Commented out some spurious output in dns.monitor, as submitted by brad@shub-internet.org -Tiny fix to mon.cgi from Matthew Price -Fix to trap.alert to make it actually work w/o complaining about "undefined type". -Fix to opstatus.cgi for refresh, submitted by howie@thingy.com, bug ID 16. -Patch from Petter Reinholdtsen to add debug output to nntp.monitor, and -g to specify the newsgroup to test. -Re-wrote tcp.monitor to not require tcp_scan. No more dependencies on the "Satan" software, since fping is available separately. -Virtual host support in http.monitor, submitted by Neale Pickett Changes between mon-0.38.12 and mon-0.38.13 Sun Jun 13 11:18:16 PDT 1999 --------------------------------------------- -Monitors and alerts are now passed ENV variables MON_STATEDIR and MON_LOGDIR. -Fixes and tuning to opstatus.cgi. -monstatus has been removed. Replacement is monshow. -util/cf-to-hosts accepts -M flag to pre-process with m4. -Fixed some monshow output when service has not yet been tested. -Some adjustments to the monshow man page. -Forked monitors now close server sockets before execing the monitor. Bug ID 16 submitted by james9394@hotmail.com. -Bug re: "time" file in output of monshow. -Some minor code cleanups. -ping.monitor now recognizes netbsd. -mon.cgi uses Mon::Client, but not all the functionality has been converted to this interface, namely the "disable" and "reset" features. Changes between mon-0.38.11 and mon-0.38.12 --------------------------------------------- -Fixed "list descriptions" bug submitted by Vad Adamluk -Added "last_check" and "monitor" output to client list opstatus. opstatus.cgi uses this. Only works for 0.38.* protocol. -opstatus.cgi now uses Mon::Client, and some bug fixes and enhancements. -Removed "bind" from ftp.monitor http.monitor http_t.monitor imap.monitor nntp.monitor pop3.monitor smtp.monitor. It was unnecessary. Changes between mon-0.38.10 and mon-0.38.11 --------------------------------------------- Another small (but substantial) bug fix in call_alert which would prevent alerts from being called if $args{"args"} was passed as an undefined value. Changes between mon-0.38.9 and mon-0.38.10 --------------------------------------------- -Fixed a bug where call_alert didn't set _last_alert correctly, thus causing things like alertevery to not work properly. -Small bug fix in handle_trap_timeout -Removed some debugging junk for dtlogging -A few code cleanups here and there -Fixed @groupargs problem in call_alert Changes between mon-0.38.8 and mon-0.38.9 --------------------------------------------- -Removed %var% substitution in favor of -M, which pre-processes the config file with m4. Macro expansion should be handled by software whose sole purpose is to perform macro expansion, hence m4. -Added an "example.m4" in the etc/ directory. -Added "fail" trap. -Pass _op_status value to alerts via env variable MON_OPSTATUS. -Updated file.alert to log MON_OPSTATUS. -Fixed bug in client buffer handling where a blank line submitted by the client would prevent all future commands from being processed. -The server no longer disconnects the client on an invalid command. -Added "--disabled" and "--state" commands to monshow. Showing disabled hosts is no longer the default. The defaults can be set in ~/.monshowrc. This requires the latest Perl module (Mon-0.4). Also added "--old" option. -Added man page for monshow. -Updated some docs in mon.1 -Don't complain if userfile does not exist and the authtype is not userfile. -Patched in Gilles' historicfile stuff, and documented it in mon.1, and fixed some bugs. -Alerts are no longer called with -l parameter. It's never been documented, and no alerts use it, so I'm ditching it. -version command returns a value like "0.38.9" rather than a float. -Separated alert calling function from the function which determines if an alert should be called. -Alerts are now forked with a separate environment than the parent. -"test alert|upalert|startupalert" client command added, which will immediately call an alert for testing purposes. Updated the docs for moncmd to reflect this command. Changes between mon-0.38pre7 and mon-0.38.8 --------------------------------------------- -mon is now kept under CVS control (exclusively to maintain my own personal sanity). The Perl module is distributed as a separate file now, so that it can find its home in the CPAN module directory. -Documented "traptimeout" and "trapduration", and cleaned up some docs in mon.1. -Included upalerts and startupalerts in gen_scriptdir_hash() -Lots of code cleanups in read_cf. -alertafter now has two forms, one just like before, and one with a single integer argument which alerts after some number of consecutive failures. -I should have done this long ago. %watch now looks like this: $watch{$group}->{$service} instead of $watch{$group}[$service] and $service is the text of the service, not an integer. -Lots of code cleanups regarding global variables which are altered by read_cf. -Fixed "list successes" and "list failures" command. -Added "clear timers" command which clears the timers for things like alertafter and alertevery and such. -netappfree.monitor has some MIB reading changes which fixes the core dumping problem. -Added set_op_status. -Removed some debug cruft from check_depend. -Fix to $fhandles{"$group/$service"}. -Updated "-h" output to be accurate. -Test -f to see if an alert or monitor exists before trying to exec it. -gilles reported a problem with the servertime output, which was fixed. -"interval" initialization was supplying a default interval, which isn't cool because it didn't allow you to have a service w/o an interval for use as a trap sink. The new default is undef. -I started work on muxpect, which is sort of a combination of the mux capabilities of fping and doing Expect-style chat sequences over TCP sockets. It is meant to replace those millions of TCP-based monitors in the mon.d directory with a less CPU-intensive version. -Some alert decision code moved from proc_cleanup to do_alert where it belongs. -Changed some trap code. Changes between mon-0.38pre6 and mon-0.38pre7 --------------------------------------------- -Added "basedir=" and -b, and "cfbasedir=" and -B -use usleep. -Added startupalerts which are called upon startup. -alerts called with env variable MON_ALERTTYPE -logdir, added downtime logging via dtlogging/dtlogfile -Periods can now be specified using a LABEL: tag (similar to labeling blocks and loops in Perl). This allows multiple periods with the same period value. This feature is useful because the "alertafter" and "alertevery" counters are kept on a per-period basis. -Fixed process.monitor to use the new values for the process table in the UCD MIB. -Fixed a problem with reload and path/file expansion. -Alerts are now called with MON_RETVAL set to the exit value of the monitor. -Added trap.alert. Not quite documented. -Added version command to Mon::Client, thanks to nagel@intelenet.net. Changes between mon-0.38pre5 and mon-0.38pre6 --------------------------------------------- -Some small adjustments to fping.monitor. -SNMP trap reception is now part of the I/O loop. -Began work on handle_snmp_trap, and got rid of SNMP-related junk in handle_trap. -Fixed problem with whitespace and monitors ending in ";;" reported by llee@stevens-tech.edu. -mon now has an officially assigned port number from the IANA. It is 2583, and the appropriate adjustments have been made to the clients. -Fixed sock_write in server to handle EAGAIN condition when kernel socket buffers fill up. -Added dialin.monitor which checks to see if dial-in modem lines are operational. It requires the Perl Expect module. Documentation is in doc/README.monitors. -Added an incomplete na_quota.monitor which is meant to monitor Network Appliance quota trees. Changes between mon-0.38pre4 and mon-0.38pre5 --------------------------------------------- -Fixed bug #3, problem with %alias -Fixed bug #4, problem with unpacking a socket which wasn't really a socket yet (out of order assignments) -Renamed Client to Mon-0.01 to follow the Perl module naming convention better, and to make room for things like logging modules and such. -Implemented more protocol commands to Mon::Client. Only 4 left... -Adjusted nntp.monitor to allow for some protocol / implementation inconsistencies. The commands now strictly follow RFC977. -Fixed problem with 0.38 protocol and Mon::Client. -Added multiple authentication types, including getpwnam, shadow, and userfile. Read the man page for details. -Added "version" client command to identify the protocol version. -Added host && user authentication to traps. Configuration is done in auth.cf. No documentation yet. -Added simple downtime logging, and documented it in mon.1. -Tiny change to reboot.monitor. -Added Mon::SNMP module to decode SNMP traps. -Added pod to Mon::Client. I think it took as long to code it as it did to document it. Changes between mon-0.38pre3 and mon-0.38pre4 --------------------------------------------- -Added fixes from Chris Adams that correct some $ALERTDIR and monitor argument problems. -Fixes to monstatus from brian moore. -Another fix to get the "exit=n" stuff working with alerts again, broken because of ALERTHASH code. -Wrote "monshow" in the clients directory, which is a per-user configurable command-line client. -Mon::Client perl module included to help simplify writing clients. It doesn't implement a number of commands yet. Look at the end of Client.pm to see which commands have been implemented and which have not been. "monshow" is in the clients directory, and it is an example of how to use the Mon::Client module. Mon::Client also needs POD documentation. Changes between mon-0.38pre2 and mon-0.38pre3 --------------------------------------------- -Added "ack" client command, which will acknowledge a service failure and surppress all further alerts for that service while it continues to fail. See the moncmd man page for details. You can "ack" with a string of text. -alertdir and scriptdir can now contain multiple colon-separated paths. This feature is useful for keeping site-specific monitors and alerts in their own directory which is separate from the monitors which are distributed with mon itself. Updated the docs for this. A hash is generated after each time the configuration is read which holds the location of where each monitor and alert script can be found. Errors are reported via syslog, so pay attention to them. -Some "alias" code tweaks. Gilles, does it work??? If no, send the patch. -Poked a little with the trap code. The trap format now contains a "spc" tag which specifies the specific type of trap, like maybe SNMPv1 or SNMPv2 or "mon 0.38". -An update to rpc.monitor to let it build under Solaris. It can now also check to see if an arbitrary RPC program number is registered. Documentation updates. Changes between mon-0.38pre1 and mon-0.38pre2 --------------------------------------------- -Some fixed from brian moore to correct client hangups -netappfree.monitor changes, including --list option to list the filesystems on the filers for help in building a config file. -Trap handling changes, including packet format. More provisions for direct SNMP handling. I might add direct provisions for mon to take SNMP traps directly. UCD SNMP trap handling callback mechanism doesn't fit into mon very well. -"list opstatus" output is now different -Time::HiRes is now required. The trick is that handle_io() wants to spend $SLEEPINT handling I/O from clients. Some OSs allow select(2) to return the time remaining, which we want because if select returned in say, 0.2 seconds then we want to call select with a timeout of 0.8 seconds so that we get the full second of waiting for I/O. Some OSs do *not* return the time remaining from a select call, and time(2) doesn't return sub-second resolution, so we need gettimeofday(2) to figure out how long select spent waiting. I guess the whole point here is to try to handle traps as soon as they come in. -Fixed @last_failures discrepancy with traps. -Added Gilles' alias record stuff to config file -Included Jon Meek's up_rtt.monitor which checks the availability of hosts and logs some statistics, like min/mean/max round trip times. Requires Time::HiRes and Statistics::Descriptive. Changes between mon-0.37l and mon-0.38 --------------------------------------- -Asynchronous trap handling. A remote agent may deliver a trap to trigger some action to be performed by a centralized mon server. -Client I/O entirely re-written to support multiple simultaneous non-blocking clients. -New client commands: test, set opstatus, list descriptions -Descriptions are now allowed in service definitions -Added Gilles' my-mon.cgi web interface. -Added Jing Tan's dependency code -When a service comes back up, it resets _first_failure so that alertevery does the right thing. -When handling a "term" from the client, kill -15 children instead of -9. -A fix from brian moore which corrected the client timeouts. -Added "servertime" client command. -Fixed moncmd to be more batch-friendly. -Some security patches to mon.cgi from Roderick Schertler, including and changes to mon and the documentation for Debian compatability. -Added "reload auth" command, which reloads the authentication table. -Added per-service environment variable passing to monitor and alert scripts. -Fixed '"no summary" with upalerts' problem reported by Eric Buda . The output of successful monitors could be lost under certain circumstances. -Fixed a small problem with upalerts reported by Josh Wilmes . Upalerts would be triggered for everything the first time mon is started. -process.monitor may optionally not load the MIBs upon startup. -"-A" option would not make itself relative to the directory that mon was started from. -netpage.alert not calls sendmail rather than "mail -s". Another fix from Josh Wilmes. -A trivial tweak to nntp.monitor. -Fixed problem with hostgroups named with periods reported by several people. This would cause a monitor process to not ever get cleaned up. -Changed how load_auth handles errors -fping.monitor adds a newline (right after removing it with tr :) -changed the debug behavior to allow multiple debug levels Changes between mon-0.37k and mon-0.37l --------------------------------------- -Config parser change from Michael Griffith that complains when "alertafter" will never trigger an alert. -Added "savestate" and "loadstate". Currently these only save and load the state of things disabled. -The server now can authenticate clients using a simple configuration file which can restrict certain users to using only some (or all) commands. "moncmd" was updated to support this feature. -Addition of "upalerts" which may be called when a service changes state from failure to success. "upalerts" can be controlled by the "upalertafter" parameter. -"alertevery" now ignores detailed output when it decides whether or not to send an alert. Patch submitted by brian moore . -"hostgroup and hyphen" patch. This simple patch will allow hyphens and periods in hostgroup tags. -Multiline output fixes in smtp.monitor -Now monitors are not called when no host arguments are supplied. This can be overridden with the per-service "allow_empty_group" option. -A fix to ftp.monitor by Tiago Severina which allows for multiple 220 lines in the greeting from the FTP server. -Added snpp.alert, contributed by Mike Dorman . This requires the SNPP Perl module. -Added ldap.monitor, contributed by David Eckelkamp . This requires the Net::LDAPapi module. -Added dns.monitor, contributed by David Eckelkamp . This requires the Net::DNS module. -Monitor definitions can now include shell-like quoted words, as defined by the Text::ParseWords module (included with perl5). e.g.: monitor something.monitor -f "this is an argument" -a arg -"allow_empty_group" is a new per-service option. If set, monitors will still be run even if all hosts in the applicable hostgroup have been disabled. The default is that allow_empty_group is not set. -Monitors are now forked with stdin connected to /dev/null. -Added "stop" and "start" commands which let make the server cease from scheduling any monitors. While stopped, clients can still be handled. The server may be started[sic] in "stopped" mode with -S. There is now a "reset stopped", which is an atomic version of "reset" and "stop". This is useful if you want to re-disable things immediately after a reset, so there will be no race conditions after the reset and before you disable things. opstatus.cgi now also reports the state of the scheduler. -Updated documentation for monitors, the main "mon" manual, and the "moncmd" manual. -Fixed a few problems in handle_client that had to do with shutting the server down. Changes between mon-0.37j and mon-0.37k --------------------------------------- -ftp.monitor defaults to the SMTP port instead of FTP! Thanks to ryde@tripnet.se for pointing this out :) -alanr@bell-labs.com added "-u" flag to http.monitor so that you can specify the URL to get. -Added hpnp monitor, which uses SNMP to query your HP JetDirect boards in your printers, and warns you when things go awry. For example, if there is a paper jam, mon can send out email telling you exactly that, and it includes in the mail the current readout on the printer's LCD. -Added netappfree.monitor, which uses SNMP to get the free space from Network Appliance filers. Uses a configuration file to set low-watermarks for each filer. -Added process.monitor (thanks to Brian Moore), which queries the UCD SNMP agents to determine if there are errors with particular processes on a machine. This is very useful for monitoring those processes which seem to die off on occasion :) Changes between mon-0.37i and mon-0.37j --------------------------------------- Tue Apr 14 19:22:13 PDT 1998 -Configuration parser now dies when a watch is "accidentally" re-defined. -Added process throttle to prevent a number of forked processes to go beyond a given value. This is a paranoia "safety net" setting. Changes between mon-0.37h and mon-0.37i --------------------------------------- Sun Apr 5 13:59:07 PDT 1998 -Added "randstart" and "randskew" parameters that can help balance out the load from services which are sheduled at the same interval. -Added "exit=range" argument to "alert", which allows triggering alerts based on the exit status of a monitor script. -Added an IMAP monitor, and an SNMP "reboot" monitor -Added http_t.monitor, which times HTTP transactions -Merged in patches supplied by Roderick Schertler - Changes to mon: - Support a pid file. This is necessary for the system's daemon control script (which stops and starts the daemon, plus tells it to reload its configuration) to work. - Treat SIGINT like SIGTERM (for interactive debugging). - Allow a `hostgroup' line in mon.cf which doesn't have any host names (useful for putting each host name on a line by itself). - Add `d' (meaning `days') to the list of suffixes accepted by the interval and alertevery keywords. - Squelch extra blank line output by alerthist and failurehist commands if there are no corresponding history entries. - Bug fix: fork() returns undef, not -1, on error. - Set umask 022, no 0. - Changes to mon.cgi: - Set -T mode. - Allow all local info fields to be blank, and set them that way by default. - Use the same default mon host as the other interfaces. - Use $ENV{SCRIPT_NAME} as the default $url. - Don't hardcode the path to mon, assume it is in the path. - Vet the name passed to the `list group' command. The old code would allow remote users to run arbitrary local commands. - Changes to opstatus.cgi: - Set -T mode. - Correct port, was 32768 should be 32777. - Add missing Content-Type to html_die(). - In monstatus correct the my() line in populate_group(), and add missing $group initialization. - Tweak typesetting in the mon.1 and moncmd.1 man pages. Changes between mon-0.37g and mon-0.37h --------------------------------------- Mon Jan 19 07:22:14 PST 1998 -I didn't merge back in a change to fping.monitor which sorts the output of fping, this causing alerts to go off unnecessarily when fping would return hosts in a different order each time it is run. An alert is send once every "alertevery" interval, unless the output changes. This is where it messed things up. -added GPL header to all source files. Changes between mon-0.37f and mon-0.37g ---------------------------------------- Sat Jan 10 10:40:26 PST 1998 -Fixed memory leak, with the help of Martin Laubach and Ulrich Pfeifer. The Perl 4.004_04 IPC::Open2 routine has a leak in it. -Now includes the SkyTel 2-way pager interface for mon! What a hack, but it works pretty well! -Also includes Art Chan's interactive web interface. It has buttons and graphics and all that other stuff that everyone wants! -Removed the Perl 5.003 Sys::Syslog patches. I don't want to encourage anyone to use an outdated version of Perl, especially since there have been plenty of bug fixes since then. -Server now handles multiple commands per client connection, and opstatus.cgi has been changed to take advantage of this. It's much faster now. Changes between mon-0.37e and mon-0.37f ---------------------------------------- Fri Oct 3 06:14:50 PDT 1997 -Fixed a small typo in "mon.d/freespace.monitor" that would correctly detect a failure condition for low disk space, but the text that it would report was incorrect. -As per Sean Robinson's suggestions, renamed the syslog patches to Perl 5.004 to accurately reflect what versions of Perl they patch. -In "mon.d/http.monitor", fixed problem with what matches as a valid HTTP response. "200 OK" is incorrect, because the text that follows the 200 is undefined in the specs. etbemon-1.3.6/COPYING0000644000000000000000000004322010061516613011073 0ustar $Id: COPYING,v 1.1.1.1 2004/06/09 05:18:03 trockij Exp $ GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. etbemon-1.3.6/COPYRIGHT0000644000000000000000000000150310061516613011331 0ustar $Id: COPYRIGHT,v 1.1.1.1 2004/06/09 05:18:03 trockij Exp $ The code in this distribution is Copyright (c) 1997-2001 by Jim Trocki. The copyrights of individual contributions are held by the respective authors of those contributions and/or their successors in interest. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. etbemon-1.3.6/CREDITS0000644000000000000000000000506310146140374011064 0ustar $Id: CREDITS,v 1.2 2004/11/15 14:45:16 vitroth Exp $ This is a list of people who have contributed code and/or ideas to mon itself or its other components. Jon Meek meekj@pt.cyanamid.com Lots of ideas, inital testing under Solaris, and http.monitor code. David Nolan vitroth+@cmu.edu Many bug fixes and feature additions. David probably runs the largest mon installation in existence. Ed Ravin eravin@panix.com Bug fixes, many enhancements to monitors, feature additions, and fixes for BSD-isms. Martin J. Laubach mjl@emsi.priv.at Bug fixes, scheduler enhancements. Gilles Lamiral lamiral@mail.dotcom.fr Minotaur CGI interface, lots of bug fixes and enhancements. Arthur K. Chan artchan@althem.com Initial version of interactive WWW interface (mon.cgi). Ulrich Pfeifer pfeifer@wait.de Lots of code cleanups, and removal of the Open2 mess. Alan Cox alan@cymru.net Initial suggestion for "alertafter" parameter. David Eckelkamp davide@tradewave.com Supplied "monstatus" command-line utility, and LDAP and DNS monitor. Eric Saxe eric@Zcompany.com Found CR/LF bug in smtp.monitor Peter Gervai grin@tolna.net Found bug in config parser, suggested process throttle option. Michael Griffith grif@cadence.com Added some sanity checking to the config parser. Brian Moore bem@cmc.net 'summary' option for alerts. Michael Alan Dorman mdorman@@debian.org Contributed Perl SNPP alert. Alan Robertson alanr@bell-labs.com Maintains the RedHat RPM. Roderick Schertler roderick@argon.org Maintains the Debian package. Tiago Severina ts@uevora.pt Reported some bugs with FTP.monitor, and is currently working on the dependency code. Tiago has been actively contributing his patches that include inherited dependency support, and once this code stabilizes and is thoroughly tested in a production environment, it will be released. It is some really great stuff--thanks, Tiago! Jing Tan jing@walrus.com Jing has contributed the dependency code which is included in the distribution as of 0.38. James FitzGibbon james@ican.net Contributed msql/mysql monitor. Mark D. Nagel nagel@intelenet.net Submitted version command for Mon::Client module. Lars Marowsky-Bree lmb@teuto.net Added trap code to Mon::Client, contributed syslog.monitor, and fixed some bugs. Mark Wagner markw@horvitznewspapers.net Bug fixes and other contributions. Andrew Ryan andrewr@mycfo.com mon.cgi v1.32 and later, bug reports and fixes. Eric Sorenson eric@transmeta.com Documentation and RPM spec updates etbemon-1.3.6/INSTALL0000644000000000000000000001570410637741301011102 0ustar $Id: INSTALL,v 1.2.2.3 2007/06/25 13:27:29 trockij Exp $ OVERVIEW -------- There are several components you'll need to get working to have a fully functional mon installation. 1. mon, the server 2. Mon::Client, the Perl library used by some clients 3. C programs in mon.d 4. Optional (but highly useful) monitors 5. A customized mon.cf to make the server do what you want 1. MON SERVER ------------- The "mon" daemon uses Perl 5.n, where n >= 005_01. Mon requires that *.ph be created from the system header files. If you try to run mon and Perl complains with the "did you run h2ph?" message, then chances are this step wasn't done, either by your package manager or manually after Perl installation. You can fix it by doing the following, as root: cd /usr/include h2ph -r -l . You'll need the following modules for the server to function, all of which are available from your nearest CPAN archive. The listed CPAN paths relative to /cpan/modules/by-authors/id/ -- versions of modules on CPAN change quickly, so there may be newer versions available, but the following are known to work: Time::Period PRYAN/Period-1.20.tar.gz Time::HiRes J/JH/JHI/Time-HiRes-1.59.tar.gz 2. INSTALLING THE PERL CLIENT MODULE ------------------------------------ The Perl client module is distributed as a separate package, and is required for the web interfaces "mon.cgi" and "monshow" and for "moncmd". It is named "mon-client-*.tar.gz". Refer to that for installation instructions. It is available on kernel.org mirrors in the /pub/software/admin/mon directory, and in CVS on sourceforge.net. Be sure to match the version of mon-client with the version of mon you are using. At this time, branch "mon-1-2-branch" of the mon CVS module matches the "mon-client-1-2-branch" branch of the mon-client CVS module. See http://sourceforge.net/projects/mon/ for information on CVS access. 3. COMPILING THE C CODE (optional) ---------------------------------- Some of the monitors included with mon are written in C and need to be compiled for your system. If you want to use the RPC monitor or the dialin.monitor wrapper, cd mon.d (edit Makefile) make make install cd .. Keep in mind that although this is known to work on Linux, Solaris, and AIX, it may not compile on your system. It is not required for the operation of mon itself. 4. MONITORS ----------- All of the monitor and alert scripts that are packaged with mon are actually optional in that mon will only use the monitors which you have specified in your configuration. There is no need to install any extra dependencies, such as Perl modules, for monitors which you will not be using. You may test to see if a monitor works outside of mon by simply running it from the command line, giving it a host as an argument. For example: $ ./fping.monitor uplift start time: Mon Jun 25 07:52:34 2007 end time : Mon Jun 25 07:52:34 2007 duration : 0 seconds -------------------------------------------------------------------------- reachable hosts rtt -------------------------------------------------------------------------- uplift 0.07 ms Some monitors may need Perl modules which may not already be installed on your system. To determine if you have the requisite modules installed, you can pass the monitor to "perl -c" and see if it says "OK", like this: $ perl -c fping.monitor fping.monitor syntax OK If it gripes about "Can't locate...", then what follows are the modules which you'll need to install from CPAN. Monitors may have their own embedded documentation at the top, and some may provide their own POD (viewable with "pod2man xyz.monitor | nroff -man"). There may also be some additional documentation on some monitors in the "doc" directory of the root of the tarball. 5. MON.CF CUSTOMIZATION AND STARTUP ----------------------------------- -You may want to begin learning about mon by following the slides from the presentation. They cover the components, what they do, how they relate, and how it all works together. Find them here: http://mon.wiki.kernel.org/index.php/Documentation -Read the man page for "mon" and "moncmd" in the doc/ directory to get an overview of the directories involved, i.e. the configuration, alert, monitors, state, and run directories. cd doc nroff -man mon.8 | more -read the "READMEs" in the doc/ directory for some useful insight on system configuration. -Make your own mon.cf file, using the suppled "example.cf" (located in the etc/ directory) as a template, or the m4-based "example.m4": cp etc/example.cf mon.cf or cp etc/example.m4 mon.m4 -Edit the "auth.cf" file. This file controls which users can perform what command. The default is pretty restrictive (read-only), but that's only for safety. Currently, "moncmd", "monshow", and "mon.cgi" are the only clients which are able to authenticate themselves to the server; the 2-way pager interface does not yet perform authentication. However, these programs work fine in read-only mode. -Add the following lines to /etc/services: mon 2583/tcp # MON mon 2583/udp # MON traps -You may want to make a DNS CNAME entry called "monhost" for your host that will run "mon". You can then set the environment variable MONHOST to be this host. "moncmd" uses this variable. -The Perl scripts look for perl in /usr/bin. You might want to change this. I'd advise keeping a locally-installed copy of Perl if you're going to monitor network resources and you expect this stuff to work when some component of the network is down. -Test it by starting "mon" from the distribution directory. Use these arguments if you chose the non-m4 config: ./mon -f -c mon.cf -b `pwd` and these arguments for the m4-based config: ./mon -f -M -c mon.m4 -b `pwd` To see if it's running on your machine: ./clients/moncmd -s localhost list pids If you get some output, then things are probably OK. Check the syslog for further diagnostics. Mon doesn't really need to be installed in any special location. Just keep it on the local disk of the machine which will be running the server. WEB INTERFACE ------------- This distribution contains two web interfaces: monshow and mon.cgi. monshow is a simple report-only tool which supports configurable "views" of the mon configuration. monshow also operates as a textmode report generator. mon.cgi, however, supports the full functionality of mon, including the ability to disable/enable groups and hosts and services, acknowledge failed services, show alert and downtime history, authenticate users, among many other things. To install monshow, simply copy clients/monshow into your web server's cgi-bin path and name it "monshow.cgi". You may want to read the man page in the doc/ directory so that you can understand how to configure a "view" to your liking. To install mon.cgi, follow the instructions found in doc/README.mon.cgi. etbemon-1.3.6/KNOWN-PROBLEMS0000644000000000000000000000027510146140374012104 0ustar # # $Name: mon-1-2-0-release $ # KNOWN PROBLEMS in $Name: mon-1-2-0-release $ ------------------------------ clients/skymon has not yet been updated to work with the new Mon::Client API. etbemon-1.3.6/README0000644000000000000000000000675610637737255010755 0ustar $Name: mon-1-2-0-release $ $Id: README,v 1.3.2.2 2007/06/25 13:10:05 trockij Exp $ INTRODUCTION ------------ "mon" is a tool for monitoring the availability of services, and sending alerts on prescribed events. Services are defined as anything tested by a "monitor" program, which can be something as simple as pinging a system, or as complex as analyzing the results of an application-level transaction. Alerts are actions such as sending emails, making submissions to ticketing systems, or triggering resource fail-over in a high-availability cluster. The tool is extremely useful for system administrators, but not limited to use by them. It was designed to be a general-purpose problem alerting system, separating the tasks of testing services for availability and sending alerts when things fail. To achieve this, "mon" is implemented as a scheduler which runs the programs which do the testing, and triggering alert programs when these scripts detect failure. Alerts can be controlled by a variety of "squelch" knobs, and complex dependencies can be configured to help suppress excessive alerts. None of the actual service testing or reporting is actually handled directly by the mon server itself. These functions are handled by auxillary programs. This model was chosen because it is very extensible, and does not require changing the code of the scheduler to add new tests or alert types. For example, an alphanumeric paging alert can be added simply by writing a new alert script, and referencing the alert script in the configuration file. Monitoring the temperature in a room can be done by adding a script that gathers data from a thermistor via a serial port. Often these monitoring scripts can just be wrappers for pre-existing software, such as "ping" or "ftp". The mon scheduler also can service network clients, allowing manipulation of run-time parameters, disabling and enabling of alerts and tests, listing failure and alert history, and reporting of current states of all monitors. There are several clients which come with the distribution, found in cgi-bin/ and clients/ : -moncmd, which is a command-line client. moncmd supports the full functionality of the client/server interface. -monshow, a dual command-line and CGI interface report generator for showing the operational status of the services monitored by the server. It displays nicely-formatted columnar output of the current operational status, groups, and the failure log. -skymon, which is a SkyTel 2-Way paging interface, allowing you to query the server's state and to manipulate it in the same manner as moncmd, right from your pager. Access is controlled via a simple password and an access control file. -mon.cgi, which is an interactive web interface, allowing you to not only view status information, but to change parameters in the server while it is running. AVAILABILITY ------------ The latest release of mon is available from kernel.org in /pub/software/admin/mon/. Please choose a mirror from: http://www.kernel.org/mirrors/ The WWW page is at http://www.kernel.org/software/mon/ CVS --- CVS trees of both the development trunk and stable release branches are available from anonymous CVS access on sourceforge.net. To check out the latest, see: http://mon.wiki.kernel.org/index.php/Development INSTALLATION ------------ See the "INSTALL" file for installation instructions. ---------- Jim Trocki Software Engineer Linux Systems Group Unisys Malvern, PA etbemon-1.3.6/TODO0000644000000000000000000003256510640447465010555 0ustar -implement trap delivery for "redistribute" in the mon server itself as an option. retain the "call script" behavior, but maybe specify internal trap delivery via "redistribute -h hostname [hostname...]". also allow multiple redistribute lines to build a list of scripts to call -deliver traps with acknowledgement via tcp -add protocol commands to dump entire status + configuration in one operation to reduce latency (not so many serialized get/response operations just to get status) -no alerts for n mins -better cookbook of examples, including some pre-fab m4 defines for templates with focus on the ability to quickly configure mon out-of-the-box for the most common setups -period "templates" > like I have to repeat my period definitions all 260 times, one for > each watch. we should have templates in the Mon config file for any > kind of object so it can be reused. so do you mean a way to define a "template" for a period so that you don't need to keep rewriting "wd {Sun-Sat}", or so that it'll use some default period if you don't specify one, or what? i can see this working a bunch of different ways. like this? define period-template xyz period wd {Sun-Sat} alert mail.alert mis@domain.com alert page.alert mis-pagers@domain.com alertevery 1h watch something service something period template(xyz) watch somethingelse service something period template(xyz) # override the 1h alertevery 2h -my recent thoughts on config management are that the parsing should be all modularized, (a keeping the config parsing code in a separate perl module to be reused by other apps), and there should be a way to turn the resulting data structure into xml and importing the same back, not so you can write your config by hand in xml, but so you can use some generic xml editing tool to mess around with the config, to get one type of gui. -the most common things should be easiest to do, regardless of a gui or text file config. that is what makes stuff "easy". however, i don't think more complicated setups lend themselves to guis as much, and in complicated setups you have to invest a lot of time to learn how the tool works, and a fancy gui in that case is less of a payoff. this is for configuration, i mean. fancy guis for reporting and stuff are good, no doubt. -global alert definitions with their own squelches (alertevery, etc.) > also, alarms need to be collated so pagers and cell phones don't get > buried with large numbers of alerts. I have a custom solution that I > wrote for this, but it's a lousy solution since it essentially implements > its own paging system. i could see how it would be good to be able to define some alert destinations *outside* of the period definitions, then refer to them in the period definitions, then you can do "collation" that way. like this: define global-alert xyz mail.alert xyz@lmnop.com alertevery 1h watch service period globalalert xyz <---collated globally watch service period globalalert xyz <---collated globally alert mail.alert pdq@lmnop.com <---not collated that would be quite easy to do and i think very useful. you could apply all the same squelch knobs (alertevery, etc.) to the global ones. ----- (from mon-1.2.0) $Id: TODO,v 1.2.2.1 2007/06/27 11:51:17 trockij Exp $ -add short a "radius howto" to the doc/ directory. -make traps authenticate via the same scheme used to obscure the password in RADIUS packets -descriptions defined in mon.cf should be 'quoted' -document command section and trap section in authfile -finish support for receiving snmp traps -output to client should be buffered and incorporated into the I/O loop. There is the danger that a sock_write to a client will block the server. -finish muxpect -make "chainable" alerts ?? i don't recall who asked for this or how it would work -make alerts nonblocking, and handle them in a similar fashion to monitors. i.e., serialize per-service (or per-period) alerts. -document "clear" client command -Document trap authentication. -Document traps. -Make monitors parallelize their tasks, similar to fping.monitor. This is an important scalability problem. -re-vamp the host disabling. 1) store them in a table with a timeout on each so that they can automatically re-enable themselves so people don't forget to re-enable them manually. 2) don't do the disabling by "commenting" them out of the host groups. We still want them to be tested for failure, but just disable alerts that have to do with the disabled hosts. When a host is commented out, accept a "reason" field that is later accessible so that you can tell why someone disabled the host. -allow checking a service at a particular time of day, maybe using inPeriod. -maybe make a command that will disable an alert for a certain amount of time -make it possible to disable just one of multiple alarms in a service -make a logging facility which forks and execs external logging daemons and writes to them via some ipc such as unix domain socket. mon should be sure that one of each type of these loggers is running at all times. configure the logging either globally or for each service. write both the success and failure status to the log in some "list opstatus" type format. each logger can do as it wishes with the data (e.g. stuff it into rrdtool, mysql, cat it to a file, etc.) # global setting logger = file watch stuff service http logger file -p _LOGDIR_ ... service fping # this will use the global logger setting ... service # this will override the global logger setting logger none ... common options to logger: -d dir path to logging dir -f file name of log file -g, -s group, service ----------- notes on a v2 protocol redesign from trockij - Configuring on a hostgroup scheme works very well. In the beginning, mon was never intended to get this complex(tm), it was intended to be a tool where it was easy to whip up custom monitoring scripts and alert scripts and plug them into a framework which allowed them all to connect to each other, and to have a way to easily build custom clients and report generators as well. - However, per host status is needed now. - This requires changes to both mon itself and also the monitors / alerts. Backward compatibility is important, and KISS is very important to retain the ease at which one can whip up a new monitor or alert or reporting client. - There will be a new protocol for communicating with the monitors / alerts, which will be masked by a Mon::Monitor / Mon::Alert module in Perl. Appropriate shell functions will be provided by the first one who asks. See below for the protocol. - We still want to retain the benefits of the old behaviour, but extend some alert management features, such as the ability to liberate alert definitions from the service periods so they can be used globally. - The server code might be broken up into multiple files (I/O routines, config parser, related parts, etc) - monitors can communicate better with the alerts (see below). For example, the monitor might hint (using "a_mail_list") the mail.alert about where else to send a warning that a user dir goes over quota. (Attention should be paid to privacy that we don't accidentially inform all users that /home/foo/how-i-will-destroy-western-civilization/ is consuming 1GB too much space ;) - Associations: these allow monitors to communicate details about failures back to the server which can be used to specify who to alert. The associations are based on key/value pairs specified in the association config file, and are expanded on the alert command line (or possibly within the alert protocol) if "@assoc-*" is in the configuration. If a host assoc. is needed, an alert spec will look like: alert mail.alert admin@xyz.com @assoc-host There are two association types (possibly more in the future): host associations, and user-defined associations. Host associations use the "assoc-host" specifier, and map one or more username to an individual host. User-defined associations are just that, and begin with the "assoc-u-" specifier. Monitors return associations via the "assoc-*" key in the monitor protocol. Alerts obtain association information either via command-line arguments which were expanded by the server from "@assoc-*" in the config file, or via the "assoc-*" key in the alert protocol. - Metrics are only passed to the mon server for "monitoring" purposes, but can be marked up in such a way that they could be easily piped to a logging utility, one which is not part of the mon process itself. monitors are _encouraged_ to collect and report performance data. "Failures" are basically just a conclusion based upon performance data and it makes no sense to collect the data twice, e.g. if you have mon polling ifInOctets.0 on a system, why should mrtg have to poll on its own. It may be desireable to propose a "unified logging system" which all monitors can easily use, something which is pluggable and extensible - The hostgroup syntax is going to be extended to add per host options. (which will be passed to the monitors / alerts using the new protocol) ns1.teuto.net( fs="/(80%,90%)",mail_list="lmb@teuto.net" ) would be passed as "h_fs=/(80%,90%)" and "h_mail_list="lmb@teuto.net" FLOATING MONITORS A floating monitor is started by mon and remains running for the entire time. If it dies, it is automatically restarted. The server forks off a separate process for fping and communicates with it via some IPC, like a named pipe or a socket or something. The floating monitor sits there waiting for a message from the server that says "start checking now". The server then adds this descriptor to %fhandles and %running and treats it similar to other forked monitors. When the floting monitor is done, it spits its output back to the server and then goes dormant again, awaiting another message from the server. Floating monitors are started when mon starts, and are restarted if mon notices that they go away. This is a way to save on fork() overhead, but to also PROTOCOL The protocol will be simple and ASCII based, in the form of "key=value". Line continuation will be provided by prefixing following lines with a ">". A "\n" on a line by itself indicates the start of a new block. The order of the keys should not be important. The first block will always contain metadata further defining the following blocks. The "version" key is always present. The current protocol version is "1". (In the examples, everything after a "#" is a comment and should be cut out) KEY CONVENTIONS Keys only private to monitors will be prefixed with an "m_". In the same vain, keys private to alerts will be prefixed with a "a_", and additional host option keys specified in the mon.cf file will be prefixed with a "h_" before being passed to monitors/alerts. By convention, flags only pertaining to a specific alert will embed that name in the key name too - ie keys only pertaining to "mail.alert" will start with "a_mail_". The key/values pairs will be passed to all processes for a specific service. "h_" are static between invocations as they come from the mon.cf file. "m_" keys will be preserved between multiple monitor executions. "a_" keys will be passed from the monitor to the alert script. MONITOR PROTOCOL (monitor -> mon) The metadata block is followed by a block describing the overall hostgroup status, followed by a detailled status for each host. The following keys are defined for the blocks: "summary" = contains a one line short summary of the status. "status" = up, fail, ignore "metric_1" = an opaque floating point number which can be referenced for triggering alerts. May try to give an "operational percentage". More than one metric may be returned. (Ping rtt, packet loss, disk space etc) "description" = longer elaborate description of the current status. "host" = hostgroup member to which this status applies. The overall hostgroup status does not include this field. "assoc-host" = host association "assoc-u-*" = user-defined association Here is an example for a hypothetical hostgroup with 2 hosts and the ping service. ### version=1 summary=Still alive. metric_1=50 # Packetloss metric_2=20.23 # rtt times description=1 out of 2 hosts still responding. > Whatever else one might want to say about the status. It is difficult to > come up with a good text here so I will just babble. status=up host=foo.bar.com metric_1=100 metric_2=0 # 100% packet loss make rtt measurements difficult ;) summary=ICMP unreachable from 2.2.2.2 status=fail description=PING 2.2.2.2 (2.2.2.2): 56 data bytes > >--- 2.2.2.2 ping statistics --- >23 packets transmitted, 0 packets received, 100% packet loss metric_1=0 metric_2=52.1 summary=ICMP echo reply received ok status=up description=64 bytes from 212.8.197.2: icmp_seq=0 ttl=60 time=110.0 ms >64 bytes from 212.8.197.2: icmp_seq=1 ttl=60 time=32.3 ms >64 bytes from 212.8.197.2: icmp_seq=2 ttl=60 time=32.8 ms >64 bytes from 212.8.197.2: icmp_seq=3 ttl=60 time=33.4 ms > >--- ns1.teuto.net ping statistics --- >4 packets transmitted, 4 packets received, 0% packet loss >round-trip min/avg/max = 32.3/52.1/110.0 ms host=baz.bar.com ###### Points still open: - mon -> monitor communication - mon <-> alert communication - the new trap protocol - muxpect - a unified logging proposal etbemon-1.3.6/VERSION0000644000000000000000000000043710146140374011114 0ustar $Name: mon-1-2-0-release $ $Log: VERSION,v $ Revision 1.2 2004/11/15 14:45:16 vitroth Pulling lots of changes from the 1.0.0pre* branch into the HEAD, to prepare to tag mon-1.1pre1 Revision 1.1.1.1.2.1 2004/06/12 18:17:57 trockij added some rcs tags to identify the file versions etbemon-1.3.6/alert.d/0000755000000000000000000000000013700752514011375 5ustar etbemon-1.3.6/alert.d/file.alert0000755000000000000000000000356210230411542013342 0ustar #!/usr/bin/perl # # file.alert - log alert to a file # # The first line from STDIN is summary information, adequate to send # to a pager or email subject line. # # Jim Trocki, trockij@arctic.org # # $Id: file.alert,v 1.2 2005/04/17 07:42:26 trockij Exp $ # # Copyright (C) 1998, Jim Trocki # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # $RCSID='$Id: file.alert,v 1.2 2005/04/17 07:42:26 trockij Exp $'; use Getopt::Std; getopts ("d:S:s:g:h:t:l:uOT"); $summary=; chomp $summary; $summary = $opt_S if (defined $opt_S); $file = shift; $file = "file" if (!defined $file); $file = "$opt_d/$file" if ($opt_d); $ALERT = $ENV{"MON_ALERTTYPE"} || "UNKNOWN ALERT"; if (defined $ENV{"MON_OPSTATUS"}) { $OPSTATUS = $ENV{"MON_OPSTATUS"}; } else { $OPSTATUS = "UNKNOWN OPSTATUS"; } $t = localtime($opt_t); ($wday,$mon,$day,$tm) = split (/\s+/, $t); open (F, ">>$file") || die "could not append to $file: $!\n"; print F <) { print F; } print F ".\n"; close (F); etbemon-1.3.6/alert.d/irc.alert0000755000000000000000000000776310230411542013207 0ustar #!/usr/bin/perl # # irc.alert - irc alert for "mon" # # options are: # -s service # -g group # -h "host1 host2 host3..." # -t tmnow # -u (if upalert) # -T (if trap) # -O (if traptimeout) # # -j join the channel before doing PRIVMSG # (some channel modes prevent PRIVMSG from # user who hasn't joined the channel) # -c channel name of the channel (without leading #) # -S server irc server # -U user user for irc server # -n nick nick # -d post alert detail to irc channel # -N num try num different nicks before giving up # -p secs when showing detail, pause secs between # sending each line. secs may be fractional. # # Jim Trocki, trockij@arctic.org # # $Id: irc.alert,v 1.2 2005/04/17 07:42:26 trockij Exp $ # # Copyright (C) 1998, Jim Trocki # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # use strict; use IO::Socket::INET; use Getopt::Std; use English; my %opt; getopts ("s:g:h:t:uTOjc:S:U:n:dN:p:", \%opt); my $CHAN = $opt{"c"} || "mon"; my $NICK = $opt{"n"} || "mon"; my $USER = $opt{"U"} || $NICK; my $SERVER = $opt{"S"} || die "must supply server via -S\n"; my $NICK_TRIES = $opt{"N"} || 5; my $PAUSE = $opt{"p"} || 0; my $TIMEOUT = 10; # # read in what the mon server sends us about the alert # my $summary = <>; $summary = "UNKNOWN" if ($summary eq ""); my @details; while (<>) { chomp; push @details, $_; } eval { local $SIG{ALRM} = sub { die "Timeout Alarm" }; alarm $TIMEOUT; # # make the connection # my $s = new IO::Socket::INET ( "PeerAddr" => "$SERVER:6667", "Proto" => "tcp", "Timeout" => 10, ); die if (!defined $s); # # register with the irc server # print $s "NICK $NICK\r\n"; print $s "USER $USER uplift.transmeta.com $USER :$USER\r\n"; my $nick_tries = 0; # # if we get in, there will be a "001" reply # from the server. deal with nick collisions. # while (<$s>) { s/\r\n//; # # we're in # last if (/^:\S+\s+001\s/); # # nick already in use, pick a new one # if (/^:\S+\s+433\s/ || /^:\S+\s+432\s/) { if (++$nick_tries >= $NICK_TRIES) { print $s "QUIT\r\n"; die "could not get an unused nick, giving up\n"; } my ($nick, $num) = ($NICK, 0); if ($NICK =~ /_/) { ($nick, $num) = split (/_/, $NICK); } $NICK = "$nick" . "_" . ++$num; print $s "NICK $NICK\r\n"; } } # # /join the channel if requested # if ($opt{"j"}) { print $s "JOIN #$CHAN\r\n"; } my @t = split (/\s+/, scalar (localtime ($opt{"t"} ? $opt{"t"} : time))); my $t = "$t[2]-$t[1] $t[3]"; my $alert = $opt{"u"} ? "UPALERT" : "ALERT"; print $s "PRIVMSG #$CHAN :$alert $t ($opt{g}/$opt{s}): $summary\r\n"; # # print out the detail if requested # if ($opt{"d"}) { foreach my $detail (@details) { print $s "PRIVMSG #$CHAN : $t ($opt{g}/$opt{s}): $detail\r\n"; if ($PAUSE) { my ($rin, $win, $ein); select ($rin, $win, $ein, $PAUSE); } } } # # /leave the channel # if ($opt{"j"}) { print $s "PART #$CHAN\r\n"; } print $s "QUIT :byebye\r\n"; while (<$s>) { # whatever } close $s; alarm 0; }; if ($EVAL_ERROR) { die "$EVAL_ERROR"; } etbemon-1.3.6/alert.d/mail.alert0000755000000000000000000000416013700752425013355 0ustar #!/usr/bin/perl # # mail.alert - Mail alert for mon # # The first line from STDIN is summary information, adequate to send # to a pager or email subject line. # # -f from@addr.x set the smtp envelope "from" address # # Jim Trocki, trockij@arctic.org # # $Id: mail.alert,v 1.3 2005/04/17 07:42:26 trockij Exp $ # # Copyright (C) 1998, Jim Trocki # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # $RCSID='$Id: mail.alert,v 1.3 2005/04/17 07:42:26 trockij Exp $'; use Getopt::Std; use Text::Wrap; getopts ("S:s:g:h:t:l:f:u"); $summary=; chomp $summary; $summary = $opt_S if (defined $opt_S); $mailaddrs = join (',', @ARGV); $mailfrom = "-f $opt_f -F $opt_f" if (defined $opt_f); $ALERT = $opt_u ? "UPALERT" : "ALERT"; $t = localtime($opt_t); ($wday,$mon,$day,$tm) = split (/\s+/, $t); open (MAIL, "| /usr/lib/sendmail -oi -t $mailfrom") || die "could not open pipe to mail: $!\n"; print MAIL <) { print MAIL; } close (MAIL); etbemon-1.3.6/alert.d/mailxmpp.alert0000644000000000000000000000577613700752375014301 0ustar #!/usr/bin/perl use strict; use BSD::Resource; # # mailxmpp.alert - Mail and xmpp alert for mon # # The first line from STDIN is summary information, adequate to send # to a pager or email subject line. # # -f from@addr.x set the smtp envelope "from" address # -x destination xmpp address # -m destination smtp address # # Jim Trocki, trockij@arctic.org # XMPP added by Russell Coker russell@coker.com.au # # $Id: mail.alert,v 1.3 2005/04/17 07:42:26 trockij Exp $ # # Copyright (C) 1998, Jim Trocki # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # setrlimit(RLIMIT_CPU, 5, 5) or die "Can't set CPU time limit to 5 seconds"; use Getopt::Std; use Text::Wrap; our $opt_S; our $opt_s; our $opt_g; our $opt_h; our $opt_l; our $opt_f; our $opt_t; our $opt_u; our $opt_m; our $opt_x; getopts ("S:s:g:h:t:l:f:um:x:"); my $summary=; chomp $summary; $summary = $opt_S if (defined $opt_S); use Sys::Hostname; my $host = hostname; my $mailfrom = "-f $opt_f -F $opt_f" if (defined $opt_f); my $ALERT = $opt_u ? "UPALERT" : "ALERT"; my $t = localtime($opt_t); my ($wday,$mon,$day,$tm) = split (/\s+/, $t); open (MAIL, "| /usr/lib/sendmail -oi -t $mailfrom") || die "could not open pipe to mail: $!\n"; my @xmpprec = split(/,/, $opt_x); # use hostname as the resource open (XMPP, "| /usr/bin/sendxmpp -a /etc/ssl/certs -t @xmpprec -r $host") || die "could not open pipe to sendxmpp: $!\n"; print MAIL <) { print MAIL; print XMPP; } close (MAIL); close (XMPP); etbemon-1.3.6/alert.d/netpage.alert0000755000000000000000000000333110230411542014040 0ustar #!/usr/bin/perl # # netpage.alert - network page alert for mon # # The first line from STDIN is summary information, adequate to send # to a pager or email subject line. Even though this code is entirely # trivial, I wrote it just so that when it's specified in the mon.cf # file, it is clear that the paging alert is network-dependent. # # Jim Trocki, trockij@arctic.org # # $Id: netpage.alert,v 1.2 2005/04/17 07:42:26 trockij Exp $ # # Copyright (C) 1998, Jim Trocki # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # $RCSID='$Id: netpage.alert,v 1.2 2005/04/17 07:42:26 trockij Exp $'; use Getopt::Std; getopts ("s:g:h:t:l:u"); $summary=; chomp $summary; $pageaddrs = join (',', @ARGV); $t = localtime($opt_t); ($wday,$mon,$day,$tm) = split (/\s+/, $t); $ALERT = $opt_u ? "UPALERT" : "ALERT"; open (MAIL, "| /usr/lib/sendmail -oi -t") || die "could not open pipe to mail: $!\n"; print MAIL <) { print MAIL; } close (MAIL); etbemon-1.3.6/alert.d/qpage.alert0000755000000000000000000000401010230411542013505 0ustar #!/usr/bin/perl # # qpage.alert - send an alert via QuickPage # # This will accept multiple pager IDs in @ARGV and call qpage for # each one of them, but you should probably use qpage groups if possible. # # qpage-specific options: # -c coverage area # -f SNPP CALLerid # -l service level # -q SNPP server, translates to "qpage -s" # # Jim Trocki, trockij@arctic.org # # Copyright (C) 1998, Jim Trocki # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # use Getopt::Std; getopts ("s:g:h:t:c:f:l:q:uv"); # # the first line is summary information, adequate to send to a pager # or email subject line # # # the following lines normally contain more detailed information, # but this is monitor-dependent # @MSG=; $summary = shift @MSG; chomp $summary; $t = localtime($opt_t); ($wday,$mon,$day,$tm) = split (/\s+/, $t); $ALERT = $opt_u ? "UPALERT" : "ALERT"; foreach $pagedest (@ARGV) { if ($opt_v) { if (open(QPAGE, "| qpage -p $pagedest 2>/dev/null")) { print QPAGE "$ALERT $opt_g/$opt_s: $summary ($wday $mon $day $tm)\n"; print QPAGE @MSG; close QPAGE; } else { die "could not open pipe to qpage: $!\n"; } } else { if (system ("qpage -p $pagedest " . "'$ALERT $opt_g/$opt_s: $summary ($wday $mon $day $tm)'" . "2>/dev/null")) { die "could not open pipe to qpage: $?\n"; } } } etbemon-1.3.6/alert.d/slackxmpp.alert0000755000000000000000000000526213673303207014440 0ustar #!/usr/bin/perl use strict; use BSD::Resource; # # mailxmpp.alert - Mail and xmpp alert for mon # # The first line from STDIN is summary information, adequate to send # to a pager or email subject line. # # -f from@addr.x set the smtp envelope "from" address # -x destination xmpp address # -m destination smtp address # # Jim Trocki, trockij@arctic.org # XMPP added by Russell Coker russell@coker.com.au # # $Id: mail.alert,v 1.3 2005/04/17 07:42:26 trockij Exp $ # # Copyright (C) 1998, Jim Trocki # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # setrlimit(RLIMIT_CPU, 5, 5) or die "Can't set CPU time limit to 5 seconds"; use Getopt::Std; use Text::Wrap; our $opt_S; our $opt_s; our $opt_g; our $opt_h; our $opt_l; our $opt_t; our $opt_u; our $opt_m; our $opt_x; getopts ("S:s:g:h:t:l:ux:"); my $summary=; chomp $summary; $summary = $opt_S if (defined $opt_S); use Sys::Hostname; my $host = hostname; my $ALERT = $opt_u ? "UPALERT" : "ALERT"; my $t = localtime($opt_t); my ($wday,$mon,$day,$tm) = split (/\s+/, $t); my @xmpprec = split(/,/, $opt_x); # use hostname as the resource open (XMPP, "| /usr/bin/sendxmpp -a /etc/ssl/certs -t @xmpprec -r $host") || die "could not open pipe to sendxmpp: $!\n"; my $slackmsg = "$ALERT $opt_g/$opt_s: $summary ($wday $mon $day $tm)\\n"; print XMPP <) { print XMPP; chomp; $slackmsg .= "$_\\n"; } close (XMPP); $slackmsg =~ s/'//g; my $slack = "/usr/bin/curl -g -X POST -H \"Content-type: application/json\" --data \'{\"text\":\"" . $slackmsg . "\"}\' $opt_h"; print "$slack\n"; system($slack); etbemon-1.3.6/alert.d/snpp.alert0000755000000000000000000000342010616437070013410 0ustar #!/usr/bin/perl -w # # snpp.alert - Pure perl SNPP client # # Copyright (C) 1998, Michael Alan Dorman # # snpp.alert is based on the alert.template distributed by mon. # # Copyright (C) 1998, Jim Trocki # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # $Id: snpp.alert,v 1.1.1.1.4.1 2007/05/03 19:55:36 trockij Exp $ # use strict; use vars qw /$opt_g $opt_q $opt_s $opt_t $opt_u/; use Getopt::Std; use Net::SNPP; getopts ("s:g:h:t:l:q:u"); my $opt_q ||= 'localhost'; # # the first line is summary information, adequate to send to a pager # or email subject line # # # the following lines normally contain more detailed information, # but this is monitor-dependent # # see the "Alert Programs" section in mon(1) for an explanation # of the options that are passed to the monitor script. # my $summary = ; chomp $summary; my $t = localtime ($opt_t); my ($wday,$mon,$day,$tm) = split (/\s+/, $t); my $snpp = Net::SNPP->new ($opt_q) or die; my $ALERT = $opt_u ? "UPALERT" : "ALERT"; $snpp->send ( Pager => [ @ARGV ], Message => "$ALERT $opt_g/$opt_s: $summary ($wday $mon $day $tm)" ); $snpp->quit; etbemon-1.3.6/alert.d/test.alert0000755000000000000000000000017213135636127013413 0ustar #!/bin/sh # # $Id: test.alert,v 1.1.1.1 2004/06/09 05:18:07 trockij Exp $ echo "`date` $*" >> /var/log/mon/test.alert.log etbemon-1.3.6/alert.d/trap.alert0000755000000000000000000000400113455600207013370 0ustar #!/usr/bin/perl # # Trap alert, for use with mon-0.38pre* and greater. # # Specify user and pass via MON_TRAP_USER (-U) and MON_TRAP_PASS (-P) # # Jim Trocki, trockij@arctic.org # # $Id: trap.alert,v 1.3 2005/04/17 07:42:26 trockij Exp $ # # Copyright (C) 1998, Jim Trocki # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # use Getopt::Std; use Mon::Client; use Socket; getopts ("s:g:h:t:l:o:uU:P:T:"); $summary=; chomp $summary; $detail = ""; while () { $detail .= $_; } chomp $detail; $t = time; $USER = ($ENV{"MON_TRAP_USER"} || $opt_U) || ""; $PASS = ($ENV{"MON_TRAP_PASS"} || $opt_P) || ""; $OPST = defined $ENV{"MON_OPSTATUS"} ? $ENV{"MON_OPSTATUS"} : 0; if ($opt_o) { $OPST = int ($opt_o); } foreach $op (keys %Mon::Client::OPSTAT) { $OPSTATUS = $op if ($Mon::Client::OPSTAT{$op} == $OPST); } $c = new Mon::Client ( port => getservbyname ('mon', 'udp') || 2583, ); $c->username($USER) if ($USER); $c->password($PASS) if ($PASS); foreach $host (@ARGV) { $c->host($host); $res = $c->send_trap( group => $ENV{MON_GROUP}, service => $ENV{MON_SERVICE}, retval => $ENV{MON_RETVAL}, opstatus => $OPSTATUS, summary => $summary, detail => $detail, ); print STDERR "Error sending trap to $host\n" if (!$res); print STDERR "Error is: ". $c->error() . "\n" if (!$res); } exit; etbemon-1.3.6/alert.template0000755000000000000000000000325010230411542012677 0ustar #!/usr/bin/perl # # template for an alert # # Jim Trocki, trockij@arctic.org # # $Id: alert.template,v 1.2 2005/04/17 07:42:26 trockij Exp $ # # Copyright (C) 1998, Jim Trocki # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # use Getopt::Std; getopts ("s:g:h:t:l:u"); # # the first line is summary information, adequate to send to a pager # or email subject line # # # the following lines normally contain more detailed information, # but this is monitor-dependent # # see the "Alert Programs" section in mon(1) for an explanation # of the options that are passed to the monitor script. # $summary=; chomp $summary; $t = localtime($opt_t); ($wday,$mon,$day,$tm) = split (/\s+/, $t); print <) { print; } etbemon-1.3.6/bin/0000755000000000000000000000000014203606346010614 5ustar etbemon-1.3.6/bin/Makefile0000644000000000000000000000053714173222400012250 0ustar ALLPROGS=btrfs.helper zfs.helper smartctl.helper hplog.helper all: $(ALLPROGS) # use -Wno-write-strings to make it easy to deal with exec() taking pointers # to non-const data WFLAGS=-Wall -W -Wshadow -Wpointer-arith -Wcast-align -Wcast-qual -pedantic -Wno-write-strings CC=gcc -O2 -g $(WFLAGS) %: %.cpp $(CC) $< -o $@ clean: rm -f $(ALLPROGS) etbemon-1.3.6/bin/btrfs.helper.cpp0000644000000000000000000000267413325225226013725 0ustar #include #include #include #include int main(int argc, char **argv) { if(argc != 2) { fprintf(stderr, "ERROR: Must specify mountpoint of BTRFS filesystem\n"); return 1; } pid_t pid = fork(); if(-1 == pid) { fprintf(stderr, "ERROR: Fork failed\n"); return 1; } else if(pid) { int wstatus = 0; if(wait(&wstatus) == -1) { fprintf(stderr, "ERROR: wait(2) error\n"); return 1; } if(!WIFEXITED(wstatus) || WEXITSTATUS(wstatus)) { fprintf(stderr, "ERROR: Error running btrfs device stats\n"); return 1; } } else { char * const child_args[] = { "/bin/btrfs", "device", "stats", argv[1], NULL }; execv(child_args[0], child_args); fprintf(stderr, "ERROR: Can't execute %s\n", child_args[0]); return 1; } pid = fork(); if(-1 == pid) { fprintf(stderr, "ERROR: Fork failed\n"); return 1; } else if(pid) { int wstatus = 0; if(wait(&wstatus) == -1) { fprintf(stderr, "ERROR: wait(2) error\n"); return 1; } if(!WIFEXITED(wstatus) || WEXITSTATUS(wstatus)) { fprintf(stderr, "ERROR: Error running btrfs subvol list\n"); return 1; } } else { char * const child_args[] = { "/bin/btrfs", "subvol", "list", argv[1], NULL }; execv(child_args[0], child_args); fprintf(stderr, "ERROR: Can't execute %s\n", child_args[0]); return 1; } } etbemon-1.3.6/bin/hplog.helper.cpp0000644000000000000000000000060014200451673013701 0ustar #include #include #include #include int main() { if(setgid(0) || setuid(0)) { fprintf(stderr, "ERROR: setgid(0)/setuid(0) failed\n"); return 1; } char * const child_args[] = { "/sbin/hplog", "-t", NULL }; execv(child_args[0], child_args); fprintf(stderr, "ERROR: Can't execute %s\n", child_args[0]); return 1; } etbemon-1.3.6/bin/smartctl.helper.cpp0000644000000000000000000000364114057340207014431 0ustar #include #include #include #include #include #include void check_device(const char * const dev) { const char * const errmsg = "ERROR: Device \"%s\" didn't match /dev/sd[a-z] /dev/sd[a-z][a-z] /dev/nvme[0-9] /dev/nvme[0-9][0-9]\n"; if(!strncmp(dev, "/dev/sd", 7)) { if(dev[7] < 'a' || dev[7] > 'z' || (dev[8] && (dev[8] < 'a' || dev[8] > 'z' || dev[9]))) { fprintf(stderr, errmsg, dev); exit(1); } } else if(!strncmp(dev, "/dev/nvme", 9)) { if(dev[9] < '0' || dev[9] > '9' || (dev[10] && (dev[10] < '0' || dev[10] > '9' || dev[11]))) { fprintf(stderr, errmsg, dev); exit(1); } } } int main(int argc, char **argv) { if(argc != 2) { fprintf(stderr, "ERROR: Must specify device for smartctl\n"); return 1; } char *child_args[5]; child_args[0] = strdup("/usr/sbin/smartctl"); if(argv[1][0] == 'M') { char *buf = strdup(argv[1] + 1); char *device = strtok(buf, ","); char *id; if(!device || strncmp(device, "/dev/sd", 7) || !(id = strtok(NULL, ",")) ) { fprintf(stderr, "ERROR: parameter for MegaRAID must be \"M/dev/sdX,X\"\n"); return 1; } check_device(device); char *megaraid = (char *)malloc(12 + strlen(id)); strcpy(megaraid, "-dmegaraid,"); strcpy(megaraid + 11, id); child_args[1] = megaraid; child_args[2] = strdup("-H"); child_args[3] = device; child_args[4] = NULL; } else { if(strncmp(argv[1], "/dev/sd", 7) && strncmp(argv[1], "/dev/nvme", 9)) { fprintf(stderr, "ERROR: First parameter must specify a /dev/sd or /dev/nvme device\n"); return 1; } check_device(argv[1]); child_args[1] = strdup("-H"); child_args[2] = argv[1]; child_args[3] = NULL; } execv(child_args[0], (char* const*)child_args); fprintf(stderr, "ERROR: Can't execute %s\n", child_args[0]); return 1; } etbemon-1.3.6/bin/zfs.helper.cpp0000644000000000000000000000064313604573137013410 0ustar #include #include #include #include int main(int argc, char **argv) { if(argc != 2) { fprintf(stderr, "ERROR: Must specify pool name of ZFS filesystem\n"); return 1; } char * const child_args[] = { "/sbin/zpool", "status", argv[1], NULL }; execv(child_args[0], child_args); fprintf(stderr, "ERROR: Can't execute %s\n", child_args[0]); return 1; } etbemon-1.3.6/clients/0000755000000000000000000000000013137761622011511 5ustar etbemon-1.3.6/clients/batch-example0000755000000000000000000000044610061516617014150 0ustar #!/bin/sh # # an example of calling moncmd in batch mode # # $Id: batch-example,v 1.1.1.1 2004/06/09 05:18:07 trockij Exp $ # trap "stty echo && echo && exit" 2 echo -n "Password: " stty -echo read p echo stty echo cat < # Based on the Mon program by Jim Trocki . # http://www.kernel.org/software/mon/ # Rewritten to support Mon::Client, mod_perl, taint mode, # authentication, the strict pragma, and other visual/functional # enhancements by Andrew Ryan . # Downtime logging contributed by Martha H Greenberg # Site-specific customization routines contributed by Ed Ravin # # ---------------------------------------------------------------------- # $Id: mon.cgi,v 1.4.2.1 2007/05/03 19:55:38 trockij Exp $ # ---------------------------------------------------------------------- # # # INSTRUCTIONS # Install this cgi script to wherever your cgi-bin directory sits # on your mon server. If you don't have a web server installed, try # http://www.apache.org. This script hasn't been tested with any # web server, although there is no reason it wouldn't work under # any other web server as a CGI script. # # This script now runs cleanly under mod_perl (tested under apache 1.3.9, # mod_perl 1.21), if you're running that. Global variables have not # been eliminated but at least we're being careful now. # # This script also runs cleanly under taint mode, which is activated # by using the -T switch for CGI scripts, and by using the directive # "PerlTaintCheck On" in your httpd.conf file if you are running # under mod_perl. # # Modify the "Configurable Parameters" section below to customize it # to your site's settings. mon.cgi also supports an optional config # file which allows you to set all the same parameters. Please # see the file README.site-customization for more details. # # If you want to easily customize the look and feel of mon.cgi, # as well as various other configuration options, copy the sample # mon.cgi.cf file (in the /config directory of this distribution) # into a location where your webserver can read it, and edit the # line beginning '$moncgi_config_file = ""' to reflect the path # to your config file. You can then change the look and feel of # mon.cgi, as well as implement access controls, directly from this # file. # # If you want to do a lot of the things that this script lets you do, # and you don't want any authorization to be necessary, then # you need to open up your auth.cf file to allow anyone to perform # actions that you would like mon.cgi to perform. # # No authentication might work in an environment where there are very # few Mon users and they can all be trusted equally, or if you want # to use mon.cgi in a sort of "read-only" capacity, where all users # can list, for example, but no web users can enable/disable # monitoring and/or control the server in any way. # # Alternatively, if you want to use authentication, you need to have # a working authentication setup with Mon from the command line # before attempting to make authentication work with mon.cgi. # # Authentication is very flexible, and is trivial to implement in # mon.cgi, assuming you already have authentication working from # the command line. Just un-comment out the "$must_login line, change # $app_secret to be something unique (VERY IMPORTANT!) and # mon will start requiring authentication for ALL commands. # # Authentication users should change their app secret on a regular # basis if security is a concern. Actually, if security is a concern, # don't run mon.cgi, because unless you use SSL, AND your monhost is # on the same server as your web server, AND you use a short timeout # on cookies, AND you change your app secret often and keep it # VERY secure, you don't have a secure web system. But this simple # authentication mechanism is enough to keep most people happy. # # # This script will require the CGI perl module. Available at any # perl CPAN site. See http://www.perl.org for details. Oh, and don't # forget Mon::Client, but the assumption is you are already running # mon in some fashion and so you know this already. # # In addition, if you want to use the authentication piece of mon.cgi, # you need to install the Crypt::TripleDES module, also available # (tested w/ Crypt::TripleDES v0.24), and your browser needs to allow # cookies (or else you need to be prepared to type in your username # and password an awful lot!). # # # BUGS # Probably many. # Send bugs/comments about this software to # Andrew Ryan # Please include any output from your web server's error log that the # script might have output, this will help immensely in solving problems. # Also please include the versions of mon.cgi, Mon and Mon::Client you # are using. # BEGIN { # Auto-detect if we are running under mod_perl or CGI. $USE_MOD_PERL = exists $ENV{'MOD_PERL'} ? 1 : 0; if ($USE_MOD_PERL) { # Use the cgi module and compile all methods at # the beginning but only once use CGI qw (-compile :standard) ; } else { # Use the cgi module and compile all methods only # when they are invoked via the autoloader. #use CGI qw (-debug) ; #DEBUG use CGI qw (:standard) ; } $CGI::POST_MAX=1024 * 100; # max 100K posts $CGI::DISABLE_UPLOADS = 1; # no uploads } # Configurable Parameters ---------------------------------------------- # Basic global vars use Mon::Client; # mon client interface use strict; # because strict is GOOD use vars qw($RCSID $RCSVERSION $VERSION $AUTHOR $organization $monadmin $logo $logo_link $reload_time $monhost $monport $url $login_expire_time $cookie_name $cookie_path %cgiparams $vcookie_name $vcookie_path $vcookie @views $curview $monhost_and_port_args $monhost_and_port_args_meta $has_read_config $moncgi_config_file $cf_file_mtime $untaint_ack_msgs @show_watch $show_watch_strict $required_mon_client_version); # Formatting-related global vars use vars qw($BGCOLOR $TEXTCOLOR $LINKCOLOR $VLINKCOLOR $greenlight_color $redlight_color $unchecked_color $yellowlight_color $disabled_color $fixed_font_face $sans_serif_font_face $dtlog_max_failures_per_page); # Security-related global vars use vars qw($must_login $app_secret %loginhash $des $has_prompted_for_auth $destroy_auth_cookie $default_username $default_password); $has_prompted_for_auth = ""; #this must always be cleared for mod_perl undef $destroy_auth_cookie; #this must always be undef'd for mod_perl undef %cgiparams; # this must always be undef'd for mod_perl undef $monhost_and_port_args; # This is defined if the user overrided monhost or monport undef $monhost_and_port_args_meta; # This is defined if the user overrided monhost or monport undef @show_watch; undef $show_watch_strict; $RCSID = '$Id: mon.cgi,v 1.4.2.1 2007/05/03 19:55:38 trockij Exp $'; $RCSVERSION = '$Revision: 1.4.2.1 $'; $VERSION = $RCSVERSION; $VERSION =~ s/\Revision: //i; $VERSION =~ s/\$//g ; $VERSION =~ s/\s+//g; $AUTHOR = 'andrewr@nam-shub.com'; $required_mon_client_version = "0.11"; #Version of Mon::Client which we require for successful operation # # If you want to use a config file to specify mon.cgi parameters, put # the full path to the file in this variable. # # If you do not wish to use a config file, leave this variable empty. # $moncgi_config_file = ""; # # This subroutine initializes the configuration variables which # can be set here, but also overridden with the optional mon.cgi # config file. # # We put this subroutine at the top of the code so that users # can get to it more easily. # sub initialize_config_globals ; sub initialize_config_globals { undef $has_read_config ; #undef this for mod_perl $must_login = ""; #this must always be undef'd for mod_perl $organization = ""; # Organization name. $monadmin = "BOFH\@your.domain"; # Your e-mail address. # note: must escape @ signs! $logo = ""; # Company or mon logo. $reload_time = 180; # Seconds for page reload. $monhost = "localhost"; # Mon server hostname. $monport = "2583"; # Mon port number. #$must_login = "yes"; # Uncomment this out if you want # authentication to be mandatory # for all connections to the mon server. #!!! WARNING!!!!! You must change $app_secret to something unique to your site! $app_secret = '1.90LK=R==36jlel492jl><>header(); print $webpage->start_html(-title=>"mon.cgi error: insufficient Mon::Client version", -BGCOLOR=>$BGCOLOR, -TEXT=>$TEXTCOLOR, -LINK=>$LINKCOLOR, -VLINK=>$VLINKCOLOR, -META=>{ 'generator'=>"mon.cgi $VERSION ($AUTHOR)", }, ); print $webpage->h3("Insufficient version ($Mon::Client::VERSION) of the Mon::Client perl module installed. Please upgrade your Mon::Client to at least version $required_mon_client_version before running mon.cgi."); print $webpage->h3("Also note, if you're running mon.cgi under Apache+mod_perl, you'll need to restart Apache after upgrading the Mon::Client library."); print $webpage->end_html; exit; } # # Read CGI params -- these overwrite anything in a config file # or hard-coded. # This can change the value of the $monhost and $monport # global variables defined in initialize_config_globals and # moncgi_read_cf. # # This can cause a problem if $monhost or $monport are defined here and we are running mod_perl... # &moncgi_get_params; # # Used to escape HTML in ack's # if ($untaint_ack_msgs =~ /^y(es)?$/i) { eval "use HTML::Entities" ; } else { undef $untaint_ack_msgs; } # Initialize a TripleDES global if login is required, # otherwise undef $must_login if ($must_login =~ /^y(es)?$/i) { eval "use Crypt::TripleDES"; $des = new Crypt::TripleDES; } else { $must_login = ""; } # # Set (or unset) $show_watch_strict according to its value # if ($must_login =~ /^y(es)?$/i) { $show_watch_strict = 1; } else { $show_watch_strict = ""; } # #Initialize the wordy descriptions of alert variables # %alert_vars = ( 'depend' => "Dependencies, if any", 'service' => "Service being monitored", 'last_check' => "The last time this service was checked", 'timer' => "Time remaining until this service is next checked", 'last_summary' => "Summary output from most recent failure of this service", 'opstatus' => "Current status of this service (0=error, 1=OK, 7=unchecked)", 'alerts_sent' => "Number of alerts sent", 'interval' => "Test interval, in seconds", 'last_detail' => "Detail output from the most recent failure of this service", 'monitor' => "Monitor used to test this service", 'last_trap' => "Last time a trap was received on this service", 'last_alert' => "Last time an alert was sent for this service", 'last_success' => "Last time this service returned an OK result", 'group' => "Hostgroup", 'failure_duration' => "Length of failure", 'ack' => "Acknowledgement status (1=failed service was ack'ed)", 'ackcomment' => "Comment issued by the acknowledger", 'first_failure' => "First failure time of this service", 'last_failure' => "Last failure time of this service", 'depend' => "Hostgroups/Services on which this service depends", 'last_check' => "Time this service was last checked", 'service' => "Service being checked", 'last_opstatus' => "Previous opstatus for this service (0=error, 1=OK, 7=unchecked)", 'exitval' => "Last exit value of monitor for this service (0=OK, anything else indicates failure)", 'depstatus' => "Dependency status (1 = dependencies OK, 0=dependencies not OK or no dependencies)", 'last_summary' => "Summary output from most recent failure of this service", 'last_detail' => "Detail output from the most recent failure of this service", ); # These are variables from svc_details which should be represented as # pretty-printed time strings. Mon gives them to us as UNIX time(2), so we # have to convert. They used to be hardcoded deep into the code, this # is an attempt at a readability improvement. # Example representation: '(31 days, 17 hours, 53 minutes, 25 seconds ago)' @time_based_alert_vars = ( "last_check", "last_failure", "last_trap", "last_alert", "last_success", "last_failure", "first_failure", ); # These are variables from svc_details which should be represented as # "pretty printed" seconds/minutes/hours/days. # Example representation: '4 minutes, 19 seconds' @pp_sec_alert_vars = ( "timer", "interval", "failure_duration", ); %auth_commands = ( # This global tracks the authorization # status of all commands mon.cgi can # issue for a user. It is a candidate for # inclusion in a cookie someday. list => { auth=>0, bgcolor=>""}, reset => { auth=>0, bgcolor=>""}, stop => { auth=>0, bgcolor=>""}, start => { auth=>0, bgcolor=>""}, savestate => { auth=>0, bgcolor=>""}, loadstate => { auth=>0, bgcolor=>""}, disable => { auth=>0, bgcolor=>""}, enable => { auth=>0, bgcolor=>""}, test => { auth=>0, bgcolor=>""}, ack => { auth=>0, bgcolor=>""}, reload => { auth=>0, bgcolor=>""}, ); $auth_commands_checked = 0; # This global tracks whether authorization # for all commands has been checked. ############################################################### # Function definitions begin below ############################################################### # # Forward declare all functions, for our sanity. # # # General functions # sub pp_sec ; sub pp_sec_brief ; sub arithmetic_mean ; sub median ; sub std_dev ; sub validate_name ; sub gen_ciphertext ; sub gen_cleartext ; # # Base mon.cgi pages # sub setup_page ; sub print_bar ; sub query_opstatus ; sub can_show_group ; sub list_status ; sub query_group ; sub end_page ; sub list_alerthist ; sub svc_details ; sub list_disabled ; sub list_dtlog ; sub list_pids ; # # mon functions # sub mon_connect ; sub mon_views; sub mon_list_group ; sub mon_list_watch ; sub mon_list_failures ; sub mon_list_successes ; sub mon_list_opstatus ; sub mon_list_disabled ; sub mon_reload ; sub mon_loadstate ; sub mon_savestate ; sub mon_loadstate_savestate ; sub mon_schedctl ; sub mon_list_pids ; sub mon_list_descriptions ; sub mon_enable ; sub mon_disable ; sub mon_test_service ; sub mon_test_config ; sub mon_reset ; sub mon_list_alerthist ; sub mon_list_sched_state ; sub mon_list_dtlog ; sub mon_ack ; sub mon_servertime ; sub mon_checkauth ; sub mon_state_change_enable_only ; sub mon_state_change ; # # mon.cgi functions # sub moncgi_get_params ; sub moncgi_logout ; sub moncgi_authform ; sub moncgi_generic_button ; sub moncgi_switch_user ; sub moncgi_print_service_table_legend ; sub moncgi_list_dtlog_navtable ; sub moncgi_test_all ; sub moncgi_reset ; sub moncgi_read_cf ; sub moncgi_login ; sub moncgi_custom_print_bar ; sub moncgi_custom_commands; ############################################################### # General functions, not specific to Mon or mon.cgi ############################################################### sub pp_sec { # This routine converts a number of seconds into a text string # suitable for (pretty) printing. The dtlog from Mon reports downtime # in seconds, and we want to present the user with more meaningful # data than "the service has been down for 13638 seconds" # # By Martha Greenberg w/ pedantic plural # modifications by Andrew. use integer; my $n = $_[0]; my ($days, $hrs, $min, $sec) = ($n / 86400, $n % 86400 / 3600, $n % 3600 / 60, $n % 60); my $s = $sec . " second"; $s .= "s" if $sec != 1; #because 0 is plural too :) if ($min > 0) { if ($min == 1) { $s = $min . " minute, " . $s; } else { $s = $min . " minutes, " . $s; } } if ($hrs > 0) { if ($hrs == 1) { $s = $hrs . " hour, " . $s; } else { $s = $hrs . " hours, " . $s; } } if ($days > 0) { if ($days == 1) { $s = $days . " day, " . $s; } else { $s = $days . " days, " . $s; } } return $s; } sub pp_sec_brief { # This routine converts a number of seconds into a text string # suitable for brief (yet pretty) printing. # # We use this on the opstatus page to display deltas of times (for # last check, next check). use integer; my $n = $_[0]; my $s; if ($n >= 0) { $s .= "+" ; } else { $s .= "-" ; $n = abs($n); } my ($days, $hrs, $min, $sec) = ($n / 86400, $n % 86400 / 3600, $n % 3600 / 60, $n % 60); if ($days > 0) { $s .= $days . "d"; } if ($hrs > 0) { $s .= $hrs . "h"; } if ($min > 0) { $s .= $min . "m"; } $s .= "${sec}s" ; return $s; } sub arithmetic_mean { # Given an array of numbers, this function returns the arithmetic mean return 0 if scalar(@_) == 0 ; #don't waste our time my $sum = 0; foreach (@_) { $sum += $_; } return $sum/scalar(@_); } sub median { # Given an array of numbers, this function returns the median return 0 if scalar(@_) == 0 ; #don't waste our time my $middle_element_index = int(scalar(@_)/2); @_ = sort {$a <=> $b} @_; if (scalar(@_)%2 == 1) { #odd num of elements, take the middle return $_[$middle_element_index]; } else { # even # of elements, take the avg of the 2 middle elements return &arithmetic_mean($_[$middle_element_index],$_[($middle_element_index-1)]); } } sub std_dev { # Given an array of numbers, this function returns their # standard deviation. return 0 if scalar(@_) < 2 ; #don't waste our time my $sum = 0; my $mean = &arithmetic_mean(@_); foreach (@_) { $sum += ( $_ - $mean )**2 ; } return ( $sum/(scalar(@_) - 1) )**0.5 ; } sub validate_name { # Return untainted host or group name if safe, undef otherwise. # Because you can never scrub your input too well. return $_[0] =~ /^([\w.\-_]+)$/ ? $1 : undef; } sub gen_ciphertext { # This function takes as its input a piece of plaintext and # returns a piece of ASCII, 3DES-encoded ciphertext, or undef if 3DES fails # for some reason. The key used is the global value "$app_secret". my ($plaintext) = (@_); my $ciphertext ; if ($ciphertext = $des->encrypt3 ("$plaintext", "$app_secret" )) { # convert key to hex $ciphertext = unpack("H*", $ciphertext) ; # print "ciphertext is $ciphertext
\n"; #DEBUG return $ciphertext; } else { return undef; } } sub gen_cleartext { # This function takes as its input a piece of ASCII, 3DES-encoded # ciphertext and returns a piece of plaintext, # or undef if 3DES fails for some reason. The key used is the # global value "$app_secret". my ($ciphertext) = (@_); my $plaintext ; return undef if ! $ciphertext; #convert key to format decrypt3() will understand $ciphertext = pack("H*", $ciphertext) ; if ($plaintext = $des->decrypt3 ("$ciphertext", "$app_secret" )) { # print "plaintext is $plaintext
\n"; #DEBUG return $plaintext; } else { return undef; } } ############################################################### # Presentation functions. These all have the common feature # that they format a bunch of information and present it in # a nice(?) way to the user. ############################################################### sub setup_page { # Setup the html doc headers and such # Also, get/set username/password cookie if $must_login is in effect my ($title) = (@_); my (@time, $ttime); my $title_color = "$TEXTCOLOR"; my $page_title = "$organization : " if $organization ne ""; $page_title = "${page_title}MON - $title ($monhost:$monport)"; my $time_now = time; my @expires_time = gmtime($time_now + $login_expire_time); # Put the cookie date format in the standard cookie format my $expires = sprintf ("%s, %.2d-%s-%d %.2d:%.2d:%.2d GMT", @days_of_week[$expires_time[6]], $expires_time[3], @year_months[$expires_time[4]], $expires_time[5] + 1900, @expires_time[2,1,0]); my ($encrypted_password, $cookie, $cookie_value); my $refresh_url; # # Define $args as null if it is not currently defined # $args = "" if ! defined($args); # Set the refresh page to always be the summary page, unless # certain commands are selected. if ( $command =~ "^query_opstatus_" ) { $refresh_url = "$url?${monhost_and_port_args_meta}command=$command"; } elsif ( ($command eq "mon_test_service") || ($command eq "svc_details") ) { $refresh_url = "$url?${monhost_and_port_args_meta}command=svc_details&args=$args"; } elsif ($command eq "query_group") { $refresh_url = "$url?${monhost_and_port_args_meta}command=query_group&args=$args"; } elsif ($command eq "list_dtlog") { $refresh_url = "$url?${monhost_and_port_args_meta}command=list_dtlog&args=$args"; } else { $refresh_url = "$url?${monhost_and_port_args_meta}command=query_opstatus"; } if ($must_login) { if ( ( defined($loginhash{'username'}) ) && ( $loginhash{'username'} ne "" ) ) { # Don't get the username and password from the cookie # if the user just submitted it via the login form. # Encrypt the password for cookie storage. $encrypted_password = &gen_ciphertext($loginhash{'password'}) ; } else { # Get the existing cookie and parse it $cookie_value = $webpage->cookie(-name=>"$cookie_name", ); ($loginhash{'username'},$loginhash{'password'}) = split(':', $cookie_value) if $cookie_value; $encrypted_password = $loginhash{'password'} ; # Decrypt the password string (if any) for use by the app, # unless the user just submitted it in cleartext. $loginhash{'password'} = &gen_cleartext($loginhash{'password'}) ; # for some reason (bug?) I get a space at the end of the password # that is returned here, so for now let's take it out, since # spaces are illegal in passwords anyway. $loginhash{'password'} =~ s/\s+//g if defined($loginhash{'password'}) ; } # Set up the new cookie (re-issue a new cookie with every access) if ($destroy_auth_cookie) { $cookie_value = "" ; } elsif ( defined($loginhash{'password'}) ) { $cookie_value = "$loginhash{'username'}:$encrypted_password" ; } else { # no username was supplied $cookie_value = "" ; } $cookie = $webpage->cookie(-name=>"$cookie_name", -value=>"$cookie_value", -expires=>"$expires", -path=>"$cookie_path", ); mon_views(); print $webpage->header( -cookie=>[$cookie,$vcookie], -refresh=>"$reload_time; URL=$refresh_url", ); } else { # Plain & simple, no cookie, no passsword $encrypted_password = "" ; mon_views(); print $webpage->header( -cookie => [$vcookie], -refresh=>"$reload_time; URL=$refresh_url", ); } print $webpage->start_html(-title=>"$page_title", -BGCOLOR=>$BGCOLOR, -TEXT=>$TEXTCOLOR, -LINK=>$LINKCOLOR, -VLINK=>$VLINKCOLOR, -META=>{ 'generator'=>"mon.cgi $VERSION ($AUTHOR)", }, ); # Useful for debugging username/password/cookie issues #DEBUG # print "cookie value is $cookie_value
\n"; #DEBUG # print "encrypt passwd is $encrypted_password
\n"; #DEBUG # print "username is "$loginhash{'username'}"
\n"; #DEBUG # print "decrypt passwd is "$loginhash{'password'}"
\n"; #DEBUG # # Print the logo image, if it was defined by the user. # if ($logo) { $webpage->print("\n"); } else { $webpage->print("\"[$organization\n"); } $webpage->print("
\n"); # # If the user has given a logo_link link, then insert an # anchor tag to it here, if logo_link was defined by the # user. # if ($logo_link) { $webpage->print("\"[$organization

MON: $title

MON: $title

\n"); $webpage->print("


\n"); } else { #just print the generic page with no logo and no link $webpage->print("\n"); if (@views) { $webpage->print(""); } $webpage->print("

MON: $title

", $webpage->start_form, $webpage->popup_menu(-name=>'setview', -values=>["--all--",sort(@views)], -default=>$curview), $webpage->submit(-name=>'Change View'), $webpage->end_form, "
\n"); } &print_bar; @time = localtime($time); $ttime = sprintf ("%.2d:%.2d:%.2d on %s, %.2d-%s-%d", @time[2,1,0], @days_of_week[$time[6]], $time[3], @year_months[$time[4]], $time[5] + 1900 ); $webpage->print("
"); $webpage->print ("\nThis information was presented at $ttime"); # # If the user is currently logged in, tell the user who # they are logged in as. # If the user is NOT currently logged in, offer to log # them in. # if ( ($loginhash{'username'}) && ($loginhash{'username'} ne $default_username) ) { $webpage->print (" to user $loginhash{'username'} (log off user $loginhash{'username'})") ; } else { $webpage->print (" (log in)"); } if ($curview && $curview ne '--all--') { $webpage->print("
Current View: $curview. If you're not seeing what you're expecting to see, try changing views via the menu at the top of this page."); } $webpage->print(".
"); } sub print_bar { # Print the command bar. Called at both the beginning and the end # of each page. # my $button = "INPUT TYPE=\"submit\" NAME=\"command\""; my $table_width = "100%"; my $face = $sans_serif_font_face; my ($cmd, $command, $desc); my $all_commands_unauthorized = 1; my $i; foreach $cmd (keys %auth_commands) { $auth_commands{$cmd}{'auth'} = &mon_checkauth($cmd); #last if $auth_commands{$cmd}{'auth'} == -1; # stop checking if we can't # contact the server $auth_commands{$cmd}{'bgcolor'} = $auth_commands{$cmd}{'auth'} == 0 ? "bgcolor=\"$disabled_color\"" : ""; $all_commands_unauthorized = 0 if $auth_commands{$cmd}{'auth'} == 1 ; } # Check to see if authentication is required and the selected user has # no permissions to do anything. This can only happen if your mon admin # is very cruel and gives you an account with no permissions (should # be very rare), or if a user enters the wrong password for a valid # account name (the usual case). # The main thing I don't like about this solution is that it embeds # the default l/p into the URL, but this isn't a secure password # anyway, right? $cmd = "list"; #set $cmd to the most basic of commands if ($auth_commands{$cmd}{'auth'} == 0) { $webpage->print("

Cannot connect to the mon server. Check the mon process to see if it is running.


\n"); } elsif ( ($must_login) && ($all_commands_unauthorized == 1) ) { $webpage->print("

You are attempting to log in with the username "$loginhash{'username'}" but your password is incorrect.

Either enter in the correct username/password above or click here to clear your authentication credentials and log back in as the default user.


\n"); } $auth_commands_checked = 1; # We have to lay the tables out by hand bec. of the colspanning :( $webpage->print("\n"); # # Print the first row of the command table # $webpage->print("\n"); $webpage->print("\t\n"); $webpage->print("\t\n"); $webpage->print("\t\n"); $webpage->print("\t\n"); $webpage->print("\t\n"); $webpage->print("\t\n"); $webpage->print("\n"); # # Print the second row of the menu table # $webpage->print("\n"); $webpage->print("\t\n"); $webpage->print("\t\n") ; $webpage->print("\t\n"); $webpage->print("\t\n"); $webpage->print("\t\n"); $webpage->print("\t\n"); $webpage->print("\t\n"); $webpage->print("\n"); # # Print the optional third row of the command table # This row can be defined at individual sites and contain commands # of your choice. Thanks to Ed Ravin (eravin@panix.com) for this. # &moncgi_custom_print_bar($face); # row 3, if any, for the local site $webpage->print("
Show Operational Status (summary) (failures only)Show Alert HistoryLoad scheduler stateStart schedulerList Disabled Hosts/ Watches/ SvcsTest Mon Config File
Show Operational Status   (full)Show Downtime LogSave scheduler stateStop schedulerReload auth fileList Mon PIDsReset Mon
"); } # query the server operational status ---------------------------------- sub query_opstatus { my ($detail_level) = (@_); my ($retval); # some variables for failures my (%op_success, %op_failure); my @scheduler_status = &mon_list_sched_state ; my $opstatus_table_width = "100%"; # the width of the whole opstatus tbl my $service_column_width = "40%"; # the width of the Service column my $service_legend_table_width = "70%"; # the width of the service legend table $webpage->print("
\n"); if ($scheduler_status[0] != 0) { $webpage->print ("The scheduler on $monhost:$monport is currently running. "); } else { my @sched_down_time = localtime ($scheduler_status[1]); my $pretty_sched_down_time = sprintf ("%.2d:%.2d:%.2d, %s-%s-%s\n", @sched_down_time[2, 1, 0, 3], @year_months[$sched_down_time[4]], $sched_down_time[5]+1900); if ($scheduler_status[1] != 0) { $webpage->print ("
The scheduler has been stopped since $pretty_sched_down_time.
\n"); } else { #value is undef, scheduler cannot be contacted (or auth failure) $webpage->print ("
The scheduler cannot be contacted at this time.
\n"); } } $webpage->print ("This page will reload every $reload_time seconds.
"); $webpage->print("

\n"); %op_success = &mon_list_successes; %op_failure = &mon_list_failures ; $webpage->print(""); $webpage->print ("\n"); $webpage->print ("\n"); $webpage->print ("\n"); # Give extra notification if the scheduler is down (this is a big deal!) unless ($scheduler_status[0] != 0) { if ($scheduler_status[1] != 0) { $webpage->print ("\n"); } else { $webpage->print ("\n"); } } &list_status($detail_level, %op_failure) if (%op_failure); if ($detail_level eq "failures") { $webpage->print ("\n") unless %op_failure; } else { &list_status($detail_level, %op_success) if (%op_success); } $webpage->print("
Host GroupService (legend)Last CheckedEst. Next Check
! SCHEDULER IS NOT RUNNING. RESULTS SHOWN BELOW MAY NOT BE CORRECT !
! SCHEDULER CANNOT BE CONTACTED. RESULTS SHOWN BELOW MAY NOT BE CORRECT !
No failures found.
\n"); # Print the legend below the table &moncgi_print_service_table_legend ($service_legend_table_width); } # # This subroutine tests whether a given group is allowed to be # shown to the user. # Inputs: Name of group to check # Outputs: 1 Group is allowed to be shown # 0 Group is not allowed to be shown # sub can_show_group { my ($group) = (@_); my $watch; # Do not print out the status for this group # unless it is on the "allowed" list if (@show_watch) { #user defined one or more watch keywords # # Loop through each access control and look for a match # foreach $watch (@show_watch) { if ( $group =~ m/^$watch$/ ) { #we found a match #print STDERR "Group $group matched '$watch'\n"; #DEBUG return 1; } } } else { #user didn't define any watch keywords, so show everything return 1; } return 0; } sub list_status { # This function lists the status of all hosts and services. It is # kind of a mess, but this is the function that 90% of the time # you will be viewing, and it has to do a lot. It could still be # cleaned up considerably though. # my ($detail_level, %op) = (@_); my (%group_list, $group, $service, $s, $g, $h); my (@time); my $bg_fail = $redlight_color ; my $bg_fail_noalerts = $yellowlight_color ; my $bg_ok = $greenlight_color; my $td_bg_color; my $face = $sans_serif_font_face; my %d = &mon_list_disabled ; my %desc = &mon_list_descriptions if $detail_level eq "full"; my $servertime = &mon_servertime; my (%ONDS, %ONDS_lastcheck, %ONDS_nextcheck) ; #special hashes of arrays for "OK, Non-Disabled Services" my %OPSTAT = %Mon::Client::OPSTAT; my $service_disabled_string ; my ($service_acked_string, $ackcomment) ; my $host_disabled_string ; my $watch_disabled_string ; my $failure_string; my $desc_string ; my %saw ; #used for sorting my @disabled_hosts; foreach $group (sort keys %op) { #begin group loop # Only show this group if we are allowed to see it next unless &can_show_group($group) ; if ($detail_level eq "full") { # get a list of members of the group if we haven't already # we need the defined() to deal with certain empty groups $group_list{$group} = [ &mon_list_group($group) ] unless (@{$group_list{$group}}); } foreach $service (sort keys %{$op{$group}}) { #begin service loop $s = \%{$op{$group}->{$service}}; $service_disabled_string = ""; $service_acked_string = ""; $host_disabled_string = ""; $watch_disabled_string = ""; $desc_string = ""; undef %saw; undef @disabled_hosts; $service_disabled_string = "(DISABLED)" if ${ d{"services"}{$group}{$service} }; # assemble the ACK message, if any. # Escape the HTML to avoid any potential nastiness if the # user requested it, otherwise, just pass it on through # as is. if ( $op{$group}{$service}{'ack'} != 0 ) { if ($untaint_ack_msgs) { # # We untaint # $ackcomment = $op{$group}{$service}{'ackcomment'} eq "" ? "(no ack msg)" : HTML::Entities::encode_entities($op{$group}{$service}{'ackcomment'}) ; } else { # # We don't untaint # $ackcomment = $op{$group}{$service}{'ackcomment'} eq "" ? "(no ack msg)" : $op{$group}{$service}{'ackcomment'} ; } $service_acked_string = " (ACKED: $ackcomment)" ; } foreach $g (keys %{$d{"hosts"}}) { foreach $h (keys %{$d{"hosts"}{$group}}) { push(@disabled_hosts , $h); } } # uniq and sort the returned array of disabled hosts @saw{@disabled_hosts} = (); @disabled_hosts = sort keys %saw; $host_disabled_string = join(" " , @disabled_hosts) if scalar(@disabled_hosts) > 0 ; $host_disabled_string = "
($host_disabled_string DISABLED)\n" if ($host_disabled_string ne ""); $watch_disabled_string = "(DISABLED)" if (${d{"watches"}{$group}}); $td_bg_color = ( ($watch_disabled_string ne "") || ($host_disabled_string ne "") ) ? $disabled_color : $BGCOLOR ; # Don't print the service individually if we are in brief mode # mode and the service is an ONDS. next if ( ($s->{"opstatus"} == $OPSTAT{"ok"}) && ($service_disabled_string eq "") && ($detail_level ne "full") ); # Now print the first column (the group and its status) $webpage->print("\n"); # check to see if full display was requested if ($detail_level eq "full") { $desc_string = ($desc{$group}{$service} ne "") ? " "$desc{$group}{$service}"" : " <no description specified>" ; $webpage->print("$watch_disabled_string"); $webpage->print("$group
\n("); $webpage->print(join(", ",@{$group_list{$group}})); $webpage->print(")$host_disabled_string\n"); } else { $webpage->print("\n"); $webpage->print("$watch_disabled_string"); $webpage->print("$group$host_disabled_string\n"); } # Now print the second column (the service and its status) if ($s->{"opstatus"} == $OPSTAT{"untested"}) { # for untested, don't use a bg in table cell and change # font color instead. $td_bg_color = ($service_disabled_string eq "") ? $unchecked_color : $disabled_color ; $webpage->print("\n"); $webpage->print("$service_disabled_string"); $webpage->print("${service}"); $webpage->print("
(UNCHECKED)
${desc_string}\n"); $webpage->print("\n"); } elsif ($s->{"opstatus"} == $OPSTAT{"fail"}) { # Check to see if the service has issued any alerts. # If not, then we call this service "failing" instead # of failed, on the assumption that if it hasn't # generated an alert yet, it isn't "really" important, # although you'd still like to know about it. if ( $s->{"alerts_sent"} == 0 ) { $td_bg_color = $bg_fail_noalerts ; $failure_string = "FAILED,NOALERTS" ; } else { $td_bg_color = $bg_fail ; $failure_string = "FAILED" ; # Also give the # of alerts if "full" view was selected $failure_string .= ",alerts_sent=" . $s->{"alerts_sent"} if $detail_level eq "full"; } $td_bg_color = ($service_disabled_string eq "") ? $td_bg_color : $disabled_color ; $webpage->print(""); $webpage->print("$service_disabled_string"); $webpage->print("${service}${desc_string} : \n"); $webpage->print("$s->{last_summary}\n"); $webpage->print("
($failure_string)"); $webpage->print(" ${service_acked_string}") if $service_acked_string ne ""; $webpage->print("\n"); } elsif ($s->{"opstatus"} == $OPSTAT{"ok"}) { $td_bg_color = ($service_disabled_string eq "") ? $bg_ok : $disabled_color ; $webpage->print(""); $webpage->print("$service_disabled_string"); $webpage->print("${service}${desc_string}\n"); } else { my $txt = ""; for (keys %OPSTAT) { $txt = $_ if ($s->{"opstatus"} == $OPSTAT{$_}); } $webpage->print(""); $webpage->print("${service_disabled_string}${service} (details: $txt)\n"); } if ($s->{"opstatus"} == $OPSTAT{"untested"}) { $webpage->print(""); $webpage->print("--"); $webpage->print("\n"); } else { $webpage->print(""); if ($s->{"last_check"}) { #traps have a null value for last_check # Service IS NOT a trap if ($s->{"opstatus"} == $OPSTAT{"fail"}) { #check svc status # If service is failing, print last checked time # and also print out last_OK time print &pp_sec_brief($s->{"last_check"} - $servertime); # We need to check if the var is defined, since traps # can throw us off. $webpage->print("
(Last OK: "); if ( (!defined($s->{"last_success"})) || ($s->{"last_success"} == 0) ) { #service is currently failed and does not have a last_success time defined # The event has never occurred $webpage->print ("Never") ; } else { #service is currently failed and has a last_success time defined # Pretty-print the time that the service was last OK @time = localtime ($s->{"last_success"}); $_ = $s->{"last_success"}; # Also calculate the delta and pretty-print that $s->{"last_success"} .= "(" . &pp_sec($time - $_) . " ago)"; print &pp_sec_brief($s->{"last_success"} - $servertime); } $webpage->print(")"); } else { # If service is not failing, just print last checked time print &pp_sec_brief($s->{"last_check"} - $servertime); } } else { # Service IS a trap, or has never been checked $webpage->print("--"); } $webpage->print("
\n"); } $webpage->print(""); # Handle case where service is a trap and hence last_check=undef if ( ( $s->{"timer"} == 0 ) && (!($s->{"last_check"})) ) { $webpage->print("--"); } else { $webpage->print (""); $webpage->print (&pp_sec_brief($s->{"timer"})); $webpage->print (""); $webpage->print ("  (test all on $group)") ; } $webpage->print("\n"); # The next 4 lines are the old way of printing (absolute time) #@time = localtime ($qtime + $s->{"timer"}); #$webpage->print(""); #printf("%.2d:%.2d:%.2d\n", @time[2, 1, 0] ); #$webpage->print("\n"); $webpage->print(""); } # end $service loop # # NEW: print a "compressed" version of OK, Non-Disabled Services (ONDS) # (the assumption being that ONDS's are not all that interesting, # let's not use up a lot of screen real estate discussing them) # # The whole thing is contingent upon us being in "brief" mode if ($detail_level ne "full") { # Build the array of ONDS's foreach $service (sort keys %{ $op{$group} }) { $s = \%{ $op{$group}->{$service} }; next if ( ${d{"services"}{$group}{$service}} ) ; if ($s->{"opstatus"} == $OPSTAT{"ok"}) { push (@{ $ONDS{$group} }, "$service"); if ($s->{"last_check"}) { #check to see if service is a trap # Service IS NOT a trap push (@{ $ONDS_lastcheck{$group} }, &pp_sec_brief($s->{"last_check"} - $servertime) ); } else { # Service IS a trap push (@{ $ONDS_lastcheck{$group} }, "--"); } if ( ( $s->{"timer"} == 0 ) && (!($s->{"last_check"})) ) { # Service IS a trap push (@{ $ONDS_nextcheck{$group} }, "--"); } else { # Service IS NOT a trap #push (@{ $ONDS_nextcheck{$group} }, &pp_sec_brief($s->{"timer"}) ); push (@{ $ONDS_nextcheck{$group} }, "" . &pp_sec_brief($s->{"timer"}) .""); } } } # print the OK, no disabled services for this host if any exist if ( $ONDS{$group} && (@{ $ONDS{$group} }) ) { $td_bg_color = ( ($watch_disabled_string ne "") || ($host_disabled_string ne "") ) ? $disabled_color : $BGCOLOR ; $webpage->print("\n"); $webpage->print(""); $webpage->print("$watch_disabled_string$group$host_disabled_string"); $webpage->print("\n"); $webpage->print(""); print join(", ", @{$ONDS{$group}}); $webpage->print("\n"); #Now print out the time(s) $webpage->print(""); print join(", ", @{$ONDS_lastcheck{$group}}); $webpage->print("\n"); $webpage->print(""); # Add the "test all" command if there is more than # one service in the group. push (@{ $ONDS_nextcheck{$group} }, "(test all on $group)") if scalar(@{ $ONDS_nextcheck{$group} }) > 1 ; print join(", ", @{$ONDS_nextcheck{$group}}); $webpage->print("\n"); $webpage->print("\n"); } } # end of ONDS printing } # end of $group loop } sub query_group { # # Print out info about the hosts in a particular hostgroup # my ($args) = (@_); my $group = &validate_name ($args); my (%hosts, $host, $retval, $c, $e, $s, $service, $status, %op, $bgcolor, $msg, $ena_checked, $dis_checked) ; my %OPSTAT = %Mon::Client::OPSTAT; my $table_width = "90%"; # Color to shade the cells depending on whether a user is allowed to # execute the disable/enable commands. my $disable_command_bgcolor = $auth_commands{'disable'}{'auth'} == 0 ? "bgcolor=\"$disabled_color\"" : "" ; my $enable_command_bgcolor = $auth_commands{'enable'}{'auth'} == 0 ? "bgcolor=\"$disabled_color\"" : "" ; my %d = &mon_list_disabled ; if (!defined $group) { $webpage->print("Invalid host group \"$group\"\n"); return undef; } @_ = &mon_list_group($group) ; # turn the array into a hash, which is what we really want foreach (@_) { $hosts{$_} = ""; } $webpage->print("
This page will reload every $reload_time seconds.
"); # Only show the rest of this page if we are allowed to see # information about this group. if ($show_watch_strict) { unless ( &can_show_group($group) ) { print $webpage->h3("You are not authorized to see detailed information for hostgroup '$group'."); print $webpage->h4("Please contact your system administrator for access."); return 0; } } $webpage->print("
Reload this page immediately.
\n"); ############################################################# # The table is divided into 3 sections: hostgroup, hosts, # and services ############################################################# # Start the form and set up our defaults print $webpage->startform(-action=>"$url"); $webpage->param('command','mon_state_change'); print $webpage->hidden(-name=>'command', ); $webpage->param('group',"$group"); print $webpage->hidden(-name=>'group', ); $webpage->param('h',"$monhost"); print $webpage->hidden(-name=>'h', ); $webpage->param('monport',"$monport"); print $webpage->hidden(-name=>'p', ); # Start the table $webpage->print("
"); ############################################################# # Print the hostgroup portion of the table ############################################################# $webpage->print(""); $webpage->print(""); $webpage->print(""); $webpage->print(""); $webpage->print("\n"); $webpage->print(""); $bgcolor = ( ${d{"watches"}{$group}} ) ? $disabled_color : $BGCOLOR; $webpage->print("") ; $dis_checked = ( ${d{"watches"}{$group}} ) ? "checked" : ""; $ena_checked = (!${d{"watches"}{$group}} ) ? "checked" : ""; $webpage->print(""); $webpage->print(""); $webpage->print("\n"); ############################################################# # Print the hosts portion of the table ############################################################# $webpage->print(""); $webpage->print(""); $webpage->print(""); $webpage->print(""); $webpage->print(""); foreach $host (keys %hosts) { if ($host =~ /^\*/) { $host =~ s/^\*// ; #strip the * or else mon dies $hosts{$host} = "disabled"; } else { $hosts{$host} = "enabled"; } } foreach $host (sort keys %hosts) { next if ($host =~ /^\*/); #ignore disabled hosts $webpage->print(""); if ($hosts{$host} eq "disabled") { #check to see if the host is disabled # the host is currently disabled $host =~ s/^\*// ; #strip the * or else mon dies (should already be gone but just in case, this is a bad thing to happen) $webpage->print(""); $webpage->print(""); $webpage->print(""); } else { #host is not currently disabled $webpage->print(""); $webpage->print(""); $webpage->print(""); } $webpage->print( "\n") ; } ############################################################# # Print the services portion of the table ############################################################# $webpage->print(""); $webpage->print(""); $webpage->print(""); $webpage->print(""); $webpage->print("\n"); %op = &mon_list_opstatus; foreach $service (sort keys %{$op{$group}}) { #begin service loop $s = \%{$op{$group}->{$service}}; undef $bgcolor; if (${d{"services"}{$group}{$service}}) { #service is disabled $bgcolor = "$disabled_color"; } $dis_checked = ( ${d{"services"}{$group}{$service}} ) ? "checked" : ""; $ena_checked = (!${d{"services"}{$group}{$service}} ) ? "checked" : ""; if ($s->{"opstatus"} == $OPSTAT{"ok"}) { #OK $bgcolor = "$greenlight_color" unless $bgcolor; $msg="(status: OK)"; } elsif ($s->{"opstatus"} == $OPSTAT{"fail"}) { unless ($bgcolor) { if ( $s->{"alerts_sent"} == 0 ) { $bgcolor = "$yellowlight_color"; $msg=": $s->{'last_summary'}
(status: FAILED,NOALERTS)"; } else { $bgcolor = "$redlight_color"; $msg=": $s->{'last_summary'}
(status: FAILED)"; } if ( $s->{'ackcomment'} ne "" ) { $msg .= "(ACKED: $s->{'ackcomment'})"; } else { $msg .= "(no ack msg)"; } } } elsif ($s->{"opstatus"} == $OPSTAT{"untested"}) { $bgcolor = "$unchecked_color" unless $bgcolor; $msg="(status: UNTESTED)"; } $webpage->print("") ; # Check whether the service is disabled or enabled $webpage->print(""); $webpage->print(""); $webpage->print("\n"); } $webpage->print(""); $webpage->print(""); $webpage->print("
Hostgroup "$group"EnabledDisabled
$group (list downtime log for hostgroup $group)
Members of hostgroup \"$group\"EnabledDisabled
$host (DISABLED)$host
Services monitored on hostgroup \"$group\"
(test all services on hostgroup $group)
EnabledDisabled
$service $msg
    (list downtime log for $group:$service)
") ; $webpage->print("
    (test service $service on group $group immediately)
"); print $webpage->reset(-name=>'Cancel Changes'); $webpage->print("
"); print $webpage->submit(-name=>'Apply Changes'); $webpage->print("
"); print $webpage->end_form(); } sub end_page { # End the document with a footer and contact info &print_bar; if ($monadmin ne "") { $webpage->print("
For questions about this server,
contact $monadmin
mon.cgi v$VERSION
"); } print $webpage->end_html; } sub list_alerthist { # This function lists the alert history formatted in a table my @l = &mon_list_alerthist ; my ($line, $localtime); my $table_width = "80%"; $webpage->print("\n"); $webpage->print("\n"); $webpage->print("\n"); $webpage->print("\n"); $webpage->print("\n"); foreach $line (reverse sort {$a->{"time"} <=> $b->{"time"}} (@l)) { # Only show the alert if we are allowed to see information # about this group. if ($show_watch_strict) { next unless &can_show_group($line->{group}); } $localtime = localtime ($line->{"time"}); $webpage->print(""); $webpage->print("\n"); $webpage->print("\n"); $webpage->print("\n"); $line->{"alert"} =~ s{^.*\/([^/]*)$}{$1}; $webpage->print("\n"); my $args = "-"; if ($line->{"args"} !~ /^\s*$/) { $args = $line->{"args"}; } $webpage->print("\n"); $webpage->print(""); $webpage->print("\n"); } $webpage->print("
GroupServiceTypeTimeAlertArgsSummary
print("args=$line->{group}\">$line->{group}$line->{service}$line->{type}$localtime$line->{alert}$args$line->{summary}
\n"); print $webpage->hr; } sub svc_details { # Lists details about a particular alert's status, regardless of # whether the alert is successful or not. # As of 1.40, this function has been expanded considerably, and # has also been given the benefit of additional verbiage from the # global variables %alert_vars, @time_based_alert_vars, and # @pp_sec_alert_vars # my ($arg) = (@_); my ($group, $service) = split (/\,/, $arg); # Only show the rest of this page if we are allowed to see # information about this group. if ($show_watch_strict) { unless ( &can_show_group($group) ) { print $webpage->h3("You are not authorized to see detailed information for hostgroup '$group'."); print $webpage->h4("Please contact your system administrator for access."); return 0; } } my $status; my $retval; my (@pids, $server, $acknowledge_string, $name_string, $ackcomment_default); my (%op, $s, $g, $var, @time); my $table_width = "90%"; #let's give both tables the same width my $font_color; my %d = &mon_list_disabled; my %desc = &mon_list_descriptions; my $servertime = &mon_servertime; my @group_members = &mon_list_group($group) ; my $time_now = $servertime; my $enable_command_bgcolor = $auth_commands{'enable'}{'auth'} == 0 ? "bgcolor=\"$disabled_color\"" : "" ; my $disable_command_bgcolor = $auth_commands{'disable'}{'auth'} == 0 ? "bgcolor=\"$disabled_color\"" : "" ; my $test_command_bgcolor = $auth_commands{'test'}{'auth'} == 0 ? "bgcolor=\"$disabled_color\"" : "" ; my $ack_command_bgcolor = $auth_commands{'ack'}{'auth'} == 0 ? "bgcolor=\"$disabled_color\"" : "" ; my $disabled_hosts_string ; # Determine whether the service is failing or not # We'll be optimistic and assume it's NOT failing :) # Actually, unchecked services also show up as "ok". %op = &mon_list_successes; if ($op{$group}{$service}) { $status = "ok"; } else { $status = "fail"; %op = &mon_list_failures; } $webpage->print("
This page will reload every $reload_time seconds.
"); print $webpage->hr; $webpage->print("
"); if (${d{"services"}{$group}{$service}}) { #service is disabled $webpage->print ("Test detail for disabled service $service in group $group \n"); } elsif ($op{$group}{$service}{'opstatus'} == 1) { #OK $webpage->print ("Success detail for group $group\n"); $webpage->print ("and service test $service "); } elsif ($op{$group}{$service}{'opstatus'} == 7) { # service is Untested $webpage->print ("Test detail for group $group and service test $service"); $webpage->print ("
(service is UNCHECKED!)"); } else { # service is Failed (or some other opstatus code I don't know about) # If a service fails, print the detail and summary information # at the top. Yes, it's buried down in the middle of the page, but # it's important enough to take up screen real estate with and # bring it to the top. $font_color = ($op{$group}{$service}{'alerts_sent'} == 0) ? $yellowlight_color : $redlight_color ; $webpage->print("\n"); $webpage->print(""); # Now print the detail and summary information for the failed service $op{$group}->{$service}->{'last_summary'} = "<not specified>" if $op{$group}->{$service}->{'last_summary'} eq "" ; $op{$group}->{$service}->{'last_detail'} = "<not specified>" if $op{$group}->{$service}->{'last_detail'} eq "" ; $op{$group}->{$service}->{'last_detail'} =~ s/\n/
/g; $webpage->print("\n"); $webpage->print("\n"); $webpage->print("
"); $webpage->print("
"); $webpage->print ("Failure detail for group $group "); $webpage->print ("and service test $service: \n"); $webpage->print("
"); $webpage->print("
Failure summary:$op{$group}->{$service}->{'last_summary'}
Failure detail:$op{$group}->{$service}->{'last_detail'}
"); } # Issue warning if the whole group has been disabled. if ( ${d{"watches"}{$group}} ) { $webpage->print ("
(NOTE: group $group is disabled.)"); } # Issue warning if any hosts in the group are currently disabled. foreach (@group_members) { if ($_ =~ s/^\*//) { $disabled_hosts_string = " $_" . $disabled_hosts_string ; } } $disabled_hosts_string = "
(NOTE: The following host(s) in group $group are disabled: $disabled_hosts_string)" if $disabled_hosts_string ne ""; $webpage->print ($disabled_hosts_string); # Check to see if a test for this service is currently running # and report back if it is (because the status might not have updated # yet...) @pids = &mon_list_pids; if (!(@pids)) { $webpage->print("Unable to to determine whether this service is currently being tested (list_pids failed)!\n"); } else { shift @pids; #discard server PID, we don't need it for (@pids) { if ( ($_->{"watch"} eq $group) && ($_->{"service"} eq $service) ) { # we have a match, a monitor is currently running for # this group and this service. $webpage->print("
NOTE: A monitor for this service is currently running as PID $_->{'pid'}. Results/opstatus codes might change when this test finishes!\n"); } } } $webpage->print("
Reload this page immediately.
"); $webpage->print("
"); print $webpage->br; $webpage->print(""); $webpage->print ("\n"); if (${d{"services"}{$group}{$service}}) { #service is disabled, offer to enable $webpage->print("\n"); } else { #service is enabled, offer to disable $webpage->print("\n"); } $webpage->print (""); $webpage->print("\n"); $webpage->print("
Test service $service on group $group immediately(ENABLE service $service in group $group)(DISABLE service $service in group $group)List downtime log for service $service and group $group
\n"); # If the service is in a failure state, offer to ack it. if ($status eq "fail") { $webpage->print(""); $webpage->print(""); $webpage->print(""); $webpage->print("\n"); $webpage->print("
"); if ($op{$group}{$service}{'ack'} != 0) { # Service has already been acked, offer to re-ack $acknowledge_string = "Re-acknowledge this failure:
(changes the acknowledgement message)
"; $ackcomment_default = "Was:\"$op{$group}{$service}{'ackcomment'}\""; } else { # Service has not yet been acked, offer to ack $acknowledge_string = "Acknowledge this failure:
(disables all subsequent alerts for this failure period)
"; $ackcomment_default = "${name_string}"; } $webpage->print("$acknowledge_string "); $webpage->print("
"); # It is crucial that we reset the param value, otherwise the # value of the default will be ignored. print $webpage->startform(-action=>"$url"); $webpage->param('ackcomment', $ackcomment_default); $webpage->param('h',"$monhost"); print $webpage->hidden(-name=>'h'); $webpage->param('p',"$monport"); print $webpage->hidden(-name=>'p'); print $webpage->textfield(-name=>'ackcomment', -value=>"$ackcomment_default", -size=>40, ); # The textarea is nice, but you lose the ability to hit ENTER to # submit your ack, which I really really like. # print $webpage->textarea(-name=>'ackcomment', # -value=>"$ackcomment_default", # -rows=>2, # -wrap=>'soft', # -columns=>40, # ); $webpage->print("  "); # We also have to reset this param value $webpage->param('command','mon_ack'); print $webpage->hidden(-name=>'command', ); $webpage->param('args',"$group,$service"); # We also have to reset this param value print $webpage->hidden(-name=>'args', ); print $webpage->submit(-name=>'ack'); print $webpage->end_form(); $webpage->print("
\n"); } $webpage->print("\n"); $webpage->print("\n"); $webpage->print("\n"); my $desc_string = ($desc{$group}{$service} ne "") ? ""$desc{$group}{$service}"" : "<no description specified>" ; $webpage->print("\n"); foreach $var (sort {$b cmp $a } (keys %{$op{$group}{$service}}) ) { # Special cases where we have a time formatted in secs # since 1970, we'll make it look purty if (grep /^${var}$/, @time_based_alert_vars) { # We need to check if the var is defined, since traps # can throw us off. if ( (!defined($op{$group}->{$service}->{$var})) || ($op{$group}->{$service}->{$var} == 0) ) { # The event has never occurred $op{$group}->{$service}->{$var} = "Never" ; } else { # Pretty-print the time @time = localtime ($op{$group}->{$service}->{$var}); $_ = $op{$group}->{$service}->{$var}; $op{$group}->{$service}->{$var} = sprintf ("%.2d:%.2d:%.2d, %s-%s-%s\n", @time[2, 1, 0, 3], @year_months[$time[4]], $time[5]+1900); # Also calculate the delta and pretty-print that $op{$group}->{$service}->{$var} .= "(" . &pp_sec($time_now - $_) . " ago)"; } } elsif ($op{$group}->{$service}->{$var} eq "") { # special case where value of $var is empty #(i.e. mon has never seen the service fail) $op{$group}->{$service}->{$var} = "-"; } elsif (grep /^${var}$/, @pp_sec_alert_vars) { if ( (!defined($op{$group}->{$service}->{$var})) || ($op{$group}->{$service}->{$var} == 0) ) { # The event has never occurred $op{$group}->{$service}->{$var} = "Never" ; } else { # Special case where time is a duration and # should be pretty printed. $op{$group}->{$service}->{$var} = &pp_sec($op{$group}->{$service}->{$var}); } } $op{$group}->{$service}->{$var} =~ s/\n/
/g; $webpage->print("\n"); } $webpage->print("
Variable Description (name)Value
Service Description$desc_string
$alert_vars{$var} ($var)$op{$group}->{$service}->{$var}
\n"); print $webpage->hr; } sub list_disabled { # This function lists all the disabled watches, services, and hosts # and returns the result as pretty(?) HTML my (%d, $group, $service, $host, $watch); my (@disabled_hosts, @disabled_svcs); my $enable_command_bgcolor = $auth_commands{'enable'}{'auth'} == 0 ? "bgcolor=\"$disabled_color\"" : $BGCOLOR ; %d = &mon_list_disabled; print $webpage->hr; $webpage->print("
\n"); # Start the form and set up our defaults print $webpage->startform(-action=>"$url"); $webpage->param('command','mon_state_change_enable_only'); print $webpage->hidden(-name=>'command', ); $webpage->param('h',"$monhost"); print $webpage->hidden(-name=>'h'); $webpage->param('p',"$monport"); print $webpage->hidden(-name=>'p'); $webpage->print("\n"); $webpage->print( ""); $webpage->print(""); $webpage->print(""); $webpage->print( "\n"); $webpage->print( ""); if ( scalar(keys %{$d{"watches"}}) > 0 ) { for (keys %{$d{"watches"}}) { $webpage->print(""); $webpage->print("\n"); } } else { $webpage->print("\n"); } # # Disabled hosts portion of table # $webpage->print(""); $webpage->print(""); $webpage->print(""); $webpage->print( "\n"); foreach $group (keys %{$d{"hosts"}}) { foreach $host (keys %{$d{"hosts"}{$group}}) { push(@disabled_hosts,""); push(@disabled_hosts,""); } } if (scalar(@disabled_hosts) > 0 ) { print join("\n", @disabled_hosts); } else { $webpage->print(""); $webpage->print(""); $webpage->print("\n"); } # # Disabled services portion of table # $webpage->print(""); $webpage->print(""); $webpage->print(""); $webpage->print("\n"); foreach $watch (keys %{$d{"services"}}) { foreach $service (keys %{$d{"services"}{$watch}}) { push(@disabled_svcs, ""); push(@disabled_svcs,""); } } if (scalar(@disabled_svcs) > 0 ) { print join("\n", @disabled_svcs); } else { $webpage->print("\n"); } $webpage->print(""); $webpage->print("\n"); $webpage->print("

Disabled Watches

Enable?

$_
<NONE>

Disabled Hosts

Enable?

$group:$host
<NONE>

Disabled Services

Enable?

$watch:$service
<NONE>
"); print $webpage->reset(-name=>'Cancel Changes'); $webpage->print("
"); print $webpage->submit(-name=>'Apply Changes'); $webpage->print("
\n"); print $webpage->end_form(); $webpage->print("
\n"); } sub list_dtlog { # Accepts the following arguments, all of which are optional: # (group,service,sortby,first log entry to show, last log entry to show) # to sort by. # # Default sort key is failtime. # # If {service,group} is null, shows detail about all failures # for the given {group,service}. # # Default first log entry to show is 1. # # Default last log entry to show is 1+$dtlog_max_failures_per_page. # # No arguments means show all service failures for all groups, # sorted by failtime. # # Someday it would be nice to take args like time ranges, etc., but # that capability should really be built into Mon itself since it # is such a useful feature and something which could leverage a lot # of mon's timeperiod work as well. # # Original patch by Martha H Greenberg # my ($arg) = (@_); my ($group, $service,$sortby,$dtlog_begin,$dtlog_end); if ( defined($arg) ) { ($group, $service,$sortby,$dtlog_begin,$dtlog_end) = split (/\,/, $arg) ; } else { $group = ""; $service = ""; $sortby = "" ; $dtlog_begin = ""; $dtlog_end = ""; } $dtlog_begin = 1 unless ( ($dtlog_begin) && ($dtlog_begin > 0) ); $dtlog_end = ($dtlog_begin + $dtlog_max_failures_per_page - 1) unless ( ($dtlog_end) && ($dtlog_end > 0) ); $sortby = "failtime" unless ($sortby); my $face = $sans_serif_font_face; my $summary_table_width = "80%"; my $dt_table_width = "100%"; my $i; # This has keeps track of the sortby keys and what # their descriptions map to. my %sortby_key = ("group" => "Group", "service" => "Service", "failtime" => "Service Failure Begin Time", "timeup" => "Service Failure End Time", "downtime" => "Total Observed Failure Time", "interval" => "Testing Interval", "summary" => "Summary", ); print $webpage->hr; my ($line, $localtimeup, $localfailtime, $ppdowntime, $ppinterval); my ($first_failure_time, $total_failures, $mtbf, $mean_recovery_time, $median_recovery_time, $std_dev_recovery_time, $min_recovery_time, $max_recovery_time, @l) = &mon_list_dtlog($group, $service) ; my ($ppfft, $ppmtbf, $ppmean_recovery_time, $ppmedian_recovery_time, $ppmin_recovery_time, $ppmax_recovery_time, $ppstd_dev_recovery_time); # Estimated uptime calculation my $time_now = time; my $approx_uptime_pct = ( ( ($time_now - $first_failure_time + $mtbf ) > 0) && ( ($time_now - $first_failure_time + $mtbf - scalar(@l) * $mean_recovery_time > 0 ) ) ) ? sprintf("%.2f%", ( ( ($time_now - $first_failure_time + $mtbf) - (scalar(@l) * $mean_recovery_time) ) / ($time_now - $first_failure_time + $mtbf) ) * 100 ) : "<not applicable>"; $webpage->print("\n"); $webpage->print("\n"); $webpage->print("\n"); $webpage->print("\n"); $webpage->print("\n"); $ppfft = $first_failure_time; my @fftime = localtime ($first_failure_time); $ppfft = sprintf ("%s, %s %d, %.2d at %.2d:%.2d:%.2d", @days_of_week[$fftime[6]], @year_months[$fftime[4]], $fftime[3], $fftime[5] + 1900 , @fftime[2,1,0] ); $webpage->print("\n\n"); $webpage->print("\n"); $webpage->print(""); $webpage->print("\n\n"); $webpage->print("\n"); $webpage->print(""); $webpage->print("\n"); $ppmtbf = &pp_sec($mtbf); $webpage->print("\n"); $webpage->print("\n"); $webpage->print(""); $webpage->print("\n"); $ppmean_recovery_time = &pp_sec($mean_recovery_time); $webpage->print("\n"); $webpage->print("\n"); $webpage->print(""); $webpage->print("\n"); $ppmedian_recovery_time = &pp_sec($median_recovery_time); $webpage->print("\n"); $webpage->print("\n"); $webpage->print(""); $webpage->print("\n"); $ppstd_dev_recovery_time = &pp_sec($std_dev_recovery_time); $webpage->print("\n"); $webpage->print("\n"); $webpage->print(""); $webpage->print("\n"); $ppmin_recovery_time = &pp_sec($min_recovery_time); $webpage->print("\n"); $webpage->print("\n"); $webpage->print(""); $webpage->print("\n"); $ppmax_recovery_time = &pp_sec($max_recovery_time); $webpage->print("\n"); $webpage->print("\n"); $webpage->print(""); $webpage->print("\n"); $webpage->print("\n"); $webpage->print("\n"); $webpage->print("
\n"); $webpage->print("Downtime Summary For Hostgroup "); if ($group eq "") { $webpage->print("<any>"); } else { $webpage->print(""$group""); } $webpage->print(" and Service "); if ($service eq "") { $webpage->print("<any>"); } else { $webpage->print(""$service""); } $webpage->print("
Log begins at:$ppfft
Total observed service failures:$total_failures
Mean time between service failures:$ppmtbf
Mean observed service failure time:$ppmean_recovery_time
Median observed service failure time:$ppmedian_recovery_time
Standard deviation of observed service failure times:$ppstd_dev_recovery_time
Minimum observed service failure time:$ppmin_recovery_time
Maximum observed service failure time:$ppmax_recovery_time
Approximate percentage of time in failure-free operation:$approx_uptime_pct
\n"); return 0 if scalar(@l) == 0; # stop if we returned no downtime events ($dtlog_begin, $dtlog_end) = &moncgi_list_dtlog_navtable ($url, $group, $service, $sortby, $dtlog_begin, $dtlog_end, $total_failures, scalar(@l), %sortby_key) ; # Start printing the actual downtime log table. # Print the header as a table with a thicker border $webpage->print("\n"); $webpage->print("\n"); $webpage->print("\n"); $webpage->print("\n"); $webpage->print("\n"); $webpage->print("\n"); $webpage->print("\n"); $webpage->print("\n"); $webpage->print("\n"); $webpage->print("\n"); # default sort order is "failtime", so no need to resort if ($sortby ne "failtime") { # do a forward-alphanumeric or reverse-numeric sort, # depending on the sortby parameter if ( ($sortby eq "group") || ($sortby eq "service") || ($sortby eq "summary") ) { @l = (sort {$a->{"$sortby"} cmp $b->{"$sortby"}}(@l)); } else { @l = (reverse sort {$a->{"$sortby"} <=> $b->{"$sortby"}}(@l)); } } # Now print the rows of the downtime table for ( $i = $dtlog_begin ; $i <= $dtlog_end ; $i++ ) { $line = $l[$i-1]; $webpage->print(""); $webpage->print(""); $webpage->print("\n"); $localfailtime = localtime ($line->{"failtime"}); $webpage->print("\n"); $localtimeup = localtime ($line->{"timeup"}); $webpage->print("\n"); $ppdowntime = &pp_sec ($line->{"downtime"}); $webpage->print("\n"); $ppinterval = &pp_sec ($line->{"interval"}); $webpage->print("\n"); $webpage->print(""); $webpage->print("\n"); } $webpage->print("
Entry$sortby_key{\"group\"}$sortby_key{\"service\"}$sortby_key{\"failtime\"}$sortby_key{\"timeup\"}$sortby_key{\"downtime\"}$sortby_key{\"interval\"}$sortby_key{\"summary\"}
$i{\"group\"}\">"); $webpage->print("$line->{\"group\"}{\"group\"},$line->{\"service\"}\">"); $webpage->print("$line->{\"service\"}$localfailtime$localtimeup$ppdowntime$ppinterval$line->{\"summary\"}
\n"); &moncgi_list_dtlog_navtable ($url, $group, $service, $sortby, $dtlog_begin, $dtlog_end, $total_failures, scalar(@l), %sortby_key) ; print $webpage->hr; undef @l; } sub list_pids { my $retval; my @pids = &mon_list_pids ; print $webpage->hr; print $webpage->h2("List of mon PID's:"); $webpage->print("Unable to list PID's on server!
\n") if !(@pids); my $server = shift @pids; $webpage->print ("Server PID is $server

\n"); if ( scalar(@pids) > 0 ) { $webpage->print("PID's of currently active monitors:
\n"); $webpage->print("
\n"); for (@pids) { $webpage->print (join ("", "\n", )); } $webpage->print("
HostgroupServicePID
", $_->{"watch"}, "", $_->{"service"}, "", $_->{"pid"}, "
\n"); } else { $webpage->print("<No monitors are running at this time>
\n"); } } ############################################################### # Mon-specific functions. These all have the common feature # that they connect to a Mon server and retrieve some data. # Generally these functions are called by the Presentation functions, # or if they are called directly they do no special output # formatting. ############################################################### sub mon_connect { # Performs the basic connection, and if necessary, authentication, # to a mon server. # If successful, returns a 1 # If unsuccessful because of login failure, returns -1 # If unsuccessful because of other reasons, returns 0 my $retval; # # If we're not connected, we need to connect and possibly authenticate # if ( (! defined($c->connected()) ) || ( $c->connected() == 0 ) ) { $c->connect(); if ($c->error) { $retval = $c->error; print "mon_connect: Could not contact mon server "$monhost": $retval \n" if $connect_failed == 0 ; $connect_failed = 1; #set the global $connect_failed var return 0; } # # Test to see if login is required, and if so, # set the username and password. # if ($must_login) { #print "
Login is "$loginhash{\"username\"}" and passwordis "$loginhash{\"password\"}"\n
"; # # Test to see if username and password are blank. # If so, then use the default username/password. # if ( ( ( ! defined($loginhash{"username"}) ) && ( ! defined($loginhash{"password"}) ) ) || ( ( $loginhash{"username"} eq "" ) && ( $loginhash{"password"} eq "" ) ) ) { # Login is required but no username/password was given, so # try the login and password to the default account $loginhash{"username"} = $default_username ; $loginhash{"password"} = $default_password ; } $c->login(%loginhash); #print "connected as user $loginhash{'username'}\n"; #DEBUG } } if ( ($must_login) && ( defined($c->error) ) && ( ($c->error =~ /530 login unsuccessful/) || ($c->error =~ /no password/) || ($c->error =~ /no username/) ) ) { # Login was required and unsuccessful, present the authform # if it hasn't already been presented. Since some presentation # functions call multiple methods you could very easily # end up with multiple prompts, which is confusing to the # user. &moncgi_authform ($command,"$args") unless $has_prompted_for_auth; $has_prompted_for_auth = 1; return -1; } return 1; } sub mon_views { my ($viewreq); my $conn = &mon_connect ; return 0 if $conn == 0; @views = $c->list_views (); print STDERR "list_views failed" if ($c->error); $viewreq = $webpage->param(-name=>"setview"); if ($viewreq && ($viewreq eq '--all--' || grep(/^$viewreq$/, @views))) { $vcookie = $webpage->cookie(-name=>"$vcookie_name", -value=>"$viewreq", -expires=>"+1y", -path=>"$vcookie_path", ); $curview = $viewreq; } else { $curview = $webpage->cookie(-name=>"$vcookie_name"); } if ($curview && $curview ne '--all--') { $c->setview($curview); } return 1; } sub mon_list_group { # List all the hosts in a given group. Returns an array of hosts # if successful, or undef if failure. my ($group) = (@_); my (@hosts, $retval); my $conn = &mon_connect ; return 0 if $conn == 0; @hosts = $c->list_group ($group); unless ($c->error) { return @hosts ; } else { $retval = $c->error; $webpage->print ("Could not list groups on mon server "$monhost": $retval"); return undef; } } sub mon_list_watch { # List all the watches. Returns an array of defined watch groups and # services. # if successful, or undef if failure. my ($group) = (@_); my (@hosts, $retval); my $conn = &mon_connect ; return 0 if $conn == 0; @hosts = $c->list_watch ($group); unless ($c->error) { return @hosts ; } else { $retval = $c->error; $webpage->print ("Could not list watches on mon server "$monhost": $retval"); return undef; } } sub mon_list_failures { # This function returns a hash of failures. my (%op, $retval); my $conn = &mon_connect ; return 0 if $conn == 0; %op = $c->list_failures(); if ($c->error) { $retval = $c->error; print "Could not execute list failures command mon server on server "$monhost": $retval (perhaps you don't have permissions in auth.cf?)\n"; &moncgi_switch_user($retval); } else { #print "
list_failures command executed successfully
\n"; } return %op; } sub mon_list_successes { # This function returns a hash of successes my (%op, $retval); my $conn = &mon_connect ; return 0 if $conn == 0; %op = $c->list_successes(); if ($c->error) { $retval = $c->error; print "Could not execute list successes command on server "$monhost": $retval (perhaps you don't have permissions in auth.cf?)\n"; &moncgi_switch_user($retval); } return %op; } sub mon_list_opstatus { # This function returns a hash of opstatus # It should accept an optional anonymous array argument, of # [group, service ...] to only return # the opstatus of the group/service pairs you are interested in. # # But it doesn't because I am lazy and don't need this feature # right now :) #my ($criteria) = @_; my (%op, $retval); my $conn = &mon_connect ; return 0 if $conn == 0; %op = $c->list_opstatus(); if ($c->error) { $retval = $c->error; print "Could not execute list opstatus command on server "$monhost":
$retval (perhaps you don't have permissions in auth.cf?)
\n"; &moncgi_switch_user($retval); } return %op; } sub mon_list_disabled { # This function lists all the disabled watches, services, and hosts # and returns the result as a hash my (%d, $retval); my $conn = &mon_connect ; return 0 if $conn == 0; %d = $c->list_disabled(); if ($c->error) { $retval = $c->error; print "Could not execute list disabled command mon server on server "$monhost":
$retval (perhaps you don't have permissions in auth.cf?)
\n"; &moncgi_switch_user($retval); } else { #print "
list_disabled command executed successfully
\n"; } return %d; } sub mon_reload { # Reload mon config file. # Right now the only option supported is to reload the auth.cf file. # my ($what) = (@_); print $webpage->hr; print $webpage->h2("Reloading mon..."); my $retval; my $conn = &mon_connect ; return 0 if $conn == 0; $retval = $c->reload($what); if ($c->error) { $retval = $c->error; print "Could not reload "$what" mon server on server "$monhost":
$retval (perhaps you don't have permissions in auth.cf?)
\n"; &moncgi_switch_user($retval); } else { print "mon server on "$monhost" successfully reloaded.\n"; } } sub mon_loadstate { # A simple wrapper function that calls mon_loadstate_savestate with # the proper arguments. my ($state) = (@_); $state = "disabled" if $state eq ""; print $webpage->hr; print $webpage->h2("Loading saved state for $state..."); &mon_loadstate_savestate("load",$state); } sub mon_savestate { # A simple wrapper function that calls mon_loadstate_savestate with # the proper arguments. my ($state) = (@_); $state = "disabled" if $state eq ""; print $webpage->hr; print $webpage->h2("Saving current state for $state..."); &mon_loadstate_savestate("save",$state); } sub mon_loadstate_savestate { # Loads or saves state of a mon object specifed by $target. Currently # the only object supported by mon for loading/saving state is the # state of the scheduler, so using this function with $target="" will # load or save the state of the scheduler. # # The load/save action is specified by the variable $action my ($action, $state) = (@_); my $retval; my $conn = &mon_connect ; return 0 if $conn == 0; if ($action eq "save") { ($retval = $c->savestate($state)) || ($retval = $c->error); } elsif ($action eq "load") { ($retval = $c->loadstate($state)) || ($retval = $c->error); } if ($c->error ne "") { print "Could not $action state mon server for state "$state" on server "$monhost":
$retval (perhaps you don't have permissions in auth.cf?)
\n"; &moncgi_switch_user($retval); } else { print "$action state succeded on mon server "$monhost".\n"; } } # Stop or start scheduler --------------------------------------------- sub mon_schedctl { # Either stops or starts the scheduler, depending on how it was called, # either with the "stop" argument or the "start" argument. # No return value. my ($action) = (@_); print $webpage->hr; print $webpage->h2("MON: $action scheduler..."); my $retval; my $conn = &mon_connect ; return 0 if $conn == 0; if ($action eq "stop") { $retval = $c->stop(); } elsif ($action eq "start") { $retval = $c->start(); } if ($c->error) { $retval = $c->error; print "Could not $action mon server on server "$monhost":
$retval (perhaps you don't have permissions in auth.cf?)
\n"; &moncgi_switch_user($retval); } else { print "$action scheduler on mon server on "$monhost" succeeded.\n"; } } sub mon_list_pids { my $retval; my @pids; my $conn = &mon_connect ; #test return 0 if $conn == 0; @pids = $c->list_pids; # my $server = shift @pids; if ($c->error) { $retval = $c->error; print "Could not list pids on mon server "$monhost": $retval (perhaps you don't have permissions in auth.cf?)\n"; &moncgi_switch_user($retval); return undef; } else { return @pids; } } sub mon_list_descriptions { # This subroutine executes the list_descriptions() routine and, # if successful, returns a hash of service descriptions, indexed # by watch and service. Returns undef on failure. # my $retval; my %desc; my $conn = &mon_connect ; return 0 if $conn == 0; %desc = $c->list_descriptions; if ($c->error) { $retval = $c->error; print "Could not list descriptions on mon server "$monhost":
$retval (perhaps you don't have permissions in auth.cf?)
\n"; &moncgi_switch_user($retval); return undef; } else { return %desc; } } # Enable a disabled host/watch/service ---------------------------------- sub mon_enable { my ($arg) = (@_); my ($type, $arg1, $arg2) = split (/\,/, $arg); print $webpage->h2("Enabling service..."); my $retval; # Only show the rest of this page if we are allowed to see # information about this group. if ( ($show_watch_strict) && ( ! $type eq "host") ) { unless ( &can_show_group($arg1) ) { print $webpage->h3("You are not authorized to see detailed information for hostgroup '$arg1'."); print $webpage->h4("Please contact your system administrator for access."); return 0; } } my $conn = &mon_connect ; return 0 if $conn == 0; if ($type eq "service") { $retval = $c->enable_service($arg1, $arg2); } elsif ($type eq "host") { $retval = $c->enable_host($arg1); } elsif ($type eq "watch") { $retval = $c->enable_watch($arg1); } if ($c->error) { $retval = $c->error; print "Could not successfully execute command enable_${type} with arguments "$arg1" and "$arg2" on server "$monhost":
$retval (perhaps you don't have permissions in auth.cf?)
\n"; &moncgi_switch_user($retval); return 0; } else { print "enable_${type} succeeded for "; if ($type eq "service") { print "
watch $arg1, service $arg2"; } elsif ($type eq "host") { print "
host $arg1"; } elsif ($type eq "watch") { print "
watch $arg1"; } print "
\n"; } return 1; } # Disable an enabled service ---------------------------------------------- sub mon_disable { my ($arg) = (@_); my ($type, $arg1, $arg2) = split (/\,/, $arg); print $webpage->h2("Disabling service..."); my $retval; # Only show the rest of this page if we are allowed to see # information about this group. if ( ($show_watch_strict) && ( ! $type eq "host") ) { unless ( &can_show_group($arg1) ) { print $webpage->h3("You are not authorized to see detailed information for hostgroup '$arg1'."); print $webpage->h4("Please contact your system administrator for access."); return 0; } } my $conn = &mon_connect ; return 0 if $conn == 0; if ($type eq "service") { $retval = $c->disable_service($arg1, $arg2); } elsif ($type eq "host") { $retval = $c->disable_host($arg1); } elsif ($type eq "watch") { $retval = $c->disable_watch($arg1); } if ($c->error) { $retval = $c->error; print "Could not successfully execute command disable_${type} with arguments "$arg1" and "$arg2" on server "$monhost":
$retval (perhaps you don't have permissions in auth.cf?)
\n"; &moncgi_switch_user($retval); } else { print "disable_${type} succeeded for "; if ($type eq "service") { print "
watch $arg1, service $arg2"; } elsif ($type eq "host") { print "
host $arg1"; } elsif ($type eq "watch") { print "
watch $arg1"; } print "
\n"; } } sub mon_test_service { # Test a service immediately. # Accepts as arguments a group and a service, and optionally an # test argument, which can be either alert, upalert, or startupalert. # Default test is "alert" my ($arg) = (@_); my ($group, $service,$test) = split (/\,/, $arg); # Only show the rest of this page if we are allowed to see # information about this group. if ($show_watch_strict) { unless ( &can_show_group($group) ) { print $webpage->h3("You are not authorized to see detailed information for hostgroup '$group'."); print $webpage->h4("Please contact your system administrator for access."); return 0; } } $test = "monitor" if $test eq ""; print $webpage->h2("Performing $test test on service $service in hostgroup $group..."); my $retval; my $conn = &mon_connect ; return 0 if $conn == 0; $retval = $c->test($test, $group, $service); if ($c->error) { $retval = $c->error; print "Could not successfully execute command "$test" test service "$service" on hostgroup "$group" on server "$monhost": $retval (perhaps you don't have permissions in auth.cf?)\n"; &moncgi_switch_user($retval); } else { print "test $test completed for service $service and hostgroup $group:


"; print " $retval
\n"; } } sub mon_test_config { # Test the mon config file immediately. # Takes no argument (there is only one config file after all) # print $webpage->h2("Testing the syntax of your mon config file..."); my $retval; my $conn = &mon_connect ; return 0 if $conn == 0; my @s = $c->test_config; if ($c->error) { $retval = $c->error; if ( $retval !~ /^520 test config completed/ ) { # command not authorized print "Could not successfully execute command "test config" on server "$monhost":
$retval (perhaps you don't have permissions in auth.cf?)
\n"; &moncgi_switch_user($retval); } elsif ( (defined ($s[0])) && ($s[0] == 0) ) { # there are config file errors $webpage->print("Error in config file found:
" . $s[1] . "\n\n
"); $webpage->print("Please note that you may have other errors in your configuration file, but the checking stops after the first one is found.
"); } else { # some other error occurred print "Could not successfully execute command "test config" on server "$monhost":
$retval (perhaps you don't have permissions in auth.cf?)
\n"; &moncgi_switch_user($retval); } } else { $webpage->print("Test config completed OK, no errors were found in your config file

\n"); } } # Reset mon ---------------------------------------------------- sub mon_reset { ($args) = (@_); print $webpage->hr; print $webpage->h2("Reset mon..."); my $retval; my $conn = &mon_connect ; return 0 if $conn == 0; if ( $args eq "keepstate" ) { # specify we want to keep the scheduler state $retval = $c->reset($args); } else { # reset scheduler state, don't give reset any arguments $retval = $c->reset(); } if ($c->error) { $retval = $c->error; $webpage->print ("Could not reset mon server on server "$monhost": $retval (perhaps you don't have permissions in auth.cf?)\n"); &moncgi_switch_user($retval); } else { $webpage->print ("mon server on "$monhost" successfully reset.

"); if ( $args eq "keepstate" ) { $webpage->print ("Scheduler state was NOT reset.

All previously disabled hosts/groups/services are still disabled."); } else { $webpage->print ("Scheduler state was reset.

All hosts/groups/services are now enabled."); } $webpage->print ("
\n"); } } # List alert history -------------------------------------------------- sub mon_list_alerthist { print $webpage->hr; print $webpage->h2("Alert History:"); my $retval ; my $conn = &mon_connect ; return 0 if $conn == 0; my @l = $c->list_alerthist(); if ($c->error) { $retval = $c->error; print "Could not list alert history on mon server "$monhost": $retval (perhaps you don't have permissions in auth.cf?)\n"; &moncgi_switch_user($retval); } else { #print "
alert history on on "$monhost" successfully retrieved.
\n"; } return @l; } sub mon_list_sched_state { # This function returns an array, @scheduler_state, which # contains the state of the scheduler. This is not exactly # documented, but @scheduler_state[0]==0 seems to indicate # that the scheduler is stopped and @scheduler_state[1] # seems to hold the time (in epoch seconds) since the scheduler was # stopped. my (@scheduler_state, $retval); my $conn = &mon_connect ; return 0 if $conn == 0; @scheduler_state = $c->list_state(); if ($c->error) { $retval = $c->error; print "Could not execute list state command mon server on server "$monhost": $retval (perhaps you don't have permissions in auth.cf?)\n"; &moncgi_switch_user($retval); } else { #print "
list state command executed successfully
\n"; } return @scheduler_state; } sub mon_list_dtlog { # Lists the downtime log (all of it) and returns the results as # an array of hash references. my ($group, $service) = (@_); my $retval ; my (@ltmp, @l, $line); my (@recovery_times); my ($first_failure_time, $mtbf, $mean_recovery_time, $median_recovery_time, $std_dev_recovery_time, $max_recovery_time, $min_recovery_time); my $max_recovery_time_default = -1; #some arbitrary number less than 0 my $min_recovery_time_default = 9999999999999; #some arbitrary really big number my $conn = &mon_connect ; return 0 if $conn == 0 ; @ltmp = $c->list_dtlog(); if ($c->error) { $retval = $c->error; $webpage->print("Could not list downtime log on mon server "$monhost": $retval (perhaps you don't have permissions in auth.cf?)\n"); &moncgi_switch_user($retval); return undef; } my $time_now = time; $max_recovery_time = $max_recovery_time_default; # initialize this to something really small $min_recovery_time = $min_recovery_time_default; # initialize this to something really big $first_failure_time = $time_now; # # Loop through all downtimes, get first downtime, min and max, # and filter based on criteria/specifications. # foreach $line (reverse sort {$a->{"failtime"} <=> $b->{"failtime"}}(@ltmp)){ # # Test to see if this is the first failure time. # if ($line->{"failtime"} < $first_failure_time) { # since this list is already sorted, this will only be true # the very first time we go thru this loop $first_failure_time = $line->{"failtime"} if $line->{"failtime"} < $first_failure_time ; } # # Skip this line if a group and/or service param was # specified and the param doesn't match. # if ( ( defined($group) ) && ($group ne "") && ($group ne $line->{"group"}) ) { next; } if ( ( defined($service) ) && ($service ne "") && ($service ne $line->{"service"}) ) { next; } # # Only show this downtime log entry if we are allowed to see # information about this group. This is probably slow but # no one said security was efficient! # if ($show_watch_strict) { unless ( &can_show_group($line->{"group"}) ) { # This line should not be shown to the user next; } } # # Add this downtime to the list of downtimes # for statistical calculation purposes. # push(@l, $line); push(@recovery_times, $line->{"downtime"}); # # set min and max downtimes # $min_recovery_time = $line->{"downtime"} if $line->{"downtime"} < $min_recovery_time; $max_recovery_time = $line->{"downtime"} if $line->{"downtime"} > $max_recovery_time; } undef @ltmp; #we don't need @ltmp's memory anymore # # Calculate mean recovery time # $mean_recovery_time = &arithmetic_mean(@recovery_times); # # also calculate median recovery time # $median_recovery_time = &median(@recovery_times); # # calculate the mean time between failures as: # (total elapsed time since first failure + E(time until first failure))/(total # of failures) # $mtbf = (scalar(@recovery_times) == 0) ? 0 : ($time_now - $first_failure_time + (($time_now - $first_failure_time) / scalar(@recovery_times))) / scalar(@recovery_times); # # Calculate std deviation of failure times # $std_dev_recovery_time = &std_dev(@recovery_times); # # In case $max_recovery_time and $min_recovery_time are unset # (i.e. there were no failures), set them to sensible defaults. # $max_recovery_time = 0 if $max_recovery_time == $max_recovery_time_default; $min_recovery_time = 0 if $min_recovery_time == $min_recovery_time_default; return $first_failure_time, scalar(@recovery_times), $mtbf, $mean_recovery_time, $median_recovery_time, $std_dev_recovery_time, $min_recovery_time, $max_recovery_time, @l ; } sub mon_ack { # This subroutine takes a comma separated list of a group and a service # as input. # It relies on the global "$ackcomment" for its text. # # If the user is authenticated as anyone other than the default # user, mon_ack inserts their name into the ack comment. # # mon_ack sends an acknowledgement to the mon server for the given # service on the host, the effect of which is to disable any further # alerts for the current failure period. # Ack'ing a service that is not in a failure state will produce the # following error: # "520 service is in a non-failure state" # # We get around this by only presenting the option to ack for # services that are currently in a failure state. # # This function does not return any values. my ($args) = @_; my ($group, $service) = split (/\,/, $args); # Only show the rest of this page if we are allowed to see # information about this group. if ($show_watch_strict) { unless ( &can_show_group($group) ) { print $webpage->h3("You are not authorized to see detailed information for hostgroup '$group'."); print $webpage->h4("Please contact your system administrator for access."); return 0; } } my $retval ; my $conn = &mon_connect ; return 0 if $conn == 0 ; my $name_string = ( ($loginhash{"username"} eq $default_username) || ($loginhash{"username"} eq "") ) ? "" : "[$loginhash{'username'}]: "; # Ack the service w/comment $retval = $c->ack($group, $service, "${name_string}${ackcomment}"); if ($c->error) { $retval = $c->error; $webpage->print("mon_ack: Could not ack service \"$service\" in group \"$group\" on mon server "$monhost": $retval (perhaps you don't have permissions in auth.cf?)\n"); &moncgi_switch_user($retval); } else { $webpage->print("Service \"$service\" in group \"$group\" acknowledged successfully."); } } sub mon_servertime { # This subroutine calls the Mon::Client::servertime function and # returns the time as a scalar, or undef if there is an error. my $retval; my $servertime; my $conn = &mon_connect ; return 0 if $conn == 0; $servertime = $c->servertime; if ($c->error) { $retval = $c->error; print "Could not get server time on mon server "$monhost": $retval (perhaps you don't have permissions in auth.cf?)\n"; &moncgi_switch_user($retval); return undef; } else { return $servertime; } } sub mon_checkauth { # This subroutine checks the authorization for a given command # to see if it is authorized by the server. # Returns: # -1 if a connection with the server cannot be made # 0 if the command is authorized, # 1 if the command is not # authorized, and returns the error string if checkauth fails # (which really shouldn't happen unless a Mon server isn't running) my ($cmd) = @_; my $retval ; my $conn = &mon_connect ; return 0 if $conn == 0 ; return -1 if $conn == -1 ; $retval = $c->checkauth($cmd); if ($retval == 0) { # command not authorized $retval = 0; } elsif ($retval == 1) { # command authorized $retval = 1; } else { # This command should not fail unless a mon server is not running $retval = $c->error; $webpage->print("mon_checkauth: Could not check auth for \"$cmd\" on mon server "$monhost": $retval\n"); # &moncgi_switch_user($retval); } return $retval; } sub mon_state_change_enable_only { # This is called only by list_disabled, and wraps mon_state_change # because mon_state_change assumes only one group and this can # span multiple groups (although the command is enable only, which # simplifies things some). my ($group, $param); my @groups = &mon_list_watch ; foreach $param ( keys(%cgiparams) ) { # For each matching action, try to enable or else exit # in case of an authentication failure (this makes us # keep our CGi variables so that when we do authenticate, # all of our actions are executed). if ($param =~ /^enagroup_/) { &mon_enable("watch,$cgiparams{$param}") || return undef; } elsif ($param =~ /^enahost_/) { &mon_enable("host,$cgiparams{$param}") || return undef; } elsif ($param =~ /^enasvc_/) { &mon_enable("service,$cgiparams{$param}") || return undef; } } &list_disabled; } sub mon_state_change { # This function changes one or more of the states of the hostgroup # given as an argument. It uses the global value %cgiparam to know # what else (hosts and/or services) to modify. my ($group, %hosts, $host, %op, $service); $group = $cgiparams{'group'}; my %d = &mon_list_disabled ; # List the state of the group if (!defined $group) { $webpage->print("Invalid host group \"$group\"\n"); return undef; } # Disable/enable group, if that was requested if ( ( defined ($cgiparams{"group_$group"}) ) && ( $cgiparams{"group_$group"} eq "ena" ) ) { # Enable group if the group is already disabled if ( ${d{"watches"}{$group}} ) { &mon_enable("watch,$group") || return 0; } } elsif ( ( defined ($cgiparams{"group_$group"}) ) && ( $cgiparams{"group_$group"} eq "dis" ) ) { # Disable group if the group is already enabled if ( ! ${d{"watches"}{$group}} ) { &mon_disable("watch,$group") || return 0; } } @_ = &mon_list_group($group) ; # List each member of the group, check to see if there is something # defined for the group. # If so, then change the state if that is required. # Don't make a state change if one is not required. foreach $host (@_) { # Hosts are disabled if they begin with an asterisk # (this is mon's convention, not mine) #print STDERR "Host is $host\n"; #DEBUG if ($host =~ m/^\*/) { # Host is disabled, check to see if we should try and re-enable $host =~ s/^\*//; if ( ( defined($cgiparams{"host_$host"}) ) && ( $cgiparams{"host_$host"} eq "ena") ) { # Try to enable and stop if we can't. &mon_enable("host,$host") || return 0; } } else { # Host is enabled, check to see if we should try and disable if ( ( defined($cgiparams{"host_$host"}) ) && ( $cgiparams{"host_$host"} eq "dis") ) { # Try to disable and stop if we can't. &mon_disable("host,$host") || return 0; } } } # Check each service on the host to see if its state # needs to change. %op = &mon_list_opstatus; foreach $service (sort keys %{ $op{$group} }) { if ( ( defined($cgiparams{"svc_$service"}) ) && ( $cgiparams{"svc_$service"} eq "dis") ) { if (! ${d{"services"}{$group}{$service}}) { #service is enabled # Try to enable and stop if we # can't (i.e. no permissions) &mon_disable("service,$group,$service") || return 0; } } elsif ( ( defined($cgiparams{"svc_$service"}) ) && ( $cgiparams{"svc_$service"} eq "ena") ) { if (${d{"services"}{$group}{$service}}) { #service is disabled # Try to enable and stop if we # can't (i.e. no permissions) &mon_enable("service,$group,$service") || return 0; } } } &query_group($group); } ############################################################### # Mon.cgi-specific functions # The moncgi_* fuctions generally do not manipulate Mon in any # way or present any Mon output to the user. # The moncgi_* functions will each generally call one or more # mon_* functions. ############################################################### # Get the params from the form ----------------------------------------- sub moncgi_get_params { my (@names, $name, $monhost_not_null, $monport_not_null); # # First get params we know about and expect to get. # $command = $webpage->param('command'); $args = $webpage->param('args'); $rt = $webpage->param('rt'); # return to value for pages # which need to keep state info about # which page called them. $rtargs = $webpage->param('rtargs'); #args for $rt $ackcomment = $webpage->param('ackcomment'); #ackcomment # # For the login form, grab username and password. # $loginhash{'username'} = $webpage->param('username'); $loginhash{'password'} = $webpage->param('password'); # # Now get any more parameters which we may have defined. # @names = $webpage->param; foreach $name (@names) { $cgiparams{$name} = $webpage->param($name); } $monhost_not_null = 1 if defined($cgiparams{"h"}) && $cgiparams{"h"} ne ""; $monport_not_null = 1 if defined($cgiparams{"p"}) && $cgiparams{"p"} ne ""; # # Allow user to override values of monhost and monport with # CGI params. # # Untaint monhost and monport, first remove bogus characters, # then "officially" untaint them using $1 # if ( defined($monhost_not_null) ) { # print STDERR "Monhost is defined as '$cgiparams{'h'}'\n"; #DEBUG $monhost = $cgiparams{"h"} ; $monhost =~ s/[^\w.-]//g; $monhost =~ /(.*)/; $monhost = $1; } if ( defined($monport_not_null) ) { # print STDERR "Monport is defined as '$cgiparams{'p'}'\n"; #DEBUG $monport = $cgiparams{"p"} ; $monport =~ s/[^\d]//g; $monport =~ /(.*)/; $monport = $1; } # # If the user gave either a host or port argument that may (or # may not) override the hard-coded value, we need to preserve # this value and encode it in all future URL's that we # generate, so that the value will be preserved when the # mon.cgi page auto-reloads. We also undef $has_read_config, # for mod_perl namespace purposes (scenario: instance 1 # of mon.cgi is invoked with a h= parameter, instance 2 is not, # the instance 2 will eventually pick up instance 1's h= # parameter. # # if ( ( defined($monhost_not_null) ) || ( defined($monport_not_null) ) ) { #print STDERR "Monhost is defined as '$cgiparams{'h'}' (h=$monhost)\n"; #DEBUG #print STDERR "Monport is defined as '$cgiparams{'p'}' (p=$monport)\n"; #DEBUG # # The META tag doesn't respect & for some reason, so # we define another variable. # At least under Navigator 4.x, this is true. # $monhost_and_port_args_meta = "h=$monhost&p=$monport&"; $monhost_and_port_args = "h=$monhost&p=$monport&"; undef $has_read_config ; } else { #user did not enter in either monhost or monport args #print STDERR "Monport ('$monport_not_null':'$cgiparams{'p'}') and monhost('$monhost_not_null':'$cgiparams{'h'}') are undefined.\n"; #DEBUG #undef $monhost_and_port_args_meta; #undef $monhost_and_port_args; $monhost_and_port_args_meta = ""; $monhost_and_port_args = ""; } } sub moncgi_logout { # This subroutine provides the written evidence to the user # that they have been logged out of the mon server. The actual # logging out is done in the setup_page() routine, when the # auth cookie is destroyed in accordance to the value of the # global variable $destroy_auth_cookie print $webpage->hr; print $webpage->h3("User $loginhash{'username'} has been logged off.
"); print $webpage->h3("You will need to re-authenticate to perform further privileged actions."); } # # This subroutine presents the authentication form to the user, # and then runs the command the user was trying to execute with # the new, improved level of privilege. # # This subroutine is usually called because a user tried to # do something that they aren't authorized to do. # # The special command name "moncgi_login" is given when the user # wants to log in without actually doing anything that requires # privs. # sub moncgi_authform { my ($command, $args) = (@_); print $webpage->startform(-method=>'POST', ); $webpage->print("
"); print $webpage->hr; # # Test to see if the command was the special command # "moncgi_login". # if ($command eq "moncgi_login") { $command = "query_opstatus"; print $webpage->h3("Please enter your mon username and password below.
"); } else { print $webpage->h3("You must authenticate as a user of sufficient privilege to perform this command.
"); } # # Start the table. # $webpage->print("\n"); $webpage->print("\n"); $webpage->print("\n"); $webpage->print("\n"); $webpage->print(""); $webpage->print("\n"); $webpage->print("\n"); $webpage->print("\n"); $webpage->print(""); $webpage->print("\n"); $webpage->print(""); $webpage->print(""); $webpage->print(""); $webpage->print("
MON username:"); print $webpage->textfield(-name=>'username', -size=>8, -maxlength=>100, ); $webpage->print("
MON password:"); # Reset the passwd param so it's always blank before # printing out the password field. $webpage->param('password',""); print $webpage->password_field(-name=>'password', -size=>8, -value=>"", -maxlength=>100, ); $webpage->print("
"); print $webpage->submit(-name=>'Login', ); $webpage->print("
\n"); $webpage->print("
"); print $webpage->br; # if this works correctly, the command will be re-executed with # the credentials the user just entered $webpage->param('command', $command); $webpage->param('args', $args); $webpage->param('ackcomment', $ackcomment); # Now pass on the rest of the CGI params as hidden # fields if there are any params passed to the form. foreach (keys (%cgiparams) ) { print $webpage->hidden(-name=>"$_", -value=>"$cgiparams{$_}", ); } print $webpage->end_form; } # Generic button function --------------------------------------------- # Not strictly necessary, but could be useful if you wished to disable # certain features of the client or add new ones in a test capacity. sub moncgi_generic_button { my ($title, $command) = (@_); print $webpage->hr; print $webpage->h2("$title"); $webpage->print ("(command $command not implemented in this client)\n"); print $webpage->hr; } sub moncgi_switch_user { # This subroutine is called after a command fails because a user # is authenticated as a user without sufficient permission to perform # the requested command, so we give the user a chance to re-authenticate # as someone of sufficient privilege. my ($retval) = (@_) ; if ( ($must_login) && ($retval =~ /520 command could not be executed/) ) { # User doesn't have permission to perform command &moncgi_authform ($command,"$args") unless $has_prompted_for_auth; $has_prompted_for_auth = 1; } } # # This subroutine just prints out the legend table explaining what # colors mean what. I broke it out as a separate function so I # could experiment with its location (top or bottom of table). # # Inputs: Width of table (e.g. "70%") # Outputs: always returns 1 sub moncgi_print_service_table_legend { my ($service_table_width) = (@_); # Old way to draw table if (1 == 0 ) { $webpage->print(""); $webpage->print ("\n"); $webpage->print("\n"); $webpage->print("\n "); $webpage->print("\n"); $webpage->print("\n"); $webpage->print("\n"); $webpage->print("
Service color legend:UncheckedGoodFailed
(no alerts sent)
Failed
(alerts sent)
Disabled
"); } # New way to draw table $webpage->print(""); $webpage->print(""); $webpage->print ("\n"); $webpage->print("\n"); $webpage->print(""); $webpage->print(""); $webpage->print(""); $webpage->print(""); $webpage->print("\n"); $webpage->print(""); $webpage->print(""); $webpage->print(""); $webpage->print(""); $webpage->print(""); $webpage->print(""); $webpage->print("
Service color legend:
(top of table)
UncheckedGoodFailed
(no alerts sent)
Failed
(alerts sent)
Disabled
$unchecked_color$greenlight_color$yellowlight_color$redlight_color$disabled_color
\n"); return 1; } sub moncgi_list_dtlog_navtable { # This function is called by list_dtlog. It takes as arguments # the following: ($url, $group, $service, $sortby, $dtlog_begin, # $dtlog_end, $total_failures, $num_events, %sortby_key). # # This function doesn't print any downtime log information per # se. It just prints out navigation for the user to browse the # downtime log. # # This function prints out a table allowing the user to navigate # between the previous N downtime log entries and the next N downtime # log entries, where N is a number we derive based on what the range # the user asked for, what the maximum entries per page to show is, # and the total number of failures observed. # # The reason it's a separate function is that we want to have the # footer placed at the top and the bottom of the downtime log # table, so we're calling it twice. my ($url, $group, $service, $sortby, $dtlog_begin, $dtlog_end, $total_failures, $num_events, %sortby_key) = (@_); my ($next_matches_lower, $next_matches_upper, $prev_matches_lower, $prev_matches_upper); return ($dtlog_begin, $dtlog_end) if $num_events == 0; # stop if we returned no downtime events # Lower bound on which failures to show as next # min($dtlog_end + 1, $total_failures $next_matches_lower = ($total_failures < $dtlog_end + 1) ? $total_failures : $dtlog_end + 1; # Upper bound on which failures to show as next # min($next_matches_lower + $dtlog_max_failures_per_page - 1, $total_failures) $next_matches_upper = ( $total_failures < ($next_matches_lower + $dtlog_max_failures_per_page - 1) ) ? $total_failures : ($next_matches_lower + $dtlog_max_failures_per_page - 1) ; # now reset $dtlog_end in case we were handed a bogus end point $dtlog_end = $next_matches_upper if ($dtlog_end > $num_events); # now reset $dtlog_begin in case we were handed a bogus begin point $dtlog_begin = $dtlog_end if $dtlog_begin > $num_events; # Lower bound on which failures to show as prev # max(1, $dtlog_begin - $dtlog_max_failures_per_page) $prev_matches_lower = ($dtlog_begin - $dtlog_max_failures_per_page > 0) ? ($dtlog_begin - $dtlog_max_failures_per_page ) : 1 ; #$webpage->print("total_failures=$total_failures, dtlog_begin=$dtlog_begin, dtlog_end=$dtlog_end, prev_matches_lower=$prev_matches_lower, next_matches_upper = $next_matches_upper, next_matches_lower = $next_matches_lower\n"); #DEBUG # Start printing the "show previous, show next" table $webpage->print("
\n"); # Only give the option to show previous entries if there are previous # entries to show. if ( ($prev_matches_lower > 0) && ($dtlog_begin > 1) ) { # in the case where ($dtlog_begin - $dtlog_max_failures_per_page) # (e.g. we are currently showing entry 9-23 and want to display 1-8) if ( ( $dtlog_begin > 1) && ($dtlog_begin - $dtlog_max_failures_per_page < 0) ) { $prev_matches_lower = 1; } # Needs to be min($dtlog_begin -1, $total_failures) $prev_matches_upper = ($total_failures < $dtlog_begin - 1) ? $total_failures : $dtlog_begin - 1; printf("" , $url, ${monhost_and_port_args}, $group, $service, $sortby, $prev_matches_lower, $prev_matches_upper ); printf("See events %d-%d\n" , $prev_matches_lower, $prev_matches_upper) ; } # Print the current entries being shown $webpage->print("Displaying downtime events $dtlog_begin-$dtlog_end of $total_failures
(sorting by $sortby_key{$sortby})
"); # Only give the option to show subsequent entries if there are subsequent # entries to show. if ( ($next_matches_upper <= $total_failures) && ($dtlog_end < $total_failures) ) { printf("", $url, ${monhost_and_port_args}, $group, $service, $sortby, $next_matches_lower , $next_matches_upper ); printf("See events %d-%d\n", $next_matches_lower , $next_matches_upper) ; } $webpage->print("

\n"); # It is possible for these values to be changed in this routine, # so send back the values to the calling routine. return ($dtlog_begin, $dtlog_end); } sub moncgi_test_all { # Tests all services for a particular hostgroup # # Inputs: group name # Outputs: void # my ($group) = (@_); # Only show the rest of this page if we are allowed to see # information about this group. if ($show_watch_strict) { unless ( &can_show_group($group) ) { print $webpage->h3("You are not authorized to see detailed information for hostgroup '$group'."); print $webpage->h4("Please contact your system administrator for access."); return 0; } } my (%s, $service); my $conn = &mon_connect; return 0 if $conn == 0; %s = &mon_list_opstatus; if ( ! &mon_checkauth("test") ) { #command is unauthorized &moncgi_switch_user("520 command could not be executed"); return 0; } foreach $service (keys %{$s{$group}}) { &mon_test_service("$group,$service"); } return 1; } # # This subroutine presents a table for the user to reset keepstate # or to reset without keepstate. To do nothing is also an option. # sub moncgi_reset { my $reset_command_bgcolor = $auth_commands{'reset'}{'auth'} == 0 ? "bgcolor=\"$disabled_color\"" : $BGCOLOR ; $webpage->print("

"); $webpage->print(""); $webpage->print(""); $webpage->print(""); $webpage->print("
Reset mon server, keep scheduler state

This clears the state of the scheduler, re-reads the config file, and keeps all watches/hosts/services in their current disabled/enabled state.

You usually want to use this method of resetting the server.

Reset mon server, reset scheduler state

This clears the state of the scheduler, re-reads the config file, and sets all watches/hosts/services to ENABLED.

You only want to use this option if you're sure you want to re-enable all groups/hosts/services!

Do nothing and return to the main status screen


"); return 1; } # # This subroutine reads and parses the optional mon.cgi config file, # and alters global variable values accordingly. # # Inputs: config filename to read # # Outputs: 1 if up-to-date config file has been read # 0 if config file contains errors. # undef if up-to-date config file was not read (file not found) # sub moncgi_read_cf { my ($cf_file) = (@_) ; my ($newcf_file_mtime, $key, $val); # # Test that config file can be read, and if it can, check to see # if we've already read it. # if(-r $cf_file) { # First we check if we have ever read a config file. This # is controlled by the global variable $has_read_config # If so, then we check to see if the copy we have read is # the latest copy. # If not, then we try to read the config file. if ($has_read_config) { # # Since we've already read a config file at least once, # we now check to see if we need to read it again. # We re-read the config file if the mtime of the config # file is different (older OR newer) than the last config # file we read. # $newcf_file_mtime = (stat($cf_file))[9]; if ($newcf_file_mtime == $cf_file_mtime) { #print STDERR "Skipping config read ($newcf_file_mtime == $cf_file_mtime)\n"; #DEBUG return 1; } else { # # Record the new mtime # #print STDERR "Re-reading config ($newcf_file_mtime == $cf_file_mtime)\n"; #DEBUG $cf_file_mtime = $newcf_file_mtime; } } else { # # We've never read the config before, so we get the # initial config file mtime. # $cf_file_mtime = (stat($cf_file))[9]; } } else { print STDERR "mon.cgi: moncgi_read_cf: Unable to open config file '$cf_file' for reading: $!\n"; return undef; } # # Start reading config file # if ( open (CF , "$cf_file") ) { while () { chomp; # Skip blank lines and comment lines next if /^\s*\#/; next if /^\s*$/; # Strip off extra blank space at beg. and end of each line s/^\s*//; s/\s*$//; # # Parse config file lines # if (/^(\w+) \s* = \s* (.*) \s*$/ix) { $key = $1; $val = $2; # # Trivially untaint $key and $val. # We'll do the "real" untainting within the # config file parsing, later. # $key =~ /(.*)/; $key = $1; $val =~ /(.*)/; $val = $1; # # Look for matching key/value pairs and assign them # to the proper variable. Complain if a key/value # pair doesn't match. # if ($key eq "organization") { $organization = $val; } elsif ($key eq "monadmin") { $monadmin = $val; } elsif ($key eq "logo") { $logo = $val ; } elsif ($key eq "logo_link") { $logo_link = $val ; } elsif ($key eq "reload_time") { if ($val <= 0) { print STDERR "mon.cgi: moncgi_read_cf: $cf_file: dtlog_max_failures_per_page must be a number > 0\n"; return 0; } $reload_time = $val; } elsif ($key eq "monhost") { # strip out all non-valid chars for taint purposes $val =~ s/[^\d\w.-]//g; $monhost = $val; } elsif ($key eq "monport") { # strip out all non-digits for taint purposes $val =~ s/[^\d]//g; if ($val <= 0) { print STDERR "mon.cgi: moncgi_read_cf: $cf_file: monport must be a number > 0\n"; return 0; } $monport = $val; } elsif ($key eq "must_login") { $must_login = $val; } elsif ($key eq "app_secret") { $app_secret = $val; } elsif ($key eq "default_username") { $default_username = $val; } elsif ($key eq "default_password") { $default_password = $val; } elsif ($key eq "login_expire_time") { if ($val <= 0) { print STDERR "mon.cgi: moncgi_read_cf: $cf_file: login_expire_time must be a number > 0\n"; return 0; } $login_expire_time = $val; } elsif ($key eq "cookie_name") { $cookie_name = $val; } elsif ($key eq "cookie_path") { $cookie_path = $val; } elsif ($key eq "fixed_font_face") { $fixed_font_face = $val; } elsif ($key eq "sans_serif_font_face") { $sans_serif_font_face = $val; } elsif ($key eq "BGCOLOR") { $BGCOLOR = $val; } elsif ($key eq "TEXTCOLOR") { $TEXTCOLOR = $val; } elsif ($key eq "LINKCOLOR") { $LINKCOLOR = $val; } elsif ($key eq "VLINKCOLOR") { $VLINKCOLOR = $val; } elsif ($key eq "greenlight_color") { $greenlight_color = $val; } elsif ($key eq "redlight_color") { $redlight_color = $val; } elsif ($key eq "yellowlight_color") { $yellowlight_color = $val; } elsif ($key eq "unchecked_color") { $unchecked_color = $val; } elsif ($key eq "dtlog_max_failures_per_page") { if ($val <= 0) { print STDERR "mon.cgi: moncgi_read_cf: $cf_file: dtlog_max_failures_per_page must be a number > 0\n"; return 0; } $dtlog_max_failures_per_page = $val; } elsif ($key eq "untaint_ack_msgs") { $untaint_ack_msgs = $val; } elsif ($key eq "watch") { push(@show_watch, $val); } elsif ($key eq "show_watch_strict") { $show_watch_strict = $val; } else { print STDERR "mon.cgi: moncgi_read_cf: Unknown key-value pair in config file $cf_file: '$key = $val'\n"; return 0; } } else { print STDERR "mon.cgi: moncgi_read_cf: Unparseable config file line in config file '$cf_file': $_\n"; return 0; } } } else { print STDERR "mon.cgi: moncgi_read_cf: Unable to open config file '$cf_file' for reading: $!\n"; return undef; } # # If we've gotten this far, it means the config file was # successfully parsed. # # # Set the global variable that indicates that we have read the # config file. # $has_read_config = 1; #print STDERR "Read the config file!\n"; #DEBUG return 1; } # # This subroutine allows the user to log in without attempting # a privileged action. Trivial but useful. # sub moncgi_login { &moncgi_authform ("moncgi_login",""); } # # This subroutine allows site admins to define their own custom # rows of the command table, which will appear as a third row to the # main command table. Take a look at the sample that's here below. # # You're on your own here with whatever code you put in this subroutine! # Go nuts! # sub moncgi_custom_print_bar { # # This is a sample routine, contributed by Ed Ravin (eravin@panix.com). # # Everything is commented out, and none of the functions are implemented # here, but this should give you the idea of what a custom command # bar would look like. # my ($face)= (@_); #$webpage->print("\n"); #$webpage->print("\tLaunch Space Shuttle\n"); #$webpage->print("\tTake Coffee Break for 30 minutes\n"); #$webpage->print("\tReset Soda Machine\n"); #$webpage->print("\tAcknowledge All Alarms\n"); #$webpage->print("\n"); } # # This subroutine extends the main command processing loop at the end # of this script with your own custom commands. Used in conjunction # with moncgi_custom_print_bar, and other subroutines that you # define in this script, moncgi_custom_commands provides a nice way # to extend mon.cgi at your site. # From Ed Ravin (eravin@panix.com) # sub moncgi_custom_commands { if ($command eq "replace_this_string_with_a_custom_command") { &setup_page("Custom Command #1"); # &call_your_first_custom_code_here; } elsif ($command eq "replace_this_string_with_another_custom_command") { &setup_page("Custom Command #2"); # &call_your_second_custom_code_here; } # as many other custom commands as you care to define go below else # didn't find anything { return 0; } 1; # did find something, suppress further command processing } ############################################################### # Main program ############################################################### # # Instantiate the mon client # $c = new Mon::Client ( host => $monhost, port => $monport, ); if ($command eq "query_opstatus" ){ # Summary opstatus view &setup_page("Operation Status: Summary View"); &query_opstatus("summary"); } elsif ($command eq "query_group" ){ # Expand hostgroup. &setup_page("Group Expansion"); &query_group($args); } elsif ($command eq "list_alerthist"){ # Alert history button. &setup_page("List the alert history"); &list_alerthist; } elsif ($command eq "svc_details"){ # View failure details. &setup_page("Service Details"); &svc_details($args); } elsif ($command eq "list_disabled"){ # List disabled hosts button. &setup_page("List disabled hosts"); &list_disabled; } elsif ($command eq "mon_test_service"){ # Test a service immediately &setup_page("Test Service"); &mon_test_service($args); sleep 1; # if we don't sleep here, svc_details will kick off before # the test does and it will look like we aren't running a test. &svc_details($args); } elsif ($command eq "mon_schedctl"){ # Stop/start the scheduler &setup_page("$args scheduler"); &mon_schedctl ($args); &query_opstatus("summary"); } elsif ($command eq "list_dtlog"){ # List the downtime log &setup_page("List Downtime Log"); &list_dtlog($args); } elsif ($command eq "mon_disable"){ # Disable a host/group/service &setup_page("Disable alert for host, group. or service"); &mon_disable($args); if ($rt eq "query_group") { &query_group($rtargs); } else { &query_opstatus("summary"); } } elsif ($command eq "mon_enable"){ # Enable a host/group/service &setup_page("Enable alert for host, group, or service"); &mon_enable($args); if ($rt eq "query_group") { &query_group($rtargs); } elsif ($rt eq "svc") { &query_opstatus("summary"); } else { &query_opstatus; } } elsif ($command eq "list_pids"){ # View pid button. &setup_page("List pids of server, alerts and monitors."); &list_pids; } elsif ($command eq "mon_reset"){ # Reset mon button. &setup_page("Reset mon"); &mon_reset($args); } elsif ($command eq "mon_ack"){ # Reset mon button. &setup_page("Acknowledge service failure"); &mon_ack($args); #$ackcomment is a global &svc_details($args); } elsif ($command eq "mon_reload"){ # Reload button. &setup_page("Reload Mon"); &mon_reload($args); } elsif ($command eq "mon_loadstate"){ # load mon scheduler state &setup_page("Load Scheduler State"); # right now we expect $args to be empty, since loadstate doesn't take # any arguments, but someday it might, so we prepare. &mon_loadstate($args); } elsif ($command eq "mon_savestate"){ # save mon scheduler state &setup_page("Save Scheduler State"); # right now we expect $args to be empty, since loadstate doesn't take # any arguments, but someday it might, so we prepare. &mon_savestate($args); } elsif ($command eq "moncgi_logout"){ # Log out as auth user. $destroy_auth_cookie = "yes"; &setup_page("Logging out"); &moncgi_logout; } elsif ($command eq "query_opstatus_full"){ # Full operations status &setup_page("Operation Status: Full View"); &query_opstatus("full"); } elsif ($command eq "query_opstatus_failures") { &setup_page("Operation Status: Failures Only"); &query_opstatus("failures"); # Selection "mon_opstatus" will fall through to else. } elsif ($command eq "mon_state_change") { &setup_page("Operation Status: Disable/Enable Groups/Hosts/Services"); &mon_state_change; } elsif ($command eq "mon_state_change_enable_only") { &setup_page("Operation Status: Enable Groups/Hosts/Services"); &mon_state_change_enable_only; } elsif ($command eq "moncgi_test_all") { &setup_page("Operation Status: Test All Services In Group"); &moncgi_test_all($args); } elsif ($command eq "mon_test_config") { &setup_page("Test Mon Config File Syntax"); &mon_test_config($args); } elsif ($command eq "moncgi_reset") { &setup_page("Reset mon Server"); &moncgi_reset($args); } elsif ($command eq "moncgi_login") { &setup_page("Log In To mon Server"); &moncgi_login($args); } elsif ( &moncgi_custom_commands) # check for user extensions { # The actual custom commands are processed # inside &moncgi_custom_commands. # # moncgi_custom_commands returns non-zero if it finds # a command to execute; } else { # All else. &setup_page("Operation Status: Summary View"); &query_opstatus("summary"); } $webpage->print("
"); # # Some stuff we keep around for debugging # #print "commands is $command, args is $args
\n"; #DEBUG #print $webpage->dump; #DEBUG &end_page; $c->disconnect(); etbemon-1.3.6/clients/moncmd0000755000000000000000000001243210230411542012676 0ustar #!/usr/bin/perl # # moncmd - send a command to the mon server # # Jim Trocki, trockij@arctic.org # # $Id: moncmd,v 1.3 2005/04/17 07:42:26 trockij Exp $ # # Copyright (C) 1998, Jim Trocki # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # use Getopt::Std; use Socket; use English; getopts ("ahf:l:s:p:rd"); sub usage; sub do_cmd; $MONSERVER = "localhost"; $MONSERVER = $ENV{"MONHOST"} if (defined ($ENV{"MONHOST"})); $MONSERVER = $opt_s if ($opt_s); $MONPORT = $opt_p || getservbyname ("mon", "tcp") || 2583; if ($opt_h) { usage; } if (!defined ($MONSERVER)) { die "No host specified or found in MONHOST\n"; } $SIG{INT} = \&handle_sig; $SIG{TERM} = \&handle_sig; # # does the input come from stdin or a file? # if ($opt_f) { if ($opt_f eq "-") { $H = STDIN; } else { open (IN, $opt_f) || die "could not open input file: $!\n"; $H = IN; } } elsif (!@ARGV) { if (-t STDIN) { print <); print "\n"; system "stty echo"; die "invalid password\n" if ($PASS =~ /^\s*$/); } elsif (!@ARGV) { $cmd = <$H>; while (defined ($cmd) && $cmd =~ /user=|pass=/i) { chomp $cmd; if ($cmd =~ /^user=(\S+)$/i) { $USER=$1 if (!defined ($USER)); } elsif ($cmd =~ /^pass=(\S+)$/i) { $PASS=$1; } $cmd = <$H>; } } die "inadequate authentication information supplied\n" if ($USER eq "" || $PASS eq ""); } # # set up TCP socket # $iaddr = inet_aton ($MONSERVER) || die "Unable to find server '$MONSERVER'\n"; if ($MONPORT =~ /\D/) { $MONPORT = getservbyname ($MONPORT, 'tcp') } $paddr = sockaddr_in ($MONPORT, $iaddr); $proto = getprotobyname ('tcp'); socket (MON, PF_INET, SOCK_STREAM, $proto) || die "could not create socket: $!\n"; connect (MON, $paddr) || die "could not connect: $!\n"; select (MON); $| = 1; select (STDOUT); #if( defined(my $line = )) { # chomp $line; # unless( $line =~ /^220\s/) { # die "didn't receive expected welcome message\n"; # } #} else { # die "error communicating with mon server: $!\n"; #} # # authenticate self to the server if necessary # if ($opt_a) { ($l, @out) = do_cmd(MON, "login $USER $PASS"); die "Could not authenticate\n" if ($l =~ /^530/); } if ($opt_f or !@ARGV) { $cmd = <$H> if ($opt_f || !@ARGV); $l = ""; while (defined ($cmd) && defined ($l)) { # # send the command # chomp $cmd; ($l, @out) = do_cmd (MON, $cmd); last if (!defined ($l)); for (@out) { print "$_\n"; } print "$l\n"; $cmd = <$H>; } close ($H); } else { ($l, @out) = do_cmd (MON, "@ARGV"); for (@out) { print "$_\n"; } print "$l\n"; } # # log out # do_cmd (MON, "quit"); close(MON); # # submit a command to the server, wait for a response # sub do_cmd { my ($fd, $cmd) = @_; my ($l, @out); return ("", undef) if ($cmd =~ /^\s*$/); @out = (); print $fd "$cmd\n"; while (defined($l = <$fd>)) { chomp $l; if ($l =~ /^(\d{3}\s)/) { last; } push (@out, $l); } ($l, @out); } # # usage # sub usage { print < Wed Jan 2 12:23:44 EST 2002 # Release Version: 1.2 # $Header: /cvsroot/mon/mon/clients/monfailures,v 1.1.1.1 2004/06/09 05:18:07 trockij Exp $ use strict; my %opt; use Getopt::Long; GetOptions (\%opt, "debug", "server=s", "port=s", "user=s", "password=s"); ############################ configurable stuff my $default_user=""; my $default_password= ""; ############################ my $debug= $opt{'debug'} || 0; my (%failures); my ($now); use Mon::Client; my $mon; # find the client if (!defined ($mon = Mon::Client->new)) { die "$0: could not create client object: $@"; } if (defined $opt{'server'}) { $mon->host ($opt{'server'}); } else { $mon->host ("localhost"); } $mon->port ($opt{'port'}) if (defined $opt{'port'}); $mon->username($opt{'user'} || $default_user); $mon->password($opt{'password'} || $default_password); $mon->connect; die "$0: Could not connect to server: " . $mon->error . "\n" unless $mon->connected; if ($mon->username ne "") { $mon->login; die "$0: login failure: " . $mon->error . "\n" if $mon->error; } # Load data from Mon %failures = $mon->list_failures; die "$0: Error doing list_failures : " . $mon->error if ($mon->error); $now= time; # time mon data was fetched # group=thathost service=port8888 opstatus=0 last_opstatus=0 exitval=1 timer=11 # last_success=0 last_trap=0 last_check=955058065 ack=0 ackcomment='' # alerts_sent=0 depstatus=0 depend='' monitor='tcp.monitor -p 8888' # last_summary='thathost' # last_detail='\0athathost could not connect: Connection refused\0a' # last_failure=955058067 interval=60 first_failure=955055062 # failure_duration=3052 my ($watch, $service, $downtime, $summary, $acked); format STDOUT_TOP =  Hostgroup:Service Down Since Error Summary ----------------- ---------- ------------- . format STDOUT = @<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<< $watch . ":" . $service, $downtime, $summary . # list out any failures if (%failures) { foreach $watch (keys %failures) { foreach $service (keys %{$failures{$watch}}) { my $sref= \%{$failures{$watch}->{$service}}; $downtime= localtime $sref->{'first_failure'}; $acked= $sref->{'ack'} !=0; $summary= $sref->{'last_summary'}; $summary= "[acked] $summary" if $acked; write; } } print "\n"; exit(1); } else { print "No failures found.\n"; exit(0); } etbemon-1.3.6/clients/monremote.pl0000755000000000000000000001032710146140375014052 0ustar #!/usr/bin/perl -w # # monremote.pl - Propagates client (user) requests from one mon process to another, # via mon.cgi # # David Nolan, vitroth@cmu.edu # # $Id: monremote.pl,v 1.2 2004/11/15 14:45:17 vitroth Exp $ # # Copyright (C) 2002 Carnegie Mellon University # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # monremote.pl will issue HTTPS requests to a remote Mon server. You must provide it with an # SSL certificate & key, and tell it where mon.cgi is running on the remote server. # Configuration block # SSL Key. You can use your apache server's key for simplicity $crt = '/usr/local/apache/conf/ssl.crt/server.crt'; $key = '/usr/local/apache/conf/ssl.key/server.key'; # List of servers to propagate changes to @hosts = ('monserver1.example.com', 'monserver2.example.com'); # Name of your master Mon server, to prevent propagations from any other hosts $mon_master = "mon-master.example.com"; # URI of mon.cgi on the remote servers. If its different on individual servers # you'll need to do extra work. (Make the hosts list a hash, with the URLS.) $path = '/cbin/mon.cgi'; # Set this to non-zero to enable debugging $debug = 0; # Comment this out once you've edited the config block above. die "monremote.pl must be customized for your environment! Please edit the configuration block."; # You shouldn't need to change anything below here. use LWP::UserAgent; use Sys::Hostname; if (!defined $ARGV[0]) { print "Usage: monremote.pl (enable|disable|test) (watch |host |service )\n"; exit; } # Make sure we're running on the master. $hostname = hostname; $hostname =~ tr/a-z/A-Z/; $mon_master =~ tr/a-z/A-Z/; if ($hostname ne $mon_master) { print STDERR "No propagation from servers other then the master!\n"; exit -1; } # Figure out what the argument portions of the URL need to be. if ($ARGV[0] eq 'disable') { $args = "?command=mon_disable"; if ($ARGV[1] eq 'watch') { $args .= "&args=watch,$ARGV[2]&rt=none"; } elsif ($ARGV[1] eq 'service') { $args .= "&args=service,$ARGV[2],$ARGV[3]&rt=none"; } elsif ($ARGV[1] eq 'host') { $args .= "&args=host,$ARGV[2]&rt=none"; } } elsif ($ARGV[0] eq 'enable') { $args = "?command=mon_enable"; if ($ARGV[1] eq 'watch') { $args .= "&args=watch,$ARGV[2]&rt=none"; } elsif ($ARGV[1] eq 'service') { $args .= "&args=service,$ARGV[2],$ARGV[3]&rt=none"; } elsif ($ARGV[1] eq 'host') { $args .= "&args=host,$ARGV[2]&rt=none"; } } elsif ($ARGV[0] eq 'test') { $args = "?command=mon_test_service&args=$ARGV[1],$ARGV[2]"; } else { print STDERR "Unknown command $ARGV[0]\n"; exit -1; } $ENV{HTTPS_CERT_FILE} = $crt; $ENV{HTTPS_KEY_FILE} = $key; # Now fork and do the work. # We fork so that we don't wait for each individual request to finish. # We fork twice so that the kernel will take care of process cleanup for us. $pid = fork; if ($pid) { waitpid ($pid, 0); print STDERR "Parent exiting\n" if ($debug); exit 0; } else { foreach $host (@hosts) { if (fork) { next; } my $ua = LWP::UserAgent->new; $ua->agent("MonRemote/0.1"); print STDERR "@ARGV\n" if ($debug); print STDERR "$args\n" if ($debug); my $req = HTTP::Request->new(GET => "https://$host/$path$args"); $req ->content_type('application/x-www-form-urlencoded'); my $res = $ua->request($req); if ($res->is_success) { print STDERR "Worker exiting\n" if ($debug); exit 0; } else { print STDERR "\n$host\n@ARGV\nRequest to remote server failed\n"; exit 0; } } print STDERR "Child exiting\n" if ($debug); exit 0; } etbemon-1.3.6/clients/monshow0000755000000000000000000007161613137761622013144 0ustar #!/usr/bin/perl -T # # monshow - concise, user view-based opstatus summary # # Jim Trocki, trockij@arctic.org # # $Id: monshow,v 1.3 2005/04/17 07:42:26 trockij Exp $ # # Copyright (C) 1998, Jim Trocki # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # use strict "vars"; use Getopt::Long; use English; use CGI; use Text::Wrap; use Mon::Client; use Data::Dumper; # # forward declarations # sub usage; sub get_auth; sub read_cf; sub err_die; sub expand_watch; sub secs_to_hms; sub display_allok; sub compose_detail; sub compose_header; sub compose_disabled; sub compose_table; sub compose_trailer; sub get_client_status; sub opstatus_color; sub pre_pad_if_empty; sub tdiff_string; # # set this to the path of your view configuration files # my $VIEWPATH = "/etc/mon/monshow"; my %OPSTAT = %Mon::Client::OPSTAT; my $WORD = '[a-zA-Z0-9_-]+'; my $OUT_BUF = ""; my $e; $= = 1000; $SIG{INT} = \&handle_sig; $SIG{TERM} = \&handle_sig; # safe $PATH for taint mode $ENV{PATH} = '/usr/local/bin:/usr/bin:/bin'; my ($DEP, $GROUP, $SERVICE, $STATUS, $TIME, $NEXT, $ALERTS, $SUMMARY, $DESC); # Untaint args, tainting is just for stuff which comes from CGI. for (@ARGV) { /(.*)/s or die; $_ = $1; } my %opt; GetOptions (\%opt, "showall", "auth", "help", "full", "disabled", "rcfile=s", "login=s", "server=s", "port=i", "prot=s", "detail=s", "watch=s", "view=s") || usage; my $CGI; my %QUERY_ARGS; if (defined $ENV{"REQUEST_METHOD"}) { unless ($CGI = new CGI) { $CGI = 1; err_die ("Can't create CGI object\n"); } } if (!$CGI && $opt{"help"}) { usage; } if ($CGI) { foreach my $e (split (/\?/, $ENV{"QUERY_STRING"})) { next if ($e !~ /=/); my ($var, $val) = split (/=/, $e); $QUERY_ARGS{$var} = $val; } } elsif (!$CGI && @ARGV != 0) { usage "No non-switch args expected\n"; } my $CF = { "host" => "localhost", "full" => 0, "show-disabled" => 0, "bg" => "d5d5d5", "bg-ok" => "a0d0a0", "bg-fail" => "e088b7", "bg-untested" => "e0e0e0", "table-color" => "cccccc", "summary-len" => 80, }; my $GLOBAL = { "view-name" => undef, }; # # read config file # my ($e, $what) = read_cf ($CF); if ($e ne "") { err_die ("while reading config file, $e"); } # # cmdline args override config file # if (!$CGI) { $CF->{"all"} = 1 if ($opt{"showall"}); $CF->{"full"} = 1 if ($opt{"full"}); $CF->{"detail"} = $opt{"detail"} if ($opt{"detail"} ne ""); $CF->{"host"} = $opt{"server"} if ($opt{"server"}); $CF->{"port"} = $opt{"port"} if ($opt{"port"}); $CF->{"prot"} = $opt{"prot"} if ($opt{"prot"}); } # # Interrupt to see if a watch= option was specified # if( $CGI && $QUERY_ARGS{'watch'} ) { # # make a single entry of a pointer to a single array # $what = [ [ $QUERY_ARGS{"watch"} ] ]; } elsif( ! $CGI && $opt{'watch'} ) { # # make a single entry of a pointer to a single array # $what = [ [ $opt{"watch"} ] ]; } # # retrieve client status # my ($e, $st) = get_client_status ($what); if ($e ne "") { err_die ($e); } expand_watch ($what, $st); my $rows = select_table ($what, $st); compose_header ($st->{"state"}); # # CGI invocation # if ($CGI) { if ($QUERY_ARGS{"disabled"}) { compose_disabled ($st->{"disabled"}); } elsif (!$QUERY_ARGS{"detail"}) { compose_table ($rows, $st); compose_disabled ($st->{"disabled"}) if ($CF->{"show-disabled"}); if ($QUERY_ARGS{"watch"}) { $OUT_BUF .= <Back to summary table
EOB } } elsif ($QUERY_ARGS{"detail"}) { compose_detail ($QUERY_ARGS{"detail"}, $st); } } # # cmdline invocation # else { if ($opt{"disabled"}) { compose_disabled ($st->{"disabled"}); } elsif ($CF->{"detail"} ne "") { compose_detail ($CF->{"detail"}, $st); } else { compose_table ($rows, $st); compose_disabled ($st->{"disabled"}) if ($CF->{"show-disabled"}); } } compose_trailer; if ($CGI) { print <query ("login"); $pass = $CGI->query ("password"); } else { if ($opt{"login"}) { $login = $opt{"login"}; } else { return "could not determine username" if (!defined ($login = getpwuid($EUID))); } if (-t STDIN) { system "stty -echo"; print "Password: "; chop ($pass = ); print "\n"; system "stty echo"; return "invalid password" if ($pass =~ /^\s*$/); } else { my $cmd; while (defined ($cmd = <>)) { chomp $cmd; if ($cmd =~ /^user=(\S+)$/i) { $login = $1; } elsif ($cmd =~ /^pass=(\S+)$/i) { $pass = $1; } last if (defined ($login) && defined ($pass)); } } } return "inadequate authentication information supplied" if ($login eq "" || $pass eq ""); return ("", $login, $pass); } # # config file # sub read_cf { my $CF = shift; my ($group, $service); my @RC; my $view = 0; my $RC = "/etc/mon/monshowrc"; if ($CGI) { if ($ENV{"PATH_INFO"} =~ /^\/\S+/) { my $p=$ENV{"PATH_INFO"}; $p =~ s/^[.\/]*//; $p =~ s/\/*$//; $p =~ s/\.\.//g; $RC = "$VIEWPATH/$p"; $GLOBAL->{"view-name"} = $p; $view = 1; } elsif ($QUERY_ARGS{"view"} ne "") { $QUERY_ARGS{"view"} =~ s/^[.\/]*//; $QUERY_ARGS{"view"} =~ s/\.\.//g; $GLOBAL->{"view-name"} = $QUERY_ARGS{"view"}; $RC = "$VIEWPATH/$QUERY_ARGS{view}"; $view = 1; } elsif (-f ".monshowrc") { $RC = ".monshowrc"; } } else { if ($opt{"rcfile"}) { $RC = $opt{"rcfile"}; } elsif ($opt{"view"} ne "") { $RC = "$VIEWPATH/$opt{view}"; $GLOBAL->{"view-name"} = $opt{"view"}; $view = 1; } elsif (-f "$ENV{HOME}/.monshowrc") { $RC = "$ENV{HOME}/.monshowrc"; } } if ($opt{"old"}) { $CF->{"prot"} = "0.37.0"; $CF->{"port"} = 32777; } if (-f $RC) { open (IN, $RC) || return "could not read $RC: $!"; my $html_header = 0; my $link_text = 0; my $link_group = ""; my $link_service = ""; while () { next if (/^\s*#/ || /^\s*$/); if ($html_header) { if (/^END\s*$/) { $html_header = 0; next; } else { $CF->{"html-header"} .= $_; next; } } elsif ($link_text) { if (/^END\s*$/) { $link_text = 0; next; } else { $CF->{"links"}->{$link_group}->{$link_service}->{"link-text"} .= $_; next; } } else { chomp; s/^\s*//; s/\s*$//; } if (/^set \s+ (\S+) \s* (\S+)?/ix) { my $cmd = $1; my $arg = $2; if ($cmd eq "show-disabled") { } elsif ($cmd eq "host") { } elsif ($cmd eq "prot") { } elsif ($cmd eq "port") { } elsif ($cmd eq "full") { } elsif ($cmd eq "bg") { } elsif ($cmd eq "bg-ok") { } elsif ($cmd eq "bg-fail") { } elsif ($cmd eq "bg-untested") { } elsif ($cmd eq "table-color") { } elsif ($cmd eq "html-header") { $html_header = 1; next; } elsif ($cmd eq "refresh") { } elsif ($cmd eq "summary-len") { } else { print STDERR "unknown set, line $.\n"; next; } if ($arg ne "") { $CF->{$cmd} = $arg; } else { $CF->{$cmd} = 1; } } elsif (/^watch \s+ (\S+)/x) { push (@RC, [$1]); } elsif (/^service \s+ (\S+) \s+ (\S+)/x) { push (@RC, [$1, $2]); } elsif (/^link \s+ (\S+) \s+ (\S+) \s+ (.*)\s*/ix) { $CF->{"links"}->{$1}->{$2}->{"link"} = $3; } elsif (/^link-text \s+ (\S+) \s+ (\S+)/ix) { $link_text = 1; $link_group = $1; $link_service = $2; next; } else { my $lnum = $.; close (IN); err_die ("error in config file, line $."); } } close (IN); } elsif (! -f $RC && $view) { err_die ("no view found"); } return ("", \@RC); } sub secs_to_hms { my ($s) = @_; my ($dd, $hh, $mm, $ss); $dd = int ($s / 86400); $s -= $dd * 86400; $hh = int ($s / 3600); $s -= $hh * 3600; $mm = int ($s / 60); $s -= $mm * 60; $ss = $s; if ($dd == 0) { sprintf("%02d:%02d:%02d", $hh, $mm, $ss); } else { sprintf("%d days, %02d:%02d:%02d", $dd, $hh, $mm, $ss); } } # # exit displaying error in appropriate output format # sub err_die { my $msg = shift; if ($CGI) { print < Error

Error

$msg
EOF } else { print < All systems OK

EOF } else { print "\nAll systems OK\n"; } } # # client status # # return ("", $state, \%opstatus, \%disabled, \%deps, \%groups, \%descriptions); # sub get_client_status { my $what = shift; my $cl; if (!defined ($cl = Mon::Client->new)) { return "could not create client object: $@"; } my ($username, $pass); if ($opt{"auth"} && !$CGI) { my $e; ($e, $username, $pass) = get_auth; if ($e ne "") { return "$e"; } $cl->username ($username); $cl->password ($pass); } $cl->host ($CF->{"host"}) if (defined $CF->{"host"}); $cl->port ($CF->{"port"}) if (defined $CF->{"port"}); $cl->port ($CF->{"prot"}) if (defined $CF->{"prot"}); $cl->connect; if ($cl->error) { return "Could not connect to server: " . $cl->error; } # # authenticate self to the server if necessary # if ($opt{"auth"} && !defined ($cl->login)) { my $e = $cl->error; $cl->disconnect; return "Could authenticate: $e"; } # # get disabled things # my %disabled = $cl->list_disabled; if ($cl->error) { my $e = $cl->error; $cl->disconnect; return "could not get disabled: $e"; } # # get state # my ($running, $t) = $cl->list_state; if ($cl->error) { my $e = $cl->error; $cl->disconnect; return "could not get state: $e"; } my $state; if ($running) { $state = $t; } else { $state = "scheduler stopped since " . localtime ($t); } # # group/service list # my @watch = $cl->list_watch; if ($cl->error) { my $e = $cl->error; $cl->disconnect; return "could not get opstatus: $e"; } # # get opstatus # my %opstatus; if (@{$what} == 0) { %opstatus = $cl->list_opstatus; if ($cl->error) { my $e = $cl->error; $cl->disconnect; return "could not get opstatus: $e"; } } else { my @list; foreach my $r (@{$what}) { if (@{$r} == 2) { push @list, $r; } else { foreach my $w (@watch) { next if ($r->[0] ne $w->[0]); push @list, $w; } } } %opstatus = $cl->list_opstatus (@list); if ($cl->error) { my $e = $cl->error; $cl->disconnect; return "could not get opstatus: $e"; } } # # dependencies # my %deps; if ($opt{"deps"}) { %deps = $cl->list_deps; if ($cl->error) { my $e = $cl->error; $cl->disconnect; return "could not list deps: $e"; } } # # descriptions # my %desc; %desc = $cl->list_descriptions; if ($cl->error) { my $e = $cl->error; $cl->disconnect; return "could not list descriptions: $e"; } # # groups # my %groups; if ($QUERY_ARGS{"detail"} || $CF->{"detail"} ne "") { foreach my $g (keys %opstatus) { my @g = $cl->list_group ($g); if ($cl->error) { my $e = $cl->error; $cl->disconnect; return "could not list group: $e"; } grep {s/\*//} @g; $groups{$g} = [@g]; } } # # log out # if (!defined $cl->disconnect) { return "error while disconnecting: " . $cl->error; } return ("", { "state" => $state, "opstatus" => \%opstatus, "disabled" => \%disabled, "deps" => \%deps, "groups" => \%groups, "desc" => \%desc, "watch" => \@watch, }); } sub compose_header { my $state = shift; my $t = localtime; # # HTML stuff # if ($CGI) { $OUT_BUF = < Operational Status EOF if ($CF->{"refresh"}) { $OUT_BUF .= < {refresh}> EOF } $OUT_BUF .= < EOF if ($CF->{"html-header"} ne "") { $OUT_BUF .= $CF->{"html-header"}; } $OUT_BUF .= <Operational Status EOF } foreach my $l (@{$rows}) { my ($depstate, $group, $service) = @{$l}; my $sref = \%{$st->{"opstatus"}->{$group}->{$service}}; $STATUS = "unknown"; $TIME = ""; $DEP = $depstate; my $last = ""; my $bgcolor = opstatus_color ($sref->{"opstatus"}); if ($sref->{"opstatus"} == $OPSTAT{"untested"}) { $STATUS = "untested"; $TIME = "untested"; } elsif ($sref->{"opstatus"} == $OPSTAT{"ok"}) { $STATUS = "-"; } elsif ($sref->{"opstatus"} == $OPSTAT{"fail"}) { if ($sref->{"ack"}) { if ($CGI) { $STATUS = "" . "ACK FAIL"; } else { $STATUS = "ACK FAIL"; } } else { $STATUS = "FAIL"; } } if ($depstate eq "") { $DEP = "-"; } $GROUP = $group; $SERVICE = $service; $DESC = $st->{"desc"}->{$group}->{$service}; $DESC = pre_pad_if_empty ($DESC) if ($CGI); if ($TIME eq "") { $TIME = tdiff_string (time - $sref->{"last_check"}); } if ($sref->{"timer"} < 60) { $NEXT = "$sref->{timer}s"; } else { $NEXT = secs_to_hms ($sref->{"timer"}); } if (length ($sref->{"last_summary"}) > $CF->{"summary-len"}) { $SUMMARY = substr ($sref->{"last_summary"}, 0, $CF->{"summary-len"}) . "..."; } else { $SUMMARY = $sref->{"last_summary"}; } $ALERTS = $sref->{"alerts_sent"} || "none"; my $fmt; if (!$CGI) { $fmt = < EOF } } if ($CGI) { $OUT_BUF .= < EOF } } sub compose_disabled { my $disabled = shift; if (!keys %{$disabled->{"watches"}} && !keys %{$disabled->{"services"}} && !keys %{$disabled->{"hosts"}}) { if ($CGI) { $OUT_BUF .= < Nothing is disabled.

EOF } else { print "\nNothing is disabled.\n"; } return; } if (keys %{$disabled->{"watches"}}) { if ($CGI) { $OUT_BUF .= < Disabled Watches EOF } else { print "\nDISABLED WATCHES:\n"; } foreach my $watch (keys %{$disabled->{"watches"}}) { if ($CGI) { $OUT_BUF .= "$watch
\n"; } else { print "$watch\n"; } } } my @disabled_services; foreach my $watch (keys %{$disabled->{"services"}}) { foreach my $service (keys %{$disabled->{"services"}{$watch}}) { push (@disabled_services, "$watch $service");; } } if (@disabled_services) { if ($CGI) { $OUT_BUF .= < Disabled Services EOF } else { print "\nDISABLED SERVICES\n"; } for (@disabled_services) { if ($CGI) { $OUT_BUF .= "$_
\n"; } else { print "$_\n"; } } } if (keys %{$disabled->{"hosts"}}) { if ($CGI) { $OUT_BUF .= < Disabled Hosts EOF } else { print "\nDISABLED HOSTS:\n"; } foreach my $group (keys %{$disabled->{"hosts"}}) { my @HOSTS = (); foreach my $host (keys %{$disabled->{"hosts"}{$group}}) { push (@HOSTS, $host); } if ($CGI) { $OUT_BUF .= sprintf ("%-15s %s
\n", $group, "@HOSTS"); } else { printf ("%-15s %s\n", $group, "@HOSTS"); } } } } sub compose_trailer { if ($CGI) { $OUT_BUF .= < EOF } } sub compose_detail { my ($args, $st) = @_; my ($group, $service) = split (/,/, $args, 2); if (!defined ($st->{"opstatus"}->{$group}->{$service})) { err_die ("$group/$service not a valid service"); } my $sref = \%{$st->{"opstatus"}->{$group}->{$service}}; my $d; my $bgcolor = opstatus_color ($sref->{"opstatus"}); $bgcolor = "bgcolor=\"#$bgcolor\"" if ($bgcolor ne ""); foreach my $k (keys %OPSTAT) { if ($OPSTAT{$k} == $sref->{"opstatus"}) { $sref->{"opstatus"} = "$k ($sref->{opstatus})"; last; } } foreach my $k (qw (opstatus exitval last_check timer ack ackcomment)) { if ($CGI && $sref->{$k} =~ /^\s*$/) { $d->{$k} = "

 
"; } else { $d->{$k} = $sref->{$k}; } } my $t = time; $d->{"last_check"} = tdiff_string ($t - $d->{"last_check"}) . " ago"; $d->{"timer"} = "in " . tdiff_string ($d->{"timer"}); foreach my $k (qw (last_success last_failure first_failure last_alert)) { if ($sref->{$k}) { $d->{$k} = localtime ($sref->{$k}); } } if ($sref->{"first_failure"}) { $d->{"failure_duration"} = secs_to_hms ($sref->{"failure_duration"}); } # # HTML output # if ($CGI) { my $sum = pre_pad_if_empty ($sref->{"last_summary"}); my $descr = pre_pad_if_empty ($st->{"desc"}->{$group}->{$service}); my $hosts = pre_pad_if_empty ("@{$st->{groups}->{$group}}"); $OUT_BUF .= <Detail for $group/$service
EOF if ($GLOBAL->{"view-name"} ne "") { $OUT_BUF .= < EOF } $OUT_BUF .= <
Server: $CF->{host}
Time: $t
State: $state
View: $GLOBAL->{"view-name"}
Color legend
all is OK
failure
untested


EOF } else { print <{host} time: $t state: $state EOF } } sub select_table { my ($what, $st) = @_; my @rows; # # display everything real nice # if ($CF->{"all"} || @{$what} == 0) { foreach my $group (keys %{$st->{"opstatus"}}) { foreach my $service (keys %{$st->{"opstatus"}->{$group}}) { push (@rows, [$group, $service]); } } } else { @rows = @{$what}; } my (%DEP, %DEPROOT); foreach my $l (@rows) { my ($group, $service) = @{$l}; my $sref = \%{$st->{"opstatus"}->{$group}->{$service}}; next if (!defined $sref->{"opstatus"}); # # disabled things # # fuckin' Perl, man. Just be referencing # $st->{"disabled"}->{"watches"}->{$group}, perl automagically # defines that hash element for you. Great. # if (defined ($st->{"disabled"}->{"watches"}) && defined ($st->{"disabled"}->{"watches"}->{$group})) { next; } elsif (defined ($st->{"disabled"}->{"services"}) && defined ($st->{"disabled"}->{"services"}->{$group}) && defined ($st->{"disabled"}->{"services"}->{$service})) { next; } # # potential root dependencies # elsif ($sref->{"depend"} eq "") { push (@{$DEPROOT{$sref->{"opstatus"}}}, ["R", $group, $service]); } # # things which have dependencies # else { push (@{$DEP{$sref->{"opstatus"}}}, ["D", $group, $service]); } } if ($CF->{"full"}) { [ @{$DEPROOT{$OPSTAT{"fail"}}}, @{$DEPROOT{$OPSTAT{"linkdown"}}}, @{$DEPROOT{$OPSTAT{"timeout"}}}, @{$DEPROOT{$OPSTAT{"coldstart"}}}, @{$DEPROOT{$OPSTAT{"warmstart"}}}, @{$DEPROOT{$OPSTAT{"untested"}}}, @{$DEPROOT{$OPSTAT{"unknown"}}}, @{$DEP{$OPSTAT{"fail"}}}, @{$DEP{$OPSTAT{"linkdown"}}}, @{$DEP{$OPSTAT{"timeout"}}}, @{$DEP{$OPSTAT{"coldstart"}}}, @{$DEP{$OPSTAT{"warmstart"}}}, @{$DEPROOT{$OPSTAT{"ok"}}}, @{$DEP{$OPSTAT{"ok"}}}, @{$DEP{$OPSTAT{"untested"}}}, @{$DEP{$OPSTAT{"unknown"}}}, ]; } else { [ @{$DEPROOT{$OPSTAT{"fail"}}}, @{$DEPROOT{$OPSTAT{"linkdown"}}}, @{$DEPROOT{$OPSTAT{"timeout"}}}, @{$DEPROOT{$OPSTAT{"coldstart"}}}, @{$DEPROOT{$OPSTAT{"warmstart"}}}, @{$DEP{$OPSTAT{"fail"}}}, @{$DEP{$OPSTAT{"linkdown"}}}, @{$DEP{$OPSTAT{"timeout"}}}, @{$DEP{$OPSTAT{"coldstart"}}}, @{$DEP{$OPSTAT{"warmstart"}}}, ]; } } # # build the table # sub compose_table { my ($rows, $st) = @_; if (@{$rows} == 0) { display_allok; return; } # # display the failure table # if ($CGI) { $OUT_BUF .= <
Dep Group Service Desc. Last check Next check Alerts Status Summary
$DEP $GROUP $SERVICE $DESC $TIME $NEXT $ALERTS $STATUS $SUMMARY
Description: $descr
Summary: $sum
Hosts: $hosts
Detail:
$sref->{last_detail}
	
EOF if ($d->{"ack"}) { my $comment = pre_pad_if_empty ($d->{"ackcomment"}); $OUT_BUF .= <

Acknowledgment of failure

$comment EOF } $OUT_BUF .= < EOF # # VAR: # variable name from "show opstatus" # # DESCR: # display name for variable # # IFZERO: # 0 = nothing special # 1 = do not display if zero # 2 = do not display if eq "" # # TYPE: # s = seconds # b = boolean # my ($VAR, $DESCR, $IFZERO, $TYPE) = (0..3); foreach my $k ( ["opstatus", "Operational Status", 0], ["exitval", "Exit Value", 0], ["depend", "Dependency", 2], ["monitor", "Monitor Program", 2], ["last_check", "Last Check", 2], ["timer", "Next Check", 2], ["last_success", "Last Success", 2], ["last_failure", "Last Failure", 2], ["first_failure", "First Failure", 2], ["failure_duration", "Failure Duration", 2], ["interval", "Schedule Interval", 0, "s"], ["exclude_period", "Exclude Period", 2], ["exclude_hosts", "Exclude Hosts", 2], ["randskew", "Random Skew", 1, "s"], ["alerts_sent", "Alerts Sent", 1], ["last_alert", "Last Alert", 2], ["monitor_duration", "Monitor Execution Duration", 2, "s"], ["monitor_running", "Monitor currently running", 0, "b"], ) { my $v = undef; if ($d->{$k->[$VAR]} ne "") { $v = \$d->{$k->[$VAR]}; } elsif ($sref->{$k->[$VAR]} ne "") { $v = \$sref->{$k->[$VAR]}; } # # convert types into display form # if ($k->[$TYPE] eq "s") { if ($$v >= 0) { $$v = secs_to_hms ($$v); } } elsif ($k->[$TYPE] eq "b") { $$v = $$v == 0 ? "false" : "true"; } # # display if zero? # next if ($k->[$IFZERO] == 1 && $$v == 0); next if ($k->[$IFZERO] == 2 && $$v eq ""); $OUT_BUF .= < $k->[$DESCR]: $$v EOF } $OUT_BUF .= < EOF # # custom links # if (defined ($CF->{"links"}->{$group}->{$service})) { if (defined ($CF->{"links"}->{$group}->{$service}->{"link-text"})) { $OUT_BUF .= <

{links}->{$group}->{$service}->{link}\">More Information

$CF->{links}->{$group}->{$service}->{'link-text'} EOF } else { $OUT_BUF .= < $CF->{links}->{$group}->{$service}->{link} EOF } } $OUT_BUF .= < Back to $group table Back to summary table

EOF } # # text output # else { my $n; $Text::Wrap::columns = 70; $n->{"desc"} = wrap (" ", " ", $st->{"desc"}->{$group}->{$service}); $n->{"last_summary"} = wrap (" ", " ", $sref->{"last_summary"}); $n->{"hosts"} = wrap (" ", " ", join (" ", @{$st->{groups}->{$group}})); print <{desc} summary ------- $n->{last_summary} hosts ----- $n->{hosts} -----DETAIL----- $sref->{last_detail} -----DETAIL----- EOF if ($d->{"ack"}) { print <{ackcomment} EOF } print <{opstatus} exitval: $d->{exitval} depend: $d->{depend} monitor: $d->{monitor} last check: $d->{last_check} next_check: $d->{timer} EOF } } sub opstatus_color { my $o = shift; my %color_hash = ( $OPSTAT{"untested"} => $CF->{"bg-untested"}, $OPSTAT{"ok"} => $CF->{"bg-ok"}, $OPSTAT{"fail"} => $CF->{"bg-fail"}, ); $color_hash{$o} || ""; } sub tdiff_string { my $time = shift; my $s; if ($time <= 90) { $s = "${time}s"; } else { $s = secs_to_hms ($time); } } # # for each watch entry which specifies only "group", # expand it into "group service" # sub expand_watch { my $what = shift; my $st = shift; for (my $i=0; $i<@{$what}; $i++) { if (@{$what->[$i]} == 1) { my @list; foreach my $l (@{$st->{"watch"}}) { if ($l->[0] eq $what->[$i]->[0]) { push @list, $l; } } splice (@{$what}, $i, 1, @list); } } } sub pre_pad_if_empty { my $l = shift; return "

 
" if ($l =~ /^\s*$/); $l; } etbemon-1.3.6/clients/skymon/0000755000000000000000000000000013135637032013024 5ustar etbemon-1.3.6/clients/skymon/README0000644000000000000000000000271010230411542013671 0ustar $Id: README,v 1.2 2005/04/17 07:42:26 trockij Exp $ This is a "moncmd" interface to a SkyTel 2-way pager. It utilizes procmail filters and password authentication to do its trick. I would not call this a "secure" authentication mechanism, but in Marcus Ranum-speak it is "really nice". Use at your own risk. It would be even more "really nice" if this did SecureID or S/Key. Also keep in mind that all queries and all results pass through the Great Wide Internet to get back to your pager. INSTALLATION 1. Do this from the /usr/doc/mon/examples directory: mkdir ~/.skytel chmod 0700 ~/.skytel cp skymon.allow ~/.skytel/allow 2. Create an encrypted password using the following Perl snippet, substituting "password" with the password that you want, and "salt" with a *2-letter* salt. perl -e 'print crypt("password", "salt"), "\n"' > ~/.skytel/password chmod 0600 password 3. Add the contents of the "skymon.procmail" file to your .procmailrc. OPERATION Commands are sent via email with the following format: /password:command Commands are the following, and can only be used if they exist in the "allow" file: eh enable host es enable service ew enable watch dh host reason disable host ds watch service reason disable service dw watch reason disable watch lf list failures ld list disabled The idea behind the brevity is that it's a pain to compose messages on that silly little keypad. --------------------- Jim Trocki trockij@arctic.org etbemon-1.3.6/clients/skymon/allow0000644000000000000000000000024410061516617014065 0ustar # # commands to allow through the pager interface # # $Id: allow,v 1.1.1.1 2004/06/09 05:18:07 trockij Exp $ # # enable eh es ew # disable dh ds dw # list lf ld etbemon-1.3.6/clients/skymon/procmail0000644000000000000000000000045010061516617014554 0ustar #Add this entry to your .procmailrc file, substituting "PIN" for #your SkyTel 7-digit 2-way PIN, and your SkyTel pager email address #(PIN@skymail.com). # # $Id: procmail,v 1.1.1.1 2004/06/09 05:18:07 trockij Exp $ # :0 H B D b c * ^From: PIN@skytel.com * ^/[a-zA-Z0-9]*: |skymon PIN@skymail.com etbemon-1.3.6/clients/skymon/skymon0000755000000000000000000001105110230411542014255 0ustar #!/usr/bin/perl # # handle mon commands send via a 2-way pager # # see /usr/doc/mon/README.skymon for information # # skytel pager email address should be supplied as first argument # # Jim Trocki, trockij@arctic.org # # $Id: skymon,v 1.2 2005/04/17 07:42:26 trockij Exp $ # # Copyright (C) 1998, Jim Trocki # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # $PASS = ""; $BUF = "\n"; $MONHOST = "monhost"; $ADDR = shift; die "no address specified\n" if ($ADDR eq ""); # # load command permissions # &load_allow() || die "could not load allow file:$!\n"; $p = 0; while (<>) { if (/^\/(\w+):(.*)/) { $password = $1; $cmd = $2; &check_password ($password) || die "pass\n"; foreach $c (split (/;/, $cmd)) { if ($BUF ne "\n" && $p) { $BUF .= "----\n"; } &parse_cmd ($c); $p = 1; } } } close (OUT); &mail_cmd() if ($BUF ne "\n"); exit; # # check password # sub check_password { my ($pass) = @_; my ($salt); &load_password() || return 0; print "$pass [$PASS]\n"; $salt = substr ($PASS, 0, 2); if (crypt ($pass, $salt) ne $PASS) { return 0; } return 1; } sub load_allow { my ($l); open (P, "$ENV{HOME}/.skytel/allow") || return 0; while (

) { next if /^\s*$/; next if /^\s*#/; $l = $_; chomp $l; $allow{$l} = 1; } close (P); } sub load_password { open (P, "$ENV{HOME}/.skytel/password") || return 0; $PASS =

; close (P); chomp $PASS; return 1; } sub load_address { open (P, "$ENV{HOME}/.skytel/address") || return 0; $ADDR =

; close (P); chomp $ADDR; return 1; } sub parse_cmd { my ($cmd) = @_; my ($c, @args); ($c, @args) = split (/\s+/, $cmd); # # list # if ($c eq "lf" && $allow{"lf"}) { &do_list (@args); } elsif ($c eq "ld" && $allow{"ld"}) { &do_list_disabled(@args); # # disable # } elsif ($c eq "dh" && $allow{"dh"}) { &do_command ("/usr/local/bin/moncmd -s $MONHOST disable host @args"); } elsif ($c eq "dw" && $allow{"dw"}) { &do_command ("/usr/local/bin/moncmd -s $MONHOST disable watch @args"); } elsif ($c eq "ds" && $allow{"ds"}) { &do_command ("/usr/local/bin/moncmd -s $MONHOST disable service @args"); # # enable # } elsif ($c eq "eh" && $allow{"eh"}) { &do_command ("/usr/local/bin/moncmd -s $MONHOST enable host @args"); } elsif ($c eq "ew" && $allow{"ew"}) { &do_command ("/usr/local/bin/moncmd -s $MONHOST enable watch @args"); } elsif ($c eq "es" && $allow{"es"}) { &do_command ("/usr/local/bin/moncmd -s $MONHOST enable service @args"); # # ack (not yet implemented) # } elsif ($c eq "a" && $allow{"a"}) { } } # # list failures # sub do_list { my (@args) = @_; my ($g, $s, $o, $l, $p); open (IN, "/usr/local/bin/moncmd -s monhost list failures|") || return; $p = 0; while () { last if (/220.*completed/); $l = $_; chomp $l; ($g, $s, $o) = ($l =~ (/^(\S+)\s+(\S+)\s+\d+\s+\d+\s+failed\s+(.*)/)); $BUF .= "\n" if ($p); $BUF .= "$g/$s:$o\n"; $p = 1; } close (IN); } # # list disabled # sub do_list_disabled { my (@args) = @_; open (IN, "/usr/local/bin/moncmd -s $MONHOST list disabled|") || return; $p = 0; while () { last if (/220.*completed/); $l = $_; chomp $l; $BUF .= "\n" if ($p); $BUF .= "$l\n"; $p = 1; } close (IN); } # # do_command # sub do_command { my ($cmd) = @_; my ($p); open (C, "$cmd|") || return; $p = 0; while () { $BUF .= "\n" if ($p); $BUF .= $_; $p = 1; } close (C); } # # mail the buffer back to the pager # sub mail_cmd { # &load_address() || die "could not load address\n"; # print "$BUF"; open (MAIL, "| /usr/lib/sendmail -oi -t") || die "could not open pipe to mail: $!\n"; print MAIL < insert n+1 empty lines .\" for manpage-specific macros, see man(7) .TH "SKYMON" "1" "February 12, 2007" "Dario Minnucci " "" .SH "NAME" skymon \- "moncmd" interface to a SkyTel 2\-way pager .SH "DESCRIPTION" .PP .\" TeX users may be more comfortable with the \fB\fP and .\" \fI\fP escape sequences to invode bold face and italics, .\" respectively. \fBskymon\fP This is a "moncmd" interface to a SkyTel 2\-way pager. .PP It utilizes procmail filters and password authentication to do its trick. I would not call this a "secure" authentication mechanism, but in Marcus Ranum\-speak it is "really nice". Use at your own risk. .PP It would be even more "really nice" if this did SecureID or S/Key. .PP Also keep in mind that all queries and all results pass through the Great Wide Internet to get back to your pager. .SH "OPERATION" Commands are sent via email with the following format: /password:command Commands are the following, and can only be used if they exist in the "allow" file: .TP .B eh Enable host .TP .B es Enable service .TP .B ew Enable watch .TP .B dh host reason Disable host .TP .B ds watch service reason Disable service .TP .B dw watch reason Disable watch .TP .B lf List failures .TP .B ld List disabled .PP The idea behind the brevity is that it's a pain to compose messages on that silly little keypad. .SH "SEE ALSO" .BR mon (8), .BR moncmd (1), .BR monshow (1) .SH "AUTHOR" skymon was written by Jim Trocki, .PP This manual page was written by Dario Minnucci , for the Debian project (but may be used by others). etbemon-1.3.6/debian/0000755000000000000000000000000014203606346011266 5ustar etbemon-1.3.6/debian/NEWS0000644000000000000000000000052712355124105011763 0ustar mon (1.2.0-3) unstable; urgency=low The following alerts and monitors are not longer provided by 'mon' package: * imap-ssl.monitor * ipvs.alert * ipvs.monitor * smblist.monitor These scripts (and many others) are provided by 'mon-contrib' package. -- Dario Minnucci Mon, 11 Jul 2011 11:05:05 +0200 etbemon-1.3.6/debian/README.Debian0000644000000000000000000000434113455035423013331 0ustar README.Debian: -------------- * New and deprecated alerts and monitors in mon-1.2.0: ------------------------------------------------------ - Added alerts: irc.alert - Added monitors: dns-query.monitor local-syslog.monitor lpd.monitor ntpdate.monitor radius.monitor snmpdiskspace.monitor snmpvar.monitor trace.monitor - Removed alerts: remote.alert - Removed monitors: http_t.monitor http_tp.monitor http_tpp.monitor - Rename monitors: dialin.monitor to dialin.monitor.wrap * Daemon runs under 'mon' user: ------------------------------- The daemon is not longer running as 'daemon' user. Since version 0.99.2-12, mon runs under user 'mon', that is created at the package installation/update process. * Daemon control via /etc/default/mon: -------------------------------------- Now 'mon' daemon can be controlled through /etc/default/mon directly. These 2 options allows you to control the daemon behaviour: - ENABLED: If you don't want to run 'mon' at boot time, please ensure the variable ENABLED in /etc/default/mon is set to something different to : "yes", "true" or "1" Default is: ENABLED="yes" - DAEMON_OPTS: Additional options can be passed to the daemon by adding them to DAEMON_OPTS. Default is DAEMON_OPTS=" -f -c /etc/mon/mon.cf -A /etc/mon/auth.cf" * Using CGI: ------------ If a webserver with CGI support is available on your system, both web interfaces can be accessed from the following URL: http:///cgi-bin/monshow.cgi OR http:///cgi-bin/mon.cgi The layout and behaviour of both interfaces, can be modified via an independent configuration files. Changes on 'monshow.cgi' should be made via it's configuration file '/etc/mon/monshowrc' For details see: /usr/share/doc/mon/README.cgi-bin /usr/share/doc/mon/examples/example.monshowrc * Using local monitors: ----------------------- Under Debian GNU/Linux, paths for alerts and monitors differs from the original paths provided by software in order to comply with FHS. Our alerts are located under '/usr/lib/mon/alert.d' and our monitors under '/usr/lib/mon/mon.d' directory. Please take this into account if your intend to add your own scripts. etbemon-1.3.6/debian/README.source0000644000000000000000000000046212355124105013441 0ustar README.source ------------- The Debian package uses quilt(1) for the modifications of the upstream source. If you want to change something it is best to use the quilt approach as documented in /usr/share/doc/quilt/README.source -- Dario Minnucci Wed, 20 Jan 2010 14:36:13 +0100 etbemon-1.3.6/debian/TODO0000644000000000000000000000016612355124105011753 0ustar # # TODO # * Add NEWS.Debian file to inform about alerts or monitors now availables via 'mon-contrib' package etbemon-1.3.6/debian/changelog0000644000000000000000000010254714203606346013151 0ustar etbemon (1.3.6-2) unstable; urgency=medium * Removed the ignore option from linux-temp.monitor because it didn't work properly and made it correctly log the section. * Removed debugging code from hplog.helper.cpp that I accidentally released in 1.3.6. -- Russell Coker Fri, 18 Feb 2022 14:05:10 +1100 etbemon (1.3.6-1) unstable; urgency=medium * Made sslcert.monitor give better logging for a name with multiple IPs * Made hp-temp.monitor work properly and give better error messages * Add dell-temp.monitor for Dell servers * Add -x option to ps.monitor to show what perl thinks the process name is -- Russell Coker Sun, 16 Jan 2022 09:21:17 +1100 etbemon (1.3.5-8.1) unstable; urgency=medium * Non-maintainer upload. * Apply patch from Aurelien Jarno to fix FTBFS with glibc 2.32. (Closes: #992896, #997898) -- Adrian Bunk Thu, 09 Dec 2021 20:05:25 +0200 etbemon (1.3.5-8) unstable; urgency=medium * Add selinux.monitor, currently checks for permissive mode and processes in initrc_t. -- Russell Coker Mon, 08 Nov 2021 13:26:44 +1100 etbemon (1.3.5-7) unstable; urgency=medium * Suggests libdbd-mysql-perl for msql-mysql.monitor. * Uncommented the line in hp-temp.monitor that does the real work. -- Russell Coker Tue, 24 Aug 2021 16:49:29 +1000 etbemon (1.3.5-6) unstable; urgency=medium * Better fix for headers in imapnew.monitor that doesn't need libhash-case-perl. * Added hp-temp.monitor to use /sbin/hplog to monitor HP server temperature * Added -M option to smartctl.monitor for MegaRAID AKA PERC support and added support for NVMe devices -- Russell Coker Mon, 07 Jun 2021 16:34:01 +1000 etbemon (1.3.5-5) unstable; urgency=medium * Make the deleted-mapped check avoid perl privsep processes, don't want to force users to logout to pass the check * Made imapnew.monitor give a correct error when a message has no Message-Id also made it do case-insensitive checks on header field names. Now recommends libhash-case-perl as imapnew.monitor depends on it. -- Russell Coker Mon, 05 Apr 2021 18:28:52 +1000 etbemon (1.3.5-4) unstable; urgency=medium * Make deleted-mapped.monitor skip programs starting with /lib/systemd/system. Add -u option to specify maximum UID to check, default 999. -- Russell Coker Mon, 22 Feb 2021 16:18:05 +1100 etbemon (1.3.5-3) unstable; urgency=medium * Support "python3" and "python3.9" as interpreters for ps.monitor. * Don't warn from deleted-mapped.monitor.real when process exits before we can open the map file. -- Russell Coker Tue, 19 Jan 2021 18:04:35 +1100 etbemon (1.3.5-2) unstable; urgency=medium * Update loadavg.monitor to display PSI cgroup2 data to show which cgroups are responsible for high load average. -- Russell Coker Wed, 06 Jan 2021 08:52:30 +1100 etbemon (1.3.5-1) unstable; urgency=medium * Add smartctl.monitor to run smartctl and parse it's output. * New minor version for new test and the other small changes. -- Russell Coker Sun, 20 Dec 2020 11:10:47 +1100 etbemon (1.3.4-5) unstable; urgency=medium * Make sslcert test deal with hosts that lack an IPv6 or an IPv4 record. -- Russell Coker Fri, 11 Dec 2020 11:30:34 +1100 etbemon (1.3.4-4) unstable; urgency=medium * Made freespace.monitor check for filesystem that wasn't mounted, recommend libsys-filesystem-perl for this. * Made sslcert.monitor check all A and AAAA records for a name by default. Added -4 option for IPv4 only. -- Russell Coker Thu, 10 Dec 2020 22:41:58 +1100 etbemon (1.3.4-3) unstable; urgency=medium * Made linux-temp.monitor send stderr of /usr/bin/sensors to /dev/null. * Made ps.monitor give more detail -- Russell Coker Thu, 21 May 2020 11:58:42 +1000 etbemon (1.3.4-2) unstable; urgency=medium * Update comments in deleted-mapped.monitor.real * Change VCS dirs in control * Change smtpswaks.monitor to have a space between "-S" and "2" as the latest version of swaks requires. -- Russell Coker Sun, 05 Apr 2020 09:39:09 +1000 etbemon (1.3.4-1) unstable; urgency=medium * Added monitor for deleted mapped files for detecting upgraded shared objects * Change Standards version to 4.3.0 -- Russell Coker Sun, 02 Feb 2020 18:13:30 +1100 etbemon (1.3.3-6) unstable; urgency=medium * Add SUID helper for zfs and for deleted-mapped.monitor * Made deleted-mapped.monitor ignore /dev/zero as memory mapped usage routinely reports that as deleted. -- Russell Coker Mon, 06 Jan 2020 19:59:16 +1100 etbemon (1.3.3-5) unstable; urgency=medium * Made loadavg.monitor check swap space and made the output nicer. * Made linux-temp.monitor display processes with top CPU use and give better summary. * Give better log errors from mon on userfile auth failures. * Added password authentication support to remote.monitor * Added deleted-mapped.monitor that checks for files that are memory mapped but have been deleted, experimental and may get false positives. Designed to deal with security updates to shared objects that are in use. -- Russell Coker Mon, 06 Jan 2020 17:04:00 +1100 etbemon (1.3.3-4) unstable; urgency=medium * Make dns.monitor correctly display a summary when multiple queries are used * Stop loadavg.monitor from saying "Text read from file" * Make ps.monitor also check for lua5.2 * Link btrfs.helper with gcc instead of g++ to reduce dependencies. * Better comments in auth.cf and README.traps * Better logging of trap password issues * Fixed a username bug in trap.alert * imapnew.monitor now deletes messages even if there is a delay or clock skew * Make btrfs.monitor correctly handle count files and have better comments. * Fix the build to clean up the compiled helper programs, and build with correct diff. Closes: #909854 * Make trapbind default to 127.0.0.1. Closes: #910741 * Fix README.monitors. Closes: #910743 -- Russell Coker Tue, 30 Apr 2019 20:38:26 +1000 etbemon (1.3.3-3) unstable; urgency=medium * Make btrfs.monitor check for subvols and also use a SETUID helper instead of sudo -- Russell Coker Mon, 23 Jul 2018 15:24:34 +1000 etbemon (1.3.3-2) unstable; urgency=medium * Don't abort mon.cgi when $ONDS{$group} is invalid * Removed defined() around hash and array checks not supported in recent perl * Check Received: headers for long delays and clock skew in imapnew.monitor -- Russell Coker Wed, 11 Jul 2018 01:40:04 +1000 etbemon (1.3.3-1) unstable; urgency=medium * Added SNI support to sslcert.monitor. * New upstream version because the previous 2 Debian releases have enough changes to make it worthwhile. -- Russell Coker Wed, 16 May 2018 16:16:54 +1000 etbemon (1.3.2-3) unstable; urgency=medium * Make smtpswaks.monitor use long form swaks arguments for ease of searching the man page * Made mailxmpp.alert set a CPU time limit -- Russell Coker Mon, 01 Jan 2018 15:25:22 +1100 etbemon (1.3.2-2) unstable; urgency=medium * Conflict with mon-contrib (<= 1.0+dfsg-3+nmu1), Closes: #876088 * Use dh_installsystemd to comply with latest debhelper, Closes: #878850 * Recommends libtimedate-perl for imap test * Added support for authentication to smtpswaks.monitorm, for relay tests. -- Russell Coker Thu, 07 Dec 2017 01:57:42 +1100 etbemon (1.3.2-1) unstable; urgency=medium * Made http.monitor use strict and made it not give an error if the server doesn't close the connection after sending the data. * Made dns.monitor give a more detailed summary. * Made zfs.monitor give a summary of the error count when it's deemed to be OK. * Rename softraid2.monitor to softraid.monitor * Make freespace.monitor check for Inodes free if filesystem supports it and recommend libfilesys-df-perl which it now uses. * Remove all configuration options from /etc/default/mon for Debian and put them in the sample mon.cf file. * Moved sample configuration files out of the debian directory for the benefit of other distributions. * Added new systemd subdirectory for systemd config files * Added systemd service file and use debhelper compat level 11 to get automatic dh_systemd stuff * Rewrote sslcert.monitor in perl and made it give better messages and also status on no error. * Made loadavg.monitor not display D status heading if there are no D state processes, only display the first 120 characters of the process details, and not display processes using less than 5% CPU. * Made mailxmpp.alert use TLS for XMPP -- Russell Coker Sun, 17 Sep 2017 16:19:34 +1000 etbemon (1.3.1-1) unstable; urgency=medium * Fixed up the hack for freespace.monitor. * Stop using quilt as upstream will be identical to Debian in almost all cases. * Made remote.monitor correctly report an error on connect timeout Closes: #870239 Made the exclude option on remote.monitor work correctly * Made loadavg.monitor correctly sort by CPU time and ignore 0.0% and ps header Closes: #870238 * Removed the hack for freespace.monitor * Changed the summary-len in monshow to 80, as we already line wrap on a 80 column terminal might as well go big * Made the password option in msql-mysql.monitor read from a file if the first character is / -- Russell Coker Thu, 10 Aug 2017 10:42:03 +1000 etbemon (1.3.0-1) unstable; urgency=medium * Forked upstream and renamed it to etbemon -- Russell Coker Tue, 25 Jul 2017 22:37:33 +1000 mon (1.2.0-12) unstable; urgency=medium * Made btrfs and zfs checks accept low and high numbers for error counts. * Add softraid2.monitor which doesn't use diff, has no problems with drive ordering, and allows specifying which arrays must exist. -- Russell Coker Wed, 12 Jul 2017 23:15:01 +1000 mon (1.2.0-11) unstable; urgency=medium * Make zfs.monitor and btrfs.monitor alert when you forget to fix the okcount after fixing an error. * Made loadavg.monitor correctly sort the CPU time and send a sort error to /dev/null * Tweaked the output of imapnew.monitor * Made the remote.monitor have better debugging and put it in a separate patch, also added --exclude option * Use /run instead of /var/run * Recommend swaks for smtpswaks.monitor * Recommend libcgi-pm-perl for monshow * Recommend bc for sslcert.monitor * Recommend libproc-processtable-perl for ps.monitor -- Russell Coker Sun, 18 Jun 2017 18:52:20 +1000 mon (1.2.0-10) unstable; urgency=medium * Change to team maintainership. * Make loadavg.monitor report on D state processes and processes using the most CPU. * Added imapnew.monitor to check for new messages via IMAP and recommends libmail-imapclient-perl for it. -- Russell Coker Tue, 23 May 2017 18:46:51 +1000 mon (1.2.0-9+nmu4) unstable; urgency=medium * Use the correct name for the tmpfiles.d file Closes: #851354 -- Russell Coker Mon, 16 Jan 2017 12:16:21 +1100 mon (1.2.0-9+nmu3) unstable; urgency=medium * Add sslcert.monitor to check certificate expiry and smtpswaks.monitor to check mail servers with swaks -- Russell Coker Wed, 21 Dec 2016 21:08:11 +1100 mon (1.2.0-9+nmu2) unstable; urgency=medium * Move freespace.monitor to local directory. -- Russell Coker Wed, 21 Dec 2016 20:47:11 +1100 mon (1.2.0-9+nmu1) unstable; urgency=medium * Non-maintainer upload. * Make default config bind to 127.0.0.1 Closes: #820712 * Add restorecon and tmpfiles.d file Closes: #822606 * Don't specify config options on both the default command-line and the default configuration file Closes: #821360 * Move local monitor scripts to /usr/lib/mon/mon-local.d to separate them from network checks Closes: #847437 * Added remote.monitor to this package and made it strict. Closes: #847441 Fixed the problems with it Closes: #824176 * Added ps.monitor and made it strict. Also made it handle perl, python, and lua5.1 interpreters correctly. Closes: #847444 * Conflicts with mon-contrib <= 1.0+dfsg-3 because of remote.monitor and ps.monitor * Added mailxmpp.alert, an alert that sends mail and XMPP messages * Added linux-temp.monitor for local system temperature and loadavg.monitor * Extended ping.monitor to support ipv6 and specifying the ping count -- Russell Coker Mon, 12 Dec 2016 10:00:22 +1100 mon (1.2.0-9) unstable; urgency=medium * debian/control: - Bump Standards-Version to 3.9.6 (no changes) - libtime-modules-perl has been renamed by upstream, so it was updated to it's current name 'libtime-parsedate-perl' (Closes: #749875) * debian/mon.init.d: required-start facility changed from $all to $syslog to deal with lintian error: "E: mon: init.d-script-depends-on-all-virtual-facility etc/init.d/mon required-start" * debian/copyright: Years updated to 2014 -- Dario Minnucci Sun, 26 Oct 2014 16:23:52 +0100 mon (1.2.0-8) unstable; urgency=low * debian/patches: - Added 06-fix-dns-monitor.diff: Fixes use of deprecated defined(@array) calls. Thanks to Brogniaux Gaëtan. (Closes: #731737) * debian/control: - Bump Standards-Version to 3.9.5 (no changes) -- Dario Minnucci Tue, 31 Dec 2013 04:16:37 +0100 mon (1.2.0-7) unstable; urgency=low * debian/copyright: - Upstream-Source URL updated. (Closes: #659993) - Years updated to 2013 * debian/watch: Modified to use SF sources. Thanks to Nick Black. (Closes: #695242) * debian/mon.dirs: Added /var/lib/mon. Thanks to Andreas Beckmann. (Closes: #661087) * debian/control: - Bump Standards-Version to 3.9.4 (no changes) - Use canonical URI on VCS-* fields -- Dario Minnucci Thu, 21 Feb 2013 03:18:47 +0100 mon (1.2.0-6) unstable; urgency=low * debian/control: Really set debhelper compat to >=9. * debian/copyright: Source URL updated. - Thanks to Jari Aalto (Closes: #655357) * debian/patches: - 04-fix-659152-report.monitor-ignores-command-line-options.diff Fix for report.monitor ignores command-line options. Thanks to Kevin McCormick (Closes: #659152) * debian/mon.postrm: Fix to not remove user 'mon' twice. (Closes: #656351) -- Dario Minnucci Sun, 12 Feb 2012 17:00:45 +0100 mon (1.2.0-5) unstable; urgency=low * Enable hardened build flags: - Added patch 00-mon-hardened-build-flags.diff. - Set debhelper compat to 9. - Added debian/source.lintian-overrides Thanks to Moritz Muehlenhoff. (Closes: #655137) * debian/copyright: Copyright years updated. * debian/control: Homepage URL updated. -- Dario Minnucci Tue, 10 Jan 2012 13:55:53 +0100 mon (1.2.0-4) unstable; urgency=low * debian/mon.{postinst,postrm,preinst}: Better handling of 'mon' user creation/deletion. (Closes: #628082) * debian/mon.postinst: Change ownership on /var/log/mon/ to let the daemon to write logfiles. (Closes: #645981) * debian/copyright: - Copyright years updated. - Updated for DEP-5 compatibility. * debian/control: Upgrade debhelper to >=8 * debian/mon.doc: Don't install changelog twice. -- Dario Minnucci Fri, 25 Nov 2011 11:28:26 +0100 mon (1.2.0-3) unstable; urgency=low * debian/control: Bump Standards-Version to 3.9.2 * List of dropped alerts and monitors that will be provided by a new package 'mon-contrib': - 06-add-imap-ssl.monitor.diff - 06-add-ipvs.alert.diff - 06-add-ipvs.monitor.diff - 06-add-smblist.monitor.diff * debian/patches: - Remove from 04-fix-SNMP-module-calls.diff previous patching about SNMP module call on file mon/mon.d/hpnp.monitor. Thanks to Marc F. Clemente (Closes: #613720) * debian/README.Debian: Fix for lintian warning: spelling-error-in-readme-debian -- Dario Minnucci Mon, 11 Jul 2011 11:04:57 +0200 mon (1.2.0-2) unstable; urgency=low * Hosted under git.debian.org (collab-main branch): http://git.debian.org/?p=collab-maint/mon.git * debian/control: - Updated debhelper dependency to (>= 7.0.50~) - Added Vcs-Git and Vcs-Browser fileds - Bump Standards-Version to 3.9.1: - Switch to dpkg-source 3.0 (quilt) format * debian/patches: - Added 01-fix-logging-to-syslog.diff. (Closes:#611751) Thanks to Allan Wind - 04-fix-SNMP-module-calls.diff: Modified to use SNMP module. (Closes:#596292). Thanks to Marc F. Clemente * debian/README.Debian: - Typos fixed * debian/mon.default: Change default state directory to /var/lib/mon to give mon a chance to write state information. (Closes:611772) Thanks to Allan Wind -- Dario Minnucci Sun, 13 Feb 2011 00:53:38 +0100 mon (1.2.0-1) unstable; urgency=low * New upstream release (Closes: #433265) * Maintainer email address updated * debian/mon.default: Added more configuration parameters * debian/control: - Added 'libtime-modules-perl', 'libcrypt-ssleay-perl' to 'Reccomends' needed by 'imap-ssl.monitor' to work. - Long description: Project URL updated - Patch system moved from 'dpatch' to 'quilt' * debian/patches/*: Added DEP3 headers - Reapplied patches: - 00_security_fixes.patch: New version has no fix for #496398 this yet - Deapplied patches: - 01_cfbasedir_fix.patch: Now changes are made via /etc/default/mon file - 03_remove_revision_control_headers.patch: New version is not including previous maintainer's revision control headers anymore. - Modified patches: - 04_fix_SNMP_module_calls.patch: Added fixes on new distributed files: - mon.d/hpnp.monitor - mon.d/snmpdiskspace.monitor - mon.d/snmpvar.monitor - 05_manpage_fixes.patch: Splited into independent manpage fixes: - 05_manpage_fix_mon.8.patch: For mon.8 manpage. - 05_manpage_fix_moncmd.1.patch: For moncmd.1 manpage. - 06_add_scripts_for_ipvs: Splited into: - 06_add_ipvs.alert.patch - 06_add_ipvs.monitor.patch - New patches: - 06_add_imap-ssl.monitor.patch: Adds imap-ssl.monitor. (Closes: #545160) - 06_add_smblist.monitor.patch: Adds smblist.monitor * debian/copyright: Updated to DEP5 format proposal. (see: http://dep.debian.net/deps/dep5/ for details) * debian/mon.init.d: - Change Required-Start to $all to start the daemon the latest possible. - Added $remote_fs dependencies -- Dario Minnucci Thu, 21 Jan 2010 17:15:21 +0100 mon (0.99.2-15) unstable; urgency=medium * debian/mon.init.d: Fixes to start the daemon later on system boot. (Closes: #547556) * debian/control: Removed dependencies on libtime-hires-perl, provided by perl -- Dario Minnucci (midget) Tue, 22 Sep 2009 16:50:11 +0200 mon (0.99.2-14) unstable; urgency=low * debian/control: debhelper compatibility updated to >=7 ${misc:Depends} added to fix debhelper-but-no-misc-depends lintian warning. Standards-Version bumped to 3.8.3: Added debian/README.source file. * debian/rules: deprecated dh_clean -k in favour of dh_prep * debian/mon.dirs: Remove creation dirs: usr/lib/mon/cgi-bin/, var/log/mon and var/run/mon * debian/mon.init.d: Was completely rewritten to be LSB compliant. (Closes: #538133) Added support for ENABLED args: "yes", "true" or "1". (Closes: #522546) Added dynamical control for recreation of /var/run/mon directory. * debian/copyright: Fixed copyright-refers-to-symlink-license * debian/README.Debian: Updated Explanations on how to use local monitors (Closes: #477164) * debian/NEWS.Debian: Removed * Added 'set -e' to: mon.mon.preinst, mon.postinst, mon.prerm, mon.postrm * debian/patches/05_manpage_fixes: Fixes typos in manpages * debian/patches/06_add_scripts_for_ipvs: Add scripts for ipvs support. Thanks to Richard Hartmann. (Closes: #500810) * Do not apply debian/patches/02_enable_monshow_full_mode.dpatch anymore to revert behaviour of 'monshow --full'. (Closes: #422866) * debian/etc/mon/monshowrc: Provides an initial .monshowrc configuration for monshow.cgi * Symbolic links added: monshow.cgi is a symbolic link of /usr/bin/monshow .monshowrc is a symbolic link of /etc/mon/monshowrc -- Dario Minnucci (midget) Thu, 03 Sep 2009 07:29:40 +0200 mon (0.99.2-13) unstable; urgency=low * debian/control: Conforms with latest Standards Version 3.8.0 * debian/control: Added 'Homepage' field * debian/patches/00_security_fixes: (Closes: #496398) -- Dario Minnucci (midget) Wed, 10 Sep 2008 14:19:23 +0200 mon (0.99.2-12) unstable; urgency=low * debian/control: Maintainer's name changed due to GPG signature update. * Changes to run mon as user mon. (Closes: #117550) * debian/mon.default: Added. (Closes: #311352) * Arguments are now managed in the new /etc/default/mon file which solves bug #305108. (Closes: #305108) * debian/mon.init.d: Completely rewritten. * debian/mon.postinst: Completely rewritten. * debian/mon.postinst: Completely rewritten. * debian/mon.preinst: Completely rewritten. * debian/mon.prerm: Completely rewritten. * debian/patches/01_cfbasedir_fix: More harcoded paths fixed. * patches/04_SNMP_module_call_fixes.dpatch: Issued to solve SNMP module issue reported on BTS #432858. (Closes: #432858) - asyncreboot.monitor: SNMP module call updated. - cpqhealth.monitor: SNMP module call updated. - foundry-chassis.monitor: SNMP module call updated. - na_quota.monitor: SNMP module call updated. - netappfree.monitor: SNMP module call updated. - process.monitor: SNMP module call updated. - reboot.monitor: SNMP module call updated. - silkworm.monitor: SNMP module call updated. - xedia-ipsec-tunnel.monitor: SNMP module call updated. -- Dario Minnucci (midget) Mon, 30 Jul 2007 00:56:22 +0200 mon (0.99.2-11) unstable; urgency=low * debian/watch: Rewritten to match upstream version format. * clients/skymon/skymon.1: Added basic manpage for skymon (Closes: #410614) * doc/mon.8: SEE ALSO section updated. * doc/moncmd.1: SEE ALSO section updated. * doc/monshow.1: SEE ALSO section updated. * debian/control: 'Suggests:' upgraded to 'Recommends:' (Closes: #181778). For further information, please read NEWS.Debian file. -- Dario Minnucci Mon, 5 Mar 2007 03:13:44 +0100 mon (0.99.2-10) unstable; urgency=low * New maintainer (Closes: #337944) * mon.d/smblist.monitor: Added Samba monitor contributed by Matthew Astley (Closes: #180872) * debian/control: Added dpatch to Build-Depends: (for dpatch support) * A few patches were issued: - patches/01_cfbasedir_fix: Fixes the configuration base directory. - patches/02_enable_monshow_full_mode: Shows all watches on cgi execution. - patches/03_remove_revision_control_headers: Removes revision control headers from most of the distributed files. (Closes: #322566) NOTE: A few headers used within the code still remains there. You can find remaining revision control headers the following files: - alert.d/file.alert - alert.d/netpage.alert - alert.d/mail.alert - mon - mon.d/http_tpp.monitor - mon.d/smtp3.monitor - mon.d/file_change.monitor * debian/NEWS.Debian file added reporting changes -- Dario Minnucci Sun, 11 Feb 2007 22:38:27 +0100 mon (0.99.2-9) unstable; urgency=low * QA upload. * Set maintainer to QA Group; Orphaned: #337944 * Bump compat level to debhelper 5 * Depend on at least debhelper 5 * Add missing binary-indep target to debian/rules * Update debian/copyright * Add missing lsb section to debian/init * Conforms with latest Standards Version 3.7.2 -- Michael Ablassmeier Thu, 2 Nov 2006 16:25:44 +0100 mon (0.99.2-8) unstable; urgency=low * msql-mysql.monitor: Use $dbh->tables rather than $dbh->func('_ListTables'), thanks to Clement 'nodens' Hermann and Jade Nicoletti (closes: #275347). * http_t.monitor: s/joint/join/, thanks to Bryan Chow (closes: #276553). * smtp.monitor: Support continued quit (221-) messages, thanks to Joe Edmonds (closes: #282104). * smtp3.monitor: Support continued banner (220-) messages, thanks to Brian Grossman (closes: #296943). -- Roderick Schertler Fri, 25 Mar 2005 21:44:00 -0500 mon (0.99.2-7) unstable; urgency=low * Back-port fix for broken host parsing in auth.cf trap section (closes: #251236). * Fix "alertafter

's and replace with
        . Important messages were
        often getting cut off the screen by the use of 
.
        + make $monhost and $monport optional CGI params as 'h' and
        'p' respectively
        + added "test service" and "test-all" to query_group page

mon.cgi v1.48 01-Dec-2000
-------------------------
	+ Have ability to do mass disabling/enabling of hosts and
	services in hostgroup.
	+ query_group: have radio button for enabled/disabled status
	(facilitates mass en/disabling)
	+ query_group: added a table on to show services for that group,
	enabled/disabled with radio button.
	+ query_group: now includes service status on this page
	+ query_group: mass dis/enabling of svcs requires a new function,
	mon_state_change
	+ svc_details: widened the table
	+ main: Command matching changed to use exact matches instead of
	regex matches (duh).
	+ main: fix bug with Revision tag in $VERSION
	+ list_disabled: Also added mass disabling
	+ mon_state_change_enable_only: new function to support
	list_disabled mass re-enabling.
	+ list_pids: cleaned up function and formatting
	+ added mon_state_change function for mass state changing
	+ added mon_list_opstatus function
	+ query_opstatus: moved legend to below main table
	+ query_opstatus: changed legend to use bgcolor instead of font color
	+ query_opstatus: ack message is now included in summary
	+ query_opstatus: increased main table width to 100%
	+ query_opstatus: can now test svcs from this page
	+ ability to do multiple tests at the same time for a single
	hostgroup
	+ moncgi_test_all: new function to test all svcs in group
	+ Ran mon.cgi through 'tidy' (http://www.w3.org/People/Raggett/tidy/)
	for improved HTML compliance. Most common pages are OK now (I think)
	except for table summary attributes. I'll get to them eventually. 
	+ added last_ok time for failed services in "Last Check" column
	+ color of UNCHECKED services is now midnight blue by default,
	unchecked services are now readable in the default color scheme!



mon.cgi v1.46 20-Aug 2000
-------------------------
	+ Fixed bug in list_dtlog that would show min and max failure time
	as "-1" seconds if no failures had been seen on that service. Also
	the table is now not printed at all instead of being a 0-row table.
	+ Made it easier for users to get themselves out of the situation
	where they enter in a valid username and an invalid password.
	+ Made the summary info MUCH easier to see when a service is in
	the failure state.
	+ alert_details is now "svc_details", a much more descriptive name,
	since it shows success as well as failure details.
	+ svc_details [nee alert_details] got a little bit of a cleanup 
	(not much).
	+ list_dtlog now has a configurable maximum number of entries per
	page that it will display, defaults at 100. Large downtime logs 
	would not render well in most browsers, and would not render at
	all with Netscape's table drawing algorithm.
	+ Added optional $monport argument, in case you don't run mon 
	on port 2583.
	+ Trap watches are now correctly handled and printed (thanks
	to Ed Ravin  for the bug report and fix).
	+ Fixed bug in pp_sec that would cause "1 days" to be printed
	out instead of "1 day".


mon.cgi v1.45 05-Jun 2000
-------------------------
	+ query_opstatus: Built an "amber level" alert for services 
	that have failed  but never issued an alert
	+ query_opstatus: Changed "Last Checked" and "Est. Next Check" 
	times to be deltas instead of absolute times, both relative to 
	servertime and not localtime.
	+ Added ACK (and re-ack) feature
	+ query_opstatus: Added additional visual warnings if scheduler 
	is not running or cannot be contacted.
	+ Changed default app secret
	+ Button bar at top of each page is cleaner
	+ Fixed bug with scheduler falsely claiming to be stopped if you try
	to stop the scheduler and aren't authenticated, or if the server is
	not running. 
	+ Fixed bug where multiple auth failures are displayed if a user
	is not authenticated (should only notify once)
	+ Made it easier to not hit "reset server" button accidentally
	+ Made font on ONDS check times size -1
	+ Show the downtime log as an option on query_group
	+ Fixed "test immediately" stuff so it tests and then shows right
	status
	+ list_opstatus: hostgroup column no longer goes white if svc is 
	unchecked
	+ alert_details is MUCH spiffier
	+ alert_details now checks to see if a monitor for that service/group
	is currently running, and as such, the status reported is subject
	to change very soon.
	+ Added more decriptive text to service status table in alert_details
	alert_details.
	+ Changed default return screen on enable_service to be alert_details
	if that's where the user last came from.
	+ Added new 0.38-18 data types for alert_details
	+ list_dtlog: Display median in addition to mean failure time 
	to lessen effects of
	downtime outliers.
	+ Added a Refresh button on alert_details page
	+ Cleaned up the list_disabled function
	+ Got rid of backwards() function, unused relic from old mon.cgi
	+ Fixed the META REFRESH tags so that it works on all browsers (put
	it in the header where it belongs) and handles more cases 
	(alert_details, test_service)
	+ Started using servertime in places instead of time on local web
	server
	+ Visual enhancements for this version submitted by
	Brian Doherty 
	+ Fixed a bug in the "failure-free operation %" calculation if
	you had an extremely large number of failures in a time period, %
	could show up as negative.


mon.cgi v1.38 18-Feb 2000
-------------------------
	+ MAJOR speedup, only use one Mon connection per page view.
	  Pages typically load 2-3x faster.
	+ list_opstatus in Summary mode is now more brief. All "OK, 
	  Non-Disabled Services" (ONDS) for any given hostgroup are
	  now aggregated in a single line.
	  If you monitor a lot of services on each of your host 
	  groups, this will save you a lot of screen real estate.
	  Services which are disabled and/or failing are still broken
	  out individually.
	+ added FAILED flag to Status box , moved DISABLED flag, so
	  mon.cgi works with Lynx & w3m or any other text browser
	  that supports tables (only Lynx and w3m tested, looks great
	  with w3m by the way).
	+ changed default path of cookie to "/" to avoid lynx complaining
	  about "invalid cookie path".
	+ changed alert_details to use a table, include "view downtime log"
	+ on query_group page, turn box gray if host is disabled.
	+ fixed a div0 bug if you have no entries in your dtlog and ask
	  to view it
	+ changed disabled host in query_group to sort alpha even when
	  hosts are disabled.
	+ alert_details function now auto-detects failure/success, doesn't
	  need to be told which one to look for ("test service immediately"
	  would show inconsistent results from this behavior, since it
	  is impossible to know the results of a test before you run it!)


mon.cgi v.1.35
--------------
+ Downtime log viewing/querying support.
+ Disabled services/hosts/watches now appear as gray-colored boxes on
the main display screen. This makes it easier to see what is disabled.
+ Fixed loadstate and savestate bugs again. These commands now work.
+ I finally have sort of a release process, so hopefully my releases
will not be littered with formatting code that is specific to my
environment, and they will run fine out of the box when you get them.
+ Fixed a few routines to work with changing ways Mon::Client asks you
to do things.
+ Also, if you are logged in as an authenticated user (not the
"default user", if one is defined), your username will appear on each
page, so you always know who you are authenticated as.
+ Added a logout button. 
+ Added ability to do "reset keepstate" as well as "reset" from the
web interface.
+ The command bar is now 2 lines instead of one. Even on my 21"
monitor, 13 buttons was too much to have on 1 line (let alone my poor
800x600 laptop LCD!).
+ Mon::Client::test is broken in v0.7. To make it work in the way that
mon.cgi expects it to, change line 1470 in Client.pm v0.7 from:
>     if ($what !~ /^alert|startupalert|upalert$/) {
to
<     if ($what !~ /^monitor|alert|startupalert|upalert$/) {


mon.cgi 1.32.1.2 01-Feb 2000
----------------------------
+ Fixed loadstate and savestate to not be NOOPs.
+ Established a "default" user for when authentication was required but
you don't want to make users log in just to list status.
+ Along with the default user, there is also now a "switch user" feature
that offers the user the chance to re-authenticate to a user of higher
privilege if they are denied the running of a command due to a lack
of authorization.
+ Fixed HTML bugs with hardcoded colors in font and table tags scattered
throughout code (patch courtesy of Martha H Greenberg ,
thanks!). This makes it possible to run mon.cgi in colors other than the
default scheme. mon.cgi users take note however, testing color schemes is
not part of my QA process (such as it is) and so if you find something
broken, let me know and I'll fix it.


etbemon-1.3.6/doc/README.alerts0000644000000000000000000000072010061516616012757 0ustar  $Id: README.alerts,v 1.1.1.1 2004/06/09 05:18:06 trockij Exp $

The following alerts are provided with the distribution:

mail.alert
    Sends an email alert to a list of email addresses. Separate
    addresses with spaces, not commas.

qpage.alert
    Calls QuickPage for one or more pagers. Multiple pagers are
    separated on the command line via spaces.

file.alert
    Logs alerts to a file, which is specified as the first argument on
    the command line.
etbemon-1.3.6/doc/README.cgi-bin0000644000000000000000000000145310230411543012770 0ustar  $Id: README.cgi-bin,v 1.3 2005/04/17 07:42:27 trockij Exp $

mon.cgi
-------
    mon.cgi is the more advanced web interface to mon, maintained by
    Andrew Ryan .

minotaur
--------
    minotaur is maintained by Gilles Lamiral. You may obtain it from
    here:

    http://www.linux-france.org/prj/minotaure/


monshow.cgi
-----------

    monshow can be found in the client/ directory. Put it into your
    cgi-bin directory, rename it monshow.cgi, and it should run via your
    web server's CGI mechanism. Upon startup, this script looks for a
    configuration file named "/etc/mon/monshowrc", or ".monshowrc" in
    the working directory. An example monshowrc is in the etc/ direcory.
    Read the man page for more information.


Jim Trocki
Transmeta Corporation
trockij@arctic.org
etbemon-1.3.6/doc/README.hints0000644000000000000000000000325610061516616012621 0ustar  $Id: README.hints,v 1.1.1.1 2004/06/09 05:18:06 trockij Exp $

To be sure that mon works reliably, you may want to pay attention to the
following hints:

-Keep all alert and mon directories on a local filesystem. When
 the daemon is run, be sure that PATH does not contain remote
 filesystems.

-Do your best to make the mon host maintain independence of all systems
 that it is monitoring. Configurations may vary as different services
 are being monitored. For example, if you need to monitor whether
 DNS is operational, don't depend on DNS being available in the monitor
 script. Use a local hosts table which contains all the hosts referred
 to in the configuration file.

-If you're monitoring a network resource, don't depend on using the network
 to deliver alerts. If you subscribe to a paging service,
 get "Quick Page" or "tpage", and hook a modem and phone line up to
 the host which runs the daemon.

-Be aware of dependencies on services so that you're not surprised
 when one component fails, and then see that three more things fail
 because of this. If you get burnt by this situation, learn from it and
 see what you can do minimize the dependencies.

-Remember the power of "m4" if you want to do more complex things with
 the configuration file.

To be sure that mon works efficiently, respect these rules:

-Monitor programs should parallelize, like fping does. Instead of
 doing a bunch of fork(2)s to send out a lot of pings, it does
 it all from a single process, using nonblocking I/O, like Dan Farmer's
 "fping" from the Satan package.

-If you use hostnames in your hostgroups, consider keeping a local
 /etc/hosts file on the mon server. Monitors can generate lots of DNS
 traffic.
etbemon-1.3.6/doc/README.mon.cgi0000644000000000000000000002704710230411543013021 0ustar  Introduction to mon.cgi
--------------------------------------------------------
This interface, along with mon itself, is available from
ftp://ftp.kernel.org/pub/software/admin/mon/

Development versions of mon.cgi can be found at
http://www.nam-shub.com/files/
--------------------------------------------------------
mon.cgi is a web-based GUI for mon. Its purpose is twofold:
 1) To provide an easy-to-read visual display of all the status items
 that mon keeps track of, and
 2) To provide an easy-to-use web administration interface to allow users to
 perform all mon administration tasks from any web browser.

This package and the documentation assumes that you have at least a
basic familiarity with mon.

-----------------------------------------------------------------
mon.cgi v.1.52
21-May-2001
by Andrew Ryan 

This interface, along with mon itself, is available from
ftp://ftp.kernel.org/pub/software/admin/mon/

Development versions of mon.cgi can be found at
http://www.nam-shub.com/files/
-----------------------------------------------------------------
This is the latest stable version of mon.cgi, meant to be used only
with mon 0.38-21 and above, and a version of Mon::Client that is
0.11 or higher. The chief reason that you will need the new
version is for the "test config" functionality.

This release has 4 new features of note:
1) Access control. Using the 'watch' keyword in the config file, you
   can restrict access to a particular configuration on a
   per-hostgroup basis. 'watch' keywords can be regular
   expressions. Original idea and keyword name stolen from monshow :)

2) 'watch' keywords can either be implemented "softly" -- by default
   only certain hostgroups are shown, but all can be accessed --
   or "strictly" -- only the hostgroups explicitly allowed by 'watch'
   keywords can be accessed in any way. Using strict access control,
   an organization using mon to watch systems belonging to multiple
   customers to be able to segregate those different customers' 
   monitoring completely.

3) There's now a login button. The people have spoken!

4) mon.cgi now checks for the proper version of Mon::Client before
   it starts. This was a major support problem.

Plus many other bug fixes and small improvements, as usual.


This release should be considered stable until proven otherwise :)

Please see the CHANGES file for more information about this release.

Thanks to all who report bugs, submit patches, and give feedback. 
Andrew Ryan 

Installing mon.cgi
------------------
Instructions for installing mon.cgi are located in the header of the
mon.cgi file itself. Roughly speaking, the order of events is:
 1) Install mon and get it working, set up monpasswd and auth.cf
 files and get them verifiably working if you're using mon.cgi
 authentication (hint: you should be!).
 2) Install a web server, preferably Apache, and preferably with
 mod_perl built in. Start the web server and verify that it works.
 3) Put mon.cgi in your cgi-bin directory and make sure it is
 executable by the apache user (make it 0755 or 0555).
 4) Edit your mon.cgi file to change default values to match your
 environment (e.g. contact email, your company logo, your company
 name, etc.). 
 5) If you're requiring users to log in (highly recommended), you must
 change the default app secret variable $app_secret in your copy of
 mon.cgi, and install the Crypt::TripleDES module from CPAN on the
 machine which will be running mon.cgi. 
 6) If you want to easily customize the look and feel of mon.cgi, as
 well as various other configuration options, copy the sample
 mon.cgi.cf file (in the /config directory of this distribution) into
 a location where your webserver can read it, and edit the line
 beginning '$moncgi_config_file = ""' to reflect the path to your
 config file. You can then change the look and feel of mon.cgi, as
 well as implement access controls, directly from this file.


mon.cgi Design Goals
--------------------
1) Provide 100% of the functionality of mon in a graphical user
   interface. Ideally, there will be some things that the GUI is better
   for, and inevitably, some things that the command line will always win
   out for. 

2) Maintain 100% compatibility with mon and Mon::Client. If a patch to
   mon or Mon::Client is required to get a piece of mon.cgi functionality
   working, we write it, submit it, and get it folded in to the main
   distribution before making it official in mon.cgi.

3) Expose mon to the largest number of people possible in the most
   useful way. It is the author's belief that mon is a very useful piece of
   monitoring software, and it is also my belief that the best way to
   insure the growth and support of this software is to expose it to a
   large number of people in your organization in a way that will
   cause them to reach the same conclusion. A web client is the most
   universal way to achieve this goal at the present time, as a web
   client can be run on any network that mon would be.

4) Simplicity and lightness. In other words: Compatibility on a large
   number of client browser sizes, versions, and resolutions; No
   frames! ;  Adhering to as many of the standard good usability
   conventions as possible ; Keeping mon.cgi all one file, with a very
   short setup time ; No special modules required past those needed
   to run mon, and optional additional modules kept to a minimum ;
   100% text browser compatibility ; Performance and speed ; Low
   resource utilization.

Sometimes these design goals work against one another, but hopefully
we come out ahead when tradeoffs are made.



Alternatives to mon.cgi
-----------------------
If you don't like mon.cgi but you would still like a web GUI, you have
2 alternatives. Your first alternative is Jim's monshow, which ships with
mon in the clients/ subdirectory of the mon distribution. The second
alternative is Gilles Lamiral's Minotaure, which can be found at
ftp://ftp.kernel.org/pub/software/admin/mon/contrib/. Both of these
are fully functional and may suit your needs better than mon.cgi. You
are encouraged to take a look at them both and decide which is best
for you.


SITE CUSTOMIZATION
------------------

mon.cgi has always been "customizable," in that the source was
available and you were encouraged to substitute your own parameters
(e.g., mon host, mon port, company logo, etc.). But this meant that 
with each new version, you had to go back and re-edit the source
code. Not a big deal, but still something of a pain.

As of v1.49, mon.cgi includes some features which are meant to
facilitate these changes and make site-specific customizations easier
to perform, especially as mon and mon.cgi continue to evolve.


Creating Your Own Config File
-----------------------------
Previous to v.1.49 of mon.cgi, you could customize the look of the
page, but all customizations had to be done in the source itself. This
has numerous disadvantages, so 1.49 introduces an *optional* config
file which will be read only as necessary and will allow you to
specify custom values for parameters without having to touch the
source code each time. You can still edit the source each time if you
want, but if you want to set up a config file, follow these steps:

1) Copy the config file (included with the mon.cgi distribution)
   config/mon.cgi.cf to a location of your choice. It's best to start
   with a sample config file, because the config file format is very
   simple, and it will give you a chance to see how it works and
   experiment with parameters.

2) Edit the mon.cgi source code to find the line that specifies the
   variable "$moncgi_config_file". Change the value to the filesystem
   path of your copy of your mon.cgi config file.

3) Now you can edit the config file and make changes at will. Every
   time you change the mtime of the file (e.g., by saving it in a text
   editor, or touch'ing the file), mon.cgi will re-read the config
   file and the changes will take effect. If there are errors in
   parsing the config file, they will go to STDERR, which in most
   setups will end up in your web server's error log. Look in the
   errors file if your config isn't working like you expect it to
   work.


Adding A New Row And Custom Commands To The Command Button Bar
--------------------------------------------------------------
Adding a new row to the command button bar, with corresponding custom
commands, is quite a bit more involved than the relatively simple
matter of changing a config file. If you've developed, or are
interested in developing your own custom commands, however, this
functionality might be just what you needed.

In the following example, we add a command called "ack_all" to the
button bar, and also add the routine to do the ack'ing. The actual
guts of the ack_all routine aren't included, but the goal of these
instructions is to give you enough to start off.

The first step is to create your own moncgi_custom_print_bar
function. A stub function exists in the mon.cgi code, and the below
code shows you how you would put in your own function that has one
button, labeled "Acknowledge All Failures".

Sample moncgi_custom_print_bar subroutine:
sub moncgi_custom_print_bar {
    #
    # This is a sample routine, which adds a third row to the
    # command table, with one command: "Acknowledge All Failures"
    #
    my ($face)= (@_);

    $webpage->print("\n");
    $webpage->print("\tAcknowledge
    All Failures\n");
    $webpage->print("\n");
}


The next step is to tell mon.cgi that you are using your own custom
commands, by creating your own moncgi_custom_commands
subroutine. Again, there is a sample function in the mon.cgi code
which you can replace with your own.

Sample moncgi_custom_commands subroutine:
sub moncgi_custom_commands
{
       if ($command eq "ack_all")
       {
	       #
	       # Set up the page
	       #
               &setup_page("Acknowledge All Alarms");
	       #
	       # Note: you would have to write the "ack all"
	       #       command yourself!
               &moncgi_ack_all;
       }
       else
       {
	       #
	       # We didn't find anything, return
	       #
	       return 0;
       }
       return 1; # we did find something, suppress further command processing
}


The last step is to create the actual subroutines which will do the
custom work you want them to do (assuming you weren't just calling
existing commands in a different way. In our example, this means we
have to write a function that actually goes out and acks all existing
failures. We won't do this here, but hopefully this gives you an idea
of how to proceed.

sub moncgi_ack_all {
    #
    # Here is where the actual code to do the "ack all" would go
    #
}

When future releases of mon.cgi come out, you can copy and paste your
custom subroutines and be up and running with the new version in
minimal time. At least, that is what this was designed for.


Credits
-------
The current maintainer is Andrew Ryan . Report
all bugs to him or the mon users mailing list.
+ Originally by: Arthur K. Chan 
+ Based on the Mon program by Jim Trocki . 
  	http://www.kernel.org/software/mon/
+ Rewritten to support Mon::Client, mod_perl, taint mode,
  authentication, the strict pragma, and other visual/functional 
  enhancements by Andrew Ryan .
+ Downtime logging contributed by Martha H Greenberg 
+ Site customization extensions by Ed Ravin 
+ The contributions of members of the mon-users mailing list have been
invaluable in many ways.

etbemon-1.3.6/doc/README.monitors0000644000000000000000000003114213462026746013351 0ustar  $Id: README.monitors,v 1.1.1.1 2004/06/09 05:18:06 trockij Exp $

The following monitors are provided with the distribution, to get
you started. It's simple to add your own monitors. See the man page
for "mon" to learn how.

fping.monitor
-------------
    This pings a list of hosts efficiently using the fping program,
    from the Satan distribution. fping.monitor is just a simple
    shell wrapper for fping, and is normally invoked with just the
    list of hosts to ping. Here's a trick: say you don't want to
    trigger an alert until a machine has unpingable for some number
    of minutes. Give fping.monitor the arguments "-r 3 -t 240000".

    arguments:

    	-a		only report failure if all hosts fail
	-r num		retry "num" times for each host before
			reporting failure
	-t num		set timeout between retries to "num"
			milliseconds
	-s num		consider hosts whose response time exceed
			"num" milliseconds as failures
	-T		for each failed host (no response only),
			traceroute to the system and report the
			output
			

ping.monitor
------------
    Similar to fping.monitor, but uses the system's ping program.
    This serializes the pings, which is normally bad to do. This
    is simply an alternative to fping.monitor, if you can't get
    fping to compile. I've only tested it with Linux and Solaris.

freespace.monitor
-----------------
    This will monitor disk space usage of a particular NFS server.
    Arguments are supplied as "path:kBfree [path:kBfree...]". If
    free space dips below kBfree, then it returns a failure condition,
    and the output is how much space is left on that server.

    If you use this monitor, use separate mounts for the volumes that
    you want to test, mounting them with the "-o ro,intr,soft" options,
    so things don't hang too bad if the server is down.

    You should use the ";;" directive to the monitor line, because
    freespace.monitor doesn't take a list of hosts. Here's an example:

watch nfsservers
        service fping
            interval 5m
            monitor fping.monitor
            period
                alert mail.alert mis-alert@company.com
                alert netpage.alert mis-pager
                alertevery 60m
        service freespace
            interval 10m
            monitor freespace.monitor /server1:5000000 /server2:5000000 ;;
            period
                alert mail.alert mis-alert@company.com
                alert netpage.alert mis-pager
                alertevery 60m


tcp.monitor
-----------
    Useful to see if it's possible to connect to a particular port
    on a particular server. This is over-simplified, and does not yet
    support parsing of the output from these services. Options are
    "-p port" to tell which port to check, and a list of hosts.


http_t.monitor
--------------
    This monitor, contributed by Jon Meek (meekj@pt.cyanamid.com), will
    use HTTP to connect to a server, get a page, and log the transfer
    speed of the transaction. It uses the Time::HiRes Perl module,
    available from CPAN. It can also register a failure if the transfer
    doesn't complete within a certain number of seconds. See the
    source code for an explanation of the arguments.

http_tp.monitor
---------------
    Used to measure and log http file transfer speed and use a proxy.
    See the comments in the source code for instructions.
    Requires Time::HiRes, LWP::UserAgent, and HTTP::Request.

dns.monitor
-----------
    dns.monitor will make several DNS queries to verify that a server is
    providing the correct information for a zone. The zone argument is
    the zone to check. There can be multiple zone arguments. The master
    argument is the master server for the zone.  It will be queried for
    the base information.  Then each server will be queried to verify
    that it has the correct answers.  It is assumed that each server is
    supposed to be authoritative for the zone.

ftp.monitor
-----------
    Connect to an ftp server, wait for an acceptible prompt, and log
    out.

hpnp.monitor
------------
    Uses SNMP to monitor HP JetDirect-equipped printers. Reports
    failures as told by the various objects in HP's MIB, and returns
    the message that is showing on the printer's LCD ("LOW TONER",
    "LOAD LETTER", etc.).

http.monitor
------------
    Connects to an http server, retrieves a URL, and returns true
    if everything is OK.

imap.monitor
------------
    Connects to an IMAP server, checks for a sane response, and
    then logs out.

ldap.monitor
------------
    This script will search an LDAP server for objects that match the
    -filter option, starting at the DN given by the -basedn option. Each
    DN found must contain the attribute given by the -attribute option
    and the attribute's value must match the value given by the -value
    option.  Servers are given on the command line. At least one server
    must be specified.

netappfree.monitor
------------------
    Use SNMP to get free disk space from a Network Appliance
    exits with value of 1 if free space on any host drops below
    the supplied parameter, or exits with the value of 2 if
    there is a "soft" error (SNMP library error, or could not get a
    response from the server).

    This requires the UCD SNMP library and G.S. Marzot's Perl SNMP
    module.

    Supply a configuration file with "--config file" option (see
    etc/netappfree.cf for an example), or "--list" for a listing
    of filesystems which are on your filers. Use --list for help in
    building a configuration file.

nntp.monitor
------------
    Tries to connect to a nntp server, and wait for the right output.

ping.monitor
------------
    Returns a list of hosts which not reachable via ICMP echo. Uses the
    system's default ping, rather than fping.

pop3.monitor
------------
    Connects to a POP3 server, waits for the OK prompt, then logs out.

process.monitor
---------------
    Monitor snmp processes.

    Arguments are:  [-c community] host [host ...]

    This script will exit with value 1 if host:community has
    processErrorFlag set.  The summary output line will be the host names
    that failed and the name of the process.  The detail lines are what
    UCD snmp returns for an ErrorMsg.  ('Too (many|few) (name) running (#
    = x)').  If there is an SNMP error (either a problem with the SNMP
    libraries, or a problem communicating via SNMP with the destination
    host), this script will exit with a warning value of 2.

    There probably should be a better way to specify a given process to
    watch instead of everything-ucd-snmp-is-watching.

reboot.monitor
--------------
    Polls the SNMP agent on hosts, and triggers a failure when a reboot
    is detected.

smtp.monitor
------------
    Connects to an SMTP server, waits for a prompt, and then logs out.

telnet.monitor
--------------
    Use tcp_scan to try to connect to the telnet port on a bunch of hosts,
    and look for a "login" prompt.

msql-mysql.monitor, rpc.monitor
-------------------------------
    See the separate README for these monitors.

readdir.monitor
---------------
    From: gilles LamiraL 
    To: "mon@linux.kernel.org" 
    Subject: readdir monitor

    Hello,

    I wrote a monitor that reads several directories and tells
    if the number of files in each directory exceeds a given number.
    Possible uses are testing /var/spool/mqueue or /var/spool/lp/
    It is a local monitor. No SNMP here. I think it can be easyly
    called from an SNMP agent.

    1) The allowed number can be specified for each directory.

    2) You can add a regex filter to match the file names.
       Only one regex is allowed for all directories.
       Tell me if you want one for directory.

    3) The return status is interesting. It gives the exceeded values 
       in a log based 2 way.

    For example: 
    You want to check if /var/spool/mqueue contains less than 100 messages

    $ ls /var/spool/mqueue | wc -l
    479
    $ ./my-readdir.monitor /var/spool/mqueue:100
    /var/spool/mqueue:479
    $ echo $?
    3

      1 means more than 100 messages
      2 means more than 200 messages
      3 means more than 400 messages
      4 means more than 800 messages

    ...
    255 means more than 5.79 * 10^76 messages (579 + 74 zeros !)
       
    Nice ?
    See more example in the script itself.


up_rtt.monitor
--------------
    mon monitor to check for circuit up and measure RTT.
    Jon Meek - 09-May-1998.  Requires Perl Modules "Time::HiRes" and
    "Statistics::Descriptive".


dialin.monitor
--------------
    Dials in to a modem and fails if a carrier and a prompt is not
    detected.  Useful for telling if your modem pool is down or if some
    spaz modem has quit answering the phone.

    dialin.monitor requires the Perl Expect module, available from
    CPAN.

    This program performs UUCP-style locking, and needs to run setgid
    uucp to accomplish this. Provided is dialin.monitor.wrap.c, a simple
    little C program which is installed as setgid uucp and directly
    executes the actual dialin.monitor Perl script. This is required
    because some systems (e.g. Linux) do not allow setuid/setgid scripts.

    To build, edit the Makefile in mon.d, and adjust monpath to your
    environment. The do:

    make && make install

    dialin.monitor accepts several arguments. The only required argument
    is "-n", which specifies the phone number to dial.

    -n number	dial in to "number"
    -t secs	timeout to wait for "CONNECT" from modem (60)
    -l lockdir	directory to use for UUCP-style locking ("/var/lock")
    -D device	serial device to use ("/dev/modem")


foundry-chassis.monitor
-----------------------
    Reports the power supply and fan status of Foundry chassis-based
    switches, like the BigIron and the FastIron. This uses the
    "FOUNDRY-SN-AGENT-MIB" and "FOUNDRY-SN-ROOT-MIB". Foundry annoyingly
    ships their MIBs in one giant file. What I do is separate them into
    distinct files so that the UCD tools don't need to parse the single
    giant file.

    I've tested this with staged failures of PSUs and it works fine.
    It actually caught an actual non-staged failure once.

    Arguments are:

    -c community     SNMP community to use


silkworm.monitor
---------------
    Reports port, fan, power supply, and temperature failures in Brocade
    SilkWorm FCAL switches. It requires Brocade's "SW-MIB" MIB.

    Sensor failures are explicitly reported by the agent, read by this
    monitor, and reported to mon. This monitor identifies port problems
    by paying attention to only those ports whose administrative status is
    "online", yet the actual operational status is not "online".

    This monitor has not yet been tested in the case of an actual (or
    staged) failure. That doesn't mean it doesn't work--it's just that
    it hasn't been tested :)

    Arguments are:

    -c community     SNMP community to use


cpqhealth.monitor
-----------------
    Report fan, PSU, and temperature failures from systems running the
    Compaq "Insight Manager". It requires the "CPQHLTH-MIB" MIB,
    and the UCD SNMP libs w/the Perl module.
    
    We've had this running for a little while now, and both tested it with
    "staged" failures and actual failures, and it seems to work rather
    well. The Insight agent is a bit quirky, though. I've seen where
    it reports that both PSUs are installed, running without error,
    yet it says it is not in a redundant configuration.

    Arguments are:

    -c community     SNMP community to use


mon.monitor
-----------
    Report the running status of a mon server.

    Arguments are:

    -p port		port to use, defaults to 2583
    -t timeout		timeout in seconds, defaults to 30
    -u username		username (optional)
    -p password		password (optional)


traceroute.monitor
------------------
	Monitor routes from monitor machine to a remote system
	using traceroute. Alarm and log when changes are detected.
	See embedded POD documentation for details.


smtp3.monitor
-------------
	smtp monior which performs logging of connect times.
	See embedded POD documentation for details.


http_tpp.monitor
---------------
	Parallel query http server monitor for mon. Logs timing
	and size results, can use a proxy server, and can
	incorporate a "Smart Alarm" function via a user supplied
	Perl module.  See embedded POD documentation for details.


file_change.monitor
-------------------
	file_change.monitor will watch specified files in a
	directory and trigger an alert when any monitored file
	changes, or is missing. File changes can optionally be
	logged using RCS.
	See embedded POD documentation for details.


na_quota.monitor
----------------
	report quota limits on network appliance filers.  see the comments
	in the file for details.
etbemon-1.3.6/doc/README.msql-mysql.monitor0000644000000000000000000000266610061516616015305 0ustar  mysql-mysql.monitor README
==========================

See the monitor script itself for most of the pertinent usage information.

This is msql-mysql.monitor, a monitor for mon that tries to intelligently
check if an mSQL or MySQL SQL server is operational.

This monitor required the perl5 modules DBI, DBD::mysql, and DBD::mSQL,
available from CPAN (http://www.cpan.org/).

The monitor may be installed as msql.monitor, in which case it defaults to
mSQL mode, or as mysql.monitor, in which case it defaults to MySQL mode. 
Regardless of how it is installed, the --mode switch may be used to force
the monitor into msql or mysql mode.

In order for the monitor to succeed, the following must be true:

- For either mode, the server must be up and answering.
- For mSQL mode, the server ACLs must allow connections from the host running
  mon as the effective user running mon to the given database.
- For MySQL mode, the server grant tables must allow connections from the host
  running mon with the username and password provided to the given database.
- For either mode, the database specified must exist, and must contain at
  least one table

If any of these conditions are not met, the monitor will fail and the DBI
error will be returned to mon for processing by the appropriate alerts.

-- 
j.

James FitzGibbon                                                james@ican.net
System Engineer, ACC Global Net                   Voice/Fax (416)207-7171/7610
etbemon-1.3.6/doc/README.paging0000644000000000000000000000375310061516616012743 0ustar  $Id: README.paging,v 1.1.1.1 2004/06/09 05:18:06 trockij Exp $

SO YOU WANT MON TO PAGE YOU??
-----------------------------

SOFTWARE

It's not the job of mon to page you, but it *does* have the
responsibility of triggering an alert program, which can page
you.

Paging via modem is probably the best way to handle notification,
since phone systems usually fail much less than local (and wide)
area networks. Think of it as "out-of-band" notification.

QuickPage
    mon ships with a wrapper for QuickPage, which uses a modem
    to send an alphanumeric page via the IXO/TAP/SNPP (what is
    it today???) protocol. QuickPage is very simple to configure,
    supports groups, runs on a number of platforms, and is free.

    The latest version of QuickPage can be found at
    ftp.it.mtu.edu:/pub/QuickPage.

Tpage
    Originally maintained by Tom Limoncelli (of INN FAQ fame),
    tpage was one of the earliest paging progmrams. It doesn't
    seem to be very well maintained recently, but it's worth
    having a look at. It supports multiple users and an "on call"
    schedule (which mon can already do), but its probably
    worth looking at anyway. It's mostly written in Perl.

    The last time I looked (Tue Sep 16 09:49:18 PDT 1997),
    I was not able to locate tpage-2.40.tar.gz :(

    Have a look at the IXO FAQ for more information, supposedly
    available from ftp://ftp.airnote.net/pub/paging-info/ixo.faq


EMAIL PAGING

If your paging company allows you to send pages via electronic
mail, you can use the "netpage.alert" script that comes with
mon. It just calls sendmail and fires off email to one or more
addresses with a specially formatted subject line that should
give maximum information in your pager's tiny alpha LCD.

To format a page nicely on a tiny LCD, you may have to play with end
of line characters. For example, pagenet pagers seem to ignore any EOL
sequences other than just a plain \r

A reminder--you might not want to rely on the network to send
you a message if the network is down :)
etbemon-1.3.6/doc/README.protocol0000644000000000000000000000755210273202056013333 0ustar  $Id: README.protocol,v 1.2 2005/07/31 17:02:38 vitroth Exp $

MON PROTOCOL
------------

The client/server protocol for mon works like this:

The server listens on TCP port 2583, which has been assigned by IANA.

In the following, a "line" is a sequence of ASCII text, terminated with
a newline (0A in hexadecimal).

A request submitted by the client is a single line.  Only one request
per line is permitted. Any number of requests per session is permitted.
The client indicates the end of requests by sending a "quit" request.

The reply to a request is zero or more lines lines.  The end of the
reply is terminated with a positive or negative acknowledgement line.
The positive acks match this regular expression:

^2[0-9][0-9] .*$

Negative acks match this expression:

^5[0-9][0-9] .*$

Characters trailing the leading integer are a comment which summarizes
the success or failure.

The actual value of the leading integer is not meaningful except to
indicate success (200-299) or failure (500-599).

An example session follows:

(client connects to port 2583)
Client: list state
Server: scheduler running
Server: 220 list state completed
Client: list xyzzy
Server: 520 unknown list command
Client: list watch
Server: group1 service1
Server: group1 service2
Server: group2 service1
Server: 220 list watch completed
Client: quit
Server: 220 quitting
(server and client terminate tcp session)

If no requests are received from the client in a given amount of time
(configurable on the server), then the server will timeout the connection
and hang up on it.

The following are the valid requests and replies implemented in
mon-0.99.2, as defined in the "client_command" routine. A command is
indicated by the word itself, required arguments are surrounded by {},
and optional arguments are surrounded by []. Case is not significant
for the commands themselves, but may be significant for their arguments.

quit
    Terminate connection with server. The server sends a "220" response then
    terminates the TCP session.

protid {version}
    Report whether or not the protocol version matches the server's protocol
    version. Returns 520 nack on failure, or 220 ack on success. As far as I
    know, nothing uses this command.

login {user} {pass}
    Attempts to log in the "user" with password "pass".  This is required if
    user authentication is specified in the server's auth.cf file.

reset [stopped] [keepstate]
    Aborts all currently running monitors, re-reads the server's configuration
    file, and reinitializes the state of all monitoring.  If "stopped" is
    specified, stops the scheduler before the reload. If "keepstate" is
    specified, then the state of the disabled list is reinstated after the
    reset.

reload auth
    Reloads the auth.cf file.

clear timers {group} {service}
    Resets all timers associated with a service. This includes the interval
    counter, traptimeout, trapduration, last alert, consecutive failures, and
    alertafterival.

test monitor {group} {service}

test alert {group} {service} {retval} {period}

test startupalert {group} {service} {retval} {period}

test upalert {group} {service} {retval} {period}

test config

version

loadstate disabled

savestate disabled

savestate opstatus

term

stop

start

set maxkeep {num}

set {group} {service} {variable} {value}

setview {view}

getview

get maxkeep

get {group} {service} {variable}

list descriptions

list group {group}

list opstatus

list opstatus {group,service} [group,service ...]

list disabled

list alerthist

list failures

list failurehist

list successes

list warnings

list pids

list watch

list state

list aliases

list aliasgroups

list deps

list dtlog

list views

ack {group} {service} {comment}

disable watch {group}

disable service {group} {service}

disable host {host [host ...]}

enable watch {group}

enable service {group} {service}

enable host {host [host ...]}

servertime

checkauth {cmd}

etbemon-1.3.6/doc/README.rpc.monitor0000644000000000000000000000307110061516616013741 0ustar  $Id: README.rpc.monitor,v 1.1.1.1 2004/06/09 05:18:06 trockij Exp $

README for rpc.monitor
-----------------------

This program is a monitor for RPC-based services such as the NFS
protocol, NIS, and anything else that is based on the RPC protocol.
Some general examples of RPC failures that this program can detect
are:

  - missing and malfunctioning RPC daemons (such as mountd and nfsd)
  - systems that are mostly down (responding to ping and maybe
    accepting TCP connections, but not much else is working)
  - systems that are extremely overloaded (and start timing out simple
    RPC requests)

To test services, the monitor queries the portmapper for a listing of
RPC programs and then optionally tests programs using the RPC null
procedure.

At Transmeta, we use:

  "rpc.monitor -a" to monitor Network Appliance filers
  "rpc.monitor -r mountd -r nfs" to monitor Linux and Sun systems

Some notes:

  - The "-a" option only tests registered RPC programs, if you want to
    test specific RPC programs, use "-r" options along with "-a".
  - The "-a" option may not be feasible for use on many Unix systems.
    Some provide more services than you want to test, include RPC
    programs that don't provide the RPC null procedure, reject calls
    from unprivileged ports, or have other problems.
  - If you get an unexpected "unknown RPC program" error, you may
    want to check the rpc line in /etc/nsswitch.conf.

Let me know if you have any comments, improvements, or suggestions.

-- 
Daniel Quinlan (at work)
quinlan@transmeta.com           http://www.pathname.com/~quinlan/
etbemon-1.3.6/doc/README.snmpdiskspace.monitor0000755000000000000000000001111410616216722016022 0ustar  # NAME
#  snmpdiskspace.monitor
#
#
# SYNOPSIS
#  snmpdiskspace.monitor [--list] [--timeout seconds] [--config filename]
#                        [--community string] [--free minfree] 
#                        [--retries retries] [--usemib ] host...
#
#
# DESCRIPTION
#  This script uses the Host Resources MIB (RFC1514), and optionally
#  the MS Windows NT Performance MIB, or UCD-SNMP extensions
#  (enterprises.ucdavis.dskTable.dskEntry) to monitor diskspace on hosts
#  via SNMP.
#
#  snmpdiskspace.monitor uses a config file to allow the specification of
#  minimum free space on a per-host and per-partition basis. The config 
#  file allows the use of regular expressions, so it is quite flexible in
#  what it can allow. See the sample config file for more details and
#  syntax.
#
#  The script only checks disks marked as "FixedDisks" by the Host MIB,
#  which should help cut down on the number of CD-ROM drives 
#  erroneously reported as being full! Since the drive classification
#  portion of the UCD Host MIB isn't too great on many OS'es, though,
#  this won't buy you a lot. Empire's SNMP agent gets this right on
#  all the hosts that I checked, though. Not sure about the MS MIB.
#  UCD-SNMP only checks specific partition types (md, hd, sd, ida)
# 
#  snmpdiskspace.monitor is intended for use as a monitor for the mon
#  network monitoring package.
#
#
# OPTIONS
#  --community   The SNMP community string to use. Default is "public".
#  --config      The config file to use. Default is either 
#                /etc/mon/snmpdiskspace.cf or 
#                /usr/lib/mon/mon.d/snmpdiskspace.cf, in that order.
#  --retries     The number of retries to use, if we get an SNMP timeout.
#                Default is retry 5 times.
#  --timeout     Seconds to wait before declaring a timeout on an SNMP get.
#                Default is 20 seconds.
#  --free        The default minimum free space, in a percentage or absolute
#                quantity, as per the config file. Thus, arguments of, for
#                example, "20%", "1gb", "50mb" are all valid.
#                Default is 5% free on every partition checked.
#
#  --ifree       The default minimum free inode percentage, specified as
#                a percentage.  Default is 5% free.
#
#  --list        Give a verbose listing of all partitions checked on all 
#                specified hosts.
#
#  --listall     like --list, but also lists the thresholds defined for
#                each filesystem, so you can doublecheck the config file
#
#  --usemib      Choose which MIB to use: one or more of host, perf, ucd
#                Default tries all three, in that order
#
#  --debug       enable debug output for config file parsing and MIB fetching
#
#
# EXIT STATUS
#  Exit status is as follows:
#    0     No problems detected.
#    1     Free space on any host was below the supplied parameter.
#    2     A "soft" error occurred, either a SNMP library error, 
#          or could not get a response from the server. 
#
#  In the case where both a soft error and a freespace violation are
#  detected, exit status is 1.
#
# BUGS
# When using the net-snmp agent, you must build it with "--with-dummy-values"
# or the monitor may not parse the Host Resources MIB properly.
#
# List of local filesystem types used when parsing the UCD MIB should be
# configurable.
#
#
# NOTES
# $Id: README.snmpdiskspace.monitor,v 1.1.2.1 2007/05/02 23:25:06 trockij Exp $
#
#  * Added support for inode status via UCD-SNMP MIB.  Fourth column in config
#  file (optional) is for inode%.
#  * added --debug and --usemib options.  Latter needed so you can force use
#  of UCD mib if you want inode status.
#  * rearranged the error messages to be more Mon-like (hostname first)
#  * added code to synchronize instance numbers when using UCD MIB.  This
#  could solve the "sparse MIB" problem usually fixed by the
#  --with-dummy-values option in net-snmp if needed for other agents
#  Ed Ravin (eravin@panix.com), January 2005
#
#  Added support for regex hostnames and partition names in the config file,
#  'use strict' by andrew ryan .
#
#  Generalised to handle multible mibs by jens persson 
#  Changes Copyright (C) 2000, jens persson
#
#  Modified for use with UCD-SNMP by Johannes Walch for 
#  NWE GmbH (j.walch@nwe.de)
#
#  Support for UCD's disk MIB added by Matt Simonsen 
#
#
# SEE ALSO
#  mon: http://www.kernel.org/software/mon/
#
#  This requires the UCD SNMP library and G.S. Marzot's Perl SNMP
#  module. (http://ucd-snmp.ucdavis.edu and CPAN, respectively).
#
#  The Empire SystemEdge SNMP agent: http://www.empire.com
etbemon-1.3.6/doc/README.snmpvar.monitor0000644000000000000000000002425510146140376014652 0ustar                               snmpvar.monitor               by P.Holzleitner

What does it do?

    snmpvar.monitor is a plug-in for the "mon" systems monitoring package
    written by Jim Trockij (http://www.kernel.org/software/mon).
    
    Called by mon, it queries freely configurable values using SNMP,
    compares them against specified limits and reports any violation.

    Some parameters that can be monitored (just to give you an idea):

      Equipment operational status (temperature, fan rotation)
      UPS Status (line power / battery, minimum line voltage, load % ...)
      Switch/Router status (interface up, BGP session up, ...)
      Server status (redundant power supply OK, disk array OK, ...)
      Status of services (process running, mail queue length, ...)
      
      
License

  GNU GPLv2 (http://www.fsf.org/licenses/gpl.txt) - See file COPYING

  
Quick Start:

    * Make sure you have UCD SNMP 3.6.2+ (libraries) and the Perl SNMP
      module installed (http://www.cpan.org/misc/cpan-faq.html)
    * Copy snmpvar.mon to your mon.d directory
    * Copy snmpvar.def to /etc/mon, add your own variables
    * Copy snmpvar.cf to /etc/mon and edit to match your needs
    * Test from mon.d directory with ./snmpvar.monitor -l host1 host2 ...
    * Test again from mon.d directory with ./snmpvar.monitor host1 host2 ...
    * Add watch/service to mon.cf, using snmpvar.monitor


Commandline options:

    --varconf=/path/to/snmpvar.def if neither /etc/mon nor /usr/lib/mon/etc
    --config=/path/to/snmpvar.cf if neither /etc/mon nor /usr/lib/mon/etc
    --community=your_SNMP_read_community if not 'public'

    --groups=Power,Disks  test only a subset of variables for a host group

    --timeout=n		SNMP GET timeout in seconds
    --retries=n		number of times to retry the SNMP GET
    --debug		tell what config is being useed
    --mibs='mib1:mib2:mibn'	load specified MIBs
    --list[=linesperpage]]	produce human-readable listing, not alarms

   For every host name passed on the command line, snmpval.monitor looks
   up the list of variables and corresponding limits in the configuration
   file (snmpmon.cf).

   If a --groups option is present, only those variables are checked
   which are in one of the specified groups.  To specify more than one
   group, separate group names with commas.  You can also exclude groups
   by prefixing the group name(s) with '-'.  Don't mix in- and exclusion.
   Examples:
      --groups=Power        only vars in the Power group
      --groups=Power,Env    vars in the Power or Env group
      --groups=-Power,-Env  all vars except those in Power or Env groups
      --groups=Power,-Env   won't work (only the exclusions)

   For every such variable, it looks up the OID, description etc. from
   the variable definition file (snmpvar.def).

   This monitor looks for configuration files in the current directory,
   in /etc/mon and /usr/lib/mon/etc.  Command line option --varconf 
   overrides the location of the variable definition file, option
   --config sets the configuration file name.

   When invoked with the --list option, the output format is changed
   into a more human-readable form used to check and troubleshoot the
   configuration.  This option must not be used from within MON.


Exit values:
   0  if everything is OK
   1  if any observed value is outside the specified interval
   2  in case of an SNMP error (e.g. no response from host)


Basic Troubleshooting:

    use snmpvar.monitor --list option to see variable values
    use snmpwalk your_hostname public .1 | less to verify SNMP agent


The snmpvar.def File:

    In this file we define variables that can be retrieved via SNMP.
    In a way, the .def file is snmpvar.monitor's idea of a MIB.
    
    Entries consist of a "Variable variable-name" declaration

      Variable PE4300_TEMP_MB

    [NOTE: The variable name cannot be "Host" or "FriendlyName"]
    followed by the mandatory specification of Object ID and Description:    
    
      OID            .1.3.6.1.4.1.674.10891.300.1.5.2.2.1.3
      Description    Motherboard Temperature
      
    It is suggested that OIDs be entered numerically as shown above 
    in order to eliminate the need for having the SNMP libraries compile
    the relevant MIB files on every invocation of the monitor.
    By default, this monitor loads no MIBs.  If you want to use symbolic
    OIDs, use the --mibs commandline option to specify which MIBs you need.
    
    By the author's convention, an OID describing an array of values, like
    ifOperStat which takes the interface number as an index, is written
    with a trailing dot, while OIDs of scalars end in a number.  As of 
    version 1.1.1, the monitor will insert the dot before the index if you
    forgot it in the .def file.
    
   
    Optional Elements of a Variable definition:
      
      DefaultIndex   3 4 5
      
    A list of indices to test by default.  Let's say the OID is .1.2.3. and
    DefaultIndex is "18 22 36", then the monitor will retrieve the values of
    .1.2.3.18, .1.2.3.22 and .1.2.3.36 when testing this variable, and will
    compare them all against the limits.  Where necessary, the DefaultIndex
    can be overridden for one host/variable combination, using the Index
    statement in the .cf file.

      FriendlyName	3	Disk Fan 1
      
    This lets you replace the standard display of "Variable [Index]",
    e.g. "Fan Speed [5]", with individual labels for each index.
    The FriendlyName option is typically specified in the .def file for
    items that have the same name for every use, e.g. component names like
    in the case of fans, power supplies etc.  The same option exists in
    the .cf file to name a particular variable on a particular host, e.g.
    to display a line name instead of an interface number on a router.
    If the FriendlyName string begins with "@", the Description is
    substituted for the "@".

      Scale          / 10.0
    
    A formula to re-scale the value returned from the host.
    The expression is appended to the raw value and the resulting expression
    is evaluated by Perl.  The raw value is available as $rawval if necessary.
      
      Unit           C

    Used in value display / messages,
    
      Decode	 1	unknown
      Decode	 2	OK
      Decode	 3	FAILURE

    Values retrieved through SNMP are often enumerations of status codes.
    The Decode statement lets you put text labels on these values.

      DefaultGroup	Environment
      
    Defines that all, by default, instances of this variable go into the
    specified group.  Individual overrides possible in .cf file.


      DefaultMin  300
      DefaultMax 2000
      DefaultEQ  1000
      DefaultNEQ 1000
      
    Default alarm limits.  See description of Min/Max/EQ/NEQ below.
      

The snmpvar.cf File:

    In here, you "call up" the variables to be retrieved for a particular
    host.

    Entries consist of a "Host host-name" declaration followed by at least
    one "variable-name [options ...]" line.
    
      Host ntserv1
    
    This hostname corresponds to the hostname on the command line, i.e. the
    hostname you used in MON's hostgroup statement.
    
      FOO_FAN_RPM   Min 1000  Max 5000  MaxValid 10000  Index 1 2 3 4
      
    This example uses almost all options.  It instructs the monitor to
    retrieve the OID specified under "FOO_FAN_RPM" in the .def file.
    
      Min  300		specifies a minimum value, measured >= minimum
      Max 2000		specifies a maximum value, measured <= maximum
      EQ  1000		specifies a exact value, measured == maximum
      NEQ 1000		specifies a exact value, measured != maximum
      
    If the measured value is outside of these limits, a failure is reported.
    To test for "Value = X", use "Min X  Max X".
      
      MinValid -1
      MaxValid 10000
      
    Some monitoring hardware occasionally measures garbage.  To avoid
    triggering an alarm when this happens, you can use MinValid/MaxValid
    to specify the range (inclusive) of plausible values for this variable.
    If the measured value exceeds these limits, only a warning will be
    generated, but no failure will be reported to MON.

      Group Environment
      
    Puts this particular variable into the specified group.
    Groups are used to test a partial set of the variables specified for
    a host, by using the --groups= command line option.

      Index 1 2 3
      
    This tells the monitor which object instances (array elements) to test
    in case of a non-scalar object.  Since the list of indices can be as
    long as necessary, the Index option must be the last one on the line
    (after Min X, Max Y etc.)
    The list specified as DefaultIndex in the .def file entry for this
    variable is used unless  Index is pecified here.

    When retrieving a non-scalar value, the snmpvar.monitor will normally
    display the instances (array elements) by appending their index to the
    description, as in "Line Status [3]".
    
    Often, it is desirable to label individual instances in a more
    mnemonic way.  To do this, you can add a number of FriendlyName
    directives after a variable request, like this:
    
      Host firewall
        IF_OPERSTAT		Index 1 2 3
	    FriendlyName	1	 1: Leased Line
	    FriendlyName	2	 2: DMZ
	    FriendlyName	3	 3: Internal Router
	    
    In this case, the monitor checks the ifOperStat for interfaces 1, 2,
    and 3 on host "firewall".  If interface 3 were not "up", the monitor
    would signal a failure of "Internal Router" instead of "ifOperStat [3]".
    If the FriendlyName string begins with "@", the Description is
    substituted for the "@".
    If all instances of this variable having the same index have the same
    meaning regardless of what host they are on, you can put the FriendlyName
    statement into te respective variable definition in the .def file
    instead. 


The snmpopt.cf File:

    This optional file is used to pass parameters to the SNMP library.
    
    For SNMPv1, this is generally not necessary unless the target's 
    SNMP port differs from the default (161).

    Note that SNMPv1 community string, timeout and retries can also be
    specified on the snmpvar.monitor command line, overriding whatever
    default or configuration file setting.
    
    You will need to edit this file in order to use SNMPv3.
    

etbemon-1.3.6/doc/README.software0000644000000000000000000000110310061516616013313 0ustar  $Id: README.software,v 1.1.1.1 2004/06/09 05:18:06 trockij Exp $

Here is some good software to have when building monitors and
alerts for mon:

QuickPage v3.2
ftp.it.mtu.edu:/pub/QuickPage
Software to send a page via modem and the IXO protocol.  It's very simple
to set up.

Satan 1.1.1
ftp://coast.cs.purdue.edu/pub/tools/unix/satan/
The Satan network security scanner has a number of utilites which 
are useful when adapted to mon.

sock
http://www.kohala.com/~rstevens/tcpipiv1.tar.Z
A utility written by Richard Stevens which allows manipulation
of TCP and UDP connections.
etbemon-1.3.6/doc/README.syslog.monitor0000644000000000000000000000457710146140376014511 0ustar  Readme file for syslog.monitor
$Id: README.syslog.monitor,v 1.2 2004/11/15 14:45:18 vitroth Exp $

(Note: This Readme file is an insult to the reader. Better documentation
 will come as soon as I find more time and fix some more bugs)

INTRODUCTION

This is a syslog for mon (http://www.kernel.org/software/mon/) by Jim
Trocki.

It is different from the other monitors, because it is constantly running
and communicates with the mon server via Mon::Client over the network,
instead of running under mon's supervision.

It listens for syslog packets comeing in from the network, parse them,
checks them against a rule set and reports to the mon server if necessary.

REQUIREMENTS

You need to have the following non-std Perl modules installed:

     Time::HiRes
	 Mon::Client

DETAILS

syslog.monitor accepts a single command line parameter, the name of the
configuration file. All options are explained inside the configuration file,
see syslog.conf as an example.

At startup, the daemon retrieves a list of all watches from the mon server
for which a service "syslog" is defined. We also read the hostgroup
definition for this watch from the mon server. (The hostnames are resolved
and the result is used to check if the incoming syslog packet is accepted
and which host it came from, so you should make sure your hostnames resolve
to all IPs from which your systems might send a syslog packet - on a Cisco,
you might want to consider "logging source-interface")

This basically amounts to:

  For every hostgroup you want syslog.monitor to accept and monitor syslog
  packets, define a syslog service.

This watch/service is where we later send our traps.

For those hosts, add a line like

*.*         @syslog.monitor.host.name

to /etc/syslog.conf.

Configure syslog.monitor by editing syslog.conf and following the comments
therein.

Start syslog.monitor.

Restart mon.

killall -HUP syslogd on the hosts you want to monitor.

Read the logfiles and fix the problems. ;-)


AUTHOR

Please don't bother Jim with questions relating to this.

If this should lead to global warming, code freeze or Elvis's revival, I
accept absolutely no responsibility. However, I will gladly receive and
incoporate bugfixes and sensible bug reports.

Lars Marowsky-Bre 

URL

It appears we have made our way to
ftp://ftp.kernel.org/pub/software/mon/contrib/ - please use a mirror, as
described on http://www.kernel.org/.
etbemon-1.3.6/doc/README.traps0000644000000000000000000000652213455576506012642 0ustar  The protocol for agents (remote or local monitor scripts)
to deliver failures to the mon server:

Trap consists of tag/value pairs which are separated by newlines. The
first tag must be "pro", which is the protocol version.

Tags which are understood are:

#
# MON-specific tags
# pro   protocol
# aut   auth
# typ   type (0=mon, 1=snmpv1)
# spc   specific type (TRAP_*)
# seq   sequence
# grp   group
# svc   service
# hst   host
# sta   status (opstatus)
# tsp   timestamp as time(2) value
# sum   summary output
# dtl   detail (terminated by \n.\n)
#
# SNMP-specific tags
# ent   enterprise OID
# agt   agent address
# gtp   generic trap type
# stp   enterprise-specific trap type
# tmp   sysUptime timestamp
# vbl   varbindlist (OID = value)
#

SNMP-specific tags do nothing at this time.

Rather than formulating the trap PDU yourself, it's a good idea to use
Mon::Client::send_trap. See the POD for Mon::Client for more details,
or see remote.alert for an example.

If an alert for a watch or service is delivered to a mon server and
its configuration does not include that watch or service, it will use
the default watch/service "default" to deliver the alert. If "default"
is not defined in the mon.cf, the alert will be logged and then discarded.

NOTE: alert/upalert stats are not handled specially for 'default' traps,
so if one unknown alert trap comes in, followed by a unknown upalert
from a different host, then the alert output from mon may be confusing.
Set up a default watch, and use it as a debugging guide to catch random
trap and remind you to update your mon config file.

watch default
    service default
	traptimeout 10m
	trapduration 60m
	period wd {Sun-Sat}
	    alert some.alert
	    upalert some.alert -u

See the mon.1 man page for the list of environment variables availble to
monitor and alert programs. One particular environmet variable to note is
the MON_TRAPINTEND variable. This is a colon (:) separated watch
group / service pair which was the intended recipient when a default watch
group and service were invoked for a trap.  This hopefully gives you
some ability to figure out what to do with a trap caught by "default",
and could be exploited to allow a lazy administrator to send useful
information from alerts ;)

There is a (very simple) alert script called "remote.alert" which
delivers a failure detected locally to a remote mon process. This
allows centralization of alert handling, and it allows distributed
mon processes. Pass the mon host name via -H  and the port via
-P .

you could use remote.alert to send a trap from one mon server to another
mon server. this can be useful for implementing a hierarchy of mon
servers, where the topmost level serves as the alert management node
for the lower leaf nodes. for example:

mon server "highlevel":

watch pr-internet
    service http_tp
        period wd {Sun-Sat}
            alert mail.alert name@address.com


mon server "lowlevel":

watch pr-internet
    service http_tp
	monitor http_tp.monitor
	interval 5m
	period wd {Sun-Sat}
	    alert remote.alert -H highlevel


when the pr-internet/http_tp service fails on the mon server "lowlevel",
it will send a trap to the mon server "highlevel", which will then send
the email alert.

For a manual test run:
echo test | MON_GROUP=localhost MON_SERVICE=trap MON_RETVAL=1 OPSTATUS=c /usr/lib/mon/alert.d/trap.alert -U $USERNAME -P $PASS localhost
etbemon-1.3.6/doc/README.variables0000644000000000000000000000302710061516616013440 0ustar  $Id: README.variables,v 1.1.1.1 2004/06/09 05:18:06 trockij Exp $

THIS FILE IS PROBABLY OUTDATED


The following are global variables:

maxkeep
    The maximum lines of alert or failure history to retain.

For each service, the following variables are maintained by the server,
and are available from the "status" command:

_failure_count
    The number of failures since the start of monitoring.

_start_of_monitor
    The time that the monitoring of this particular service started,
    as reported by the time(2) system call.

_alert_count
    The number of alerts triggered since _start_of_monitor, in time(2) format.

_last_failure
    The time(2) of the last failure that was detected.

_last_success
    The time(2) of the last success for this service.

_last_output
    The output of the last monitor command (not the current).

_current_output
    The output of the current monitor command.

_timer
    The number of seconds left before the monitor is invoked again.

_last_opstatus
    The _op_status before the dependency code set it to STAT_DEPEND

_op_status
    STAT_FAIL		the monitor returned a failure
    STAT_OK		the monitor returned a success
    STAT_COLDSTART	a coldstart trap was received
    STAT_WARMSTART	a warmstart trap was received
    STAT_LINKDOWN	a linkdown trap was received
    STAT_UNKOWN		unknown (reserved for stupid things)
    STAT_TIMEOUT	a trap timeout occurred
    STAT_UNTESTED	this service has not yet been tested
    STAT_DEPEND		this service has been marked by the depend routines
    STAT_WARN		a warning state
etbemon-1.3.6/doc/globals0000644000000000000000000000175510061516616012165 0ustar  config globals in %CF

$ALERTDIR
$AUTHFILE
$AUTHTYPE
$BASEDIR
$CF
$CFBASEDIR
$CLIENT_TIMEOUT
$DTLOGFILE
$DTLOGGING
$LOGDIR
$MAXPROCS
$MAX_KEEP
$OCFILE
$PIDFILE
$RANDSTART
$SCRIPTDIR
$SERVPORT
$SNMPPORT
$STATEDIR
$TRAPPORT
$USERFILE



globals

$RCSID
$AUTHOR
$OS
$TRAP_PDU
$SLEEPINT
$STOPPED
$STOPPED_TIME
$TRAP_PRO_VERSION
$PROT_VERSION
$HOSTNAME
$PWD
%oncall
$iovec
$numclients
$clientcount
%clients

@last_alerts
@last_failures
$procs
$fdset_rbits
$fdset_ebits
%watch_disabled
$i (debugging only)

$tm
$lasttm

alert flags
    $FL_MONITOR
    $FL_UPALERT
    $FL_TRAP
    $FL_TRAPTIMEOUT
    $FL_STARTUPALERT

trap types
    $TRAP_COLDSTART
    $TRAP_WARMSTART
    $TRAP_LINKDOWN
    $TRAP_LINKUP
    $TRAP_AUTHFAIL
    $TRAP_EGPNEIGHBORLOSS
    $TRAP_ENTERPRISE
    $TRAP_HEARTBEAT

opstatuses
    $STAT_FAIL
    $STAT_OK
    $STAT_COLDSTART
    $STAT_WARMSTART
    $STAT_LINKDOWN
    $STAT_UNKNOWN
    $STAT_TIMEOUT
    $STAT_UNTESTED
    $STAT_DEPEND
    $STAT_WARN
%OPSTAT

%MONITORHASH
%ALERTHASH
etbemon-1.3.6/doc/how-to-write-a-monitor.txt0000644000000000000000000000000210061516616015610 0ustar  

etbemon-1.3.6/doc/how-to-write-an-alert.txt0000644000000000000000000000000310061516616015407 0ustar  


etbemon-1.3.6/doc/mon.80000644000000000000000000013700713135637222011503 0ustar  .\" $Id: mon.8,v 1.6.2.3 2007/06/25 13:10:07 trockij Exp $
.TH mon 8 "$Date: 2007/06/25 13:10:07 $" Linux "Parallel Service Monitoring Daemon"
.SH NAME
mon \- monitor services for availability, sending alarms upon failures.
.SH SYNOPSIS
.B mon
.RB [ \-dfhlMSv ]
.RB [ \-a
.IR dir ]
.RB [ \-A
.IR authfile ]
.RB [ \-b
.IR dir ]
.RB [ \-B
.IR dir ]
.RB [ \-c
.IR config ]
.RB [ \-D
.IR dir ]
.RB [ \-i
.IR secs ]
.RB [ \-k
.IR num ]
.RB [ \-l
.IR [ statetype ] ]
.RB [ \-L
.IR dir ]
.RB [ \-m
.IR num ]
.RB [ \-p
.IR num ]
.RB [ \-P
.IR pidfile ]
.RB [ \-r
.IR delay ]
.RB [ \-s
.IR dir ]
.SH DESCRIPTION
.B mon
is a general-purpose scheduler for monitoring service availability
and triggering alerts upon detecting failures.
.B mon
was designed to be open in the sense that it supports arbitrary
monitoring facilities and alert methods via a common interface, which
are easily implemented through programs (in C, Perl, shell, etc.), 
SNMP traps, and special Mon (UDP packet) traps.

.SH OPTIONS
.TP
.BI \-a\  dir
Path to alert scripts. Default is
.IR /usr/local/lib/mon/alert.d:alert.d .
Multiple alert paths may be specified by separating them with
a colon.  Non-absolute paths are taken to be relative to the
base directory
.RI ( /usr/lib/mon
by default).
.TP
.BI \-b\  dir
Base directory for mon. scriptdir, alertdir, and statedir
are all relative to this directory unless specified from /.
Default is
.IR /usr/lib/mon .
.TP
.BI \-B\  dir
Configuration file base directory. All config files are located here, including
mon.cf, monusers.cf, and auth.cf.
.TP
.BI \-A\  authfile
Authentication configuration file. By default this is
.IR /etc/mon/auth.cf " if the " /etc/mon
directory exists, or
.I /usr/lib/mon/auth.cf
otherwise.
.TP
.BI \-c\  file
Read configuration from
.IR file .
This defaults to
IR /etc/mon/mon.cf " if the " /etc/mon
directory exists, otherwise to
.IR /etc/mon.cf .
.TP
.BI \-d
Enable debugging mode.
.TP
.BI \-D\ dir
Path to state directory.  Default is the first of
.IR /var/state/mon ", " /var/lib/mon ", and " /usr/lib/mon/state.d
which exists.
.TP
.BI \-f
Fork and run as a daemon process. This is the
preferred way to run
.BR mon .
.TP
.BI \-h
Print help information.
.TP
.BI \-i\  secs
Sleep interval, in seconds. Defaults to 1. This shouldn't need to
be adjusted for any reason.
.TP
.BI \-k\  num
Set log history to a maximum of
.I num
entries. Defaults
to 100.
.TP
.BI \-l\ statetype
Load state from the last saved state file. The 
supported saved state types are 
.B disabled
for disabled watches, services, and hosts, 
.B opstatus
for failure/alert/ack status of 
all services,
and 
.B all 
for both.  If no statetype is provided, 
.B disabled
is assumed.
.TP
.BI \-L\ dir
Sets the log dir. See also
.B logdir
in the configuration file.  The default is
.B /var/log/mon
if that directory exists, otherwise
.BR log.d
in the base directory.
.TP
.B \-M
Pre-process the configuration file with the
macro expansion package
.IR m4 .
.\"
.\"
.\"
.TP
.BI \-m\  num
Set the throttle for the maximum number of processes to
.IR num .
.TP
.BI \-p\  num
Make server listen on port
.IR num .
This defaults to 2583.
.TP
.B \-S
Start with the scheduler stopped.
.TP
.BI \-P\  pidfile
Store the server's pid in
.IR pidfile ,
the default is the first of
.IR /run/mon/mon.pid ,
.IR /run/mon.pid ,
and
.IR /etc/mon.pid
whose directory exists.  An empty value tells
.B mon
not to use a pid file.
.TP
.BI \-r\  delay
Sets the number of seconds used to randomize the startup delay
before each service is scheduled. Refer to the global
.I randstart
variable in the configuration file.
.TP
.BI \-s\  dir
Path to monitor scripts. Default is
.IR /usr/local/lib/mon/mon.d:mon.d .
Multiple alert paths may be specified by separating them with
a colon.  Non-absolute paths are taken to be relative to the
base directory
.RI ( /usr/lib/mon
by default).
.TP
.BI \-v
Print version information.

.SH DEFINITIONS
.TP
.BI monitor
A program which tests for a certain condition, returns either true or
false, and optionally produces output to be passed back to the scheduler.
Common monitors detect host reachability via ICMP echo messages, or
connection to TCP services.
.TP
.BI period
A period in time as interpreted by the Time::Period module.
.TP
.BI alert
A program which sends a message when invoked by the scheduler.
The scheduler calls upon an alert when it detects a failure from
a monitor.
An alert program accepts a set of command-line arguments from the
scheduler, in addition to data via standard input.
.TP
.BI hostgroup
A single host or list of hosts, specified as names or IP addresses.
.TP
.BI service
A collection of parameters used to deal with monitoring a particular
resource which is provided by a group. Services are usually modeled after
things such as an SMTP server, ICMP echo capability, server disk space
availability, or SNMP events.
.TP
.BI view
A collection of hostgroups, used to filter mon output for client display.
i.e. a 'network-services' view might be defined so your network staff
can see just the hostgroups which matter to them, without having to see
all hostgroups defined in Mon.
.TP
.BI watch
A collection of services which apply to a particular group.
.SH OPERATION
When the
.B mon
scheduler starts, it reads a configuration file to determine the
services it needs to monitor. The configuration file defaults to
.IR /etc/mon.cf ,
and can be specified using the
.BI \-c
parameter. If the
.B -M
option is specified, then the configuration file is pre-processed
with
.IR m4 .
If the configuration file ends with .m4, the file is also processed by
m4 automatically.

The scheduler enters a loop which handles client connections,
monitor invocations, and failure alerts. Each service has a timer,
specified in the configuration file as the
.BI interval
variable, which tells the scheduler how frequently to invoke a
monitor process.
The scheduler may be temporarily stopped. While it is stopped, client
access still functions, but it just doesn't schedule things. This
is useful in conjunction while resetting the server, because you can do this:
save the hosts and services which are disabled, reset the server
with the scheduler stopped, re-disabled those hosts and services,
then start the scheduler. It also allows making atomic changes
across several client connections.
See the
.B moncmd
man page for more information.

.SH MONITOR\ PROGRAMS
Monitor processes are invoked with the arguments specified in the
configuration file, appended by the hosts from the applicable
host group. For example, if the watch group is "servers", which contain
the hostnames "smtp", "nntp", and "ns", and the monitor line reads
as follows,
.br
\fC
monitor fping.monitor \-t 4000 \-r 2
\fR
.br
then the exectuable "fping.monitor" will be executed with these
parameters:
.br
\fC
MONITOR_DIR/fping.monitor \-t 4000 \-r 2 smtp nntp ns
\fR
.br

MONITOR_DIR is actually a search path, by default
.I /usr/local/lib/mon/mon.d
then
.IR /usr/lib/mon/mon.d ,
but it can be overridden by the
.BI \-s
option or in the configuration file.
If all hosts in the hostgroup have been disabled,
then a warning is sent to syslog and the monitor is
not run. This behavior may be overridden with the
"allow_empty_group" option in the service definition.
If the final argument to the "monitor" line is ";;"
(it must be preceded by whitespace),
then the host list will not be appended to the parameter list.

In addition to environment variables defined by
the user in the service definition,
.B mon
passes certain variables to monitor process.

.TP
.B MON_LAST_SUMMARY
The first line of the output from the last time the monitor exited.
This is not the summary of the current monitor run, but the previous
one.  This may be used by an alert script to provide historical
context in an alert.

.TP
.B MON_LAST_OUTPUT
The entire output of the monitor from the last time it exited.  This
is not the output of the current monitor run, but the previous one.
This may be used by an alert script to provide historical context in
an alert.


.TP
.B MON_LAST_FAILURE
The time(2) of the last failure for this service.

.TP
.B MON_FIRST_FAILURE
The time(2) of the first time this service failed.

.TP
.B MON_LAST_SUCCESS
The time(2) of the last time this service passed.

.TP
.B MON_DESCRIPTION
The description of this service, as defined in the
configuration file using the
.I description
tag.

.TP
.B MON_DEPEND_STATUS
The depend status, "o" if dependency failure, "1" otherwise.

.TP
.B MON_LOGDIR
The directory log files should be placed,
as indicated by the
.I logdir
global configuration variable.

.TP
.B MON_STATEDIR
The directory where state files should be kept,
as indicated by the
.I statedir
global configuration variable.

.TP
.B MON_CFBASEDIR
The directory where configuration files should be kept,
as indicated by the
.I cfbasedir
global configuration variable.

.P
"fping.monitor" should return an exit status of 0 if it
completed successfully (found no problems), or nonzero if a problem
was detected. The first line of output from the monitor
script has a special meaning: it
is used as a brief summary of the exact failure which was detected, and
is passed to the alert program. All remaining output is also passed
to the alert program, but it has no required interpretation.

If a monitor for a particular service is still
running, and the time comes for
.B mon
to run another monitor for that service, it will not
start another monitor. For example, if the
.I interval
is 10s, and the monitor does not finish running
within 10 seconds, then
.B mon
will wait until the first monitor exits before
running another one.

.SH ALERT DECISION LOGIC
Upon a non-zero or zero exit status, the associated alert or upalert
program (respectively) is started,
pending the following conditions: If an alert for a specific
service is disabled, do not send an alert.
If
.B dep_behavior
is set to
.IR "'a'" ,
or
.B alertdepend
is set, and a parent dependency is failing, then suppress the alert.
If the alert has previously been acknowledged, do not send
the alert, unless it is an upalert.
If an alert is not within the specified period, record the failure
via syslog(3) and do not send an alert.
If the failure does not fall within a defined period, do not
send an alert.
No upalerts are sent without corresponding down alerts,
unless
.B no_comp_alerts
is defined in the period section. An upalert will only be sent
if the previous state is a failure.
If an alert was already sent within the last
.B alertevery
interval, do not send another alert,
.I unless
the summary output from the current monitor program differs from the last
monitor process.
Otherwise, send an alert using each alert program
listed for that period. The
.B "observe_detail"
argument to
.B alertevery
affects this behavior by observing the changes in the detail part
of the output in addition to the summary line.
If a monitor has successive failures and the
summary output changes in each of them,
.B alertevery
will not suppress multiple consecutive alerts.
The reasoning is that if the summary output changes, then
a significant event occurred and the user should be alerted.
The "strict" argument to alertevery will suppress both
comparing the output from the previous monitor run to the current
and prevent a successful return value of the monitor from
resetting the alertevery timer. For example, "alertevery 24h strict"
will only send out an alert once every 24 hours, regardless of
whether the monitor output changes, or if the service stops and then
starts failing.

.SH ALERT\ PROGRAMS
Alert programs are found in the path supplied with the
.BI \-a
parameter, or in the
.I /usr/local/lib/mon/alert.d
and
directories if not specified.  They are invoked with the following command-line
parameters:

.TP
.BI \-s\  service
Service tag from the configuration file.
.TP
.BI \-g\  group
Host group name from the configuration file.
.TP
.BI \-h\  hosts
The expanded version of the host group, space delimited, but contained
in one shell "word".
.TP
.BI \-l\  alertevery
The number of seconds until the next alarm will be sent.
.TP
.BI \-O
This option  is  supplied  to an alert only if the
alert is being generated as a result of an expected traap timing out
.TP
.BI \-t\  time
The time (in
.BR time (2)
format) of when this failure condition
was detected.
.TP
.BI \-T
This option is supplied to an alert only if the alert was triggered by a trap
.TP
.B \-u
This option is supplied to an alert only if it is being
called as an upalert.

.P
The remaining arguments are supplied from the trailing parameters in
the configuration file, after the "alert" service parameter.

As with monitor programs, alert programs are invoked with environment
variables defined by the user in the service definition, in addition
to the following which are explicitly set by the server:

.TP
.B MON_LAST_SUMMARY
The first line of the output from the last time the
monitor exited.

.TP
.B MON_LAST_OUTPUT
The entire output of the monitor from the last time it
exited.

.TP
.B MON_LAST_FAILURE
The time(2) of the last failure for this service.

.TP
.B MON_FIRST_FAILURE
The time(2) of the first time this service failed.

.TP
.B MON_LAST_SUCCESS
The time(2) of the last time this service passed.

.TP
.B MON_DESCRIPTION
The description of this service, as defined in the
configuration file using the
.I description
tag.

.TP
.B MON_GROUP
The watch group which triggered this alarm

.TP
.B MON_SERVICE
The service heading which generated this alert

.TP
.B MON_RETVAL
The exit value of the failed monitor program, or return value
as accepted from a trap.

.TP
.B MON_OPSTATUS
The operational status of the service.

.TP
.B MON_ALERTTYPE
Has one of the following values: "failure", "up", "startup",
"trap", or "traptimeout", and signifies the type of alert which
was triggered.

.TP
.B MON_TRAP_INTENDED
This is only set when an unknown mon trap is received and caught
by the default/defaut watch/service. This contains colon
separated entries of the trap's intended watch group and service name.

.TP
.B MON_LOGDIR
The directory log files should be placed,
as indicated by the
.I logdir
global configuration variable.

.TP
.B MON_STATEDIR
The directory where state files should be kept,
as indicated by the
.I statedir
global configuration variable.

.TP
.B MON_CFBASEDIR
The directory where configuration files should be kept,
as indicated by the
.I cfbasedir
global configuration variable.

.P
The first line from standard input must be used as a brief summary
of the problem, normally supplied as the subject line of an email, or
text sent to an alphanumeric pager. Interpretation of all subsequent
lines read from stdin is left up to the alerting program. The usual
parameters are a list of recipients to deliver the notification to.
The interpretation of the recipients is not specified, and is up
to the alert program.

.SH CONFIGURATION FILE
The configuration file consists of zero or more global variable definitions,
zero or more hostgroup definitions,
and one or more watch definitions. Each watch definition may have one
or more service definitions. A watch definition is terminated by a blank
line, another definition, or the end of the file. A line beginning with optional
leading whitespace and a pound ("#") is
regarded as a comment, and is ignored.

Lines are parsed as they are read. Long lines may be continued by ending
them with a backslash ("\\").  If a line is continued, then the backslash,
the trailing whitespace after the backslash, and the leading whitespace
of the following line are removed. The end result is assembled into a
single line.

Typically the configuration file has the following layout:

1. Global variable definitions

2. Hostgroup definitions

3. Watch definitions

See the "etc/example.cf" file which comes for the distribution for an example.

.SS "Global Variables"
The following variables may be set to override compiled-in
defaults. Command-line options will have a higher precedence than
these definitions.

.TP
.BI "alertdir = " dir
.I dir
is the full path to the alert scripts. This is the value set by
the
.B \-a
command-line parameter.

Multiple alert paths may be specified by separating them with
a colon.  Non-absolute paths are taken to be relative to the
base directory
.RI ( /usr/lib/mon
by default).

When the configuration file is read, all alerts referenced from the
configuration will be looked up in each of these paths, and the full
path to the first instance of the alert found is stored in a hash. This
hash is only generated upon startup or after a "reset" command, so newly
added alert scripts will not be recognized until a "reset" is performed.

.TP
.BI "mondir = " dir
.I dir
is the full path to the monitor scripts. This value may also be
set by the
.B \-s
command-line parameter. If this path does not begin with a "/", it will be
relative to
.IR basedir .

Multiple alert paths may be specified by separating them with
a colon. All paths must be absolute.

When the configuration file is read, all monitors referenced from the
configuration will be looked up in each of these paths, and the
full path to the first
instance of the monitor found is stored in a hash. This hash is only
generated upon startup or after a "reset" command, so newly added monitor
scripts will not be recognized until a "reset" is performed.

.TP
.BI "statedir = " dir
.I dir
is the full path to the state directory.
.B mon
uses this directory to save various state information. If this path does not begin with a "/", it will be
relative to
.IR basedir .

.TP
.BI "logdir = " dir
.I dir
is the full path to the log directory.
.B mon
uses this directory to save various logs, including
the downtime log. If this path does not begin with a "/", it will be
relative to
.IR basedir .

.TP
.BI "basedir = " dir
.I dir
is the full path for the state, log, monitor, and alert directories.

.TP
.BI "cfbasedir = " dir
.I dir
is the full path where all the config files can be found
(monusers.cf, auth.cf, etc.).

.TP
.BI "authfile = " file
.I file
is the path to the authentication file. If the path does not begin
with a "/", it will be relative to
.IR cfbasedir .

.TP
.BI "authtype = " "type [type...]"
.I type
is the type of authentication to use. A space-separated list of
types may be specified, and they will be checked the order they are
listed. As soon as a successful authentication is performed, the user
is considered authenticated by mon for the duration of the session and
no more authentication checks are performed.

If
.I type
is
.BR getpwnam ,
then the standard Unix passwd file authentication method will be used
(calls getpwnam(3) on the user and compares the crypt(3)ed version
of the password with what it gets from getpwnam). This will not work
if shadow passwords are enabled on the system.

If
.I type
is
.BR userfile ,
then usernames and hashed passwords are read from
.IR userfile ,
which is defined via the
.B userfile
configuration variable.

If
.I type
is
.BR pam ,
then PAM (pluggable authentication modules) will be used for authentication.
The service specified by the
.B pamservice
global will be used. If no global is given, the PAM
.B passwd
service will be used.

If
.I type
is
.BR trustlocal ,
then if the client connection comes from locahost, the username passed from 
the client will be trusted, and the password will be ignored.  This can be used 
when you want the client to handle the authentication for you.  I.e. a CGI script 
using one of the many apache authentication methods.

.TP
.BI "userfile = " file
This file is used when
.B authtype
is set to
.IR userfile .
It consists of a sequence of lines of the format
.BR "'username : password'" .
.B password
is stored as the hash returned by the standard Unix
crypt(3) function. 
.B NOTE:
the format of this file is compatible with the Apache file based
username/password file format. It is possible to use the
.I htpasswd
program supplied with Apache to manage the mon userfile.

Blank lines and lines beginning with # are ignored.

.TP
.BI "pamservice = " service
The PAM service used for authentication. This is applicable
only if "pam" is specified as a parameter to the
.B authtype
setting. If this global is not defined, it defaults
to
.BR "passwd" .

.TP
.BI "serverbind = " addr

.TP
.BI "trapbind = " addr

.B serverbind
and
.B trapbind
specify which address to bind the server and trap ports to, respectively.
If these are not defined, the default address is INADDR_ANY, which
allows connections on all interfaces. For security reasons,
it could be a good idea to bind only to the loopback interface.

.TP
.BI "dtlogfile = " file
.I file
is a file which will be used to record the downtime log. Whenever
a service fails for some amount of time and then stop failing, this
event is written to the log. If this parameter is not set, no
logging is done. The format of the file is as follows (# is a
comment and may be ignored):

.BR "timenoticed group service firstfail downtime interval summary".

.B timenoticed
is the time(2) the service came back up.

.B "group service"
is the group and service which failed.

.B "firstfail"
is the time(2) when the service began to fail.

.B "downtime"
is the number of seconds the service failed.

.B "interval"
is the frequency (in seconds) that the service is polled.

.B "summary"
is the summary line from when the service was failing.

.TP
.BI "monerrfile = " filename
By default, when mon daemonizes itself, it connects
stdout and stderr to /dev/null. If
.B monerrfile
is set to a file, then stdout and stderr will be
appended to that file. In all cases stdin is connected
to /dev/null. If mon is told to run in the foreground
and to not daemonize, then none of this applies, since
stdin/stdout/stderr stay connected to whatever they
were at the time of invocation.

.TP
.BI "dtlogging = " yes/no

Turns downtime logging on or off. The default is off.

.TP
.BI "histlength = " num
.I num
is the the maximum number of events to be retained
in history list. The default is 100.
This value may also be set by the
.B \-k
command-line parameter.

.TP
.BI "historicfile = " file
If this variable is set, then alerts are logged to
.IR file ,
and upon startup, some (or all) of the past history is read
into memory.

.TP
.BI "historictime = " timeval
.I num
is the amount of the history file to read upon startup.
"Now" -
.I timeval
is read. See the explanation of
.I interval
in the "Service Definitions" section
for a description of
.IR timeval .

.TP
.BI "serverport = " port
.I port
is the TCP port number that the server should bind to. This value may also be
set by the
.B \-p
command-line parameter. Normally this port is looked up via getservbyname(3),
and it defaults to 2583.

.TP
.BI "trapport = " port
.I port
is the UDP port number that the trap server should bind to.
Normally this port is looked up via getservbyname(3),
and it defaults to 2583.

.TP
.BI "pidfile = " path
.I path
is the file the sever will store its pid in.  This value may also be set
by the
.B \-P
command-line parameter.

.TP
.BI "maxprocs = " num
Throttles the number of concurrently forked processes to
.I num.
The intent is to provide a safety net for the unlikely situation
when the server tries to take on too many tasks at once.  Note that this
situation has only been reported to happen when trying to use a garbled
configuration file! You don't want to use a garbled configuration
file now, do you?

.TP
.BI "cltimeout = " secs
Sets the client inactivity timeout to
.I secs.
This is meant to help thwart denial of service attacks or
recover from crashed clients.
.I secs
is interpreted as a "1h/1m/1s" string, where
"1m" = 60 seconds.

.TP
.BI "randstart = " interval
When the server starts, normally all services will not be scheduled
until the interval defined in the respective service section.
This can cause long delays before the first check of a service,
and possibly a high load on the server if multiple things are scheduled
at the same intervals.
This option is used to randomize the scheduling
of the first test for all services during the startup period, and
immediately after the
.I reset
command.
If
.I randstart
is defined, the scheduled run time of all services of all watch groups
will be a random number between zero and
.I randstart
seconds.

.TP
.BI "dep_recur_limit = " depth
Limit dependency recursion level to
.IR depth .
If dependency recursion (dependencies which depend on other dependencies)
tries to go beyond
.IR depth ,
then the recursion is aborted and a messages is logged to syslog.
The default limit is 10.

.TP
.BI "dep_behavior = " {a|m|hm}
.B dep_behavior
controls whether the dependency expression
suppresses one of: the running of alerts, the running of 
monitors, or the passing of individual hosts to the monitors.
Read more about the behavior in the "Service Definitions" 
section below.

This is a global setting which controls the default
settings for the service-specified variable.

.TP
.BI "dep_memory = " timeval
If set, dep_memory will cause dependencies to continue to prevent
alerts/monitoring for a period of time after the service returns to a
normal state.  This can be used to prevent over-eager alerting when a
machine is rebooting, for example.  See the explanation of
.I interval
in the "Service Definitions" section
for a description of
.IR timeval .

This is a global setting which controls the default
settings for the service-specified variable.

.TP
.BI "syslog_facility = " facility
Specifies the syslog facility used for logging.
.B daemon
is the default.



.TP
.BI "startupalerts_on_reset = " {yes|no}

If set to "yes", startupalerts will be invoked when the
.B reset
client command is executed. The default is "no".

.TP
.BI "monremote = " program

If set, this external program will be called by Mon when various
client requests are processed.  This can be used to propagate those
changes from one Mon server to another, if you have multiple
monitoring machines.  An example script, 
.B monremote.pl
is available in the clients directory.

.SS "Hostgroup Entries"

Hostgroup entries begin with the keyword
.BR hostgroup ,
and are followed by a hostgroup tag and one or more hostnames
or IP addresses, separated by whitespace. The hostgroup tag must
be composed of alphanumeric
characters, a dash ("-"), a period ("."),
or an underscore ("_"). Non-blank lines following
the first hostgroup line are interpreted as more hostnames.
The hostgroup definition ends with a blank line. For example:

.RS
.nf
hostgroup servers nameserver smtpserver nntpserver
	nfsserver httpserver smbserver

hostgroup router_group cisco7000 agsplus
.fi
.RE

.SS "View Entries"
View entries begin with the keyword
.BR view , 
and are followed by a view tag and the names of one or more
hostgroups.  The view tag must be composed of alphanumeric
characters, a dash ("-"), a period ("."),
or an underscore ("_"). Non-blank lines following
the first view line are interpreted as more hostgroup names.
The view definition ends with a blank line. For example:

.RS
.nf
view servers dns-servers web-servers file-servers
     mail-servers

view network-services routers switches vpn-servers
.fi
.RE


.SS "Watch Group Entries"

Watch entries begin with a line that starts
with the keyword
.BR watch ,
followed by whitespace and a single word which
normally refers
to a pre-defined hostgroup. If the second word is not recognized
as a hostgroup tag, a new hostgroup is created whose tag is
that word, and that word is its only member.

Watch entries consist of one or more service definitions.

A watch group is terminated by a blank line, the end of the file, or by a
subsequent definition, "watch", "hostgroup", or otherwise.

There may be a special watch group entry called "default". If a
default watch group is defined with a service entry named "default",
then this definition will be used in handling traps received for
an unrecognized watch and service.

.SS "Service Definitions"

.TP
.BI service " servicename"
A service definition begins with they keyword
.B service
followed by a word which is the tag for this service.
This word must be unique among all services defined for the
same watch group.

The components of a service are an interval, monitor, and
one or more time period definitions, as defined below.

If a service name of "default" is defined within a watch
group called "dafault" (see above), then the default/default
definition will be used for handling unknown mon traps.

The following configuration parameters are valid only following
a service definition:

.TP
.BI VARIABLE= "value"
Environment variables may be defined for each service, which will be
included in the environment of monitors and alerts. Variables must
be specified in all capital letters, must begin with an alphabetical
character or an underscore, and there must be no spaces to the left
of the equal sign.

.TP
.BI interval " timeval"
The keyword
.B interval
followed by a time value specifies the frequency that
a monitor script will be triggered.
Time values are defined as "30s", "5m", "1h", or "1d",
meaning 30 seconds, 5 minutes, 1 hour, or 1 day. The numeric portion
may be a fraction, such as "1.5h" or an hour and a half. This
format of a time specification will be referred to as
.IR timeval .

.TP
.BI failure_interval " timeval"
Adjusts the polling interval to
.I timeval
when the service check is failing. Resets the interval
to the original when the service succeeds.

.TP
.BI traptimeout " timeval"
This keyword takes the same time specification argument as
.BI interval ,
and makes the service expect a trap from an external source
at least that often, else a failure will be registered. This is
used for a heartbeat-style service.

.TP
.BI trapduration " timeval"
If a trap is received, the status of the service the trap was delivered
to will normally remain constant. If
.B trapduration
is specified, the status of the service will remain in a failure
state for the duration specified by
.IR timeval ,
and then it will be reset to "success".

.TP
.BI randskew " timeval"
Rather than schedule the monitor script to run at the start of each
interval, randomly adjust the interval specified by the
.B interval
parameter by plus-or-minus
.B "randskew".
The skew value is specified as the
.B interval
parameter: "30s", "5m", etc...
For example if
.B "interval"
is 1m, and
.B "randskew"
is "5s", then
.I mon
will schedule the monitor script some time between every
55 seconds and 65 seconds.
The intent is to help distribute the load on the server when
many services are scheduled at the same intervals.

.TP
.BI monitor " monitor-name [arg...]"
The keyword
.B monitor
followed by a script name and arguments
specifies the monitor to run when the timer
expires. Shell-like quoting conventions are
followed when specifying the arguments to send
to the monitor script.
The script is invoked from the directory
given with the
.B \-s
argument, and all following words are supplied
as arguments to the monitor program, followed by the
list of hosts in the group referred to by the current watch group.
If the monitor line ends with ";;" as a separate word,
the host groups are not appended to the argument list
when the program is invoked.

.TP
.B allow_empty_group
The
.B allow_empty_group
option will allow a monitor to be invoked even when the
hostgroup for that watch is empty because of
disabled hosts. The default behavior is not
to invoke the monitor when all hosts in a hostgroup
have been disabled.

.TP
.BI description " descriptiontext"
The text following
.B description
is queried by client programs, passed to alerts and monitors via an
environment variable. It should contain a brief description of the
service, suitable for inclusion in an email or on a web page.

.TP
.BI exclude_hosts " host [host...]"
Any hosts listed after
.B exclude_hosts
will be excluded from the service check.

.TP
.BI exclude_period " periodspec"
Do not run a scheduled monitor during the time
identified by
.IR periodspec .

.TP
.BI depend " dependexpression"
The
.B depend
keyword is used to specify a dependency expression, which
evaluates to either true of false, in the boolean sense.
Dependencies are actual Perl expressions, and must obey all syntactical
rules. The expressions are evaluated in their own package space so as
to not accidentally have some unwanted side-effect.
If a syntax error is found when evaluating the expression, it
is logged via syslog.

Before evaluation, the following substitutions on the expression occur:
phrases which look like "group:service" are substituted with the value
of the current operational status of that specified service. These
opstatus substitutions are computed recursively, so if service A
depends upon service B, and service B depends upon service C, then
service A depends upon service C. Successful operational statuses (which
evaluate to "1") are "STAT_OK", "STAT_COLDSTART", "STAT_WARMSTART", and
"STAT_UNKNOWN".  The word "SELF" (in all caps) can be used for the group
(e.g. "SELF:service"), and is an abbreviation for the current watch group.

This feature can be used to control alerts for services which are
dependent on other services, e.g. an SMTP test which is dependent upon
the machine being ping-reachable.

.TP
.BI dep_behavior " {a|m|hm}"
The evaluation of the dependency graphs specified via the
.B depend
keyword
can control the
suppression of alert or monitor invocations, or the suppression
of individual hosts passed to the monitor.

.BR "Alert suppression" .
If this option is set to "a",
then the dependency expression
will be evaluated after the
monitor for the service exits or
after a trap is received.
An alert will only be sent
if the evaluation succeeds, meaning
that none of the nodes in the dependency
graph indicate failure.

.BR "Monitor suppression" .
If it is set to "m",
then the dependency expression will be evaulated
before the monitor for the service is about to run.
If the evaulation succeeds, then the monitor
will be run. Otherwise, the monitor will not
be run and the status of the service will remain
the same.

.BR "Host suppression" .
If it is set to "hm" then Mon will extract the list of "parent"
services from the dependency expression.  (In fact the expression can
be just a list of services.) Then when the monitor for the service is
about to be run, for each host in the current hostgroup Mon will
search all the parent services which are currently failing and look
for the hostname in the current summary output.  If the hostname is
found, this host will be excluded from this run of the monitor.  This
can be used to e.g. allow an SMTP test on a group of hosts to still be run
even when a single host is not ping-reachable.  If all the rest of the
hosts are working fine, the service will be in an OK state, but if
another host fails the SMTP test Mon can still alert about that host
even though the parent dependency was failing.  The dependency
expression will
.B not
be used recursively in this case.

.TP
.BI alertdepend " dependexpression"
.TP
.BI monitordepend " dependexpression"
.TP
.BI hostdepend " dependexpression"
These keywords allow you to specify multiple dependency expressions of 
different types.  Each one corresponds to the different 
.B dep_behavior
settings listed above.  They will be evaluated independently in the different
contexts as listed above.  If
.B depend
is present, it takes precedence over the matching keyword, depending on the
.B dep_behavior
setting.

.TP
.BI "dep_memory " timeval
If set, dep_memory will cause dependencies to continue to prevent
alerts/monitoring for a period of time after the service returns to a
normal state.  This can be used to prevent over-eager alerting when a
machine is rebooting, for example.  See the explanation of
.I interval
in the "Service Definitions" section
for a description of
.IR timeval .

.TP
.BI redistribute " alert [arg...]"
A service may have one redistribute option, which is a special form of an
an alert definition.  This alert will be called on every service status
update, even sequential success status updates.  This can be used to
integrate Mon with another monitoring system, or to link together multiple
Mon servers via an alert script that generates Mon traps.  See the "ALERT
PROGRAMS" section above for a list of the parameters mon will pass
automatically to alert programs.

.TP
.BI unack_summary
Remove the "acknowledged" state from a service if the summary component of the
failure message changes.  In most common usage the summary is the list
of hosts that are failing, so additional hosts failing would remove an
ack.


.SS "Period Definitions"

Periods are used to define the conditions which
should allow alerts
to be delivered.

.TP
.BI period " [label:] periodspec"
A period groups one or more alarms and variables
which control how often an alert happens when there
is a failure.
The
.B period
definition has two forms. The first
takes an argument which is a
period specification from Patrick Ryan's
Time::Period Perl 5 module. Refer to
"perldoc Time::Period" for more information.

The second form requires a label followed by a period specification, as
defined above. The label is a tag consisting of an alphabetic character
or underscore followed by zero or more alphanumerics or underscores
and ending with a colon. This
form allows multiple periods with the same period definition. One use
is to have a period definition which has no
.B alertafter
or
.B alertevery
parameters for a particular time period, and another
for the same time period with a different
set of alerts that does contain those
parameters.

Period definitions, in either the first or second form, must be unique within
each service definition. For example, if you need to define two
periods both for "wd {Sun-Sat}", then one or both of the period definitions
must specify a label such as "period t1: wd {Sun-Sat}" and
"period t2: wd {Sun-Sat}".

.TP
.BI alertevery " timeval [observe_detail | strict]"
The
.B alertevery
keyword (within a
.B period
definition) takes the same type of argument as the
.B interval
variable, and limits the number of times an alert
is sent when the service continues to fail.
For example, if the interval is "1h", then only
the alerts in the period section will only
be triggered once every hour. If the
.B alertevery
keyword is
omitted in a period entry, an alert will be sent
out every time a failure is detected. By default,
if the summary output of two successive failures changes,
then the alertevery interval is overridden, and an alert
will be sent.
If the string
"observe_detail" is the last argument, then both the summary
and detail output lines will be considered when comparing the
output of successive failures.
If the string "strict" is the last argument, then the output
of the monitor or the state change of the service will have
no effect on when alerts are sent. That is, "alertevery 24h strict"
will send only one alert every 24 hours, no matter what.
Please refer to the
.B "ALERT DECISION LOGIC"
section for a detailed explanation of how alerts are suppressed.

.TP
.BI alertafter " num"

.TP
.BI alertafter " num timeval"

.TP
.BI alertafter " timeval"
The
.B alertafter
keyword (within a
.B period
section) has three forms: only with the "num"
argument, or with the "num timeval" arguments,
or only with the "timeval" argument.
In the first form, an alert will only be invoked
after "num" consecutive failures.

In the second form,
the arguments are a positive integer followed by an interval,
as described by the
.B interval
variable above.
If these parameters are specified,
then the alerts for that period will only
be called after that many failures happen
within that interval. For example,
if
.B alertafter
is given the arguments "3\ 30m", then the alert will be called
if 3 failures happen within 30 minutes.

In the third form,
the argument is an interval,
as described by the
.B interval
variable above.
Alerts for that period
will only be called if the service has been
in a failure state for more than the length
of time desribed by the interval, regardless
of the number of failures noticed within that
interval.

.TP
.BI numalerts " num"

This variable tells the server to call no more than
.I num
alerts during a
failure. The alert counter is kept on a per-period basis,
and is reset upon each success.

.TP
.B "no_comp_alerts"

If this option is specified, then upalerts will be called whenever the
service state changes from failure to success, rather than only after
a corresponding "down" alert.

.TP
.BI alert " alert [arg...]"
A period may contain multiple alerts, which are triggered
upon failure of the service. An alert is specified with
the
.B alert
keyword, followed by an optional
.B exit
parameter, and arguments which are interpreted the same as
the
.B monitor
definition, but without the ";;" exception. The
.B exit
parameter takes the form of 
.B "exit=x"
or
.B "exit=x-y"
and has the effect that the alert is only called if the
exit status of the monitor script falls within the range
of the
.B exit
parameter. If, for example, the alert line is
.I "alert exit=10-20 mail.alert mis"
then
.I mail-alert
will only be invoked with
.I mis
as its arguments if the monitor
program's exit value is between 10 and 20. This feature
allows you to trigger different alerts at different
severity levels (like when free disk space goes from 8% to 3%).

See the
.B "ALERT PROGRAMS"
section above for a list of the pramaeters mon will pass 
automatically to alert programs.

.TP
.BI upalert " alert [arg...]"
An
.B upalert
is the compliment of an
.BR alert .
An upalert is called when a services makes the state transition from
failure to success, if a corresponding "down" alert
was previously sent. The
.B upalert
script is called supplying
the same parameters as the
.B alert
script, with the addition of the
.B \-u
parameter which is simply used to let
an alert script know that it is being called
as an upalert. Multiple upalerts may be
specified for each period definition.
Set the per-period
.B no_comp_alerts
option to 
send an upalert regardless if whether or not
a "down" alert was  sent.

.TP
.BI startupalert " alert [arg...]"
A
.B startupalert
is only called when the
.B mon
server starts execution, or when a "reset"
command was issued to the server, depending on
the setting of the
.B startupalerts_on_reset
global.
Unlike other alerts,
.B startupalerts
are not called following the
exit of a monitor, i.e. they are
called in their own right, therefore the
"exit=" argument is not applicable to
.B startupalert.

.TP
.BI upalertafter " timeval"
The
.B upalertafter
parameter is specified as a string that
follows the syntax of the
.B interval
parameter ("30s", "1m", etc.), and
controls the triggering of an
.BR upalert .
If a service comes back up after
being down for a time greater than
or equal to the value of this option, an
.B upalert
will be called. Use this option to prevent
upalerts to be called because of "blips" (brief outages).

.SH "AUTHENTICATION CONFIGURATION FILE"
The file specified by the
.B authfile
variable in the configuration file (or
passed via the
.B "-A"
parameter) will be loaded upon startup.
This file defines restrictions upon which client
commands may be executed by which users. It is a
text file which consists of comments,
command definitions, and trap authentication parameters.
A comment line begins with optional
whitespace followed by pound sign. Blank lines are ignored.

The file is separated into a command section and a trap
section. Sections are specified by a single line containing
one of the following statements:

.RS
.nf
	command section
.fi
.RE

or

.RS
.nf
	trap section
.fi
.RE

Lines following one of the above statements apply to that section until
either the end of the file or another section begins.

A command definition consists of a command, followed by a colon,
followed by a comma-separated list of users who may execute the command.
The default is that no users may execute any commands unless they are
explicitly allowed in this configuration file. For clarity, a user can
be denied by prefixing the user name with "!". If the word "AUTH_ANY"
is used for a username, then any authenticated user will be allowed to
execute the command. If the word "all" is used for a username, then
that command may be executed by any user, authenticated or not.

The trap section allows configuration of which users may send traps from
which hosts. The syntax is a source host (name or ip address), whitespace,
a username, whitespace, and a plaintext password for that user. If
the source host is "*", then allow traps from any host. If the username
is "*", then accept traps without regard for the username or password. If
no hosts or users are specified, then no traps will be accepted.

An example configuration file:

.RS
.nf
command section
list:		all
reset:		root,admin
loadstate:      	root
savestate:      	root

trap section
127.0.0.1	root	r@@tp4sswrd
.fi
.RE

This means that all clients are able to perform the
.B list
command, "root" is able to perform "reset", "loadstate", "savestate",
and "admin" is able to execute the "reset"
command.

.SH CLIENT\-SERVER\ INTERFACE
The server listens on TCP port 2583, which may be overridden using
the
.BI \-p\  port
option. Commands are a single line each, terminated by a newline.
The server can handle any number of simultaneous client connections.

.SH CLIENT\ INTERFACE\ COMMANDS

See manual page for
.BR moncmd .

.SH MON\ TRAPPING
Mon has the facility to receive special "mon traps" from any local
or remote machine. Currently, the only available method for
sending mon traps are through the Mon::Client perl interface,
though the UDP packet format is defined well enough to permit
the writing of traps in other languages.

Traps are handled similarly to monitors: a trap sends
an operational status, summary line, and description
text, and mon generates an alert or
upalert as necessary.

Traps can be caught by any watch/service group set up in
the mon configuration file, however it is suggested that
you configure watch/service groups specifically for
the traps you expect to receive. When defining a special
watch/service group for traps, do not include a "monitor"
directive (as no monitor need be invoked). Since a monitor
is not being invoked, it is not necessary for the watch
definition to have a hostgroup which contains real host names.
Just make up a useful name, and mon will automatically create
the watch group for you.

Here is a simple config file example:

.RS
.nf
watch trap-service
	service host1-disks
		description TRAP: for host1 disk status
		period wd {Sun-Sat}
			alert mail.alert someone@your.org
			upalert mail.alert \-u someone@your.org

.fi
.RE

Since mon listens on a UDP port for any trap, a
default facility is available for handling traps to unknown
groups or services.
To enable this facility, you must include a "default" watch
group with a "default" service entry containing the specifics
of alarms.  If a default/default watch group and service are
not configured, then unknown traps get logged via syslog, and
no alarm is sent.
.B NOTE:
The default/default facility is a single entity as far as
accounting and alarming go. Alarm programs which are not
aware of this fact may send confusing information when a
failure trap comes from one machine, followed by a
success (ok) trap from a different machine. See the alarm
environment variable
.B MON_TRAP_INTENDED
above for a possible way around this. It is intended that
default/default be used as a facility to catch unknown
traps, and should not be relied upon to catch all traps
in a production environment. If you are lazy and only want
to use default/default for catching all traps,
it would be best to disable
upalerts, and use the MON_TRAP_INTENDED environment
variable in alert scripts to make the alerts more
meaningful to you.

Here is an example default facility:

.RS
.nf
watch default
	service default
		description Default trap service
		period wd {Sun-Sat}
			alert mail.alert someone@your.org
			upalert mail.alert \-u someone@your.org

.fi
.RE

.SH EXAMPLES
The
.B mon
distribution comes with an
example configuration called
.IR example.cf .
Refer to that file for more information.

.SH SEE ALSO
.BR moncmd (1),
.BR Time::Period (3pm),
.BR Mon::Client (3pm)
.SH HISTORY
.B mon
was written because I couldn't find anything out
there that did just what I needed, and nothing was worth modifying
to add the features I wanted. It doesn't have a cool name, and
that bothers me because I couldn't think of one.
.SH BUGS
Report bugs to the email address below.
.SH AUTHOR
Jim Trocki 
etbemon-1.3.6/doc/moncmd.10000644000000000000000000002014713135637032012153 0ustar  .\" $Id: moncmd.1,v 1.2 2005/04/17 07:42:27 trockij Exp $
.TH moncmd 1 "$Date: 2005/04/17 07:42:27 $" Linux "moncmd"
.SH NAME
moncmd \- send commands to mon daemon and show the results.
.SH SYNOPSIS
.B moncmd
.RB [ \-a ]
.RB [ \-d ]
.RB [ \-l
.IR username ]
.RB [ \-f
.IR file ]
.RB [ \-s
.IR server ]
.RB [ \-p
.IR port ]
.RB [ command ]
.SH DESCRIPTION
.B moncmd
sends commands to the
.B mon
server.
.SH OPTIONS
.TP
.B \-a
Authenticate with the server.
.TP
.B \-d
enable debugging, which is the same as
.B \-s
.IR localhost .
.TP
.BI "-f " file
Read and execute commands from
.IR file .
.TP
.BI "-l " username
Supply
.I username
as the username while authenticating to the server.
.TP
.BI \-s\  server
Connect to
.IR server .
.TP
.BI \-p\  port
Use TCP port
.I port
when connecting to the server, instead of the
default of 32777.

.SH MONITOR HOST
.B moncmd
will use the host specified by the
.B \-s
parameter as the server.  If there is no
.B \-s
parameter it will use the host specified in the MONHOST environment
variable.  If there is no host in either of these locations it will exit
with an error.

.SH BATCH OPERATION
If no commands are supplied to
.B moncmd
on the command line, then commands will
be taken from either standard input, or from
the file specified by the \-f parameter.
If standard input is connected
to a TTY and the \-a option is supplied,
then it will prompt for a password.
If the \-a option is supplied without the \-f
option and standard input is not a TTY, then
the username and password are read from
standard input using the syntax "USER=username" and
"PASS=password". The remaining input lines are
interpreted as commands to send to the server.
.B moncmd
will not take usernames or passwords from a file,
for obvious security reasons.

If the username is neither supplied by the \-l parameter
or through standard input,
it is taken from the effective user ID of the
current process.

.SH COMMANDS
The following is a list of the commands that
the server understands.
.\"
.\"
.TP
.BI "enable | disable service " group " " servicename
Enables/disables alerts for
.I group
and
.IR servicename .
All disabled states are automatically saved to the
state file, which may optionally be re-loaded upon
restarting or initial startup of the server.

.TP
.BI "ack " "group service comment"
Acknowledge a failure condition. This will store
.I comment
in the state of service (queryable by doing a
.I "list opstatus"
command), and will surppress further alerts for
the service. Once the service returns to a non-failure
state, then the acknowledgement is reset.

.TP
.B "version"
Displays the protocol version in the form of
"version
.BR num """
where
.B num
is the protocol version number.

.TP
.BI "list aliases"
Lists aliases.

.TP
.BI "list aliasgroups"
Lists alias groups.

.TP
.B savestate
Save the state of the server. Currently, the only state which
is saved is the host/watches/services which are disabled.

.TP
.B loadstate
Load the state of the server. Currently, the only state which
is loaded is the host/watches/services which are disabled.

.TP
.BI "enable | disable host " hostname
Enables/disables host
.I hostname
in all groups. When the monitor is called, this
hostname will not be included in the list of
hostnames sent to the monitor. If a group has only
one hostname in it, then the
.BI "enable | disable watch"
command should be used instead.

.TP
.BI "enable | disable watch " watchgroup
Enables/disables an entire watch for
.IR watchgroup ,
as defined in
the configuration file. Disabling a watch not only
stops alerts from happening, but it stops the actual
monitor processes from being scheduled.

.TP
.BI "reset"
Resets the server, forcing it to re-read the configuration file,
kill off currently running monitors,
restart all monitoring, and reset all counters.
This command is only accessible if
.B moncmd
connects from the host which is running the
.B mon
server.
.TP
.BI "reset stopped"
Resets the server and immediately stops the scheduler.
This is an atomic version of the commands
.B "reset"
and
.BR "stop" .

.TP
.BI "reload auth"
Reloads the auth.cf file in order to incorporate any new changes.
The auth table is completely re-generated; it is not merged.

.TP
.BI "reset keepstate"
If the word "keepstate" comes after the reset command,
the server will do a "loadstate" right after the reset,
before the scheduler kicks back in.

.TP
.BI "stop"
Stops the scheduler, but continues to allow
client connections.

.TP
.BI "start"
Re-starts the scheduler after it has been
stopped.

.TP
.BI "test monitor " group " " servicename
Triggers a test for
.I "group"
and
.I "service"
immediately by
setting the service's countdown timer to zero.

.TP
.BI "test (alert | upalert | startupalert) " group " " servicename " " retval " " period
Triggers a test alert, upalert, or startupalert for
.I group
and
.IR servicename .
.I retval
is the integer exit value to pass to the alert via
the MON_RETVAL environment variable. You must also
specify the
.I period
as it appears in the configuration file.
All alerts of the given type in that period will be triggered,
but the alert will not be logged.

.TP
.BI "servertime"
Returns the current time of the server as seconds since Jan 1, 1970.

.TP
.BI "list group " groupname
Lists the members of group
.IR groupname .

.TP
.B "list descriptions"
List the descriptions of each service, as defined
in the configuration file. If a service description
is undefined, then it is not listed.

.TP
.BI "list alerthist"
Lists the last alarms triggered for each service of each
watch group, in addition to the summary output. The number
of alerts to keep in memory is bounded by the
.I maxkeep
variable, configurable on the
.B mon
command line at startup, and expandable with the
.B set
command during runtime.

.TP
.BI "list failurehist"
Lists the last failures, in addition to the summary output.
This is also limited by the
.I maxkeep
variable.

.TP
.BI "list opstatus"
Lists operational status of all services. Reports whether the last time
a service group was tested resulted in success or failure. The output
is:

.nf
group service untested
group service time timeleft succeeded
group service time timeleft failed output
.fi

where
.I output
is the first line of output from the monitor script
which failed,
.I time
is the time that the condition was last noticed in
.BR time (2)
format, and
.I timeleft
is the number of seconds left until the service is tested
again.

.TP
.BI "list successes"
Generates the same output as the
.B "list opstatus"
command, but only shows the services that
have succeeded the last time they were tested.

.TP
.BI "list failures"
Generates the same output as the
.B "list opstatus"
command, but only shows the services that
have failed the last time they were tested.

.TP
.BI "list disabled"
Lists all hosts and services which have been disabled by the
.B "disable host|service"
command.

.TP
.BI "list pids"
Shows the currently active watch groups/services along with their
process IDs, and it process ID of the server daemon.

.TP
.BI "list watch"
Lists all watches and services.

.TP
.BI "list state"
Lists the state of the scheduler.

.TP
.BI "set " group " " service " " variable " " value
Sets a variable to value. Useful for temporarily changing an interval
or alertevery value. Be careful, because this can just set any
value in the %watch hash, and some values that are specified in
the configuration file like "10m" or "35s" are converted and stored as
just plain integer seconds (e.g. "alertevery").

.TP
.BI "get " group " " service " " variable
Displays the value of group service variable.

.TP
.BI "set " variable " " value
Assigns
.I value
to the global variable
.IR variable .

.TP
.BI "set opstatus " group " " service " " value
Sets the opstatus value for
.I group
and
.I service.

.TP
.BI "get " variable
Shows the value of global variable
.IR variable .

.TP
.BI "term"
Terminates the server.
This command is only accessible if
.B moncmd
connects from the host which is running the
.B mon
server.

.SH "ENVIRONMENT VARIABLES"

.IP MONSERVER
The hostname of the server which runs the
.B mon
process.
.IP MONPORT
The port number to connect to.

.SH SEE ALSO
mon(8)
.SH BUGS
Report bugs to the email address below.
.SH AUTHOR
Jim Trocki 
etbemon-1.3.6/doc/monfailures.10000644000000000000000000000211613135637032013216 0ustar  .\"                                      Hey, EMACS: -*- nroff -*-
.\" First parameter, NAME, should be all caps
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
.\" other parameters are allowed: see man(7), man(1)
.TH MONFAILURES 1 "September  4, 2009"
.\" Please adjust this date whenever revising the manpage.
.\"
.\" Some roff macros, for reference:
.\" .nh        disable hyphenation
.\" .hy        enable hyphenation
.\" .ad l      left justify
.\" .ad b      justify to both left and right margins
.\" .nf        disable filling
.\" .fi        enable filling
.\" .br        insert line break
.\" .sp     insert n+1 empty lines
.\" for manpage-specific macros, see man(7)
.SH NAME
monfailures \- Lists mon failures
.SH SYNOPSIS
.B monfailures
.br
.SH DESCRIPTION
.PP
\fBmonfailures\fP is a program that lists the latest mon failures.
.SH SEE ALSO
.BR mon (8),
.BR monshow (1).
.SH AUTHOR
monfailures was written by Dario Minnucci .
.PP
This manual page was written by Dario Minnucci ,
for the Debian project (and may be used by others).

etbemon-1.3.6/doc/monshow.10000644000000000000000000001526110230411543012357 0ustar  .\" $Id: monshow.1,v 1.2 2005/04/17 07:42:27 trockij Exp $
.TH monshow 1 "$Date: 2005/04/17 07:42:27 $" Linux "monshow"
.SH NAME
monshow \- show operational status of mon server.
.SH SYNOPSIS
.B monshow
.RB [ \-\-help ]
.RB [ \-\-showall ]
.RB [ \-\-full ]
.RB [ \-\-disabled ]
.RB [ \-\-detail
.IR group,service ]
.RB [ \-\-view
.IR name ]
.RB [ \-\-auth ]
.RB [ \-\-login
.IR user ]
.RB [ \-\-old ]
.RB [ \-\-server
.IR hostname ]
.RB [ \-\-port
.IR portnum ]
.RB [ \-\-prot
.IR protocol ]
.RB [ \-\-rcfile
.IR file ]
.SH DESCRIPTION
.B monshow
show the operational status of the
.B mon
server. Both command-line and CGI interfaces are available.
.SH OPTIONS
.TP
.B \-\-help
show help
.\"
.\"
.\"
.TP
.B \-\-showall
Do not read configuration file, and show operational status of all groups
and services.
.\"
.\"
.\"
.TP
.B \-\-full
Instead of showing only failed services, show all services no matter the
state.
.\"
.TP
.BI \-\-detail\  group,service
Display detailed information for
.I group
and
.IR service .
This includes description, detailed output of the monitor,
dependency information, and more. When invoked via CGI,
append "detail=group,service" to get detail for a service.
.\"
.TP
.BI "--view " name
Display a pre-configured view. When invoked via CGI, supply
the arguments "view=name" in the URL, or by using this technique:
"http://monhost/monshow.cgi/name". For security reasons,
leading forward slashes and imbedded ".."s are removed from the
view name.
.\"
.TP
.B \-\-auth
Authenticate client to the mon server.
.\"
.\"
.\"
.TP
.B \-\-disabled
Show disabled groups, services, and hosts. The default is to not show
anything which is disabled, but this may be overridden by the config file.
.\"
.\"
.\"
.TP
.BI "--server " hostname
Connect to the mon server on host
.IR hostname .
.I hostname
can be either the name of a host or an IP address.
If this name is not supplied by this argument, then the environment variable
.I MONHOST
is used, if it exists. Otherwise,
.I monshow
will fail.
.\"
.\"
.\"
.TP
.BI \-\-login \ username
When authenticating, use
.IR username .
.\"
.\"
.\"
.TP
.BI \-\-port \ portnum
Connect to the server on
.BR portnum .
.\"
.\"
.\"
.TP
.BI \-\-prot \ protocol
Sets the protocol to
.IR protocol .
The protocol must match the format "1.2.3". If unset, the default
supplied by the Mon::Client module is used. Do not use this parameter
unless you really know what you are doing.
.\"
.\"
.\"
.TP
.B \-\-old
Use the old 0.37 protocol and port number (32777).
.\"
.\"
.\"
.TP
.BI \-\-rcfile \ file
Use configuration file
.I file
instead of ~/.monshowrc.

.SH CGI INVOCATION
If
.B monshow
is invoked with the "REQUEST_METHOD" environment variable
set, then CGI invocation is assumed. In that case,
.B monshow
gathers variables and commands submitted via the
POST method and QUERY_STRING. Command-line options
are ignored for security reasons.

All reports which are produced via the web interface have a text mode
equivalent.

.SH VIEWS

A view is a pre-defined configuration supplied to
.BR monshow .
Views can be used to generate different reports of the status
of certain services for different audiences. They are especially useful
if you are monitoring hundreds of things with mon, and you need to
see only a subset of the overall operational status.
For example, the web server admins can see a report which
has only the web server statuses, and the file server admins can
have their own report which shows only the servers. Users can customize
their own views by editing their own configurations.

Views are stored as files in a system-wide directory, typically
.IR /etc/mon/monshow ,
where each file specifies one view. If this path is not suitable
for any reason, it can be changed by modifying the
.B $VIEWPATH
variable in the
.B monshow
script.

When invoking
.B monshow
from the command line, the view to display is specified by the
.BI "--view=" name
argument. 

In the case of CGI invocation, views can be specified by
appending either
.I "?view=name"
or
.I "/name"
to the URL. For example, the following are equivalent:

.I "http://monhost/monshow.cgi?view=test"
.br
.I "http://monhost/monshow.cgi/test"

If a view is not specified, then a default configuration will be
loaded from
.I "$HOME/.monshowrc"
(command-line invocation) or
.I "cgi-path/.monshowrc"
(CGI invocation).

.SH VIEW CONFIGURATION FILE

The view file contains a list of which services
to display, how to display them, and a number of other parameters.
Blank lines and lines beginning with a # (pound) are ignored.

.TP
.BI "watch" " group"
Include the status of all the services for "group".
.\"
.TP
.BI "service" " group service"
Include the status of the service specified by
.I group
and
.IR service .
.\"
.P
If no
.B watch
or
.B service
configuration lines are present, then the status of all groups
and services are displayed.
.\"
.TP
.B "set show-disabled"
This has the same effect as using
the
.B \-\-disabled
option.
.\"
.TP
.BI "set host" " hostname"
Query the mon server
.IR hostname .
.\"
.TP
.BI "set port" " number"
The TCP port which the mon server is listening on.
.\"
.TP
.BI "set prot" " protocol"
Set the protocol. This probably should not be used unless
you really know what you're doing.
.\"
.TP
.B "set full"
Show everything disabled, all failures, all successes, and all
untested services.
.\"
.TP
.BI "set bg" " color"
Background color for the CGI report. The value of this
parameter should resemble "d5d5d5" (without the quotes).
.\"
.TP
.BI "set bg-ok" " color"
Background color for services which are in an "ok" state.
.\"
.TP
.BI "set bg-fail" " color"
Background color for services which are failing.
.\"
.TP
.BI "set bg-untested" " color"
Background color for services which have yet to be tested.
.\"
.TP
.BI "set refresh" " seconds"
For CGI output, set the frequency that the report reloads.
The default is to not reload.
.\"
.TP
.BI "summary-len" " len"
For CGI output, set the maximum length of the summary output
to display. Summary text which exceeds
.I len
will be truncated and replaced with ellipses.
.\"
.TP
.BI "link" " group service URL"
For the CGI report, make a link to
.I URL
at the bottom of the detail report for
.I "group/service"
for more information.
.\"
.TP
.BI "link-text" " group service"
Insert all HTML up until a line beginning with "END"
after the link specified
with the
.B "link"
setting.
.\"
.TP
.B "set html-header"
Lines after this statement, continuing up until a line beginning
with the word "END" will be displayed after the "" tag
in the CGI output. Use this to display custom headers, including
images and other fancy things.

.SH "ENVIRONMENT VARIABLES"

.IP MONHOST
The hostname of the server which runs the
.B mon
process.

.SH SEE ALSO
mon(8)
.SH BUGS
Report bugs to the email address below.
.SH AUTHOR
Jim Trocki 
etbemon-1.3.6/etc/0000755000000000000000000000000013774327151010625 5ustar  etbemon-1.3.6/etc/auth.cf0000644000000000000000000000174313455575712012111 0ustar  #
# authentication file
#
# entries look like this:
# command: {user|all}[,user...]
#
# THE DEFAULT IT TO DENY ACCESS TO ALL IF THIS FILE
# DOES NOT EXIST, OR IF A COMMAND IS NOT DEFINED HERE
#

#
# command section
#
command section

ack:		AUTH_ANY
checkauth:	all
clear:		AUTH_ANY
disable:	AUTH_ANY
dump:		AUTH_ANY
enable:		AUTH_ANY
get:		AUTH_ANY
list:		all
loadstate:	AUTH_ANY
protid:		all
quit:		all
reload:		AUTH_ANY
reset:		AUTH_ANY
savestate:	AUTH_ANY
servertime:	all
set:		AUTH_ANY
start:		AUTH_ANY
stop:		AUTH_ANY
term:		AUTH_ANY
test:		AUTH_ANY
version:	all

#
# trap section
#
# if no source hosts or users are defined, then do not
# accept traps
#
trap section

#source_host	user	password
#
# allow from user "mon" from any host
# monpassword is an encrypted password from print(crypt($PASS, $SALT));
# 
# * mon monpassword
#
# allow from host 127.0.0.1 without requiring
# a valid username and password
# this only applies if there is no entry for "*" IP address
#
# 127.0.0.1 * *
#
etbemon-1.3.6/etc/example.cf0000644000000000000000000001550210637737260012576 0ustar  #
# Example "mon.cf" configuration for "mon".
#
# $Id: example.cf,v 1.1.1.1.4.1 2007/06/25 13:10:08 trockij Exp $
#

# Please read the mon.8 manual page!
#
# NOTE:
#
# A "watch" definition (a line which begins with the word "watch" and is
# followed by "service" definitions) is terminated by an
# empty line, or by a subsequent definition. You may not put blank lines
# inside of your watch definitions.
#

#
# global options
#
cfbasedir   = /usr/lib/mon/etc
alertdir    = /usr/lib/mon/alert.d
mondir      = /usr/lib/mon/mon.d
maxprocs    = 20
histlength = 100
randstart = 60s

#
# authentication types:
#   getpwnam      standard Unix passwd, NOT for shadow passwords
#   shadow        Unix shadow passwords (not implemented)
#   userfile      "mon" user file
#
authtype = getpwnam

#
# NB:  hostgroup and watch entries are terminated with a blank line (or
# end of file).  Don't forget the blank lines between them or you lose.
#

#
# group definitions (hostnames or IP addresses)
#
hostgroup serversbd1 dns-yp1 foo1 bar1

hostgroup serversbd2 dns-yp2 foo2 bar2 ola3

hostgroup routers cisco7000 linuxrouter agsplus

hostgroup hubs cisco316t hp800t ssii10

hostgroup workstations blue yellow red green cornflower violet

hostgroup netapps f330 f540

hostgroup wwwservers www

hostgroup printers hp5si hp5c hp750c

hostgroup new nntp

hostgroup ftp ftp

#
# For the servers in building 1, monitor ping and telnet
# BOFH is on weekend call :)
#
watch serversbd1
    service ping
	description ping servers in bd1
	interval 5m
	monitor fping.monitor
	period wd {Mon-Fri} hr {7am-10pm}
	    alert mail.alert mis@domain.com
	    alert page.alert mis-pagers@domain.com
	    alertevery 1h
	period NOALERTEVERY: wd {Mon-Fri} hr {7am-10pm}
	    alert mail.alert mis@domain.com
	    alert page.alert mis-pagers@domain.com
	period wd {Sat-Sun}
	    alert mail.alert bofh@domain.com
	    alert page.alert bofh@domain.com
    service telnet
	description telnet to servers in bd1
	interval 10m
	monitor telnet.monitor
	depend serversbd1:ping
	period wd {Mon-Fri} hr {7am-10pm}
	    alertevery 1h
	    alertafter 2 30m
	    alert mail.alert mis@domain.com
	    alert page.alert mis-pagers@domain.com

watch serversbd2
    service ping
	description ping servers in bd2
	interval 5m
	monitor fping.monitor
	depend routers:ping
	period wd {Mon-Fri} hr {7am-10pm}
	    alert mail.alert mis@domain.com
	    alert page.alert mis-pagers@domain.com
	    alertevery 1h
	period wd {Sat-Sun}
	    alert mail.alert bofh@domain.com
	    alert page.alert bofh@domain.com
    service telnet
	description telnet to servers in bd2
	interval 10m
	monitor telnet.monitor
	depend routers:ping serversbd2:ping
	period wd {Mon-Fri} hr {7am-10pm}
	    alertevery 1h
	    alertafter 2 30m
	    alert mail.alert mis@domain.com
	    alert page.alert mis-pagers@domain.com

watch mailhost
    service fping
	period wd {Mon-Fri} hr {7am-10pm}
	    alert mail.alert mis@domain.com
	    alert page.alert mis-pagers@domain.com
	    alertevery 1h
    service telnet
	interval 10m
	monitor telnet.monitor
	period wd {Mon-Fri} hr {7am-10pm}
	    alertevery 1h
	    alertafter 2 30m
	    alert mail.alert mis@domain.com
	    alert page.alert mis-pagers@domain.com
    service smtp
	interval 10m
	monitor smtp.monitor
	period wd {Mon-Fri} hr {7am-10pm}
	    alertevery 1h
	    alertafter 2 30m
	    alert page.alert mis-pagers@domain.com
    service imap
	interval 10m
	monitor imap.monitor
	period wd {Mon-Fri} hr {7am-10pm}
	    alertevery 1h
	    alertafter 2 30m
	    alert page.alert mis-pagers@domain.com
    service pop
	interval 10m
	monitor pop3.monitor
	period wd {Mon-Fri} hr {7am-10pm}
	    alertevery 1h
	    alertafter 2 30m
	    alert page.alert mis-pagers@domain.com

watch wwwservers
    service ping
	interval 2m
	monitor fping.monitor
	allow_empty_group
	period wd {Sun-Sat}
	    alert qpage.alert mis-pagers
	    alertevery 45m
    service http
	interval 4m
	monitor http.monitor
	allow_empty_group
	period wd {Sun-Sat}
	    alert qpage.alert mis-pagers
	    upalert mail.alert -S "web server is back up" mis
	    alertevery 45m
    service telnet
	monitor telnet.monitor
	allow_empty_group
	period wd {Mon-Fri} hr {7am-10pm}
	    alertevery 1h
	    alertafter 2 30m
	    alert mail.alert mis@domain.com
	    alert page.alert mis-pagers@domain.com

#
# If the routers aren't pingable, send a page using
# a phone line and the IXO protocol, which doesn't
# rely on the network. Failure of a router is pretty serious,
# so check every two minutes.
#
# Send out one page every 45 minutes, but log the failure
# to a file every time.
#
watch routers
    service ping
	description routers which connect bd1 and bd2
	interval 1m
	monitor fping.monitor
	period wd {Sun-Sat}
	    alert qpage.alert mis-pagers
	    alertevery 45m
	period LOGFILE: wd {Sun-Sat}
	    alert file.alert -d /usr/lib/mon/log.d routers.log

#
# If mon cannot ping one of the hubs, users will be calling soon
#
watch hubs
    service ping
	interval 1m
	monitor fping.monitor
	period wd {Sun-Sat}
	    alert qpage.alert mis-pagers
	    alertevery 45m

#
# Monitor free disk space on the NFS servers
#
# When space gets below 5 megs, send mail, and delete
# the oldest nightly snapshots.
#
# monitors that terminate with ";;" are not executed with the
# host group appended to the command line
#
watch netapps
    service freespace
    	interval 15m
	monitor freespace.monitor /f330:5000 /f540:5000 ;;
	period wd {Sun-Sat}
	    alert mail.alert mis@domain.com
#	    alert delete.snapshot
	    alertevery 1h

#
# workstations
#
watch workstations
    service ping
	interval 5m
	monitor fping.monitor
	period wd {Sun-Sat}
	    alert mail.alert mis@domain.com
	    alertevery 1h

#
# news server
#
watch news
    service ping
	interval 5m
	monitor fping.monitor
	period wd {Sun-Sat}
	    alert mail.alert mis@domain.com
	    alertevery 1h
    service nntp
	interval 5m
	monitor nntp.monitor
	period wd {Sun-Sat}
	    alert mail.alert mis@domain.com
	    alertevery 1h

#
# HP printers
#
watch printers
    service ping
	interval 5m
	monitor fping.monitor
	period wd {Sun-Sat}
	    alert mail.alert mis@domain.com
	    alertevery 1h
    service hpnp
	interval 5m
	monitor hpnp.monitor
	period wd {Sun-Sat}
	    alert mail.alert mis@domain.com
	    alertevery 1h

#
# FTP server
#
watch ftp
    service ftp
	interval 5m
	monitor ftp.monitor
	period wd {Sun-Sat}
	    alert mail.alert mis@domain.com
	    alertevery 1h

#
# dial-in terminal server
#
watch dialin
    service 555-1212
        interval 60m
        monitor dialin.monitor.wrap -n 555-1212 -t 80 ;;
        period wd {Sun-Sat}
            alert mail.alert mis@domain.com
            upalert mail.alert mis@domain.com
            alertevery 8h
    service 555-1213
        interval 33m
        monitor dialin.monitor.wrap -n 555-1213 -t 80 ;;
        period wd {Sun-Sat}
            alert mail.alert mis@domain.com
            upalert mail.alert mis@domain.com
            alertevery 8h
etbemon-1.3.6/etc/example.m40000644000000000000000000001675410061516616012527 0ustar  dnl
dnl ########################################################################
dnl #          This file is meant to be processed with m4                  #
dnl ########################################################################
dnl
dnl #
dnl # m4 macro definitions
dnl #
dnl
define(_DIR_,           `/usr/lib/mon')dnl
define(_FILE_LOG_DIR_,  `_DIR_/file-log.d')dnl
dnl
dnl #
dnl # useful time periods
dnl #
dnl
define(_FILE_,          `_TST_/log.d')dnl
define(_WEEKDAY_,       `wd {Mon-Fri}')dnl
define(_WEEKEND_,       `wd {Sat-Sun}')dnl
define(_ANYTIME_,       `wd {Sun-Sat}')dnl
define(_OFF_HOURS_,     `wd {Mon-Fri} hr {10pm-7am}, wd {Sat Sun}')dnl
define(_WORK_HOURS_,    `wd {Mon-Fri} hr {7am-10pm}')dnl
define(_PAGING_HOURS_,  `_WORK_HOURS_')dnl
dnl
dnl #
dnl # useful pager aliases
dnl #
dnl
define(_MIS_PAGER_,    `joe bob zoomzip')dnl
dnl
dnl #
dnl # useful mail aliases
dnl #
dnl
define(_MIS_EMAIL_,       `joe bob zoomzip')dnl
define(_PRINTER_EMAIL_,   `zoomzip')dnl       # facilities are responsible for
dnl                                           # printer maintenance
define(_RAS_EMAIL_,       `bob')dnl           # bob is the remote access admin
dnl
dnl #
dnl # -------------------------actual config begins here-------------------------
dnl #
#
# Example "mon.cf" configuration for "mon".
#
# $Id: example.m4,v 1.1.1.1 2004/06/09 05:18:06 trockij Exp $
#
#
# This works with 0.38pre13
#

#
# global options
#
cfbasedir   = _DIR_/etc
alertdir    = _DIR_/alert.d
mondir      = _DIR_/mon.d
maxprocs    = 20
histlength  = 100
randstart   = 60s

#
# authentication types:
#   getpwnam      standard Unix passwd, NOT for shadow passwords
#   shadow        Unix shadow passwords (not implemented)
#   userfile      "mon" user file
#
authtype = getpwnam

#
# NB:  hostgroup and watch entries are terminated with a blank line (or
# end of file).  Don't forget the blank lines between them or you lose.
#

#
# group definitions (hostnames or IP addresses)
#
hostgroup serversbd1 dns-yp1 foo1 bar1

hostgroup serversbd2 dns-yp2 foo2 bar2 ola3

hostgroup routers cisco7000 linuxrouter agsplus

hostgroup hubs cisco316t hp800t ssii10

hostgroup workstations blue yellow red green cornflower violet

hostgroup netapps f330 f540

hostgroup wwwservers www

hostgroup printers hp5si hp5c hp750c

hostgroup new nntp

hostgroup ftp ftp

#
# For the servers in building 1, monitor ping and telnet
# BOFH is on weekend call :)
#
watch serversbd1
    service ping
	description ping servers in bd1
	interval 5m
	monitor fping.monitor
	period _WORK_HOURS_
	    alert mail.alert _MIS_EMAIL_
	    alertevery 1h
	period PAGE: _PAGING_HOURS_
	    alert qpage.alert _MIS_PAGER_
	    alertevery 2h
	period _WEEKEND_
	    alert mail.alert bofh@domain.com
	    alert qpage.alert bofh@domain.com
	    alertevery 1h
    service telnet
	description telnet to servers in bd1
	interval 10m
	monitor telnet.monitor
	depend serversbd1:ping
	period _WORK_HOURS_
	    alertevery 1h
	    alertafter 2 30m
	    alert mail.alert _MIS_EMAIL_
	period PAGE: _PAGING_HOURS_
	    alert qpage.alert _MIS_PAGER_
	    alertevery 2h

watch serversbd2
    service ping
	description ping servers in bd2
	interval 5m
	monitor fping.monitor
	depend routers:ping
	period _WORK_HOURS_
	    alert mail.alert _MIS_EMAIL_
	    alertevery 1h
	period _WEEKEND_
	    alert mail.alert bofh@domain.com
	    alert qpage.alert bofh@domain.com
    service telnet
	description telnet to servers in bd2
	interval 10m
	monitor telnet.monitor
	depend routers:ping serversbd2:ping
	period _WORK_HOURS_
	    alertevery 1h
	    alertafter 2 30m
	    alert mail.alert _MIS_EMAIL_
	period PAGE: _PAGING_HOURS_
	    alert qpage.alert _MIS_PAGER_
	    alertevery 2h

watch mailhost
    service fping
	period _WORK_HOURS_
	    alert mail.alert _MIS_EMAIL_
	    alert qpage.alert _MIS_PAGER_
	    alertevery 1h
    service telnet
	interval 10m
	monitor telnet.monitor
	period _WORK_HOURS_
	    alertevery 1h
	    alertafter 2 30m
	    alert mail.alert _MIS_EMAIL_
	    alert qpage.alert _MIS_PAGER_
    service smtp
	interval 10m
	monitor smtp.monitor
	period _WORK_HOURS_
	    alertevery 1h
	    alertafter 2 30m
	    alert qpage.alert _MIS_PAGER_
    service imap
	interval 10m
	monitor imap.monitor
	period _WORK_HOURS_
	    alertevery 1h
	    alertafter 2 30m
	    alert qpage.alert _MIS_PAGER_
    service pop
	interval 10m
	monitor pop3.monitor
	period _WORK_HOURS_
	    alertevery 1h
	    alertafter 2 30m
	    alert qpage.alert _MIS_PAGER_

watch wwwservers
    service ping
	interval 2m
	monitor fping.monitor
	allow_empty_group
	period _ANYTIME_
	    alert qpage.alert _MIS_PAGER_
	    alertevery 45m
    service http
	interval 4m
	monitor http.monitor
	allow_empty_group
	period _ANYTIME_
	    alert qpage.alert _MIS_PAGER_
	    upalert mail.alert -S "web server is back up" _MIS_EMAIL_
	    alertevery 45m
    service telnet
	monitor telnet.monitor
	allow_empty_group
	period _WORK_HOURS_
	    alertevery 1h
	    alertafter 2 30m
	    alert mail.alert _MIS_EMAIL_
	    alert qpage.alert _MIS_PAGER_

#
# If the routers aren't pingable, send a page using
# a phone line and the IXO protocol, which doesn't
# rely on the network. Failure of a router is pretty serious,
# so check every two minutes.
#
# Send out one page every 45 minutes, but log the failure
# to a file every time.
#
watch routers
    service ping
	description routers which connect bd1 and bd2
	interval 1m
	monitor fping.monitor
	period _ANYTIME_
	    alert qpage.alert _MIS_PAGER_
	    alertevery 45m
	period LOGFILE: _ANYTIME_
	    alert file.alert -d _FILE_LOG_DIR_ routers.log ;;

#
# If mon cannot ping one of the hubs, users will be calling soon
#
watch hubs
    service ping
	interval 1m
	monitor fping.monitor
	period _ANYTIME_
	    alert qpage.alert _MIS_PAGER_
	    alertevery 45m

#
# Monitor free disk space on the NFS servers
#
# When space gets below 5 megs, send mail, and delete
# the oldest nightly snapshots.
#
# monitors that terminate with ";;" are not executed with the
# host group appended to the command line
#
watch netapps
    service freespace
    	interval 15m
	monitor freespace.monitor /f330:5000 /f540:5000 ;;
	period _ANYTIME_
	    alert mail.alert _MIS_EMAIL_
#	    alert delete.snapshot
	    alertevery 1h

#
# workstations
#
watch workstations
    service ping
	interval 5m
	monitor fping.monitor
	period _ANYTIME_
	    alert mail.alert _MIS_EMAIL_
	    alertevery 1h

#
# news server
#
watch news
    service ping
	interval 5m
	monitor fping.monitor
	period _ANYTIME_
	    alert mail.alert _MIS_EMAIL_
	    alertevery 1h
    service nntp
	interval 5m
	monitor nntp.monitor
	period _ANYTIME_
	    alert mail.alert _MIS_EMAIL_
	    alertevery 1h

#
# HP printers
#
watch printers
    service ping
	interval 5m
	monitor fping.monitor
	period _ANYTIME_
	    alert mail.alert _PRINTER_EMAIL_
	    alertevery 1h
    service hpnp
	interval 5m
	monitor hpnp.monitor
	period wd {Sun-Sat}
	    alert mail.alert _PRINTER_EMAIL_
	    alertevery 1h

#
# FTP server
#
watch ftp
    service ftp
	interval 5m
	monitor ftp.monitor
	period _ANYTIME_
	    alert mail.alert _MIS_EMAIL_
	    alertevery 1h

#
# dial-in terminal server
#
watch dialin
    service 555-1212
        interval 60m
        monitor dialin.monitor.wrap -n 555-1212 -t 80 ;;
        period _ANYTIME_
            alert mail.alert _RAS_EMAIL_
            upalert mail.alert _RAS_EMAIL_
            alertevery 8h
    service 555-1213
        interval 33m
        monitor dialin.monitor.wrap -n 555-1213 -t 80 ;;
        period wd {Sun-Sat}
            alert mail.alert _RAS_EMAIL_
            upalert mail.alert _RAS_EMAIL_
            alertevery 8h
etbemon-1.3.6/etc/example.monshowrc0000644000000000000000000000205410061516616014212 0ustar  #
# Configuration for monshow
#
# Place this file in one of the following places:
#         $HOME/.monshowrc
#         cgi-bin/.monshowrc
#
# /etc/mon/monshowrc will be overridden if any of the others
# exist.
#
# $Id: example.monshowrc,v 1.1.1.1 2004/06/09 05:18:06 trockij Exp $
#

# mon server and port
set host monhost
set port 2583
#set prot

# disabled groups/services/hosts
set show-disabled

# show all statuses instead of just failures
set full

# refresh web page every 5 minutes
#set refresh 30

#
# row colors for CGI, these are the defaults
#
set table-color cccccc
set bg-ok	a0d0a0
set bg-fail	e088b7
set bg-untested	e0e0e0

#
# HTML header
#
set html-header

This is the custom HTML header

END # # footer for detail report # link bd2 ping http://monhost/detail-bd2-ping.html link-text bd2 ping This is detail about bd2 ping which is probably data collected from some other non-mon source. END # # show only these services. if none of these # are listed, show all groups and services # #watch serversbd1 #watch serversbd2 #service news nntp etbemon-1.3.6/etc/init.d/0000755000000000000000000000000014014617564012010 5ustar etbemon-1.3.6/etc/init.d/mon0000644000000000000000000002101413120440134012502 0ustar #!/bin/sh # ### BEGIN INIT INFO # Provides: mon # Required-Start: $remote_fs $syslog # Required-Stop: $remote_fs $syslog # Should-Start: $local_fs # Should-Stop: $local_fs # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: monitor hosts/services/whatever and alert about problems # Description: "mon" is a tool for monitoring the availability of services. Services # may be network-related, environmental conditions, or anything that can # be tested with software. If a service is unavailable mon can tell you # with syslog, email, your pager or a script of your choice. You can # control who gets each alert based on the time of day or day of week, # and you can control how often an existing problem is re-alerted. ### END INIT INFO PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin DAEMON=/usr/sbin/mon # Introduce the server's location here NAME=mon DESC="mon daemon" LOGDIR=/var/log/mon # Log directory to use PIDFILE=/run/mon/$NAME.pid test -x $DAEMON || exit 0 . /lib/lsb/init-functions # Default options, these can be overriden by the information # at /etc/default/$NAME DAEMON_OPTS="" # Additional options given to the server DIETIME=1 # Time to wait for the server to die, in seconds # If this value is set too low you might not # let some servers to die gracefully and # 'restart' will not work STARTTIME=1 # Time to wait for the server to start, in seconds # If this value is set each time the server is # started (on start or restart) the script will # stall to try to determine if it is running # If it is not set and the server takes time # to setup a pid file the log message might # be a false positive (says it did not start # when it actually did) LOGFILE=$LOGDIR/$NAME.log # Server logfile DAEMONUSER=mon # Users to run the daemons as. If this value # is set start-stop-daemon will chuid the server # Include defaults if available if [ -f /etc/default/$NAME ] ; then . /etc/default/$NAME fi # Check that the user exists (if we set a user) # Does the user exist? if [ -n "$DAEMONUSER" ] ; then if getent passwd | grep -q "^$DAEMONUSER:"; then # Obtain the uid and gid DAEMONUID=`getent passwd |grep "^$DAEMONUSER:" | awk -F : '{print $3}'` DAEMONGID=`getent passwd |grep "^$DAEMONUSER:" | awk -F : '{print $4}'` else log_failure_msg "The user $DAEMONUSER, required to run $NAME does not exist." exit 1 fi fi set -e running_pid() { # Check if a given process pid's cmdline matches a given name pid=$1 name=$2 [ -z "$pid" ] && return 1 [ ! -d /proc/$pid ] && return 1 cmd=`cat /proc/$pid/cmdline | tr "\000" "\n"|head -n 1 |cut -d : -f 1` # Is this the expected server # [ "$cmd" != "/usr/bin/perl $name" ] && return 1 return 0 } running() { # Check if the process is running looking at /proc # (works for all users) # No pidfile, probably no daemon present [ ! -f "$PIDFILE" ] && return 1 pid=`cat $PIDFILE` running_pid $pid $DAEMON || return 1 return 0 } start_server() { # Start the process using the wrapper # # Create /run/mon if does not exists # if [ ! -d "/run/mon" ] ; then mkdir -p /run/mon chown mon:mon /run/mon [ -x /sbin/restorecon ] && /sbin/restorecon /run/mon fi start-stop-daemon --start --quiet --pidfile $PIDFILE \ --chuid $DAEMONUSER \ --startas $DAEMON \ -- $DAEMON_OPTS errcode=$? return $errcode } stop_server() { # Stop the process using the wrapper start-stop-daemon --stop --quiet --pidfile $PIDFILE \ --user $DAEMONUSER \ --exec /usr/bin/perl errcode=$? # # Remove /run/mon when daemon is stopped # if [ -d /run/mon ] ; then rmdir --ignore-fail-on-non-empty /run/mon fi return $errcode } reload_server() { [ ! -f "$PIDFILE" ] && return 1 pid=pidofproc $PIDFILE # This is the daemon's pid # Send a SIGHUP kill -1 $pid return $? } force_stop() { # Force the process to die killing it manually [ ! -e "$PIDFILE" ] && return if running ; then kill -15 $pid # Is it really dead? sleep "$DIETIME"s if running ; then kill -9 $pid sleep "$DIETIME"s if running ; then echo "Cannot kill $NAME (pid=$pid)!" exit 1 fi fi fi rm -f $PIDFILE } check_directive() { # # Check directive status in /etc/default/mon # if [ $1 != "yes" ] && [ $1 != "true" ] && [ $1 != "1" ] then log_failure_msg "mon is disabled, set ENABLED to \"yes\", \"true\" or \"1\" in /etc/default/mon to enable it." exit 0 fi } case "$1" in start) check_directive $ENABLED log_daemon_msg "Starting $DESC " "$NAME" # Check if it's running first if running ; then log_progress_msg "apparently already running" log_end_msg 0 exit 0 fi if start_server ; then # NOTE: Some servers might die some time after they start, # this code will detect this issue if STARTTIME is set # to a reasonable value [ -n "$STARTTIME" ] && sleep $STARTTIME # Wait some time if running ; then # It's ok, the server started and is running log_end_msg 0 else # It is not running after we did start log_end_msg 1 fi else # Either we could not start it log_end_msg 1 fi ;; stop) log_daemon_msg "Stopping $DESC" "$NAME" if running ; then # Only stop the server if we see it running errcode=0 stop_server || errcode=$? log_end_msg $errcode else # If it's not running don't do anything log_progress_msg "apparently not running" log_end_msg 0 exit 0 fi ;; force-stop) # First try to stop gracefully the program $0 stop if running; then # If it's still running try to kill it more forcefully log_daemon_msg "Stopping (force) $DESC" "$NAME" errcode=0 force_stop || errcode=$? log_end_msg $errcode fi ;; restart|force-reload) check_directive $ENABLED log_daemon_msg "Restarting $DESC" "$NAME" errcode=0 stop_server || errcode=$? # Wait some sensible amount, some server need this [ -n "$DIETIME" ] && sleep $DIETIME start_server || errcode=$? [ -n "$STARTTIME" ] && sleep $STARTTIME running || errcode=$? log_end_msg $errcode ;; status) log_daemon_msg "Checking status of $DESC" "$NAME" if running ; then log_progress_msg "running" log_end_msg 0 else log_progress_msg "apparently not running" log_end_msg 1 exit 1 fi ;; # Use this if the daemon cannot reload reload) log_warning_msg "Reloading $NAME daemon: not implemented, as the daemon" log_warning_msg "cannot re-read the config file (use restart)." ;; # And this if it cann #reload) # # If the daemon can reload its config files on the fly # for example by sending it SIGHUP, do it here. # # If the daemon responds to changes in its config file # directly anyway, make this a do-nothing entry. # # log_daemon_msg "Reloading $DESC configuration files" "$NAME" # if running ; then # reload_server # if ! running ; then # Process died after we tried to reload # log_progress_msg "died on reload" # log_end_msg 1 # exit 1 # fi # else # log_progress_msg "server is not running" # log_end_msg 1 # exit 1 # fi #;; *) N=/etc/init.d/$NAME echo "Usage: $N {start|stop|force-stop|restart|force-reload|status}" >&2 exit 1 ;; esac exit 0 etbemon-1.3.6/etc/mon.cf0000644000000000000000000000402113663342633011724 0ustar # # Example mon.cf file # # Author: Dario Minnucci # Date: Mon, 07 Sep 2009 13:57:38 +0200 # # # Global options # alertdir = /usr/lib/mon/alert.d mondir = /usr/lib/mon/mon.d:/usr/lib/mon/mon-local.d logdir = /var/log/mon statedir = /var/lib/mon cfbasedir = /etc/mon historicfile = /var/log/mon/history.log authfile = /etc/mon/auth.cf maxprocs = 20 histlength = 100 randstart = 60s dtlogging = yes dtlogfile = dtlog # tcp bind for mon client protocol (monshow etc) serverbind = 127.0.0.1 # udp bind for traps trapbind = 127.0.0.1 clientallow = 127.0.0.1 # # Define groups of hosts to monitor # hostgroup localhost localhost # # Define watches # watch localhost # example trap service for traps from other systems service trap description trap traptimeout 10m trapduration 60m period alert mail.alert root@localhost upalert mail.alert root@localhost service ping description Responses to ping interval 5m monitor fping.monitor period wd {Mon-Fri} hr {7am-10pm} alert mail.alert root@localhost alertevery 1h period wd {Sat-Sun} alert mail.alert root@localhost service http description HTTP service interval 10m monitor http.monitor period numalerts 10 alert mail.alert root@localhost upalert mail.alert root@localhost service smtp description SMTP service interval 10m monitor smtp.monitor -t 60 period numalerts 10 alert mail.alert root@localhost upalert mail.alert root@localhost # service pop3 # description POP3 service # interval 10m # monitor pop3.monitor # period # numalerts 10 # alert mail.alert root@localhost # upalert mail.alert root@localhost # service imap # description IMAP service # interval 10m # monitor imap.monitor -t 60 # period # numalerts 10 # alert mail.alert root@localhost # upalert mail.alert root@localhost # service telnet # description TELNET service # interval 10m # monitor telnet.monitor # period wd {Mon-Fri} hr {7am-10pm} # alertevery 1h # alertafter 2 30m # alert mail.alert root@localhost etbemon-1.3.6/etc/mon.cgi.cf0000644000000000000000000000657310146140376012474 0ustar # # The mon.cgi config file. # Format: # key = value # # Blank lines and lines that begin with '#' are ignored. # # Both key names and values are case sensitive. # # This file comes with the mon.cgi distribution and contains all of the # valid key/value pairs that mon.cgi will accept. # # The latest version of mon.cgi is always available at: # http://www.nam-shub.com/files/ # # If there are errors in your config file, mon.cgi will stop parsing it, # and will print messages to STDERR, which should end up in your web # server's error log. # # $Id: mon.cgi.cf,v 1.2 2004/11/15 14:45:18 vitroth Exp $ # # Your organization (what you want printed on the top of each page) organization = Network Operations # Contact email for mon administrator at your site monadmin = bofh@your.domain #Company or mon logo (URL path) logo = /URL-path/to/your.gif # URL to go to when you click on the logo image logo_link = http://www.kernel.org/pub/software/admin/mon/html/ # Seconds between page reload reload_time = 180 # Where to run mon (host,port) monhost = localhost monport = 2583 # Set this to anything other than 'Y' or 'yes' to turn off authentication # (HINT: authentication is a *good* thing) must_login = yes # Application secret. Set this to something long and unguessable. app_secret = LKAHETOI#KJHJKSHDOWOIUW^*((985i2hkljlkjfdhglkdhfgdlkfjghldksfjhg98 34tklh qrthq3 i3lu4 KLHKLJHKLJH ncxmvn owow y YnneO87210502673kn6l3 # Default username and password (only used if must_login is set) default_username = readonly default_password = public # Idle time, in seconds, until login cookie is invalidated. Note that if # ( login_expire_time < reload_time ) you will not be able to "idle". login_expire_time = 900 # Whether or not to untaint HTML in ack msgs using HTML::Entities (recommended) untaint_ack_msgs = yes # The name of the cookie set by mon.cgi and its path cookie_name = mon-cookie cookie_path = / # Default alternate fonts to use (assumes default font is a serif font) fixed_font_face = courier sans_serif_font_face = Helvetica, Arial # Default color scheme for page BGCOLOR = black TEXTCOLOR = white LINKCOLOR = yellow VLINKCOLOR = #00FFFF # Default colors for failed services greenlight_color = #009900 redlight_color = red unchecked_color = #000033 yellowlight_color = #FF9933 # # A white-background look for mon.cgi, from Thomas Bates # #BGCOLOR = #FFFFFF #TEXTCOLOR = #000000 #LINKCOLOR = 0000FF #VLINKCOLOR = #551a8b # #greenlight_color=#a0d0a0 #redlight_color=ff6060 #unchecked_color=f0f0f0 #disabled_color=#e0e0e0 #yellowlight_color = #FFAF4F # Maximum number of downtime events to show, per page dtlog_max_failures_per_page = 100 # Watch keywords will show only the specified hostgroups by default. # Matching is by regexp. # e.g., show the watch whose name is www #watch = www # e.g., show any watches whose names start with gw- #watch = gw-.* # Set show_watch_strict to 'yes' if you want to be sure that users only # information about the hostgroups that they are authorized to # view. If show_watch_strict is set to 1, as far as your GUI users # will know, there is nothing else running on the mon instance # except for their hostgroups, *even if those users know the names # of other hostgroups on your mon server*. # # Set to show_watch_strict to 'no' to show only the defined watch # groups by default, but allow users to see information about # others as well. show_watch_strict = no etbemon-1.3.6/etc/monshowrc0000644000000000000000000000161112355124105012552 0ustar # # Initial .monshowrc file # # /etc/mon/monshowrc will be overridden if any of the others # exist. # # mon server and port #set host monhost set port 2583 #set prot # disabled groups/services/hosts set show-disabled # show all statuses instead of just failures set full # refresh web page every 5 minutes set refresh 60 # # row colors for CGI, these are the defaults # set table-color cccccc set bg-ok a0d0a0 set bg-fail e088b7 set bg-untested e0e0e0 # # HTML header # set html-header

Debian GNU/Linux

END # # footer for detail report # #link bd2 ping http://monhost/detail-bd2-ping.html #link-text bd2 ping #This is detail about bd2 ping which is probably data #collected from some other non-mon source. #END # # show only these services. if none of these # are listed, show all groups and services # #watch serversbd1 #watch serversbd2 #service news nntp etbemon-1.3.6/etc/na_quota.cf0000644000000000000000000000045310061516616012740 0ustar # # # filer uranium tree /home kb_warn 10kb kb_emerg 5kb file_warn 200 file_emerg 50 tree /project-mis kb_warn 10kb kb_emerg 5kb file_warn 200 file_emerg 50 user trockij kb_warn 5gb kb_emerg 1gb file_warn 250 file_emerg 100 filer plutonium tree /project kb_warn 50kb etbemon-1.3.6/etc/netappfree.cf0000644000000000000000000000133110061516616013256 0ustar # # netappfree.cf- configuration file for netappfree.monitor # # format: # # host filesys free # # host hostname of the netapp, should correspond with a host # defined in the netapp host group # # filesys The filesystem to check, as represented in netapp.mib. # For ONTAP 5.*, resembles "/vol/vol0/" or "/vol/vol0/.snapshot" # For ONTAP 4.3.4, resembles "active" or "snapshot" # For ONTAP 4.3.1, resembles "/" or "/.snapshot" # # free The amount of free space which will trigger a failure, # expressed as "10kb", "10MB", or "10GB" # # $Id: netappfree.cf,v 1.1.1.1 2004/06/09 05:18:06 trockij Exp $ # f330 / 4GB f540 active 4GB f630 /vol/vol0/ 4GB pu / 4gb np active 25gb etbemon-1.3.6/etc/snmpdiskspace.cf0000644000000000000000000000445610616216722014005 0ustar # # snmpdiskspace.cf- configuration file for snmpdiskspace.monitor # $Id: snmpdiskspace.cf,v 1.1.2.1 2007/05/02 23:25:06 trockij Exp $ # # format: # # host filesys free ifree # # The monitor script uses a "first match" algorithm. So put your more # specific directives at top, and leave the more general directives # for the bottom. # # # host Regex describing the name of the host(s). Remember to escape # dots if you're fully qualifying hostnames, e.g., # some\.domain\.com, otherwise you might not be matching what # you think you're matching. # # filesys Regex describing the filesystem to check, as represented # in the relevant mib (after mangling by the monitor). # Remember to use regex syntax, and not file glob syntax. # # free The amount of free space which will trigger a failure, # expressed as "10", "10kb", "10MB", or "10GB" for # bytes, kilobytes, megabytes or gigabytes. The format # "10%" signifies percent of the total disk space. # "0" turns of checking for the filesystem/disk. # # ifree Percentage of free inodes, below which will trigger a failure. # Expressed as "5%". The host must support the UCD dskTable MIB. # # # BE SURE TO TEST your configuration with the "--listall" option! # This way, you will see exactly what filesystems are found by the script, # and what their alarm thresholds will be. # # Examples: # * * 5% # Give a warning when the free space goes below 5 % # (This is the default behavior of the monitor) # This should always be the last line in your config file # because it will match everything. # # * * 5% 10% # As above, but also warn if free inodes drops below 10%. # # ior * 15% # On the host ior the limit is 15% # # poo / 1gb # poo's root should have a full gig free # # www[1-4] * 500mb # any partition on the machines www1, www2, www3, and ww4 # should have at least 500mb free. # # * /cdrom/.* 0 # anything that is mounted on /cdrom will be full anyway # At least for Solaris, you need a regex like this bec. # vold mounts each new CD on a new partition, and you # won't know its name until you put it into the drive. # # # Always ignore anything on cdrom partitions * /cdrom.* 0 * /mnt 0 # # # This line always should be last because it matches everything. * * 5% etbemon-1.3.6/etc/snmpopt.cf0000644000000000000000000000066410146140376012635 0ustar # # snmpopt.cf # # This optional file is used to pass parameters to the SNMP library, # used by snmpvar.monitor. # # (default values shown) # common options # Version = 1 # Port = 161 # Retries = 8 # Timeout = 5 # SNMPv1/v2 options # Community = public # SNMPv3 options # SecName = initial # SecLevel = noAuthNoPriv # AuthPass = # SecEngineId = # ContextEngineId = # Context # AuthProto = MD5 # PrivProto = DES # PrivPass = etbemon-1.3.6/etc/snmpvar.cf0000644000000000000000000000610410146140376012616 0ustar # # snmpvar.cf # # this is a sample configuration file for snmpvar.monitor. you # must configure this to meet your own needs. # # list of variables and ranges to be monitored by snmpvar.monitor # refers to variables defined in snmpvar.def # # a Dell server, RAID instrumentation only: Host nov-1 MEGARAID0_LOGICAL_STATUS Min 2 Max 2 Index 0 MEGARAID0_PHYS_STATUS Min 3 Max 3 Index 0 1 2 3 4 5 # a Compaq server: Host nov-2 # has 1 RAID volume, 6 physical disks CPQARRAY_LOG_STATUS Index 1 CPQARRAY_PHYS_STATUS Index 0 1 2 3 4 5 PROLIANT_TEMP_STATUS PROLIANT_PSU_STATUS PROLIANT_FAN_STATUS Index 2 4 5 # a Dell server running NT 4 with perfmib Host ntserv1 WINNT_MEM_COMMITTED Max 700 WINNT_LOGICAL_C_FREE Min 50 WINNT_LOGICAL_D_FREE Min 50 MEGARAID_C0_LOGICAL_STATUS Index 0 MEGARAID_C0_CH0_PHYS_STATUS Index 0 1 2 3 4 PE4300_TEMP_CPU PE4300_TEMP PE4300_5V_CURRENT PE4300_12V_CURRENT PE4300_3V_CURRENT PE4300_FAN_CPU_RPM PE4300_FAN_DISK_RPM PE4X00_PSU_STATUS # an APC UPS (with SNMP adapter or through controlling server running PowerNet) Host srvups1 APCUPS_OUTPUT_STAT APCUPS_LINEVOLT_MAX APCUPS_LINEVOLT_MIN # here, we override the default maximum specified in snmpvar.def: APCUPS_LOAD Max 75 APCUPS_BATT_TEMP # these are the MeasureUPS parameters (external sensor) APCUPS_EXT_TEMP Max 32 APCUPS_EXT_HUMID Min 10 Max 90 APCUPS_EXT_SWITCH_STAT Min 2 Max 2 Index 1 FriendlyName 1 Diesel Generator Status # an HP ProCurve 4000 switch Host hp4000-servers HP_ICF_FAN_STATE # has redundant PSU HP_ICF_PSU_STATE Index 2 3 IF_OPERSTAT Index 1 3 17 25 65 73 FriendlyName 1 A1: Server LAUREL FriendlyName 3 A3: Server HARDY FriendlyName 17 C1: Server TITAN (1000SX) FriendlyName 25 D1: Server MERCURY (1000SX) FriendlyName 65 I1: Switch D1017:G1 (1000TX) FriendlyName 73 J1: Switch SERVERS1:H1 (1000SX) # an IBM8272 Token Ring switch Host trsw1 IBM8272_LINK_STATE Min 1 Max 1 Index 1 2 3 4 5 6 7 9 11 12 13 14 15 16 17 18 21 22 23 24 FriendlyName 1 1: Floor 10 Ring FriendlyName 2 2: Floor 12 Ring FriendlyName 3 3: Floor 13 Ring FriendlyName 9 9: Server NOV-1 FriendlyName 13 13: Server ntserv1 FriendlyName 18 18: Switch 2 Interlink Fibre IBM8272_TEMP_SYS Min 1 Max 1 # a cisco router Host cisco1 IF_OPERSTAT Index 1 2 3 4 FriendlyName 1 1: Internal Ethernet FriendlyName 2 2: Internal TokenRing FriendlyName 3 3: Firewall BGP_PEERSTATE Index 10.1.1.1 10.2.1.1 FriendlyName 10.1.1.1 iBGP Session: myotherrouter FriendlyName 10.2.1.1 eBGP Session: Provider X CISCO_TEMP_STATE # a Nokia IP series firewall appliance Host firewall IF_OPERSTAT Index 1 2 3 FriendlyName 1 1: Leased Line FriendlyName 2 2: DMZ FriendlyName 3 3: Internal Router NOKIA_IP_CHASSIS_TEMP NOKIA_IP_FAN_STAT NOKIA_IP_PSU_STAT NOKIA_IP_PSU_TEMP # a Linux server with some private SNMP extensions Host mailserver LINUX_MAILQUEUE Max 80 etbemon-1.3.6/etc/snmpvar.def0000644000000000000000000003713110146140376012770 0ustar # # sample snmpvar.def. you should configure this to meet your # own needs. # # Definitions of variables to be monitored using snmpvar.monitor # # # generic host (router/switch/...) Variable IF_OPERSTAT OID .1.3.6.1.2.1.2.2.1.8 Description ifOperStatus DefaultEQ 1 Decode 1 up Decode 2 down Decode 3 testing Decode 4 unknown Decode 5 dormant # generic router Variable BGP_PEERSTATE OID .1.3.6.1.2.1.15.3.1.2 Description bgpPeerState DefaultEQ 6 Decode 1 idle Decode 2 connect Decode 3 active Decode 4 opensent Decode 5 openconfirm Decode 6 established # generic Host Resources MIB implementation Variable HR_DEVICE_STATUS OID .1.3.6.1.2.1.25.3.2.1.5. Description Device Status DefaultEQ 2 Decode 1 unknown Decode 2 running Decode 3 warning Decode 4 testing Decode 5 down # some variables from a Windows NT "perfmib" configuration # see ms-perfmib directory for NT side configuration Variable WINNT_CPU_TOTAL OID .1.3.6.1.4.1.311.1.1.3.1.1.1.9.0 Description CPU Load Total Unit % Variable WINNT_CPU_SYS OID .1.3.6.1.4.1.311.1.1.3.1.1.1.11.0 Description CPU Load System Unit % Variable WINNT_MEM_COMMITTED OID .1.3.6.1.4.1.311.1.1.3.1.1.2.2.0 Description Committed Memory Scale / 1024 / 1024 # the Scale expression is used as (eval($rawval . $scale)) Unit MB Variable WINNT_MEM_AVAILABLE OID .1.3.6.1.4.1.311.1.1.3.1.1.2.1.0 Description Available Memory Scale / 1024 /1024 Unit MB Variable WINNT_LOGICAL_C_FREE OID .1.3.6.1.4.1.311.1.1.3.1.1.6.1.4.6.48.58.48.58.67.58 Description Free Disk Space on drive C Unit MB Variable WINNT_LOGICAL_D_FREE OID .1.3.6.1.4.1.311.1.1.3.1.1.6.1.4.6.48.58.48.58.68.58 Description Free Disk Space on drive D Unit MB # Dell PowerEdge 2550 Server Instrumentation Variable PE2550_FAN_SYS_RPM OID .1.3.6.1.4.1.674.10892.1.700.12.1.6.1. Description System Fan Speed DefaultIndex 1 2 3 Unit rpm DefaultMin 600 DefaultMax 6000 DefaultMaxValid 10000 DefaultGroup Environment Variable PE2550_FAN_DISK_RPM OID .1.3.6.1.4.1.674.10892.1.700.12.1.6.1.4 Description Disk Fan Speed Unit rpm DefaultMin 6000 DefaultMax 14000 DefaultMaxValid 15000 DefaultGroup Environment Variable PE2550_TEMP_CPU OID .1.3.6.1.4.1.674.10892.1.700.20.1.6.1. Description CPU Temperature DefaultIndex 1 2 Unit C Scale / 10.0 DefaultMax 50 DefaultGroup Environment Variable PE2550_TEMP OID .1.3.6.1.4.1.674.10892.1.700.20.1.6.1. Description Temperature DefaultIndex 3 4 5 FriendlyName 3 Motherboard FriendlyName 4 Backplane 1 FriendlyName 5 Backplane 2 Unit C Scale / 10.0 DefaultMax 40 DefaultGroup Environment Variable PE2550_PSU_STATUS DefaultIndex 1 2 OID .1.3.6.1.4.1.674.10892.1.600.12.1.5.1. Description Power Supply Status DefaultEQ 3 Decode 1 other Decode 2 unknown Decode 3 OK Decode 4 noncrit Decode 5 critical Decode 6 nonrecoverable DefaultGroup Power # Dell PowerEdge 4300 Server Instrumentation Variable PE4300_TEMP_CPU OID .1.3.6.1.4.1.674.10891.300.1.5.2.2.1. Description CPU Temperature DefaultIndex 1 2 Scale / 10.0 Unit C DefaultMax 40 DefaultGroup Environment Variable PE4300_TEMP OID .1.3.6.1.4.1.674.10891.300.1.5.2.2.1. Description Temperature DefaultIndex 3 4 5 6 FriendlyName 3 @Motherboard FriendlyName 4 @Ambient FriendlyName 5 @Backplane 1 FriendlyName 6 @Backplane 2 Scale / 10.0 Unit C DefaultMax 40 DefaultGroup Environment Variable PE4300_5V_CURRENT OID .1.3.6.1.4.1.674.10891.303.1.5.2.5.1. Description DC Current (+5V) DefaultIndex 1 4 7 Scale / 1000.0 Unit A DefaultMax 25 DefaultMaxValid 100 DefaultGroup Power Variable PE4300_12V_CURRENT OID .1.3.6.1.4.1.674.10891.303.1.5.2.5.1. Description DC Current (+12V) DefaultIndex 2 5 8 Scale / 1000.0 Unit A DefaultMax 10 DefaultMaxValid 100 DefaultGroup Power Variable PE4300_3V_CURRENT OID .1.3.6.1.4.1.674.10891.303.1.5.2.5.1. Description DC Current (+3V) DefaultIndex 3 6 9 Scale / 1000.0 Unit A DefaultMax 10 DefaultMaxValid 100 DefaultGroup Power Variable PE4300_FAN_CPU_RPM OID .1.3.6.1.4.1.674.10891.301.1.5.2.3.1. Description CPU Fan Speed Unit rpm DefaultIndex 1 2 DefaultMin 1000 DefaultMax 5000 DefaultMaxValid 10000 DefaultGroup Environment # really the same as above, other index ranges only; different description # one could also make it an array and use FriendlyName in the .cf file Variable PE4300_FAN_DISK_RPM OID .1.3.6.1.4.1.674.10891.301.1.5.2.3.1. Description Disk Fan Speed Unit rpm DefaultIndex 3 4 5 DefaultMin 1000 DefaultMax 5000 DefaultMaxValid 10000 DefaultGroup Environment Variable PE4X00_PSU_STATUS DefaultIndex 1 2 3 OID .1.3.6.1.4.1.674.10891.304.1.4.2.6.1. Description Power Supply Status DefaultEQ 3 Decode 1 other Decode 2 unknown Decode 3 OK Decode 4 noncrit Decode 5 critical Decode 6 nonrecoverable DefaultGroup Power Variable PE4X00_EXT_DISK1_PSU_STATUS DefaultIndex 1 2 OID .1.3.6.1.4.1.674.10891.304.1.4.2.6.2. Description ExtStorage 1 PSU Status DefaultEQ 3 Decode 1 other Decode 2 unknown Decode 3 OK Decode 4 noncrit Decode 5 critical Decode 6 nonrecoverable DefaultGroup Power # Dell PowerEdge 6350 Server Instrumentation Variable PE6350_TEMP_CPU OID .1.3.6.1.4.1.674.10891.300.1.5.2.2.1. Description CPU Temperature DefaultIndex 1 2 3 4 Scale / 10.0 Unit C DefaultMax 55 DefaultGroup Environment Variable PE6350_TEMP OID .1.3.6.1.4.1.674.10891.300.1.5.2.2.1. Description Temperature DefaultIndex 5 6 7 FriendlyName 5 @Motherboard FriendlyName 6 @Ambient FriendlyName 7 @Backplane Scale / 10.0 Unit C DefaultMax 40 DefaultGroup Environment Variable PE6350_TEMP_EXT_DISK1 OID .1.3.6.1.4.1.674.10891.300.1.5.2.2.2.1 Description ExtStorage 1 Temperature Scale / 10.0 Unit C DefaultGroup Environment Variable PE6350_FAN_RPM OID .1.3.6.1.4.1.674.10891.301.1.5.2.3.1. Description Fan Speed DefaultIndex 1 2 3 4 Unit rpm DefaultMin 1000 DefaultMax 5000 DefaultMaxValid 10000 DefaultGroup Environment Variable PE6350_FAN_RPM_EXT_DISK1 OID .1.3.6.1.4.1.674.10891.301.1.5.2.3.2. Description ExtStorage 1 Fan Speed DefaultIndex 1 2 3 Unit rpm DefaultMin 1000 DefaultMax 5000 DefaultMaxValid 10000 DefaultGroup Environment # Dell PowerEdge 4200 Server Instrumentation Variable PE4200_TEMP_CPU OID .1.3.6.1.4.1.674.10891.300.1.5.2.2.1. Description CPU Temperature DefaultIndex 1 2 Scale / 10.0 Unit C DefaultMax 40 DefaultGroup Environment Variable PE4200_TEMP OID .1.3.6.1.4.1.674.10891.300.1.5.2.2.1. Description Temperature DefaultIndex 3 4 5 6 FriendlyName 3 @Ambient FriendlyName 4 @Panel FriendlyName 5 @Backplane Top FriendlyName 6 @Backplane Bottom Scale / 10.0 Unit C DefaultMax 35 DefaultGroup Environment Variable PE4200_PSU_5V_CURRENT OID .1.3.6.1.4.1.674.10891.303.1.5.2.5.1. Description DC Current (+5V) DefaultIndex 1 2 FriendlyName 1 @Top PSU FriendlyName 2 @Bottom PSU Scale / 1000.0 Unit A DefaultMax 10 DefaultMaxValid 50 DefaultGroup Power Variable PE4200_PSU_3V_CURRENT OID .1.3.6.1.4.1.674.10891.303.1.5.2.5.1. Description DC Current (+3.3V) DefaultIndex 3 4 FriendlyName 3 @Top PSU FriendlyName 4 @Bottom PSU Scale / 1000.0 Unit A DefaultMax 5 DefaultMaxValid 50 DefaultGroup Power Variable PE4200_PSU_12V_CURRENT OID .1.3.6.1.4.1.674.10891.303.1.5.2.5.1. Description DC Current (+12V) DefaultIndex 5 6 FriendlyName 5 @Top PSU FriendlyName 6 @Bottom PSU Scale / 1000.0 Unit A DefaultMax 10 DefaultMaxValid 50 DefaultGroup Power Variable PE4200_FAN_RPM OID .1.3.6.1.4.1.674.10891.301.1.5.2.3.1. Description Fan Speed Unit rpm DefaultIndex 1 3 4 5 # Fan #2 is a standby unit FriendlyName 1 @Chassis 1 FriendlyName 2 @Chassis 2 FriendlyName 3 @Chassis 3 FriendlyName 4 @Top PSU FriendlyName 5 @Bottom PSU DefaultMin 1000 DefaultMax 5000 DefaultMaxValid 10000 DefaultGroup Environment # AMI MegaRAID (aka Dell PERC) RAID controller instrumentation Variable MEGARAID_C0_LOGICAL_STATUS OID .1.3.6.1.4.1.3582.1.1.2.1.3.0. Description RAID Ctl0 Volume Status DefaultEQ 2 Decode 0 offline Decode 1 degraded Decode 2 normal Decode 3 initialize Decode 4 checkconsistency Variable MEGARAID_C1_LOGICAL_STATUS OID .1.3.6.1.4.1.3582.1.1.2.1.3.1. Description RAID Ctl1 Volume Status DefaultEQ 2 Decode 0 offline Decode 1 degraded Decode 2 normal Decode 3 initialize Decode 4 checkconsistency Variable MEGARAID_C0_CH0_PHYS_STATUS OID .1.3.6.1.4.1.3582.1.1.3.1.4.0.0. Description Ctl0Ch0 Phys Drive Status DefaultEQ 3 Decode 1 ready Decode 3 online Decode 4 failed Decode 5 rebuild Decode 6 hotspare Decode 20 nondisk Variable MEGARAID_C1_CH0_PHYS_STATUS OID .1.3.6.1.4.1.3582.1.1.3.1.4.1.0. Description Ctl1Ch0 Phys Drive Status DefaultEQ 3 Decode 1 ready Decode 3 online Decode 4 failed Decode 5 rebuild Decode 6 hotspare Decode 20 nondisk Variable MEGARAID_C1_CH1_PHYS_STATUS OID .1.3.6.1.4.1.3582.1.1.3.1.4.1.1. Description Ctl1Ch1 Phys Drive Status DefaultEQ 3 Decode 1 ready Decode 3 online Decode 4 failed Decode 5 rebuild Decode 6 hotspare Decode 20 nondisk # APC SmartUPS monitoring (using PowerNet SNMP agents or SNMP adapter boards) Variable APCUPS_LINEVOLT_MAX OID .1.3.6.1.4.1.318.1.1.1.3.2.2.0 Description Recent Max Line Voltage Unit V DefaultMax 245 DefaultGroup Power Variable APCUPS_LINEVOLT_MIN OID .1.3.6.1.4.1.318.1.1.1.3.2.3.0 Description Recent Min Line Voltage Unit V DefaultMin 205 DefaultGroup Power Variable APCUPS_LOAD OID .1.3.6.1.4.1.318.1.1.1.4.2.3.0 Description Output Load Unit % DefaultMax 90 DefaultGroup Power Variable APCUPS_BATT_TEMP OID .1.3.6.1.4.1.318.1.1.1.2.2.2.0 Description Battery Temperature Unit C DefaultMax 45 DefaultGroup Environment # external sensors connected to a MeasureUPS board Variable APCUPS_EXT_TEMP OID .1.3.6.1.4.1.318.1.1.2.1.1.0 Description Temperature Unit C DefaultGroup Environment Variable APCUPS_EXT_HUMID OID .1.3.6.1.4.1.318.1.1.2.1.2.0 Description Humidity Unit % DefaultMin 10 DefaultMax 90 DefaultGroup Environment Variable APCUPS_EXT_SWITCH_STAT OID .1.3.6.1.4.1.318.1.1.2.2.2.1.5 Description Contact Decode 1 unknown Decode 2 OK Decode 3 FAULT Variable APCUPS_OUTPUT_STAT OID .1.3.6.1.4.1.318.1.1.1.4.1.1.0 Description UPS Status DefaultEQ 2 Decode 1 unknown Decode 2 Online Decode 3 On Battery Decode 4 On Smart Boost Decode 5 Timed Sleeping Decode 6 Software Bypass Decode 7 Off Decode 8 Rebooting Decode 9 Switched Bypass Decode 10 Hardware Failure Bypass Decode 11 Sleeping Until Power Return Decode 12 On Smart Trim DefaultGroup Power # Compaq ProLiant Server Instrumentation Variable PROLIANT_TEMP_STATUS OID .1.3.6.1.4.1.232.6.2.6.3.0 Description Temperature Status DefaultEQ 2 Decode 1 Other Decode 2 OK Decode 3 Degraded Decode 4 FAILED DefaultGroup Environment Variable PROLIANT_FAN_STATUS OID .1.3.6.1.4.1.232.6.2.6.7.1.9.0. Description Fan Status DefaultEQ 2 Decode 1 Other Decode 2 OK Decode 3 Degraded Decode 4 FAILED DefaultGroup Environment Variable PROLIANT_PSU_STATUS OID .1.3.6.1.4.1.232.6.2.9.3.1.5.0. Description Power Supply Status DefaultIndex 1 2 DefaultEQ 1 Decode 1 OK Decode 2 Failure Decode 3 BIST Failure Decode 4 Fan Failure Decode 5 Temp Failure Decode 6 Interlock Open DefaultGroup Power Variable CPQARRAY_LOG_STATUS OID .1.3.6.1.4.1.232.3.2.3.1.1.4.1. Description RAID Volume Status DefaultIndex 1 DefaultEQ 2 Decode 1 Other Decode 2 OK Decode 3 FAILED Decode 4 Unconfigured Decode 5 Recovering Decode 6 Ready For Rebuild Decode 7 Rebuilding Decode 8 Wrong Drive Decode 9 Bad Connect Decode 10 Overheating Decode 11 Shutdown Decode 12 expanding Decode 13 Not Available Decode 14 Queued For Expansion Variable CPQARRAY_PHYS_STATUS OID .1.3.6.1.4.1.232.3.2.5.1.1.6.1. Description Phys Drive Status DefaultEQ 2 Decode 1 Other Decode 2 OK Decode 3 Failed Decode 4 Predictive Failure # IBM 8272 Token Ring switch Variable IBM8272_LINK_STATE OID .1.3.6.1.4.1.2.6.66.1.2.2.1.1.15. Description Link State DefaultEQ 1 Decode 1 up Decode 2 down Variable IBM8272_TEMP_SYS OID .1.3.6.1.4.1.2.6.66.1.2.1.2.11.0 Description Switch Temperature DefaultEQ 1 Decode 1 normal Decode 2 HIGH DefaultGroup Environment # Nokia IP series firewall appliance Variable NOKIA_IP_CHASSIS_TEMP OID .1.3.6.1.4.1.94.1.21.1.1.5.0 Description Chassis Temperature DefaultEQ 1 Decode 1 normal Decode 2 OVERTEMP DefaultGroup Environment Variable NOKIA_IP_FAN_STAT OID .1.3.6.1.4.1.94.1.21.1.2.1.1.2. Description Fan Status DefaultEQ 1 Decode 1 running Decode 2 DEAD DefaultGroup Environment Variable NOKIA_IP_PSU_STAT OID .1.3.6.1.4.1.94.1.21.1.3.1.1.3. Description PSU Status DefaultEQ 1 Decode 1 running Decode 2 DEAD DefaultGroup Environment Variable NOKIA_IP_PSU_TEMP OID .1.3.6.1.4.1.94.1.21.1.3.1.1.2. Description Chassis Temperature DefaultEQ 1 Decode 1 normal Decode 2 OVERTEMP DefaultGroup Environment # Mail Server (custom extension scripts in UCD SNMP agent) Variable LINUX_MAILQUEUE OID .1.3.6.1.4.1.2021.8.1.101.1 Description Mail Queue Length # see sample in ucd-snmp subdir in snmpvar.monitor distribution # cisco router # ciscoEnvMonTemperatureState Variable CISCO_TEMP_STATE OID .1.3.6.1.4.1.9.9.13.1.3.1.6. Description Chassis Temperature DefaultIndex 1 DefaultEQ 1 Decode 1 normal Decode 2 Warning Decode 3 CRITICAL Decode 4 SHUTDOWN Decode 5 not present DefaultGroup Environment Variable CISCO_MEM_POOL_FREE OID .1.3.6.1.4.1.9.9.48.1.1.1.6. Description Memory Pool Free Bytes DefaultIndex 1 2 FriendlyName 1 CPU FriendlyName 2 I/O # HP switch # hpicfSensorStatus Variable HP_ICF_FAN_STATE OID .1.3.6.1.4.1.11.2.14.11.1.2.6.1.4.1 Description Fan Status DefaultEQ 4 Decode 1 unknown Decode 2 bad Decode 3 warning Decode 4 good Decode 5 not present DefaultGroup Environment Variable HP_ICF_PSU_STATE OID .1.3.6.1.4.1.11.2.14.11.1.2.6.1.4. Description PSU Status DefaultEQ 4 Decode 1 unknown Decode 2 bad Decode 3 warning Decode 4 good Decode 5 not present DefaultGroup Power etbemon-1.3.6/etc/syslog-monitor.conf0000644000000000000000000000611010146140376014467 0ustar # Configuration file for syslog.monitor # $Id: syslog-monitor.conf,v 1.2 2004/11/15 14:45:18 vitroth Exp $ ############################################################################# # Which timeout to set for select()ing on the input socket. # You really do not wish to play with this. # select_timeout 10 # Log level (just like syslog you know;) loglevel 6 # If undefined, will write to stdout # You better specify an absolute path here. # logfile /var/log/syslog.monitor # Where copies of incoming syslog messages get written to. # In the filename, you can define the following substitutions: # %H = gets replaced with the hostname # %L = gets replaced with the syslog level as a string # %l = same, but as a number # %F = syslog facility (local0, kern, ...) # %G = hostgroup the host belongs to # %D = date at which the message was received, in ISO 8601 (1999-04-03) syslogfile /var/log/syslog.%H.%F.%D # If set, will make syslog.monitor fork and go into the background as soon # as possible. # Be aware that the program will refuse to daemonize if you do not set a logfile. # daemon_mode mon_host cherusker.bi.teuto.net # Set these if necessary # mon_user # mon_pass # IP number on which to listen for incomeing UDP packets bind_ip 0.0.0.0 # port number (you almost certainly do not want to touch this) # bind_port 514 # Define a check called "emerg" check emerg # A slightly more elaborate description, which is sent to the mon server # as part of the trap desc Emergencies # The period which is monitored period 60m # How often this check _must_ trigger within said period. # Set to -1 to disable. min -1 # How often this check might occur at max within the period. max 3 # If this is set, no further matches will be checked if this check matched. # Use this carefully. # final # The check itself. Evaluated within Perl (), you can do powerful stuff # here. The current message is referenced by $$r. # Parameters you might want to match on: # $$r{'src_port'} - The source port from which the packert was sent. # $$r{'src_ip'} - The source IP. # $$r{'host'} - The hostname, resolved using the cache build # at startup. # $$r{'level'} - numeric syslog level of the message. (0-7) # $$r{'Level'} - syslog level as a string (ie 'crit') # $$r{'facility'} - Facility (ie 'local0' etc) # $$r{'msg'} - The text part of the message # $$r{'time'} - The unixtime at which the message was received, # $$r{'group'} - The group the host sending this message # belongs to pattern ($$r{'level'} <=3) # A "catch-all" - we really should receive at least one line within 15m, # But more than 1000 might be strange... check all desc All period 15m min 200 max 10000 final pattern (1) # Relating to hostgroup unix: group unix # For each host in the hostgroup unix, run a separate instance of each # check listed here (references the check defined above) per-host emerg # For the _entire_ hostgroup, run these checks: per-group all # Only on this host, run these: # on-host donar.bi.teuto.net emerg-kern etbemon-1.3.6/etc/very-simple.cf0000644000000000000000000000142213764421743013413 0ustar # # Very simple mon.cf file # # $Id: very-simple.cf,v 1.1.1.1 2004/06/09 05:18:06 trockij Exp $ # alertdir = /usr/lib/mon/alert.d mondir = /usr/lib/mon/mon.d maxprocs = 20 histlength = 100 randstart = 60s # # define groups of hosts to monitor # hostgroup servers localhost hostgroup mail mailhost watch servers service ping interval 5m monitor fping.monitor period wd {Mon-Fri} hr {7am-10pm} alert mail.alert root@localhost alertevery 1h period wd {Sat-Sun} alert mail.alert root@localhost service telnet interval 10m monitor telnet.monitor period wd {Mon-Fri} hr {7am-10pm} alertevery 1h alertafter 2 30m alert mail.alert root@localhost etbemon-1.3.6/etc/windows.cf0000644000000000000000000000371513774327151012637 0ustar # # Example mon.cf file for Windows # # Author: Russell Coker # # # Global options # alertdir = c:\mon\alert.d mondir = c:\mon\mon.d;c:\mon\mon-local.d logdir = c:\mon\log statedir = c:\mon\state cfbasedir = c:\mon\etc historicfile = c:\mon\log\history.log authfile = c:\mon\etc\auth.cf maxprocs = 20 histlength = 100 randstart = 60s dtlogging = yes dtlogfile = dtlog # tcp bind for mon client protocol (monshow etc) serverbind = 127.0.0.1 # udp bind for traps trapbind = 127.0.0.1 clientallow = 127.0.0.1 # # Define groups of hosts to monitor # hostgroup localhost localhost # # Define watches # watch localhost # example trap service for traps from other systems service trap description trap traptimeout 10m trapduration 60m period alert mail.alert root@localhost upalert mail.alert root@localhost service ping description Responses to ping interval 5m monitor fping.monitor period wd {Mon-Fri} hr {7am-10pm} alert mail.alert root@localhost alertevery 1h period wd {Sat-Sun} alert mail.alert root@localhost service http description HTTP service interval 10m monitor http.monitor period numalerts 10 alert mail.alert root@localhost upalert mail.alert root@localhost service smtp description SMTP service interval 10m monitor smtp.monitor -t 60 period numalerts 10 alert mail.alert root@localhost upalert mail.alert root@localhost # service pop3 # description POP3 service # interval 10m # monitor pop3.monitor # period # numalerts 10 # alert mail.alert root@localhost # upalert mail.alert root@localhost # service imap # description IMAP service # interval 10m # monitor imap.monitor -t 60 # period # numalerts 10 # alert mail.alert root@localhost # upalert mail.alert root@localhost # service telnet # description TELNET service # interval 10m # monitor telnet.monitor # period wd {Mon-Fri} hr {7am-10pm} # alertevery 1h # alertafter 2 30m # alert mail.alert root@localhost etbemon-1.3.6/mon0000755000000000000000000040670513664436434010610 0ustar #!/usr/bin/perl # # mon - schedules service tests and triggers alerts upon failures # # Jim Trocki, trockij@arctic.org # # $Id: mon,v 1.22.2.2 2007/06/06 11:46:19 trockij Exp $ # # Copyright (C) 1998 Jim Trocki # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # use strict; my $RELEASE='mon-1.3.4'; # # NetBSD rc.d script compatibility # $0= "mon" . " " . join(" ", @ARGV) if $^O eq "netbsd"; # # modules in the perl distribution # use Getopt::Long qw(:config no_ignore_case); use Text::ParseWords; use POSIX; use Fcntl; use Socket; use Sys::Hostname; use Sys::Syslog qw(:DEFAULT); use FileHandle; use File::Spec; use Data::Dumper; # # CPAN modules # use Time::HiRes qw(gettimeofday tv_interval usleep); use Time::Period; sub auth; sub call_alert; sub check_auth; sub clear_timers; sub client_accept; sub client_close; sub client_command; sub client_dopending; sub client_write_opstatus; sub collect_output; sub daemon; sub debug; sub debug_dir; sub dep_ok; sub dep_summary; sub depend; sub dhmstos; sub die_die; sub disen_host; sub disen_service; sub disen_watch; sub do_alert; sub do_startup_alerts; sub err_startup; sub esc_str; sub gen_scriptdir_hash; sub handle_io; sub handle_trap; sub handle_trap_timeout; sub host_exists; sub host_singleton_group; sub inRange; sub init_cf_globals; sub init_globals; sub load_auth; sub load_state; sub normalize_paths; sub mysystem; sub init_dtlog; sub pam_conv_func; sub proc_cleanup; sub process_event; sub randomize_startdelay; sub read_cf; sub readhistoricfile; sub reload; sub remove_proc; sub reset_server; sub run_monitor; sub save_state; sub set_last_test; sub set_op_status; sub reset_timer; sub setup_server; sub sock_write; sub syslog_die; sub un_esc_str; sub usage; sub write_dtlog; # # globals # my %opt; # cmdline arguments my %CF; # configuration directives my $PWD; # current working directory my $HOSTNAME; # system hostname my $STOPPED; # 1 = scheduler stopped, 0 = not stopped my $STOPPED_TIME; # time(2) scheduler was stopped, if stopped my $SLEEPINT; # don't touch my %watch_disabled; # watches disabled, indexed by watch my %watch; # main configuration file data structure my %alias; # aliases my %groups; # hostgroups, indexed by group my %views; # view lists, indexed by name my %view_users; # view preferences, per user # # I/O routine globals # my %clients; # fds of connected clients my $numclients; # count of connected clients my %running; # procs which are forked and running, # indexed by group/service my $iovec; # used for select loop my %runningpid; # procs which are forked and running, # indexed by PID my $procs; # number of outstanding procs my %fhandles; # input file handles of children my %ibufs; # buffer structure to hold data from children my ($fdset_rbits, $fdset_ebits); my $splitpath = "\s*:\s*"; my $joinpath = ":"; if($^O eq "MSWin32") { $splitpath = "\s*;\s*"; $joinpath = ";"; } # # history globals # my @last_alerts; # alert history, in memory my @last_failures; # failure history, in memory # # misc. globals # my $i; # loop iteration counter, used for debugging only my $lasttm; # the last time(2) the mon loop started my $pid_file_owner; # set when creating pid file my $tm; # used in main loop # # authentication structure globals # my %AUTHCMDS; my %NOAUTHCMDS; my %AUTHTRAPS; # # PAM authentication globals (must not be lexically scoped) # use vars qw ( $PAM_username $PAM_password ) ; # # opstatus globals # my (%OPSTAT, %FAILURE, %SUCCESS, %WARNING); # operational statuses my ($TRAP_COLDSTART, $TRAP_WARMSTART, # trap types $TRAP_LINKDOWN, $TRAP_LINKUP, $TRAP_AUTHFAIL, $TRAP_EGPNEIGHBORLOSS, $TRAP_ENTERPRISE, $TRAP_HEARTBEAT); my ($STAT_FAIL, $STAT_OK, $STAT_COLDSTART, # _op_status values $STAT_WARMSTART, $STAT_LINKDOWN, $STAT_UNKNOWN, $STAT_TIMEOUT, $STAT_UNTESTED, $STAT_DEPEND, $STAT_WARN); my ($FL_MONITOR, $FL_UPALERT, # alert type flags $FL_TRAP, $FL_TRAPTIMEOUT, $FL_STARTUPALERT, $FL_TEST, $FL_REDISTRIBUTE, $FL_ACKALERT, $FL_DISABLEALERT); my $TRAP_PDU; my (%ALERTHASH, %MONITORHASH); # hash of pathnames for # alerts/monitors my $PROT_VERSION; my $START_TIME; # time(2) server started my $TRAP_PRO_VERSION; # trap protocol version my $DEP_EVAL_SANDBOX; # perl environment for # dep evals # # argument parsing # my $getopt_result = GetOptions(\%opt, qw/ A|authfile=s B|cfbasedir=s D|statedir=s L|logdir=s M|m4:s O|syslogfacility=s P|pidfile=s S|stopped a|alertdir=s b|basedir=s c|configfile=s d|debug+ f|fork h|help i|sleep=i k|maxkeep=i l|loadstate:s m|maxprocs=i p|port=i r|randstart=s s|scriptdir=s t|trapport=i v|version /); if (!$getopt_result) { usage(); exit; } # # these two things can be taken care of without # initializing things further # if ($opt{"v"}) { print "$RELEASE\n"; exit; } if ($opt{"h"}) { usage(); exit; } if ($opt{"d"}) { eval 'require Data::Dumper;'; if ($@ ne "") { die "error: $@\n"; } } if ($^O eq "linux" || $^O =~ /^(open|free|net)bsd$/ || $^O eq "aix") { Sys::Syslog::setlogsock ('unix'); } elsif ($^O eq "solaris") { Sys::Syslog::setlogsock ('stream'); } openlog ("mon", "cons,pid", $CF{"SYSLOG_FACILITY"}); # # definitions # die "basedir $opt{b} does not exist\n" if ($opt{"b"} && ! -d $opt{"b"}); init_globals(); init_cf_globals(); syslog_die ("config file $CF{CF} does not exist") if (! -f $CF{"CF"}); # # read config file # if ((my $err = read_cf ($CF{"CF"}, 1)) ne "") { syslog_die ("$err"); } closelog; openlog ("mon", "cons,pid", $CF{"SYSLOG_FACILITY"}); # # cmdline args override config file # $CF{"ALERTDIR"} = $opt{"a"} if ($opt{"a"}); $CF{"BASEDIR"} = $opt{"b"} if ($opt{"b"}); $CF{"AUTHFILE"} = $opt{"A"} if ($opt{"A"}); $CF{"LOGDIR"} = $opt{"L"} if ($opt{"L"}); $CF{"STATEDIR"} = $opt{"D"} if ($opt{"D"}); $CF{"SCRIPTDIR"} = $opt{"s"} if ($opt{"s"}); $CF{"PIDFILE"} = $opt{"P"} if defined($opt{"P"}); # allow empty pidfile $CF{"MAX_KEEP"} = $opt{"k"} if ($opt{"k"}); $CF{"MAXPROCS"} = $opt{"m"} if ($opt{"m"}); $CF{"SERVPORT"} = $opt{"p"} if ($opt{"p"}); $CF{"TRAPPORT"} = $opt{"t"} if ($opt{"t"}); $SLEEPINT = $opt{"i"} if ($opt{"i"}); if ($opt{"r"}) { syslog_die ("bad randstart value") if (!defined (dhmstos ($opt{"r"}))); $CF{"RANDSTART"} = dhmstos($opt{"r"}); } if ($opt{"S"}) { $STOPPED = 1; $STOPPED_TIME = time; } # # do some path cleanups and # build lookup tables for alerts and monitors # normalize_paths(); gen_scriptdir_hash(); if ($opt{"d"}) { debug_dir(); } # # load the auth control, bind, and listen # load_auth (1); load_view_users(1); # # init client interface # %clients is an I/O structure, indexed by the fd of the client # $numclients is the number of clients currently connected # $iovec is fd_set for clients and traps # %clients = (); $numclients = 0; $iovec = ''; setup_server(); # # fork and become a daemon # init_dtlog() if ($CF{"DTLOGGING"}); daemon() if ($opt{"f"}); if ($CF{"PIDFILE"} ne '' && open PID, ">$CF{PIDFILE}") { $pid_file_owner = $$; print PID "$pid_file_owner\n"; close PID; } set_last_test (); # # randomize startup checks if asked to # randomize_startdelay() if ($CF{"RANDSTART"}); @last_alerts = (); @last_failures = (); readhistoricfile (); $procs = 0; $i=0; $lasttm=time; $fdset_rbits = $fdset_ebits = ''; %watch_disabled = (); $SIG{HUP} = \&reset_server; $SIG{INT} = \&handle_sigterm; # for interactive debugging $SIG{TERM} = \&handle_sigterm; $SIG{PIPE} = 'IGNORE'; # # load previously saved state # if (exists $opt{"l"}) { if ($opt{"l"}) { # If -l was given an argument (all, disabled, opstatus, etc...) # pass that to load_state load_state($opt{"l"}); }else{ # Otherwise default to old behavior of just loading disabled hosts/services/groups load_state("disabled"); } } syslog ('info', "mon server started"); # # startup alerts # do_startup_alerts(); # # main monitoring loop # for (;;) { debug (1, "$i" . ($STOPPED ? " (stopped)" : "") . "\n"); $i++; $tm = time; # # step through the watch groups, decrementing and # handing expired timers # if (!$STOPPED) { if (defined $CF{"EXCLUDE_PERIOD"} && $CF{"EXCLUDE_PERIOD"} ne "" && inPeriod (time, $CF{"EXCLUDE_PERIOD"})) { debug (1, "not running monitors because of global exclude_period\n"); } else { foreach my $group (keys %watch) { foreach my $service (keys %{$watch{$group}}) { my $sref = \%{$watch{$group}->{$service}}; my $t = $tm - $lasttm; $t = 1 if ($t <= 0); # # trap timer # if ($sref->{"traptimeout"}) { $sref->{"_trap_timer"} -= $t; if ($sref->{"_trap_timer"} <= 0 && $tm - $sref->{"_last_trap"} > $sref->{"traptimeout"}) { $sref->{"_trap_timer"} = $sref->{"traptimeout"}; handle_trap_timeout ($group, $service); } } # # trap duration timer # if (defined ($sref->{"_trap_duration_timer"})) { $sref->{"_trap_duration_timer"} -= $t; if ($sref->{"_trap_duration_timer"} <= 0) { set_op_status ($group, $service, $STAT_OK); undef $sref->{"_trap_duration_timer"}; } } # # polling monitor timer # if ($sref->{"interval"} && $sref->{"_timer"} <= 0 && !$running{"$group/$service"}) { if (!$CF{"MAXPROCS"} || $procs < $CF{"MAXPROCS"}) { if (defined $sref->{"exclude_period"} && $sref->{"exclude_period"} ne "" && inPeriod (time, $sref->{"exclude_period"})) { debug (1, "not running $group,$service because of exclude_period\n"); } elsif (($sref->{"dep_behavior"} eq "m" && defined $sref->{"depend"} && $sref->{"depend"} ne "") || (defined $sref->{"monitordepend"} && $sref->{"monitordepend"} ne "")) { if (dep_ok ($sref, 'm')) { run_monitor ($group, $service); } else { debug (1, "not running $group,$service because of depend\n"); } } else { run_monitor ($group, $service); } } else { syslog ('info', "throttled at $procs processes"); } } else { $sref->{"_timer"} -= $t; if ($sref->{"_timer"} < 0) { $sref->{"_timer"} = 0; } } } } } } $lasttm = time; # # collect any output from subprocs # collect_output; # # clean up after exited processes, and trigger alerts # proc_cleanup; # # handle client, server, and trap I/O # this routine sleeps for $SLEEPINT if no I/O is ready # handle_io; } die "not reached"; END { unlink $CF{"PIDFILE"} if $$ == $pid_file_owner && $CF{"PIDFILE"} ne ''; } ############################################################################## # # startup alerts # sub do_startup_alerts { foreach my $group (keys %watch) { foreach my $service (keys %{$watch{$group}}) { do_alert ($group, $service, "", 0, $FL_STARTUPALERT); } } } # # handle alert event, throttling the alert call if necessary # sub do_alert { my ($group, $service, $output, $retval, $flags) = @_; my (@groupargs, $last_alert, $alert); my ($sref, $range, @alerts); debug (1, "do_alert flags=$flags\n"); $sref = \%{$watch{$group}->{$service}}; my $tmnow = time; if ($STOPPED) { syslog ("notice", "ignoring alert for $group,$service because the mon scheduler is stopped"); return; } # # if redistribute it set, call it now # if ($sref->{"redistribute"} ne '') { my ($fac, $args); ($fac, $args) = split (/\s+/, $sref->{"redistribute"}, 2); call_alert ( group => $group, service => $service, output => $output, retval => $retval, flags => $flags | $FL_REDISTRIBUTE, alert => $fac, args => $args, ) } # # if the alarm is disabled, ignore it # if ((exists $watch_disabled{$group} && $watch_disabled{$group} == 1) || (defined $sref->{"disable"} && $sref->{"disable"} == 1)) { syslog ("notice", "ignoring alert for $group,$service"); return; } # # dependency check # if (!($flags & $FL_STARTUPALERT) && !($flags & $FL_UPALERT) && ((defined $sref->{"depend"} && $sref->{"dep_behavior"} eq "a") || (defined $sref->{"alertdepend"}))) { if (!$sref->{"_depend_status"}) { debug (1, "alert for $group,$service supressed because of dep fail\n"); return; } } my ($summary) = split("\n", $output); $summary = "(NO SUMMARY)" if (!defined $summary || $summary =~ /^\s*$/m); my ($prevsumm) = split("\n", $sref->{"_failure_output"}) if (defined $sref->{"_failure_output"}); $prevsumm = "(NO SUMMARY)" if (!defined $prevsumm || $prevsumm =~ /^\s*$/m); my $strippedsummary = $summary; $strippedsummary =~ s/\s//mg; my $strippedprevious = $prevsumm; $strippedprevious =~ s/\s//mg; # If the summary changed, un-acknowledge the service if 'unack_summary' is set if ($sref->{'_ack'} != 0 && $sref->{'unack_summary'} == 1 && $strippedsummary ne $strippedprevious && !($flags & ($FL_UPALERT|$FL_ACKALERT|$FL_DISABLEALERT))) { print STDERR "Unacking $group/$service:\nSummary: X".$strippedsummary."X\nPrevious: X".$strippedprevious."X\n"; $sref->{"_ack"} = 0; $sref->{"_ack_comment"} = ""; $sref->{"_consec_failures"}=1; foreach my $period (keys %{$sref->{"periods"}}) { $sref->{"periods"}->{$period}->{"_last_alert"} = 0; # $sref->{"periods"}->{$period}->{"_alert_sent"} = 0; $sref->{"periods"}->{$period}->{"_1stfailtime"} = 0; $sref->{"periods"}->{$period}->{"_failcount"} = 0; } } # # no alerts for ack'd failures, except for upalerts or summary changes # when observe_summary is set # if ($sref->{"_ack"} != 0 && !($flags & ($FL_UPALERT|$FL_ACKALERT|$FL_DISABLEALERT))) { syslog ("debug", "no alert for $group.$service" . " because of ack'd failure"); return; } # # check each time period for pending alerts # foreach my $periodlabel (keys %{$sref->{"periods"}}) { # # only send alerts that are in the proper period # next if (!inPeriod ($tmnow, $sref->{"periods"}->{$periodlabel}->{"period"})); my $pref = \%{$sref->{"periods"}->{$periodlabel}}; # # skip upalerts/ackalerts not paired with down alerts # disable by setting "no_comp_alerts" in period section # if (!$pref->{"no_comp_alerts"} && ($flags & ($FL_UPALERT | $FL_ACKALERT)) && !$pref->{"_alert_sent"}) { syslog ('debug', "$group/$service/$periodlabel: Suppressing upalert since no down alert was sent.") if ($flags & $FL_UPALERT); syslog ('debug', "$group/$service/$periodlabel: Suppressing ackalert since no down alert was sent.") if ($flags & $FL_ACKALERT); next; } # # skip looping upalerts when "no_comp-alerts" set. # if ($pref->{"no_comp_alerts"} && ($flags & $FL_UPALERT) && ($pref->{"_no_comp_alerts_upalert_sent"}>0)) { next; } # # do this if we're not handling an upalert, startupalert, ackalert, or disablealert # if (!($flags & $FL_UPALERT) && !($flags & $FL_STARTUPALERT) && !($flags & $FL_DISABLEALERT) && !($flags & $FL_ACKALERT)) { # # alert only when exit code matches # if (exists $pref->{"alertexitrange"}) { next if (!inRange($retval, $pref->{"alertexitrange"})); } # # alert only numalerts # if ($pref->{"numalerts"} && $pref->{"_alert_sent"} >= $pref->{"numalerts"}) { syslog ('debug', "$group/$service/$periodlabel: Suppressing alert since numalerts is met."); next; } # # only alert once every "alertevery" seconds, unless # output from monitor is different or if strict alertevery # # strict and _ignore_summary are basically the same though # strict short-circuits and overrides other settings and exists # for compatibility with pre-1.1 configs # if ($pref->{"alertevery"} != 0 && # if alertevery is set and ($tmnow - $pref->{"_last_alert"} < $pref->{"alertevery"}) && # we're within the time period and one of these: (($pref->{"_alertevery_strict"}) || # [ strict is set or ($pref->{"_observe_detail"} && $sref->{"_failure_output"} eq $output) || # observing detail and output hasn't changed or (!$pref->{"_observe_detail"} && (!$pref->{"_ignore_summary"}) && ($prevsumm eq $summary)) || # not observing detail # and not ignoring summary and summ hasn't changed or ($pref->{"_ignore_summary"}))) # we're ignoring summary changes ] { syslog ('debug', "$group/$service/$periodlabel: Suppressing alert for now due to alertevery."); next; } # # alertafter NUM # if (defined $pref->{"alertafter_consec"} && ($sref->{"_consec_failures"} < $pref->{"alertafter_consec"})) { syslog ('debug', "$group/$service/$periodlabel: Suppressing alert for now due to alertafter consecutive failures."); next; } # # alertafter timeval # elsif ( (!defined ($pref->{"alertafter"})) && (defined ($pref->{"alertafterival"})) ) { $pref->{'_1stfailtime'} = $tmnow if $pref->{'_1stfailtime'} == 0; if ($tmnow - $pref->{'_1stfailtime'} <= $pref->{'alertafterival'}) { syslog ('debug', "$group/$service/$periodlabel: Suppressing alert for now due to alertafter numval."); next; } } # # alertafter NUM timeval # elsif (defined ($pref->{"alertafter"})) { $pref->{"_failcount"}++; if ($tmnow - $pref->{'_1stfailtime'} <= $pref->{'alertafterival'} && $pref->{"_failcount"} < $pref->{"alertafter"}) { syslog ('debug', "$group/$service/$periodlabel: Suppressing alert for now due to alertafter num timeval."); next; } # # start a new time interval # if ($tmnow - $pref->{'_1stfailtime'} > $pref->{'alertafterival'}) { $pref->{"_failcount"} = 1; } if ($pref->{"_failcount"} == 1) { $pref->{"_1stfailtime"} = $tmnow; } if ($pref->{"_failcount"} < $pref->{"alertafter"}) { syslog ('debug', "$group/$service/$periodlabel: Suppressing alert for now due to alertafter num timeval."); next; } } } # # at this point, no alerts are blocked, # so send the alerts # # # trigger multiple alerts in this period # if ($flags & $FL_UPALERT) { @alerts = @{$pref->{"upalerts"}}; } elsif ($flags & $FL_STARTUPALERT) { @alerts = @{$pref->{"startupalerts"}}; } elsif ($flags & $FL_DISABLEALERT) { @alerts = @{$pref->{"disablealerts"}}; } elsif ($flags & $FL_ACKALERT) { @alerts = @{$pref->{"ackalerts"}}; } else { @alerts = @{$pref->{"alerts"}}; } my $called = 0; for (my $i=0;$i<@alerts;$i++) { my ($range, $fac, $args); if ($alerts[$i] =~ /^exit\s*=\s*((\d+|\d+-\d+))\s/i) { $range=$1; next if (!inRange($retval, $range)); ($fac, $args) = (split (/\s+/, $alerts[$i], 3))[1,2]; } else { ($fac, $args) = split (/\s+/, $alerts[$i], 2); } $called++ if (call_alert ( group => $group, service => $service, output => $output, retval => $retval, flags => $flags, pref => $pref, alert => $fac, args => $args, ) ); } # # reset _alert_sent if up alert was sent from a trap # if ($called) { if( (($FL_TRAP | $flags) && ($FL_UPALERT & $flags)) ) { $pref->{"_alert_sent"} = 0; $pref->{"_last_alert"} = 0; } else { $pref->{"_alert_sent"}++; # # reset _no_comp_alerts_upalert_sent counter - when service will be # back up, upalert will be sent. # if ($pref->{"no_comp_alerts"}) { $pref->{"_no_comp_alerts_upalert_sent"} = 0; } } if ($pref->{"no_comp_alerts"} && ($flags & $FL_UPALERT)) { $pref->{"_no_comp_alerts_upalert_sent"}++; } } } } # # walk through the watch list and reset the time # the service was last called # sub set_last_test { my ($i, $k, $t); $t = time; foreach $k (keys %watch) { foreach my $service (keys %{$watch{$k}}) { $watch{$k}->{$service}->{"_timer"} = $watch{$k}->{$service}->{"interval"}; } } } # # parse configuration file # # build the following data structures: # # %group # each element of %group is an array of hostnames # group records are terminated by a blank line in the # configuration file # %watch{"group"}->{"service"}->{"variable"} = value # %alias # sub read_cf { my ($CF, $commit) = @_; my ($var, $watchgroup, $ingroup, $curgroup, $inwatch, $args, $hosts, %disabled, $h, $i, $inalias, $curalias, $inview, $curview); my ($sref, $pref); my ($service, $period); my ($authtype, @authtypes); my $line_num = 0; # # parse configuration file # if (exists($opt{"M"}) || $CF =~ /\.m4$/) { my $m4 = "m4"; $m4 = $opt{"M"} if (defined($opt{"M"})); return "could not open m4 pipe of cf file: $CF: $!" if (!open (CFG, "$m4 $CF |")); } else { return "could not open cf file: $CF: $!" if (!open (CFG, $CF)); } # # buffers to hold the new un-committed config # my %new_alias = (); my %new_views = (); my %new_CF = %CF; my %new_groups; my %new_watch; my %is_watch; my $servnum = 0; my $DEP_BEHAVIOR = "a"; my $DEP_MEMORY = 0; my $UNACK_SUMMARY = 0; my $incomplete_line = 0; my $linepart = ""; my $l = ""; my $acc_line = ""; for (;;) { # # read in a logical "line", which may span actual lines # do { $line_num++; last if (!defined ($linepart = )); next if $linepart =~ /^\s*#/; # # accumulate multi-line lines (ones which are \-escaped) # if ($incomplete_line) { $linepart =~ s/^\s*//; } if ($linepart =~ /^(.*)\\\s*$/) { $incomplete_line = 1; $acc_line .= $1; chomp $acc_line; next; } else { $acc_line .= $linepart; } $l = $acc_line; $acc_line = ""; chomp $l; $l =~ s/^\s*//; $l =~ s/\s*$//; $incomplete_line = 0; $linepart = ""; }; # # global variables which can be overriden by the command line # if (!$inwatch && $l =~ /^(\w+) \s* = \s* (.*) \s*$/ix) { if ($1 eq "alertdir") { $new_CF{"ALERTDIR"} = $2; } elsif ($1 eq "basedir") { if(File::Spec->file_name_is_absolute($2)) { $new_CF{"BASEDIR"} = $2; } else { $new_CF{"BASEDIR"} = File::Spec->catdir( (File::Spec->curdir(), $2) ); } } elsif ($1 eq "cfbasedir") { if(File::Spec->file_name_is_absolute($2)) { $new_CF{"CFBASEDIR"} = $2; } else { $new_CF{"CFBASEDIR"} = File::Spec->catdir( (File::Spec->curdir(), $2) ); } } elsif ($1 eq "mondir") { $new_CF{"SCRIPTDIR"} = $2; } elsif ($1 eq "logdir") { $new_CF{"LOGDIR"} = $2; } elsif ($1 eq "histlength") { $new_CF{"MAX_KEEP"} = $2; } elsif ($1 eq "serverport") { $new_CF{"SERVPORT"} = $2; } elsif ($1 eq "trapport") { $new_CF{"TRAPPORT"} = $2; } elsif ($1 eq "serverbind") { $new_CF{"SERVERBIND"} = $2; } elsif ($1 eq "clientallow") { $new_CF{"CLIENTALLOW"}= $2; } elsif ($1 eq "trapbind") { $new_CF{"TRAPBIND"} = $2; } elsif ($1 eq "pidfile") { $new_CF{"PIDFILE"} = $2; } elsif ($1 eq "randstart") { $new_CF{"RANDSTART"} = dhmstos($2); if (!defined ($new_CF{"RANDSTART"})) { close (CFG); return "cf error: bad value '$2' for randstart option (syntax: randstart = timeval), line $line_num"; } } elsif ($1 eq "maxprocs") { $new_CF{"MAXPROCS"} = $2; } elsif ($1 eq "statedir") { $new_CF{"STATEDIR"} = $2; } elsif ($1 eq "authfile") { $new_CF{"AUTHFILE"} = $2; if (! -r $new_CF{"AUTHFILE"}) { close (CFG); return "cf error: authfile '$2' does not exist or is not readable, line $line_num"; } } elsif ($1 eq "authtype") { $new_CF{"AUTHTYPE"} = $2; @authtypes = split(' ' , $new_CF{"AUTHTYPE"}) ; foreach $authtype (@authtypes) { if ($authtype eq "pam") { eval 'use Authen::PAM qw(:constants);' ; if ($@ ne "") { close (CFG); return "cf error: could not use PAM authentication: $@"; } } } } elsif ($1 eq "pamservice") { $new_CF{"PAMSERVICE"} = $2; } elsif ($1 eq "userfile") { $new_CF{"USERFILE"} = $2; if (! -r $new_CF{"USERFILE"}) { close (CFG); return "cf error: userfile '$2' does not exist or is not readable, line $line_num"; } } elsif ($1 eq "historicfile") { $new_CF{"HISTORICFILE"} = $2; } elsif ($1 eq "historictime") { $new_CF{"HISTORICTIME"} = dhmstos($2); if (!defined $new_CF{"HISTORICTIME"}) { close (CFG); return "cf error: bad value '$2' for historictime command (syntax: historictime = timeval), line $line_num"; } } elsif ($1 eq "cltimeout") { $new_CF{"CLIENT_TIMEOUT"} = dhmstos($2); if (!defined ($new_CF{"CLIENT_TIMEOUT"})) { close (CFG); return "cf error: bad value '$2' for cltimeout command (syntax: cltimeout = secs), line $line_num"; } } elsif ($1 eq "monerrfile") { $new_CF{"MONERRFILE"} = $2; } elsif ($1 eq "dtlogfile") { $new_CF{"DTLOGFILE"} = $2; } elsif ($1 eq "dtlogging") { $new_CF{"DTLOGGING"} = 0; if ($2 == 1 || $2 eq "yes" || $2 eq "true") { $new_CF{"DTLOGGING"} = 1; } } elsif ($1 eq "dep_recur_limit") { $new_CF{"DEP_RECUR_LIMIT"} = $2; } elsif ($1 eq "dep_behavior") { if ($2 ne "m" && $2 ne "a" && $2 ne "hm") { close (CFG); return "cf error: unknown dependency behavior '$2', line $line_num"; } $DEP_BEHAVIOR = $2; } elsif ($1 eq "dep_memory") { my $memory = dhmstos($2); if (!defined $memory) { close (CFG); return "cf error: bad value '$2' for dep_memory option (syntax: dep_memory = timeval), line $line_num"; } $DEP_MEMORY = $memory; } elsif ($1 eq "unack_summary") { if (defined $2) { if ($2 =~ /y(es)?/i) { $UNACK_SUMMARY = 1; } elsif ($2 =~ /n(o)?/i) { $UNACK_SUMMARY = 0; } elsif ($2 eq "0" || $2 eq "1") { $UNACK_SUMMARY = $2; } else { return "cf error: invalid unack_summary value '$2' (syntax: unack_summary [0|1|y|yes|n|no])"; } } else { $UNACK_SUMMARY = 1; } } elsif ($1 eq "syslog_facility") { $new_CF{"SYSLOG_FACILITY"} = $2; } elsif ($1 eq "startupalerts_on_reset") { if ($2 =~ /^1|yes|true|on$/i) { $new_CF{"STARTUPALERTS_ON_RESET"} = 1; } else { $new_CF{"STARTUPALERTS_ON_RESET"} = 0; } } elsif ($1 eq "monremote") { $new_CF{"MONREMOTE"} = $2; } elsif ($1 eq "exclude_period") { if (inPeriod (time, $2) == -1) { close (CFG); return "cf error: malformed exclude_period '$2' (the specified time period is not valid as per Time::Period::inPeriod), line $line_num"; } $new_CF{"EXCLUDE_PERIOD"} = $2; } else { close (CFG); return "cf error: unknown variable '$1', line $line_num"; } next; } # # end of record # if ($l eq "") { $ingroup = 0; $inalias = 0; $inwatch = 0; $period = 0; $inview = 0; $curgroup = ""; $curalias = ""; $watchgroup = ""; $servnum = 0; next; } # # hostgroup record # if ($l =~ /^hostgroup\s+([a-zA-Z0-9_.-]+)\s*(.*)/) { $curgroup = $1; $ingroup = 1; $inview = 0; $inalias = 0; $inwatch = 0; $period = 0; $hosts = $2; %disabled = (); foreach $h (grep (/^\*/, @{$groups{$curgroup}})) { # We have to make $i = $h because $h is actually # a pointer to %groups and will modify it. $i = $h; $i =~ s/^\*//; $disabled{$i} = 1; } @{$new_groups{$curgroup}} = split(/\s+/, $hosts); # # keep hosts which were previously disabled # for ($i=0;$i<@{$new_groups{$curgroup}};$i++) { $new_groups{$curgroup}[$i] = "*$new_groups{$curgroup}[$i]" if ($disabled{$new_groups{$curgroup}[$i]}); } next; } if ($ingroup) { push (@{$new_groups{$curgroup}}, split(/\s+/, $l)); for ($i=0;$i<@{$new_groups{$curgroup}};$i++) { $new_groups{$curgroup}[$i] = "*$new_groups{$curgroup}[$i]" if ($disabled{$new_groups{$curgroup}[$i]}); } next; } # # alias record # if ($l =~ /^alias\s+([a-zA-Z0-9_.-]+)\s*$/) { $inalias = 1; $inview = 0; $ingroup = 0; $inwatch = 0; $period = 0; $curalias = $1; next; } if ($inalias) { if ($l =~ /\A(.*)\Z/) { push (@{$new_alias{$curalias}}, $1); next; } } # # view record # if ($l =~ /^view\s+([a-zA-Z0-9_.-]+)\s+(.*)$/) { $inview = 1; $inalias = 0; $ingroup = 0; $inwatch = 0; $period = 0; $curview = $1; $new_views{$curview}={}; foreach (split(/\s+/, $2)) { $new_views{$curview}->{$_} = 1; }; next; } if ($inview) { foreach (split(/\s+/, $l)) { $new_views{$curview}->{$_} = 1; }; next; } # # watch record # if ($l =~ /^watch\s+([a-zA-Z0-9_.-]+)\s*/) { $watchgroup = $1; $inwatch = 1; $inview = 0; $inalias = 0; $ingroup = 0; $period = 0; if (!defined ($new_groups{$watchgroup})) { # # This hostgroup doesn't exist yet, we'll create it and warn # @{$new_groups{$watchgroup}} = ($watchgroup); print STDERR "Warning: watch group $watchgroup defined with no corresponding hostgroup.\n"; } if ($new_watch{$watchgroup}) { close (CFG); return "cf error: watch '$watchgroup' already defined, line $line_num"; } $curgroup = ""; $service = ""; next; } if ($inwatch) { # # env variables # if ($l =~ /^([A-Z_][A-Z0-9_]*)=(.*)/) { if ($service eq "") { close (CFG); return "cf error: environment variable defined without a service, line $line_num"; } $new_watch{$watchgroup}->{$service}->{"ENV"}->{$1} = $2; next; } # # non-env variables # else { $l =~ /^(\w+)\s*(.*)$/; $var = $1; $args = $2; } # # service entry # if ($var eq "service") { $service = $args; if ($service !~ /^[a-zA-Z0-9_.-]+$/) { close (CFG); return "cf error: invalid service tag '$args', line $line_num"; } elsif (exists $new_watch{$watchgroup}->{$service}) { close (CFG); return "cf error: service $service already defined for watch group $watchgroup, line $line_num"; } $period = 0; $sref = \%{$new_watch{$watchgroup}->{$service}}; $sref->{"service"} = $args; $sref->{"interval"} = undef; $sref->{"randskew"} = 0; $sref->{"redistribute"} = ""; $sref->{"dep_behavior"} = $DEP_BEHAVIOR; $sref->{"dep_memory"} = $DEP_MEMORY; $sref->{"exclude_period"} = ""; $sref->{"exclude_hosts"} = {}; $sref->{"_op_status"} = $STAT_UNTESTED; $sref->{"_last_op_status"} = $STAT_UNTESTED; $sref->{"_ack"} = 0; $sref->{"_ack_comment"} = ''; $sref->{"unack_summary"} = $UNACK_SUMMARY; $sref->{"_consec_failures"} = 0; $sref->{"_failure_count"} = 0 if (!defined($sref->{"_failure_count"})); $sref->{"_start_of_monitor"} = time if (!defined($sref->{"_start_of_monitor"})); $sref->{"_alert_count"} = 0 if (!defined($sref->{"_alert_count"})); $sref->{"_last_failure"} = 0 if (!defined($sref->{"_last_failure"})); $sref->{"_last_success"} = 0 if (!defined($sref->{"_last_success"})); $sref->{"_last_trap"} = 0 if (!defined($sref->{"_last_trap"})); $sref->{"_last_traphost"} = '' if (!defined($sref->{"_last_traphost"})); $sref->{"_exitval"} = "undef" if (!defined($sref->{"_exitval"})); $sref->{"_last_check"} = undef; # # -1 for _monitor_duration means no monitor has been run yet # so there is no duration data available # $sref->{"_monitor_duration"} = -1; $sref->{"_monitor_running"} = 0; $sref->{"_depend_status"} = undef; $sref->{"failure_interval"} = undef; $sref->{"_old_interval"} = undef; next; } if ($service eq "") { close (CFG); return "cf error: need to specify service in watch record, line $line_num"; } # # period definition # # for each service there can be one or more alert periods # this is stored as an array of hashes named # %{$watch{$watchgroup}->{$service}->{"periods"}} # each index for this hash is a unique tag for the period as # defined by the user or named after the period (such as # "wd {Mon-Fri} hr {7am-11pm}") # # the value of the hash is an array containing the list of alert commands # and arguments, so # # @alerts = @{$watch{$watchgroup}->{$service}->{"periods"}->{"TAG"}} # if ($var eq "period") { $period = 1; my $periodstr; if ($args =~ /^([a-z_]\w*) \s* : \s* (.*)$/ix) { $periodstr = $1; $args = $2; } else { $periodstr = $args; } if (exists $sref->{"periods"}->{$periodstr}) { close (CFG); return "cf error: period '$periodstr' already defined for watch group $watchgroup service $service, line $line_num"; } $pref = \%{$sref->{"periods"}->{$periodstr}}; if (inPeriod (time, $args) == -1) { close (CFG); return "cf error: malformed period '$args' (the specified time period is not valid as per Time::Period::inPeriod), line $line_num"; } $pref->{"period"} = $args; $pref->{"alertevery"} = 0; $pref->{"numalerts"} = 0; $pref->{"_alert_sent"} = 0; $pref->{"no_comp_alerts"} = 0; $pref->{"_no_comp_alerts_upalert_sent"} = 0; @{$pref->{"alerts"}} = (); @{$pref->{"upalerts"}} = (); @{$pref->{"ackalerts"}} = (); @{$pref->{"disablealerts"}} = (); @{$pref->{"startupalerts"}} = (); next; } # # period variables # if ($period) { if ($var eq "alert") { push @{$pref->{"alerts"}}, $args; } elsif ($var eq "ackalert") { push @{$pref->{"ackalerts"}}, $args; } elsif ($var eq "disablealert") { push @{$pref->{"disablealerts"}}, $args; } elsif ($var eq "upalert") { $sref->{"_upalert"} = 1; push @{$pref->{"upalerts"}}, $args; } elsif ($var eq "startupalert") { push @{$pref->{"startupalerts"}}, $args; } elsif ($var eq "alertevery") { $pref->{"_observe_detail"} = 0; $pref->{"_alertevery_strict"} = 0; $pref->{"_ignore_summary"} = 0; if ($args =~ /(\S+) \s+ observe_detail \s*$/ix) { $pref->{"_observe_detail"} = 1; $args = $1; } elsif ($args =~ /(\S+) \s+ ignore_summary \s*$/ix) { $pref->{"_ignore_summary"} = 1; $args = $1; } # # for backawards-compatibility with <= 0.38.21 # elsif ($args =~ /(\S+) \s+ summary/ix) { $args = $1; } # # strict # elsif ($args =~ /(\S+) \s+ strict \s*$/ix) { $pref->{"_alertevery_strict"} = 1; $args = $1; } if (!($args = dhmstos ($args))) { close (CFG); return "cf error: invalid time interval '$args' (syntax: alertevery {positive number}{smhd} [ strict | observe_detail | ignore_summary ]), line $line_num"; } $pref->{"alertevery"} = $args; next; } elsif ($var eq "alertafter") { my ($p1, $p2); # # alertafter NUM # if ($args =~ /^(\d+)$/) { $p1 = $1; $pref->{"alertafter_consec"} = $p1; } # # alertafter timeval # elsif ($args =~ /^(\d+[hms])$/) { $p1 = $1; if (!($p1 = dhmstos ($p1))) { close (CFG); return "cf error: invalid time interval '$args' (syntax: alertafter = [{positive integer}] [{positive number}{smhd}]), line $line_num"; } $pref->{"alertafterival"} = $p1; $pref->{"_1stfailtime"} = 0; } # # alertafter NUM timeval # elsif ($args =~ /(\d+)\s+(\d+[hms])$/) { ($p1, $p2) = ($1, $2); if (($p1 - 1) * $sref->{"interval"} >= dhmstos($p2)) { close (CFG); return "cf error: interval & alertafter not sensible. No alerts can be generated with those parameters, line $line_num"; } $pref->{"alertafter"} = $p1; $pref->{"alertafterival"} = dhmstos ($p2); $pref->{"_1stfailtime"} = 0; $pref->{"_failcount"} = 0; } else { close (CFG); return "cf error: invalid interval specification '$args', line $line_num"; } } elsif ($var eq "upalertafter") { if (!($args = dhmstos ($args))) { close (CFG); return "cf error: invalid upalertafter specification '$args' (syntax: upalertafter = {positive number}{smhd}), line $line_num"; } $pref->{"upalertafter"} = $args; } elsif ($var eq "numalerts") { if ($args !~ /^\d+$/) { close (CFG); return "cf error: -numeric arg '$args' (syntax: numalerts = {positive integer}, line $line_num"; } $pref->{"numalerts"} = $args; next; } elsif ($var eq "no_comp_alerts") { $pref->{"no_comp_alerts"} = 1; next; } elsif ($var eq "alerts_dont_count") { $pref->{"alerts_dont_count"} = 1; next; } elsif ($var eq 'alertexitrange') { if ($args !~ /^\s*(\d+|\d+-\d+)\s*$/) { close (CFG); return "cf error: invalid exit code range '$args', line $line_num"; } $pref->{"alertexitrange"} = $args; } else { close (CFG); return "cf error: unknown syntax [$l], line $line_num"; } } # # non-period variables # elsif (!$period) { if ($var eq "interval") { if (!($args = dhmstos ($args))) { close (CFG); return "cf error: invalid time interval '$args' (syntax: interval = {positive number}{smhd}), line $line_num"; } } elsif ($var eq "failure_interval") { if (!($args = dhmstos ($args))) { close (CFG); return "cf error: invalid interval '$args' (syntax: failure_interval = {positive number}{smhd}), line $line_num"; } } elsif ($var eq "monitor") { # valid } elsif ($var eq "redistribute") { # valid } elsif ($var eq "allow_empty_group") { # valid } elsif ($var eq "description") { # valid } elsif ($var eq "unack_summary") { if (defined $args) { if ($args =~ /y(es)?/i) { $args = 1; } elsif ($args =~ /n(o)?/i) { $args = 0; } if ($args eq "0" || $args eq "1") { $sref->{"unack_summary"} = $args; } else { return "cf error: invalid unack_summary value '$args' (syntax: unack_summary [0|1|y|yes|n|no])"; } } else { $sref->{"unack_summary"} = 1; } next; } elsif ($var eq "traptimeout") { if (!($args = dhmstos ($args))) { close (CFG); return "cf error: invalid traptimeout interval '$args' (syntax: traptimeout = {positive number}{smhd}), line $line_num"; } $sref->{"_trap_timer"} = $args; } elsif ($var eq "trapduration") { if (!($args = dhmstos ($args))) { close (CFG); return "cf error: invalid trapduration interval '$args' (syntax: trapduration = {positive number}{smhd}), line $line_num"; } } elsif ($var eq "randskew") { if (!($args = dhmstos ($args))) { close (CFG); return "cf error: invalid randskew time interval '$args' (syntax: randskew = {positive number}{smhd}), line $line_num"; } } elsif ($var eq "dep_behavior") { if ($args ne "m" && $args ne "a" && $args ne "hm") { close (CFG); return "cf error: unknown dependency behavior '$args' (syntax: dep_behavior = {m|a}), line $line_num"; } } elsif ($var eq "dep_memory") { my $timeval = dhmstos($args); if (!$timeval) { close (CFG); return "cf error: bad value '$args' for dep_memory option (syntax: dep_memory = timeval), line $line_num"; } $args = $timeval; } elsif ($var eq "depend") { $args =~ s/SELF:/$watchgroup:/g; } elsif ($var eq "alertdepend") { $args =~ s/SELF:/$watchgroup:/g; } elsif ($var eq "monitordepend") { $args =~ s/SELF:/$watchgroup:/g; } elsif ($var eq "hostdepend") { $args =~ s/SELF:/$watchgroup:/g; } elsif ($var eq "exclude_hosts") { my $ex = {}; foreach my $h (split (/\s+/, $args)) { $ex->{$h} = 1; } $args = $ex; } elsif ($var eq "exclude_period") { if (inPeriod (time, $args) == -1) { close (CFG); return "cf error: malformed exclude_period '$args' (the specified time period is not valid as per Time::Period::inPeriod), line $line_num"; } } else { close (CFG); return "cf error: unknown syntax [$l], line $line_num"; } $sref->{$var} = $args; } else { close (CFG); return "cf error: unknown syntax outside of period section [$l], line $line_num"; } } next; } close (CFG) || return "Could not open pipe to m4 (check that m4 is properly installed and in your PATH): $!"; # # Go through each defined hostgroup and check that there is a # watch associated with that hostgroup record. # # hostgroups without associated watches are not a violation of # mon config syntax, but it's usually not what you want. # for (keys(%new_watch)) { $is_watch{$_} = 1 }; foreach $watchgroup ( keys (%new_groups) ) { print STDERR "Warning: hostgroup $watchgroup has no watch assigned to it!\n" unless $is_watch{$watchgroup}; } # # no errors, commit new config if $commit was specified # return "" unless $commit; %views = %new_views; %alias = %new_alias; %groups = %new_groups; %watch = %new_watch; %CF = %new_CF; ""; } # # convert a string like "20m" into seconds # sub dhmstos { my ($str) = @_; my ($s); $str = lc ($str); if ($str =~ /^\s*(\d+(?:\.\d+)?)([dhms])\s*$/i) { if ($2 eq "m") { $s = $1 * 60; } elsif ($2 eq "h") { $s = $1 * 60 * 60; } elsif ($2 eq "d") { $s = $1 * 60 * 60 * 24; } else { $s = $1; } } else { return undef; } $s; } # # reset the state of the server on SIGHUP, and reread config # file. # sub reset_server { my ($keepstate) = @_; # # reap children that may be running # foreach my $pid (keys %runningpid) { my ($group, $service) = split (/\//, $runningpid{$pid}); kill 15, $pid; waitpid ($pid, 0); syslog ('info', "reset killed child $pid, exit status $?"); remove_proc ($pid); } $procs = 0; save_state ("all") if ($keepstate); syslog ('info', "resetting, and re-reading configuration $CF{CF}"); if ((my $err = read_cf ($CF{"CF"}, 1)) ne "") { syslog ('err', "error reading config file: $err"); return undef; } normalize_paths; gen_scriptdir_hash; $lasttm=time; # the last time(2) the loop started $fdset_rbits = $fdset_ebits = ''; set_last_test (); randomize_startdelay() if ($CF{"RANDSTART"}); load_state ("all") if ($keepstate); if ($CF{"DTLOGGING"}) { init_dtlog(); } readhistoricfile; if ($CF{"STARTUPALERTS_ON_RESET"}) { do_startup_alerts; } return 1; } sub init_dtlog { my $t = time; return if (!$CF{"DTLOGGING"}); if (!open (DTLOG, ">>$CF{DTLOGFILE}")) { syslog ('err', "could not append to $CF{DTLOGFILE}: $!"); $CF{"DTLOGGING"} = 0; } else { $CF{"DTLOGGING"} = 1; print DTLOG <{"host"} = inet_ntoa($addr); $clients{$fno}->{"fhandle"} = $CLIENT; $clients{$fno}->{"user"} = undef; # username if authenticated $clients{$fno}->{"timeout"} = $CF{"CLIENT_TIMEOUT"}; $clients{$fno}->{"last_read"} = time; # last time data was read $clients{$fno}->{"buf"} = ''; $numclients++; } # # do all pending client commands # sub client_dopending { my ($cl, $cmd, $l); foreach $cl (keys %clients) { if ($clients{$cl}->{"buf"} =~ /^([^\r\n]*)[\r\n]+/s) { $cmd = $1; $l = length ($cmd); $clients{$cl}->{"buf"} =~ s/^[^\r\n]*[\r\n]+//s; client_command ($cl, $cmd); } } } # # close a client connection # sub client_close { my ($cl, $reason) = @_; syslog ('info', "closing client $cl: $reason") if (defined $reason); die if !defined ($clients{$cl}->{"fhandle"}); close ($clients{$cl}->{"fhandle"}); delete $clients{$cl}; vec ($iovec, $cl, 1) = 0; $numclients--; } # # Handle a connection from a client # sub client_command { my ($cl, $l) = @_; my ($cmd, $args, $group, $service, $s, $sname, $stchanged); my ($var, $value, $msg, @l, $sock, $port, $addr, $sref, $auth, $fh); my ($user, $pass, @argsList, $comment); my ($authtype, @authtypes); my $is_auth = 0; #flag for multiple auth types syslog ('info', "client command \"$l\"") if ($l !~ /^\s*login/i); $fh = $clients{$cl}->{"fhandle"}; if ($l !~ /^(dump|login|disable|enable|quit|list|set|get|setview|getview| stop|start|loadstate|savestate|reset|clear|checkauth| reload|term|test|servertime|ack|version|protid)(\s+(.*))?$/ix) { sock_write ($fh, "520 invalid command\n"); return; } ($cmd, $args) = ("\L$1", $3); $stchanged = 0; print STDERR "client command $cmd\nclient args $args\n"; # # quit command # if ($cmd eq "quit") { sock_write ($fh, "220 quitting\n"); client_close ($cl); } elsif ($opt{"d"} && $cmd eq "dump") { print STDERR Dumper (\%watch), "\n\n"; # # protocol identification # } elsif ($cmd eq "protid") { if ($args != int ($PROT_VERSION)) { sock_write ($fh, "520 protocol mismatch\n"); } else { sock_write ($fh, "220 protocol match\n"); } # # login # } elsif ($cmd eq "login") { ($user, $pass) = split (/\s+/, $args, 2); @authtypes = split(' ' , $CF{"AUTHTYPE"}) ; # Check each for of authentication in order, and stop checking # as soon as we get a positive authentication result. foreach $authtype (@authtypes) { if (defined auth ($authtype, $user, $pass, $clients{$cl}->{"host"})) { $is_auth = 1; last; } } if ($is_auth != 1) { sock_write ($fh, "530 login unsuccessful\n"); } else { $clients{$cl}->{"user"} = $user; syslog ("info", "authenticated $user"); sock_write ($fh, "220 login accepted\n"); } # # reset # } elsif ($cmd eq "reset" && check_auth ($clients{$cl}->{"user"}, $cmd)) { my ($keepstate); if ($args =~ /stopped/i) { $STOPPED = 1; $STOPPED_TIME = time; } if ($args =~ /keepstate/) { $keepstate = 1; } if (reset_server ($keepstate)) { sock_write ($fh, "220 reset PID $$\@$HOSTNAME\n"); } else { sock_write ($fh, "520 reset PID $$\@$HOSTNAME failed, error in config file\n"); } # # reload # } elsif ($cmd eq "reload" && check_auth ($clients{$cl}->{"user"}, $cmd)) { if (!defined reload (split (/\s+/, $args))) { sock_write ($fh, "520 unknown reload command\n"); } else { sock_write ($fh, "220 reload completed\n"); } # # clear # } elsif ($cmd eq "clear" && check_auth ($clients{$cl}->{"user"}, $cmd)) { if ($args =~ /^timers \s+ ([a-zA-Z0-9_.-]+) \s+ ([a-zA-Z0-9_.-]+)/ix) { if (!defined $watch{$1}->{$2}) { sock_write ($fh, "520 unknown group\n"); } else { clear_timers ($1, $2); sock_write ($fh, "220 clear timers completed\n"); } } else { sock_write ($fh, "520 unknown clear command\n"); next; } # # test # } elsif ($cmd eq "test" && check_auth ($clients{$cl}->{"user"}, $cmd)) { my ($cmd, $args) = split (/\s+/, $args, 2); # # test monitor # if ($cmd eq "monitor") { my ($group, $service) = split (/\s+/, $args); if (!defined $watch{$group}->{$service}) { sock_write ($fh, "$group $service not defined\n"); } else { $watch{$group}->{$service}->{"_timer"} = 0; $watch{$group}->{$service}->{"_next_check"} = 0; mysystem("$CF{MONREMOTE} test $group $service") if ($CF{MONREMOTE}); } sock_write ($fh, "220 test monitor completed\n"); # # test alert # } elsif ($cmd =~ /^alert|startupalert|upalert|ackalert|disablealert$/) { my ($group, $service, $retval, $period) = split (/\s+/, $args, 4); if (!defined $watch{$group}->{$service}) { sock_write ($fh, "520 $group $service not defined\n"); } elsif (!defined $watch{$group}->{$service}->{"periods"}->{$period}) { sock_write ($fh, "520 period not defined\n"); } else { my $f = 0; my $a; if ($cmd eq "alert") { $a = $watch{$group}->{$service}->{"periods"}->{$period}->{"alerts"}; } elsif ($cmd eq "startupalert") { $f = $FL_STARTUPALERT; $a = $watch{$group}->{$service}->{"periods"}->{$period}->{"startupalerts"}; } elsif ($cmd eq "upalert") { $f = $FL_UPALERT; $a = $watch{$group}->{$service}->{"periods"}->{$period}->{"upalerts"}; } elsif ($cmd eq "ackalert") { $f = $FL_ACKALERT; $a = $watch{$group}->{$service}->{"periods"}->{$period}->{"ackalerts"}; } elsif ($cmd eq "disablealert") { $f = $FL_DISABLEALERT; $a = $watch{$group}->{$service}->{"periods"}->{$period}->{"disablealerts"}; } for (@{$a}) { my ($alert, $args) = split (/\s+/, $_, 2); if ($args =~ /^exit=/) { $args =~ s/^exit=\S+ \s+//x; } call_alert ( group => $group, service => $service, output => "test\ntest detail\n", retval => $retval, flags => $f | $FL_TEST, alert => $alert, args => $args, ); } sock_write ($fh, "220 test alert completed\n"); } # # test config file # } elsif ($cmd =~ /^config$/) { if ((my $err = read_cf ($CF{"CF"}, 0)) ne "") { sock_write ($fh, $err); sock_write ($fh, "\n520 test config completed, errors found in config file\n"); } else { sock_write ($fh, "220 test config completed OK, no errors found\n"); } } else { sock_write ($fh, "520 test error\n"); } # # version # } elsif ($cmd eq "version") { sock_write ($fh, "version " . int ($PROT_VERSION) . "\n"); sock_write ($fh, "220 version completed\n"); # # load state # } elsif ($cmd eq "loadstate" && check_auth ($clients{$cl}->{"user"}, $cmd)) { foreach (split (/\s+/, $args)) { load_state ($_); } sock_write ($fh, "220 loadstate completed\n"); # # save state # } elsif ($cmd eq "savestate" && check_auth ($clients{$cl}->{"user"}, $cmd)) { if ($args =~ /\S/) { foreach (split (/\s+/, $args)) { save_state ($_); } sock_write ($fh, "220 savestate completed\n"); } else { sock_write ($fh, "520 savestate error, arguments required\n"); } # # term # } elsif ($cmd eq "term" && check_auth ($clients{$cl}->{"user"}, $cmd)) { sock_write ($fh, "220 terminating server\n"); client_close ($cl, "terminated by user command"); syslog ("info", "terminating by user command"); exit; # # stop testing # } elsif ($cmd eq "stop"&& check_auth ($clients{$cl}->{"user"}, $cmd)) { $STOPPED = 1; $STOPPED_TIME = time; sock_write ($fh, "220 stop completed\n"); # # start testing # } elsif ($cmd eq "start" && check_auth ($clients{$cl}->{"user"}, $cmd)) { $STOPPED = 0; $STOPPED_TIME = 0; sock_write ($fh, "220 start completed\n"); } elsif ($cmd eq "setview") { my @args=split /\s+/, $args; if (@args > 1) { sock_write($fh, "500 Unknown setview command\n") } elsif (@args == 1) { if (defined($views{$args[0]})) { $clients{$cl}->{"view"} = $args[0]; sock_write($fh, "selecting view $args[0]\n"); sock_write($fh, "220 setview completed\n") } else { sock_write($fh, "504 unknown view $args[0]\n"); } } else { delete $clients{$cl}->{"view"}; sock_write($fh, "no view selected -- all groups will be displayed\n"); sock_write($fh, "220 setview completed\n") } } elsif ($cmd eq "getview") { if ($clients{$cl}->{"view"}) { sock_write($fh, "view ".$clients{$cl}->{"view"}. " selected\n"); } else { sock_write($fh, "no view selected -- all groups will be displayed\n"); } sock_write($fh, "220 getview completed\n") # # set # } elsif ($cmd eq "set" && check_auth ($clients{$cl}->{"user"}, $cmd)) { if ($args =~ /^maxkeep\s+(\d+)/) { $CF{"MAX_KEEP"} = $1; sock_write ($fh, "220 set completed\n"); } else { ($group, $service, $var, $value) = split (/\s+/, $args, 4); if (!defined $watch{$group}->{$service}) { sock_write ($fh, "520 $group,$service not defined\n"); } elsif ($var eq "opstatus") { if (!defined ($OPSTAT{$value})) { sock_write ($fh, "520 undefined opstatus\n"); } else { set_op_status ($group, $service, un_esc_str ((parse_line ('\s+', 0, $value))[0])); sock_write ($fh, "220 set completed\n"); } } else { $value = un_esc_str ((parse_line ('\s+', 0, $value))[0]); $watch{$group}->{$service}->{$var} = $value; sock_write ($fh, "$group $service $var='$value'\n"); sock_write ($fh, "220 set completed\n"); } } # # get # } elsif ($cmd eq "get" && check_auth ($clients{$cl}->{"user"}, $cmd)) { if ($args =~ /^maxkeep\s*$/) { sock_write ($fh, "maxkeep = $CF{MAX_KEEP}\n"); sock_write ($fh, "220 set completed\n"); } else { ($group, $service, $var) = split (/\s+/, $args, 3); if (!defined $watch{$group}->{$service}) { sock_write ($fh, "520 $group,$service not defined\n"); } else { sock_write ($fh, "$group $service $var='" . esc_str ($watch{$group}->{$service}->{$var}, 1) . "'\n"); sock_write ($fh, "220 get completed\n"); } } # # list # } elsif ($cmd eq "list" && check_auth ($clients{$cl}->{"user"}, $cmd)) { @argsList = split(/\s+/, $args); ($cmd, $args) = split (/\s+/, $args, 2); # # list service descriptions # if ($cmd eq "descriptions") { foreach $group (keys %watch) { foreach $service (keys %{$watch{$group}}) { if (view_match($clients{$cl}->{"view"}, $group, $service)) { sock_write ($fh, "$group $service " . esc_str ($watch{$group}->{$service}->{"description"}, 1) . "\n"); } } } sock_write ($fh, "220 list descriptions completed\n"); # # list group members # } elsif ($cmd eq "group") { if ($groups{$args}) { sock_write ($fh, "hostgroup $args @{$groups{$args}}\n"); sock_write ($fh, "220 list group completed\n"); } else { sock_write ($fh, "520 list group error, undefined group\n"); } # # list status of all services # } elsif ($cmd eq "opstatus") { if (!defined $args || $args eq "") { foreach $group (keys %watch) { foreach $service (keys %{$watch{$group}}) { if (view_match($clients{$cl}->{"view"}, $group, $service)) { client_write_opstatus ($fh, $group, $service); } } } sock_write ($fh, "220 list opstatus completed\n"); } else { my $err = 0; my @g = (); my ($group, $service); foreach my $gs (split (/\s+/, $args)) { ($group, $service) = split (/,/, $gs); $err++ && last if ($service ne "" && !defined $watch{$group}->{$service}); push (@g, [$group, $service]); } if (!$err) { foreach my $gs (@g) { if ($gs->[1] ne "") { client_write_opstatus ($fh, $gs->[0], $gs->[1]); } else { foreach $service (keys %{$watch{$gs->[0]}}) { client_write_opstatus ($fh, $gs->[0], $service); } } } sock_write ($fh, "220 list opstatus completed\n"); } else { sock_write ($fh, "520 $group,$service does not exist\n"); } } # # list disabled hosts and services # } elsif ($cmd eq "disabled") { foreach $group (keys %groups) { if (view_match($clients{$cl}->{"view"}, $group, undef)) { @l = grep (/^\*/, @{$groups{$group}}); if (@l) { grep (s/^\*//, @l); sock_write ($fh, "group $group: @l\n"); } } } foreach $group (keys %watch) { if (view_match($clients{$cl}->{"view"}, $group, undef)) { if (exists $watch_disabled{$group} && $watch_disabled{$group} == 1) { sock_write ($fh, "watch $group\n"); } } foreach $service (keys %{$watch{$group}}) { if (view_match($clients{$cl}->{"view"}, $group, $service)) { if (defined $watch{$group}->{$service}->{'disable'} && $watch{$group}->{$service}->{'disable'} == 1) { sock_write ($fh, "watch $group service " . "$service\n"); } } } } sock_write ($fh, "220 list disabled completed\n"); # # list last alert history # } elsif ($cmd eq "alerthist") { foreach my $l (@last_alerts) { sock_write ($fh, esc_str ($l) . "\n"); } sock_write ($fh, "220 list alerthist completed\n"); # # list time of last failures for each service # } elsif ($cmd eq "failures") { foreach $group (keys %watch) { foreach $service (keys %{$watch{$group}}) { if (view_match($clients{$cl}->{"view"}, $group, $service)) { my $sref = \%{$watch{$group}->{$service}}; client_write_opstatus ($fh, $group, $service) if ($FAILURE{$sref->{"_op_status"}}); } } } sock_write ($fh, "220 list failures completed\n"); # # list the failure history # } elsif ($cmd eq "failurehist") { foreach my $l (@last_failures) { sock_write ($fh, esc_str ($l) . "\n"); } sock_write ($fh, "220 list failurehist completed\n"); # # list the time of last successes for each service # } elsif ($cmd eq "successes") { foreach $group (keys %watch) { foreach $service (keys %{$watch{$group}}) { if (view_match($clients{$cl}->{"view"}, $group, $service)) { my $sref = \%{$watch{$group}->{$service}}; client_write_opstatus ($fh, $group, $service) if ($SUCCESS{$sref->{"_op_status"}}); } } } sock_write ($fh, "220 list successes completed\n"); # # list warnings # } elsif ($cmd eq "warnings") { foreach $group (keys %watch) { foreach $service (keys %{$watch{$group}}) { if (view_match($clients{$cl}->{"view"}, $group, $service)) { my $sref = \%{$watch{$group}->{$service}}; client_write_opstatus ($fh, $group, $service) if ($WARNING{$sref->{"_op_status"}}); } } } sock_write ($fh, "220 list successes completed\n"); # # list process IDs # } elsif ($cmd eq "pids") { sock_write ($fh, "server $$\n"); foreach $value (keys %runningpid) { ($group, $service) = split (/\//, $runningpid{$value}); sock_write ($fh, "$group $service $value\n"); } sock_write ($fh, "220 list pids completed\n"); # # list watch groups and services # } elsif ($cmd eq "watch") { foreach $group (keys %watch) { foreach $service (keys %{$watch{$group}}) { if (view_match($clients{$cl}->{"view"}, $group, $service)) { if (!defined $watch{$group}->{$service}) { sock_write ($fh, "$group (undefined service)\n"); } else { sock_write ($fh, "$group $service\n"); } } } } sock_write ($fh, "220 list watch completed\n"); # # list server state # } elsif ($cmd eq "state") { if ($STOPPED) { sock_write ($fh, "scheduler stopped since $STOPPED_TIME\n"); } else { sock_write ($fh, "scheduler running\n"); } sock_write ($fh, "220 list state completed\n"); # # list aliases # } elsif ($cmd eq "aliases") { my (@listAliasesRequest) = @argsList; shift (@listAliasesRequest); # if no alias request, all alias are responded unless (@listAliasesRequest) { @listAliasesRequest = keys (%alias); } foreach my $alias (@listAliasesRequest){ sock_write ($fh, "alias $alias\n"); foreach $value (@{$alias{$alias}}) { sock_write ($fh, "$value\n"); } sock_write ($fh, "\n"); } sock_write ($fh, "220 list aliases completed\n"); # # list aliasgroups # } elsif ($cmd eq "aliasgroups") { my (@listAliasesRequest); @listAliasesRequest = keys (%alias); sock_write ($fh, "@listAliasesRequest\n") unless (@listAliasesRequest == 0); sock_write ($fh, "220 list aliasgroups completed\n"); # # list deps # } elsif ($cmd eq "deps") { foreach my $g (keys %watch) { foreach my $s (keys %{$watch{$g}}) { if (view_match($clients{$cl}->{"view"}, $group, $service)) { my $sref = \%{$watch{$g}->{$s}}; if ($sref->{"depend"} ne "") { sock_write ($fh, "exp $g $s '" . esc_str ($sref->{"depend"}, 1) . "'\n"); } else { sock_write ($fh, "exp $g $s 'NONE'\n"); } my @u = ($sref->{"depend"} =~ /[a-zA-Z0-9_.-]+:[a-zA-Z0-9_.-]+/g); if (@u) { sock_write ($fh, "cmp $g $s @u\n"); } else { sock_write ($fh, "cmp $g $s NONE\n"); } } } } sock_write ($fh, "220 list deps completed\n"); # # downtime log # } elsif ($cmd eq "dtlog") { if ($CF{"DTLOGGING"}) { if (!open (DTLOGTMP, "< $CF{DTLOGFILE}")) { sock_write ($fh, "520 list dtlog error, cannot open dtlog\n"); } else { while () { sock_write ($fh, $_ ) if (!/^#/ && !/^\s*$/); } close (DTLOGTMP); sock_write ($fh, "220 list dtlog completed\n"); } } else { sock_write ($fh, "520 list dtlog error, dtlogging is not turned on\n"); } # # list available views # } elsif ($cmd eq "views") { sock_write ($fh, "views ".join(' ',sort(keys %views))."\n"); sock_write ($fh, "220 list group completed\n"); # unknown list command } else { sock_write ($fh, "520 unknown list command\n"); } # # acknowledge a failure # } elsif ($cmd eq "ack" && check_auth ($clients{$cl}->{"user"}, $cmd)) { my ($group, $service, $comment) = split (/\s+/, $args, 3); if (!defined ($watch{$group})) { sock_write ($fh, "520 unknown group\n"); } elsif (!defined $watch{$group}->{$service}) { sock_write ($fh, "520 unknown service\n"); } my $sref = \%{$watch{$group}->{$service}}; if ($sref->{"_op_status"} == $STAT_OK || $sref->{"_op_status"} == $STAT_UNTESTED) { sock_write ($fh, "520 service is in a non-failure state\n"); } else { $sref->{"_ack"} = time; $sref->{"_ack_comment"} = $clients{$cl}->{"user"} . ": " . un_esc_str ((parse_line ('\s+', 0, $comment))[0]); sock_write ($fh, "220 ack completed\n"); do_alert($group, $service, $sref->{"_ack_comment"}, undef, $FL_ACKALERT) } # # disable watch, service or host # } elsif ($cmd eq "disable" && check_auth ($clients{$cl}->{"user"}, $cmd)) { ($cmd, $args) = split (/\s+/, $args, 2); # # disable watch # if ($cmd eq "watch") { if (!defined (disen_watch($args, 0))) { sock_write ($fh, "520 disable error, unknown watch \"$args\"\n"); } else { $stchanged++; mysystem("$CF{MONREMOTE} disable watch $args") if ($CF{MONREMOTE}); sock_write ($fh, "220 disable watch completed\n"); } # # disable service # } elsif ($cmd eq "service") { ($group, $service) = split (/\s+/, $args, 2); if (!defined (disen_service ($group, $service, 0))) { sock_write ($fh, "520 disable error, unknown service\n"); } else { $stchanged++; mysystem("$CF{MONREMOTE} disable service $group $service") if ($CF{MONREMOTE}); sock_write ($fh, "220 disable service completed\n"); do_alert($group, $service, $clients{$cl}->{"user"}, undef, $FL_DISABLEALERT) } # # disable host # } elsif ($cmd eq "host") { my @notfound = (); my @hosts = split (/\s+/, $args); foreach my $h (@hosts) { if (!host_exists ($h)) { push @notfound, $h; } } if (@notfound) { sock_write ($fh, "520 disable host failed, host(s) @notfound do not exist\n"); } else { foreach my $h (@hosts) { # # disable a watch if there is a group with this host # as its only member. this prevents warning messages # about monitors not being run on empty host groups # foreach my $g (host_singleton_group($h)) { disen_watch($g, 0); mysystem("$CF{MONREMOTE} disable watch $g") if ($CF{MONREMOTE}); } disen_host ($h, 0); $stchanged++; mysystem("$CF{MONREMOTE} disable host $h") if ($CF{MONREMOTE}); } sock_write ($fh, "220 disable host completed\n"); } } else { sock_write ($fh, "520 command could not be executed\n"); } # # enable watch, service or host # } elsif ($cmd eq "enable" && check_auth ($clients{$cl}->{"user"}, $cmd)) { ($cmd, $args) = split (/\s+/, $args, 2); # # enable watch # if ($cmd eq "watch") { if (!defined (disen_watch ($args, 1))) { sock_write ($fh, "520 enable error, unknown watch\n"); } else { $stchanged++; mysystem("$CF{MONREMOTE} enable watch $args") if ($CF{MONREMOTE}); sock_write ($fh, "220 enable watch completed\n"); } # # enable service # } elsif ($cmd eq "service") { ($group, $service) = split (/\s+/, $args, 2); if (!defined (disen_service ($group, $service, 1))) { sock_write ($fh, "520 enable error, unknown group\n"); } else { $stchanged++; mysystem("$CF{MONREMOTE} enable service $group $service") if ($CF{MONREMOTE}); sock_write ($fh, "220 enable completed\n"); } # # enable host # } elsif ($cmd eq "host") { foreach my $h (split (/\s+/, $args)) { foreach my $g (host_singleton_group($h)) { disen_watch($g, 1); mysystem("$CF{MONREMOTE} enable watch $g") if ($CF{MONREMOTE}); } disen_host ($h, 1); mysystem("$CF{MONREMOTE} enable host $h") if ($CF{MONREMOTE}); $stchanged++; } sock_write ($fh, "220 enable completed\n"); } else { sock_write ($fh, "520 command could not be executed\n"); } # # server time # } elsif ($cmd eq "servertime" && check_auth ($clients{$cl}->{"user"}, $cmd)) { sock_write ($fh, join ("", time, " ", scalar (localtime), "\n")); sock_write ($fh, "220 servertime completed\n"); # # check auth # } elsif ($cmd eq "checkauth") { @_ = split(' ',$args); $cmd = $_[0]; $user = $clients{$cl}->{"user"}; # Note that we call check_auth without syslogging here. if (check_auth($clients{$cl}->{"user"}, $cmd, 1)) { sock_write ($fh, "220 command authorized\n"); } else { sock_write ($fh, "520 command could not be executed\n"); } } else { sock_write ($fh, "520 command could not be executed, unknown command\n"); } save_state ("disabled") if ($stchanged); syslog ('info', "finished client command \"$l\"") if ($l !~ /^\s*login/i); } sub client_write_opstatus { my $fh = shift; my ($group, $service) = @_; my $sref = \%{$watch{$group}->{$service}}; my $summary = esc_str ($sref->{"_last_summary"}, 1); my $detail = esc_str ($sref->{"_last_detail"}, 1); my $depend = esc_str ($sref->{"depend"}, 1); my $hostdepend = esc_str ($sref->{"hostdepend"}, 1); my $monitordepend = esc_str ($sref->{"monitordepend"}, 1); my $alertdepend = esc_str ($sref->{"alertdepend"}, 1); my $monitor = esc_str ($sref->{"monitor"}, 1); my $comment; if ($sref->{"_ack"} != 0) { $comment = esc_str ($sref->{"_ack_comment"}, 1); } else { $comment = ''; } my $alerts_sent = 0; my $l = 0; foreach my $period (keys %{$sref->{"periods"}}) { $alerts_sent += $sref->{"periods"}->{$period}->{"_alert_sent"} if (!defined($sref->{"periods"}{$period}{"alerts_dont_count"})); $l = $sref->{"periods"}->{$period}->{"_last_alert"} if (defined $sref->{"periods"}->{$period}->{"_last_alert"} && $sref->{"periods"}->{$period}->{"_last_alert"} > $l); } my $buf = sprintf("group=$group service=$service opstatus=$sref->{_op_status} last_opstatus=%s exitval=%s timer=%s last_success=%s last_trap=%s last_traphost=%s last_check=%s ack=%s ackcomment=$comment alerts_sent=$alerts_sent depstatus=%s depend=$depend hostdepend=$hostdepend monitordepend=$monitordepend alertdepend=$alertdepend monitor=$monitor last_summary=%s last_detail=%s", (defined $sref->{_last_op_status} ? $sref->{_last_op_status} : ""), (defined $sref->{_exitval} ? $sref->{_exitval} : ""), (defined $sref->{_timer} ? $sref->{_timer} : ""), (defined $sref->{_last_success} ? $sref->{_last_success} : ""), (defined $sref->{_last_trap} ? $sref->{_last_trap} : ""), (defined $sref->{_last_traphost} ? $sref->{_last_traphost} : ""), (defined $sref->{_last_check} ? $sref->{_last_check} : ""), (defined $sref->{_ack} ? $sref->{_ack} : ""), (defined $sref->{"_depend_status"} ? int ($sref->{"_depend_status"}) : ""), $summary, $detail); $buf .= " last_failure=$sref->{_last_failure}" if ($sref->{"_last_failure"}); if ($sref->{"interval"}) { $buf .= " interval=$sref->{interval}" . " monitor_duration=$sref->{_monitor_duration}" . " monitor_running=$sref->{_monitor_running}" } $buf .= " exclude_period=". esc_str($sref->{exclude_period}) if ($sref->{"exclude_period"} ne ""); $buf .= " exclude_hosts=" . esc_str(join (" ", keys %{$sref->{exclude_hosts}})) if (keys %{$sref->{"exclude_hosts"}}); $buf .= " randskew=$sref->{randskew}" if ($sref->{"randskew"}); $buf .= " last_alert=$l" if ($l); if ($sref->{"_first_failure"}) { my $t = time - $sref->{"_first_failure"}; $buf .= " first_failure=$sref->{_first_failure}" . " failure_duration=$t"; } # if ($sref->{"_first_success"}) # { # my $t = time - $sref->{"_first_success"}; # $buf .= " first_success=$sref->{_first_success}" . # " success_duration=$t"; # } $buf .= "\n"; sock_write ($fh, $buf); } # # show usage # sub usage { print <<"EOF"; usage: mon [-a dir] [-A file] [-b dir] [-B dir] [-c config] [-d] [-D dir] [-f] [-h] [-i secs] [-k num] [-l [type]] [-L dir] [-M [path]] [-m num] [-p num] [-P file] [-r num] [-s dir] [-S] [-t num] mon -v -a dir alert script dir -A file authorization file -b dir base directory for alerts and monitors (basedir) -B dir base directory for configuration files (cfbasedir) -c config config file, defaults to "mon.cf" -d debug -D dir state directory (statedir) -f fork and become a daemon -h this help -i secs sleep interval (seconds), defaults to 1 -k num keep history of last num events -l [type] load some types of old state from statedir. type can be disabled (default), opstatus or all. -L dir log directory (logdir) -M [path] pre-process config file with m4. if m4 isn't in \$PATH specify the path to m4 here -m num throttle at maximum number of monitor processes -O facility syslog facility to use -p num server listens on port num -P file PID file -r num randomize startup schedule -s dir monitor script dir -S start with scheduler stopped -t port trap port -v print version Report bugs to russell\@coker.com.au EOF } # # become a daemon # sub daemon { my $pid; if ($pid = fork()) { # the parent goes away all happy and stuff exit (0); } elsif (!defined $pid) { die "could not fork: $!\n"; } setsid(); # # make it so that we cannot regain a controlling terminal # if ($pid = fork()) { # the parent goes away all happy and stuff exit (0); } elsif (!defined $pid) { syslog ('err', "could not fork: $!"); exit 1; } # chdir ('/'); umask (022); if (!open (N, "+>>" . $CF{"MONERRFILE"})) { syslog ("err", "could not open error output file $CF{'MONERRFILE'}: $!"); exit (1); } select (N); $| = 1; select (STDOUT); if (!open (STDIN, "/dev/null")) { syslog ("err", "could not open STDIN from /dev/null: $!"); exit (1); } print N "Mon starting at ".localtime(time)."\n"; if (!open(STDOUT, ">&N") || !open (STDERR, ">&N")) { syslog ("err", "could not redirect: $!"); exit(1); } syslog ('info', "running as daemon"); } # # debug # sub debug { my ($level, @l) = @_; return if (!defined $opt{"d"} || $level > $opt{"d"}); if ($opt{"d"} && !$opt{"f"}) { print STDERR @l; } else { syslog ('debug', join ('', @l)); } } # # die_die # sub die_die { my ($level, $msg) = @_; die "[$level] $msg\n" if ($opt{"d"}); syslog ($level, "fatal, $msg"); closelog(); exit (1); } # # handle cleanup of exited processes # trigger alerts on failures (or send no alert if disabled) # do some accounting # sub proc_cleanup { my ($summary, $tmnow, $buf); $tmnow = time; return if (keys %running == 0); while ((my $p = waitpid (-1, &WNOHANG)) >0) { next if (!exists $runningpid{$p}); my ($group, $service) = split (/\//, $runningpid{$p}); my $sref = \%{$watch{$group}->{$service}}; # # suck in any extra data # my $fh = $fhandles{$runningpid{$p}}; while (my $z = sysread ($fh, $buf, 8192)) { $ibufs{$runningpid{$p}} .= $buf; } debug (1, "PID $p ($runningpid{$p}) exited with [" . int ($?>>8) . "]\n"); $sref->{"_monitor_duration"} = $tmnow - $sref->{"_last_check"}; $sref->{"_monitor_running"} = 0; process_event ("m", $group, $service, int ($?>>8), $ibufs{$runningpid{$p}}); reset_timer ($group, $service); remove_proc ($p); } } # # handle the event where a monitor exits or a trap is received # # $type is "m" for monitor, "t" for trap # sub process_event { my ($type, $group, $service, $exitval, $output) = @_; debug (1, "process_event type=$type group=$group service=$service exitval=$exitval output=[$output]\n"); my $sref = \%{$watch{$group}->{$service}}; my $tmnow = time; my ($summary, $detail) = split("\n", $output, 2); $sref->{"_exitval"} = $exitval; if ($sref->{"depend"} ne "" && $sref->{"dep_behavior"} eq "a") { dep_ok ($sref, 'a'); } # # error exit value # if ($exitval) { # # accounting # $sref->{"_failure_count"}++; $sref->{"_consec_failures"}++; $sref->{"_last_failure"} = $tmnow; if ($sref->{"_op_status"} == $STAT_OK || $sref->{"_op_status"} == $STAT_UNKNOWN || $sref->{"_op_status"} == $STAT_UNTESTED) { $sref->{"_first_failure"} = $tmnow; } set_op_status ($group, $service, $STAT_FAIL); $summary = "(NO SUMMARY)" if ($summary =~ /^\s*$/m); $sref->{"_last_summary"} = $summary; $sref->{"_last_detail"} = $detail; shift @last_failures if (@last_failures > $CF{"MAX_KEEP"}); push @last_failures, "$group $service" . " $tm $summary"; syslog ('crit', "failure for $last_failures[-1]"); # # send an alert if necessary # if ($type eq "m") { do_alert ($group, $service, $output, $exitval, $FL_MONITOR); # # change interval if needed # if (defined ($sref->{"failure_interval"}) && !defined $sref->{"_old_interval"}) { $sref->{"_old_interval"} = $sref->{"interval"}; $sref->{"interval"} = $sref->{"failure_interval"}; $sref->{"_next_check"} = 0; } } elsif ($type eq "t") { do_alert ($group, $service, $output, $exitval, $FL_TRAP); } elsif ($type eq "T") { do_alert ($group, $service, $output, $exitval, $FL_TRAPTIMEOUT); } $sref->{"_failure_output"} = $output; } # # success exit value # else { if ($CF{"DTLOGGING"} && defined ($sref->{"_op_status"}) && $sref->{"_op_status"} == $STAT_FAIL) { write_dtlog ($sref, $group, $service); } my $old_status = $sref->{"_op_status"}; set_op_status ($group, $service, $STAT_OK); if ($type eq "t") { $sref->{"_last_uptrap"} = $tmnow; } # # if this service has just come back up and # we are paying attention to this event, # let someone know # if (($sref->{"redistribute"} ne '') || ((defined ($sref->{"_op_status"})) && ($old_status == $STAT_FAIL) && (defined($sref->{"_upalert"})) && (!defined($sref->{"upalertafter"}) || (($tmnow - $sref->{"_first_failure"}) >= $sref->{"upalertafter"})))) { # Save the last failing monitor's output for posterity $sref->{"_upalertoutput"}= $sref->{"_last_output"}; do_alert ($group, $service, $sref->{"_upalertoutput"}, 0, $FL_UPALERT); } # # send also when no upalertafter set # elsif (defined($sref->{"_upalert"}) && $old_status == $STAT_FAIL) { do_alert ($group, $service, $sref->{"_upalertoutput"}, 0, $FL_UPALERT); } $sref->{"_ack"} = 0; $sref->{"_ack_comment"} = ''; $sref->{"_first_failure"} = 0; $sref->{"_last_failure"} = 0; $sref->{"_consec_failures"} = 0; $sref->{"_failure_output"} = ""; $sref->{"_last_summary"} = $summary; $sref->{"_last_detail"} = $detail; # # reset the alertevery timer # foreach my $period (keys %{$sref->{"periods"}}) { # # "alertevery strict" should not reset _last_alert # if (!$sref->{"periods"}->{$period}->{"_alertevery_strict"}) { $sref->{"periods"}->{$period}->{"_last_alert"} = 0; } $sref->{"periods"}->{$period}->{"_1stfailtime"} = 0; $sref->{"periods"}->{$period}->{"_alert_sent"} = 0; } # # change interval back to original # if (defined ($sref->{"failure_interval"}) && $sref->{"_old_interval"} != undef) { $sref->{"interval"} = $sref->{"_old_interval"}; $sref->{"_old_interval"} = undef; $sref->{"_next_check"} = 0; } $sref->{"_last_success"} = $tmnow; } # # save the output # $sref->{"_last_output"} = $output; $sref->{"_last_summary"} = $summary; $sref->{"_last_detail"} = $detail; } # # collect output from running processes # sub collect_output { my ($buf, $rout); return if (!keys %running); my $nfound = select ($rout=$fdset_rbits, undef, undef, 0); debug (1, "select returned $nfound file handles\n"); return if ($! == &EINTR); if ($nfound) { # # look for the file descriptors that are readable, # and try to read as much as possible from them # foreach my $k (keys %fhandles) { my $fh = $fhandles{$k}; if (vec ($rout, fileno($fh), 1) == 1) { my $z = 0; while ($z = sysread ($fh, $buf, 8192)) { $ibufs{$k} .= $buf; debug (1, "[$buf] from $fh\n"); } # # ignore if EAGAIN, since we're nonblocking # if (!defined($z) && $! == &EAGAIN) { # # error on this descriptor # } elsif (!defined($z)) { debug (1, "error on $fh: $!\n"); syslog ('err', "error on $fh: $!"); vec($fdset_rbits, fileno($fh), 1) = 0; } elsif ($z == 0 && $! == &EAGAIN) { debug (1, "EAGAIN on $fh\n"); # # if EOF encountered, stop trying to # get input from this file descriptor # } elsif ($z == 0) { debug (1, "EOF on $fh\n"); vec($fdset_rbits, fileno($fh), 1) = 0; } } } } } # # handle forking a monitor process, and set up variables # sub run_monitor { my ($group, $service) = @_; my (@args, @groupargs, $pid, @ghosts, $monitor, $monitorargs); my $sref = \%{$watch{$group}->{$service}}; ($monitor, $monitorargs) = ($sref->{"monitor"} =~ /^(\S+)(\s+(.*))?$/); if (!defined $MONITORHASH{$monitor} || ! -f $MONITORHASH{$monitor}) { syslog ('err', "no monitor found while trying to run [$monitor]"); return undef; } else { $monitor = $MONITORHASH{$monitor}; } $monitor .= " " . $monitorargs if ($monitorargs); @ghosts = (); # # if monitor ends with ";;", do not append groups # to command line # if ($monitor =~ /;;\s*$/) { $monitor =~ s/\s*;;\s*$//; @args = quotewords ('\s+', 0, $monitor); @ghosts = (1); # # exclude disabled hosts # } else { @ghosts = grep (!/^\*/, @{$groups{$group}}); # # per-service excludes # if (keys %{$sref->{"exclude_hosts"}}) { my @g = (); for (my $i=0; $i<@ghosts; $i++) { push (@g, $ghosts[$i]) if !$sref->{"exclude_hosts"}->{$ghosts[$i]}; } @ghosts = @g; } # # per-host dependencies # if ((defined $sref->{"depend"} && $sref->{"depend"} ne "" && $sref->{"dep_behavior"} eq 'hm') || (defined $sref->{"hostdepend"} && $sref->{"hostdepend"} ne "")) { my @g = (); my $sum = dep_summary($sref); for (my $i=0; $i<@ghosts; $i++) { push (@g, $ghosts[$i]) if (! grep /\Q$ghosts[$i]\E/, @$sum); } @ghosts = @g; } @args = (quotewords ('\s+', 0, $monitor), @ghosts); } if (@ghosts == 0 && !defined ($sref->{"allow_empty_group"})) { syslog ('err', "monitor for $group/$service" . " not called because of no host arguments\n"); reset_timer ($group, $service); } else { $fhandles{"$group/$service"} = new FileHandle; $pid = open ($fhandles{"$group/$service"}, '-|'); if (!defined $pid) { syslog ('err', "Could not fork: $!"); delete $fhandles{"$group/$service"}; return 0; } elsif ($pid == 0) { open(STDERR, '>&STDOUT') or syslog ('err', "Could not dup stderr: $!"); open(STDIN, "{"ENV"}}) { $ENV{$v} = $sref->{"ENV"}->{$v}; } $ENV{"MON_GROUP"} = $group; $ENV{"MON_SERVICE"} = $service; $ENV{"MON_LAST_SUMMARY"} = $sref->{"_last_summary"} if (defined $sref->{"_last_summary"}); $ENV{"MON_LAST_OUTPUT"} = $sref->{"_last_output"} if (defined $sref->{"_last_output"}); $ENV{"MON_LAST_FAILURE"} = $sref->{"_last_failure"} if (defined $sref->{"_last_failure"}); $ENV{"MON_FIRST_FAILURE"} = $sref->{"_first_failure"} if (defined $sref->{"_first_failure"}); $ENV{"MON_DEPEND_STATUS"} = $sref->{"_depend_status"} if (defined $sref->{"_depend_status"}); $ENV{"MON_FIRST_SUCCESS"} = $sref->{"_first_success"} if (defined $sref->{"_first_success"}); $ENV{"MON_LAST_SUCCESS"} = $sref->{"_last_success"} if (defined $sref->{"_last_success"}); $ENV{"MON_DESCRIPTION"} = $sref->{"description"} if (defined $sref->{"description"}); $ENV{"MON_STATEDIR"} = $CF{"STATEDIR"}; $ENV{"MON_LOGDIR"} = $CF{"LOGDIR"}; $ENV{"MON_CFBASEDIR"} = $CF{"CFBASEDIR"}; if (!exec @args) { syslog ('err', "could not exec '@args': $!"); exit (1); } } $sref->{"_last_check"} = scalar (time); $sref->{"_monitor_running"} = 1; debug (1, "watching file handle ", fileno ($fhandles{"$group/$service"}), " for $group/$service\n"); # # set nonblocking I/O and setup bit vector for select(2) # configure_filehandle ($fhandles{"$group/$service"}) || syslog ("err", "could not configure filehandle for $group/$service: $!"); vec ($fdset_rbits, fileno($fhandles{"$group/$service"}), 1) = 1; $fdset_ebits |= $fdset_rbits; # # note that this is running # $running{"$group/$service"} = 1; $runningpid{$pid} = "$group/$service"; $ibufs{"$group/$service"} = ""; $procs++; } if ($sref->{"_next_check"}) { $sref->{"_next_check"} += $sref->{"interval"}; } else { $sref->{"_next_check"} = time() + $sref->{"interval"}; } } # # set the countdown timer for this service # sub reset_timer { my ($group, $service) = @_; my $sref = \%{$watch{$group}->{$service}}; if ($sref->{"randskew"} != 0) { $sref->{"_timer"} = $sref->{"interval"} + (int (rand (2)) == 0 ? -int(rand($sref->{"randskew"}) + 1) : int(rand($sref->{"randskew"})+1)); } elsif ($sref->{"_next_check"}) { if (($sref->{"_timer"} = $sref->{"_next_check"} - time()) < 0) { $sref->{"_timer"} = $sref->{"interval"}; } } else { $sref->{"_timer"} = $sref->{"interval"}; } } # # randomize the delay before each test # $opt{"randstart"} is seconds # sub randomize_startdelay { my ($group, $service); foreach $group (keys %watch) { foreach $service (keys %{$watch{$group}}) { $watch{$group}->{$service}->{"_timer"} = int (rand ($CF{"RANDSTART"})); } } } # # return 1 if $val is within $range, # where $range = "number" or "number-number" # sub inRange { my ($val, $range) = @_; my ($retval); $retval = 0; if ($range =~ /^(\d+)$/ && $val == $1) { $retval = 1 } elsif ($range =~ /^(\d+)\s*-\s*(\d+)$/ && ($val >= $1 && $val <= $2)) { $retval = 1 } $retval; } # # disable ($cmd==0) or enable a watch # sub disen_watch { my ($w, $cmd) = @_; return undef if (!defined ($watch{$w})); if (!$cmd) { $watch_disabled{$w} = 1; } else { $watch_disabled{$w} = 0; } } # # disable ($cmd==0) or enable a service # sub disen_service { my ($g, $s, $cmd) = @_; my ($snum); return undef if (!defined $watch{$g}); return undef if (!defined $watch{$g}->{$s}); if (!$cmd) { $watch{$g}->{$s}->{"disable"} = 1; } else { $watch{$g}->{$s}->{"disable"} = 0; } } # # disable ($cmd==0) or enable a host # sub disen_host { my ($h, $cmd) = @_; my $found = undef; foreach my $g (keys %groups) { if ((!defined $cmd) || $cmd == 0) { if (grep (s/^$h$/*$h/, @{$groups{$g}})) { $found = 1; } } else { if (grep (s/^\*$h$/$h/, @{$groups{$g}})) { $found = 1; } } } $found; } sub host_exists { my $host = shift; my $found = 0; foreach my $g (keys %groups) { if (grep (/^$host$/, @{$groups{$g}})) { $found = 1; last; } } $found; } # # given a host, search groups and return an array of group # names which have that host as their only member. return # an empty array if no group found # # sub host_singleton_group { my $host = shift; my @found; foreach my $g (keys %groups) { if (grep (/^\*?$host$/, @{$groups{$g}}) && scalar(@{$groups{$g}}) == 1) { push (@found, $g); } } return (@found); } # # save state # sub save_state { my (@states) = @_; my ($group, $service, @l, $state); foreach $state (@states) { if ($state eq "disabled" || $state eq "all") { if (!open (STATE, ">$CF{STATEDIR}/disabled")) { syslog ("err", "could not write to state file: $!"); next; } foreach $group (keys %groups) { @l = grep (/^\*/, @{$groups{$group}}); if (@l) { grep (s/^\*//, @l); grep { print STATE "disable host $_\n" } @l; } } foreach $group (keys %watch) { if (exists $watch_disabled{$group} && $watch_disabled{$group} == 1) { print STATE "disable watch $group\n"; } foreach $service (keys %{$watch{$group}}) { if (defined $watch{$group}->{$service}->{'disable'} && $watch{$group}->{$service}->{'disable'} == 1) { print STATE "disable service $group $service\n"; } } } close (STATE); } if ($state eq "opstatus" || $state eq "all") { if (!open (STATE, ">$CF{STATEDIR}/opstatus")) { syslog ("err", "could not write to opstatus state file: $!"); next; } foreach $group (keys %watch) { foreach $service (keys %{$watch{$group}}) { print STATE "group=$group\tservice=$service"; foreach my $var (qw(op_status failure_count alert_count last_success first_success consec_failures last_failure first_failure last_summary last_failure_time last_failure_summary last_failure_detail last_detail ack ack_comment last_trap last_traphost exitval last_check last_op_status failure_output trap_timer)) { print STATE "\t$var=" . esc_str($watch{$group}->{$service}->{"_$var"}); } foreach my $periodlabel (keys %{$watch{$group}->{$service}->{periods}}) { foreach my $var (qw(last_alert alert_sent 1stfailtime failcount)) { print STATE "\t$periodlabel:$var=" . esc_str($watch{$group}->{$service}{periods}{$periodlabel}{"_$var"}); } } print STATE "\n"; } } close (STATE); } } } # # load state # sub load_state { my (@states) = @_; my ($l, $cmd, $args, $group, $service, $what, $state); foreach $state (@states) { if ($state eq "disabled" || $state eq "all") { if (!open (STATE, "$CF{STATEDIR}/disabled")) { syslog ("err", "could not read state file: $!"); next; } while (defined ($l = )) { chomp $l; ($cmd, $what, $args) = split (/\s+/, $l, 3); next if ($cmd ne "disable"); if ($what eq "host") { disen_host ($args); } elsif ($what eq "watch") { syslog ("err", "undefined watch reading state file: $l") if (!defined disen_watch ($args)); } elsif ($what eq "service") { ($group, $service) = split (/\s+/, $args, 2); syslog ("err", "undefined group or service reading state file: $l") if (!defined disen_service ($group, $service)); } } syslog ("info", "state '$state' loaded"); close (STATE); } if ($state eq "opstatus" || $state eq "all") { if (!open (STATE, "$CF{STATEDIR}/opstatus")) { syslog ("err", "could not read state file: $!"); next; } while (defined ($l = )) { chomp $l; my %opstatus = map{ /^(.*)=(.*)$/; $1 => $2} split (/\t/, $l,); next unless (exists $opstatus{group} && exists $watch{$opstatus{group}} && exists $opstatus{service} && exists $watch{$opstatus{group}}->{$opstatus{service}}); foreach my $op (keys %opstatus) { next if ($op eq 'group' || $op eq 'service'); if ($op =~ /^(.*):(.*)$/) { next unless exists $watch{$opstatus{group}}->{$opstatus{service}}{periods}{$1}; $watch{$opstatus{group}}->{$opstatus{service}}{periods}{$1}{"_$2"} = un_esc_str($opstatus{$op}); } else { $watch{$opstatus{group}}->{$opstatus{service}}{"_$op"} = un_esc_str($opstatus{$op}); } } } syslog ("info", "state '$state' loaded"); close (STATE); } } } # # authenticate a login # sub auth { my ($type, $user, $plaintext, $host) = @_; my ($pass, %u, $l, $u, $p); if ($user eq "" || ($type ne 'trustlocal' && $plaintext eq "")) { syslog ('err', "an undef username or password supplied"); return undef; } # # standard UNIX passwd # if ($type eq "getpwnam") { (undef, $pass) = getpwnam($user); return undef if (!defined $pass); if ((crypt ($plaintext, $pass)) ne $pass) { return undef; } return 1; # # shadow password # } elsif ($type eq "shadow") { # # "mon" authentication # } elsif ($type eq "userfile") { if (!open (U, $CF{"USERFILE"})) { syslog ('err', "could not open user file '$CF{USERFILE}': $!"); return undef; } while () { next if (/^\s*#/ || /^\s*$/); chomp; ($u,$p) = split (/\s*:\s*/, $_, 2); $u{$u} = $p; } close (U); if (!defined($u{$user})) #user was not found in userfile { syslog('warning', "User '$user' not in file '$CF{USERFILE}'"); return undef; } if ((crypt ($plaintext, $u{$user})) ne $u{$user}) #user gave wrong password { syslog('warning', "User '$user' gave bad password"); return undef; } return 1; # # PAM authentication # } elsif ($type eq "pam") { local $PAM_username = $user; local $PAM_password = $plaintext; my $pamh; if (!ref($pamh = new Authen::PAM($CF{'PAMSERVICE'}, $PAM_username, \&pam_conv_func))) { syslog ('err', "Error code $pamh during PAM init!: $!"); return undef; } my $res = $pamh->pam_authenticate ; return undef if ($res != &Authen::PAM::PAM_SUCCESS) ; return 1; } elsif ($type eq "trustlocal") { # We're configured to trust all authentications from localhost # i.e. cgi scripts are handling authentication themselves return undef if ($host ne "127.0.0.1"); return 1; } else { syslog ('err', "authentication type '$type' not known"); } return undef; } # # load the table of who can do which commands # sub load_auth { my ($startup) = @_; my ($l, $cmd, $users, $u, $host, $user, $password, $sect); %AUTHCMDS = (); %NOAUTHCMDS = (); %AUTHTRAPS = (); $sect = "command"; if (!open (C, $CF{"AUTHFILE"})) { err_startup ($startup, "could not open $CF{AUTHFILE}: $!"); return undef; } while (defined ($l = )) { next if ($l =~ /^\s*#/ || $l =~ /^\s*$/); chomp $l; $l =~ s/^\s*//; $l =~ s/\s*$//; if ($l =~ /^command\s+section/) { $sect = "command"; next; } elsif ($l =~ /^trap\s+section/) { $sect = "trap"; next; } if ($sect eq "command") { ($cmd, $users) = split (/\s*:\s*/, $l, 2); if (!defined $users) { err_startup ($startup, "could not parse line $. of auth file\n"); next; } foreach $u (split (/\s*,\s*/, $users)) { if ( $u =~ /^AUTH_ANY$/ ) { # Allow all authenticated users $AUTHCMDS{"\L$cmd"}{$u} = 1; } elsif ( $u =~ /^!(.*)/ ) { # Directive is to "deny-user" $NOAUTHCMDS{"\L$cmd"}{$1} = 1; } else { # Directive is to "allow-user" $AUTHCMDS{"\L$cmd"}{$u} = 1; } } } elsif ($sect eq "trap") { if ($l !~ /^(\S+)\s+(\S+)\s+(\S+)$/) { syslog ('err', "invalid entry in trap sect of $CF{AUTHFILE}, line $."); next; } ($host, $user, $password) = ($1, $2, $3); if ($host eq "*") { # # allow traps from all hosts # } elsif ($host =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) { if (($host = inet_aton ($host)) eq "") { syslog ('err', "invalid host in $CF{AUTHFILE}, line $."); next; } } elsif ($host =~ /^[A-Z\d][[A-Z\.\d\-]*[[A-Z\d]+$/i) { if (($host = inet_aton ($host)) eq "") { syslog ('err', "invalid host in $CF{AUTHFILE}, line $."); next; } } else { syslog ('err', "invalid host in $CF{AUTHFILE}, line $."); next; } if ($host ne "*") { $host = inet_ntoa ($host); } syslog ('notice', "Adding trap auth of: $host $user $password"); $AUTHTRAPS{$host}{$user} = $password; } else { syslog ('err', "unknown section in $CF{AUTHFILE}: $l"); } } close (C); } sub load_view_users {} sub view_match { my ($view, $group, $service) = @_; if (!defined($view)) { # print STDERR "No view in use\n"; return 1; } if (defined($group) && defined($views{$view}->{$group})) { # print STDERR "View $view contains $group\n"; return 1; } if (defined($views{$view}->{$group.":".$service})) { # print STDERR "View $view contains $group:$service\n"; return 1; } return 0; } # # return undef if $user isn't permitted to perform $cmd # Optional third argument controls logging to syslog. # e.g., # check_auth("joe", "disable") # will check to see if user joe is authorized to disable, and # complain to syslog if joe is not authorized # check_auth("joe", "disable", 1) # will check to see if user joe is authorized to disable but # NOT complain to syslog if joe is not authorized # sub check_auth { my ($user, $cmd, $no_syslog) = @_; # # Check to see if the authenticated user is specifically # denied the ability to run this command. # if ( (defined ($user) && $NOAUTHCMDS{$cmd}{$user}) || (defined ($user) && $NOAUTHCMDS{$cmd}{"AUTH_ANY"}) ) { syslog ("err", "user '$user' tried '$cmd', denied"); return undef; } # # Check for "all". This allows any client, authenticated or # not, to execute the requested command. # return 1 if ($AUTHCMDS{$cmd}{"all"}); # # Check for AUTH_ANY. This allows any authenticated user to # execute the requested command. # return 1 if (defined ($user) && $AUTHCMDS{$cmd}{"AUTH_ANY"}); # # Check to see if the authenticated user is specifically #allowed the ability to run this command. # return 1 if (defined ($user) && $AUTHCMDS{$cmd}{$user}); syslog ("err", "user '$user' tried '$cmd', not authenticated") unless defined($no_syslog); return undef; } # # reload things # sub reload { my (@what) = @_; for (@what) { if ($_ eq "auth") { load_auth; } else { return undef; } } return 1; } sub err_startup { my ($startup, $msg) = @_; if ($startup) { die "$msg\n"; } else { syslog ('err', $msg); } } # # handle a trap # sub handle_trap { my ($buf, $from) = @_; my $time = time; my %trap = (); my $flags = 0; my $tmnow = time; my $intended; my $fromip; # # MON-specific tags # pro protocol # aut auth # usr username # pas password # typ type ("failure", "up", "startup", "trap", "traptimeout") # spc specific type (STAT_OK, etc.) THIS IS NO LONGER USED # seq sequence # grp group # svc service # hst host # sta status (same as exit status of a monitor) # tsp timestamp as time(2) value # sum summary output # dtl detail # # # this part validates the trap # { foreach my $line (split (/\n/, $buf)) { if ($line =~ /^(\w+)=(.*)/) { my $trap_name = $1; my $trap_val = $2; chomp $trap_val; $trap_val =~ s/^\'(.*)\'$/\1/; $trap{$trap_name} = un_esc_str ($trap_val); } else { syslog ('err', "unspecified tag in trap: $line"); } } $trap{"sum"} = "$trap{sum}\n" if ($trap{"sum"} !~ /\n$/); my ($port, $addr) = sockaddr_in ($from); $fromip = inet_ntoa ($addr); # # trap authentication # my ($traphost, $trapuser, $trappass); if (defined ($AUTHTRAPS{"*"})) { $traphost = "*"; } else { $traphost = $fromip; } if (defined ($AUTHTRAPS{$traphost}{"*"})) { $trapuser = "*"; $trappass = ""; } else { $trapuser = $trap{"usr"}; $trappass = $trap{"pas"}; } if (!defined ($AUTHTRAPS{$traphost})) { syslog ('err', "received trap from unauthorized host: $fromip"); return undef; } if ($trapuser ne "*") { if (!defined $AUTHTRAPS{$traphost}{$trapuser}) { syslog ('err', "received trap from unknown user $trapuser, host $traphost"); return undef; } if (crypt ($trappass, $AUTHTRAPS{$traphost}{$trapuser}) ne $AUTHTRAPS{$traphost}{$trapuser}) { syslog ('err', "received trap with bad password from user $trapuser, host $traphost"); return undef; } } # # protocol version # if ($trap{"pro"} < $TRAP_PRO_VERSION) { syslog ('err', "cannot handle traps from version less than $TRAP_PRO_VERSION"); return undef; } # # validate trap type # if (!defined $trap{"sta"}) { syslog ('err', "no trap sta value specified from $fromip"); return undef; } # # if mon receives a trap for an unknown group/service, then the # default/default group/service should catch these if it is defined # if (!defined $watch{$trap{"grp"}} && defined $watch{"default"}) { $intended = "$trap{'grp'}:$trap{'svc'}"; $trap{"grp"} = "default"; } if ($trap{"grp"} eq 'default' && !defined($watch{default}->{$trap{"svc"}}) && defined($watch{'default'}->{'default'})) { $trap{"svc"} = "default"; } if (!defined ($groups{$trap{"grp"}})) { syslog ('err', "trap received for undefined group $trap{grp}"); return; } elsif (!defined $watch{$trap{"grp"}}->{$trap{"svc"}}) { syslog ('err', "trap received for undefined service type $trap{grp}/$trap{svc}"); return; } } # # trap has been validated, proceed # my $sref = \%{$watch{$trap{"grp"}}->{$trap{"svc"}}}; # # a trap recieved resets the trap timeout timer # if (exists $sref->{"traptimeout"}) { $sref->{"_trap_timer"} = $sref->{"traptimeout"}; } $sref->{"_last_trap"} = $time; if ($intended) { $sref->{"_intended"} = $intended; } syslog ('info', "trap $trap{typ} $trap{spc} from " . "$fromip grp=$trap{grp} svc=$trap{svc}, sta=$trap{sta}\n"); $sref->{"_trap_duration_timer"} = $sref->{"trapduration"} if ($sref->{"trapduration"}); process_event ("t", $trap{"grp"}, $trap{"svc"}, $trap{"sta"}, "$trap{sum}\n$trap{dtl}"); if( defined($sref->{"_intended"}) ) { undef($sref->{"_intended"}); } } # # trap timeout # sub handle_trap_timeout { my ($group, $service) = @_; my ($tmnow); $tmnow = time; my $sref = \%{$watch{$group}->{$service}}; $sref->{"_trap_timer"} = $sref->{"traptimeout"}; process_event ("T", $group, $service, 1, "trap timeout\n" . "trap timeout after " . $sref->{"traptimeout"} . "s at " . localtime ($tmnow) . "\n"); } # # write to a socket # sub sock_write { my ($sock, $buf) = @_; my ($nleft, $nwritten); $nleft = length ($buf); while ($nleft) { $nwritten = syswrite ($sock, $buf, $nleft); if (!defined ($nwritten)) { return undef if ($! != EAGAIN); usleep (100000); next; } $nleft -= $nwritten; substr ($buf, 0, $nwritten) = ""; } } # # do I/O processing for traps and client connections # sub handle_io { # # build iovec for server connections, traps, and clients # $iovec = ''; my $niovec = ''; vec ($iovec, fileno (TRAPSERVER), 1) = 1; vec ($iovec, fileno (SERVER), 1) = 1; foreach my $cl (keys %clients) { vec ($iovec, $cl, 1) = 1; } # # handle client I/O while there is some to handle # my $sleep = $SLEEPINT; my $tm0 = [gettimeofday]; my $n; while ($n = select ($niovec = $iovec, undef, undef, $sleep)) { my $tm1 = [gettimeofday]; if ($! != &EINTR) { # # mon trap # if (vec ($niovec, fileno (TRAPSERVER), 1)) { my ($from, $trapbuf); if (!defined ($from = recv (TRAPSERVER, $trapbuf, 65536, 0))) { syslog ('err', "error trying to recv a trap: $!"); } else { handle_trap ($trapbuf, $from); } next; # # client connections # } elsif (vec ($niovec, fileno (SERVER), 1)) { client_accept; } # # read data from clients if any exists # if ($numclients) { foreach my $cl (keys %clients) { next if (!vec ($niovec, $cl, 1)); my $buf = ''; $n = sysread ($clients{$cl}->{"fhandle"}, $buf, 8192); if ($n == 0 && $! != &EAGAIN) { client_close ($cl); } elsif (!defined $n) { client_close ($cl, "read error: $!"); } else { $clients{$cl}->{"buf"} .= $buf; $clients{$cl}->{"timeout"} = $CF{"CLIENT_TIMEOUT"}; $clients{$cl}->{"last_read"} = time; } } } } # # execute client commands which have been read # client_dopending if ($numclients); last if (tv_interval ($tm0, $tm1) >= $SLEEPINT); $sleep = $SLEEPINT - tv_interval ($tm0, $tm1); } if (!defined ($n)) { syslog ('err', "select returned an error for I/O loop: $!"); } # # count down client inactivity timeouts and close expired connections # if ($numclients) { foreach my $cl (keys %clients) { my $timenow = time; $clients{$cl}->{"timeout"} = $timenow - $clients{$cl}->{"last_read"}; if ($clients{$cl}->{"timeout"} >= $CF{"CLIENT_TIMEOUT"}) { client_close ($cl, "timeout after $CF{CLIENT_TIMEOUT}s"); } } } } # # generate alert and monitor path hashes # sub gen_scriptdir_hash { my ($d, @scriptdirs, @alertdirs, $found); %MONITORHASH = (); %ALERTHASH = (); foreach $d (split (/$splitpath/, $CF{"SCRIPTDIR"})) { if (-d "$d" && -x "$d") { push (@scriptdirs, $d); } else { syslog ('err', "scriptdir $d is not usable"); } } foreach $d (split (/$splitpath/, $CF{"ALERTDIR"})) { if (-d $d && -x $d) { push (@alertdirs, $d); } else { syslog ('err', "alertdir $d is not usable"); } } # # monitors # foreach my $group (keys %watch) { foreach my $service (keys %{$watch{$group}}) { next if (!defined $watch{$group}->{$service}->{"monitor"}); my $monitor = (split (/\s+/, $watch{$group}->{$service}->{"monitor"}))[0]; $found = 0; foreach (@scriptdirs) { if (-x "$_/$monitor") { $MONITORHASH{$monitor} = "$_/$monitor" unless (defined $MONITORHASH{$monitor}); $found++; last; } } if (!$found) { syslog ('err', "$monitor not found in one of (\@scriptdirs[@scriptdirs])"); } } } # # alerts # foreach my $group (keys %watch) { foreach my $service (keys %{$watch{$group}}) { if ($watch{$group}->{$service}->{"redistribute"} ne '') { my $alert = $watch{$group}->{$service}->{"redistribute"}; $found = 0; foreach (@alertdirs) { if (-x "$_/$alert") { $ALERTHASH{$alert} = "$_/$alert" unless (defined $ALERTHASH{$alert}); $found++; } } if (!$found) { syslog ('err', "$alert not found in one of (\@alerttdirs[@alertdirs])"); } } foreach my $period (keys %{$watch{$group}->{$service}->{"periods"}}) { foreach my $my_alert ( @{$watch{$group}->{$service}->{"periods"}->{$period}->{"alerts"}}, @{$watch{$group}->{$service}->{"periods"}->{$period}->{"upalerts"}}, @{$watch{$group}->{$service}->{"periods"}->{$period}->{"startupalerts"}}, @{$watch{$group}->{$service}->{"periods"}->{$period}->{"ackalerts"}}, @{$watch{$group}->{$service}->{"periods"}->{$period}->{"disablealerts"}}, ) { my $alert = $my_alert; $alert =~ s/^(\S+=\S+ )*(\S+).*$/$2/; $found = 0; foreach (@alertdirs) { if (-x "$_/$alert") { $ALERTHASH{$alert} = "$_/$alert" unless (defined $ALERTHASH{$alert}); $found++; } } if (!$found) { syslog ('err', "$alert not found in one of (\@alerttdirs[@alertdirs])"); } } } } } } # # do some processing on dirs # sub normalize_paths { my ($authtype, @authtypes); # # do some sanity checks on dirs # $CF{"STATEDIR"} = File::Spec->catdir( ($CF{BASEDIR}, $CF{STATEDIR}) ) if (! File::Spec->file_name_is_absolute($CF{"STATEDIR"})); syslog ('err', "$CF{STATEDIR} does not exist") if (! -d $CF{"STATEDIR"}); $CF{"LOGDIR"} = File::Spec->catdir( ($CF{BASEDIR}, $CF{LOGDIR}) ) if (! File::Spec->file_name_is_absolute($CF{"LOGDIR"})); syslog ('err', "$CF{LOGDIR} does not exist") if (! -d $CF{LOGDIR}); $CF{"AUTHFILE"} = File::Spec->catdir( ($CF{CFBASEDIR}, $CF{AUTHFILE}) ) if (! File::Spec->file_name_is_absolute($CF{"AUTHFILE"})); syslog ('err', "$CF{AUTHFILE} does not exist") if (! -f $CF{"AUTHFILE"}); @authtypes = split(' ' , $CF{"AUTHTYPE"}) ; foreach $authtype (@authtypes) { if ($authtype eq "userfile") { $CF{"USERFILE"} = File::Spec->catdir( ($CF{CFBASEDIR}, $CF{USERFILE}) ) if (! File::Spec->file_name_is_absolute($CF{"USERFILE"})); syslog ('err', "$CF{USERFILE} does not exist") if (! -f $CF{"USERFILE"}); } } $CF{"DTLOGFILE"} = File::Spec->catdir( ($CF{LOGDIR}, $CF{DTLOGFILE}) ) if (! File::Spec->file_name_is_absolute($CF{"DTLOGFILE"})); if ($CF{"HISTORICFILE"} ne "") { $CF{"HISTORICFILE"} = File::Spec->catdir( ($CF{LOGDIR}, $CF{HISTORICFILE}) ) if (! File::Spec->file_name_is_absolute($CF{"HISTORICFILE"})); } # # script and alert dirs may have multiple paths # foreach my $dir (\$CF{"SCRIPTDIR"}, \$CF{"ALERTDIR"}) { my @n; foreach my $d (split (/$splitpath/, $$dir)) { $d =~ s{/$}{}; $d = File::Spec->catdir( ($CF{BASEDIR}, $d) ) if (! File::Spec->file_name_is_absolute($d)); syslog ('err', "$d does not exist, check your alertdir and mondir paths") unless (-d $d); push @n, $d; } $$dir = join ($joinpath, @n); } } # # set opstatus and save old status # sub set_op_status { my ($group, $service, $status) = @_; $watch{$group}->{$service}->{"_last_op_status"} = $watch{$group}->{$service}->{"_op_status"}; $watch{$group}->{$service}->{"_op_status"} = $status; } sub debug_dir { print STDERR < 1, $STAT_LINKDOWN => 1, $STAT_TIMEOUT => 1, ); %SUCCESS = ( $STAT_OK => 1, $STAT_COLDSTART => 1, $STAT_WARMSTART => 1, $STAT_UNKNOWN => 1, $STAT_UNTESTED => 1, ); %WARNING = ( $STAT_COLDSTART => 1, $STAT_WARMSTART => 1, $STAT_UNKNOWN => 1, $STAT_WARN => 1, ); %OPSTAT = ("fail" => $STAT_FAIL, "ok" => $STAT_OK, "coldstart" => $STAT_COLDSTART, "warmstart" => $STAT_WARMSTART, "linkdown" => $STAT_LINKDOWN, "unknown" => $STAT_UNKNOWN, "timeout" => $STAT_TIMEOUT, "untested" => $STAT_UNTESTED); # # fast lookup hashes for alerts and monitors # %MONITORHASH = (); %ALERTHASH = (); } # # clear timers # sub clear_timers { my ($group, $service) = @_; return undef if (!defined $watch{$group}->{$service}); my $sref = \%{$watch{$group}->{$service}}; $sref->{"_trap_timer"} = $sref->{"traptimeout"} if ($sref->{"traptimeout"}); $sref->{"_trap_duration_timer"} = $sref->{"trapduration"} if ($sref->{"trapduration"}); $sref->{"_timer"} = $sref->{"interval"} if ($sref->{"interval"}); $sref->{"_consec_failures"} = 0 if ($sref->{"_consec_failures"}); foreach my $period (keys %{$sref->{"periods"}}) { my $pref = \%{$sref->{"periods"}->{$period}}; $pref->{"_last_alert"} = 0 if ($pref->{"alertevery"}); $pref->{"_consec_failures"} = 0 if ($pref->{"alertafter_consec"}); $pref->{'_1stfailtime'} = 0 if ($pref->{"alertafterival"}); } } # # load some amount of the alert history into memory # sub readhistoricfile { return if ($CF{"HISTORICFILE"} eq ""); if (!open (HISTFILE, $CF{"HISTORICFILE"})) { syslog ('err', "Could not read history from $CF{HISTORICFILE} : $!"); return; } my $epochLimit = 0; if ($CF{"HISTORICTIME"} != 0) { $epochLimit = time - $CF{"HISTORICTIME"}; } @last_alerts = (); while () { next if (/^\s*$/ || /^\s*#/); chomp; my $epochAlert = (split(/\s+/))[3]; push (@last_alerts, $_) if ($epochAlert >= $epochLimit); } close (HISTFILE); if (defined $CF{"MAX_KEEP"}) { splice(@last_alerts, 0, $#last_alerts + 1 - $CF{"MAX_KEEP"}); } } # # This routine simply calls an alert. # # call with %args = ( # group => "name of group", # service => "name of service", # pref => "optional period reference", # alert => "alert script", # args => "args to alert script", # flags => "flags, as in $FL_*", # retval => "return value of monitor", # output => "output of monitor", # ) # sub call_alert { my (%args) = @_; foreach my $mandatory_arg (qw(group service flags retval alert output)) { if (!exists $args{$mandatory_arg}) { debug (1, "returning from call_alert because of missing arg $mandatory_arg\n"); return (undef); } } my @groupargs = grep (!/^\*/, @{$groups{$args{"group"}}}); my $tmnow = time; my ($summary) = split("\n", $args{"output"}); $summary = "(NO SUMMARY)" if (!defined $summary || $summary =~ /^\s*$/m); my $sref = \%{$watch{$args{"group"}}->{$args{"service"}}}; my $pref; if (defined $args{"pref"}) { $pref = $args{"pref"}; } if (! defined $args{"args"}) { $args{"args"} = ''; } my $alert = ""; if (!defined $ALERTHASH{$args{"alert"}} || ! -f $ALERTHASH{$args{"alert"}}) { syslog ('err', "no alert found while trying to run $args{alert}"); return undef; } else { $alert = $ALERTHASH{$args{"alert"}}; } my $alerttype = ""; # sent to syslog and stored in @last_alerts my $alert_type = "failure"; # MON_ALERTTYPE set to this if ($args{"flags"} & $FL_UPALERT) { $alerttype = "upalert"; $alert_type = "up"; } elsif ($args{"flags"} & $FL_STARTUPALERT) { $alerttype = "startupalert"; $alert_type = "startup"; } elsif ($args{"flags"} & $FL_ACKALERT) { $alerttype = "ackalert"; $alert_type = "ack"; } elsif ($args{"flags"} & $FL_DISABLEALERT) { $alerttype = "disablealert"; $alert_type = "disable"; } elsif ($args{"flags"} & $FL_TRAPTIMEOUT) { $alerttype = "traptimeoutalert"; $alert_type = "traptimeout"; } elsif ($args{"flags"} & $FL_TRAP) { $alerttype = "trapalert"; $alert_type = "trap"; } elsif ($args{"flags"} & $FL_TEST) { $alerttype = "testalert"; $alert_type = "test"; } else { $alerttype = "alert"; } # # log why we are triggering an alert # my $a = $alert; $a =~ s{^.*/([^/]+)$}{$1}; syslog ("alert", "calling $alerttype $a for" . " $args{group}/$args{service} ($alert,$args{args}) $summary") if (!($args{"flags"} & $FL_REDISTRIBUTE));; # We may block while writing to the alert script, so we'll fork first, allowing the # master process to move on. my $pid; if ($pid = fork()) { ## Master # Do Nothing } elsif (defined($pid)) { ## Child my $pid = open (ALERT, "|-"); if (!defined $pid) { syslog ('err', "could not fork: $!"); return undef; } # # grandchild, the actual alert # if ($pid == 0) { # # set env variables to pass to the alert # foreach my $v (keys %{$sref->{"ENV"}}) { $ENV{$v} = $sref->{"ENV"}->{$v}; } $ENV{"MON_LAST_SUMMARY"} = $sref->{"_last_summary"} if (defined $sref->{"_last_summary"}); $ENV{"MON_LAST_OUTPUT"} = $sref->{"_last_output"} if (defined $sref->{"_last_output"}); $ENV{"MON_LAST_FAILURE"} = $sref->{"_last_failure"} if (defined $sref->{"_last_failure"}); $ENV{"MON_FIRST_FAILURE"} = $sref->{"_first_failure"} if (defined $sref->{"_first_failure"}); $ENV{"MON_FIRST_SUCCESS"} = $sref->{"_first_success"} if (defined $sref->{"_last_success"}); $ENV{"MON_LAST_SUCCESS"} = $sref->{"_last_success"} if (defined $sref->{"_last_success"}); $ENV{"MON_DESCRIPTION"} = $sref->{"description"} if (defined $sref->{"description"}); $ENV{"MON_GROUP"} = $args{"group"} if (defined $args{"group"}); $ENV{"MON_SERVICE"} = $args{"service"} if (defined $args{"service"}); $ENV{"MON_RETVAL"} = $args{"retval"} if (defined $args{"retval"}); $ENV{"MON_OPSTATUS"} = $sref->{"_op_status"} if (defined $sref->{"_op_status"}); $ENV{"MON_ACK"} = $sref->{"_ack_comment"} if ($sref->{"_ack"} && $sref->{"_ack_comment"} ne ""); $ENV{"MON_ALERTTYPE"} = $alert_type; $ENV{"MON_STATEDIR"} = $CF{"STATEDIR"}; $ENV{"MON_LOGDIR"} = $CF{"LOGDIR"}; $ENV{"MON_CFBASEDIR"} = $CF{"CFBASEDIR"}; if( defined($sref->{"_intended"}) ) { $ENV{"MON_TRAP_INTENDED"} = $sref->{"_intended"}; } else { undef ($ENV{"MON_TRAP_INTENDED"}) if (defined($ENV{"MON_TRAP_INTENDED"})); } my $t; $t = "-u" if ($args{"flags"} & $FL_UPALERT); $t = "-a" if ($args{"flags"} & $FL_ACKALERT); $t = "-D" if ($args{"flags"} & $FL_DISABLEALERT); $t = "-T" if ($args{"flags"} & $FL_TRAP); $t = "-O" if ($args{"flags"} & $FL_TRAPTIMEOUT); my @execargs = ( $alert, "-s", "$args{service}", "-g", "$args{group}", "-h", "@groupargs", "-t", "$tmnow", ); if ($t) { push @execargs, $t; } if ($args{"args"} ne "") { push @execargs, quotewords('\s+',0,$args{"args"}); } if (!exec @execargs) { syslog ('err', "could not exec alert $alert: $!"); return undef; } exit; } # # this will block if the alert is sucking gas, which is why we forked above # print ALERT $args{"output"}; close (ALERT); exit; } # # test alerts and redistributions don't count # return (1) if ($args{"flags"} & ($FL_TEST | $FL_REDISTRIBUTE)); # # tally this alert # if (defined $args{"pref"}) { $pref->{"_last_alert"} = $tmnow; } $sref->{"_alert_count"}++; # # store this in the log # shift @last_alerts if (@last_alerts > $CF{"MAX_KEEP"}); my $alertline = "$alerttype $args{group} $args{service}" . " $tmnow $alert ($args{args}) $summary"; push @last_alerts, $alertline; # # append to alert history file # if ($CF{"HISTORICFILE"} ne "") { if (!open (HISTFILE, ">>$CF{HISTORICFILE}")) { syslog ('err', "Could not append alert history to $CF{HISTORICFILE}: $!"); } else { print HISTFILE $alertline, "\n"; close (HISTFILE); } } return 1; } # # recursively evaluate a dependency expression # substitutes "GROUP:SERVICE" with "1" or "0" if the service is pass/fail, resp. # # returns an anonymous hash reference # # { # status =>, # "D" recursion depth exceeded # # "O" everything is OK # # "E" eval error # depend =>, # 1 for success (no deps in a failure state) # # 0 if any deps failed # error =>, # the textual error associated with "D" or "E" status # } # sub depend { my ($depend, $depth, $deptype) = @_; debug (2, "checking DEP [$depend]\n"); if ($depth > $CF{"DEP_RECUR_LIMIT"}) { return { status => "D", depend => undef, error => "recursion too deep for ($depend)", }; } foreach my $depstr ($depend =~ /[a-zA-Z0-9_.-]+:[a-zA-Z0-9_.-]+/g) { my ($group ,$service) = split(':', $depstr); my $sref = \%{$watch{$group}->{$service}}; my $depval = undef; my $subdepend = ""; if (defined $sref->{"depend"} && $sref->{"dep_behavior"} eq $deptype) { $subdepend = $sref->{"depend"}; } elsif ($deptype eq 'a' && defined $sref->{"alertdepend"}) { $subdepend = $sref->{"alertdepend"}; } elsif ($deptype eq 'm' && defined $sref->{"monitordepend"}) { $subdepend = $sref->{"monitordepend"}; } # # disabled watches and services used to be counted as "passing" # now we'll use the actual values, to avoid having dependent services # alert when a broken service gets disabled # # if ((exists $watch_disabled{$group} && $watch_disabled{$group}) || (defined $sref->{"disable"} && $sref->{"disable"} == 1)) # { # $depval = 1; # # # root dependency found # # } # elsif ($subdepend eq "") if ($subdepend eq "") { debug (2, " found root dep $group,$service\n"); $depval = $SUCCESS{$sref->{"_op_status"}} && ($sref->{"_last_failure_time"} < (time - $sref->{"dep_memory"})); # # not a root dep, recurse # } else { # # do it recursively # my $dstatus = depend ($subdepend, $depth + 1, $deptype); debug (2, "recur depth $depth returned $dstatus->{status},$dstatus->{depend}\n"); # # a bad thing happened, bail out # if ($dstatus->{"status"} ne "O") { debug (2, "recursive dep failure for $group,$service (status=$dstatus->{status})\n"); return $dstatus; } $depval = $dstatus->{"depend"} && $SUCCESS{$sref->{"_op_status"}} && ($sref->{"_last_failure_time"} < (time - $sref->{"dep_memory"})); } my $v = int ($depval); debug (2, " ($group,$service) $depth depend=[$v][$depend]"); $depend =~ s/\b$depstr\b/$v/g; debug (2, " depend=[$depend]\n"); } debug (2, " before eval: [$depend]"); my $e = eval("$DEP_EVAL_SANDBOX $depend"); debug (2, " after eval: [$e]\n"); if ($@ eq "") { return { status => "O", depend => $e, }; } else { return { status => "E", depend => $e, error => $@, }; } } # # returns undef on error # 0 if dependency failure, sets _depend_status to 0 # 1 if dependencies are OK, sets _depend_status to 1 # sub dep_ok { my $sref = shift; my $deptype = shift; my $depend = ""; if (defined $sref->{"depend"} && $sref->{"dep_behavior"} eq $deptype) { $depend = $sref->{"depend"}; } elsif ($deptype eq 'a' && defined $sref->{"alertdepend"}) { $depend = $sref->{"alertdepend"}; } elsif ($deptype eq 'm' && defined $sref->{"monitordepend"}) { $depend = $sref->{"monitordepend"}; } return 1 unless ($depend ne ""); my $s = depend ($depend, 0, $deptype); if ($s->{"status"} eq "D") { debug (2, "dep recursion too deep\n"); return undef; } elsif ($s->{"status"} eq "E") { syslog ("notice", "eval error for dependency starting at $depend: ".$s->{error}); return undef; } elsif ($s->{"status"} eq "O" && !$s->{"depend"}) { $sref->{"_depend_status"} = 0; return 0; } $sref->{"_depend_status"} = 1; return 1; } # # returns undef on error # otherwise a reference to a list summaries from all # DIRECT dependencies currently failing sub dep_summary { my $sref = shift; my @sum; my @deps = (); if (defined $sref->{"depend"} && $sref->{"dep_behavior"} eq "hm") { @deps = ($sref->{"depend"} =~ /[a-zA-Z0-9_.-]+:[a-zA-Z0-9_.-]+/g); } elsif (defined $sref->{"hostdepend"}) { @deps = ($sref->{"hostdepend"} =~ /[a-zA-Z0-9_.-]+:[a-zA-Z0-9_.-]+/g); } return [] if (! @deps); foreach (@deps) { my ($group, $service) = split /:/; if (!(exists $watch{$group} && exists $watch{$group}->{$service})) { return undef; } if ($watch{$group}->{$service}{"_op_status"} == $STAT_FAIL) { push @sum, $watch{$group}->{$service}{"_last_summary"}; } elsif ($watch{$group}->{$service}{"_last_failure_time"} >= (time - $watch{$group}->{$service}{"dep_memory"})) { push @sum, $watch{$group}->{$service}{"_last_failure_summary"}; } } return \@sum; } # # convert a string to a hex-escaped string, returning # the escaped string. # # $str is the string to be escaped # if $inquotes is true, backslashes are doubled, making # the escaped string suitable to be enclosed in # single quotes and later passed to Text::quotewords. # For example, var='quoted value' # sub esc_str { my $str = shift; my $inquotes = shift; my $escstr = ""; return $escstr if (!defined $str); for (my $i = 0; $i < length ($str); $i++) { my $c = substr ($str, $i, 1); if (ord ($c) <= 32 || ord ($c) > 126 || $c eq "\"" || $c eq "\'") { $c = sprintf ("\\%02x", ord($c)); } elsif ($inquotes && $c eq "\\") { $c = "\\\\"; } $escstr .= $c; } $escstr; } # # convert a hex-escaped string into an unescaped string, # returning the unescaped string # sub un_esc_str { my $str = shift; $str =~ s{\\([0-9a-f]{2})}{chr(hex($1))}eg; $str; } sub syslog_die { my $msg = shift; syslog ("err", $msg); die "$msg\n"; } no warnings; # Redefining syslog sub syslog { my @args = @_; eval { local $SIG{"__DIE__"}= sub { }; my @log = map { s/\%//mg; $_ } @args; Sys::Syslog::syslog(@log); } } use warnings; # # Have a "conversation" with a PAM authentication module. This fools the # PAM module into authenticating us non-interactively. # sub pam_conv_func { my @res; while ( @_ ) { my $code = shift; my $msg = shift; my $ans = ""; $ans = $PAM_username if ($code == Authen::PAM::PAM_PROMPT_ECHO_ON() ); $ans = $PAM_password if ($code == Authen::PAM::PAM_PROMPT_ECHO_OFF() ); push @res, Authen::PAM::PAM_SUCCESS(); push @res, $ans; } push @res, Authen::PAM::PAM_SUCCESS(); return @res; } sub write_dtlog { my ($sref, $group, $service) = @_; my $tmnow = time; $sref->{"_first_failure"} = $START_TIME if ($sref->{"_first_failure"} == 0); if (!open (DTLOG, ">>$CF{DTLOGFILE}")) { syslog ('err', "could not append to $CF{DTLOGFILE}: $!"); $CF{"DTLOGGING"} = 0; } else { $CF{"DTLOGGING"} = 1; print DTLOG ($tmnow, " $group", " $service", " ", 0 + $sref->{"_first_failure"}, " ", 0 + $tmnow - $sref->{"_first_failure"}, " ", 0 + $sref->{'interval'}, " $sref->{'_last_summary'}\n") or syslog ('err', "error writing to $CF{DTLOGFILE}: $!"); close(DTLOG); } } # Perl's "system" function blocks. We don't want the mon process to # ever block. So we fork then call system. Mon will handle the # child process cleanup elsewhere. sub mysystem { my @args = @_; my $pid; print STDERR "mysystem called: @args\n"; if ($pid = fork()) { ## parent return; } elsif (defined($pid)) { ## child system(@args); exit(0) } else { ## parent - fork failed print STDERR "You lose!\n"; } print STDERR "mysystem returning\n"; }; etbemon-1.3.6/mon-local.d/0000755000000000000000000000000014203606346012147 5ustar etbemon-1.3.6/mon-local.d/Makefile0000644000000000000000000000050114173222105013574 0ustar ALLPROGS=deleted-mapped.monitor all: $(ALLPROGS) # use -Wno-write-strings to make it easy to deal with exec() taking pointers # to non-const data WFLAGS=-Wall -W -Wshadow -Wpointer-arith -Wcast-align -Wcast-qual -pedantic -Wno-write-strings CC=gcc -O2 -g $(WFLAGS) %: %.cpp $(CC) $< -o $@ clean: rm -f $(ALLPROGS) etbemon-1.3.6/mon-local.d/btrfs.monitor0000755000000000000000000000560413455624426014717 0ustar #!/usr/bin/perl use strict; use Getopt::Std; # Mon script to check BTRFS error count # Options: list of BTRFS mount points # /var/lib/mon has files named btrfs-$MOUNTPOINT.count (with "root" for the # root filesystem) that lists the number of acceptable errors. EG if your # root filesystem once had a single error and that's considered OK put 1 in # /var/lib/mon/btrfs-root.count # For mountpoints other than /, all '/' characters in the path will be replaced # by '-' characters. # if you have less errors than specified (IE you replaced an error without # changing the count file accordingly) then it also flags an error condition. # if you need to support a range of errors (EG you expect that a scrub will # generate a dozen errors and do not need alerts about that) then have the # low and high ends of the range seperated by :. EG "100:110" means that any # number of errors between 100 and 110 inclusive is expected and not something # to give a notification. # # Option -s is the maximum number of subvols, default 500. # Copyright Russell Coker GPLv3 my $failed = ""; my $warnings = ""; our $opt_s = 500; getopts("s:"); foreach my $test (@ARGV) { open(BTRFS, "/usr/lib/mon/bin/btrfs.helper $test 2>&1 ) { if($_ =~ /^ERROR/ || $_ =~ /not found/) { $failed .= "$test : $_"; } if($_ =~ /^ID/) { # on to the subvol list phase last; } if($_ !~ /\ [0-9]$/) { $warnings .= ""; } chomp; $_ =~ s/^.*\ //; $testcount += $_; } my $subvolcount = 1; while() { if($_ =~ /^ID/) { $subvolcount++; } else { $failed .= "$test getting subvol list"; } } close(BTRFS); if($subvolcount > $opt_s) { $failed .= "$test subvol $subvolcount > $opt_s "; $warnings .= "$test has $subvolcount subvols should only have $opt_s\n"; } if($testcount > 0) { my @okcount; my $okhigh = 0; my $oklow = 0; my $filename; if($test eq "/") { $filename = "/var/lib/mon/btrfs-root.count"; } else { $filename = $test; $filename =~ s/\//-/g; $filename = "/var/lib/mon/btrfs" . $filename . ".count"; } if(open(COUNT, "<$filename")) { my $line = ; chomp $line; close(COUNT); my @okcount = split(/:/, $line); if($okcount[1]) { $okhigh = $okcount[1]; $oklow = $okcount[0]; } else { $okhigh = $okcount[0]; $oklow = $okcount[0]; } } if($testcount > $okhigh) { $failed .= "$test has error count $testcount > $okhigh "; } elsif($testcount < $oklow) { $failed .= "$test has error count $testcount < $oklow so you replaced a disk without fixing $filename "; } } } if($failed ne "") { print "$failed\n$warnings"; exit(1); } exit(0); etbemon-1.3.6/mon-local.d/deleted-mapped.monitor.cpp0000644000000000000000000000046413604576002017216 0ustar #include #include #include #include int main() { char * const child_args[] = { "/usr/lib/mon/mon-local.d/deleted-mapped.monitor.real", NULL }; execv(child_args[0], child_args); fprintf(stderr, "ERROR: Can't execute %s\n", child_args[0]); return 1; } etbemon-1.3.6/mon-local.d/deleted-mapped.monitor.real0000755000000000000000000000727014022323560017356 0ustar #!/usr/bin/perl use strict; use Getopt::Std; # Check for programs that have deleted files mapped, this can be due to # packages replaced to fix security issues. # Don't check systemd programs (which can cause problems if restarted in # # The option -u specifies the maximum UID to report on, default 999 # (Debian regular users start at 1000) our $opt_u = 999; getopts("u:"); opendir(my $dh, "/proc") || die "Can't opendir /proc: $!"; my @procs = grep { /^[0-9]+$/ && -d "/proc/$_" } readdir($dh); closedir $dh; my %uniq_file; my %root_procs; my %non_root_procs; foreach ( @procs ) { my $pid_num = $_; my $proc_name = readlink("/proc/$pid_num/exe"); if($proc_name =~ /^\/lib\/systemd\/systemd/ or $proc_name eq "/usr/bin/dbus-daemon") { next; } if($proc_name =~ /^\/usr\/sbin\/sshd/ && open(CMD, "; close(CMD); if($name =~ /sshd: [a-z][a-z0-9]* .priv/) { next; } } my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks) = stat("/proc/$pid_num"); if($uid > $opt_u) { next; } my $maps_file = "/proc/$_/maps"; my $status_file = "/proc/$_/status"; if(not open(MAP, "<$maps_file")) { next; } # /memfd: is for memfd https://dvdhrm.wordpress.com/tag/memfd/ # what is /[aio] ? # ignore things under /home as some programs map files in user home dir and # unlink them. # ignore /run/user for files under $XDG_RUNTIME_DIR (/run/user/$UID) # ignore /dev/zero as that is different for each map and thus looks deleted # ignore /tmp/ as Python creates temporary files there for mapping # ignore /var/lib as lots of programs manage their own temporary files there # ignore /i915 which is used by some X apps on systems with Intel video # # temporarily ignore /etc/selinux/default/contexts/files/* for systemd my @del = grep { !/\/etc\/selinux\/default/ } grep { !/\/i915/ } grep { !/\/var\/lib\// } grep { !/\/tmp\// } grep { !/\/home/ } grep { !/\/run\/user/ } grep { !/\/dev\/zero/ } grep { !/\/dev\/shm\// } grep { !/\/SYSV/ } grep { !/\/memfd:/ } grep { !/\/\[aio\]/ } grep { /deleted.$/ } ; close(MAP); next if($#del == -1); for (@del) { chomp; s/^.* //; s/..deleted.*$//; $uniq_file{$_}++; } my $uid = 1; if(not open(STATUS, "<$status_file")) { $uid = 0; } else { while() { if($_ =~ /^Uid:/ or $_ =~ /^Gid:/) { chomp; my @uid_arr = split(' ', $_); if($uid_arr[1] == 0 or $uid_arr[2] == 0 or $uid_arr[3] == 0 or $uid_arr[4] == 0) { $uid = 0; } } } } if($proc_name) { if($uid == 0) { $root_procs{$proc_name} .= " $pid_num"; } else { $non_root_procs{$proc_name} .= " $pid_num"; } } # printf("PID:%s, deleted: %s\n", $_, join(' ', keys(%uniq_file))); } my $file_count = keys %uniq_file; if($file_count == 0) { exit(0); } my $root_count = keys %root_procs; my $non_root_count = keys %non_root_procs; if($root_count == 0) { print "$file_count deleted mapped files, $non_root_count processes\n"; } else { if($non_root_count == 0) { print "$file_count deleted mapped files, $root_count root owned processes\n"; } else { print "$file_count deleted mapped files, $root_count root owned and $non_root_count non-root processes\n"; } print "$root_count root programs:\n"; for(keys %root_procs){ print "$_: $root_procs{$_}\n"; } print "\n"; } if($non_root_count != 0) { print "$non_root_count non-root programs:\n"; for(keys %non_root_procs){ print "$_: $non_root_procs{$_}\n"; } print "\n"; } print "$file_count deleted mapped files:\n"; for(keys %uniq_file){ print("$_\n"); } exit(1); etbemon-1.3.6/mon-local.d/dell-temp.monitor0000755000000000000000000000123114174476601015451 0ustar #!/usr/bin/perl use strict; # Mon script to check Dell server temperature via "omreport chassis temps" open(SENSORS, "/opt/dell/srvadmin/bin/omreport chassis temps|") or die "Can't run omreport"; my $status = ""; my $count = 0; my $err = ""; my $all = ""; while() { $all .= $_; chomp; if($_ =~ /^Status/) { $_ =~ s/^.*: //; $status = $_; } elsif($_ =~ /^Probe Name/) { if($status =~ /Ok/) { $count++; $status = ""; next; } $_ =~ s/^.*: //; $err .= "$_($status) "; } } close(SENSORS); if(length($err) > 0) { print "$err\n"; print $all; exit(1); } print "$count sensors ok\n"; exit(0); etbemon-1.3.6/mon-local.d/freespace.monitor0000755000000000000000000000721713733113703015524 0ustar #!/usr/bin/perl use strict; use Filesys::Df; use Sys::Filesystem; # # Monitor disk space usage # # Arguments are: # # path:freespace[:freeinodes] [path:freespace[:freeinodes]...] # or # path:free%[:freeinodes] [path:free%[:freeinodes]...] # # This script will exit with value 1 if "path" has less than # "freespace" or less than "free" percent available. # the freespace defaults to kilobytes but can have M, G, or T appended to # measure in MiB, GiB, or TiB. # # This script will check for the path being a mountpoint, if it is not then # assume that filesystem was umounted and give error # # The first output line is a list of the paths which failed, and # how much space is free, in megabytes. # # If you are testing NFS-mounted directories, should probably # mount them with the ro,intr,soft options, so that operations # on those mount points don't block forever if the server is # down, and I may eventually change this code to use an alarm(2) # to interrupt the stat and statfs system calls. # # This requires Fabien Tassin's Filesys::Df module, available from # your friendly neighborhood CPAN mirror. See http://www.perl.com/perl/ # That is in the Debian package libfilesys-df-perl # # Jim Trocki, trockij@arctic.org # # Russell Coker # Added support for MiB, GiB, and TiB # Added check for Inodes (default 10%) # Made it work with Strict. # # $Id: freespace.monitor,v 1.2 2005/04/17 07:42:27 trockij Exp $ # # Copyright (C) 1998, Jim Trocki # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # my @failures; my $fs = new Sys::Filesystem; my @mounts = $fs->mounted_filesystems(); foreach (@ARGV) { my ($path, $minavail, $mininodes) = split (/:/, $_, 3); if(not grep(/^$path$/, @mounts)) { push (@failures, "$path is not a mount point"); next; } my $ref = df ($path); if (!defined($ref)) { push (@failures, "statfs error for $path: $!"); next; } # for debugging #foreach my $key (keys %$ref) #{ # print "$key:$ref->{$key}\n"; #} if ($minavail =~ /(\d+(\.\d+)?)%/o) { $minavail = int(($ref->{blocks}) * $1 / 100); } elsif ($minavail =~ /[Mm]$/) { $minavail *= 1024; } elsif ($minavail =~ /[Gg]$/) { $minavail *= 1024 * 1024; } elsif ($minavail =~ /[Tt]$/) { $minavail *= 1024 * 1024 * 1024; } if (defined($mininodes)) { if(!defined($ref->{files})) { push (@failures, sprintf ("%s doesn't tell us how many Inodes are free", $path)); next; } if($mininodes =~ /(\d+(\.\d+)?)%/o) { $mininodes = int(($ref->{files}) * $1 / 100); } } # by default check for 10% free Inodes elsif (defined($ref->{files})) { $mininodes = int(($ref->{files}) / 10); } if ($ref->{bavail} < $minavail) { push (@failures, sprintf ("%1.1fGB free on %s", $ref->{bavail} / 1024 / 1024, $path)); } if (defined($mininodes) && $ref->{ffree} < $mininodes) { push (@failures, sprintf ("%d inodes free on %s", $ref->{ffree}, $path)); } } if (@failures) { print join (", ", @failures), "\n"; exit 1; } exit 0; etbemon-1.3.6/mon-local.d/hp-temp.monitor0000755000000000000000000000441014200704126015124 0ustar #!/usr/bin/perl use strict; use Getopt::Std; # Mon script to check HP server temperature via a setuid wrapper around the # "hplog" program. # # Takes any line containing "Normal" to be good, anything else is bad. # Copyright Russell Coker GPLv3 # # Use -i to specify a comma separated list of ID numbers to ignore, EG # -i2,4 # Use -f for Fahrenheit open(SENSORS, "/usr/lib/mon/bin/hplog.helper|") or die "Can't run hplog"; my $line_id = ""; my $input = 0; my $summary = ""; my $failed = ""; my @ignore_list; my $temp_ignore = "[- 1-9][- 0-9][-0-9]F."; our $opt_f; our $opt_i; getopts("i:f"); if($opt_f) { $temp_ignore = ".[- 1-9][- 0-9][-0-9]C"; } if(length($opt_i) > 0) { foreach my $item (split(/,/, $opt_i)) { $ignore_list[$item] = 1; } } # this is written for a hplog output line having 2 characters for the ID num, a # space, then 28 characters for the description, 8 characters for the status, # and then temperatures. my $goodcount = 0; while() { chomp; next if(not $_ =~ /^[ 1-9][0-9] /); if($_ =~ /Normal/) { $goodcount++; next; } $line_id = substr($_, 0, 2); next if($ignore_list[$line_id] == 1); my $name = substr($_, 4, 28); $name =~ s/ *$//; $name =~ s/Basic Sensor/Bas:/; $summary .= ", " if(length($summary) > 0); $summary .= $name; $_ =~ s/$temp_ignore//g; $failed .= "$_\n"; } if(length($failed) == 0) { print "$goodcount sensors ok\n"; exit(0); } print "$summary\n"; print $failed; my $format = "%8s %5s %4s %8s %s\n"; my $ccount = 0; my $output = ""; use Proc::ProcessTable; my $process_table = new Proc::ProcessTable('cache_ttys' => 0 ); foreach my $p ( sort { $b->pctcpu <=> $a->pctcpu } @{$process_table->table} ) { if($ccount > 9 || $p->pctcpu < 5.0) { last; } $ccount++; my $name; $name = getpwuid($p->uid) or $name = $p->uid; my $cmd = $p->cmndline, 0, 60; if(length($cmd) == 0) { $cmd = "[" . $p->fname . "]"; } $cmd = substr($cmd, 0, 60); my $devname = $p->ttydev; $devname =~ s/\/dev\///; $output .= sprintf($format, $name, sprintf("%5d", $p->pid), sprintf("%4.1f", $p->pctcpu), $devname, $cmd); } if($ccount > 0) { print "\nHere are processes with the top CPU percentages:\n"; printf($format, "USER", "PID", "CPU", "TTY", "COMMAND"); print "$output\n"; } exit(1); etbemon-1.3.6/mon-local.d/linux-temp.monitor0000755000000000000000000000621214200704061015654 0ustar #!/usr/bin/perl use strict; use Getopt::Std; # Mon script to check Linux system temperature via the "sensors" program. # Copyright Russell Coker GPLv3 # # Use -p to specify the percentage of maximum temperature that is an error, # default 90% # Use -c to specify the maximum number of CPU cores that may be over # temperature without an alert, default 0 open(SENSORS, "/usr/bin/sensors -u -A 2> /dev/null|") or die "Can't run sensors"; my $section = ""; my $section_id = ""; my $input = 0; my $max = 0; my $percent = 90; my $failed = ""; my $core_failed = ""; my $max_cores = 0; our $opt_c = 0; our $opt_p = 0; getopts("c:i:p:"); $max_cores = $opt_c; if($opt_p > 0) { $percent = $opt_p; } my $worst = ""; my $worst_percent = 0; my $name = ""; my $section_count = 0; while() { chomp; if(length($name) == 0) { $name = $_; } # if we have the start of a temperature reading section or the end of a group if($_ =~ /:$/ || length($_) == 0) { # if we have just finished a section if($max > 0 && $input > 0) { $section_count++; my $test_percent = $input * 100 / $max; my $line; if($test_percent > $percent) { if($section =~ /^Core/) { $line = "$name $section($section_id): $input > $percent\% of $max\n"; $core_failed .= $line; $max_cores--; } else { $line = "$name($section_id): $input > $percent\% of $max\n"; $failed .= $line; } } if($test_percent > $worst_percent) { $worst = $line; $worst_percent = $test_percent; } } $section = $_; $max = 0; $input = 0; if(length($_) == 0) { $name = ""; } next; } my $line = $_; $line =~ s/^ *//; if($line =~ /^temp/) { my $num = $line; $num =~ s/^.*: //; if($line =~ /_input/) { $input = $num; $section_id = $line; $section_id =~ s/^temp//; $section_id =~ s/_input.*$//; } elsif($line =~ /_max:/ && $num > 0) { $max = $num; } elsif($line =~ /_crit:/ && $num > 0 && $max == 0) { $max = $num; } if($max > 120) { $max = 120; } } } if(length($failed) == 0 && $max_cores >= 0) { print "$section_count sensors ok\n"; exit(0); } print $worst; print $core_failed; print $failed; my $format = "%8s %5s %4s %8s %s\n"; my $ccount = 0; my $output = ""; use Proc::ProcessTable; my $process_table = new Proc::ProcessTable('cache_ttys' => 0 ); foreach my $p ( sort { $b->pctcpu <=> $a->pctcpu } @{$process_table->table} ) { if($ccount > 9 || $p->pctcpu < 5.0) { last; } $ccount++; my $name; $name = getpwuid($p->uid) or $name = $p->uid; my $cmd = $p->cmndline, 0, 60; if(length($cmd) == 0) { $cmd = "[" . $p->fname . "]"; } $cmd = substr($cmd, 0, 60); my $devname = $p->ttydev; $devname =~ s/\/dev\///; $output .= sprintf($format, $name, sprintf("%5d", $p->pid), sprintf("%4.1f", $p->pctcpu), $devname, $cmd); } if($ccount > 0) { print "\nHere are processes with the top CPU percentages:\n"; printf($format, "USER", "PID", "CPU", "TTY", "COMMAND"); print "$output\n"; } exit(1); etbemon-1.3.6/mon-local.d/loadavg.monitor0000755000000000000000000001365213775157427015225 0ustar #!/usr/bin/perl use strict; # Mon script to check load average # 3 load average numbers on the command line # optional 4th parameter is the maximum percentage of swap+RAM used (default 90) # RAM used is deemed to be MemTotal-MemAvailable # Copyright Russell Coker GPLv3 if ( $#ARGV < 2 || $#ARGV > 3 ) { print STDERR "Usage min 5min 15min [%swap]\n"; exit 1; } my $SwapAlert = 90; if($#ARGV == 3) { $SwapAlert = $ARGV[3]; } open(LOAD, "; close(LOAD); chomp $load; my @arr = split(/ /, $load); my $SwapTotal; my $SwapFree; my $MemTotal; my $MemAvailable; open(MEMINFO, ") { chomp; if($_ =~ /SwapTotal/) { $_ =~ s/ kB.*$//; $_ =~ s/^.* //; $SwapTotal = $_; } elsif($_ =~ /SwapFree/) { $_ =~ s/ kB.*$//; $_ =~ s/^.* //; $SwapFree = $_; } elsif($_ =~ /MemTotal/) { $_ =~ s/ kB.*$//; $_ =~ s/^.* //; $MemTotal = $_; } elsif($_ =~ /MemAvailable/) { $_ =~ s/ kB.*$//; $_ =~ s/^.* //; $MemAvailable = $_; } } close(MEMINFO); my $SwapUsed = $SwapTotal - $SwapFree; my $summary; if($arr[0] > $ARGV[0] || $arr[1] > $ARGV[1] || $arr[2] > $ARGV[2]) { $summary = "$arr[0] $arr[1] $arr[2] >= $ARGV[0] $ARGV[1] $ARGV[2]"; } my $SwapPercent = ($SwapUsed + $MemTotal - $MemAvailable) * 100 / ($SwapTotal + $MemTotal); if($SwapPercent > $SwapAlert) { if($summary) { $summary .= " "; } $summary .= sprintf("Swap+RAM Use: %d%% > %d%%", $SwapPercent, $SwapAlert); } if(length($summary) == 0) { exit(0); } print("$summary\n"); # https://stackoverflow.com/questions/37124052/explain-perl-code-to-display-a-number-of-bytes-in-kb-mb-gb-etc # thanks Borodin sub fmt2 { my ($n) = @_; my @suffix = ( '', qw/ K M G T P E / ); my $i = 0; until ( $n < 1000 or $i == $#suffix ) { $n /= 1024; ++$i; } sprintf $i ? '%.3g%sB' : '%.0f%sB', $n, $suffix[$i]; } use Proc::ProcessTable; my $process_table = new Proc::ProcessTable('cache_ttys' => 0 ); my $format = "%8s %5s %6s %6s %8s %s\n"; my $output = ""; my $dcount = 0; foreach my $process ( @{$process_table->table} ) { if($process->state eq "uwait") { $dcount++; my $name; $name = getpwuid($process->uid) or $name = $process->uid; my $cmd = $process->cmndline, 0, 60; if(length($cmd) == 0) { $cmd = "[" . $process->fname . "]"; } $cmd = substr($cmd, 0, 60); my $devname = $process->ttydev; $devname =~ s/\/dev\///; $output .= sprintf($format, $name, sprintf("%5d", $process->pid), fmt2($process->size), fmt2($process->rss), $devname, $cmd); } } if($dcount > 0) { print "Here are D state processes:\n"; printf($format, "USER", "PID", "VSZ", "RSS", "TTY", "COMMAND"); print $output; } $format = "%8s %5s %4s %8s %s\n"; my $ccount = 0; $output = ""; foreach my $p ( sort { $b->pctcpu <=> $a->pctcpu } @{$process_table->table} ) { if($ccount > 9 || $p->pctcpu < 5.0) { last; } $ccount++; my $name; $name = getpwuid($p->uid) or $name = $p->uid; my $cmd = $p->cmndline, 0, 60; if(length($cmd) == 0) { $cmd = "[" . $p->fname . "]"; } $cmd = substr($cmd, 0, 60); my $devname = $p->ttydev; $devname =~ s/\/dev\///; $output .= sprintf($format, $name, sprintf("%5d", $p->pid), sprintf("%4.1f", $p->pctcpu), $devname, $cmd); } if($ccount > 0) { if($dcount > 0) { print "\n"; } print "Here are processes with the top CPU percentages:\n"; printf($format, "USER", "PID", "CPU", "TTY", "COMMAND"); print "$output"; } $format = "%8s %5s %6s %6s %8s %s\n"; my $rcount = 0; $output = ""; foreach my $p ( sort { $b->rss <=> $a->rss } @{$process_table->table} ) { if(($p->rss * 100 / 1024 / $MemTotal) < 2.0 or $rcount > 9) { last; } $rcount++; my $name; $name = getpwuid($p->uid) or $name = $p->uid; my $cmd = $p->cmndline, 0, 60; if(length($cmd) == 0) { $cmd = "[" . $p->fname . "]"; } $cmd = substr($cmd, 0, 60); my $devname = $p->ttydev; $devname =~ s/\/dev\///; $output .= sprintf($format, $name, sprintf("%5d", $p->pid), fmt2($p->size), fmt2($p->rss), $devname, $cmd); } if($rcount > 0) { if($dcount > 0 or $ccount > 0) { print "\n"; } print "Here are processes with the top RAM use:\n"; printf($format, "USER", "PID", "VIRT", "RES", "TTY", "COMMAND"); print "$output"; } printf("\nSwap Used: %s / %s\n", fmt2($SwapUsed*1024), fmt2($SwapTotal*1024)); use File::Find; use Cwd; my $cgmount = "/sys/fs/cgroup"; my $cgmountlength = length($cgmount); my %cpuexclude; my %ioexclude; my @iopressure; my @cpupressure; sub wanted { if($_ eq "cpu.pressure" or $_ eq "io.pressure") { my $dir = getcwd(); my @dir_parts = split(/\//, $dir); pop(@dir_parts); my $parent = join('/', @dir_parts); my $type; if($_ eq "cpu.pressure") { if($cpuexclude{$parent} == 1) { $ioexclude{$dir} = 1; return; } $type = "cpu"; } else { if($ioexclude{$parent} == 1) { $ioexclude{$dir} = 1; return; } $type = "io"; } open(P, $_) or return; my $line =

; my $some = (split(/ /, (split(/=/, $line))[1]))[0]; if($some < 0.5) { if($type eq "cpu") { $cpuexclude{$dir} = 1; } else { $ioexclude{$dir} = 1; } } else { $line = substr($line, 5); $dir = substr($dir, $cgmountlength); if($type eq "cpu") { push(@cpupressure, "$dir $line"); } else { push(@iopressure, "$dir $line"); $line =

; push(@iopressure, "$dir $line"); } } close(P); } } find(\&wanted, ( $cgmount )); if($#cpupressure != -1) { print "\nSystem CPU Pressure:"; foreach (@cpupressure) { print "$_"; } } if($#iopressure != -1) { print "\nSystem IO Pressure:"; foreach (@iopressure) { print "$_"; } print "\n"; } exit(1); etbemon-1.3.6/mon-local.d/ps.monitor0000755000000000000000000000660714174476514014227 0ustar #!/usr/bin/perl use strict; # Monitors processes on the local host. Requires Proc::ProcessTable # normal usage: # monitor ps.monitor ( process:[min]-[max] )+ ;; # # where: # process process name # min optional minimum number of process name running # max optional maxumum number of process name running # # example: # monitor ps.monitor dhcpd3:1-1 syslog-ng:1- ;; # # debugging usage: # /usr/lib/mon/mon-local.d/ps.monitor -x PID # # where PID is the PID that you want to know the name for where # Proc::ProcessTable doesn't agree with ps on the process name #Copyright 2005 Allan Wind # # Updated by Russell Coker 2020 # #Permission is hereby granted, free of charge, to any person obtaining a copy of #this software and associated documentation files (the "Software"), to deal in #the Software without restriction, including without limitation the rights to #use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies #of the Software, and to permit persons to whom the Software is furnished to do #so, subject to the following conditions: # #The above copyright notice and this permission notice shall be included in all #copies or substantial portions of the Software. # #THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR #IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, #FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE #AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, #OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE #SOFTWARE. use Proc::ProcessTable; # parse command line my %watched_processes; my $special_pid = 0; if($ARGV[0] =~ /-x/) { $special_pid = $ARGV[1]; } else { while(<@ARGV>) { if(m/([^:]+):([0-9]*)?-([0-9]*)?/) { # $1 is process, $2 is min and $3 is max $watched_processes{$1} = [$2, $3, 0]; } else { print "Can't parse \"$_\"\n"; exit 1; } } } my @interpreters = ( "perl", "python", "python3", "python3.9", "lua5.1", "lua5.2" ); # read process table and count the processes of interest my $process_table = new Proc::ProcessTable('cache_ttys' => 0 ); foreach my $process ( @{$process_table->table} ) { if($special_pid && $process->pid != $special_pid) { next; } my $name = $process->fname; $name = substr($name, rindex($name, "/") + 1); $name =~ s/ .*$//; foreach my $i (@interpreters) { if($name eq $i) { my @cmd = split(/ /, $process->cmndline); $name = substr($cmd[1], rindex($cmd[1], "/") + 1); last; } } if($special_pid) { print "PID:$special_pid has name \"$name\"\n"; exit(0); } if( defined($watched_processes{$name}) ) { $watched_processes{$name}[2]++; } } my $summary; my $detail; # print name:count of processes if needed my $report = 0; for my $process (keys(%watched_processes)) { my $count = $watched_processes{$process}[2]; my $min = $watched_processes{$process}[0] || $count; my $max = $watched_processes{$process}[1] || $count; if($min > $count || $max < $count) { $report = 1; $summary .= "$process:$watched_processes{$process}[2] "; if($min > $count) { $detail .= "$process:$watched_processes{$process}[2] < $min ($min-$max)\n"; } else { $detail .= "$process:$watched_processes{$process}[2] > $max ($min-$max)\n"; } } } if($report) { print "$summary\n$detail"; } exit $report; etbemon-1.3.6/mon-local.d/selinux.monitor0000755000000000000000000000071514142105030015237 0ustar #!/bin/bash # checks for SE Linux being in Enforcing mode and for having no processes in # initrc_t. if [ $(ps axZ|grep initrc_t|grep -v grep|wc -l) != "0" ]; then if [ "$(getenforce 2>&1)" != "Enforcing" ]; then echo "In permissive mode and processes in initrc_t" else echo "Processes in initrc_t" fi ps axZ|grep initrc_t|grep -v grep exit 1 fi if [ "$(getenforce 2>&1)" != "Enforcing" ]; then echo "In permissive mode" exit 1 fi exit 0 etbemon-1.3.6/mon-local.d/smartctl.monitor0000755000000000000000000000533514057341457015430 0ustar #!/usr/bin/perl use strict; use Getopt::Std; # copyright 2020 Russell Coker, Licensed under GPLv3 or higher. # # Monitor script to run smartctl and parse output. By default checks # /dev/sd[a-z] /dev/sd[a-z][a-z] /dev/nvme[0-9] /dev/nvme[0-9][0-9] but # you can give a list of devices on the command line # # -f to treat all marginal conditions as failed # -m ATTRIBUTE_NAME to treat attribute as marginal # # -M for MegaRAID support, takes parameters of a device node on the MegaRAID # and a list of disk IDs separated by commas, eg "-M /dev/sda,0,1,7" for # disks 0, 1, and 7 on the MegaRAID controller that runs /dev/sda. my $summary; my $margsummary; my $detail; my $margdetail; my $megadev; my @ids; our $opt_f; our $opt_m; our $opt_M; getopts("fm:M:") or die; if($opt_M) { @ids = split(/,/, $opt_M); $megadev = $ids[0]; shift @ids; } else { if(-1 == $#ARGV) { @ids = glob( "/dev/sd[a-z] /dev/sd[a-z][a-z] /dev/nvme[0-9] /dev/nvme[0-9][0-9]" ); if(-1 == $#ids) { print "No devices found\n"; exit(1); } } else { @ids = @ARGV; } } foreach my $dev (@ids) { my $cmd; if($opt_M) { $cmd = "/usr/lib/mon/bin/smartctl.helper M$megadev,$dev" } else { $cmd = "/usr/lib/mon/bin/smartctl.helper $dev"; } open(SMART, "$cmd|") or die "Can't run smartctl.helper"; my $header = 0; while() { if($_ =~ /^=== START OF .*SMART DATA SECTION/) { $header = 1; last; } } if(not $header) { die "Error running \"$cmd\", does device exist?"; } my $line = ; my $name = $dev; $name =~ s/^.dev.//; my $attribute; my $failstate = 0; if($line =~ /FAILED/) { $failstate = 1; } else { $line = ; if(not $line =~ /Please note the following marginal Attributes/) { close(SMART); next; } } my $newdetail = "Drive $dev:\n"; while() { $newdetail .= $_; if($_ =~ /^ID/) { while() { $newdetail .= $_; if(length($_) < 3) { last; } chomp; $_ =~ s/^[ 0-9]+ //; $_ =~ s/ .*$//; $attribute .= "$_ "; } } } $newdetail .= "\n"; $attribute =~ s/ $//; if($failstate and not $attribute eq $opt_m) { $detail .= $newdetail; $summary .= "$name FAIL($attribute) "; } else { $margdetail .= $newdetail; $margsummary .= "$name MARGINAL($attribute) "; } close(SMART); } if($summary or ($margsummary and $opt_f)) { print "$summary$margsummary\n"; print $detail . $margdetail; exit(1); } if($margsummary) { print "$margsummary\n"; print $margdetail; } else { if($opt_M) { print("MegaRAID $opt_M OK\n"); } else { print("@ids OK\n"); } } exit(0); etbemon-1.3.6/mon-local.d/softraid.monitor0000755000000000000000000000205313135637150015376 0ustar #!/usr/bin/perl use strict; # Linux Software RAID monitoring script by Russell Coker # Licensed under GPL-3 # Command-line parameters are the list of RAID arrays that MUST be online, # without the /dev, eg "softraid2.monitor md0 md2" # # if you only have a single array no parameters are needed open(MDSTAT, ") { chomp $_; if($_ =~ /^md/) { $name = $_; $name =~ s/ : .*$//; $arrays{$name} = 1; next; } if($_ =~ / blocks /) { if($_ =~ /\[U+\]/) { $summary .= "$name:ok "; next; } my @arr = split(/[\[\]]/, $_); $summary .= "$name:fail "; $detail .= "$name: $arr[1] $arr[3]\n"; } } if(length($summary) == 0) { printf("No software RAID\n"); exit(1); } foreach my $raid (@ARGV) { if(!$arrays{$raid}) { $summary .= "$raid:unknown "; $detail .= "$raid: not found\n"; } } print("$summary\n$detail"); if(length($detail) == 0) { exit(0); } exit(1); etbemon-1.3.6/mon-local.d/zfs.monitor0000755000000000000000000000644113604573461014377 0ustar #!/usr/bin/perl use strict; # Mon script to check ZFS error count # Options: list of ZFS mount points # /var/lib/mon has files named zfs-$MOUNTPOINT.count (with "root" for the # root filesystem) that lists the number of acceptable errors. EG if your # root filesystem once had a single error and that's considered OK put 1 in # /var/lib/mon/zfs-root.count # if you have less errors than specified (IE you replaced an error without # changing the count file accordingly) then it also flags an error condition. # if you need to support a range of errors (EG you expect that a scrub will # generate a dozen errors and do not need alerts about that) then have the # low and high ends of the range seperated by :. EG "100:110" means that any # number of errors between 100 and 110 inclusive is expected and not something # to give a notification. # # Copyright Russell Coker GPLv3 my $summary = ""; my $failed = ""; my $status = ""; my %faulty; foreach my $test (@ARGV) { open(ZFS, "/usr/lib/mon/bin/zfs.helper $test 2>&1 ) { if($_ =~ /^ERROR/ || $_ =~ /sudo/ || $_ =~ /not found/) { $summary .= "Can't test $test "; $failed .= "$test : $_"; last RUNZFS; } if($_ !~ /\ [0-9]$/) { $warnings .= ""; } chomp; my $dev = $_; $dev =~ s/^\s*//; $dev =~ s/\s.*$//; next if $_ =~ /state:/; if($_ =~ /DEGRADED/) { $faulty{DEGRADED} .= "$dev "; } elsif($_ =~ /FAULTED/) { $faulty{FAULTED} .= "$dev "; } elsif($_ =~ /OFFLINE/) { $faulty{OFFLINE} .= "$dev "; } elsif($_ =~ /REMOVED/) { $faulty{REMOVED} .= "$dev "; } elsif($_ =~ /UNAVAIL/) { $faulty{UNAVAIL} .= "$dev "; } elsif($_ =~ /ONLINE/) { $_ =~ s/^.*\ ONLINE +//; my @arr = split(/ +/); my $count = $arr[0] + $arr[1] + $arr[2]; if($count > 0) { $warnings .= "$dev has $count errors\n"; } $testcount += $count; } } close(ZFS); if(scalar(keys %faulty) > 0) { foreach my $key(keys %faulty) { $failed .= "$key: $faulty{$key}\n"; } if($testcount > 0) { $failed .= "$test has error count $testcount\n"; $failed .= "$warnings"; } $summary .= "$test device failure "; } elsif($testcount > 0) { my @okcount; my $okhigh = 0; my $oklow = 0; my $filename = "/var/lib/mon/zfs-$test.count"; if(open(COUNT, "<$filename")) { my $line = ; chomp $line; close(COUNT); my @okcount = split(/:/, $line); if($okcount[1]) { $okhigh = $okcount[1]; $oklow = $okcount[0]; } else { $okhigh = $okcount[0]; $oklow = $okcount[0]; } } if($testcount > $okhigh) { $summary .= "$test has error count $testcount > $okhigh "; $failed .= "$warnings"; } elsif($testcount < $oklow) { $summary .= "$test has error count $testcount < $oklow so you replaced a disk without fixing $filename"; $failed .= "$warnings"; } $status .= "$test:$testcount errors "; } } if($failed ne "" || $summary ne "") { print "$summary\n"; print $failed; exit(1); } print "$status\n"; exit(0); etbemon-1.3.6/mon.d/0000755000000000000000000000000014203606346011057 5ustar etbemon-1.3.6/mon.d/Makefile0000644000000000000000000000172314170644067012527 0ustar # # $Id: Makefile,v 1.1.1.1 2004/06/09 05:18:05 trockij Exp $ # # compiles on Linux, Solaris 2.5, Solaris 2.6, and AIX Version 4.2 # CC = gcc CFLAGS = `dpkg-buildflags --get CFLAGS` LDFLAGS = `dpkg-buildflags --get LDFLAGS` INCFLAGS = -I/usr/include/tirpc LDLIBS = -ltirpc # uncomment next line for Solaris # LDLIBS = -lnsl -lsocket CPPFLAGS = `dpkg-buildflags --get CPPFLAGS` MONPATH=/usr/lib/mon DIALIN_MONITOR_REAL=$(MONPATH)/mon.d/dialin.monitor PROGS = rpc.monitor dialin.monitor.wrap all: $(PROGS) rpc.monitor: rpc.monitor.c $(CC) -o rpc.monitor $(CFLAGS) $(CPPFLAGS) $(INCFLAGS) $(LDFLAGS) rpc.monitor.c $(LDLIBS) dialin.monitor.wrap: dialin.monitor.wrap.c $(CC) -o dialin.monitor.wrap $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) \ -DREAL_DIALIN_MONITOR=\"$(DIALIN_MONITOR_REAL)\" \ dialin.monitor.wrap.c clean: rm -f $(PROGS) install: install -d $(MONPATH)/mon.d install rpc.monitor $(MONPATH)/mon.d/ install -g uucp -m 02555 dialin.monitor.wrap $(MONPATH)/mon.d/ etbemon-1.3.6/mon.d/asyncreboot.monitor0000755000000000000000000001254413135636631015034 0ustar #!/usr/bin/perl # # monitor host reboots via SNMP, asynchronously # # for use with "mon" # # options: # # asynch-reboot.monitor --statefile=filename --dir=dir host1 host2... # # Since this is scheduled from mon, it must maintain state between # runs. It uses the "statefile" for this, in which it stores a # sysUpTime sample for each host specified on the command line. # # THIS STATE FILE MUST NOT BE SHARED BETWEEN MULTIPLE INSTANCES OF THIS # MONITOR, SINCE IT DOES NOT HANDLE LOCKING OF THE FILE DURING UPDATES!! # # Jim Trocki # # $Id: asyncreboot.monitor,v 1.1.1.1 2004/06/09 05:18:05 trockij Exp $ # # Copyright (C) 1998, Jim Trocki # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # use Mon::SNMP; use Getopt::Long; sub secs_to_hms; sub read_state_file; sub write_state_file; sub secs_to_hms; sub print_failures; GetOptions (\%opt, "statefile=s", "dir=s", "timeout=i"); $STATEDIR = $opt{"dir"} || "/usr/lib/mon/state.d"; $STATEFILE = $opt{"statefile"} || "state"; $STATE = "$STATEDIR/$STATEFILE"; $TIMEOUT = $opt{"timeout"} || 10; die "reboot state dir $STATEDIR does not exist\n" if (! -w $STATEDIR); die "no host arguments\n" if (@ARGV == 0); read_state_file; %getting = (); %gotten = (); %sessions = (); foreach my $host (@ARGV) { $sessions{$host} = new SNMP::Session ( "DestHost" => $host, "Retries" => 10, "Version" => 2, ); $getting{$host} = 1; $sessions{$host}->get ( [['.1.3.6.1.2.1.1.3.0']], [\&h, $sessions{$host}], ); } SNMP::MainLoop($TIMEOUT); # # what was gotten and what was not # @failures = (); foreach my $host (keys %gotten) { next if ($gotten{$host}->{"uptime"} eq "timeout"); # # no history for this # if (!defined $last_sample{$host}{"uptime"}) { } elsif ($last_sample{$host}{"uptime"} < 2**32 - (120 * 60 * 100) && $gotten{$host}->{"uptime"} < $last_sample{$host}{"uptime"}) { push (@failures, $host); $last_sample{$host}{"olduptime"} = $last_sample{$host}{"uptime"}; $last_sample{$host}{"oldcheck"} = $last_sample{$host}{"lastcheck"}; } $last_sample{$host}{"uptime"} = $gotten{$host}->{"uptime"}; $last_sample{$host}{"lastcheck"} = $gotten{$host}->{"time"}; } for (keys %getting) { print "notgot $_ $getting{$_}\n"; $gotten{$_}->{"uptime"} = "timeout"; $gotten{$_}->{"time"} = time; $gotten{$_}->{"error"} = "timeout"; } write_state_file; # # all is OK, nobody has rebooted # if (@failures == 0) { exit; } print_failures; exit 1; # # callback for asynch requests # sub h { $gotten{$_[0]->{"DestHost"}}->{"time"} = time; delete $getting{$_[0]->{"DestHost"}}; if (!defined ($_[1])) { $gotten{$_[0]->{"DestHost"}}->{"uptime"} = "timeout"; $gotten{$_[0]->{"DestHost"}}->{"error"} = $_[0]->{"ErrorStr"}; return; } $gotten{$_[0]->{"DestHost"}}->{"uptime"} = $_[1][0]->val; } sub secs_to_hms { my ($s) = @_; my ($dd, $hh, $mm, $ss); $dd = int ($s / 86400); $s -= $dd * 86400; $hh = int ($s / 3600); $s -= $hh * 3600; $mm = int ($s / 60); $s -= $mm * 60; $ss = $s; if ($dd == 0) { sprintf("%02d:%02d", $hh, $mm); } else { sprintf("%d days, %02d:%02d", $dd, $hh, $mm); } } sub read_state_file { my $host; if (! -f $STATE) { open (O, ">$STATE"); close (O); } # # read in state file # if (!open (IN, "$STATE")) { die "could not open state file $STATE\n"; } while (defined ($host = )) { if ($host =~ /^(\S+) (\d+) (\d+)/) { $last_sample{$1}{"uptime"} = $2; $last_sample{$1}{"lastcheck"} = $3; } } close (IN); } sub write_state_file { # # update state file # if (!open (OUT, ">$STATE")) { die "could not open $STATEFILE for writing: $!\n"; } foreach my $k (sort keys %last_sample) { print OUT "$k $last_sample{$k}{uptime} $last_sample{$k}{lastcheck}\n"; } close (OUT); } # # we have reboots, so calculate uptime, downtime, # and report it # sub print_failures { my $t = time; my @f; foreach my $host (@failures) { my $downtime = secs_to_hms ( $t - $last_sample{$host}{"oldcheck"} - int ($last_sample{$host}{"uptime"} / 100) ); my $uptime = secs_to_hms ( int ($last_sample{$host}{"olduptime"} / 100) ); push (@f, "$host / down $downtime / up $uptime"); } @f = sort @f; print join (" ", sort @failures), "\n"; printf ("%-20s %s\n", "host", "rebooted on"); printf ("----------------------------------------------\n"); my $timen = time; foreach my $host (@failures) { my $secs = int($last_sample{$host}{"uptime"} / 100); my $t = localtime ($timen - $secs); printf ("%-20s %s\n", $host, $t); } print "\n"; print join ("\n", @f), "\n"; } etbemon-1.3.6/mon.d/cpqhealth.monitor0000755000000000000000000002203213135636631014446 0ustar #!/usr/bin/perl # # "mon" monitor to detect thermal/fan/psu failures # for Compaq Proliant machines which run the "Compaq Insight Agent" # # arguments are "[-c community] [-f] [-p] [-t] host [host...]" # # -f do not query the fan table # -p do not query the PSU table # -t do not query the temperature table # # Jim Trocki # # $Id: cpqhealth.monitor,v 1.1.1.1 2004/06/09 05:18:05 trockij Exp $ # # Copyright (C) 2000, Jim Trocki # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # use Mon::SNMP; use Getopt::Std; use strict; sub get_status; sub get_table; sub get_vars; sub fancy_psu_table; $ENV{"MIBS"} = "CPQHLTH-MIB"; my %opt; getopts ('c:pft', \%opt); my $COMM = $opt{"c"} || "public"; my @failures = (); my $detail = ""; my $detail_head = ""; my $fan_detail = ""; my $psu_detail = ""; foreach my $host (@ARGV) { my %status = get_status ($host, $COMM); if ($status{"error"} ne "") { push (@failures, $host); $detail .= "could not retrieve status from $host: $status{error}\n\n"; next; } elsif ($status{"failure"}) { push (@failures, $host); } if ($status{"overall_status"}->{"redundant_fans"} ne "ok") { $detail_head .= "$host has fan problem\n"; } if ($status{"overall_status"}->{"redundant_psus"} ne "ok") { $detail_head .= "$host has PSU problem\n"; } if ($status{"overall_status"}->{"temperature"} ne "ok") { $detail_head .= "$host has temperature problem\n"; } # # Fan # $fan_detail .= fancy_fan_table ($host, $status{"flt_tol_fan_table"}) . "\n"; # # PSU # $psu_detail .= fancy_psu_table ($host, $status{"psu_status_table"}) . "\n"; } # # output returned to mon # if (@failures != 0) { print join (" ", sort @failures), "\n"; } else { print "\n"; } print "$detail_head"; if (!$opt{"f"}) { print < "error name, empty string means no error", # ) # sub get_status { my ($host, $comm) = @_; my $s; if (!defined ($s = new SNMP::Session ( "DestHost" => $host, "Community" => $comm, "UseEnums" => 1, "Version" => 2, ))) { return ("error" => "cannot create session"); } my $error; my $failure_detected = 0; my $psu_status_table; my $flt_tol_fan_table; my $temp_sensor_table; my $overall_status; # # is this really a compaq box w/the insight agent? # my $sys_oid = $s->get (["sysObjectID", 0]); return ("error" => $s->{"ErrorStr"}) if ($s->{"ErrorStr"} ne ""); return ("error" => "not Compaq device") if ($sys_oid ne ".1.3.6.1.4.1.311.1.1.3.1.2"); if (0) { # # get overall status # # from what i can tell, this is totally useless, and # it doesn't tell you about the things you actually care about, # like whether the PSUs are running in a redundant configuration # or not, or PSUs which used to be in order but are now # out of order. # ($error, $overall_status) = get_vars ($s, ["cpqHeThermalCondition", 0], ["cpqHeThermalTempStatus", 0], ["cpqHeThermalSystemFanStatus", 0], ["cpqHeThermalCpuFanStatus", 0], ["cpqHeFltTolPwrSupplyCondition", 0], ); return ("error" => "$error while retrieving overall status") if ($error ne ""); } $overall_status = { "redundant_fans" => "ok", "temperature" => "ok", "redundant_psus" => "ok", }; if (!$opt{"p"}) { # # PSU table # ($error, $psu_status_table) = get_table ($s, ["cpqHeFltTolPowerSupplyChassis"], ["cpqHeFltTolPowerSupplyBay"], ["cpqHeFltTolPowerSupplyPresent"], ["cpqHeFltTolPowerSupplyCondition"], ["cpqHeFltTolPowerSupplyStatus"], ["cpqHeFltTolPowerSupplyMainVoltage"], ["cpqHeFltTolPowerSupplyCapacityUsed"], ["cpqHeFltTolPowerSupplyCapacityMaximum"], ["cpqHeFltTolPowerSupplyRedundant"], ["cpqHeFltTolPowerSupplyModel"], ["cpqHeFltTolPowerSupplySerialNumber"], ["cpqHeFltTolPowerSupplyAutoRev"], ); return ("error" => $error) if ($error ne ""); foreach my $r (@{$psu_status_table}) { next if ($r->{"cpqHeFltTolPowerSupplyPresent"} eq "absent"); if ($r->{"cpqHeFltTolPowerSupplyCondition"} ne "ok" || $r->{"cpqHeFltTolPowerSupplyStatus"} ne "noError" || $r->{"cpqHeFltTolPowerSupplyRedundant"} eq "notRedundant") { $failure_detected = 1; $overall_status->{"redundant_psus"} = "fail"; last; } } } if (!$opt{"f"}) { # # Fan chassis table # ($error, $flt_tol_fan_table) = get_table ($s, ["cpqHeFltTolFanChassis"], ["cpqHeFltTolFanIndex"], ["cpqHeFltTolFanLocale"], ["cpqHeFltTolFanPresent"], ["cpqHeFltTolFanType"], ["cpqHeFltTolFanSpeed"], ["cpqHeFltTolFanRedundant"], ["cpqHeFltTolFanRedundantPartner"], ["cpqHeFltTolFanCondition"], ); return ("error" => $error) if ($error ne ""); foreach my $r (@{$flt_tol_fan_table}) { next if ($r->{"cpqHeFltTolFanPresent"} ne "present"); if ($r->{"cpqHeFltTolFanRedundant"} ne "redundant" || $r->{"cpqHeFltTolFanCondition"} ne "ok") { $failure_detected = 1; $overall_status->{"redundant_fans"} = "fail"; last; } } } if (!$opt{"t"}) { # # chassis temp table # ($error, $temp_sensor_table) = get_table ($s, ["cpqHeTemperatureChassis"], ["cpqHeTemperatureIndex"], ["cpqHeTemperatureLocale"], ["cpqHeTemperatureCelsius"], ["cpqHeTemperatureThreshold"], ["cpqHeTemperatureCondition"], ); return ("error" => $error) if ($error ne ""); foreach my $r (@{$temp_sensor_table}) { # # cpqHeTemperatureCelsius == -1 if not present # (as far as i can tell) # next if ($r->{"cpqHeTemperatureCelsius"} == -1); if ($r->{"cpqHeTemperatureCondition"} ne "ok") { $failure_detected = 1; $overall_status->{"temperature"} = "fail"; last; } } } ( "error" => "", "failure" => $failure_detected, "overall_status" => $overall_status, "temp_sensor_table" => $temp_sensor_table, "flt_tol_fan_table" => $flt_tol_fan_table, "psu_status_table" => $psu_status_table, ); } sub get_table { my ($s, @tbl) = @_; my $table = []; my $tblid = $tbl[0]->[0]; my $i = 0; my $row = new SNMP::VarList (@tbl); return ("MIB problem") if (!defined $row); while (defined ($s->getnext ($row))) { last if ($s->{"ErrorStr"} ne ""); my $r = $row->[0]->[0]; last if ($r ne $tblid); foreach my $col (@{$row}) { $table->[$i]->{"iid"} = $col->[1]; $table->[$i]->{$col->[0]} = $col->[2]; } $i++; } return ($s->{"ErrorStr"}) if ($s->{"ErrorStr"} ne ""); ( "", $table, ); } sub get_vars { my ($s, @vars) = @_; my $r = new SNMP::VarList ( @vars ); return ("MIB problem") if (!defined $r); return ($s->ErrorStr) if (!defined ($s->get ($r))); my $v; foreach my $element (@{$r}) { $v->{$element->[0]} = $element->[2]; } ("", $v); } sub fancy_psu_table { my ($host, $psu_status_table) = @_; my $detail; foreach my $r (@{$psu_status_table}) { $detail .= sprintf ("%-12s psu %-3s %-10s %-11s %-12s %-11s %-4s %s\n", $host, $r->{"iid"}, $r->{"cpqHeFltTolPowerSupplyPresent"}, $r->{"cpqHeFltTolPowerSupplyStatus"}, $r->{"cpqHeFltTolPowerSupplyRedundant"}, $r->{"cpqHeFltTolPowerSupplyCondition"}, $r->{"cpqHeFltTolPowerSupplyBay"}, $r->{"cpqHeFltTolPowerSupplyChassis"}, ); } $detail; } sub fancy_fan_table { my ($host, $fan_table) = @_; my $detail; foreach my $r (@{$fan_table}) { $detail .= sprintf ("%-12s fan %-3s %-4s %-9s %-10s %-7s %-12s %-7s %-7s %s\n", $host, $r->{"iid"}, $r->{"cpqHeFltTolFanChassis"}, $r->{"cpqHeFltTolFanLocale"}, $r->{"cpqHeFltTolFanPresent"}, $r->{"cpqHeFltTolFanCondition"}, $r->{"cpqHeFltTolFanRedundant"}, $r->{"cpqHeFltTolFanRedundantPartner"}, $r->{"cpqHeFltTolFanSpeed"}, $r->{"cpqHeFltTolFanType"}, ); } $detail; } etbemon-1.3.6/mon.d/dialin.monitor0000755000000000000000000001703110061516615013732 0ustar #!/usr/bin/perl # # Check to see if modems on the terminal server are still answering the phone # # This script should be run using a setgid uucp wrapper which then # invokes this script in order to gain permissions to do UUCP-style # modem locking. # # Jim Trocki # # $Id: dialin.monitor,v 1.1.1.1 2004/06/09 05:18:05 trockij Exp $ # use Getopt::Std; use Expect; use POSIX; use English; use Sys::Syslog; sub hangup_ath; sub hangup_dtr; sub lock_modem; sub unlock_modem; sub attempt_dialin; Sys::Syslog::setlogsock ('unix'); openlog ("dialin.monitor", "cons,pid", "daemon"); getopts ('dn:D:l:r:t:', \%opt); die "not running as GID uucp, are you using the setgid wrapper?\n" unless ($opt{"d"} || $EGID == getgrnam ("uucp")); $NUMBER = $opt{"n"} || die "specify dial number with -n\n"; $DIAL_TIMEOUT = $opt{"t"} || 60; $DEVICE = $opt{"D"} || "/dev/modem"; $LOCKDIR = $opt{"l"} || "/var/lock"; $RETRIES = $opt{"r"} || 2; $SIG{"TERM"} = \&unlock_modem_and_die; $SIG{"INT"} = \&unlock_modem_and_die; my $no = 0; my $yes = 0; my @detail = (); for (my $retr = 0; $retr < $RETRIES; $retr++) { my $r = attempt_dialin; if ($r eq "OK") { $yes++; last; } $no++; push @detail, $r; sleep 5; } exit 0 if ($yes); print "failure for $NUMBER after $RETRIES retries\n", join ("\n", @detail), "\n"; exit 1; # # make an attempt to dial in # returns "OK" upon success, and an error string upon failure # sub attempt_dialin { my $got_lock = 0; for (my $tries=0; $tries < 6; $tries++) { my $r = lock_modem; if ($r eq "ok") { $got_lock = 1; last; } if ($opt{"d"}) { print STDERR "problem getting lock: $!\n" } sleep 10; } if ($opt{"d"}) { print STDERR "got_lock=$got_lock\n" } if (!$got_lock) { return "could not get lock"; } if ((my $r = hangup_dtr) != 1) { unlock_modem; return "could not drop DTR: $r"; } if (!open (MODEM, "+<$DEVICE")) { return "could not open $DEVICE: $!"; } select (MODEM); $| = 1; select (STDOUT); my $s = Expect->exp_init (\*MODEM); if (!$s) { unlock_modem; return "could not init expect"; } $s->exp_stty ("9600", "cs8", "-clocal", "crtscts", "-parenb", "-cstopb"); # # Reset modem # my $err = ""; for (my $n =0; $n < 2; $n++) { if ($opt{"d"}) { print STDERR "resetting modem\n" } print $s "ATZ\r"; ($matched_pattern_position, $error, $successfully_matching_string, $before_match,$after_match) = $s->expect (5, "OK"); if ($error eq "1:TIMEOUT") { $err = "timeout waiting for OK prompt"; next; } elsif (!defined $matched_pattern_position) { $err = "no pattern matched waiting for OK prompt"; next; } $err = ""; $s->clear_accum; last; } if ($err ne "") { unlock_modem; return $err; } # # dial phone number and wait for connect # if ($opt{"d"}) { print STDERR "dialing and waiting for carrier\n" } print $s "ATDT$NUMBER\r"; ($matched_pattern_position, $error, $successfully_matching_string, $before_match,$after_match) = $s->expect ($DIAL_TIMEOUT, "CONNECT", "BUSY", "NO CARRIER", "NO DIALTONE"); if ($error eq "1:TIMEOUT") { unlock_modem; return "timeout waiting for connection [$before_match] [$after_match]"; } elsif (!defined $matched_pattern_position) { unlock_modem; return "no pattern matched waiting for connection"; } elsif ($matched_pattern_position != 1) { unlock_modem; return "no connection: $successfully_matching_string"; } $s->clear_accum; # # once connected, wait for login prompt # if ($opt{"d"}) { print STDERR "got connect, waiting for login prompt\n" } ($matched_pattern_position, $error, $successfully_matching_string, $before_match,$after_match) = $s->expect (30, "login:"); if ($error eq "1:TIMEOUT") { close (MODEM); hangup_dtr; unlock_modem; return "connection but timeout on prompt"; } elsif (!defined $matched_pattern_position) { close (MODEM); hangup_dtr; unlock_modem; return "no login prompt"; } $s->clear_accum; # # got login prompt, hang up phone # if ($opt{"d"}) { print STDERR "all OK, hanging up\n" } close (MODEM); if (($r = hangup_dtr) != 1) { unlock_modem; return "could not toggle DTR: $r"; } unlock_modem; return "OK"; } # # this quite possibly only works on Linux, or at least that's # where I stole the TIOCM_DTR and TIOCMBIC values from # sub hangup_dtr { if ($opt{"d"}) { print STDERR "\tdropping DTR\n" } open (M, "+<$DEVICE") || return "could not open device: $!"; my $TIOCM_DTR = pack ("i", 0x02); my $TIOCMBIC = 0x5417; if (!ioctl (M, $TIOCMBIC, $TIOCM_DTR)) { return "could not do ioctl: $!"; } sleep 5; close (M); return 1; } sub hangup_ath { my $i, $ok; my $matched_pattern_position, $error, $successfully_matching_string, $before_match, $after_match; if ($opt{"d"}) { print STDERR "\thanging up via ATH\n" } $ok = 0; PLUS_LOOP: for ($i=0; $i<3; $i++) { print $s "+++"; ($matched_pattern_position, $error, $successfully_matching_string, $before_match, $after_match) = $s->expect (4, "OK"); if (defined $matched_pattern_position) { $ok = 1; last PLUS_LOOP; } } return undef unless ($ok); print $s "ATH\r"; ($matched_pattern_position, $error, $successfully_matching_string, $before_match, $after_match) = $s->expect (5, "OK"); return 1 if ($matched_pattern_position == 1); return undef; } sub lock_modem { my $dev, $pid; my $lockfile, $tmpfile; if ($opt{"d"}) { print STDERR "\tlocking modem\n" } ($dev) = $DEVICE =~ /\/([^\/]*)$/; return "device unparseable" unless ($dev ne ""); $lockfile = "$LOCKDIR/LCK..$dev"; $tmpfile = "$LOCKDIR/TMPLCK..$$"; open (O, ">$tmpfile") || return "could not open tmp lock: $!"; print O "$$\n"; close (O); if (!link ($tmpfile, $lockfile)) { if ($! == EEXIST) { if (!open (I, $lockfile)) { unlink ($tmpfile); return "could not open existing lock file: $!"; } $pid = ; close (I); my ($npid) = $pid =~ /(\d+)/; my $v = kill 0, $npid; if ($v == 0 && $! != ESRCH) { unlink ($tmpfile); return "lock already exists"; } if ($opt{"d"}) { print STDERR "lock from dead process exists\n" } if (!unlink ($lockfile)) { unlink ($tmpfile); if ($opt{"d"}) { print STDERR "lock from dead process exists, could not unlink stale lock\n" } return "could not unlink stale lock file: $!"; } if (!link ($tmpfile, $lockfile)) { unlink ($tmpfile); if ($opt{"d"}) { print STDERR "lock from dead process exists, could create lock\n" } return "could not create lock file: $!"; } } else { return "cannot create lock file: $!"; } } unlink ($tmpfile) || return "could not unlink temp lock file: $!"; if ($opt{"d"}) { print STDERR "lock is OK\n" } return "ok"; # create a temp file in /var/lock and put PID in it # make a hard link to it, check return value # if errno = EEXIST then # open and read existing lock file # check if the proc exists via kill -0 # if it does exist, unlink the tmpfile and return failure # else unlink lockfile # link tmpfile to lockfile # unlink tmpfile # return OK # } sub unlock_modem { my $dev; if ($opt{"d"}) { print STDERR "\tunlocking modem\n" } ($dev) = $DEVICE =~ /\/([^\/]*)$/; return "device unparseable" unless ($dev ne ""); unlink ("$LOCKDIR/LCK..$dev") || return "could not unlink lock file: $!"; return 1; } sub unlock_modem_and_die { unlock_modem; die; } etbemon-1.3.6/mon.d/dialin.monitor.wrap.c0000644000000000000000000000115410146140376015120 0ustar /* * setgid wrapper for use with dialin.monitor. Required for * UUCP locking permissions in /var/lock. * * cc -o dialin.monitor.wrap dialin.monitor.wrap.c * chown root dialin.monitor.wrap * chgrp uucp dialin.monitor.wrap * chmod 02555 dialin.monitor.wrap * * $Id: dialin.monitor.wrap.c,v 1.2 2004/11/15 14:45:18 vitroth Exp $ * */ #include #ifndef REAL_DIALIN_MONITOR #define REAL_DIALIN_MONITOR "/usr/lib/mon/mon.d/dialin.monitor" #endif int main (int argc, char *argv[]) { char *real_img = REAL_DIALIN_MONITOR; argv[0] = real_img; /* exec */ return execv (real_img, argv); } etbemon-1.3.6/mon.d/dns-query.monitor0000755000000000000000000000414510061516616014424 0ustar #!/usr/bin/perl # # very straightforward dns monitor for use with "mon" # # arguments: # -t timeout timeout (defaults to 5 seconds) # -n name name to query, defaults to "mailhost" # # $Id: dns-query.monitor,v 1.1.1.1 2004/06/09 05:18:06 trockij Exp $ # # Copyright (C) 2003, Jim Trocki # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # use strict; use Getopt::Std; use Net::DNS::Resolver; my %opt; getopts ("t:n:", \%opt); my $TIMEOUT = defined $opt{"t"} ? $opt{"t"} : 5; my $NAME = $opt{"n"} || "mailhost"; my $r = Net::DNS::Resolver->new; if (!defined $r) { die "could not create new Net::DNS::Resolver object\n"; } $r->udp_timeout ($TIMEOUT); my (%good, %bad); foreach my $server (@ARGV) { $r->nameservers ($server); my $p = $r->search ($NAME); if (!defined $p) { $bad{$server}->{"detail"} = $r->errorstring; } else { my $n = $p->{"answer"}->[0]; $good{$server}->{"detail"} = "$n->{name} $n->{class} $n->{type} $n->{address}"; } } if (keys %bad) { print join (" ", sort keys %bad), "\n"; } else { print "\n"; } if (keys %bad) { print "failures:\n"; foreach my $k (keys %bad) { print " $k: $bad{$k}->{detail} ($NAME)\n"; } print "\n"; } if (keys %good) { print "successes:\n"; foreach my $k (keys %good) { print " $k: successfull lookup for $good{$k}->{detail} ($NAME)\n"; } } exit 1 if (keys %bad); exit 0; etbemon-1.3.6/mon.d/dns.monitor0000755000000000000000000004122113343237654013265 0ustar #!/usr/bin/perl # # Copyright (C) 1998 David Eckelkamp # Copyright (C) 2002-2006 Carnegie Mellon University # Copyright (C) 2017 Russell Coker # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # $Id: dns.monitor,v 1.3 2006/09/05 12:52:37 vitroth Exp $ # =head1 NAME dns.monitor - Monitor DNS servers for the "mon" system =head1 SYNOPSIS B =over 12 ( [ I<-zone zone [-zone zone ...]> =over 4 I<-master server [-master server ...]> I<[-serial_threshold num]> I<[-failsingle]> ] =back | [ I<-caching_only> =over 4 I<-query record[:type[:value]] [-query record[:type[:value]] ...]> ] ) =back I<[-tcp]> I<[-retry num]> I<[-retransmit num]> I<[-timeout num]> I<[-debug num]> I =back =head1 DESCRIPTION B will make several DNS queries to verify that a server is operating correctly In normal mode, B will compare the zones between a master server and one or more slave servers. The I argument is the zone to check. There can be multiple I arguments. The I argument is the master server for the I. There can be multiple I arguments. The master server(s) will be queried for the base information. If the I argument is provided, the serials collected from the I servers are checked to be within I. The greatest serial of all of the I servers is chosen for comparison. Then each I will be queried to verify that it has the correct answers. If the I argument is provided, the slave servers must return a zone whose serial number is no more than the threshold from the serial number of the zone on the master. (Zone serial numbers may not be identical during zone propagation, or on Dynamic DNS zones which may be updated hundreds or thousands of times an hour) It is assumed that each I is supposed to be authoritative for the I. The I<-tcp> option will cause lookups to be done via TCP instead of the default UDP. In caching mode, specified via the I<-caching_only> switch, B will perform a set of DNS queries to one or more servers. The I argument is the query to perform. The query may have an optional query type specified as I<:type> on the end of the query. I.e your.zone.com:MX will cause B to fetch the MX records for your.zone.com. There can be multiple I arguments. The query type may also have an optional result specified as I<:value> on the end of the query (type must also be specified). Each I will be contacted to verify that it returns a valid response to the query. If a query result is specified B will return an error is the DNS query returns an answer which differs from the supplied result. If you wish to use B to verify that a caching DNS server is actually fetching fresh data from other servers successfully, it is recommended that the DNS records you query should have very short TTLs. The exit code of B will be the highest number of servers which failed on a single zone/query, 0 if no problems occurred, or -1 if an error with the script arguments was detected. If all of the I servers fail, the return code will be 252. If using the I option and any I server fails, the return code will be 251. =head1 AUTHOR The script was originally written by David Eckelkamp The script was modified to support Caching DNS servers, configurable retry/timeout parameters, multiple DNS Master servers, and configurable Zone serials by David Nolan and Jason Carr from Carnegie Mellon University. Modified to give a better summary by Russell Coker. =cut use strict; use Getopt::Long; use English; use File::Basename; use Net::DNS::Resolver; use Net::DNS::Packet; use Net::DNS::RR; use Data::Dumper; my($Program) = basename($0); my(@Zones) = (); my(@Queries) = (); my(@Master) = (); my($SerialThreshold) = (0); my($CachingServer) = (0); my($UseTCP) = (0); my ($retries, $retrans, $timeout) = ( 2, 5, undef ); my $debug = 0; my $failsingle = 0; my(%OptVars) = ( "master" => \@Master, "zone" => \@Zones, "serial_threshold" => \$SerialThreshold, "caching_only" => \$CachingServer, "query" => \@Queries, "retry" => \$retries, "retransmit" => \$retrans, "timeout" => \$timeout, "tcp" => \$UseTCP, "debug" => \$debug, "failsingle" => \$failsingle ); if (!GetOptions(\%OptVars, "master=s@", "zone=s@", "serial_threshold=s", "caching_only", "tcp", "query=s@", "retry=i", "retransmit=i", "timeout=i", "debug", "failsingle")) { print STDERR "Problems with Options, sorry\n"; exit -1; } if ( $#ARGV < 0 ) { print STDERR "$Program: at least one server must be specified\n"; usage(); exit -1; } if (!$CachingServer) { if (! @Master) { print STDERR "$Program: The zone master server must be specified\n"; usage(); exit -1; } if (! @Zones) { print STDERR "$Program: At least one zone must be specified\n"; usage(); exit -1; } } else { if (! @Queries) { print STDERR "$Program: At least one query must be specified\n"; usage(); exit -1; } } if (!$CachingServer) { my($err_cnt) = 0; my($bad_servers, $reason, $failcount, @FailedZones, @FailedServers, @Reasons); my($zone, $line, $i); my $summary; foreach $zone (@Zones) { ($bad_servers, $reason, $failcount) = dns_verify($zone, \@Master, \@ARGV); if (defined($bad_servers)) { $err_cnt = $failcount if ($failcount > $err_cnt); push(@FailedZones, $zone); push(@FailedServers, $bad_servers); push(@Reasons, $reason); $summary .= "$bad_servers($zone) "; } } @FailedServers=split(' ',join(" ",@FailedServers)); if ($err_cnt > 0) { print "$summary\n"; # Now print the detail lines for ($i=0; $i<=$#FailedZones; $i++) { print "Zone '$FailedZones[$i]': failed servers: $FailedServers[$i]\n"; foreach $line (split("\n", $Reasons[$i])) { print "$line\n"; } print "\n"; } } exit $err_cnt; } else { my($err_cnt) = 0; my($bad_servers, $summary, $reason, $failcount, @FailedQuerys, @FailedServers, @Reasons); my($query, $type, $line, $i, $target); my $allsummary; foreach (@Queries) { ($query, $type, $target) = split /:/; $type = 'A' if ($type eq ""); ($bad_servers, $summary, $reason, $failcount) = dns_test($query, $type, $target, @ARGV); if (defined($bad_servers)) { $err_cnt = $failcount if ($failcount > $err_cnt); push(@FailedQuerys, "$query $type") if (!$target); push(@FailedQuerys, "$query $type == $target $type") if ($target); push(@FailedServers, $bad_servers); push(@Reasons, $reason); $allsummary .= "$summary "; } } @FailedServers=split(' ',join(" ",@FailedServers)); if ($err_cnt > 0) { print "$allsummary\n"; # Now print the detail lines for ($i=0; $i<=$#FailedQuerys; $i++) { foreach $line (split("\n", $Reasons[$i])) { print "$line\n"; } print "\n"; } } exit $err_cnt; } # dns_verify($zone, \@master, \@Servers) # This subroutine takes 3 or more arguments. The first argument is the name of # the DNS zone/domain to check. The second argument is the name of the DNS # server you consider to be the master of the given zone. The subroutine # will make a DNS query to the the master to get the SOA for the zone and # extract the serial number. The third and rest of the arguments are taken as # names of slave DNS servers. Each server will be queried for the SOA of the # given zone and the serial number will be checked against that found in the # SOA record on the master server. By default the zone serials must be # the same. This may be overridden by the serial_threshold command line # argument. # The return value is a 3 element list. The first element is a space delimited # string containing the names of the slave servers that did not match the # master zone. The second element is a string containing the diagnostic # output that should explain the problem encountered. The third element is a count # of how many servers failed, which will be used as the exit code. sub dns_verify { # First verify that we have enough arguments. my($Zone) = shift; my(@Master) = @{shift()}; my(@Servers) = @{shift()}; my($result) = undef; my(@failed, $res, $soa_req, $Serial, $error_cnt, $server); my(%serials) = (); my(%errors) = (); # Query the $Master for the SOA of $Zone and get the serial number. $res = new Net::DNS::Resolver; $res->usevc(1) if ($UseTCP); $res->defnames(0); # don't append default zone $res->recurse(0); # no recursion $res->retry($retries); # retries before failure $res->retrans($retrans); # retransmission interval $res->udp_timeout($timeout); # set udp timeout $res->tcp_timeout($timeout); # set tcp timeout $error_cnt=0; # Loop through each master server foreach my $qs (@Master) { $res->nameservers($qs); $soa_req = $res->query($Zone, "SOA"); if (!defined($soa_req) || ($soa_req->header->ancount <= 0)) { $error_cnt++; $errors{$qs} = sprintf("SOA query for $Zone from $qs failed %s\n", $res->errorstring); if ($res->errorstring eq 'NOERROR') { $errors{$qs} .= sprintf(" Empty answer received. (No zone on server?)\n") } if ($failsingle) { return ($qs, $errors{$qs}, 251); } next; } unless ($soa_req->header->aa) { $error_cnt++; $errors{$qs} = sprintf("$qs is not authoritative for $Zone\n"); if ($failsingle) { return ($qs, $errors{$qs}, 251); } next; } unless ($soa_req->header->ancount == 1) { $error_cnt++; $errors{$qs} = sprintf("Too many answers for SOA query to %s for %s\n", $qs, $Zone); if ($failsingle) { return ($qs, $errors{$qs}, 251); } next; } unless (($soa_req->answer)[0]->type eq "SOA") { $error_cnt++; $errors{$qs} = printf("Query for SOA for %s from %s failed: " . "return type = %s\n", $Zone, $qs, ($soa_req->answer)[0]->type); if ($failsingle) { return ($qs, $errors{$qs}, 251); } next; } $serials{$qs} = ($soa_req->answer)[0]->serial; } if ($debug >= 2) { print Data::Dumper->Dump([\%serials], ['serials']); } if ($error_cnt == scalar @Master) { # all masters errored return("", values %errors, 251); } my $maxvalue = undef; my $minvalue = undef; my $maxkey = undef; my $minkey = undef; foreach my $key (keys %serials) { if ($serials{$key} > $maxvalue) { $maxvalue = $serials{$key}; $maxkey = $key; } if (($serials{$key} < $minvalue) || (!defined $minkey)) { $minvalue = $serials{$key}; $minkey = $key; } } if (abs($maxvalue - $minvalue) > $SerialThreshold) { return ($minkey, "\nQuery to $minkey about $Zone failed\n" . "Serial number = $minvalue, should have been $maxvalue\n", 252) } $Serial = $maxvalue; return ("", "\nNo SOA Serial found for $Zone!?!?", 252) if (!$Serial); # Now, foreach server given on the command line, get the serial number from # the SOA and compare it to the master. $error_cnt = 0; foreach $server (@Servers) { $res = new Net::DNS::Resolver; $res->usevc(1) if ($UseTCP); $res->defnames(0); # don't append default zone $res->recurse(0); # no recursion $res->retry($retries); $res->retrans($retrans); $res->udp_timeout($timeout); $res->tcp_timeout($timeout); $res->nameservers($server); $soa_req = $res->query($Zone, "SOA"); if (!defined($soa_req) || ($soa_req->header->ancount <= 0)) { $error_cnt++; push(@failed, $server); $result .= sprintf("\nSOA query for $Zone from $server failed %s\n", $res->errorstring); if ($res->errorstring eq 'NOERROR') { $result .= sprintf(" Empty answer received. (No zone on server?)\n"); } next; } unless($soa_req->header->aa && $soa_req->header->ancount == 1 && ($soa_req->answer)[0]->type eq "SOA" && ((abs(($soa_req->answer)[0]->serial - $Serial)) <= $SerialThreshold)) { $error_cnt++; push(@failed, $server); $result .= sprintf("\nQuery to $server about $Zone failed\n" . "Authoritative = %s\n" . "Answer count = %d\n" . "Answer Type = %s\n" . "Serial number = %s, should have been %s\n" , $soa_req->header->aa ? "yes" : "no", $soa_req->header->ancount, ($soa_req->answer)[0]->type, ($soa_req->answer)[0]->serial, $Serial); next; } } if ($error_cnt == 0) { return(undef, undef, undef); } else { return("@failed", $result, $error_cnt); } } # dns_test($query, $type, $target, $server, ...) # This subroutine takes 4 or more arguments. The first argument is the name of # the DNS record to query. The second argument is the type of the DNS # query to perform. The third argument is the name of a second DNS record to query, # whose results should match the first query. The fourth and rest of the arguments are # taken as names of caching DNS servers. Each server will be queried for the # given record and type # The return value is a 3 element list. The first element is a space delimited # string containing the names of the servers that failed to respond to the # query. The second element is a string containing the diagnostic # output that should explain the problem encountered. The third element is the # count of how many servers failed, which will be used as the exit code. sub dns_test { # First verify that we have enough arguments. my($Query, $type, $target, @Servers) = @_; my($summary) = undef; my($result) = undef; my(@failed, $res, $req, $treq, $Serial, $error_cnt, $server); # Now, foreach server given on the command line, # make the query $error_cnt = 0; foreach $server (@Servers) { $res = new Net::DNS::Resolver; $res->defnames(0); # don't append default zone $res->retry($retries); # 2 retries before failure $res->retrans($retrans); $res->udp_timeout($timeout); $res->tcp_timeout($timeout); $res->nameservers($server); $req = $res->query($Query, $type); if (!defined($req) || ($req->header->ancount <= 0)) { $error_cnt++; push(@failed, $server); $result .= sprintf("\n$type query for $Query from $server failed %s\n", $res->errorstring); $summary .= "$Query\@$server "; next; } elsif ($target) { $treq = $res->query($target, $type); my $status = 0; foreach my $qans ($req->answer) { print STDERR $qans->string."\n" if ($debug); print STDERR $qans->rdatastr."\n" if ($debug); foreach my $tans ($treq->answer) { print STDERR "target\n" if ($debug); print STDERR $tans->string."\n" if ($debug); print STDERR $tans->rdatastr."\n" if ($debug); if ($tans->rdatastr eq $qans->rdatastr) { print STDERR "match found\n" if ($debug); $status = 1; last; } } last if ($status); } if (!$status) { $error_cnt++; push @failed, $server; $result .= "Query $Query:$type failed to match $target\n"; } } } if ($error_cnt == 0) { return(undef, undef, undef), undef; } else { return("@failed", $summary, $result, $error_cnt); } } sub usage { print STDERR < # $RCSid = q{$Id: file_change.monitor,v 1.2 2004/11/15 14:45:19 vitroth Exp $}; # # Copyright (C) 2001 Jon Meek # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # =head1 NAME file_change.monitor =head1 SYNOPSIS I =head1 DESCRIPTION B will watch specified files in a directory and trigger an alert when any monitored file changes, or is missing. File changes can optionally be logged using RCS. This monitor was designed to monitor B of the actual files. The files will often be copies of files mirrored from remote systems such as firewalls, routers, mail gateways, etc. File changes are detected using MD5 checksums. Current file information is stored in the mon state directory in a file that corresponds to the base directory (with '/' replaced by '_'). The file contains a time stamp (in UNIX seconds), the MD5 checksum (in hexadecimal) and the name of the file. This file is generated automatically if it does not already exist. =head1 OPTIONS =over 5 =item B<-b base_directory> The base directory for the files. All filenames are relative to this directory. =item B<-r> Log file changes using RCS. Each directory containing files to be checked should have an RCS subdirectory. The mon user needs access (possibly both file permissions and RCS authorization) to the RCS files. B will leave the file locked so that it will be able to check in the next revision. This option should NOT be used when the original files are being monitored directly since there will be permission issues and because the current checkin process re-writes the original file (via I). =item B<-d> Provide debugging information. =back =head1 EXAMPLE MON CONFIGURATION hostgroup fw_configs pr-ifw/pr-ifw1.html pt-ifw/pt-ifw.html rd-ifw/rd-ifw1.html rd-ifw/rd-ifw2.html watch fw_configs service file_change interval 5m monitor file_change.monitor -r -b /home/httpd/html/sys_status period wd {Sun-Sat} alert mail.alert meekj@ieee.org =head1 HANDLING RCS PERMISSION ISSUES Files must be initially checked-in before the monitor can take over the task. sudo -u netmon ci -l file.cfg If file_change.monitor ever runs as a different user, such as root, there will be problems. To correct the situation, perform the following on each file: sudo ci -u -mfile_change.monitor file.cfg sudo -u netmon co -l file.cfg =head1 BUGS B does not currently recognize any file locking mechanism. There could be a problem if a file is being modified when the monitor runs. Using a program like rsync to copy files to the monitor directory should nearly eliminate this problem since copies are usually made to a temporary file and the rename is an atomic operation. =head1 AUTHOR Jon Meek =cut use Getopt::Long; use Digest::MD5; $TimeNow = time; GetOptions( "b=s" => \$BaseDir, "d" => \$Debug, "r" => \$RCS, ); $StateFile = $BaseDir; $StateFile =~ s/\//_/g; # Change / to _ to make filename $StateFile = "$ENV{MON_STATEDIR}/$StateFile"; $CI = 'ci'; # Assume that RCS's ci is in the path print "Will use RCS: $RCS\n" if $Debug; # # Read the previous checksums if the State File exists # if (-e $StateFile) { print "Existing $StateFile\n" if $Debug; open(F, $StateFile); while ($in = ) { ($t, $md5, $f) = split(' ', $in); if ($md5 eq 'LastCheck') { # May add a LastCheck time later $LastCheck = $md5; } else { $PrevChangeTime{$f} = $t; $PrevMD5{$f} = $md5; } } close F; $StateFileExists = 1; # Remember that there is a existing State File } else { $StateFileExists = 0; # or not print "No Existing $StateFile\n" if $Debug; } $NewFile = 0; @Failures = (); foreach $f (@ARGV) { if ($f =~ /\*/) { push(@Files, glob("$BaseDir/$f")); } else { push(@Files, "$BaseDir/$f"); } } #@Files = @ARGV; # File names are left on the command line after Getopt $md5 = new Digest::MD5; foreach $f (@Files) { # Check each file # if (defined $BaseDir) { # $rdfile = "$BaseDir/$f"; # } else { # $rdfile = "$f"; # } # if (open(F, $rdfile)) { if (open(F, $f)) { seek(F, 0, 0); # Compute MD5 checksum $md5->reset(); $md5->addfile(F); $fileMD5 = $md5->hexdigest(); close F; print "File: $f\n NewMD5: $fileMD5\n PreviousMD5: $PrevMD5{$f}\n" if $Debug; $CurrentMD5{$f} = $fileMD5; if (exists $PrevMD5{$f}) { if ($CurrentMD5{$f} ne $PrevMD5{$f}) { push(@Failures, $f); $CurrentChangeTime{$f} = $TimeNow; $dTime = $TimeNow - $PrevChangeTime{$f}; $fmtTimeDiff = &TimeDisplayScale($dTime); $ResultString{$f} = "File changed, previous change $fmtTimeDiff"; print " File: $f changed, previous change $dTime s\n" if $Debug; if ($RCS) { # Check new version of file into RCS $Command = "$CI -l -mfile_change.monitor $f 2>&1"; # Save STDOUT & STDIN from ci print " ci command: $Command\n" if $Debug; $OpenResult = open(CI, "$Command |") or warn "Can't fork $Command: $!"; print " command open result: $CmdResult\n" if $Debug; while ($in = ) { $CiOutput .= $in; } close CI or warn "Can't close ci: $!/$?";; print " ci output: $CiOutput\n" if $Debug; } } else { $CurrentChangeTime{$f} = $PrevChangeTime{$f}; } } else { # Here if no state file entry exists for this $f $CurrentChangeTime{$f} = $TimeNow; $NewFile++; } } else { # The file does not exist, report as a failure push(@Failures, $f); $ResultString{$f} = 'File Does Not Exist'; } } print "\n" if $Debug; # # Report results, or keep quiet if all is well # print "New: $NewFile Fail: @Failures $StateFile\n" if $Debug; if ($NewFile || @Failures) { # Need to write new state file print "Writing a new $StateFile\n" if $Debug; open(F, ">$StateFile"); foreach $f (sort keys %CurrentMD5) { print F "$CurrentChangeTime{$f} $CurrentMD5{$f} $f\n"; } close F; } if (@Failures == 0) { # No files changed exit 0; } # # Handle file change notification # print "@Failures\n"; foreach $f (sort @Failures) { print "$f: $ResultString{$f}\n\n"; } print "\n"; print "$CiOutput\n"; #print "$CiOutput\n" if $Debug; exit 1; # Indicate failures sub TimeDisplayScale { # Scale the time from seconds to minutes/hours/days my($current_time, $past_time) = @_; my($dt, $ret, $idt, $dts); $dt = $current_time - $past_time; $dts = $dt; if ($dt < 60) { # Arbitrary seconds/minutes boundry $ret = "$dt seconds"; } else { $dt = $dt / 60; $idt = int ($dt + 0.5); $ret = sprintf("%d minutes (%d s)", $idt, $dts); } if ($dt > 120) { # Arbitrary minutes/hours boundry $dt = $dt / 60; $ret = sprintf("%0.1f hours (%d s)", $dt, $dts); } if ($dt > 48) { # Arbitrary hours/day boundry $dt = $dt / 24; $ret = sprintf("%0.1f days (%d s)", $dt, $dts); } return $ret; } __END__ file_change.monitor -d -b /home/httpd/html/sys_status pr-ifw/pr-ifw1.html pt-ifw/pt-ifw.html ~/lab/mon/file_change.monitor -r -d -b /home/httpd/html/sys_status rd-ifw/rd-ifw2.html etbemon-1.3.6/mon.d/foundry-chassis.monitor0000755000000000000000000001472213135636631015625 0ustar #!/usr/bin/perl # # "mon" monitor to detect chassis-related failures for Foundry switches # # arguments are "[-c community] host [host...]" # # # Jim Trocki # # $Id: foundry-chassis.monitor,v 1.1.1.1 2004/06/09 05:18:05 trockij Exp $ # # Copyright (C) 2000, Jim Trocki # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # use Mon::SNMP; use Getopt::Std; use strict; sub get_status; sub get_table; sub get_vars; $ENV{"MIBS"} = "FOUNDRY-SN-AGENT-MIB:RFC1213-MIB"; my %opt; getopts ('c:', \%opt); my $COMM = $opt{"c"} || "public"; my @failures = (); my $detail = ""; my %fans; my %PSUs; my %modules; foreach my $host (@ARGV) { my %status = get_status ($host, $COMM); if ($status{"error"} ne "") { push (@failures, $host); $detail .= "could not retrieve status from $host: $status{error}\n\n"; next; } elsif ($status{"failure"}) { push (@failures, $host); $detail .= $status{"failure_summary"}; } $fans{$host} = $status{"fan_table"}; $PSUs{$host} = $status{"psu_table"}; $modules{$host} = $status{"mod_table"}; } if (@failures != 0) { print join (" ", sort @failures), "\n\n$detail\n"; } else { print "\n$detail"; } print <{"iid"}, $r->{"snChasFanOperStatus"}, $r->{"snChasFanDescription"}); } print "\n"; } print <{"iid"}, $r->{"snChasPwrSupplyOperStatus"}, $r->{"snChasPwrSupplyDescription"}); } print "\n"; } print <{"iid"}, $r->{"snAgentBrdModuleStatus"}, $r->{"snAgentBrdMainBrdDescription"}); } print "\n"; } if (@failures != 0) { exit 1; } exit 0; # # params: (hostname, community) # # returns: # ( # "error" => "error name, empty string means no error", # "failure" => "nonzero if a failure", # "psu_table" => [], # "fan_table" => [], # "mod_table" => [], # ) # sub get_status { my ($host, $comm) = @_; my $s; if (!defined ($s = new SNMP::Session ( "DestHost" => $host, "Community" => $comm, "Version" => 2, "UseEnums" => 1, ))) { return ("error" => "cannot create session"); } my $error; my $failure_detected = 0; my $failure_summary = ""; my $psu_table; my $fan_table; my $mod_table; # # is this really a foundry box? # my $sys_oid = $s->get (["sysObjectID", 0]); return ("error" => $s->{"ErrorStr"}) if ($s->{"ErrorStr"} ne ""); return ("error" => "not Foundry device") if ($sys_oid !~ /^\.1\.3\.6\.1\.4\.1\.1991\./); # # this is indeed foundry equipment, so # get power supply table # ($error, $psu_table) = get_table ($s, ["snChasPwrSupplyDescription"], ["snChasPwrSupplyOperStatus"], ); return ("error" => $error) if ($error ne ""); foreach my $r (@{$psu_table}) { next if ($r->{"snChasPwrSupplyOperStatus"} eq "normal"); $failure_detected = 1; $failure_summary .= "$host PSU failure: $r->{snChasPwrSupplyDescription}\n"; last; } # # get fan table # ($error, $fan_table) = get_table ($s, ["snChasFanDescription"], ["snChasFanOperStatus"], ); return ("error" => $error) if ($error ne ""); foreach my $r (@{$fan_table}) { next if ($r->{"snChasFanOperStatus"} eq "normal"); $failure_detected = 1; $failure_summary .= "$host fan failure: $r->{snChasFanDescription}\n"; last; } # # get module status # ($error, $mod_table) = get_table ($s, ["snAgentBrdMainBrdDescription"], ["snAgentBrdModuleStatus"], ); return ("error" => $error) if ($error ne ""); foreach my $r (@{$mod_table}) { next if ($r->{"snAgentBrdModuleStatus"} eq "moduleRunning"); $failure_detected = 1; $failure_summary .= "$host module failure: $r->{snAgentBrdMainBrdDescription}\n"; last; } ( "error" => "", "failure" => $failure_detected, "failure_summary" => $failure_summary, "psu_table" => $psu_table, "fan_table" => $fan_table, "mod_table" => $mod_table, ); } sub get_table { my ($s, @tbl) = @_; my $table = []; my $tblid = $tbl[0]->[0]; my $i = 0; my $row = new SNMP::VarList (@tbl); return ("MIB problem") if (!defined $row); while (defined ($s->getnext ($row))) { last if ($s->{"ErrorStr"} ne ""); my $r = $row->[0]->[0]; last if ($r ne $tblid); foreach my $col (@{$row}) { $table->[$i]->{"iid"} = $col->[1]; $table->[$i]->{$col->[0]} = $col->[2]; } $i++; } return ($s->{"ErrorStr"}) if ($s->{"ErrorStr"} ne ""); ( "", $table, ); } sub get_vars { my ($s, @vars) = @_; my $r = new SNMP::VarList ( @vars ); return ("MIB problem") if (!defined $r); return ($s->ErrorStr) if (!defined ($s->get ($r))); my $v; foreach my $element (@{$r}) { $v->{$element->[0]} = $element->[2]; } ("", $v); } etbemon-1.3.6/mon.d/fping.monitor0000755000000000000000000001172410620740052013573 0ustar #!/usr/bin/perl # # Return a list of hosts which not reachable via ICMP echo # # Jim Trocki, trockij@arctic.org # # $Id: fping.monitor,v 1.3.2.1 2007/05/11 01:00:26 trockij Exp $ # # Copyright (C) 1998, Jim Trocki # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # use strict; use Getopt::Std; my %opt; getopts ("ahr:s:t:T", \%opt); sub usage { print <&1 |") || die "could not open pipe to fping: $!\n"; my @unreachable; my @alive; my @addr_not_found; my @slow; while () { chomp; if (/^(\S+) is unreachable/) { push (@unreachable, $1); } elsif (/^(\S+) is alive \((\S+)/) { if ($opt{"s"} && $2 > $opt{"s"}) { push (@slow, [$1, $2]); } else { push (@alive, [$1, $2]); } } elsif (/^(\S+)\s+address\s+not\s+found/) { push @addr_not_found, $1; push @unreachable, $1; } # # fping can output a number of messages in addition to the eventual # reachable/unreachable. Ignore them since we'll also get the main # "unreachable" message). # elsif (/^ICMP .+ from \S+ for ICMP Echo sent to /) { # do nothing } # # ICMP Host Unreachable from 1.2.3.4 for ICMP Echo sent to 2.4.6.8 # elsif (/^ICMP (.*) for ICMP Echo sent to (\S+)/) { if (! exists $details{$2}) { $details{$2}= $_; } } elsif (/^ICMP Time Exceeded from \S+ for ICMP Echo sent to (\S+) /) { push @unreachable, $1; } else { print STDERR "unidentified output from fping: [$_]\n"; } } close (IN); $END_TIME = time; my $retval = $? >> 8; if ($retval == 3) { print "fping: invalid cmdline arguments [$CMD @ARGV]\n"; exit 1; } elsif ($retval == 4) { print "fping: system call failure\n"; exit 1; } elsif ($retval == 1 || $retval == 2 || @slow != 0) { print join (" ", sort (@unreachable, map { $_->[0] } @slow)), "\n\n"; } elsif ($retval == 0) { print "\n"; } else { print "unknown return code ($retval) from fping\n"; } print "start time: " . localtime ($START_TIME) . "\n"; print "end time : " . localtime ($END_TIME) . "\n"; print "duration : " . ($END_TIME - $START_TIME) . " seconds\n\n"; if (@unreachable != 0) { print <&1"); } print "\n"; } # # fail only if all hosts do not respond # if ($opt{"a"}) { if (@unreachable == @ARGV) { exit 1; } exit 0; } exit 1 if (@slow != 0); exit $retval; etbemon-1.3.6/mon.d/ftp.monitor0000755000000000000000000001122010620057066013256 0ustar #!/usr/bin/perl # # Use try to connect to a FTP server, and # wait for the right output. # # For use with "mon". # # Arguments are "-p port -t timeout host [host...]" # # Adapted from "http.monitor" by # Jim Trocki # # http.monitor originally written by # # Jon Meek # American Cyanamid Company # Princeton, NJ # # $Id: ftp.monitor,v 1.1.1.1.4.1 2007/05/08 11:25:42 trockij Exp $ # # Copyright (C) 1998, Jim Trocki # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # use Getopt::Std; use English; getopts ("p:t:"); $PORT = $opt_p || 21; $TIMEOUT = $opt_t || 30; my %good; my %bad; # # collect the status on all the hosts # foreach my $host (@ARGV) { my $result = ftpGET ($host, $PORT); if (!$result->{"ok"}) { $bad{$host} = $result; } else { $good{$host} = $result; } } # # summary line # if (keys %bad == 0) { print "\n"; } else { print join (" ", sort keys %bad), "\n"; } # # detail # foreach my $host (keys %bad) { print "$host failed with error " . $bad{$host}->{"error"}, "\n"; print "detail for $host\n"; print "==============================================================================\n"; if ($bad{$host}->{"detail"} ne "") { print $bad{$host}->{"detail"}; } else { print "no detail\n"; } print "\n"; } print "\n"; foreach my $host (keys %good) { print "$host succeeded\n"; print "detail for $host\n"; print "==============================================================================\n"; if ($good{$host}->{"detail"} ne "") { print $good{$host}->{"detail"}; } else { print "no detail\n"; } print "\n"; } if (keys %bad != 0) { exit 1; } exit 0; sub ftpGET { use Socket; use Sys::Hostname; my($Server, $Port) = @_; my($ok); my $result = { "ok" => 0, "error" => undef, "detail" => undef, }; ############################################################### eval { local $SIG{ALRM} = sub { die "Timeout Alarm" }; alarm $TIMEOUT; my $err = &OpenSocket($Server, $Port); # Open a connection to the server if ($err ne "") { # Failure to open the socket $result = { "ok" => 0, "error" => $err, "detail" => undef, }; return $result; } while ($in = ) { $result->{"detail"} .= " < $in"; if ($in =~ /^220 /) { $result->{"ok"} = 1; last; } } if (!$result->{"ok"}) { alarm 0; $result->{"ok"} = 0; $result->{"error"} = "Connection refused"; close(S); return undef; } print S "quit\r\n"; $result->{"detail"} .= " > quit\n"; while ($in = ) { $result->{"detail"} .= " < $in"; next if ($in =~ /^[0-9]{3}\-/); if ($in !~ /^221 /) { alarm 0; $result->{"ok"} = 0; $result->{"error"} = "FTP server error after quit"; close(S); return undef; } } close(S); alarm 0; # Cancel the alarm }; # # catch timeout # if ($EVAL_ERROR and ($EVAL_ERROR =~ /^Timeout Alarm/)) { $result->{"ok"} = 0; $result->{"error"} = "timeout"; } return $result; } # # Make a Berkeley socket connection between this program and a TCP port # on another (or this) host. Port can be a number or a named service # # returns "" on success, or an error string on failure # sub OpenSocket { my ($host, $port) = @_; my $proto = (getprotobyname('tcp'))[2]; return ("could not get protocol") if (!defined $proto); my $conn_port; if ($port =~ /^\d+$/) { $conn_port = $port; } else { $conn_port = (getservbyname($port, 'tcp'))[2]; return ("could not getservbyname for $port") if (!defined $conn_port); } my $host_addr = (gethostbyname($host))[4]; return ("gethostbyname failure") if (!defined $host_addr); my $that = sockaddr_in ($conn_port, $host_addr); if (!socket (S, &PF_INET, &SOCK_STREAM, $proto)) { return ("socket: $!"); } if (!connect (S, $that)) { return ("connect: $!"); } select(S); $| = 1; select(STDOUT); ""; } etbemon-1.3.6/mon.d/hpnp.monitor0000755000000000000000000000556310061516615013446 0ustar #!/usr/bin/perl # # SNMP monitoring of HP JetDirect-equipped printers # # returns 1 if an actual printer failure is indicated by SNMP, # or 2 if it cannot communicate with the printer. # # Jim Trocki # # $Id: hpnp.monitor,v 1.1.1.1 2004/06/09 05:18:05 trockij Exp $ # # Copyright (C) 1998, Jim Trocki # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # use SNMP; use Getopt::Long; GetOptions (\%opt, "community=s", "timeout=i", "retries=i", "lpq"); die "no host arguments\n" if (@ARGV == 0); $RET = 0; @ERRS = (); $COMM = $opt{"community"} || "public"; $TIMEOUT = $opt{"timeout"} * 1000 * 1000 || 2000000; $RETRIES = $opt{"retries"} || 5; @DESC = ("offline", "paper problem", "needs human intervention", "peripheral error", "paper out", "paper jam", "toner low"); foreach $host (@ARGV) { undef $s; if (!defined($s = new SNMP::Session (DestHost => $host, Timeout => $TIMEOUT, Community => $COMM, "Version" => 2, Retries => $RETRIES))) { print "cannot create SNMP session to $host\n"; $RET = ($RET == 1) ? 1 : 2; next; } undef $vars; $vars = new SNMP::VarList ( ['.1.3.6.1.4.1.11.2.3.9.1.1.2.1', 0], # line state ['.1.3.6.1.4.1.11.2.3.9.1.1.2.2', 0], # paper state ['.1.3.6.1.4.1.11.2.3.9.1.1.2.3', 0], # human intervention ['.1.3.6.1.4.1.11.2.3.9.1.1.2.6', 0], # gdStatusPeripheralError ['.1.3.6.1.4.1.11.2.3.9.1.1.2.8', 0], # gdStatusPaperOut ['.1.3.6.1.4.1.11.2.3.9.1.1.2.9', 0], # gdStatusPaperJam ['.1.3.6.1.4.1.11.2.3.9.1.1.2.10', 0], # gdStatusTonerLow ['.1.3.6.1.4.1.11.2.3.9.1.1.3', 0], # gdStatusDisplay ); if (!defined ($s->get($vars))) { push (@hosts, $host); push (@ERRS, "$host unreachable\n\n"); $RET = ($RET == 1) ? 1 : 2; next; } $display = ${$vars}[7]->val; $h = 0; @H = (); for ($i = 0; $i< 6; $i++) { if (${$vars}[$i]->val) { push (@H, @DESC[$i]); $RET = 1; $h = 1; } } if ($h) { push (@hosts, $host); } if (@H > 0) { push (@ERRS, "$host\n" . "-" x length($host) . "\n" . join ("\n", @H, "\n")); push (@ERRS, "display reads:\n$display\n\n"); } } if (@hosts > 0) { print join (" ", sort @hosts), "\n"; print "\n"; print @ERRS; } exit $RET; etbemon-1.3.6/mon.d/http.monitor0000755000000000000000000001147213143527701013456 0ustar #!/usr/bin/perl use strict; # # Use try to connect to a http server. # For use with "mon". # # http.monitor [-p port] [-t secs] [-u url] [-a agent] [-o] host [host...] # # -p port TCP port to connect to (defaults to 80) # -t secs timeout, defaults to 30 # -u url path to get, defaults to "/" # -a agent User-Agent, default to "mon.d/http.monitor" # -o omit http headers from healthy hosts # -m regex match regex in response (header + content) # # Jon Meek # American Cyanamid Company # Princeton, NJ # # $Id: http.monitor,v 1.1.1.1.4.1 2007/05/08 11:05:48 trockij Exp $ # # Copyright (C) 1998, Jim Trocki # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # use Getopt::Std; use English; use Data::Dumper; sub httpGET; our $opt_p; our $opt_t; our $opt_u; our $opt_a; our $opt_m; our $opt_o; getopts ("p:t:u:a:m:o"); my $PORT = $opt_p || 80; my $TIMEOUT = $opt_t || 30; my $URL = $opt_u || "/"; my $USERAGENT = $opt_a || "mon.d/http.monitor"; my $MATCHRE = $opt_m; my %good; my %bad; exit 0 if (!@ARGV); foreach my $host (@ARGV) { my $result = httpGET ($host, $PORT); if (!$result->{"ok"}) { $bad{$host} = $result; } else { $good{$host} = $result; } } my $ret; if (keys %bad) { $ret = 1; print join (" ", sort keys %bad), "\n"; } else { $ret = 0; print "\n"; } foreach my $h (keys %bad) { print "HOST $h: $bad{$h}->{error}\n"; if ($bad{$h}->{"header"} ne "") { print $bad{$h}->{"header"}, "\n"; } print "\n"; } if (!$opt_o) { foreach my $h (keys %good) { print "HOST $h: ok\n"; print $good{$h}->{"header"}, "\n"; print "\n"; } } exit $ret; sub httpGET { use Socket; use Sys::Hostname; my($Server, $Port) = @_; my($ServerOK, $TheContent); $TheContent = ''; my $Path = $URL; my $result = { "ok" => 0, "error" => undef, "header" => undef, }; ############################################################### eval { local $SIG{ALRM} = sub { die "Timeout Alarm" }; alarm $TIMEOUT; my $err = &OpenSocket($Server, $Port); # Open a connection to the server if ($err ne "") { # Failure to open the socket $result = { "ok" => 0, "error" => $err, "header" => undef, }; return undef; } print S "GET $Path HTTP/1.0\r\n"; print S "Host: $Server\r\n"; print S "User-Agent: $USERAGENT\r\n\r\n"; while (my $in = ) { $TheContent .= $in; # Store data for later processing } close(S); alarm 0; # Cancel the alarm }; ($result->{"header"}) = ($TheContent =~ /^(.*?)\r?\n\r?\n/s); if ($TheContent =~ /^HTTP\/([\d\.]+)\s+(200|30[12]|401)\b/) { $result->{"ok"} = 1; } else { $result->{"ok"} = 0; $result->{"error"} = "HTTP response code failure"; } if ($MATCHRE ne "") { if ($TheContent =~ /$MATCHRE/s) { $result->{"ok"} = 1; } else { $result->{"ok"} = 0; $result->{"error"} = "Regex match failed"; } } # check $result->{"ok"} as timeout isn't a problem if we already got good data # should rewrite this to use a http library if ($result->{"ok"} != 1 && $EVAL_ERROR and ($EVAL_ERROR =~ /^Timeout Alarm/)) { $result->{"ok"} = 0; $result->{"error"} = "timeout after $TIMEOUT seconds"; } return $result; } # # Make a Berkeley socket connection between this program and a TCP port # on another (or this) host. Port can be a number or a named service # # returns "" on success, or an error string on failure # sub OpenSocket { my ($host, $port) = @_; my $proto = (getprotobyname('tcp'))[2]; return ("could not get protocol") if (!defined $proto); my $conn_port; if ($port =~ /^\d+$/) { $conn_port = $port; } else { $conn_port = (getservbyname($port, 'tcp'))[2]; return ("could not getservbyname for $port") if (!defined $conn_port); } my $host_addr = (gethostbyname($host))[4]; return ("gethostbyname failure") if (!defined $host_addr); my $that = sockaddr_in ($conn_port, $host_addr); if (!socket (S, &PF_INET, &SOCK_STREAM, $proto)) { return ("socket: $!"); } if (!connect (S, $that)) { return ("connect: $!"); } select(S); $| = 1; select(STDOUT); ""; } etbemon-1.3.6/mon.d/http_tppnp.monitor0000755000000000000000000007103310630617405014675 0ustar #!/usr/bin/perl # # Parallel http monitor, with timing, using separate process for each request # results are gathered using a named pipe # an optional "SmartAlarm" capability is provided # to classify alarms and/or limit alarms when there # are sporadic outages # # http_tppnp.monitor : http _ timing - proxy - parallel - named pipe # http _ t p p np # # # Jon Meek # Lawrenceville, NJ # meekj at ieee.org # # $Id: http_tppnp.monitor,v 1.2.2.1 2007/06/03 20:05:25 trockij Exp $ # # Copyright (C) 2004, Jon Meek # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # =head1 NAME B - http/https server parallel monitor for mon =head1 DESCRIPTION http/https server monitor for mon. Logs timing and size results, can use a proxy server. Each measurements is made using a separate measurement process, a central server is used to collect, process, and log the results. An optional "SmartAlarm" capability is provided to classify alarms and/or limit alarms when there are sporadic outages =head1 SYNOPSIS B -l log_file_YYYYMM.log [--servertimeout nn] [--clienttimeout nn] [--responsealarmtime nn] [--randskew nn] [--okcodes nnn,mmm,kkk] [--okstring 'Required string'] [--nocache] [--pipe pipename] [--stripprotocol] [--smartalarm smartalarm.module] [--sacfg smartalarm.cfg] [--smartalarmdir /smartalarm/path] [--forcesmartalarm] [--d --debug] [--debuglog file] [--v] host [host:/path_to_doc ...] The host list can be in any combination of the following: webmail.mysite.com/index.html http://webmail.mysite.com/ test.mysite.com/~meekj/ca_zip.txt@proxy.mysite.com http://webmail.mysite.com:81/ https://webmail.mysite.com/ http is the default if the protocol is not specified =head1 OPTIONS =over 5 =item B<-l log_file_template> or B<--log log_file_template> /path/to/logs/internet_web_YYYYMM.log Current year & month are substituted for YYYYMM, that is the only possible template at this time. The format of the log file is: unix_time proxy protocol://host path bytes response_time response_code If B<--stripprotocol> is specified then protocol:// is not included. The response_time is in seconds. If the response was determined to be a failure the time is reported as a negative number. =item B<-c> or B<--okcodes> Comma seperated list of acceptable http response codes, 200 is the default but must be explicitly included in the list if -c or --okcodes is used. =item B<--okstring 'Required string'> If defined, the string must be present in the content for the test to pass. The string can be a simple Perl regular expression, be sure to test it on your data. Note that Perl regular expression special characters ( +?.*^$()[{|\ ) may need to be escaped if your string is NOT supposed to be a regular expression. =item B<--nocache> Add 'Pragma: no-cache' and 'Cache-Control: max-stale=0' headers to all requests. In addition, check for Warning headers which indicate that the content was delivered from the cache anyway. This seems to be required when monitoring certain Web sites through certain cache servers. =item B<--servertimeout N s> Wait this long before giving up the wait for measurement results. If you change this, be sure that it is at least (clienttimeout + randskew + 5) seconds. Defaults to 45 seconds. =item B<--clienttimeout N s> N s The maximum time each measurement process waits for a response after its request is made (timeout starts after randskew time). Defaults to 30 seconds. =item B<--responsealarmtime N s> or B<-T N s> Trigger an alarm if any response is greater than N seconds. Defaults to a very large number, effectively disabling response time checks beyond the regular timeout. =item B<--randskew N s> Each measurement process will wait a random number of seconds, up to this maximum number before starting. Defaults to 10 seconds. =item B<--stripprotocol> Strip {http, https, ftp}:// from the URL stored in the logfile, for backwards compatibility of log format. =item B<--smartalarm Full/path/or/NameOfSmartAlarm> For selecting the httpSmartAlarm module to filter alarms and trigger an alarm only if certain conditions are met. If the full path is not specified, then the smart alarm is expected to exist in the ./mon.d directory (or more precisely, in the same directory as this monitor). Note that .pm should not be included in the module name, however the monitor will strip it out if it is included. The httpSmartAlarm module has the following structure: package httpSmartAlarm; # # Module to provide "Smart Alarms" for http_tppnp.monitor # use Exporter(); $VERSION = 0.02; @ISA = qw(Exporter); @EXPORT = qw(CheckAlarm); sub CheckAlarm { my ($ConfigFile, %TestResult) = @_; $TotalDownCount = 0; @DownList = (); &ReadParams($ConfigFile); # Read your config file, if you have one foreach $k (sort keys %TestResult) { # Check the results print "TestResult: $k - $TestResult{$k}\n" if $Debug; ($Failed, $tod, $proxy, $protocol, $site, $file, $size, $t, $http_code) = split(' ', $TestResult{$k}); # # Supply some sort of algorithm here # } return ($TotalDownCount, @DownList); } # Supply a ReadParams subroutine, if needed 1; =item B<--smartalarmdir /path/to/SmartAlarm> Alternate method of supplying the path to the filter module. =item B<--forcesmartalarm> Run SmartAlarm even if there are no failures. Useful if your SmartAlarm looks for other problems such as a bad route. =item B<--sacfg> The full path to the SmartAlarm configuration file. =item B<--pipe /path/to/pipe> The full path, including file name, of the named pipe used for inter-process communication. The default is /tmp/http_tppnp, the PID of the server process is added to this name to ensure uniqueness and allow multiple sets of server/clients to run simultaneously. =item B<-d> or B<--debug> Debug/Test, for manual testing only. =item B<--debuglog file> Write debug and response data to file. Defaults to STDOUT. =item B<-v> Verbose, show content of returned data, for manual testing only. =item B<-a> [Not backported from http_tpp yet] list all results if there is a failure, otherwise list only failed tests =item B<-r> [Not backported from http_tpp yet] Follow redirects, can be useful with -d =back =head1 MON CONFIGURATION EXAMPLE Note that a proxy will be used to access ot.myweb.com hostgroup internet_web www.ama-assn.org www.gartner.com test.mysite.com/~meekj/ca_zip.txt ot.myweb.com/ca_zip.txt@proxy.mysite.com watch internet_web service internet_web interval 5m monitor http_tppnp.monitor -l /usr/local/mon/logs/internet_web_YYYYMM.log -T 10 -t 15 period wd {Sun-Sat} alert mail.alert firewall_admin alertevery 1h summary Command line test examples: http_tppnp.monitor -d www.redhat.com bns.pha.com mythey.com/_mem_bin/FormsLogin.asp\?/ nonexist.pha.com www.sun.com/@proxy.labs.theyw.com http_tppnp.monitor -d www.redhat.com@proxy.labs.theyw.com www.sun.com/@proxy.labs.theyw.com www.yahoo.com/@proxy.labs.theyw.com =head1 BUGS Using a proxy for https or ftp has not been tested, and probably does not work at this time because all proxies are invoked as http. The path to mkfifo is hardcoded to /usr/bin/mkfifo, this is good for Linux and Solaris, but should be an option. Earlier versions had occasional problems with zombie/defunct processes under extreme conditions, such as DNS slowness. Additional protections have been added and this does not seem to be a problem. At times, the monitor would do an "exit 1" telling mon that there was a failure even though the failure list is empty. This is probably fixed. It was due the main program exiting before all the child processes. A two second wait before an "exit 0" appears to be sufficient, but the SIGCHLD handler is also disabled. If zombie processes appear, this method should be reviewed. The above problem could be avoided with a mon option to ignore alerts with an empty failure summary. There should be multiple "debug" output levels. One level should report only information useful to a user running the program manually, such as response times, byte counts, special headers, etc. =head1 REQUIRED PERL MODULES LWP::UserAgent HTTP::Request::Common Time::HiRes and, if https/SSL monitoring will be performed Crypt::SSLeay =head1 AUTHOR Jon Meek, meekj at ieee.org =head1 SEE ALSO http.monitor Use only for simple testing of a small number of hosts. http_tp.monitor Not actively maintained. http_tpp.monitor Should not be used, this monitor is a replacement. phttp.monitor by Gilles LAMIRAL lwp-http.mon by Daniel Hagerty (hag at linnaean.org) =cut $RCSid = q{$Id: http_tppnp.monitor,v 1.2.2.1 2007/06/03 20:05:25 trockij Exp $ }; use IO::Socket; use POSIX qw(:signal_h WNOHANG); use Getopt::Long; use Time::HiRes qw( gettimeofday tv_interval ); use LWP::UserAgent; use HTTP::Request::Common; $SmartAlarmConfig = ''; # Initialize, in case none is supplied # # Note that options needed in the client space must be passed on the client # command line. See sub ForkClient below. # GetOptions( "servertimeout=i" => \$ServerTimeout, "clienttimeout=i" => \$ClientTimeout, "responsealarmtime=i" => \$ResponseAlarmTime, "T=i" => \$ResponseAlarmTime, "randskew=i" => \$RandSkew, "okcodes=s" => \$opt_c, "okstring=s" => \$OKstring, "pipe=s" => \$NamedPipe, "c=s" => \$opt_c, "l=s" => \$opt_l, "log=s" => \$opt_l, "stripprotocol" => \$StripProtocol, "nocache" => \$NoCache, "smartalarm=s" => \$SmartAlarm, # Name of the SmartAlarm module "sacfg=s" => \$SmartAlarmConfig, # Name of the SmartAlarm config file "smartalarmdir=s" => \$SmartAlarmDir, "forcesmartalarm" => \$ForceSmartAlarm, "d" => \$Debug, "debug" => \$Debug, "debuglog=s" => \$DebugLog, "v", "client", # For use by client only "url=s" => \$URL, "proxy=s" => \$Proxy, ); $ServerTimeout = 45 unless $ServerTimeout; $ClientTimeout = 30 unless $ClientTimeout; $ResponseAlarmTime = 10000 unless $ResponseAlarmTime; $RandSkew = 10 unless defined $RandSkew; # Can be zero $NamedPipe = '/tmp/http_tppnp' unless $NamedPipe; $MKFIFO = '/usr/bin/mkfifo'; # Program to make the named pipe, or FIFO my $ResponseCount = 0; # Count the responses as they are delivered my %httpCode = (); # Where the results are kept my %httpTime = (); # Keys are in URL@proxy form my %httpSize = (); my %s = (); # A temporary hash used to pass data $TimeOfDay = time; if ($Debug) { # STDOUT is default destination for debug messages $DebugLog = q{-} unless defined $DebugLog; } if ($DebugLog) { open(DEBUGLOG, ">>$DebugLog") || warn "Can't open debug log: $DebugLog"; $Debug = 1; } ######################################################################################### # # Client code - started by fork-exec in Server code below # if ($opt_client) { sleep 1; # Give the server a second to get setup sub PipeProblem { # For alarm/timeout signal my $signame = shift; print "$ProgName could not write to pipe, received signal $signame\n"; print DEBUGLOG "\n--------- Exiting from PipeProblem with alert ---------\n\n" if $Debug; exit 1; } $SIG{PIPE} = \&PipeProblem; $RandomDelayTime = int(rand($RandSkew)); print DEBUGLOG "Child($$): $Proxy $URL - Delaying $RandomDelayTime s (max $RandSkew)\n" if $Debug; # exit if ($URL =~ /junk/); # For testing what happens if a client never responds (URL contains 'junk') sleep($RandomDelayTime); # Randomly delay ourselves to avoid a rush my $ua = new LWP::UserAgent; $ua->timeout($ClientTimeout); # Set timeout for LWP $TheContent = ''; if ($Proxy ne 'noproxy') { $ua->proxy('http', "http://$Proxy"); # Need to generalize this for other protocols } $s{measurementtime} = time; # Not currently used, but may become log option $dt = 0; $t0 = [gettimeofday]; # Get start time if ($NoCache) { # Request fresh content to get past caches $response = $ua->get($URL, Pragma => 'no-cache', 'Cache-Control' => 'max-stale=0'); } else { $response = $ua->request(GET $URL); } $t1 = [gettimeofday]; # Get end time $dt = tv_interval($t0, $t1); # Compute elapsed time $ResultCode = $response->code(); $WarningHeader = $response->header('Warning'); # Some caches might return this, see check below $TheContent = $response->content(); $ByteCount = length($TheContent); if ($NoCache && ($WarningHeader =~ /(\d{3})/)) { # Be sure that fresh data were delivered $WarningCode = $1; # If not, alter the Result Code to force an alarm $ResultCode = 503 if (($WarningCode >= 110) && ($WarningCode < 199)); } $StringCheckFail = 0; if ($OKstring) { # Check the content to verify that the required string is present $StringCheckFail = 1 if ($TheContent !~ /$OKstring/); } print DEBUGLOG "URL: $URL $ResultCode $ByteCount $dt\n" if $Debug; print "Warning Header: $WarningHeader\n" if $Debug; print $TheContent if $opt_v; # # Submit the results to the server process over a named pipe # if (-p $NamedPipe) { # Be sure that the pipe is there, otherwise our server may have exited open (PIPE, ">$NamedPipe") || die "Can't open pipe: $NamedPipe\n"; print PIPE "$URL $Proxy $ResultCode $StringCheckFail $ByteCount $dt\n"; print DEBUGLOG "\nChild($$) --------- Exiting normally ---------\n" if $Debug; exit 0; # The client invocation ends here } else { print DEBUGLOG "Child($$) exiting because pipe $NamedPipe does not exist\n" if $Debug; exit 0; } } ############# End Client Section ################################################### #################################################################################### # ############# Server Section #################################### # # # Determine path to monitor, for starting children # $ProgName = $0; # Will need full path print DEBUGLOG "\n\nStarting at $TimeOfDay Name: $ENV{PWD} / $ProgName\n" if $Debug; if (!(-x $ProgName)) { # We can't find ourself, won't be able to exec! print DEBUGLOG @ARGV if $Debug; print DEBUGLOG "\n" if $Debug; print "$ProgName cannot be found, or is not executable by mon\n"; exit 1; # Indicate failure to mon } if ($SmartAlarm) { # Use Smart Alarm module use File::Basename; $basename = basename($SmartAlarm); # Get the path to the module $dirname = dirname($SmartAlarm); if ((length($dirname) == 0) || ($dirname eq '.')) { $SmartAlarmDir = dirname($ProgName) unless $SmartAlarmDir; } else { $SmartAlarmDir = $dirname; } $basename =~ s/\.pm$//; print DEBUGLOG "SmartAlarmDir: $SmartAlarmDir Module: $basename\n" if $Debug; # use lib "/usr/local/mon/mon.d"; # Use ENV variable or option later push (@INC, $SmartAlarmDir); eval "use $basename"; do { print "Couldn't load $SmartAlarmDir/$basename.pm: $@\n"; exit 1; } unless ($@ eq ''); httpSmartAlarm->import(); } # # Reap children to avoid defunct processes / zombies # See "Network Programming with Perl" by Lincoln Stein # sub Reaper { my $signame = shift; my $timenow = time; while ((my $child_pid = waitpid(-1, WNOHANG)) > 0) { print DEBUGLOG "Parent $$ Reaped child: $child_pid after $signame at $timenow\n" if $Debug; } } $SIG{CHLD} = \&Reaper; # Handle interrupt key and termination signals sub OtherSIGs { my $signame = shift; unlink $NamedPipe; print "$ProgName Terminated on Signal: $signame\n"; print DEBUGLOG "\n--------- Exiting OtherSIGs with alert following $signame ---------\n\n" if $Debug; exit 1; } $SIG{HUP} = $SIG{INT} = $SIG{QUIT} = $SIG{TERM} = \&OtherSIGs; # # Make the named pipe for children to report results # $NamedPipe .= ".$$"; # Tack on the PID for uniqueness print DEBUGLOG "Making $NamedPipe\n" if $Debug; $cmd = qq{$MKFIFO $NamedPipe}; $ret_val = system($cmd); #$SIG{CHLD} = $SIG{PIPE} = $SIG{INT} = 'IGNORE'; # don't want to die on 'Broken pipe' or Ctrl-C if ($opt_c) { # Parse list of acceptable http response codes (@t) = split(/,/, $opt_c); foreach $code (@t) { $AcceptableResponseCode{$code}++; } } else { $AcceptableResponseCode{200}++; # Default is 200 } foreach $target (@ARGV) { # Build host and path lists print DEBUGLOG "\nTarget: $target\n" if $Debug; # # Normalize the request # we may want to have more restrictive URL formats in the future # and eliminate this # $protocol = 'http'; # Default protocol $host_path = ''; if ($target =~ /^(\w+):\/\/(.*)/) { $protocol = $1; $host_path = $2; } else { $host_path = $target; } print DEBUGLOG "Protocol: $protocol host/path: $host_path\n" if $Debug; undef $proxy_server; if ($host_path =~ /@/) { ($host_path, $proxy_server) = split(/@/, $host_path, 2); } elsif (defined $Proxy) { # Allow one proxy to be set for all tests, but override with @ in host/path $proxy_server = $Proxy; } ($host, $Path) = split(/\//, $host_path, 2); if (defined $proxy_server) { $ProxyServer = $proxy_server; } else { $ProxyServer = 'noproxy'; } print DEBUGLOG "$host - $ProxyServer - $Path\n" if $Debug; $URL = "$protocol://$host/$Path"; push(@URLs, $URL); push(@Proxies, $ProxyServer); } $RandSkew = 0 if (@URLs <= 1); # No need to delay if there is a single URL # # Open the named pipe, must be in read/write mode, otherwise open will block # open (PIPE, "+< $NamedPipe") || die "Server Process: Can't open pipe: $NamedPipe\n"; # # Use evals for time-out capability # eval { $SIG{ALRM} = sub {die "Server alarm timeout"}; alarm($ServerTimeout); eval { # # Check each target URL by firing off a measurement child process # for ($i = 0; $i <= $#URLs; $i++) { $URL = $URLs[$i]; $Proxy = $Proxies[$i]; $URL_Proxy = $URL . '@' . $Proxy; # Unique test key $URL_Proxies{$URL_Proxy}++; # Checklist, used to track replies &ForkClient($URL, $Proxy); # Fire off a client to run the test } while (1) { $in = ; print DEBUGLOG "Data from pipe: $in" if $Debug; ($s{url}, $s{proxy}, $s{result_code}, $s{string_check_fail}, $s{byte_count}, $s{dt}) = split(' ', $in); $url = $s{url}; $proxy = $s{proxy}; $URL_Proxy = $url . '@' . $proxy; delete $URL_Proxies{$URL_Proxy}; # Saw this combination, check it off the list $NumTestsLeft = scalar keys(%URL_Proxies); print DEBUGLOG " $NumTestsLeft tests to go\n" if $Debug; # # Save measurement results in hashes # $httpCode{$URL_Proxy} = $s{result_code}; $httpStringFail{$URL_Proxy} = $s{string_check_fail}; $httpTime{$URL_Proxy} = $s{dt}; $httpSize{$URL_Proxy} = $s{byte_count}; last if ($NumTestsLeft == 0); # Bail out and process if we got all the replies } close PIPE; alarm(0); }; alarm(0); # Race condition prevention }; unlink $NamedPipe; # For housekeeping, and to let any straggling clients know # that the server process has exited # # Process the results, exit occurs from ProcessResults # &ProcessResults(\%httpCode, \%httpStringFail, \%httpTime, \%httpSize); ############# End of Server Code ############################################ # # Subroutines below # sub ForkClient { my ($url, $proxy) = @_; FORK: if ($pid = fork) { # parent here # child process pid is available in $pid # waitpid($pid,0); # Can't do this and retain parallelism # $returnstatus = ($? >> 8); } elsif (defined $pid) { #pid is zero here if defined # child here # Form our exec() string $execstring = "$ProgName --client --url $url --proxy $proxy --pipe $NamedPipe --randskew $RandSkew"; $execstring .= ' --nocache' if $NoCache; # Add additional flags $execstring .= ' -d' if $Debug; $execstring .= " --debuglog $DebugLog" if $DebugLog; $execstring .= " --okstring '$OKstring'" if $OKstring; $execstring .= ' -v' if $opt_v; print DEBUGLOG "execstring: $execstring\n" if $Debug; exec($execstring); # parent process pid is available with getppid } elsif ($! =~ /No more process/) { # EAGAIN, supposedly recoverable fork error sleep 2; redo FORK; } else { # weirdo fork error # return 1; } } # # Check for alarm conditions, etc. # sub ProcessResults { my ($Codes, $StringFail, $Times, $Sizes) = @_; my @Failures = (); my %FailureDetail = (); my %ResultString = (); # # Check for non-responders, LWP will usually give an error # so we may not exercise this often # foreach $r (keys %URL_Proxies) { # Unfullfilled test results print DEBUGLOG "$r $URL_Proxies{$r}\n" if $Debug; push(@Failures, $r); $ThisOneFailed = 1; $FailureDetail{$r} = 'No response'; ($protocol, $host, $path, $proxy) = &split_url($r); $Times->{$r} = -1.0; $Sizes->{$r} = 0; $Codes->{$r} = 0; if ($StripProtocol) { # Don't include http:// etc in log file for backwards compatibility $ResultString{$r} = sprintf("%d %s %s %s %d %0.4f %d", $TimeOfDay, $proxy, $host, $path, $Sizes->{$r}, $Times->{$r}, $Codes->{$r}); } else { $ResultString{$r} = sprintf("%d %s %s://%s %s %d %0.4f %d", $TimeOfDay, $proxy, $protocol, $host, $path, $Sizes->{$r}, $Times->{$r}, $Codes->{$r}); } $SmartAlarmString{$r} = sprintf("%d %d %s %s %s %s %d %d %0.3f %s", $ThisOneFailed, $TimeOfDay, $proxy, $protocol, $host, $path, $Sizes->{$r}, $Times->{$r}, $Codes->{$r}); } # # Check response codes, times, etc # print DEBUGLOG "\nProcessResults\n" if $Debug; foreach $r (keys %$Codes) { next if (exists $URL_Proxies{$r}); # We already got it above $ThisOneFailed = 0; printf DEBUGLOG ("%8.3f %5d %6d %s\n", $Times->{$r}, $Codes->{$r}, $Sizes->{$r}, $r) if $Debug; # # Check http response code against list # if (!exists $AcceptableResponseCode{$Codes->{$r}}) { $ThisOneFailed++; $Times->{$r} = -1.0 * $Times->{$r}; # Log uses negative time as failure indicator $FailureDetail{$r} = "Bad response code ($Codes->{$r}) "; } # # Check response time against limit, if set, but don't negate response time # if ($ResponseAlarmTime) { if ($Times->{$r} > $ResponseAlarmTime) { $ThisOneFailed++; $FailureDetail{$r} .= 'Long response time'; } } if ($StringFail->{$r}) { $ThisOneFailed++; $FailureDetail{$r} .= qq{String '$OKstring' is missing}; } if ($ThisOneFailed) { push(@Failures, $r); } # Pick apart the URL so that we can generate a log entry # compatible with previous versions # ($protocol, $host, $path, $proxy) = &split_url($r); if ($StripProtocol) { # Don't include http:// etc in log file for backwards compatibility $ResultString{$r} = sprintf("%d %s %s %s %d %0.4f %d", $TimeOfDay, $proxy, $host, $path, $Sizes->{$r}, $Times->{$r}, $Codes->{$r}); } else { $ResultString{$r} = sprintf("%d %s %s://%s %s %d %0.4f %d", $TimeOfDay, $proxy, $protocol, $host, $path, $Sizes->{$r}, $Times->{$r}, $Codes->{$r}); } $SmartAlarmString{$r} = sprintf("%d %d %s %s %s %s %d %d %0.3f %s", $ThisOneFailed, $TimeOfDay, $proxy, $protocol, $host, $path, $Sizes->{$r}, $Times->{$r}, $Codes->{$r}); } if ($Debug) { foreach $r (sort keys %ResultString) { print DEBUGLOG "ResultString: $ResultString{$r}\n"; } } # # Write results to logfile, if -l # if ($opt_l) { $LogFile = $opt_l; ($sec, $min, $hour, $mday, $Month, $Year, $wday, $yday, $isdst) = localtime($TimeOfDay); $Month++; $Year += 1900; $YYYYMM = sprintf('%04d%02d', $Year, $Month); $LogFile =~ s/YYYYMM/$YYYYMM/; # Fill in current year and month if (-e $LogFile) { # Check for existing log file $NewLogFile = 0; } else { $NewLogFile = 1; } open(LOG, ">>$LogFile") || warn "$0 Can't open logfile: $LogFile\n"; foreach $r (sort keys %ResultString) { print LOG "$ResultString{$r}\n"; } close LOG; } if ((@Failures == 0) && $ForceSmartAlarm) { # Run SmartAlarm to look for other problems, i.e. bad route ($count, @Failures) = &CheckAlarm($SmartAlarmConfig, %SmartAlarmString); if (@Failures == 0) { sleep 2; # Allow SIGCHLDs to arrive $SIG{CHLD} = 'IGNORE'; # We are finished, don't wait for straggling SIGCHLDs (hopefully will not leave zombies) exit 0; } $SummaryString = join ' ', @Failures; # Double check failure list $SummaryString =~ s/^\s+//; # Trim whitespace $SummaryString =~ s/\s+$//; # exit 0 if (length($SummaryString) <= 0); # Require data in failure list print "$SummaryString\n"; # Note that we are not supplying any detail data from SmartAlarm print DEBUGLOG "\n--------- Exiting ForceSmartAlarm alarm mode with alert ---------\n\n" if $Debug; exit 1; # Indicate failure to mon } if (@Failures == 0) { # No failures, exit with status 0 print DEBUGLOG "\n--------- No Failures ---------\n" if $Debug; print DEBUGLOG "\n--------- Exiting normally ---------\n\n" if $Debug; sleep 2; # Allow SIGCHLDs to arrive $SIG{CHLD} = 'IGNORE'; # We are finished, don't wait for straggling SIGCHLDs (hopefully will not leave zombies) exit 0; } if ($SmartAlarm) { # Smart alarm enabled, check the down list to see if we really # want to trigger an alarm ($SmartAlarmDownCount, @SmartAlarmFailures) = &CheckAlarm($SmartAlarmConfig, %SmartAlarmString); print DEBUGLOG "*** SmartAlarm Result: $SmartAlarmDownCount\n" if $Debug; if ($SmartAlarmDownCount) { # Have alarm, exit with status 1 print DEBUGLOG "\n--------- Have Smart Alarm Failures - mon Data Below ---------\n" if $Debug; @SortedFailures = sort @SmartAlarmFailures; # Sort to help mon in summary mode $SummaryString = join ' ', @SortedFailures; # Double check failure list $SummaryString =~ s/^\s+//; # Trim whitespace $SummaryString =~ s/\s+$//; # exit 0 if (length($SummaryString) <= 0); # Require data in failure list print "$SummaryString\n"; # There were failures, list them foreach $r (sort @Failures) { # Then provide details print "$r $Sizes->{$r} bytes $Times->{$r} s $FailureDetail{$r}\n"; } print DEBUGLOG "\n--------- Exiting SmartAlarm mode with alert ---------\n\n" if $Debug; exit 1; # Indicate failure to mon } print DEBUGLOG "\n--------- No Failures Classified by SmartAlarm ---------\n" if $Debug; print DEBUGLOG "\n--------- Exiting SmartAlarm mode ---------\n\n" if $Debug; sleep 2; # Allow SIGCHLDs to arrive $SIG{CHLD} = 'IGNORE'; # We are finished, don't wait for straggling SIGCHLDs (hopefully will not leave zombies) exit 0; } # Regular alarm mode print DEBUGLOG "\n--------- Have Failures - mon Data Below ---------\n" if $Debug; @SortedFailures = sort @Failures; # Sort to help mon in summary mode $SummaryString = join ' ', @SortedFailures; # Double check failure list $SummaryString =~ s/^\s+//; # Trim whitespace $SummaryString =~ s/\s+$//; # exit 0 if (length($SummaryString) <= 0); # Require data in failure list print "$SummaryString\n"; # There were failures, list them foreach $r (@SortedFailures) { # Then provide details print "$r $Sizes->{$r} bytes $Times->{$r} s $FailureDetail{$r}\n"; } print DEBUGLOG "\n--------- Exiting regular alarm mode with alert ---------\n\n" if $Debug; exit 1; # Indicate failure to mon } # # Pick apart the URL so that we can generate a log entry # compatible with previous versions # sub split_url { my $r = shift; my ($protocol, $host, $path, $proxy); $r =~ /^(\w+):\/\/([^\/]+)\/?(.*?)@(.*)/; $protocol = $1; $host = $2; # Ends when '/' seen $path = $3; $proxy = $4; if (length($path) < 1) { # Set the path for logging purposes $path = '/'; # we don't want an empty, space separated, field } return $protocol, $host, $path, $proxy; } etbemon-1.3.6/mon.d/imap.monitor0000755000000000000000000001103610301645774013425 0ustar #!/usr/bin/perl # # Use try to connect to an IMAP server, and # wait for the right output. # # For use with "mon". # # Arguments are "-p port -t timeout host [host...]" # # Adapted from "http.monitor" by # Jim Trocki, trockij@transmeta.com # # http.monitor written by # # Jon Meek # American Cyanamid Company # Princeton, NJ # # $Id: imap.monitor,v 1.3 2005/08/20 15:27:56 vitroth Exp $ # # Copyright (C) 1998, Jim Trocki # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # use Getopt::Std; use English; getopts ("m:p:t:"); $PORT = $opt_p || 143; $TIMEOUT = $opt_t || 30; $MAILBOX=$opt_m || undef; @failures = (); foreach $host (@ARGV) { if (! &imapGET($host, $PORT)) { push (@failures, $host); } } if (@failures == 0) { exit 0; } print join (" ", sort @failures), "\n\n", join ("\n", @longerr), "\n"; exit 1; sub imapGET { use Socket; use Sys::Hostname; my($Server, $Port) = @_; my($ServerOK, $TheContent, $cmd); $ServerOK = 0; $TheContent = ''; $Path = '/'; ############################################################### eval { local $SIG{ALRM} = sub { die "Timeout Alarm" }; alarm $TIMEOUT; $result = &OpenSocket($Server, $Port); # Open a connection to the server if ($result == 0) { # Failure to open the socket push @longerr, "$Server: Unable to connect"; return ''; } $in = ; if ($in !~ /^\* (OK|PREAUTH|BYE)/) { alarm 0; push @longerr, "$Server: No IMAP banner received"; return 0; } $cmd="login"; print S "A1 LOGIN ANONYMOUS ANONYMOUS\r\n"; while (defined($in=)) { if ($in =~ /^A1 (\w+) (.*)/) { if ($1 eq "OK") { $ServerOK = 1; } else { $errmsg="$1 $2"; } last; } } if ($ServerOK && $MAILBOX) { $cmd="examine"; $ServerOK=0; print S "A2 EXAMINE $MAILBOX\r\n"; while (defined($in=)) { if ($in =~ /^A2 (\w+) (.*)/) { if ($1 eq "OK") { $ServerOK = 1; } else { $errmsg="$1 $2"; } last; } } } if ($ServerOK) { $cmd="logout"; $ServerOK=0; print S "A3 LOGOUT\r\n"; while (defined($in=)) { if ($in =~ /^A3 (\w+) (.*)/) { if ($1 eq "OK") { $ServerOK = 1; } else { $errmsg="$1 $2"; } last; } } } if (!$ServerOK) { if ($errmsg) { push @longerr, "$Server: bad response to $cmd: $errmsg"; } else { push @longerr, "$Server: No response to $cmd"; } } close(S); alarm 0; # Cancel the alarm }; if ($EVAL_ERROR and ($EVAL_ERROR =~ /^Timeout Alarm/)) { push @longerr, "$Server: **** Time Out\n"; return 0; } elsif ($EVAL_ERROR) { push @longerr, "$Server: $EVAL_ERROR"; return 0; } return $ServerOK; } sub OpenSocket { # # Make a Berkeley socket connection between this program and a TCP port # on another (or this) host. Port can be a number or a named service # local($OtherHostname, $Port) = @_; local($OurHostname, $sockaddr, $name, $aliases, $proto, $type, $len, $ThisAddr, $that); $OurHostname = &hostname; ($name, $aliases, $proto) = getprotobyname('tcp'); ($name, $aliases, $Port) = getservbyname($Port, 'tcp') unless $Port =~ /^\d+$/; ($name, $aliases, $type, $len, $ThisAddr) = gethostbyname($OurHostname); ($name, $aliases, $type, $len, $OtherHostAddr) = gethostbyname($OtherHostname); my $that = sockaddr_in ($Port, $OtherHostAddr); $result = socket(S, &PF_INET, &SOCK_STREAM, $proto) || return undef; $result = connect(S, $that) || return undef; select(S); $| = 1; select(STDOUT); # set S to be un-buffered return 1; # success } etbemon-1.3.6/mon.d/imapnew.monitor0000755000000000000000000001174514037553151014143 0ustar #!/usr/bin/perl use strict; # needs package libmail-imapclient-perl on Debian # Mon script to talk to IMAP server, look for new messages, and DELETE old # messages. Use this with something like smtpswaks.monitor to send mail. # Copyright Russell Coker GPLv3 # Options: -h target_host -u username -p password -P password_file # -f folder (default "INBOX") -s for ssl (default no ssl) -t checktime # -k max clock skew (seconds that a message appears to have gone back in time) # default 1 # -d max delay in seconds (default half checktime) # the -P option specifies a file containing the password so ps won't reveal # it. # The -t option specifies how recently mail must have been received, if you # specify -t 300 (the default) then if there was no new mail in the last 5 # minutes then it's a failure use Getopt::Std; our $opt_d; our $opt_f; our $opt_h; our $opt_k; our $opt_p; our $opt_P; our $opt_u; our $opt_s; our $opt_t; getopts("d:f:h:k:p:P:st:u:"); if(!$opt_h || !$opt_u || (!$opt_p && !$opt_P)) { printf("Must specify host, user, and password.\n"); exit(1); } my $timeout = $opt_t ? $opt_t : 300; my $max_delay = $opt_d ? $opt_d : $timeout / 2; my $max_skew = $opt_k ? $opt_k : 1; if($opt_P) { open(PASSWORD, "<$opt_P") or die "Can't open password file $opt_P"; $opt_p = ; close(PASSWORD); chomp $opt_p; } use Mail::IMAPClient; use Date::Parse; my $imap = Mail::IMAPClient->new( Server => $opt_h, User => $opt_u, Password => $opt_p, Ssl => $opt_s ? 1 : 0, Uid => 1, ); my $IMAP_folder = $opt_f ? $opt_f : "INBOX"; if(!$imap) { printf("Can't talk to IMAP server $opt_h with $@.\n"); printf("Can't check mail in account $opt_u\n"); exit(1); } my $err_str; # Leaving this here in case someone wants to extend it to check multiple folders #my $folders = $imap->folders; #if(!$folders) #{ # $err_str = $imap->LastError; # printf("Can't get folder list for $IMAP_User with $err_str.\n"); # exit(1); #} #print "folders: @$folders\n"; if(!$imap->select($IMAP_folder) || $imap->LastError) { $err_str = $imap->LastError; printf("Can't select folder \"$IMAP_folder\" for $opt_u with $err_str.\n"); exit(1); } my $check_time = time() - $timeout; my $delete_time = $check_time - $timeout; my $status; my @msgs; @msgs = $imap->messages(); if($imap->LastError) { $err_str = $imap->LastError; printf("Can't get message list with $err_str.\n"); exit(1); } if($#msgs == -1) { printf("No messages in account\n"); exit(1); } my $delcount = 0; my $newcount = 0; foreach my $msg (@msgs) { my $delivery_date = $imap->internaldate($msg); my $delivery_secs = str2time($delivery_date); # printf("msg:$msg, date:$delivery_date, delivery_secs:$delivery_secs\n"); if($delivery_secs < $delete_time) { if(!$imap->delete_message($msg)) { $err_str = $imap->LastError; printf("Can't delete old message with $err_str.\n"); exit(1); } $delcount++; } if($delivery_secs > $check_time) { $newcount++; } my @received = $imap->parse_headers( $msg, "Received" );; my @rec_date; my @rec_host; push(@rec_date, $delivery_secs); push(@rec_host, "Delivery"); foreach (@received) { my $rdate = $_; my $host = $_; $rdate =~ s/^.*; //; $host =~ s/^.*by //; $host =~ s/ \(.*$//; push(@rec_date, str2time($rdate)); push(@rec_host, $host); } my $header_date = $imap->get_header($msg, "Date" ); push(@rec_date, str2time($header_date)); push(@rec_host, "Sender"); my $subject = $imap->get_header($msg, "Subject"); my $msgid = $imap->get_header($msg, "Message-ID"); if(not $msgid) { print "message without Message-Id header (subject $subject)\n"; exit(1); } for(my $i = 0; $rec_date[$i+1]; $i++) { my $skew = $rec_date[$i+1] - $rec_date[$i]; my $delay = -$skew; if($skew > $max_skew) { print "Clock skewed\n"; print "$rec_host[$i] received message $skew seconds before $rec_host[$i+1] sent it\nSubject: $subject\nMessage-ID: $msgid\n"; if($delcount) { $imap->expunge(); $err_str = $imap->LastError; if($imap->LastError) { printf("Can't expunge old message with $err_str.\n"); } } exit(1); } elsif($delay > $max_delay) { print "Message delayed $delay seconds\n"; print "$rec_host[$i] received message $delay seconds after $rec_host[$i+1] sent it\nSubject: $subject\nMessage-ID: $msgid\n"; if($delcount) { $imap->expunge(); $err_str = $imap->LastError; if($imap->LastError) { printf("Can't expunge old message with $err_str.\n"); } } exit(1); } } } if($delcount) { $imap->expunge(); $err_str = $imap->LastError; if($imap->LastError) { printf("Can't expunge old message with $err_str.\n"); exit(1); } } $imap->disconnect; if($newcount) { printf("Del $delcount msgs, found $newcount msgs\n"); exit(0); } printf("Deleted $delcount messages and no new messages\n"); exit(1); etbemon-1.3.6/mon.d/ldap.monitor0000755000000000000000000001126510061516614013414 0ustar #!/usr/bin/perl # # This script will search an LDAP server for objects that match the -filter # option, starting at the DN given by the -basedn option. Each DN found must # contain the attribute given by the -attribute option and the attribute's # value must match the value given by the -value option. Servers are given on # the command line. At least one server must be specified. # This script use the Net::LDAP, which uses some LDAP libraries like those # from UMich, Netscape, or ISODE. # # Porting to LDAP (from LDAPapi) by Thomas Quinot , # 1999-09-20. # Copyright (C) 1998, David Eckelkamp # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # $Id: ldap.monitor,v 1.1.1.1 2004/06/09 05:18:04 trockij Exp $ # use Net::LDAP; use Getopt::Long; # Here are the default values for the things you can specify via options $LDAPPort = 389; $BaseDN = "o=Your Org, c=US"; $Filter = "cn=Directory Admin"; $Attribute = "objectClass"; $Value = "YourValue"; $verbose = 0; @errs = (); %OptVars = ("port" => \$LDAPPort, "basedn" => \$BaseDN, "filter" => \$Filter, "attribute" => \$Attribute, "value" => \$Value, "verbose" => \$verbose); if (!GetOptions(\%OptVars, "port=i", "basedn=s", "filter=s", "attribute=s", "value=s", "verbose")) { print "Problems with Options, sorry.\n"; exit 1; } # There has to be at least one argument left, the ldap server to query. if ($#ARGV < 0) { print "$0: Insufficient arguments. There must be at least 1 server to query\n"; exit 1; } # Loop through all the server given on the command line. $ErrCnt = 0; foreach $LDAPHost (@ARGV) { # Open the connection to the server and do a simple, anonymous bind unless ($ldap = Net::LDAP->new($LDAPHost, port => $LDAPPort)) { push(@FailedHosts, "$LDAPHost:$LDAPPort"); push(@errs, "ldap_init Failed: host=$LDAPHost:$LDAPPort: $!"); $ErrCnt++; next; } unless ($ldap->bind) { $ErrCnt++; push(@FailedHosts, "$LDAPHost:$LDAPPort"); #ldap_perror($ldap, "ldap bind failed: host=$LDAPHost:$LDAPPort\n"); push(@errs, "ldap bind failed: host=$LDAPHost:$LDAPPort"); next; } unless ($mesg = $ldap->search(base => $BaseDN, filter => $Filter)) { my($errnd, $extramsg, $err); push(@errs, "$LDAPHost " . $mesg->error); $ldap->unbind; push(@FailedHosts, "$LDAPHost:$LDAPPort"); $ErrCnt++; next; } $nentries = 0; foreach $entry ($mesg->entries) { my $dn = $entry->dn; $nentries++; foreach $attr ($entry->attributes) { $record{$dn}->{$attr} = [$entry->get ($attr)]; } } $ldap->unbind; if ($nentries == 0) { push(@errs, "$LDAPHost returned no entries"); push(@FailedHosts, "$LDAPHost:$LDAPPort"); $ErrCnt++; next; } # Analyze results. # Step 1 is to loop through all DNs returned from the search. print "Looking for $Attribute=$Value\n" if $verbose; foreach $dn (sort keys %record) { print "checking object $dn\n" if $verbose; # Loop through the attributes for this DN $attrFound = 0; $goodVal = 0; foreach $attr (keys %{$record{$dn}}) { print " checking attr=$attr\n" if $verbose; next unless ($attr eq $Attribute); $attrFound++; print " found correct attribute\n" if $verbose; # Each value could be/is an array so search the array foreach $val (@{$record{$dn}{$attr}}) { print " checking val = $val\n" if $verbose; next unless ($val eq $Value); $goodVal++; print " found correct value\n" if $verbose; last; } last if ($goodVal); } if (!$attrFound || !$goodVal) { print "For object $dn:\n"; } if (!$attrFound) { $ErrCnt++; push(@errs,"Could not find Attribute \"$Attribute\" for DN=$dn"); push(@FailedHosts, "$LDAPHost:$LDAPPort"); } elsif (!$goodVal) { $ErrCnt++; push(@errs, "Value \"$Value\" not found for Attribute \"$Attribute\""); push(@FailedHosts, "$LDAPHost:$LDAPPort"); } } } if ($ErrCnt > 0) { print join (" ", sort @FailedHosts), "\n"; print join("\n", @errs), "\n"; } exit $ErrCnt; etbemon-1.3.6/mon.d/local-syslog.monitor0000755000000000000000000001615210630542607015107 0ustar #!/usr/bin/perl # # A syslog monitor for mon, with support for Cisco router messages # # $Id: local-syslog.monitor,v 1.1.2.1 2007/06/03 13:43:35 trockij Exp $ # # Copyright (C) 2001-2006, Jon Meek, meekj at ieee.org # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # =head1 NAME B - syslog monitor for mon =head1 DESCRIPTION Watch local syslog log files and alert when a regular expression is matched. Include router interface descriptions for logs generate by a Cisco router. =head1 SYNOPSIS When the regular expression is matched, an alert is triggered. The alert details contain the actual log entries that matched. An optional additional description can be added to the details for an IP address / Interface Name pair if the log entry comes from a Cisco router. A common usage involves having other systems send their syslog information to this mon server so they can be watched by this monitor. =head1 OPTIONS =over 5 =item B<-c> Configuration file =item B<-d> Debug/Test. Useful for manual command line use. =back =head1 CONFIGURATION FILE =item B Regular expression that will trigger an alarm when there is a match. =item B The top of the directory tree where the syslog files are kept. =item B Syslog files are usually specified on the command line, but can be listed in the config file as well. =item B IP Address / Interface Name pairs can be expanded in the details section of an alert. These lines consist of an IP address followed by whitespace, then the interface name followed by whitespace, then a description of the interface. This is added to the alert if the log entry is found to match the output generated from a Cisco router. Example: Strings %BGP-5|%LINEPROTO-5-UPDOWN|%LINK-3-UPDOWN BaseDir /d2/logs/remotesyslog #File exnetmon-gv/cisco.log #File ot-gv/cisco.log 192.168.56.1 FastEthernet0/0 To Extranet Switch 192.168.56.1 Serial0/0 Frame-Relay DHEC266467 DLCI 612 192.168.56.1 FastEthernet0/1 Inside Interface 192.168.56.1 Serial0/1 T-1 to ICO DHEC397828 =head1 MON CONFIGURATION EXAMPLE hostgroup remote-syslog exnetmon-wl/cisco.log ot-wl/cisco.log watch remote-syslog service syslog interval 15m monitor local-syslog.monitor -c /usr/local/mon/syslog.cfg period wd {Sun-Sat} alert mail.alert meekj-at-ieee.org =head1 AUTHOR Jon Meek, meekj at ieee.org =cut use Getopt::Std; #use File::Basename; #use Time::HiRes qw( gettimeofday tv_interval ); $BaseDir = ''; @Failures = (); # Initialize failure list $TimeOfDay = time; # Current time getopts ("dc:"); if (defined $ENV{MON_STATEDIR}) { # Are we running under mon? $STATE_DIR = $ENV{MON_STATEDIR}; $RunningUnderMon = 1; } else { $RunningUnderMon = 0; } if ($opt_c) { # Read configuration file $ConfigFile = $opt_c; if (open(C, $ConfigFile)) { while ($in = ) { last if ($in =~ /^Exit/i); next if ($in =~ /^\#/); # Comments chomp $in; if ($in =~ /^BaseDir/i) { ($tag, $BaseDir) = split(' ', $in, 2); next; } if ($in =~ /^File/i) { ($tag, $file) = split(' ', $in, 2); push(@Files, $file); next; } if ($in =~ /^Strings/i) { ($tag, $data) = split(' ', $in, 2); $RegEx .= $data; next; } if ($in =~ /^[0-9\.]+/) { ($router_ip, $interface_name, $description) = split(' ', $in, 3); # print "$router_ip - $interface_name - $description\n" if $opt_d; $RouterInterfaceDescription{"$router_ip $interface_name"} = $description; next; } if ($in =~ /^RouterList/i) { ($tag, $RouterListFile) = split(' ', $in, 2); next; } if ($in =~ /^StateDir/i) { # If the mon environment variable needs to be overriden ($tag, $STATE_DIR) = split(' ', $in, 2); next; } } } else { print "local-syslog.monitor: Couldn't open $ConfigFile configuration file\n"; exit 1; } } push (@Files, @ARGV); # Get file names from the command line foreach $File (@Files) { $FullPath = "$BaseDir/$File"; if (!-e $FullPath) { # File does not exist print "**** $FullPath does not exist\n" if $opt_d; next; } $StateFile = $FullPath; $StateFile =~ s/\//-/g; # Change / to - to make filename $StateFile =~ s/^-//; $StateFile = "$STATE_DIR/$StateFile"; # # Read the previous file sizes if the State File exists # if (-e $StateFile) { print "Existing $StateFile\n" if $opt_d; open(F, $StateFile); $in = ; ($t, $last_size) = split(' ', $in); close F; $StateFileExists = 1; # Remember that there is a existing State File } else { $StateFileExists = 0; # or not $last_size = 0; print "No Existing $StateFile\n" if $opt_d; } # # Get file information # ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $mtime, $ctime, $blksize, $blocks) = stat($FullPath); # $basename = basename($SmartAlarm); # Get the path to the module # $dirname = dirname($SmartAlarm); print "$StateFile Last size: $last_size Size - : $size\n" if $opt_d; next if ($size == $last_size); # File has not changed since last check (may want to check time too) $FailureDetail{$File} = ''; open(F, $FullPath); if ($size > $last_size) { # Position to read new lines only seek(F, $last_size, 0); } while ($in = ) { chomp $in; if ($in =~ /$RegEx/o) { # Check the master regular expression # # see if we have a description on the router/interface (from cisco) # if ($in =~ /^(\w{3}\s+\d{1,2}\s+\d{2}:\d{2}:\d{2})\s+(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/) { $router_ip = $2; $in =~ /\s+Interface\s+([\w\/\.]+)/; $interface_name = $1; # print "*** $router_ip $interface_name\n"; if (exists $RouterInterfaceDescription{"$router_ip $interface_name"}) { $in .= ' [' . $RouterInterfaceDescription{"$router_ip $interface_name"} . ']'; } } $HaveFailureData{$File}++; $FailureDetail{$File} .= "$in\n"; print "$in\n" if $opt_d; } } $CurrentPosition = tell(F); print "Final Position: $CurrentPosition\n" if $opt_d; close F; # Write new state file print "Writing a new $StateFile\n" if $opt_d; open(F, ">$StateFile"); print F "$TimeOfDay $CurrentPosition\n"; close F; } foreach $k (sort keys %HaveFailureData) { push(@Failures, $k); } if (@Failures == 0) { # Indicate "all OK" to mon exit 0; } # # Otherwise we have one or more failures # print "@Failures\n"; foreach $k (@Failures) { print "$k $FailureDetail{$k}\n"; } print "\n"; exit 1; # Indicate failure to mon etbemon-1.3.6/mon.d/lpd.monitor0000755000000000000000000001635510061516615013261 0ustar #!/usr/bin/perl # # Try to connect to an lpd server and get status of print queues. # For use with "mon". # # lpd.monitor [-l] [-d] [-s secs] [-p port] [-t secs] -h host queue [queue...] # # -l interpret queue output as lprng (error, status, etc.) # -d do not show detail # -e report queues with "error" jobs # -s secs report jobs stalled longer than "secs" as an error # -h host host running lpd # -p port TCP port to connect to (defaults to 515) # -t secs timeout, defaults to 30 # # "get" routine based on other monitors written by Jon Meek # # $Id: lpd.monitor,v 1.1.1.1 2004/06/09 05:18:05 trockij Exp $ # # Copyright (C) 2001, 2002, Jim Trocki # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # use Getopt::Std; use English; sub lpdGET; sub check_lprng; sub OpenSocket; getopts ("deh:s:lp:t:P:"); $PORT = $opt_p || 515; $TIMEOUT = $opt_t || 30; $STALLED = $opt_s || 60; # stalled 1 mins $HOST = $opt_h || die "no host supplied with -h\n"; my %good; my %bad; my %details; exit 0 if (!@ARGV); foreach my $queue (@ARGV) { my $result = lpdGET ($HOST, $PORT, $queue); if (!$result->{"ok"}) { $bad{$queue} = $result; } # # look in lprng output for bad things # elsif ($opt_l) { my $err = check_lprng ($result->{"header"}); $details{$queue} = $err->{"fields"}; if (!$err->{"ok"}) { $bad{$queue} = $result; $bad{$queue}->{"error"} = $err->{"error"}; } else { $good{$queue} = $result; } } else { $good{$queue} = $result; } } my $ret; if (keys %bad) { $ret = 1; print join (" ", sort keys %bad), "\n"; } else { $ret = 0; print "\n"; } # # show detail # if (!$opt_d) { # # failure detail # foreach my $q (keys %bad) { print "------------------------------------------------------------------------------\n"; print "HOST $HOST QUEUE $q: $bad{$q}->{error}\n"; print $details{$q}->{"Printer"}, "\n"; print "------------------------------------------------------------------------------\n"; if ($opt_l) { # this will probably never be true if ($details{$q}->{"queuelist"} eq "") { print "queue empty\n"; } else { print $details{$q}->{"queuelist"}; } } elsif ($bad{$q}->{"header"} ne "") { print $bad{$q}->{"header"}, "\n"; } print "\n"; } if (keys %good) { print <<'EOF'; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%% %%%%%%% %%%%%%% the following are queues which have no problems at this moment %%%%%%% %%%%%%% %%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% EOF } # # non-failure detail # foreach my $q (keys %good) { print "------------------------------------------------------------------------------\n"; print "HOST $HOST QUEUE $q: ok\n"; print $details{$q}->{"Printer"}, "\n"; print "------------------------------------------------------------------------------\n"; if ($opt_l) { if ($details{$q}->{"queuelist"} eq "") { print "queue empty\n"; } else { print "$details{$q}->{queuelist}\n"; } } else { print $good{$q}->{"header"}, "\n"; } print "\n"; } } exit $ret; sub lpdGET { use Socket; use Sys::Hostname; my($Server, $Port, $Queue) = @_; my($ServerOK, $TheContent); $TheContent = ''; my $result; eval { local $SIG{ALRM} = sub { die "Timeout Alarm" }; alarm $TIMEOUT; my $err = &OpenSocket($Server, $Port); # Open a connection to the server if ($err ne "") { # Failure to open the socket $result = { "ok" => 0, "error" => $err, "header" => undef, }; return undef; } # # lpd queue list # "short" listing command is 0x03 # "long" listing command is 0x04 # print S "\x04$Queue\x0a"; $/ = "\x0a"; while (defined ($in = )) { $TheContent .= $in; # Store data for later processing } close(S); alarm 0; # Cancel the alarm $ServerOK = 1; }; if ($EVAL_ERROR and ($EVAL_ERROR =~ /^Timeout Alarm/)) { return { "ok" => 0, "error" => "timeout after $TIMEOUT seconds", "header" => $TheContent, }; } if ($result->{"error"} ne "") { return $result; } return { "ok" => $ServerOK, "header" => $TheContent, "error" => undef, }; } # # look for badness in lprng output # error # stalled > $opt_n secs # sub check_lprng { my ($buff) = @_; my $in_rank = 0; my $fail = 0; my $status = { "ok" => 1, "fields" => {}, "error" => "", }; foreach my $l (split (/\x0d?\x0a/sm, $buff)) { # # sort data # if ($l =~ /^\s+([^:]+):\s+(.*)$/) { $status->{"fields"}->{$1} .= $2; } elsif ($l =~ /^Printer:\s+(.*)/) { $status->{"fields"}->{"Printer"} = $1; } if ($l =~ /^\s+Rank.*Owner/) { $in_rank++; $status->{"fields"}->{"queuelist"} = ""; } if ($in_rank) { $status->{"fields"}->{"queuelist"} .= "$l\n"; } # # check for errors # if ($in_rank && $opt_e && $l =~ /^error/ && !$fail) { $status->{"ok"} = 0; $status->{"error"} = "job error"; $fail = 1; } elsif ($in_rank && $l =~ /^stalled\((\d+)sec/ && $1 > $STALLED && !$fail) { $status->{"ok"} = 0; $status->{"error"} = "job stalled $1 seconds"; $fail = 1; } elsif ($in_rank && $l =~ /^active\(attempt-(\d+)/ && !$fail) { $status->{"ok"} = 0; $status->{"error"} = "multiple attempts, currently $1"; $fail = 1; } } return $status; } # # Make a Berkeley socket connection between this program and a TCP port # on another (or this) host. Port can be a number or a named service # # returns "" on success, or an error string on failure # sub OpenSocket { my ($host, $port) = @_; my $proto = (getprotobyname('tcp'))[2]; return ("could not get protocol") if (!defined $proto); my $conn_port; if ($port =~ /^\d+$/) { $conn_port = $port; } else { $conn_port = (getservbyname($port, 'tcp'))[2]; return ("could not getservbyname for $port") if (!defined $conn_port); } my $host_addr = (gethostbyname($host))[4]; return ("gethostbyname failure") if (!defined $host_addr); my $that = sockaddr_in ($conn_port, $host_addr); if (!socket (S, &PF_INET, &SOCK_STREAM, $proto)) { return ("socket: $!"); } if (!connect (S, $that)) { return ("connect: $!"); } select(S); $| = 1; select(STDOUT); ""; } etbemon-1.3.6/mon.d/mon.monitor0000755000000000000000000000311710616437073013271 0ustar #!/usr/bin/perl # # mon.monitor # # monitor mon server # # Jim Trocki # # $Id: mon.monitor,v 1.1.1.1.4.1 2007/05/03 19:55:39 trockij Exp $ use strict; use English; use Mon::Client; use Getopt::Std; my %opt; getopts ('u:p:P:t:', \%opt); my @failures; my @details; my $TIMEOUT = 30; $TIMEOUT = $opt{"t"} if ($opt{"t"}); foreach my $host (@ARGV) { my $c = new Mon::Client ( "host" => $host, ); if ($opt{"p"}) { $c->port ($opt{"p"}); } eval { local $SIG{"ALRM"} = sub { die "Timeout Alarm" }; alarm $TIMEOUT; if (!defined $c->connect) { push @failures, $host; push @details, "$host: " . $c->error; undef $c; next; } if ($opt{"u"} && $opt{"P"}) { if (! defined $c->login ( "username" => $opt{"u"}, "password" => $opt{"P"}, )) { push @failures, $host; push @details, "$host: " . $c->error; undef $c; next; } } my @st = $c->list_state; if ($c->error ne "") { push @failures, $host; push @details, "$host: " . $c->error; $c->disconnect; undef $c; next; } push @details, "$host: @st"; if (!defined $c->disconnect) { push @failures, $host; push @details, "$host: could not disconnect, " . $c->error; undef $c; next; } undef $c; }; if ($EVAL_ERROR =~ "Timeout Alarm") { push @failures, $host; push @details, "$host: timeout"; } } if (@failures) { print join (" ", sort @failures), "\n"; } else { print "no failures\n"; } if (@details) { print join ("\n", @details), "\n"; } if (@failures) { exit 1; } exit 0; etbemon-1.3.6/mon.d/msql-mysql.monitor0000755000000000000000000001013113142310277014602 0ustar #!/usr/bin/perl # # $Id: msql-mysql.monitor,v 1.1.1.1.4.1 2007/05/08 11:22:29 trockij Exp $ # # arguments: # # [--mode [msql|mysql]] --username=username --password=password # --database=database --port=# # hostname # # a monitor to determine if a mSQL or MySQL database server is operational # # Rather than use tcp.monitor to ensure that your SQL server is responding # on the proper port, this attempts to connect to and list the databases # on a given database server. # # The single argument, --mode [msql|mysql] is inferred from the script name # if it is named mysql.monitor or msql.monitor. Thus, the following two are # equivalent: # # ln msql-mysql.monitor msql.monitor # ln msql-mysql.monitor mysql.monitor # msql.monitor hostname # mysql.monitor hostname # # and # # msql-mysql.monitor --mode msql hostname # msql-mysql.monitor --mode mysql hostname # # use the syntax that you feel more comfortable with. # # This monitor requires the perl5 DBI, DBD::mSQL and DBD::mysql modules, # available from CPAN (http://www.cpan.org) # # Copyright (C) 1998, ACC TelEnterprises # Written by James FitzGibbon # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # use DBI; use Getopt::Long; use POSIX ':signal_h'; my @details=(); my @failures=(); my $mask = POSIX::SigSet->new( SIGALRM ); my $action = POSIX::SigAction->new( sub { die "connect timeout" }, # the handler code ref $mask, # not using (perl 5.8.2 and later) 'safe' switch or sa_flags ); GetOptions( \%options, "mode=s", "port=i", "username=s", "password=s", "database=s", "timeout=i" ); # uncomment these two lines and provide suitable information if you don't # want to pass sensitive information on the command line #$options{username} ||= "username"; #$options{password} ||= "password"; # if the password starts with / it will be taken as the name of a file to # read for the parameter, eg --password=/var/lib/mon/mysql-pass.txt if(substr($options{password}, 0, 1) eq "/") { open(FILE, "<$options{password}") or die "can't open $options{password}"; $options{password} = ; chomp $options{password}; close(FILE); } $options{timeout} = 60 if ! $options{timeout}; if( $0 =~ m/\/msql\.monitor$/ || $options{mode} =~ m/msql/i ) { $mode = "mSQL"; $options{port} = 1114 if ! $options{port}; } elsif( $0 =~ m/\/mysql\.monitor/ || $options{mode} =~ m/mysql/i) { $mode = "mysql"; $options{port} = 3306 if ! $options{port}; } else { print "invalid mode $mode!\n"; exit 1; } for $host( @ARGV ) { my $dbh = 0; my $oldaction = POSIX::SigAction->new(); sigaction( 'ALRM', $action, $oldaction ); eval { alarm $options{timeout}; $dbh = DBI->connect( "DBI:$mode:$options{database}:$host:$options{port}", $options{username}, $options{password}, { PrintError => 0 } ); alarm 0; }; alarm 0; sigaction( 'ALRM', $oldaction ); if ($@) { push( @failures, $host); push( @details, "$host: Could not connect to $mode server on $options{port}: $@\n"); next; } elsif( ! $dbh ) { push( @failures, $host); push( @details, "$host: Could not connect to $mode server on $options{port}: " . $DBI::errstr . "\n"); next; } @tables = $dbh->tables(); if( $#tables < 0 ) { push( @failures, $host); push( @details, "$host: No tables found for database $options{database}\n"); } $dbh->disconnect(); } if (@failures) { print join (" ", sort @failures), "\n"; print sort @details if (scalar @details > 0); exit 1; } else { exit 0; } etbemon-1.3.6/mon.d/na_quota.monitor0000755000000000000000000003345413135636631014316 0ustar #!/usr/bin/perl -w # # "mon" monitor to detect quotas near their limits on Network Appliance # filers using SNMP # # Originally by Jim Trocki # Updated by Theo Van Dinter (tvd@colltech.com, felicity@kluge.net) (c) 2001 # $Id: na_quota.monitor,v 1.1.1.1 2004/06/09 05:18:04 trockij Exp $ # # Invoke from mon via: # monitor na_quota.monitor [-c snmp community] [-f configuration file] ;; # # This script uses a configuration file to determine the alert points and # which filers to probe. The configuration file format is as follows: # filer_name type volume name size_diff files_diff # # filer_name = hostname of a filer (ie: toaster) # type = quota type, either tree or user # volume = the volume to check, can be "*" to set the default # name = the name of the qtree, can be "*" to set the default # size_diff = the amount of free space available to cause an alert. # "# [kmgt]b", "#.# [kmgt]b", "#" (assumes KB), or "#%" # files_diff = the number of files available to cause an alert. # "#" or "#%" # # For values with whitespace, enclose in quotes. (ie: "30 KB") # Use "-" for no alert, files_diff can be left off if unused. # Either size_diff or files_diff must be defined ("-" for both isn't allowed). # Volume and Name can be "*" for "all". It will be overridden as appropriate: # i.e.: toaster tree vol0 * 20% # default all trees in vol0 to 20% # toaster tree vol0 foo 10% # vol0 tree foo will use 10% instead # toaster tree vol0 bar 1GB # vol0 tree bar will use 1GB instead # toaster tree vol0 baz 0 # vol0 tree baz will only alert when # # size used == size limit # # Alerts occur when the used space/files is within "size_diff" or # "files_diff" from the limit. So if a size limit is at 100KB and used # is 80KB, the free space is 20KB or 20%. An alert will occur if the # size_diff is >= 20KB or >=20%. Note: The percentage is a rounded # integer, so 10% actually means 9.5 - 10.4% or below 10.4%... # # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # use Mon::SNMP; use strict; use Getopt::Std; use Text::ParseWords; use vars qw/ $opt_f $opt_c $host %failures /; $|++; $ENV{"MIBS"} = "NETWORK-APPLIANCE-MIB"; # We need the NetApp MIB loaded ... getopts ('c:f:'); $opt_f ||= "/usr/lib/mon/na_quota.cf"; # Configuration File $opt_c ||= "public"; # Community my $CONF = read_cf($opt_f); die "error reading config file $opt_f: $CONF\n" unless ( ref $CONF ); # Go through each specified host foreach $host (@ARGV) { if (!defined $CONF->{$host}) { $failures{$host} = "$host specified on the command line but not defined in $opt_f"; next; } my $q = retrieve_quotas ($host, $opt_c); # Grab the quotas from $host # If $q isn't a reference, it's an error string. unless (ref $q) { $failures{$host} = "could not retrieve quotas from $host: $q"; next; } # Check for user quotas, then tree quotas. foreach ( "user", "tree" ) { my $fails = quota_check($host,$_,$CONF,$q); @failures{keys %{$fails}} = values %{$fails} if ( defined $fails ); } } # Display failures if there were any, then exit with 0 or 1 appropriately. my $retval = 0; if (defined %failures) { print join("\n",join(" ",sort keys %failures),"",values %failures,""); $retval = 1; } exit $retval; # Read in the configuration file # # Input : Path to the configuration file # Output: Hash reference of the configuration # $ref->{filer_name}->{quota_type}->{volume}->{quota_name}->{"files" or "size"} = diff # sub read_cf { my $cf = shift; my $error = undef; my($filer,$type,$user,$path); my $CONF = undef; # Open the configuration file or return the error string open(CF, "<$cf") || return $!; while (defined($_=)) { chomp; s/\s*#.*$//; # kill comments s/^\s*//; s/\s*$//; # get rid of pre-suff whitespace next unless /\S/; # skip blank lines # Use quotewords to allow for quotas with spaces, etc. my($filer,$type,$volume,$name,$size,$files) = "ewords('\s+',0,$_); # Allow "-" to mean undefined. $size = undef if ( defined $size and $size eq "-" ); $files = undef if ( defined $files and $files eq "-" ); unless ( defined $filer && $filer =~ /^[a-z0-9_.-]+$/i ) { $error = "invalid filer name specified, $filer, line $."; last; } unless ( defined $type && $type =~ /^(tree|user)$/i ) { $error = "invalid quota type specified, $type, line $."; last; } unless ( defined $volume && ( $volume eq "*" || $volume =~ /^[_a-z][_a-z0-9]*$/i ) ) { $error = "invalid volume specified, $volume, line $."; last; } unless ( defined $name ) { $error = "invalid name specified, $name, line $."; last; } unless ( defined $size || defined $files ) { $error = "invalid line, no size_quota or file_quota, line $."; last; } # Convert the filer and type to lowercase, the rest are case-sensitive $filer = lc $filer; $type = lc $type; # If we have a KB limit and it's a valid limit ... if ( defined $size && defined($size = to_kb($size)) ) { $CONF->{$filer}->{$type}->{$volume}->{$name}->{"size"} = $size; } elsif ( defined $size ) { $error = "invalid size specification, $size, line $."; last; } # If we have a file limit and it's a valid limit ... if ( defined $files && $files =~ /^\d+\s*\%?$/ ) { $CONF->{$filer}->{$type}->{$volume}->{$name}->{"files"} = $files; } elsif ( defined $files ) { $error = "invalid files specification, $files, line $."; last; } } close (CF); # Return either the configuration HASH or the error string. return ( defined $error ) ? $error : $CONF; } # Convert given units to KB # # Input : Scalar value that is one of the following: # "# xB" (x=[kmgt]), "#" (assume KB), or "#%" # Output: integer "#" in KB or "#%" (passthru) # sub to_kb { my $value = shift; my ($num, $unit); if ($value =~ /^(\d+(?:\.\d+)?)\s*([kmgt])b$/i) { # "# xB" ($num, $unit) = ($1, lc $2); } elsif ( $value =~ /^\d+\s*\%?$/ ) { # "#%" or "#" (assume KB) return $value; } else { # who knows? error out. return undef; } # Figure out the prefix xB -> KB conversion ratio. Leave as KB by default. my $mval = ($unit eq "m") ? 1024 : ($unit eq "g") ? 1048576 : ($unit eq "t") ? 1073741824 : 1; return (int ($num*$mval)); } # Convert given # of KB into a more displayable string (MB, GB, etc.) # # Input : Scalar value of KB. Any non-numeric chars are stripped out. # Output: String in the format "#.##xB" where x is [KMGT]. ie: 10 becomes "10KB". # sub from_kb { my $value = shift; my @prefix = qw/ T G M K /; my $index = $#prefix; return undef unless defined $value; $value =~ tr/0-9//cd; # we only handle numbers (KB) while ( $value > 1024 && $index >= 0 ) { # Run until we can't go any further! $index--; $value /= 1024; } return sprintf "%.2f%sB", $value, $prefix[$index]; # Return the formatted string } # Retrieve the quota information from the NetApp via SNMP. # # Input : Hostname and SNMP Community (defaults to public) # Output: Hash reference of the quota information # $ref->{"user"}->{volume}->{username or uid}->{info} = value # $ref->{"tree"}->{volume}->{tree_name}->{info} = value # where info is: "qrVKBytesUsed", "qrVKBytesLimit", "qrVFilesUsed", "qrVFileLimit" # sub retrieve_quotas { my $host = shift; # Hostname my $community = shift || "public"; # SNMP Community, "public" by default my $quotas = undef; # Hash of quota information my %volnames = (); # Hash of volume names for reference # Establish the SNMP session if possible. my $s = new SNMP::Session ( DestHost => $host, Community => $community || "public", "Version" => 2, UseEnums => 1, ); if (!defined $s) { return "could not create SNMP session" } # Map volume numbers to names for use later on my $v = new SNMP::Varbind (["qvStateVolume"]); $s->getnext ($v); while (!$s->{"ErrorStr"} && $v->tag eq "qvStateVolume") { my @q = $s->get ([ ["qvStateVolume", $v->iid], ["qvStateName", $v->iid], ]); last if ($s->{"ErrorStr"}); $volnames{$q[0]} = $q[1]; $s->getnext ($v); } if ($s->{"ErrorStr"}) { return $s->{"ErrorStr"}; } # Get the quota information $v = new SNMP::Varbind (["qrVIndex"]); $s->getnext ($v); while (!$s->{"ErrorStr"} && $v->tag eq "qrVIndex") { # go through each qrVIndex my @q = $s->get ([ ["qrVType", $v->iid], ["qrVId", $v->iid], ["qrVKBytesUsed", $v->iid], ["qrVKBytesLimit", $v->iid], ["qrVFilesUsed", $v->iid], ["qrVFileLimit", $v->iid], ["qrVPathName", $v->iid], ["qrVVolume", $v->iid], ["qrVTree", $v->iid], ]); last if ($s->{"ErrorStr"}); # exit if there's a problem # Skip the crap quotas... if ( $q[0] ne "qrVTypeUnknown" && $q[0] ne "qrVTypeUserDefault" ) { # Turn qrVTypeUser and qrVTypeTree into "user" and "tree" if ( $q[0] =~ /^qrVType(User|Tree)$/ ) { $q[0] =~ s/^.+(User|Tree)$/\L$1/; } else { return "Unknown quota type ($q[0]) returned from filer!"; } # Map volume number to volume name $q[7] = $volnames{$q[7]}; # Map UID to Username if possible, use the system ... if ($q[0] eq "user"){ my($user) = (getpwuid($q[1]))[0]; $q[1] = $user if defined $user; } # Setup hash of quotas. type -> vol -> name -> key = value my $id = ( $q[0] eq "user" ) ? $q[1] : $q[8]; $quotas->{$q[0]}->{$q[7]}->{$id}->{"qrVKBytesUsed"} = $q[2]; $quotas->{$q[0]}->{$q[7]}->{$id}->{"qrVKBytesLimit"} = $q[3]; $quotas->{$q[0]}->{$q[7]}->{$id}->{"qrVFilesUsed"} = $q[4]; $quotas->{$q[0]}->{$q[7]}->{$id}->{"qrVFilesLimit"} = $q[5]; } $s->getnext ($v); # go on to the next one } # If we errored out, return the error. Otherwise return the hash reference. return ( $s->{"ErrorStr"} ) ? $s->{"ErrorStr"} : $quotas; } # This subroutine will check both tree and user quotas. Note: It's fairly nasty. # It was much much worse at one point, but it's a bit cleaner now. There's one routine # to handle both the tree and user quotas now instead of one for each type (size/files). # # Input : hostname, type (user|files), configuration hash ref, quota information hash ref # Output: hash reference of failures, or undef if there are no failures. # sub quota_check { my($host,$type,$CONF,$q) = @_; my $failures = undef; my $actvolume; # sort by volume name (unnecessary, but (*) needs to be last...) foreach $actvolume ( sort { ($a eq "*")?1:($b eq "*")?-1:$a cmp $b; } keys %{$CONF->{$host}->{$type}} ) { my $names = $CONF->{$host}->{$type}->{$actvolume}; my @volumes = (); my $done = (); # Generate the appropriate volume list if ( $actvolume eq "*" ) { @volumes = grep(!exists $done->{$host}->{$type}->{$_}, keys %{$q->{$type}}); } else { @volumes = ( $actvolume ); } my $volume; foreach $volume ( @volumes ) { my $actname; # sort by name (unnecessary, but (*) needs to be last...) foreach $actname ( sort { ($a eq "*")?1:($b eq "*")?-1:$a cmp $b; } keys %{$names} ) { my $qtype = $names->{$actname}; # quota information my @names = (); # Generate the appropriate quota name list if ( $actname eq "*" ) { @names = grep(!exists $done->{$host}->{$type}->{$volume}->{$_}, keys %{$q->{$type}->{$volume}}); } else { @names = ( $actname ); } my $name; foreach $name ( @names ) { # Keep track of which stuff we've checked $done->{$host}->{$type}->{$volume}->{$name}++; # If a configured check isn't quota-ed, report it as error. if ( exists $q->{$type}->{$volume}->{$name} ) { my %info = %{$q->{$type}->{$volume}->{$name}}; my $sorf; foreach $sorf ( "size", "files" ) { my $kbofi = ($sorf eq "size")?"KBytes":"Files"; my $limit = $info{"qrV${kbofi}Limit"}; my $used = $info{"qrV${kbofi}Used"}; if ( exists $qtype->{$sorf} ) { # Verify that the usage is being limited if ( $limit < 0 ) { $failures->{"$host:$volume:$name"}="requested quota ('$host $type $volume $name $sorf') isn't limited on the filer" unless ( $actname eq "*" ); next; } elsif ( $limit == 0 ) { $failures->{"$host:$volume:$name"}="requested quota ('$host $type $volume $name $sorf') has a limit of 0 $sorf on the filer"; next; } # Percentage and # free/left # Make sure to round fpct ... ;) my $fkb = $limit-$used; my $fpct = int($fkb/$limit*100+0.5); if ( $qtype->{$sorf} =~ /^(\d+)\s*\%$/ ) { my $pct = $1; if ( $fpct <= $pct ) { my $msg = "$type $sorf quota $host:$volume:$name has $fpct% "; $msg.=($sorf eq "files")?"files left": "(".from_kb($fkb).") free"; $msg.=" <= $pct% ($actvolume:$actname)"; $failures->{"$host:$volume:$name"}=$msg; } } else { # non-percent if ( $fkb <= $qtype->{$sorf} ) { my $msg = "$type $sorf quota $host:$volume:$name has "; $msg.=($sorf eq "files")?"$fkb files left": from_kb($fkb)." free"; $msg.=" <= "; $msg.=($sorf eq "files")?$qtype->{$sorf}: from_kb($qtype->{$sorf}); $msg.=" ($actvolume:$actname)"; $failures->{"$host:$volume:$name"}=$msg; } } } } } else { $failures->{"$host:$volume:$name"}="requested quota ('$host $type $volume $name') doesn't exist on filer" unless ( $actname eq "*" ); next; } } } } } return $failures; } etbemon-1.3.6/mon.d/netappfree.monitor0000755000000000000000000002120613135636631014630 0ustar #!/usr/bin/perl -w # # Use SNMP to get free disk space or inode status from a Network Appliance # # exit values: # 1 - free space or inodes on any host dropped below the supplied parameter # 2 - network or SNMP error (SNMP library error, no response from server) # 3 - config error - (filesystem in config file does not exist on filer) # USAGE # [--community=] [--timeout=] # [--config=/path/to/configfile] [--list] host1 host2 ... # EXAMPLES # --list option will dump current status from requested hosts: # netappfree.monitor --list filer1 filer2 filer3 # sample output: # filer ONTAP filesystem KB total KB avail Inode% # ---------------------------------------------------------------------------- # filer1 6.1.2R3 /vol/vol0/ 61092616 6773416 86 # filer1 6.1.2R3 /vol/vol0/.snaps 2545524 1260240 0 # sample invocation in mon.cf, with local MIB directory for the Netapp MIB # NETWORK-APPLIANCE-MIB.txt (copy from /etc/mib/netapp.mib on filer): # service freespace # description test freespace and inodes on Netapp filers # depend SELF:ping # MIBDIRS=/usr/local/share/snmp/mibs # interval 7m # monitor netappfree.monitor # CONFIG FILE FORMAT # # Run "netappfree --list host1 host2 ..." first to get list of filesystems # and whether inodes are properly reported. If you don't want to monitor # inodes for a particular FS, leave tha column blank. # # # host filesystem freespace [InodeThreshold] # (in kb, gb, or mb) (in % or k) # # filer1 /vol/main/ 5gb 90% # filer2 /vol/vol0/ 5gb 500k # # This requires the UCD SNMP library and G.S. Marzot's Perl SNMP # module. # # Originally by Jim Trocki. Modified by Theo Van Dinter # (tvd@colltech.com, felicity@kluge.net) to add verbose error output, # more error checking, etc. Can be used in conjunction with # snapdelete.alert to auto-remove snapshots if needed. # Modified December 2003 by Ed Ravin (eravin@panix.com) to add inode # checking, detect nonexistent filesystem in config file, pass perl -w # checks, added more info to error messages for clarity, updated doc comments # above. # $Id: netappfree.monitor,v 1.1.1.1 2004/06/09 05:18:04 trockij Exp $ # # Copyright (C) 1998, Jim Trocki # Copyright (C) 1999-2001, Theo Van Dinter # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # use Mon::SNMP; use Getopt::Long; sub list; sub readcf; sub toKB; $ENV{"MIBS"} = 'RFC1213-MIB:NETWORK-APPLIANCE-MIB'; GetOptions (\%opt, "community=s", "timeout=i", "retries=i", "config=s", "list"); die "no host arguments\n" if (@ARGV == 0); $RET = 0; @ERRS = (); %HOSTS = (); $COMM = $opt{"community"} || "public"; $TIMEOUT = $opt{"timeout"} || 2; $TIMEOUT *= 1000 * 1000; $RETRIES = $opt{"retries"} || 5; $CONFIG = $opt{"config"} || (-d "/etc/mon" ? "/etc/mon" : "/usr/lib/mon/etc") . "/netappfree.cf"; ($dfIndex, $dfFileSys, $dfKBytesTotal, $dfKBytesAvail, $dfInodesFree, $dfPerCentInodeCapacity) = (0..5); list (@ARGV) if ($opt{"list"}); readcf ($CONFIG) || die "could not read config: $!\n"; foreach $host (@ARGV) { next if (!defined $FREE{$host}); if (!defined($s = new SNMP::Session (DestHost => $host, Timeout => $TIMEOUT, Community => $COMM, Retries => $RETRIES))) { $RET = ($RET == 1) ? 1 : 2; $HOSTS{$host} ++; push (@ERRS, "could not create session to $host: " . $SNMP::Session::ErrorStr); next; } $v = new SNMP::VarList ( ['dfIndex'], ['dfFileSys'], ['dfKBytesTotal'], ['dfKBytesAvail'], ['dfInodesFree'], ['dfPerCentInodeCapacity'], ); if ( $v->[$dfIndex]->tag !~ /^df/ ) { push(@ERRS,"OIDs not mapping correctly! Check that NetApp MIB is available!"); $RET = 1; last; } while (defined $s->getnext($v)) { last if ($v->[$dfIndex]->tag !~ /dfIndex/); my $filesys= $v->[$dfFileSys]->val; next unless exists($FREE{$host}{$filesys}); if ($v->[$dfKBytesAvail]->val < $FREE{$host}{$filesys}{'bytes'}) { $HOSTS{$host} ++; push (@ERRS, sprintf ("%1.1fGB free on %s:%s (threshold %1.1fGB, fs size %1.1fGB)", $v->[$dfKBytesAvail]->val / 1024 / 1024, $host, $filesys, $FREE{$host}{$filesys}{'bytes'} / 1024 / 1024, $v->[$dfKBytesTotal]->val / 1024 / 1024) ); $RET = 1; } # mark filesys entry as seen in filer's MIB $FREE{$host}{$v->[$dfFileSys]->val}{'existsOnFiler'}= 1; if (defined($FREE{$host}{$v->[$dfFileSys]->val}{'inode'})) { my $inodefreewanted= $FREE{$host}{$v->[$dfFileSys]->val}{'inode'}; if (0 < $inodefreewanted and $inodefreewanted < 1) { # percentage? if ($v->[$dfPerCentInodeCapacity]->val > $inodefreewanted * 100) { # percentage exceeded? $HOSTS{$host} ++; push (@ERRS, sprintf("%d%% inodes used on %s:%s, over threshold of %d%%", $v->[$dfPerCentInodeCapacity]->val, $host, $v->[$dfFileSys]->val, $inodefreewanted * 100 )); $RET = 1; } } elsif ($v->[$dfInodesFree]->val < $inodefreewanted) { $HOSTS{$host} ++; push (@ERRS, sprintf("%1.1f inodes free on %s:%s, below threshold of %1.1f", $v->[$dfInodesFree]->val, $host, $v->[$dfFileSys]->val, $inodefreewanted )); $RET = 1; } } } if ($s->{ErrorNum}) { $HOSTS{$host} ++; push (@ERRS, "could not get dfIndex for $host: " . $s->{ErrorStr}); $RET = ($RET == 1) ? 1 : 2; } } foreach $host (@ARGV) { foreach $filesys (keys %{$FREE{$host}}) { if (! $FREE{$host}{$filesys}{'existsOnFiler'} ) { $HOSTS{$host} ++; push (@ERRS, "filesystem $filesys does not exist on $host"); $RET = ($RET == 1) ? 1 : 3; } } } if ($RET) { print join(" ", sort keys %HOSTS), "\n\n", join("\n", @ERRS), "\n"; } exit $RET; # # read configuration file # sub readcf { my ($f) = @_; my ($l, $host, $filesys, $free, $inodefree); open (CF, $f) || return undef; while () { next if (/^\s*#/ || /^\s*$/); chomp; ($host, $filesys, $free, $inodefree) = split; if (!defined ($FREE{$host}{$filesys}{'bytes'} = toKB ($free))) { die "error free specification, config $f, line $.\n"; } if (!defined ($FREE{$host}{$filesys}{'inode'} = toIN ($inodefree))) { # allow this to be optional for compatibility # die "error inodefree specification, config $f, line $.\n"; } $FREE{$host}{$filesys}{'existsOnFiler'}= 0; } close (CF); } sub toKB { my ($free) = @_; my ($n, $u); if ($free =~ /^(\d+\.\d+)(kb|mb|gb)$/i) { ($n, $u) = ($1, "\L$2"); } elsif ($free =~ /^(\d+)(kb|mb|gb)$/i) { ($n, $u) = ($1, "\L$2"); } else { return undef; } return (int ($n * 1024)) if ($u eq "mb"); return (int ($n * 1024 * 1024)) if ($u eq "gb"); int ($n); } sub toIN { my ($infree) =@_; return undef unless defined($infree); if ($infree =~ /^(\d+\.?\d+)%$/) { # percentage return $1 / 100; } if ($infree =~ /^(\d+\.?\d+)(k|kb)$/) { # kilos? return $1 * 1024; } if ($infree =~ /^(\d+\.?\d+)$/) { # bare?? return $1; } return undef; } sub list { my (@hosts) = @_; foreach $host (@hosts) { if (!defined($s = new SNMP::Session (DestHost => $host, Timeout => $TIMEOUT, Community => $COMM, Retries => $RETRIES))) { print STDERR "could not create session to $host: " . $SNMP::Session::ErrorStr, "\n"; next; } $ver = $s->get(['sysDescr', 0]); $ver =~ s/^netapp.*release\s*([^:]+):.*$/$1/i; $v = new SNMP::VarList ( ['dfIndex'], ['dfFileSys'], ['dfKBytesTotal'], ['dfKBytesAvail'], ['dfInodesFree'], ['dfPerCentInodeCapacity'], ); while (defined $s->getnext($v)) { last if ($v->[$dfIndex]->tag !~ /dfIndex/); write; } } exit 0; } format STDOUT_TOP = filer ONTAP filesystem KB total KB avail Inode% ------------------------------------------------------------------------------ . format STDOUT = @<<<<<<<<<<<<<< @<<<<<<<<<< @<<<<<<<<<<<<<<< @>>>>>>>>>> @>>>>>>>>>> @>> $host, $ver, $v->[1]->[2], $v->[2]->[2], $v->[3]->[2], $v->[5]->[2] . etbemon-1.3.6/mon.d/nntp.monitor0000755000000000000000000001164710616437074013467 0ustar #!/usr/bin/perl # # nntp.monitor # example: monitor nntp.monitor -g groupname -u user -a password # # Connect to an nntp server which possibly requires authentication, and # wait for the right output. # # For use with "mon". # # Arguments are "-p port -t timeout [-g group] [-f] host [host...] -u username -a password" # # This monitor connects to the NNTP server(s), checks for a greeting, logs in, # then performs a "mode reader" and a "group (groupname)", and then disconnects. # If the group is not specified by the -g option, then "control" is assumed. # # if "-f" is supplied, then it is assumed that a feeder is being tested, # and the "mode reader" and "group (groupname)" commands are not executed. # # Adapted from "http.monitor" by # Jim Trocki, trockij@arctic.org # authentication support added by # Kai Schaetzl/conactive.com # # http.monitor written by # # Jon Meek # American Cyanamid Company # Princeton, NJ # # $Id: nntp.monitor,v 1.2.2.1 2007/05/03 19:55:40 trockij Exp $ # # Copyright (C) 1998, Jim Trocki # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # use Getopt::Std; use English; getopts ("fg:p:t:d:u:a:"); $GROUP = $opt_g || 'control'; $PORT = $opt_p || 119; $TIMEOUT = $opt_t || 30; $FEEDER = $opt_f; $DEBUG = $opt_d || ""; $USER = $opt_u || ''; $PASS = $opt_a || ''; @failures = (); foreach $host (@ARGV) { if (! &nntpGET($host, $PORT)) { push (@failures, $host); } } if (@failures == 0) { exit 0; } print join (" ", sort @failures), "\n"; exit 1; sub nntpGET { use Socket; use Sys::Hostname; my($Server, $Port) = @_; my($ServerOK, $TheContent); $ServerOK = 0; $TheContent = ''; $Path = '/'; ############################################################### eval { local $SIG{ALRM} = sub { die "Timeout Alarm" }; alarm $TIMEOUT; $result = &OpenSocket($Server, $Port); # Open a connection to the server if ($result == 0) { # Failure to open the socket print "Unable to open socket\n" if $DEBUG; return ''; } # # welcome message # $in = ; if ($in !~ /^2\d\d/) { alarm 0; print "No welcome message\n" if $DEBUG; return 0; } if (!$FEEDER) { if ($USER ne "") { # user print S "authinfo user $USER\r\n"; $in = ; if ($in !~ /^381/) { alarm 0; print "No reaction to authinfo user\n" if $DEBUG; return 0; } # password print S "authinfo pass $PASS\r\n"; $in = ; if ($in !~ /^281/) { alarm 0; print "No reaction to authinfo pass or wrong password\n" if $DEBUG; return 0; } } # # mode reader, wait for OK response # print S "mode reader\r\n"; $in = ; if ($in !~ /^2\d\d/) { alarm 0; print "Unable to perform 'mode reader'\n" if $DEBUG; return 0; } # # select $GROUP group, wait for OK response # print S "group $GROUP\r\n"; $in = ; if ($in !~ /^2\d\d/) { alarm 0; print "Unable to select group '$GROUP'\n" if $DEBUG; return 0; } } # # log out # print S "quit\r\n"; $in = ; if ($in !~ /^2\d\d/) { alarm 0; print "No response on 'quit' command.\n" if $DEBUG; return 0; } $ServerOK = 1; close(S); alarm 0; # Cancel the alarm }; if ($EVAL_ERROR and ($EVAL_ERROR =~ /^Timeout Alarm/)) { print "**** Time Out\n"; return 0; } return $ServerOK; } sub OpenSocket { # # Make a Berkeley socket connection between this program and a TCP port # on another (or this) host. Port can be a number or a named service # local($OtherHostname, $Port) = @_; local($OurHostname, $sockaddr, $name, $aliases, $proto, $type, $len, $ThisAddr, $that); $OurHostname = &hostname; ($name, $aliases, $proto) = getprotobyname('tcp'); ($name, $aliases, $Port) = getservbyname($Port, 'tcp') unless $Port =~ /^\d+$/; ($name, $aliases, $type, $len, $ThisAddr) = gethostbyname($OurHostname); ($name, $aliases, $type, $len, $OtherHostAddr) = gethostbyname($OtherHostname); my $that = sockaddr_in ($Port, $OtherHostAddr); $result = socket(S, &PF_INET, &SOCK_STREAM, $proto) || return undef; $result = connect(S, $that) || return undef; select(S); $| = 1; select(STDOUT); # set S to be un-buffered return 1; # success } etbemon-1.3.6/mon.d/ntpdate.monitor0000755000000000000000000002504310630537263014137 0ustar #!/usr/bin/perl # # ntpdate.monitor Verify that NTP is running and times are within tolerance # ntpdate will do most of the work for us # =head1 NAME B - ntp monitor using ntpdate to do most of the work =head1 DESCRIPTION A mon monitor to verify that ntp is running on multiple servers, those servers have synchronized time, and that the times are within specified limits. The mon server should be running ntp since the times are reported relative to the system performing the query. =head1 SYNOPSIS B =head1 OPTIONS =over 5 =item B<--maxstratum> Maximum stratum number, default is 10. Stratum 16 indicates that ntp is running on a system, but the clock is not synchronized. An alarm will be triggered if this value is exceeded. =item B<--maxoffset> Maximum value of the clock offset in seconds, default is 800 ms (a large value, ntp typically keeps clocks within milliseconds of each other). An alarm will be triggered if this value is exceeded. =item B<-l log_file_template> or B<--log log_file_template> /path/to/logs/internet_web_YYYYMM.log Current year & month are substituted for YYYYMM, that is the only possible template at this time. The format of the log file is: time server stratum offset delay time is in UNIX seconds, offset, and delay are in seconds. Note that offset and delay times in mon detail, and the optional HTML page are in milliseconds. =item B<-shortalerts> Use only hostname in alert list. For organizations with long FQDNs this will make mail and pager alerts more readable. =item B<--htmlfile /full/path/to/file.html> Optional location to write the formated results from the current test. Be sure that the directory is writeable by the user under whom mon is running. =item B<-d> or B<--debug> Debug/Test/Verbose, for manual testing only. =item B<--ntpdate> Specify the location of ntpdate, the default is /usr/sbin/ntpdate =back =head1 MON CONFIGURATION EXAMPLE hostgroup ntp ntp1.somedomain.org ntp2.somedomain.org ntp3.somedomain.org watch ntp service ntpdate interval 30m monitor ntpdate.monitor --maxoffset 0.100 --log /usr/local/mon/logs/gv-ntp-YYYYMM.log period wd {Sun-Sat} alert mail.alert user@somedomain.org alertevery 1h summary =head1 BUGS Listing a server twice can cause ntpdate to report that server as Stratum 0. This can happen even if an alias name is used. The shortalerts option only reports the hostname, it could be extended to provide a configurable number of FQND fields. ntpdate will be removed from the NTP distribution at some point. This monitor will need to be modified to use some form of ntpd -q instead. Check the first line of this file to be sure that it points to an appropriate perl executable. =head1 AUTHOR Jon Meek, meekj at ieee.org =head1 SEE ALSO ntp.monitor by Daniel Hagerty =cut $RCSid = q{$Id: ntpdate.monitor,v 1.3.2.1 2007/06/03 13:14:27 trockij Exp $ }; # # Jon Meek # Lawrenceville, NJ # meekj at ieee.org # # # $Id: ntpdate.monitor,v 1.3.2.1 2007/06/03 13:14:27 trockij Exp $ # # Copyright (C) 2002-2006, Jon Meek # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # use Getopt::Long; GetOptions( "maxstratum=i" => \$MaxStratum, "maxoffset=f" => \$MaxOffset, # "dns" => \$UseDNS, "d|debug" => \$Debug, "l=s" => \$LogFile, "log=s" => \$LogFile, "htmlfile=s" => \$HtmlFile, "shortalerts" => \$ShortAlerts, "ntpdate=s" => \$NTPDATE, ); use Net::DNS; use Sys::Hostname; use POSIX qw(strftime); # # Set Defaults # # ntpdate reports stratum 16 if ntp is running, but time is not synchronized # stratum 0 will be reported if ntp is not running # $MaxStratum = 10 unless $MaxStratum; $MinStratum = 1; # Use the first occurrence of this stratum as the reference time for alarms $ReferenceStratum = 1 unless $ReferenceStratum; # # Trigger alarm if the time is ever off by this much # $MaxOffset = 0.800 unless $MaxOffset; # seconds $NTPDATE = '/usr/sbin/ntpdate' unless $NTPDATE; $HtmlFileHandle = &HTMLheader($HtmlFile) if $HtmlFile; @Failures = (); @Hosts = @ARGV; # Host names are left on the command line after Getopt %NameByIP = &DNSlookups(\@Hosts); $TimeOfDay = time; # Current time print "TimeOfDay: $TimeOfDay\n" if $Debug; $cmd = qq{$NTPDATE -q @Hosts |}; $pid = open(NTP, $cmd) || die "Couldn't run $cmd: $!\n"; while ($in = ) { # print $in if $Debug; chomp $in; # # Pick out server strings # if ($in =~ /^server\s+([\d\.]+),\s+stratum\s+(\d+),\s+offset\s+([\d\.\-\+]+),\s+delay\s+([\d\.\-\+]+)/) { $ip = $1; $stratum = $2; $offset = $3; $delay = $4; $name = $NameByIP{$ip}; print "$in Name: $name Stratum: $stratum\n" if $Debug; if (exists $NameByIP{$ip}) { # Use system name if we have it $HostName = $NameByIP{$ip}; } else { $HostName = $ip; # Otherwise use IP address } $IP{$HostName} = $ip; $Stratum{$HostName} = $stratum; $Offset{$HostName} = $offset; $Delay{$HostName} = $delay; $Detail{$HostName} = $in; if ((!defined $ReferenceOffset) && ($stratum == 1)) { # Save offset from first stratum 1 server seen $ReferenceOffset = $offset; } # # Prepare log entries # if ($LogFile or $Debug) { $LogString{$HostName} = qq{$TimeOfDay $HostName $stratum $offset $delay}; } } } #1234567890123456789012345678901234567890123456789012345678901234567890 #fwmon-gv.gv.us.pri.wyeth.com 0.276 2 0.413 61.050 # # Build formatted results and check alarm limits # $FmtDetail = qq{NTP Server times in milliseconds Delta Stratum Rel Delay\n}; &HTMLtableHeader($HtmlFileHandle, 'NTP Server', 'Delta, ms', 'Stratum', 'Rel, ms', 'Delay, ms', 'Status') if $HtmlFile; foreach $hostname (sort keys %Stratum) { $DeltaTime = $Offset{$hostname} - $ReferenceOffset; $DeltaTimeByHost{$hostname} = $DeltaTime; $msDeltaTime = 1000 * $DeltaTime; $msOffset = 1000 * $Offset{$hostname}; $msDelay = 1000 * $Delay{$hostname}; $FmtDetail .= sprintf ("%-35s %9.3f %3d %9.3f %9.3f", $hostname, $msDeltaTime, $Stratum{$hostname}, $msOffset, $msDelay); $fail_string = ' '; if (($Stratum{$hostname} > $MaxStratum) || ($Stratum{$hostname} < $MinStratum) || (abs($DeltaTime) > $MaxOffset)) { $ip = $IP{$hostname}; $FailureDetail{$hostname} = $Detail{$hostname}; push(@Failures, $hostname); $FmtDetail .= q{ Fail}; $fail_string = 'Fail'; } $FmtDetail .= "\n"; if ($HtmlFile) { $fDeltaTime = sprintf("%12.3f", $msDeltaTime); $fOffset = sprintf("%12.3f", $msOffset); $fDelay = sprintf("%12.3f", $msDelay); &HTMLtableRow($HtmlFileHandle, $hostname, $fDeltaTime, $Stratum{$hostname}, $fOffset, $fDelay, $fail_string); } } print "\n$FmtDetail\n" if $Debug; # # Write results to logfile, if -l # if ($LogFile) { $LogFile = $LogFile; ($sec, $min, $hour, $mday, $Month, $Year, $wday, $yday, $isdst) = localtime($TimeOfDay); $Month++; $Year += 1900; $YYYYMM = sprintf('%04d%02d', $Year, $Month); $LogFile =~ s/YYYYMM/$YYYYMM/; # Fill in current year and month if (-e $LogFile) { # Check for existing log file $NewLogFile = 0; } else { $NewLogFile = 1; } open(LOG, ">>$LogFile") || warn "$0 Can't open logfile: $LogFile\n"; foreach $ip (sort keys %LogString) { print LOG "$LogString{$ip}\n"; } close LOG; } if ($Debug) { foreach $ip (sort keys %LogString) { print "LOG: $LogString{$ip}\n"; } } &HTMLtrailer($HtmlFileHandle) if $HtmlFile; if (@Failures == 0) { # Indicate "all OK" to mon exit 0; } # # Otherwise we have one or more failures # if ($ShortAlerts) { foreach $host (sort @Failures) { if ($host =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) { # IP address, don't shorten push(@SortedFailures, $host); } else { $host =~ /(.*?)\./; push(@SortedFailures, $1); } } } else { @SortedFailures = sort @Failures; } print "------- Have Failures -------\n" if $Debug; print "@SortedFailures\n"; print "------- Details -------\n" if $Debug; print $FmtDetail; #foreach $hostname (sort keys %FailureDetail) { # print "$NameByIP{$hostname} $hostname $FailureDetail{$hostname} $DeltaTimeByHost{$hostname} s\n"; #} exit 1; # Indicate failure to mon # # Get the IP addresses for the hosts (because ntpdate returns IP addresses) # sub DNSlookups { my ($Hosts) = @_; $res = new Net::DNS::Resolver; for (my $i = 0; $i < @$Hosts; $i++) { $target = $Hosts->[$i]; $query = $res->search($target); if ($query) { foreach $rr ($query->answer) { #print "$target Type: ", $rr->type, "\n" if $Debug; if ($rr->type eq "A") { print $rr->address . ' ' if $Debug; $NameByIP{$rr->address} = $target; } } } } return %NameByIP; } sub HTMLheader { # # Print basic standard header for this application # my($FileName) = @_; local *F; open(F, ">$FileName") || warn "$$ can't open $FileName, check permissions"; $Title = "NTP Server Status"; $MonitorHostname = hostname; $FmtTimeNow = strftime("%A %d-%b-%Y %H:%M:%S %Z", localtime(time)); print F <<"EndOfHeader"; $Title

$Title from $MonitorHostname

$FmtTimeNow

EndOfHeader return *F; } sub HTMLtableHeader { my($FileHandle, @Headers) = @_; print $FileHandle "\n"; foreach $h (@Headers) { print $FileHandle "\n"; } print $FileHandle "\n"; } sub HTMLtableRow { my ($FileHandle, @Fields) = @_; my ($align, $f); $align = ''; print $FileHandle "\n"; foreach $f (@Fields) { print $FileHandle "$f\n"; $align = ' align=right'; } print $FileHandle "\n"; } sub HTMLtrailer { # # Print basic standard trailer for this application # my($FileHandle) = @_; print $FileHandle "
$h
\n\n\n"; close $FileHandle; } etbemon-1.3.6/mon.d/phttp.monitor0000755000000000000000000005220610146140377013636 0ustar #!/usr/bin/perl -w =head1 NAME phttp.monitor - parallel http monitor. =head1 SYNOPSIS type this: phttp.monitor --help and read, it is a safe job. =head1 DESCRIPTION phttp.monitor checks http servers in parallel without forking. The request can be an arbitrary multi-line string and the response can be parsed using an arbitrary regular expression. So, HTTP proxies, GET POST PUT TRACE directives, authorization scheme, xxx code or complex content responses, are all possible. =head1 RETURN STATUS O on success for all hosts, or usage demand (--help option) 1 on failure of any host =head1 SUMMARY LINE list of hosts that failed the test with the connection time (in secondes) beetween (), if any, like : www.foo.org(15) www.boo.com(1) =head1 DETAILS detail output (just after summary) follows this convention: =over =item * lines beginning with + are successes =item * lines beginning with ~ are just warnings =item * lines beginning with - are failures =back =head1 CAVEATS =head2 OPEN FILE HANDLES Be careful that the number of open file handles is limited. Usually 1024 and since 0, 1, 2 (stdin, stdout, stderr) are already open, you have only 1021 maximum connections allowed and upon upper connections the tests will systematically fail. =head2 TIMEOUT The timeout counter for each host begins just after the first connect command. The name resolution is already done so it does not count. But since everything is done in parallel, be carefull that the timeout can come from your proper bandwidth, cpu etc. For example, using the same host on both sides (client and server) and running phttp.monitor with a "-n 19" nice value, the first complete response comes after ~35 secondes and the last after ~55 secondes. All were successful, thanks to Apache. Yes, I demanded the same header page 1021 times and I am not rich (an old Cirix 133 Mega hertz). =head2 DOS Deny Of Service is easy if you have a good tube and a good box. Please, do not use this software for hard war. Be nice. =head1 LICENCE This is GNU PUBLIC LICENCE software =head1 AUTHOR Gilles LAMIRAL lamiral@mail.dotcom.fr =cut require 5.002; # Give me more than five use strict; # use English; # because use French does not work... use Getopt::Long; # way home use Socket; # ou chaussette use POSIX; # or Y use FileHandle; use IO::Select; # No I did not go in a laugh school, I just sucked a clown... use Time::HiRes qw(gettimeofday usleep); $OUTPUT_AUTOFLUSH = 1; my $VERSION = 0.02; my( $help, $debugGeneral, $debugOptions, $debugResolution, $debugCreation, $debugConnection, $debugSelection, $debugWriting, $debugReading, $debugResults, $debugAnalyse, $debugEverything, ); #my $hostname; my( $port, $request, $nbrequests, $inserthost, $timeout, $softimeout, $regex); getoptions(); usage(), exit(0) if ($help); defaultvalues(); my @list = split(/\s+/, join(" ", @ARGV, (" ")) x $nbrequests); #my $iaddr = gethostbyname($hostname); #my @iaddr = unpack('C4', $iaddr); #$debugGeneral and print 'my ip = ', join('.',@iaddr), "\n"; my $proto = getprotobyname('tcp'); #my $paddr = sockaddr_in(0, $iaddr); $debugGeneral and print dump_posix(); $debugGeneral and print "CREATING THE USEFUL DATA\n"; my (%client, %onrace, %offrace, %badrace, %goodrace, %pacerace, %fh2id); my $count = 0; foreach my $host (@list) { $count++; $client{$count}{'host'} = $host; $client{$count}{'success'} = ""; $client{$count}{'problem'} = ""; $onrace{$count}++; } resolve_names(); create_sockets(); first_connection(); write_preparation(); my $readwriteable_handles = new IO::Select(); ($debugGeneral or $debugWriting or $debugReading) and print "SELECTING, WRITING, READING AND CLOSING\n"; # What write my %notconnected = %onrace; ONRACE: while(keys(%onrace)){ my (@new_writeable, @new_readable, @new_errorable); $debugGeneral and print dump_onrace(); my @id = sort { $a <=> $b } keys(%onrace); IDT: foreach my $id (@id) { my $now = gettimeofday; my $begin = $client{$id}{"begin"}; if (($now - $begin) > $timeout) { # game over, baby. $client{$id}{"problem"} .= "- hard timeout reached\n"; $debugConnection and print "hard timeout reached\n"; $client{$id}{"fhandle"}->close(); delete($notconnected{$id}); outrace($id); next IDT; }; } # We have to look if the connection succeeded # before doing IO @id = sort { $a <=> $b } keys(%notconnected); ID: foreach my $id (@id) { my($command) = ""; $command = connect($client{$id}{"fhandle"}, $client{$id}{"hispaddr"}); $debugConnection and print "reconnect host id : $client{$id}{'host'} $id\n"; if (defined($command) and ($command == 1)) { # Linux success $debugConnection and print "reconnect succeeded : [$command]\n"; $client{$id}{"success"} .= "+ reconnect succeeded\n"; delete($notconnected{$id}); $onrace{$id}++; #next ID; } elsif ((not defined($command)) and (($! == EISCONN()))) { # Solaris success $client{$id}{"success"} .= "+ reconnect command succeeded EISCONN : $!\n"; $debugConnection and print "reconnect command succeeded EISCONN : $! ", scalar($! + 0), "\n"; # good and sorry. delete($notconnected{$id}); $onrace{$id}++; #next ID; } elsif ((not defined($command)) and (($! == EALREADY()) or ($! == EAGAIN()))) { #$client{$id}{"problem"} .= "~ reconnect command EALREADY : $!\n"; $debugConnection and print "reconnect command EALREADY : $! ", scalar($! + 0), "\n"; # not so bad, play again. $onrace{$id}++; next ID; } elsif (defined($command) and ($command == -1) and ($! == ETIMEOUT())) { $client{$id}{"problem"} .= "- reconnect command failed ETIMEOUT : $!\n"; $debugConnection and print "reconnect command failed by timeout : $!\n"; $client{$id}{"fhandle"}->close(); delete($notconnected{$id}); outrace($id); next ID; } else { $client{$id}{"problem"} .= "- reconnect command failed : $!\n"; $debugConnection and print "reconnect command failed : $! ", scalar($! + 0), "\n"; if (defined($command)) { $debugConnection and print "command status : $command\n"; }else{ $debugConnection and print "command status : not defined\n"; } $client{$id}{"fhandle"}->close(); $debugConnection and print "deleting $client{$id}{'host'} $id\n"; delete($notconnected{$id}); outrace($id); next ID; } $readwriteable_handles->add($client{$id}{"fhandle"}); $fh2id{$client{$id}{"fhandle"}} = $id; } @new_writeable = $readwriteable_handles->can_write(10); @new_readable = $readwriteable_handles->can_read(2); $debugWriting and print "writeable : ", join (" ", map { $fh2id{$_} } @new_writeable), "\n"; $debugReading and print "readable : ", join (" ", map { $fh2id{$_} } @new_readable), "\n"; WRITE: foreach my $sock (@new_writeable) { my($id, $nleft, $bytes_wrote); $id = $fh2id{$sock}; $nleft = length ($client{$id}{"wbuf"}); next if ($nleft == 0); $debugWriting and print "syswrite to $client{$id}{'host'} $nleft bytes\n"; $bytes_wrote = syswrite ($sock, $client{$id}{"wbuf"}, $nleft); if (defined($bytes_wrote)){ $debugWriting and print "bytes_wrote = $bytes_wrote\n"; if ($bytes_wrote == 0) { # Server close the connexion $readwriteable_handles->remove($sock); $client{$id}{"problem"} .= "- server close the connexion : $!\n"; $debugWriting and print "server close the connexion : $!\n"; $sock->close(); outrace($id); }else{ substr($client{$id}{"wbuf"}, 0, $bytes_wrote) = ""; if (length($client{$id}{"wbuf"}) == 0) { # No more writing $client{$id}{"success"} .= "+ syswrite command succeeded\n"; $debugWriting and print "syswrite command succeeded on $client{$id}{'host'}\n"; #$readwriteable_handles->remove($sock); #$sock->close(); #delete($onrace{$id}); } } }else{ if ($! == EAGAIN()){ $debugWriting and print "EAGAIN\n"; next WRITE; }elsif($! == EINPROGRESS()){ $debugWriting and print "EINPROGRESS\n"; next WRITE; }else{ $debugWriting and print "Do not know what happened : $!\n"; next WRITE; } } } READ: foreach my $sock (@new_readable) { my($id, $buf); $id = $fh2id{$sock}; $buf = <$sock>; if ($buf) { $debugReading and print "reading from $client{$id}{'host'} : ", length($buf), " bytes\n"; $client{$id}{'rbuf'} .= $buf; } else { $debugReading and print "reading from $client{$id}{'host'} : ", 0, " bytes\n"; $readwriteable_handles->remove($sock); $sock->close(); delete($onrace{$id}); finishrace($id); } } usleep (100000); } analyse_race(); $debugResults and dump_final(); summary(); details(); exit 1 if scalar(%badrace); exit 0; # burk ! ################################################################################ ################################## END OF MAIN ################################# ################################################################################ sub getoptions { GetOptions( "help" => \$help, "Dopt" => \$debugOptions, "Dgen" => \$debugGeneral, "Dres" => \$debugResolution, "Dcre" => \$debugCreation, "Dcon" => \$debugConnection, "Dsel" => \$debugSelection, "Dwri" => \$debugWriting, "Drea" => \$debugReading, "Dana" => \$debugAnalyse, "Dfin" => \$debugResults, "Dall" => \$debugEverything, "port=i" => \$port, "nbrequests=i" => \$nbrequests, "request=s" => \$request, "inserthost!" => \$inserthost, "timeout=i" => \$timeout, "softimeout=i" => \$softimeout, "regex=s" => \$regex, # "hostname=s" => \$hostname, ); } sub defaultvalues { $port = defined($port) ? $port : 80; $request = defined($request) ? $request : 'HEAD / HTTP/1.0\nUser-Agent: phttp.monitor\r\n\r\n'; # Thanks so much Larry Wall ! finger in the nose. $request =~ s!\Q\n!\n!g ; $request =~ s!\Q\r!\r!g ; $nbrequests = defined($nbrequests) ? $nbrequests : 1; $inserthost = defined($inserthost) ? $inserthost : 1; $timeout = defined($timeout) ? $timeout : 20; $softimeout = defined($softimeout) ? $softimeout : $timeout; $regex = defined($regex) ? $regex : '^HTTP/([\d\.]+)\s+200\b'; $debugOptions = 1, $debugGeneral = 1, $debugCreation = 1, $debugResolution = 1, $debugConnection = 1, $debugSelection = 1, $debugWriting = 1, $debugReading = 1, $debugResults = 1, $debugAnalyse = 1 if ($debugEverything); $debugOptions and print dump_options(); sub dump_options { # Why I wrote a function for this? # Silly ! my (@dump); push (@dump, "port = $port", "\n", "request = $request", "\n", "nbrequests = $nbrequests", "\n", "inserthost = $inserthost", "\n", "timeout = $timeout", "\n", "softimeout = $softimeout", "\n", "regex = $regex", "\n", ); return (@dump); } } sub usage { print < : the http port to connect to. default is 80. --request : the request send to the servers. default is HEAD / HTTP/1.0\\nUser-Agent: phttp.monitor\\n\\n CAVEAT: Do not forget to quote the string. enable -Dopt to see what you really input. You can use \\n to mean newline. --(no)inserthost : insert individual hostname and port in the HTTP request. really usefull with virtual servers. default is on. If you do not want this feature, use --noinserthost --nbrequests : number of requests to do per host do not use it to make DOS attack, please. default is 1. --timeout : time out for any connection. do not forget that all is done in parallel and may that timeout can come from bandwith, cpu usage, etc. default is 20. --softimeout : soft timeout for any connection. the connection will not be interupted when the soft timeout is reached but the test will fail. default is <--timeout> --regex : regular expression to match for a good http response. default is : ^HTTP/([\\d\\.]+)\\s+200\\b CAVEAT: Do not forget to quote the string. enable -Dopt to see what you really input. --Dgen : print general debug information. --Dopt : print option and variables values. --Dres : print debug information on name resolution. --Dcre : print debug information on non blocking socket creation. --Dcon : print debug information on socket connection. --Dsel : print debug information on selecting socket. --Dwri : print debug information on writing socket. --Drea : print debug information on reading socket. --Dana : print debug information on analysing results. --Dfin : print debug information on final results. --Dall : print all debug information. ARGUMENTS host1 host2 ... : list of host to check DEFAULT with no option, the default behavior is exactly like the command: $0 \\ --port=80 \\ --nbrequests=1 \\ --request='HEAD / HTTP/1.0\\r\\nUser-Agent: phttp.monitor\\r\\n\\r\\n' \\ --inserthost \\ --timeout=20 \\ --softimeout=20 \\ --regex='^HTTP/([\\d\\.]+)\\s+200\\b' EOF } sub write_preparation { my @id = sort { $a <=> $b } keys(%onrace); $debugWriting and print "PREPARING THE WRITE MESSAGES\n"; foreach my $id (@id) { # I did not start to try with real HTTP server ! #my $message = "$id" x 100 . "\n"; my $message = qq!$request!; if ($inserthost) { $message =~ s/\r\n\r\n/\r\nHost: $client{$id}{'host'}\r\n\r\n/; }; $client{$id}{"wbuf"} = $message x 1; $debugWriting and print $client{$id}{"wbuf"}; $client{$id}{"length_to_write"} = length($client{$id}{"wbuf"}); } } sub outrace { my ($id) = @_; $client{$id}{'end'} = gettimeofday; delete($onrace{$id}); $badrace{$id}++; $offrace{$id}++; } sub finishrace { my ($id) = @_; delete($onrace{$id}); $client{$id}{'end'} = gettimeofday; $goodrace{$id}++; } sub first_connection { ($debugGeneral or $debugConnection) and print "ASKING FOR CONNECTIONS\n"; $debugConnection and print dump_onrace(); my @id = sort { $a <=> $b } keys(%onrace); foreach my $id (@id) { my ($command); $debugConnection and printf "%-4s %s\n", $id, $client{$id}{'host'}; $client{$id}{"begin"} = gettimeofday; $command = connect($client{$id}{"fhandle"}, $client{$id}{"hispaddr"}); $debugConnection and print "connect : $!\n"; if ($command or ((not $command) and ($! == EINPROGRESS()))){ # Good in non blocking context $client{$id}{"success"} .= "+ first connect succeeded\n"; $onrace{$id}++; }else{ $client{$id}{"problem"} .= "- first connect failed : [$command] $!\n"; $debugConnection and print "first connect failed : [$command] $!\n"; $client{$id}{"fhandle"}->close(); outrace($id); next; } } } sub resolve_names { ($debugGeneral or $debugResolution) and print "RESOLVING NAMES\n"; $debugResolution and print dump_onrace(); my @id = sort { $a <=> $b } keys(%onrace); foreach my $id (@id) { my ($command, $hisiaddr, $hispaddr); $hisiaddr = inet_aton($client{$id}{'host'}); if (defined($hisiaddr)){ # Good $client{$id}{"success"} .= "+ resolving $client{$id}{'host'} succeeded\n"; $debugResolution and printf "%-4s %20s %-15s\n", $id, $client{$id}{'host'}, join('.', unpack('C4', $hisiaddr)); $onrace{$id}++; }else{ # Bad $client{$id}{"problem"} .= "- could not resolve $client{$id}{'host'}\n"; $debugResolution and printf "%-4s %20s %-15s\n", $id, $client{$id}{'host'}, "...."; # This is just because it fails early. $client{$id}{'begin'} = gettimeofday; outrace($id); next; } $hispaddr = pack_sockaddr_in($port, $hisiaddr); if (defined($hispaddr)){ # Good $client{$id}{"success"} .= "+ pack_sockaddr_in command succeeded\n"; $client{$id}{"hispaddr"} = $hispaddr; $onrace{$id}++; }else{ # Bad $client{$id}{"problem"} .= "- pack_sockaddr_in command failed\n"; $debugConnection and print "pack_sockaddr_in command failed\n"; $client{$id}{"fhandle"}->close(); outrace($id); next; } } } sub create_sockets { ($debugGeneral or $debugCreation) and print "CREATING THE NON-BLOCKING SOCKETS\n"; $debugCreation and print dump_onrace(); my @id = sort { $a <=> $b } keys(%onrace); foreach my $id (@id) { my $command; $client{$id}{"fhandle"} = new FileHandle; $client{$id}{"fhandle"}->autoflush(); $command = socket($client{$id}{"fhandle"}, PF_INET, SOCK_STREAM, $proto); if (defined($command)) { if ($command != 0){ # Good $client{$id}{"success"} .= "+ socket command succeeded\n"; $debugCreation and print "socket command succeeded $id -> $client{$id}{'host'}\n"; $onrace{$id}++; }else { # Bad $client{$id}{"problem"} .= "- socket command failed [$command] $!\n"; $debugCreation and print "socket command failed $id -> $client{$id}{'host'} [$command] $!\n"; $client{$id}{"fhandle"}->close(); # This is just because it fails early. $client{$id}{'begin'} = gettimeofday; outrace($id); next; } }else{ # Bad $client{$id}{"problem"} .= "- socket command failed [undef] $!\n"; $debugCreation and print "socket command failed $id -> $client{$id}{'host'} [undef] $!\n"; $client{$id}{"fhandle"}->close(); # This is just because it fails early. $client{$id}{'begin'} = gettimeofday; outrace($id); next; } $command = fcntl($client{$id}{"fhandle"}, F_SETFL(), O_NONBLOCK); if ($command == 0){ # Good $client{$id}{"success"} .= "+ fcntl command succeeded\n"; $onrace{$id}++; }else{ # Bad $client{$id}{"problem"} .= "- fcntl command failed $!\n"; $debugCreation and print "fcntl command failed $!\n"; $client{$id}{"fhandle"}->close(); # This is just because it fails early. $client{$id}{'begin'} = gettimeofday; outrace($id); next; } } } sub dump_posix { my (@dump); push (@dump, "eagain = ", EAGAIN(), "\n", "einprogress = ", EINPROGRESS(), "\n", "etimeout = ", ETIMEDOUT(), "\n", "ealready = ", EALREADY(), "\n", "eisconn = ", EISCONN(), "\n", ); return (@dump); } sub dump_onrace { my @dump; push (@dump, "ONRACE : ", join(" ", sort { $a <=> $b } keys(%onrace)), "\n", ); return @dump; } sub dump_final { print "-" x 0, "\n" x 0, "-" x 36, " RESULTS ", "-" x 35, , "\n", ; print "SUCCESS : ", join (" ", sort map { "$client{$_}{'host'}" . "(" . int($client{$_}{'end'} - $client{$_}{'begin'} + 0.5) . ")" } keys(%pacerace)), "\n"; print "FAILED : ", join (" ", sort map { "$client{$_}{'host'}" . "(" . int($client{$_}{'end'} - $client{$_}{'begin'} + 0.5) . ")" } keys(%badrace)), "\n"; print "-" x 80, "\n"; } sub analyse_race { $debugGeneral and print "ANALYSING RESPONSES\n"; foreach my $id (sort { $a <=> $b } keys(%goodrace)) { my $rbuf= $client{$id}{'rbuf'} || undef; my $host = $client{$id}{'host'}; my $timeresponse = $client{$id}{'end'} - $client{$id}{'begin'}; $debugAnalyse and print "$host response in $timeresponse s :\n$rbuf"; if ($rbuf =~ m~$regex~) { $client{$id}{"success"} .= "+ match the pattern expected\n"; my $end = $client{$id}{'end'}; my $begin = $client{$id}{'begin'}; if (($end - $begin) > $softimeout) { # game over, baby. $client{$id}{"problem"} .= "- soft timeout reached\n"; $debugAnalyse and print "soft timeout reached\n"; $badrace{$id}++; } else{ $pacerace{$id}++; }; }else{ $client{$id}{"problem"} .= "couldn't match the regexp \"$regex\"\n"; $client{$id}{"problem"} .= "in the response below:\n\n$rbuf\n"; $badrace{$id}++; } } } sub summary { my @summary; $debugGeneral and print "SUMARY LINE :\n"; return unless (scalar(%badrace)); foreach my $id (sort { $client{$::a}{'host'} cmp $client{$::b}{'host'} || ($client{$::a}{'end'} - $client{$::a}{'begin'}) <=> ($client{$::b}{'end'} - $client{$::b}{'begin'}) || $::a <=> $::b } keys(%badrace)) { push(@summary, "$client{$id}{'host'}" . "(" . int($client{$id}{'end'} - $client{$id}{'begin'} + 0.5) . ")" ) ; } print join (" ", @summary), "\n" x 1; return; # The first I wrote (it works, of course) # the sorting is alphabetic print join (" ", sort map { "$client{$_}{'host'}" . "(" . int($client{$_}{'end'} - $client{$_}{'begin'} + 0.5) . ")" } keys(%badrace)), "\n" x 2; } sub details { $debugGeneral and print "DETAILS :\n"; foreach my $id (sort { $client{$::a}{'host'} cmp $client{$::b}{'host'} || $::a <=> $::b } keys(%badrace)) { print "\nDetail for id:$id -> $client{$id}{'host'}(", int($client{$id}{'end'} - $client{$id}{'begin'} + 0.5), ")\n", $client{$id}{'success'}, $client{$id}{'problem'}, ; } } etbemon-1.3.6/mon.d/ping.monitor0000755000000000000000000000376313135637176013451 0ustar #!/bin/bash # # Return a list of hosts which not reachable via ICMP echo # # Jim Trocki, trockij@arctic.org # # $Id: ping.monitor,v 1.2 2005/04/17 07:42:27 trockij Exp $ # # Copyright (C) 1998, Jim Trocki # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # TEMP=$(getopt -o c:6 -n "$0" -- "$@") if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi # Note the quotes around `$TEMP': they are essential! eval set -- "$TEMP" COUNT=1 IPV6="" while true ; do case "$1" in -c) COUNT="$2" shift 2 ;; -6) IPV6="6" shift ;; --) shift break ;; *) echo "Options parse error: $1" exit 1 ;; esac done plat=`uname` p=`which ping` if [ ! -x "$p" ] then echo ping.monitor error, could not find ping exit 1 fi if [ "$#" = 0 ] then echo ping: no hosts found exit 1 fi case "$plat" in Linux) PING="ping$IPV6 -c $COUNT" ;; SunOS) PING="/usr/sbin/ping$IPV6" ;; NetBSD|OpenBSD) PING="/sbin/ping$IPV6 -c $COUNT" ;; *) echo "unknown plat <$plat>" exit 1 ;; esac failed="" for h in "$@" do if $PING $h >/dev/null 2>/dev/null 0); exit 1; sub pop3GET { use Socket; use Sys::Hostname; my($Server, $Port) = @_; my($ServerOK, $TheContent); $ServerOK = 0; $TheContent = ''; $Path = '/'; ############################################################### eval { local $SIG{ALRM} = sub { die "Timeout Alarm" }; alarm $TIMEOUT; $result = &OpenSocket($Server, $Port); # Open a connection to the server if ($result == 0) { # Failure to open the socket return ''; } $in = ; if ($in !~ /^\+OK/) { alarm 0; return 0; } print S "quit\r\n"; $in = ; if ($in !~ /^\+OK/) { alarm 0; return 0; } $ServerOK = 1; close(S); alarm 0; # Cancel the alarm }; if ($EVAL_ERROR and ($EVAL_ERROR =~ /^Timeout Alarm/)) { push(@details, "$host: timeout($TIMEOUT)\n"); return 0; } return $ServerOK; } sub OpenSocket { # # Make a Berkeley socket connection between this program and a TCP port # on another (or this) host. Port can be a number or a named service # local($OtherHostname, $Port) = @_; local($OurHostname, $sockaddr, $name, $aliases, $proto, $type, $len, $ThisAddr, $that); $OurHostname = &hostname; ($name, $aliases, $proto) = getprotobyname('tcp'); ($name, $aliases, $Port) = getservbyname($Port, 'tcp') unless $Port =~ /^\d+$/; ($name, $aliases, $type, $len, $ThisAddr) = gethostbyname($OurHostname); ($name, $aliases, $type, $len, $OtherHostAddr) = gethostbyname($OtherHostname); if (!defined $OtherHostAddr) { push (@details, "$host: cannot resolve hostname\n"); return undef; } my $that = sockaddr_in ($Port, $OtherHostAddr); if (! ($result = socket(S, &PF_INET, &SOCK_STREAM, $proto)) || (! ($result = connect(S, $that))) ) { push (@details, "$host: $!\n"); return undef; } select(S); $| = 1; select(STDOUT); # set S to be un-buffered return 1; # success } etbemon-1.3.6/mon.d/process.monitor0000755000000000000000000000552213135636631014160 0ustar #!/usr/bin/perl # # Monitor snmp processes # # Arguments are: # # [-c community] host [host ...] # # This script will exit with value 1 if host:community has prErrorFlag # set. The summary output line will be the host names that failed # and the name of the process. The detail lines are what UCD snmp returns # for an prErrMessage. ('Too (many|few) (name) running (# = x)'). # If there is an SNMP error (either a problem with the SNMP libraries, # or a problem communicating via SNMP with the destination host), # this script will exit with a warning value of 2. # # There probably should be a better way to specify a given process to # watch instead of everything-ucd-snmp-is-watching. # # $Id: process.monitor,v 1.1.1.1.4.1 2007/04/26 10:39:55 trockij Exp $ # # # Copyright (C) 1998, Brian Moore # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # use Mon::SNMP; use Getopt::Std; $ENV{'MIBS'} = "UCD-SNMP-MIB"; getopts("c:"); $community = $opt_c || 'public'; $RETVAL = 0; foreach $host (@ARGV) { $session = new SNMP::Session(DestHost => $host, Version => 2, Community => $community); if (!defined ($session)) { $RETVAL = ($RETVAL == 1) ? 1 : 2; push @failures, "$host session error"; push @longerr, "$host could not get SNMP session"; next; } my $v = new SNMP::Varbind (["prIndex"]); $session->getnext ($v); while (!$session->{"ErrorStr"} && $v->tag eq "prIndex") { my @q = $session->get ([ ["prNames", $v->iid], ["prMin", $v->iid], ["prMax", $v->iid], ["prCount", $v->iid], ["prErrorFlag", $v->iid], ["prErrMessage", $v->iid], # ["prErrFix", $v->iid], ]); last if ($session->{"ErrorStr"}); if ($q[4] > 0) { $RETVAL = 1; push (@failures, $host); push (@longerr, "$host: count=$q[3] min=$q[1] max=$q[2] err=$q[5]"); } $session->getnext ($v); } if ($session->{"ErrorStr"}) { push (@failures, $host); push (@longerr, "$host returned an SNMP error: " . $session->{"ErrorStr"}); $RETVAL = 1; } } if (@failures) { print join (", ", sort @failures), "\n", "\n"; print join ("\n", @longerr), "\n"; } exit $RETVAL; etbemon-1.3.6/mon.d/radius.monitor0000755000000000000000000001020313135636556013767 0ustar #!/usr/bin/perl # # Monitor radius processes # # Based upon radius.monitor by Brian Moore, posted to the mon mailing list # # Arguments are: # # --username=user --password=pass --secret=secret # [--port=#] [--attempts=#] [--dictionary=/path/to/dictionary] # hostname [hostname ...] # # Arguments are in standard POSIX format and can be given as the least # significant part (i.e. -p is the same as --password). # # This monitor performs a real RADIUS check, attempting to be as much like a # terminal server as possible. This requires that you include a username, # password, and secret in your mon.cf file. Depending on your unix # implementation, this may allow unscrupulous users to view the command line # arguments, including your RADIUS secret. If you prefer, you can uncomment # three lines below (see comments) to provide defaults for username, # password, and secret. # # This monitor attempts to check a username and password up to n times # (defaults to 9, but can be set via the --attempts=# command line switch). # It only registers a failure to mon after failing to receive a satisfactory # response n times. It returns an immediate failure to mon if it receives a # failed authentication. For this reason, you will need to create a dummy # user on your RADIUS server for authentication testing. # # # Copyright (C) 1998, ACC TelEnterprises # Written by James FitzGibbon # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # use Authen::Radius; use Sys::Hostname; use Getopt::Long; GetOptions( \%options, "port=i", "secret=s", "username=s", "password=s", "attempts=i", "dictionary=s" ); $options{"port"} ||= 1645; $options{"attempts"} ||= 9; # # uncomment these three lines and replace with appropriate info if you'd prefer # not to pass sensitive information on the command line # # the correct solution is to store them in a file in /var/lib/mon, should fix # this # $options{"username"} ||= "username"; $options{"password"} ||= "password"; $options{"secret"} ||= "radius-secret"; $options{"dictionary"} ||= "/etc/radius/dictionary"; Authen::Radius->load_dictionary( $options{dictionary} ); undef $diag; @failed_hosts = (); foreach $host (@ARGV) { $auth = new Authen::Radius(Host => "$host:$options{port}", Secret => $options{secret} ); $auth->add_attributes( { Name => "User-Name", Value => $options{username} }, { Name => "Password", Value => $options{password} }, { Name => "NAS-IP-Address", Value => join( ".", unpack ( "C4", (gethostbyname( hostname() ))[4] ) ) }, ); $done = 0; $attempts = 0; while( ! $done ) { $auth->send_packet( ACCESS_REQUEST ); $err = $auth->get_error(); if( $err ne "ENONE" ) { $attempts++; if( $attempts > $options{attempts} ) { push @failed_hosts, $host; push( @failures, "$host failed for user $options{username}: " . $auth->strerror( $err ) ); $done = 1; } next; } $resptype = $auth->recv_packet(); $err = $auth->get_error(); if( $err ne "ENONE" ) { $attempts++; if( $attempts > $options{attempts} ) { push @failed_hosts, $host; push( @failures, "$host failed for user $options{username}: " . $auth->strerror( $err ) ); $done = 1; } } elsif( $resptype == ACCESS_REJECT ) { push @failed_hosts, $host; push( @failures, "$host returned bad auth for user $options{username}" ); $done = 1; } else { $done = 1; } } } if (@failed_hosts) { print "@failed_hosts\n\n"; print join (", ", @failures), "\n"; exit 1; }; exit 0; etbemon-1.3.6/mon.d/rd.monitor0000755000000000000000000001140010061516614013070 0ustar #!/usr/bin/perl # readdir.monitor # Return a list of directories that contains more than given files numbers # For use with "mon" or stand alone. # # # Usage : my-mailqueue.monitor [options] [dir1[:num1] dir2[:num2] ...] # # --number n : the maximum file number allowed # --regex string : a regex expression to match # --debug : print some debug information (do not use this with mon) # but just in command line to understand everything :-) # dir1 dir2 : list of directory to check # Examples: # # Do nothing (nothing to check) # $ ./my-readdir.monitor # # Checks if: # /var/spool/mqueue contains more than 50 files (50 is a default value) # # $ ./my-readdir.monitor /var/spool/mqueue/ # # Checks if: # /var/spool/mqueue contains more than 14 files # # $ ./my-readdir.monitor /var/spool/mqueue/:14 # # Check if : # /var/spool/mqueue contains more than 14 files # /var/spool/lp/requests contains more than 7 files # # $ ./my-readdir.monitor /var/spool/mqueue/:14 /var/spool/lp/requests:7 # # Check if : # /var contains more than 34 files # /var/spool contains more than 34 files # /bin contains more than 65 files # # $ ./my-readdir.monitor --number=34 /var /var/spool /bin:65 # # Check if : # /var/spool/mqueue contains more than 3 files which name # begins with "df" # # $ ./my-readdir.monitor --number=3 --regex "^df" /var/spool/mqueue # # The regex can be every perl regex. # this program exits with the $maxlogNumberFound in log based 2 fashion. # file number found = 1 * number Allowed, log = 1 # file number found = 2 * number Allowed, log = 2 # file number found = 4 * number Allowed, log = 3 # . # . # . # 2^n * $numberAllowed, log = n+1 # # Reverse: # if the return status is N, that means that the directories # contains more (or equal) than 2^(N-1) * allowed files number # and less than 2^N * allowed files number # The worse situation is return (in case of several directories) # # Gilles LAMIRAL, lamiral@mail.dotcom.fr # # # Copyright (C) 1998, Gilles LAMIRAL # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA # use Getopt::Long; use DirHandle; GetOptions( "number:i" => \$globalNumberAllowed, "debug" => \$debug, "regex:s" => \$regex ); $globalNumberAllowed = ($globalNumberAllowed) ? $globalNumberAllowed : "50"; @failures = (); $maxlogNumberFound = 0; foreach $dir (@ARGV) { my ($dirHandle, @filesList, @filesListFiltered, $numberFound); ($dir, $numberAllowed) = split (/:/, $dir, 2); $numberAllowed = ($numberAllowed) ? $numberAllowed : $globalNumberAllowed; ($debug) and print "directory checked : $dir\n"; ($debug) and print " number of file allowed : $numberAllowed\n"; $dirHandle = new DirHandle "$dir"; if (defined $dirHandle) { # reads the directory and filters "." and ".." files @filesList = grep !/^\.\.?$/, $dirHandle->read(); $dirHandle->close(); if ($regex) { foreach $file (@filesList) { push(@filesListFiltered, $file) if ($file =~ /$regex/); } @filesList = @filesListFiltered; } $numberFound = scalar(@filesList); #($debug) and print "@filesList\n"; ($debug) and print " number of files : $numberFound\n"; if ($numberFound >= $numberAllowed) { push (@failures, sprintf ("%s:%s", $dir, $numberFound)); $logNumberFound = 1+(log($numberFound / $numberAllowed)/log(2)); ($debug) and print " 1+(log($numberFound/$numberAllowed)/log(2)) = ", $logNumberFound,"\n"; if ($logNumberFound > $maxlogNumberFound) { $maxlogNumberFound = $logNumberFound; } } }else{ warn "Could not open $dir : $!\, warn at"; push (@failures, sprintf ("%s:%s", $dir, "COULD_NOT_OPEN")); }; } if (@failures == 0) { exit 0; } ($debug) and print "\nSummary:"; print join (" ", sort @failures), "\n"; if ($maxlogNumberFound >= 1) { ($debug) and print "maxlogNumberFound (exit status) =$maxlogNumberFound\n"; $exitStatus = int($maxlogNumberFound); }else{ $exitStatus = 1; } exit($exitStatus); etbemon-1.3.6/mon.d/reboot.monitor0000755000000000000000000001174413135636631013777 0ustar #!/usr/bin/perl -w # # monitor host reboots via SNMP # # for use with "mon" # # options: # # reboot.monitor --statefile=filename --dir=dir [--community=com] host1 host2... # # Since this is scheduled from mon, it must maintain state between # runs. It uses the "statefile" for this, in which it stores a # sysUpTime sample for each host specified on the command line. # # THIS STATE FILE MUST NOT BE SHARED BETWEEN MULTIPLE INSTANCES OF THIS # MONITOR, SINCE IT DOES NOT HANDLE LOCKING OF THE FILE DURING UPDATES!! # # Jim Trocki # # $Id: reboot.monitor,v 1.2 2004/11/15 14:45:19 vitroth Exp $ # # Copyright (C) 1998, Jim Trocki # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # modified June 2000 by Ed Ravin # changed output to conform with other monitors (just hostname on summary) # minor cosmetic changes (usage, use default Mon state dir) # the old behavior still available with the "--verbose" option use Mon::SNMP; use Getopt::Long; ($ME = $0) =~ s-.*/--; GetOptions (\%opt, "statefile=s", "dir=s", "community=s", "verbose"); $STATEDIR = $opt{"dir"} ? $opt{"dir"} : $ENV{"MON_STATEDIR"} ? $ENV{"MON_STATEDIR"} : die "$ME: --dir not specified and \$MON_STATEDIR not set\n"; $STATEFILE = $opt{"statefile"} || $ME; $STATE = "$STATEDIR/$STATEFILE"; $COMM = $opt{"community"} || "public"; die "$ME: reboot state dir $STATEDIR does not exist\n" if (! -w $STATEDIR); $VERBOSE= $opt{"verbose"} || 0; die "$ME: no host arguments\n" if (@ARGV == 0); if (! -f $STATE) { open (O, ">$STATE"); close (O); } # # read in state file # if (!open (IN, "$STATE")) { die "$ME: could not open state file $STATE\n"; } while (defined ($host = )) { if ($host =~ /^(\S+) (\d+) (\d+)/) { $last_sample{$1}{"uptime"} = $2; $last_sample{$1}{"lastcheck"} = $3; } } close (IN); # # get uptime for each host via SNMP # @failures = (); foreach $host (@ARGV) { if (!defined($s = new SNMP::Session (DestHost => $host, Community => $COMM, "Version" => 2))) { print "reboot.monitor: cannot create SNMP session to $host\n"; next; } if (!defined($u = $s->get("sysUpTime.0"))) { next; } # # If the uptime is lower than the last sample, # assume this is a reboot. Note that this cannot # account for counter rollover! # # # no history for this # if (!defined $last_sample{$host}{"uptime"}) { } elsif ($last_sample{$host}{"uptime"} < 2**32 - (120 * 60 * 100) && $u < $last_sample{$host}{"uptime"}) { push (@failures, $host); $last_sample{$host}{"olduptime"} = $last_sample{$host}{"uptime"}; $last_sample{$host}{"oldcheck"} = $last_sample{$host}{"lastcheck"}; } $last_sample{$host}{"uptime"} = $u; $last_sample{$host}{"lastcheck"} = time; } # # update state file # if (!open (OUT, ">$STATE")) { die "$ME: could not open $STATEFILE for writing: $!\n"; } foreach $k (sort keys %last_sample) { print OUT "$k $last_sample{$k}{uptime} $last_sample{$k}{lastcheck}\n"; } close (OUT); # # all is OK, nobody has rebooted # if (@failures == 0) { exit; } # # we have reboots, so calculate uptime, downtime, # and report it # $t = time; foreach $host (@failures) { $downtime = &secs_to_hms ( $t - $last_sample{$host}{"oldcheck"} - int ($last_sample{$host}{"uptime"} / 100)); $uptime = &secs_to_hms ( int ($last_sample{$host}{"olduptime"} / 100)); if ($VERBOSE) { push (@f, "$host / down $downtime / up $uptime"); } else { push (@f, "$host"); } } @f = sort @f; print "@f\n"; printf ("%-20s %-25s %-25s\n", "host", "rebooted on", "last seen up on"); printf ("%-20s %-25s %-25s\n", "-" x 20, "-" x 25, "-" x 25); $timen = time; foreach $host (@failures) { $secs = int($last_sample{$host}{"uptime"} / 100); $t = localtime ($timen - $secs); $downtime= localtime($last_sample{$host}{"oldcheck"} - ($last_sample{$host}{"uptime"} / 100) ); printf ("%-20s %-25s %-25s\n", $host, $t, $downtime); } exit 1; sub secs_to_hms { my ($s) = @_; my ($dd, $hh, $mm, $ss); $dd = int ($s / 86400); $s -= $dd * 86400; $hh = int ($s / 3600); $s -= $hh * 3600; $mm = int ($s / 60); $s -= $mm * 60; $ss = $s; if ($dd == 0) { sprintf("%02d:%02d", $hh, $mm); } else { sprintf("%d days, %02d:%02d", $dd, $hh, $mm); } } etbemon-1.3.6/mon.d/remote.monitor0000644000000000000000000002360513514461027013770 0ustar #!/usr/bin/perl -w use strict; # # Returns a mon server list that failed services # my $VERSION = "1.2"; sub usage { print < \$port, "timeout|t:i" => \$timeout, "summary" => \$summary, "bigsummary" => \$bigsummary, "failure_duration:i" => \$min_failure_duration, "alerts_sent:i" => \$min_alerts_sent, "debug|d" => \$debug, "help|h" => \$help, "exclude|e:s" => \$exclude, "restrict|r:s" => \$restrict, "passwordfile|:s" => \$passwordfile, ); usage() and exit if ($help); $port = ($port) ? $port : "2583"; $timeout = ($timeout) ? $timeout : "10"; $summary = ($summary) ? $summary : $bigsummary; $min_failure_duration = ($min_failure_duration) ? $min_failure_duration : 0; $min_alerts_sent = ($min_alerts_sent) ? $min_alerts_sent : 1; ($restrict) and ($only_watch,$only_service) = split( /:/, ($restrict) ); ($exclude) and ($never_watch,$never_service) = split( /:/, ($exclude) ); my @failures = (); my %failuresDetails; my @extendsummary = (); my %passwords; if($passwordfile) { open(PASS, "<$passwordfile") or die "Can't open $passwordfile"; while() { chomp; my @arr = split(':', $_); $passwords{$arr[0]}{username} = $arr[1]; $passwords{$arr[0]}{password} = $arr[2]; } close(PASS); } foreach my $host (@ARGV) { my $begin = time; eval { local $SIG{ALRM} = sub { die "Timeout Alarm\n" }; alarm $timeout; &getinfo($host, $port); alarm 0; # Cancel the alarm }; my $end = time; my $timeResponse = $end - $begin; if ($@ and ($@ =~ /^Timeout Alarm/)) { ($debug) and print "Timeout connection\n"; $failuresDetails{${host}} = join("", "Timeout connection"); push (@failures, ${host}); push (@extendsummary, "${host}:TIMEOUT(${timeResponse})"); next; } } if (@failures == 0) { exit 0; } if ($summary) { print "@extendsummary\n\n"; } else { print "@failures\n\n"; } foreach my $host (@failures) { print "Details for $host failure :\n", "$failuresDetails{$host}\n\n"; } # exit with the the error status on. exit(1); sub getinfo { my ($host, $port) = @_; ($debug) and print "testing mon server $host :\n"; my $cl = Mon::Client->new; $cl->host ($host); $cl->port ($port); unless (defined ($cl->connect)) { ($debug) and print "connection failed: ", $cl->error, "\n"; $failuresDetails{${host}} = join("", "Connection failed: ", $cl->error); push (@failures, ${host}); push (@extendsummary, "${host}:CONNECT"); return; }else{ ($debug) and print "connection succeeded\n"; ($debug) and print "host : ", $cl->host, "\n", "port : ", $cl->port, "\n", ; if($passwords{$host}) { unless(defined ($cl->login(%{$passwords{$host}}))) { $failuresDetails{${host}} = join("", "Login failed: ", $cl->error); push (@failures, ${host}); push (@extendsummary, "${host}:LOGIN"); return; } } my %s; %s = $cl->list_opstatus; if($debug) { print "list_opstatus: ", "\n", ; foreach my $item (keys %s) { foreach my $iteminitem (keys %{$s{$item}}) { print "$item: $iteminitem = ( "; foreach my $iteminiteminitem (keys %{$s{$item}{$iteminitem}}) { print "$iteminiteminitem = $s{$item}{$iteminitem}{$iteminiteminitem} "; } print ")\n"; } print "\n"; } } if ($cl->error) { $failuresDetails{${host}} = join("", "list_opstatus failed:", $cl->error); push (@failures, ${host}); push (@extendsummary, "${host}:list_opstatus"); next; } my %d = $cl->list_disabled; ($debug) and print "list_disabled: ", %d, "\n", "error : ", $cl->error ? $cl->error : "none","\n", ; # parsing of %d if ($debug) { print "===\nlist_disabled detail:\n"; while ( my ($category,$pwatch) = each %d ) { while( my ($watch, $pvalue) = each %$pwatch ) { while( my ($value) = each %$pvalue ) { print "$category,$watch,$value\n"; } } } print "end of list_disabled detail\n===\n"; } # error state host flag my($hosterr) = 0; my($hostwatch); ($debug) and print "===\nlist_opstatus detail:\n"; foreach my $watch (sort keys %s) { my $watcherr = 0; my $ext_service = "[$watch:"; next if ( ($only_watch) && !( $watch eq ($only_watch) )); foreach my $service (sort keys %{$s{$watch}}) { my($opstatus); next if ( ($only_service) && !( $service eq ($only_service) )); next if ( ($never_watch) && ( $watch eq ($never_watch) ) && (!$never_service || $service eq ($never_service))); my $alerts_sent = $s{$watch}{$service}{alerts_sent}; my $failure_duration = $s{$watch}{$service}{failure_duration}; next if ($alerts_sent < $min_alerts_sent); next if ($failure_duration < $min_failure_duration); # state service recuperation $opstatus = $s{$watch}{$service}{opstatus}; ($debug) and print "$watch $service opstatus=$opstatus\n"; #if no error (!= 0) then next next if ($opstatus != 0); #if this service is disabled then next next if (defined($d{services}{$watch}{$service})); # at this point we've got a failure so get the last summary my $last_summary = $s{$watch}{$service}{last_summary}; # service failed and not disabled $hosterr++; $watcherr++; ($debug) and print "Watch $watch service $service failed with $alerts_sent alerts for $failure_duration seconds\n"; push (@failures, ${host}) unless (defined($failuresDetails{${host}})); $failuresDetails{${host}} .= "Watch $watch, service $service, failed ". "with summary : ${last_summary}\n"; # save services if ($summary) { if ($bigsummary) { $ext_service .="${service}{${last_summary}}|"; } else { $ext_service .="${service}|"; } } } if ($watcherr) { chop($ext_service); $ext_service .= "]"; $hostwatch .= $ext_service; } } #modification of summary if ($hosterr) { push (@extendsummary, "$host($hostwatch)"); } ($debug) and print "end of list_opstatus detail:\n===\n"; } $cl->disconnect; } etbemon-1.3.6/mon.d/rpc.monitor.c0000644000000000000000000002550010061516614013473 0ustar /* * $Id: rpc.monitor.c,v 1.1.1.1 2004/06/09 05:18:04 trockij Exp $ * * a monitor for RPC services, contains some code from rpcinfo(8) * * Copyright (C) 1986 Sun Microsystems, Inc. * Copyright (C) 1998 Daniel Quinlan * * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape * media and as a part of the software program in whole or part. Users * may copy or modify Sun RPC without charge, but are not authorized * to license or distribute it to anyone else except as part of a product or * program developed by the user. * * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. * * Sun RPC is provided with no support and without any obligation on the * part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC * OR ANY PART THEREOF. * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 */ #if (__svr4__ && __sun__) #define SOLARIS #endif #include #include #include #include #include #include #include #include #ifdef SOLARIS #include #include #endif #include #include #include #include #include #define DEFAULT_TIMEOUT 10 struct failure_ent { char *host; char *reason; struct failure_ent *next; }; struct program_ent { int number; int required; int listed; struct program_ent *next; }; /* function prototypes */ void test_host(char *host); void test_programs (char *host, struct pmaplist *head); void test_failure(char *host, char *reason); void add_program(char *program, int required); void print_failures(); int get_rpc_number(char *program); #ifndef SOLARIS int get_inet_address(struct sockaddr_in *, char *); #endif void usage(); void alarm_nop(); /* global variables */ int opt_all; /* test all registered programs */ int opt_programs; /* test specific programs */ int opt_verbose; /* be verbose */ int timeout; /* host timeout */ char *binary; /* name of this program */ struct program_ent *programs; /* list of programs to test */ struct failure_ent *failures; /* list of test failures */ int main(int argc, char **argv) { int c; /* set defaults for global variables */ opt_all = 0; opt_programs = 0; opt_verbose = 0; timeout = DEFAULT_TIMEOUT; programs = NULL; failures = NULL; binary = strdup(argv[0]); while ((c = getopt(argc, argv, "t:avhp:r:")) != EOF) { switch(c) { case 't': timeout = atoi(optarg); break; case 'a': opt_all = 1; break; case 'p': opt_programs = 1; add_program(optarg, 0); break; case 'r': opt_programs = 1; add_program(optarg, 1); break; case 'v': opt_verbose = 1; break; case 'h': default: usage(); break; } } while (optind < argc) { test_host(argv[optind++]); } if (failures) { print_failures(); exit(1); } exit(0); } void add_program(char *program, int required) { struct program_ent *new, *tmp; new = (struct program_ent *) malloc(sizeof(struct program_ent)); new->number = get_rpc_number(program); new->required = required; new->listed = 0; new->next = NULL; if (opt_verbose) { printf("adding test: %s, %d, %s\n", program, new->number, required ? "required" : "unrequired"); } if (programs == NULL) { programs = new; } else { tmp = programs; while (tmp->next != NULL) { tmp = tmp->next; } tmp->next = new; } } int want_test(int number) { struct program_ent *tmp; tmp = programs; while (tmp != NULL) { if (number == tmp->number) { return 1; } tmp = tmp->next; } return 0; } void test_failure(char *host, char *reason) { struct failure_ent *tmp, *new; /* chomp */ if (reason[strlen(reason) - 1] == '\n') { reason[strlen(reason) - 1] = '\0'; } new = (struct failure_ent *) malloc(sizeof(struct failure_ent)); new->host = strdup(host); new->reason = strdup(reason); new->next = NULL; if (failures == NULL) { failures = new; } else { tmp = failures; while (tmp->next != NULL) { tmp = tmp->next; } tmp->next = new; } } void print_failures() { struct failure_ent *tmp; char *last = NULL; /* print failed hosts, removing consecutive duplicates */ tmp = failures; while (tmp != NULL) { if (!last || strcmp(last, tmp->host)) { printf("%s%s", last ? " " : "", tmp->host); } last = tmp->host; tmp = tmp->next; } printf("\n"); /* print reasons */ tmp = failures; while (tmp != NULL) { printf("%s: %s\n", tmp->host, tmp->reason); tmp = tmp->next; } } void test_host(char *host) { struct pmaplist *head = NULL; struct timeval tv; CLIENT *client; #ifndef SOLARIS struct sockaddr_in addr; int socket = RPC_ANYSOCK; #endif tv.tv_sec = timeout; tv.tv_usec = 0; #ifdef SOLARIS if ((client = clnt_create_timed(host, PMAPPROG, PMAPVERS, "tcp", &tv)) == NULL) { #else if (! get_inet_address(&addr, host)) { test_failure(host, "gethostbyname failed"); return; } addr.sin_port = htons(PMAPPORT); signal(SIGALRM, alarm_nop); alarm(timeout); if ((client = clnttcp_create(&addr, PMAPPROG, PMAPVERS, &socket, 0, 0)) == NULL) { alarm(0); #endif test_failure(host, clnt_spcreateerror("clnttcp_create failed")); return; } #ifndef SOLARIS alarm(0); #endif clnt_control(client, CLSET_TIMEOUT, (char *) &tv); if (clnt_call(client, PMAPPROC_DUMP, (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_pmaplist, (char *) &head, tv) != RPC_SUCCESS) { test_failure(host, clnt_sperror(client, "clnt_call failed")); clnt_destroy(client); return; } if (head == NULL) { test_failure(host, "no remote programs registered"); clnt_destroy(client); return; } if (opt_all || opt_programs) { test_programs(host, head); } clnt_destroy(client); } void test_programs (char *host, struct pmaplist *head) { struct timeval tv; CLIENT *tclient; struct protoent *proto; char failtext[80]; int testing; struct rpcent *rpc; struct program_ent *ptmp; tv.tv_sec = timeout; tv.tv_usec = 0; if (opt_verbose) printf("testing host program vers proto port\n"); /* reset listed flag */ for (ptmp = programs; ptmp != NULL; ptmp = ptmp->next) ptmp->listed = 0; for (; head != NULL; head = head->pml_next) { proto = getprotobynumber(head->pml_map.pm_prot); rpc = getrpcbynumber(head->pml_map.pm_prog); testing = (opt_all || want_test(head->pml_map.pm_prog)); for (ptmp = programs; ptmp != NULL; ptmp = ptmp->next) if (head->pml_map.pm_prog == ptmp->number) ptmp->listed = 1; if (opt_verbose) { printf("%-7s", testing ? "true" : "false"); printf("%10s%10ld%5ld", host, head->pml_map.pm_prog, head->pml_map.pm_vers); if (proto) printf("%6s", proto->p_name); else printf("%6ld", head->pml_map.pm_prot); printf("%7ld", head->pml_map.pm_port); if (rpc) printf(" %s\n", rpc->r_name); else printf("\n"); } if (!testing) continue; if (!proto) { fprintf(stderr, "%s: %ld: unknown protocol\n", binary, head->pml_map.pm_prot); exit(1); } #ifdef SOLARIS if ((tclient = clnt_create_timed(host, head->pml_map.pm_prog, head->pml_map.pm_vers, proto->p_name, &tv)) == NULL) { #else signal(SIGALRM, alarm_nop); alarm(timeout); if ((tclient = clnt_create(host, head->pml_map.pm_prog, head->pml_map.pm_vers, proto->p_name)) == NULL) { alarm(0); #endif if (rpc) snprintf(failtext, 80, "clnt_create failed: %s/%s/v%ld", rpc->r_name, proto->p_name, (long)head->pml_map.pm_vers); else snprintf(failtext, 80, "clnt_create failed: %ld/%s/v%ld", head->pml_map.pm_prog, proto->p_name, (long)head->pml_map.pm_vers); test_failure(host, clnt_spcreateerror(failtext)); continue; } else { #ifndef SOLARIS alarm(0); #endif clnt_control(tclient, CLSET_TIMEOUT, (char *) &tv); if (clnt_call(tclient, NULLPROC, (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_void, NULL, tv) != RPC_SUCCESS) { if (rpc) snprintf(failtext, 80, "clnt_call failed: %s/%s/v%ld", rpc->r_name, proto->p_name, (long)head->pml_map.pm_vers); else snprintf(failtext, 80, "clnt_call failed: %ld/%s/v%ld", head->pml_map.pm_prog, proto->p_name, (long)head->pml_map.pm_vers); test_failure(host, clnt_sperror(tclient, failtext)); clnt_destroy(tclient); continue; } clnt_destroy(tclient); } } /* did we find everything we want to require? */ for (ptmp = programs; ptmp != NULL; ptmp = ptmp->next) { if (ptmp->required && ptmp->listed == 0) { rpc = getrpcbynumber(ptmp->number); if (rpc) snprintf(failtext, 80, "RPC program not registered: %s", rpc->r_name); else snprintf(failtext, 80, "RPC program not registered: %d", ptmp->number); test_failure(host, failtext); } } } int get_rpc_number(char *program) { struct rpcent *rpc; if (isalpha(*program)) { rpc = getrpcbyname(program); if (!rpc) { fprintf(stderr, "%s: %s: unknown RPC program\n", binary, program); exit(1); } return(rpc->r_number); } else { return(atoi(program)); } } #ifndef SOLARIS int get_inet_address(struct sockaddr_in *addr, char *host) { struct hostent *hp; bzero((char *) addr, sizeof *addr); addr->sin_addr.s_addr = (unsigned long) inet_addr(host); if (addr->sin_addr.s_addr == -1 || addr->sin_addr.s_addr == 0) { if ((hp = gethostbyname(host)) == NULL) { return(0); } bcopy(hp->h_addr, (char *)&addr->sin_addr, hp->h_length); } addr->sin_family = AF_INET; return(1); } #endif void usage () { printf( "Usage: %s [options] host [host...]\n" " -t n host timeout in seconds (%d seconds is the default)\n" " -a test all registered programs with RPC null procedure\n" " -p program test program (either a name or number) if registered with\n" " RPC null procedure, multiple -p flags may be specified\n" " -r program same as \"-p\", except fail if program is not registered\n" " -v verbose mode\n", binary, DEFAULT_TIMEOUT); exit(0); } void alarm_nop() { return; } etbemon-1.3.6/mon.d/seq.monitor0000755000000000000000000000343310230411543013253 0ustar #!/bin/sh # # This is for testing mon during development. # # Call this script with $1 set to a directory, and # $2 set to some text tag, # usually the name of the service you're testing. # # Put a file in $1 called "$1.seq", which is a space # separated list of words. On consecutive calls to # this script, the next word will be interpreted. # # If the word is "0" then this script exits with success. # # Otherwise, echo the word and exit with a failure # # You probably want to "rm -f $1/$2.count" the first # time you run this. # # Jim Trocki, trockij@arctic.org # # $Id: seq.monitor,v 1.2 2005/04/17 07:42:27 trockij Exp $ # # Copyright (C) 1998, Jim Trocki # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # path=$1 id=$2 if [ -f "$path/$id.count" ] then count=`cat $path/$id.count` else count=0 fi if [ ! -d "$path" ] then echo "$path" not found exit 1 fi seq=`cat $path/$id.seq` set -- $seq max=$# if [ "$count" = "$max" ] then count=0 else shift $count fi echo `expr $count + 1` > $path/$id.count if [ "$1" = 0 ] then echo "success" exit 0 else echo "failure:$1" exit 1 fi etbemon-1.3.6/mon.d/silkworm.monitor0000755000000000000000000001503513135636631014351 0ustar #!/usr/bin/perl # # "mon" monitor to detect thermal/fan/psu/port failures # for brocade silkworm fcal switches # # arguments are "[-c community] host [host...]" # # -c community SNMP community # # Jim Trocki # # $Id: silkworm.monitor,v 1.1.1.1 2004/06/09 05:18:05 trockij Exp $ # # Copyright (C) 2000, Jim Trocki # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # use Mon::SNMP; use Getopt::Std; use strict; sub get_status; sub get_table; sub get_vars; sub fancy_psu_table; $ENV{"MIBS"} = "RFC1213-MIB:SW-MIB"; my %opt; getopts ('c:', \%opt); my $COMM = $opt{"c"} || "public"; my @failures = (); my $detail; my %sensors; my %ports; my %opstatus; foreach my $host (@ARGV) { my %status = get_status ($host, $COMM); if ($status{"error"} ne "") { push (@failures, $host); $detail .= "could not retrieve status from $host: $status{error}\n\n"; next; } elsif ($status{"failure"}) { push (@failures, $host); $detail .= $status{"failure_summary"}; } $sensors{$host} = $status{"sensor_table"}; $ports{$host} = $status{"port_table"}; $opstatus{$host} = $status{"operstatus"}; } # # output returned to mon # if (@failures != 0) { print join (" ", sort @failures), "\n"; print "$detail\n"; } else { print "\n"; } print <{"swSensorValue"}; $val = "unknown" if ($val == -2147483648); printf ("%-20s %-12s %-9s %-10s %s\n", $host, $r->{"swSensorType"}, $r->{"swSensorStatus"}, $val, $r->{"swSensorInfo"}, ); } print "\n"; } print <{"swFCPortIndex"}, $r->{"swFCPortType"}, $r->{"swFCPortAdmStatus"}, $r->{"swFCPortPhyState"}, $r->{"swFCPortOpStatus"}, $r->{"swFCPortLinkState"}, ); } print "\n"; } exit 1 if (@failures != 0); exit 0; # # params: (hostname, community) # # returns: # ( # "error" => "error name, empty string means no error", # ) # sub get_status { my ($host, $comm) = @_; my $s; if (!defined ($s = new SNMP::Session ( "DestHost" => $host, "Community" => $comm, "Version" => 2, "UseEnums" => 1, ))) { return ("error" => "cannot create session"); } my $error; my $failure_detected = 0; my $failure_summary = ""; my $sensor_table; my $port_table; my $operstatus; # # is this really a brocade fcal switch? # my $sys_oid = $s->get (["sysObjectID", 0]); return ("error" => $s->{"ErrorStr"}) if ($s->{"ErrorStr"} ne ""); return ("error" => "not Brocade fiberchannel switch") if ($sys_oid !~ /^\.1\.3\.6\.1\.4\.1\.1588\.2\.1\.1\.[12]/); # # operational status # if (!defined ($operstatus = $s->get ("swOperStatus.0"))) { return ("error" => "$s->{ErrorStr}"); } $failure_detected++ if ($operstatus ne "online"); # # sensor table # ($error, $sensor_table) = get_table ($s, ["swSensorType"], ["swSensorStatus"], ["swSensorValue"], ["swSensorInfo"], ); return ("error" => $error) if ($error ne ""); # # port table # ($error, $port_table) = get_table ($s, ["swFCPortIndex"], ["swFCPortType"], ["swFCPortPhyState"], ["swFCPortOpStatus"], ["swFCPortAdmStatus"], ["swFCPortLinkState"], ); return ("error" => $error) if ($error ne ""); foreach my $r (@{$sensor_table}) { next if ($r->{"swSensorStatus"} eq "nominal" || $r->{"swSensorStatus"} eq "absent" ); $failure_summary .= "$host sensor $r->{swSensorType} failure ($r->{swSensorStatus})\n"; $failure_detected++; } foreach my $r (@{$port_table}) { # # ignore disabled/loopback ports # next if ($r->{"swFCPortLinkState"} ne "enabled"); # # ignore operational ports # next if ($r->{"swFCPortOpStatus"} eq "online"); $failure_summary .= "$host port $r->{swFCPortIndex} failure ($r->{swFCPortOpStatus})\n"; $failure_detected++; } ( "error" => "", "failure" => $failure_detected, "failure_summary" => $failure_summary, "operstatus" => $operstatus, "sensor_table" => $sensor_table, "port_table" => $port_table, ); } sub get_table { my ($s, @tbl) = @_; my $table = []; my $tblid = $tbl[0]->[0]; my $i = 0; my $row = new SNMP::VarList (@tbl); return ("MIB problem") if (!defined $row); while (defined ($s->getnext ($row))) { last if ($s->{"ErrorStr"} ne ""); my $r = $row->[0]->[0]; last if ($r ne $tblid); foreach my $col (@{$row}) { $table->[$i]->{"iid"} = $col->[1]; $table->[$i]->{$col->[0]} = $col->[2]; } $i++; } return ($s->{"ErrorStr"}) if ($s->{"ErrorStr"} ne ""); ( "", $table, ); } sub get_vars { my ($s, @vars) = @_; my $r = new SNMP::VarList ( @vars ); return ("MIB problem") if (!defined $r); return ($s->ErrorStr) if (!defined ($s->get ($r))); my $v; foreach my $element (@{$r}) { $v->{$element->[0]} = $element->[2]; } ("", $v); } etbemon-1.3.6/mon.d/smtp.monitor0000755000000000000000000001175010230411543013447 0ustar #!/usr/bin/perl # # Use try to connect to a SMTP server, and # wait for the right output. # # For use with "mon". # # Arguments are "-p port -t timeout host [host...]" # # Adapted from "http.monitor" by # Jim Trocki, trockij@arctic.org # # http.monitor written by # # Jon Meek # American Cyanamid Company # Princeton, NJ # # $Id: smtp.monitor,v 1.2 2005/04/17 07:42:27 trockij Exp $ # # Copyright (C) 1998, Jim Trocki # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # use Getopt::Std; use English; getopts ("p:t:"); $PORT = $opt_p || 25; $TIMEOUT = $opt_t || 30; my %good; my %bad; foreach $host (@ARGV) { my $result = smtpGET($host, $PORT); if ($result->{"ok"}) { $good{$host} = $result; } else { $bad{$host} = $result; } } # # summary line # if (keys %bad == 0) { print "\n"; } else { print join (" ", sort keys %bad), "\n"; } # # detail # foreach my $host (keys %bad) { print "$host failed with error " . $bad{$host}->{"error"}, "\n"; print "detail for $host\n"; print "==============================================================================\n"; if ($bad{$host}->{"detail"} ne "") { print $bad{$host}->{"detail"}; } else { print "no detail\n"; } print "\n"; } print "\n"; foreach my $host (keys %good) { print "$host succeeded\n"; print "detail for $host\n"; print "==============================================================================\n"; if ($good{$host}->{"detail"} ne "") { print $good{$host}->{"detail"}; } else { print "no detail\n"; } print "\n"; } if (keys %bad != 0) { exit 1; } exit 0; sub smtpGET { use Socket; use Sys::Hostname; my($Server, $Port) = @_; my($ServerOK, $TheContent); my ($OurHostname); my $result = { "ok" => 0, "error" => undef, "detail" => undef, }; $ServerOK = 0; $TheContent = ''; $Path = '/'; ############################################################### eval { local $SIG{ALRM} = sub { die "Timeout Alarm" }; alarm $TIMEOUT; if (! OpenSocket($Server, $Port)) { $result->{"error"} .= "Unable to create SMTP connection to port $Port"; $result->{"ok"} = 0; return $result; } $in = ; $result->{"detail"} .= $in; while ($in =~ /^220-/) { $in = ; $result->{"detail"} .= $in; } if ($in !~ /^220 /) { alarm 0; print S "QUIT\r\n"; close (S); $result->{"error"} = "did not receive 220 greeting"; $result->{"ok"} = 0; return $result; } $OurHostname = &hostname; print S "HELO $OurHostname\r\n"; $in = ; $result->{"detail"} .= $in; while ($in =~ /^250-/) { $in = ; $result->{"detail"} .= $in; } if ($in !~ /^250 /) { alarm 0; print S "QUIT\r\n"; close (S); $result->{"error"} = "did not get 250 response to HELO"; $result->{"ok"} = 0; return $result; } print S "quit\r\n"; $in = ; $result->{"detail"} .= $in; if ($in !~ /^221 /) { alarm 0; print S "QUIT\r\n"; close (S); $result->{"error"} = "did not get 221 response to quit"; $result->{"ok"} = 0; return $result; } $result->{"ok"} = 1; print S "QUIT\r\n"; close(S); alarm 0; # Cancel the alarm }; if ($EVAL_ERROR and ($EVAL_ERROR =~ /^Timeout Alarm/)) { $result->{"error"} = "timeout"; $result->{"ok"} = 0; return $result; } return $result; } sub OpenSocket { # # Make a Berkeley socket connection between this program and a TCP port # on another (or this) host. Port can be a number or a named service # local($OtherHostname, $Port) = @_; local($OurHostname, $sockaddr, $name, $aliases, $proto, $type, $len, $ThisAddr, $that); $OurHostname = &hostname; ($name, $aliases, $proto) = getprotobyname('tcp'); ($name, $aliases, $Port) = getservbyname($Port, 'tcp') unless $Port =~ /^\d+$/; ($name, $aliases, $type, $len, $ThisAddr) = gethostbyname($OurHostname); ($name, $aliases, $type, $len, $OtherHostAddr) = gethostbyname($OtherHostname); my $that = sockaddr_in ($Port, $OtherHostAddr); $result = socket(S, &PF_INET, &SOCK_STREAM, $proto) || return undef; $result = connect(S, $that) || return undef; select(S); $| = 1; select(STDOUT); # set S to be un-buffered return 1; # success } etbemon-1.3.6/mon.d/smtp3.monitor0000755000000000000000000004362110630617564013553 0ustar #!/usr/bin/perl # Yet another smtp monitor using IO::Socket with timing, logging # This version looks deeper than the banner to catch milter and other problems # # $Id: smtp3.monitor,v 1.2.2.1 2007/06/03 20:07:16 trockij Exp $ # # Copyright (C) 2001-2006, Jon Meek, meekj at ieee.org # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # =head1 NAME B - smtp monitor for mon with timing, logging, optional MX lookup, and diagnostic capability. =head1 DESCRIPTION A SMTP monitor using IO::Socket with connection response timing and optional logging. This test is reasonably complete. Following the greeting banner from the SMTP server the monitor client issues the HELO and MAIL commands then closes the session with a QUIT command. Early versions of this monitor simply looked at the initial greeting banner, but that did not detect certain temporary failure conditions. While configuring mon for this monitor keep in mind that a busy mail server may reject new connections. =head1 SYNOPSIS B [-d] [-l log_file_YYYYMM.log] [--timeout timeout_seconds] [--alarmtime alarm_time] [--maxfailtime seconds] [--mx] [--esmtp] [--requiretls] [--nofail] [--from user@domain.com] [--to r1@d1.com,r2@d2.edu] [--size nnnnn] [--port nn] host host1 host2 ... =head1 OPTIONS =over 5 =item B<-d> Debug/Diagnostic mode. Useful for manual command line use for diagnosing mail delivery problems. To determine if a mail destination will accept mail the --mx flag will useful. =item B<--timeout timeout> Connect timeout in seconds. =item B<--alarmtime alarm_timeout> Alarm if connect is successful but took longer than alarm_timeout seconds. =item B<--maxfailtime seconds> Alarm if connect fails only if the response time is greater than this value. If a Sendmail server is in REFUSE_LA, or similar, state due to load it will usually reject the connection in a few milliseconds. A typical value might be 0.050 for servers near the monitoring system. =item B<-l log_file_template> /path/to/logs/smtp_YYYYMM.log Current year & month are substituted for YYYYMM, that is the only possible template at this time. =item B<--mx> Lookup the MX records for the domains/hosts and test them in preference order. The first successful test will be considered a success for that domain. This was originally devised for manual command line use as a tool to verify that mail stuck in outbound queues really can not be delivered. It could be used with mon as well, however you are usually going to want to test ALL of your smtp servers, not just be sure that one of them is OK. --mx applies to all of the domains/hosts listed on the command line. =item B<--esmtp> Try ESMTP before SMTP. =item B<--requiretls> Check that STARTTLS is offered, fail if it is not. This option forces B<--esmtp>. =item B<--nofail> Never provide a failure return to mon. Useful in certain testing envrionments when logging. =item B<--port nnn> Specify a port to use. Defaults to 25. =back =head1 MON CONFIGURATION EXAMPLE hostgroup smtp mail1.mymails.org mail2.mymails.org mail3.mymails.org watch smtp service smtp_check interval 5m monitor smtp3.monitor --timeout 70 --alarmtime 30 -l /n/na1/logs/wan/smtp_YYYYMM.log period wd {Sun-Sat} alert mail.alert meekj@mymails.org alertevery 1h summary =head1 LOG FILE FORMAT A normal log entry has the format: measurement_time smtp_host_name connect_time A failed connection log entry contains: measurement_time smtp_host_name connect_time smtp_code_and_greeting (or connect_error) Where: F - Is the time of the connection attempt in seconds since 1970 F - Is the name of the smtp server that was tested. If --mx was selected then this field is servername=MX_record where MX_record is the mail domain (host) from the command line. F - Is the time from the connect request until the SMTP greeting appeared in seconds with 100 microsecond resolution. If the connection failed the time spent waiting for the connection will be a negative number. F - Should have the SMTP response code integer followed by the greeting banner if there was a problem. F - If present may indicate "Connect failed" meaning that the connect attempt failed immediately, possibly due to a DNS lookup error or because the server is not running any service on port 25. The field may also be "Connect timeout" indicating that the connect failed after the set timeout period. =head1 BUGS It should be possible to specify --esmtp and --requiretls on a per-host basis. A SMTP temporary failure code could cause the monitor to retry the connection a certain number of times. It is not yet possible to specify the username / domain for the HELO and MAIL commands, but it would be very simple to add. =head1 REQUIRED NON-STANDARD PERL MODULES IO::Socket Time::HiRes Net::DNS (only if --mx option will be used) If you do not have Time::HiRes you can choose to comment out the lines that refer to F and F but several features will be lost. =head1 AUTHOR Jon Meek, meekj at ieee.org $Id: smtp3.monitor,v 1.2.2.1 2007/06/03 20:07:16 trockij Exp $ =cut use English; use Sys::Hostname; use Getopt::Long; use IO::Socket; use Time::HiRes qw( gettimeofday tv_interval ); $RCSid = q{$Id: smtp3.monitor,v 1.2.2.1 2007/06/03 20:07:16 trockij Exp $ }; $ESMTP = 0; $RequireTLS = 0; GetOptions ('mx' => \$UseMX, 'd' => \$opt_d, 'esmtp' => \$ESMTP, 'requiretls' => \$RequireTLS, 'timeout=i' => \$TimeOut, 't=i' => \$TimeOut, 'alarmtime=i' => \$opt_T, 'maxfailtime=f' => \$MaxFailTime, 'T=i' => \$opt_T, 'logfile=s' => \$opt_l, 'l=s' => \$opt_l, 'nofail' => \$NoFail, 'size=i' => \$MessageSize, 'port=i' => \$Port, 'from=s' => \$FromAddress, 'to=s' => \$ToAddresses, ); $ESMTP = 1 if $RequireTLS; if ($UseMX) { # Will need Net::DNS Module, but don't require the module if it won't be used eval "use Net::DNS"; do { warn "Couldn't load Net::DNS: $@"; undef $UseMX; } unless ($@ eq ''); $Resolver = new Net::DNS::Resolver; } $Port = 'smtp(25)' unless $Port; $TimeOut = 30 unless $TimeOut; # Default timeout in seconds $dt = 0; # Initialize connect time variable @Failures = (); # Initialize failure list $TimeOfDay = time; # Current time print "TimeOfDay: $TimeOfDay\n" if $opt_d; # # Get the process username and the hostname of the monitor machine # $MonitorUsername = getpwuid($UID); $MonitorHostname = hostname; $host_address = gethostbyname($MonitorHostname); $MonitorHostname = gethostbyaddr($host_address, AF_INET); $FromAddress = qq{$MonitorUsername\@$MonitorHostname} unless $FromAddress; print " From: $FromAddress\n" if $opt_d; print " TimeOut: $TimeOut\n" if $opt_d; # # Check each host, or MX record # foreach $host (@ARGV) { print "Check: $host\n" if $opt_d; # # Get the MX records, if we need them # if ($UseMX) { undef %MXval; undef @MXorder; @mx = mx($Resolver, $host); if (@mx) { foreach $rr (@mx) { $preference = $rr->preference; $mxrecord = $rr->exchange; $MXval{$mxrecord} = $preference; } } else { print "can't find MX records for $host: ", $Resolver->errorstring, "\n" if $opt_d; push(@Failures, $host); # Call it a failure $FailureDetail{$host} = "Can't find MX records"; next; } # # Sort the MX records into preference order # print "MX records for $host:\n" if $opt_d; foreach $k (sort {$MXval{$a} <=> $MXval{$b}} keys %MXval) { $Arecord = ''; # Clear for this MX push(@MXorder, $k); if ($opt_d) { # If in debug/verbose mode lookup A record $name = $k . '.'; # Append dot for absolute lookup if ($packet = $Resolver->search($name)) { @answer = $packet->answer; foreach $rr (@answer) { $address = ''; $name = $rr->name; $type = $rr->type; $address = $rr->address if ($type eq 'A'); $Arecord .= "$type: $address "; # Append, in case some other records are found } } else { $arecord = "Could not find A record for $name"; } } printf " %3d - %s %s\n", $MXval{$k}, $k, $Arecord if $opt_d; } } # # Now actually do the smtp check # if ($UseMX && @mx) { # Check MX records, stop after first success foreach $mx (@MXorder) { $HostPlusMX = "$host=$mx"; push(@HostNames, $HostPlusMX); $TestTime{$HostPlusMX} = time; print "Checking $HostPlusMX\n" if $opt_d; $result = &CheckSMTP($HostPlusMX); last if ($result); } } else { # Regular host check push(@HostNames, $host); $TestTime{$host} = time; $result = &CheckSMTP($host); } } if ($opt_d) { foreach $host (sort @HostNames) { print "$TestTime{$host} $host $ConnectTime{$host} $InitialBanner{$host}\n"; # ($shortfail, $rest) = split(/\n/, $InitialBanner{$host}, 2); # print "$TestTime{$host} $host $ConnectTime{$host} $shortfail\n"; } } # Write results to logfile, if -l if ($opt_l) { # Determine logfile name, usually based on year/month $LogFile = $opt_l; ($sec,$min,$hour,$mday,$Month,$Year,$wday,$yday,$isdst) = localtime($TimeOfDay); $Month++; $Year += 1900; $YYYYMM = sprintf('%04d%02d', $Year, $Month); $LogFile =~ s/YYYYMM/$YYYYMM/; # Fill in current year and month open(LOG, ">>$LogFile") || warn "$0 Can't open logfile: $LogFile\n"; foreach $host (sort @HostNames) { $FailureDetail{$host} =~ s/\n/ /g; # Put it on one line, but result may be too long $FailureDetail{$host} =~ s/ $//; # Trim final space # ($shortfail, $rest) = split(/\n/, $FailureDetail{$host}, 2); # print LOG "$TestTime{$host} $host $ConnectTime{$host} $shortfail\n"; print LOG "$TestTime{$host} $host $ConnectTime{$host} $FailureDetail{$host}\n"; } close LOG; } if (@Failures == 0) { # Indicate "all OK" to mon exit 0; } # # Otherwise we have one or more failures # @SortedFailures = sort @Failures; print "@SortedFailures\n"; foreach $host (@SortedFailures) { print "$host $ConnectTime{$host} $FailureDetail{$host}\n"; } print "\n"; exit 0 if $NoFail; # Never indicate failure if $NoFail is set exit 1; # Indicate failure to mon sub CheckSMTP { my $host = shift; my $t1, $t2, $dt, $mx_name, $stripped_host; my $Failure = 0; # Flag to indicate failure for return code # return 0 may not be working inside eval my $buflength = 1024; if ($host =~ /=/) { # Have MX data ($mx_name, $stripped_host) = split(/=/, $host); } else { $stripped_host = $host; } # # Use eval/alarm to handle timeout # eval { local $SIG{ALRM} = sub { die "timeout\n" }; # Alarm handler alarm($TimeOut); # Do a SIG_ALRM in $TimeOut seconds $t1 = [gettimeofday]; # Start connection timer, then connect my $sock = IO::Socket::INET->new(PeerAddr => $stripped_host, PeerPort => $Port, Proto => 'tcp'); if (defined $sock) { # Connection succeded $in = ''; $bytes = sysread($sock, $in, $buflength); # Handle multi-line banners $InitialBanner{$host} = $in; $t2 = [gettimeofday]; # Stop clock print " Banner: $InitialBanner{$host}\n" if $opt_d; if ($InitialBanner{$host} !~ /^220/) { # Consider "220 Service ready" to be only valid push(@Failures, $host); # Note failure if (length($InitialBanner{$host}) == 0) { # Note empty banner $InitialBanner{$host} = 'null'; } $FailureDetail{$host} = "BANNER: " . $InitialBanner{$host}; # Save failure banner $ConnectTime{$host} = -1; # last; $Failure = 1; print "QUIT\r\n" if $opt_d; print $sock "QUIT\r\n"; # Shutdown connection close $sock; return 0; } if ($ESMTP) { # Try EHLO first print "EHLO $MonitorHostname\r\n" if $opt_d; print $sock "EHLO $MonitorHostname\r\n"; $in = ''; $bytes = sysread($sock, $in, $buflength); # Handle multi-line banners $EhloResponse{$host} = $in; print " EHLO resp: $EhloResponse{$host}\n" if $opt_d; if ($EhloResponse{$host} !~ /^250/) { # Consider "250 Requested mail action okay, completed" to be only valid push(@Failures, $host); # Note failure print "EHLO Failure!\n" if $opt_d; $FailureDetail{$host} = "EHLO: " . $EhloResponse{$host}; # Save failure banner #last; $Failure = 1; print "QUIT\r\n" if $opt_d; print $sock "QUIT\r\n"; # Shutdown connection close $sock; return 0 if $RequireESMTP; } if ($RequireTLS && ($EhloResponse{$host} !~ /STARTTLS/)){ # Check TLS advertisement push(@Failures, $host); # Note failure $FailureDetail{$host} = "STARTTLS Not Offered "; print "STARTTLS Not Offered!\n" if $opt_d; print $sock "QUIT\r\n"; # Shutdown connection close $sock; return 0; } } if (!$ESMTP or ($ESMTP && $Failure)) { print $sock "HELO $MonitorHostname\r\n"; $in = ''; $bytes = sysread($sock, $in, $buflength); # Handle multi-line banners $HeloResponse{$host} = $in; print " HELO resp: $HeloResponse{$host}\n" if $opt_d; if ($HeloResponse{$host} !~ /^250/) { # Consider "250 Requested mail action okay, completed" to be only valid push(@Failures, $host); # Note failure print "HELO Failure!\n" if $opt_d; $FailureDetail{$host} = "HELO: " . $HeloResponse{$host}; # Save failure banner #last; $Failure = 1; print "QUIT\r\n" if $opt_d; print $sock "QUIT\r\n"; # Shutdown connection close $sock; return 0; } } $FromLine = qq{MAIL From:<$FromAddress>}; if ($MessageSize) { $FromLine .= qq{ SIZE=$MessageSize}; } $FromLine .= qq{\r\n}; print $FromLine if $opt_d; print $sock $FromLine; chomp($MailResponse{$host} = <$sock>); print " MAIL resp: $MailResponse{$host}\n" if $opt_d; if ($MailResponse{$host} !~ /^250\s+/) { # Consider "250 Requested mail action okay, completed" to be only valid push(@Failures, $host); # Note failure $FailureDetail{$host} = "MAIL: " . $MailResponse{$host}; # Save failure banner #last; $Failure = 1; print "QUIT\r\n" if $opt_d; print $sock "QUIT\r\n"; # Shutdown connection close $sock; return 0; } if ($ToAddresses) { # Addresses given on command line (@to_addrs) = split(/,/, $ToAddresses); foreach $to (@to_addrs) { $RcptCommand = qq{RCPT TO:<$to>}; print "$RcptCommand\r\n" if $opt_d; print $sock "$RcptCommand\r\n"; chomp($RcptResponse = <$sock>); print " RCPT resp: $RcptResponse\n" if $opt_d; } } print "QUIT\r\n" if $opt_d; print $sock "QUIT\r\n"; # Shutdown connection close $sock; $dt = tv_interval ($t1, $t2); # Compute connection time $ConnectTime{$host} = sprintf("%0.4f", $dt); # Format to 100us resolution if ($opt_T) { # Check for slow response if ($dt > $opt_T) { push(@Failures, $host); # Call it a failure $FailureDetail{$host} = "Slow Connect"; $Failure = 1; return 0; } } } else { # Connection failed $t2 = [gettimeofday]; # Stop clock $dt = tv_interval ($t1, $t2); # Compute connection time $ConnectTime{$host} = sprintf("-%0.4f", $dt); # Format to 100us resolution, -val if failure print " Connect to $host failed\n" if $opt_d; if ($MaxFailTime) { if ($dt <= $MaxFailTime) { # Don't alarm on connection refusals due to server load $Failure = 0; return 1; } } push(@Failures, $host); # Save failed host $FailureDetail{$host} = "Connect failed"; $Failure = 1; return 0; } }; alarm(0); # Stop alarm countdown if ($@ =~ /timeout/) { # Detect timeout failures $t2 = [gettimeofday]; # Stop clock $dt = tv_interval ($t1, $t2); # Compute connection time $ConnectTime{$host} = sprintf("-%0.4f", $dt); # Format to 100us resolution, -val if timeout push(@Failures, $host); print " Connect to $host timed-out\n" if $opt_d; $FailureDetail{$host} = "Connect timeout"; $Failure = 1; return 0; } if ($Failure) { # Important when an MX record list is being checked return 0; } else { return 1; } } __END__ SMTP Reply Codes From RFC-821 - may use in the future 211 System status, or system help reply 214 Help message [Information on how to use the receiver or the meaning of a particular non-standard command; this reply is useful only to the human user] 220 Service ready 221 Service closing transmission channel 250 Requested mail action okay, completed 251 User not local; will forward to 354 Start mail input; end with . 421 Service not available, closing transmission channel [This may be a reply to any command if the service knows it must shut down] 450 Requested mail action not taken: mailbox unavailable [E.g., mailbox busy] 451 Requested action aborted: local error in processing 452 Requested action not taken: insufficient system storage 500 Syntax error, command unrecognized [This may include errors such as command line too long] 501 Syntax error in parameters or arguments 502 Command not implemented 503 Bad sequence of commands 504 Command parameter not implemented 550 Requested action not taken: mailbox unavailable [E.g., mailbox not found, no access] 551 User not local; please try 552 Requested mail action aborted: exceeded storage allocation 553 Requested action not taken: mailbox name not allowed [E.g., mailbox syntax incorrect] 554 Transaction failed etbemon-1.3.6/mon.d/smtpswaks.monitor0000644000000000000000000000265113657160256014537 0ustar #!/bin/bash # Mon script to check sending mail with swaks # Options: -f FROM [-e EHLO] [-t TIMEOUT] RECIPIENT[:SERVER] [RECIPIENT[:SERVER] ...] # [ -a authuser ] [ -p authpass ] TIMEOUT=10 EHLO=$(cat /etc/mailname) FROM="mon@$EHLO" # Copyright Russell Coker GPLv3 TEMP=$(getopt -o f:e:t:a:p:P: -n "$0" -- "$@") if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi # Note the quotes around `$TEMP': they are essential! eval set -- "$TEMP" while true ; do case "$1" in -f) FROM="$2" shift 2 ;; -e) EHLO="$2" shift 2 ;; -t) TIMEOUT="$2" shift 2 ;; -a) AUTHUSER="--auth-user $2" TLS="-tls --auth --tls-verify" shift 2 ;; -p) AUTHPASS="-ap $2" TLS="-tls --auth --tls-verify" shift 2 ;; -P) AUTHPASS="-ap $(cat $2)" TLS="-tls --auth --tls-verify" shift 2 ;; --) shift break ;; *) echo "Options parse error: $1" exit 1 ;; esac done FAILED="" for TEST in $* ; do RECIPIENT=$(echo $TEST|cut -f1 -d:) SERVER=$(echo $TEST|cut -f2,3 -d:) if [ "$SERVER" = "$RECIPIENT" ]; then SERVER="" else SERVER="--server $SERVER" fi RESULT=$(swaks --timeout $TIMEOUT $TLS $AUTHUSER $AUTHPASS --ehlo $EHLO --from $FROM --to $RECIPIENT $SERVER -S 2 2>&1) || FAILED="$FAILED ($TEST $RESULT)" done if [ "$FAILED" != "" ]; then echo "$FAILED" exit 1 fi etbemon-1.3.6/mon.d/snmpdiskspace.monitor0000755000000000000000000004167713135636631015361 0ustar #!/usr/bin/perl # # NAME # snmpdiskspace.monitor # # # SYNOPSIS # snmpdiskspace.monitor [--list] [--timeout seconds] [--config filename] # [--community string] [--free minfree] # [--retries retries] [--usemib ] host... # # # DESCRIPTION # This script uses the Host Resources MIB (RFC1514), and optionally # the MS Windows NT Performance MIB, or UCD-SNMP extensions # (enterprises.ucdavis.dskTable.dskEntry) to monitor diskspace on hosts # via SNMP. # # snmpdiskspace.monitor uses a config file to allow the specification of # minimum free space on a per-host and per-partition basis. The config # file allows the use of regular expressions, so it is quite flexible in # what it can allow. See the sample config file for more details and # syntax. # # The script only checks disks marked as "FixedDisks" by the Host MIB, # which should help cut down on the number of CD-ROM drives # erroneously reported as being full! Since the drive classification # portion of the UCD Host MIB isn't too great on many OS'es, though, # this won't buy you a lot. Empire's SNMP agent gets this right on # all the hosts that I checked, though. Not sure about the MS MIB. # UCD-SNMP only checks specific partition types (md, hd, sd, ida) # # snmpdiskspace.monitor is intended for use as a monitor for the mon # network monitoring package. # # # OPTIONS # --community The SNMP community string to use. Default is "public". # --config The config file to use. Default is either # /etc/mon/snmpdiskspace.cf or # /usr/lib/mon/mon.d/snmpdiskspace.cf, in that order. # --retries The number of retries to use, if we get an SNMP timeout. # Default is retry 5 times. # --timeout Seconds to wait before declaring a timeout on an SNMP get. # Default is 20 seconds. # --free The default minimum free space, in a percentage or absolute # quantity, as per the config file. Thus, arguments of, for # example, "20%", "1gb", "50mb" are all valid. # Default is 5% free on every partition checked. # # --ifree The default minimum free inode percentage, specified as # a percentage. Default is 5% free. # # --list Give a verbose listing of all partitions checked on all # specified hosts. # # --listall like --list, but also lists the thresholds defined for # each filesystem, so you can doublecheck the config file # # --usemib Choose which MIB to use: one or more of host, perf, ucd # Default tries all three, in that order # # --debug enable debug output for config file parsing and MIB fetching # # # EXIT STATUS # Exit status is as follows: # 0 No problems detected. # 1 Free space on any host was below the supplied parameter. # 2 A "soft" error occurred, either a SNMP library error, # or could not get a response from the server. # # In the case where both a soft error and a freespace violation are # detected, exit status is 1. # # BUGS # When using the net-snmp agent, you must build it with "--with-dummy-values" # or the monitor may not parse the Host Resources MIB properly. # # List of local filesystem types used when parsing the UCD MIB should be # configurable. # # # NOTES # $Id: snmpdiskspace.monitor,v 1.1.2.2 2007/05/08 11:05:49 trockij Exp $ # # * Added support for inode status via UCD-SNMP MIB. Fourth column in config # file (optional) is for inode%. # * added --debug and --usemib options. Latter needed so you can force use # of UCD mib if you want inode status. # * rearranged the error messages to be more Mon-like (hostname first) # * added code to synchronize instance numbers when using UCD MIB. This # could solve the "sparse MIB" problem usually fixed by the # --with-dummy-values option in net-snmp if needed for other agents # Ed Ravin (eravin@panix.com), January 2005 # # Added support for regex hostnames and partition names in the config file, # 'use strict' by andrew ryan . # # Generalised to handle multible mibs by jens persson # Changes Copyright (C) 2000, jens persson # # Modified for use with UCD-SNMP by Johannes Walch for # NWE GmbH (j.walch@nwe.de) # # Support for UCD's disk MIB added by Matt Simonsen # # # SEE ALSO # mon: http://www.kernel.org/software/mon/ # # This requires the UCD SNMP library and G.S. Marzot's Perl SNMP # module. (http://ucd-snmp.ucdavis.edu and CPAN, respectively). # # The Empire SystemEdge SNMP agent: http://www.empire.com # # # COPYRIGHT # # Copyright (C) 1998, Jim Trocki # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # use strict; use Mon::SNMP; use Getopt::Long; sub readcf; sub toBytes; sub get_values; # setup what mibs to use # $ENV{"MIBS"} = 'RFC1213-MIB:HOST-RESOURCES-MIB:WINDOWS-NT-PERFORMANCE:UCD-SNMP-MIB'; $ENV{"MIBS"} = 'RFC1213-MIB:HOST-RESOURCES-MIB:UCD-SNMP-MIB'; my %opt; # parse the commandline GetOptions (\%opt, "community=s", "timeout=i", "retries=i", "config=s", "list", "listall", "free=i", "ifree=n", "usemib=s", "debug"); die "No host arguments given!\n" if (@ARGV == 0); my $RET = 0; #exit value of script my @ERRS = (); # array holding detail output my @HOSTS = (); # array holding summary output my @cfgfile = (); #array holding contents of config file # Read in defaults my $COMM = $opt{"community"} || $ENV{"COMMUNITY"} || "public"; my $TIMEOUT = $opt{"timeout"} * 100000 || 2000000; #default timeout is 20 seconds my $RETRIES = $opt{"retries"} || 5; my $CONFIG = $opt{"config"} || (-d "/etc/mon" ? "/etc/mon" : "/usr/lib/mon/mon.d") . "/snmpdiskspace.cf"; my $DISKFREE = $opt{"free"} || -5; #default max % full is 95% my $INODEFREE = $opt{"ifree"} || 5; #default max % inode full is 95% my $USEMIB= $opt{"usemib"} || "host perf ucd"; my $LIST= $opt{"list"} || $opt{"listall"} || 0; my $LISTALL= $opt{"listall"} || 0; my $DEBUG= $opt{"debug"} || 0; my ($host, $checkval, $icheckval, %FREE, $disk, @disklist, $cfgline); # read the config file if ( !readcf ($CONFIG) ) { # not being able to read config file shouldn't be a fatal, since we # have defaults we can use. print STDERR "readcf: Could not read config file $CONFIG: $!\n"; } # now do the checks for each host foreach $host (@ARGV) { # fetch the info from the computers @disklist = get_values($host); next unless (@disklist) && (ref($disklist[0]) eq "ARRAY"); #make sure we got an OK return value from get_values before going any further # Now check each partition foreach $disk (@disklist) { undef $checkval ; undef $icheckval ; # Go through the config file line by line until we # find a match for this host/partition. Stop as soon # as we find a match. foreach $cfgline (@cfgfile) { if ( ($host =~ m/^$cfgline->[0]$/) && ($disk->[2] =~ m/^$cfgline->[1]$/) ) { print STDERR "'$host' matched /^$cfgline->[0]\$/ or '$disk->[2]' matched /^$cfgline->[1]\$/, using checkval $cfgline->[2]\n" if $DEBUG; $checkval = $cfgline->[2] ; $icheckval= $cfgline->[3] ; last; } } # Set to default otherwise $checkval = $DISKFREE unless defined($checkval); $icheckval= $INODEFREE unless defined($icheckval); $icheckval=~ s/%$//; # do the checking, first absolute and then percentage next if $checkval == 0 && $icheckval == 0; # nothing to check: ignore my $hostfailed= 0; if (($checkval > 0) && ($disk->[0] <$checkval)) { $hostfailed++; push (@ERRS,sprintf("%s: filesystem %s is (%1.1f%% full), %1.0fMB free (below threshold %1.0fMB free)", $host , $disk->[2] , $disk->[1] , $disk->[0] / 1048576, $checkval / 1048576 )); } elsif (($checkval < 0) && ($disk->[1] - $checkval >=100)) { $hostfailed++; push (@ERRS,sprintf("%s: filesystem %s is (%1.1f%% full), %1.0fMB free (below threshold %s%% free)", $host , $disk->[2] , $disk->[1] , $disk->[0] / 1048576, abs($checkval) )); } if (($icheckval > 0) && ($disk->[3] ne "N/A") && (100 - $disk->[3]) < $icheckval ) { $hostfailed++; push (@ERRS, sprintf ("%s: filesystem %s has %1.1f%% inodes free (below threshold %s%% inodes free)", $host, $disk->[2], 100 - $disk->[3], $icheckval )); } if ($hostfailed) { push (@HOSTS, $host); $RET = 1; } # if the user want a listing, then the user will get a listing :-) write if ($LIST or $LISTALL); if ($LISTALL) { printf(" Will alarm if MB free declines below threshold %1.0fMB free\n", $checkval / 1048576) if $checkval > 0; printf(" Will alarm if %%free space declines below threshold %1.1f%% free\n", abs($checkval)) if $checkval < 0; printf(" No free space alarm defined in config file.\n") if $checkval == 0; printf(" Will alarm if %%free inodes declines below %1.1f%%\n", $icheckval) if $icheckval > 0; printf(" No %%inodes free alarm defined in config file.\n") if $icheckval == 0; printf(" WARNING: Unable to alarm on inodes free, dskPercentNode not found in MIB\n") if $disk->[3] eq "N/A" and $icheckval > 0; } } } if ($LIST or $LISTALL) { print "\n\n"; } # Uniq the array of failures, so multiple failures on a single host # are reported in the details section (lines #2-infinity) but not # in the summary (line #1). # Then print out the failures, if any. my %saw; undef %saw; @saw{@HOSTS} = (); @HOSTS = keys %saw; if ($RET) { print "@HOSTS\n"; print "\n"; print join("\n", @ERRS), "\n"; } exit $RET; # # read configuration file # sub readcf { my ($f) = @_; my ($l, $host, $filesys, $free, $ifree); open (CF, $f) || return undef; while () { next if (/^\s*#/ || /^\s*$/); chomp; ($host, $filesys, $free, $ifree) = split; # if (!defined ($FREE{$host}{$filesys} = toBytes ($free))) { if (!push (@cfgfile, [$host , $filesys , toBytes ($free), $ifree || 0]) ) { die "error free specification, config $f, line $.\n"; } print STDERR "cf: assigned host=$host, filesys=$filesys, free=$free, ifree=$ifree\n" if $DEBUG; } close (CF); } sub toBytes { # take a string and parse it as folows # N return N # N kb return N*1024 # N mb return N*1024^2 # N gb return N*1024^3 # N % return -N my ($free) = @_; my ($n, $u); if ($free =~ /^(\d+\.\d+)(kb|mb|gb|%|)$/i) { ($n, $u) = ($1, "\L$2"); } elsif ($free =~ /^(\d+)(kb|mb|gb|%|)$/i) { ($n, $u) = ($1, "\L$2"); } else { return undef; } return (int ($n * -1)) if ($u eq "%"); return (int ($n * 1024 )) if ($u eq "kb"); return (int ($n * 1024 * 1024)) if ($u eq "mb"); return (int ($n * 1024 * 1024 * 1024)) if ($u eq "gb"); int ($n); } # # Do the work of trying to get the data from the host via SNMP # sub get_values { my ($host) = @_; my (@disklist,$Type,$Descr,$AllocationUnits,$Size,$Used,$Freespace,$Percent,$InodePercent); my ($v,$s); if (!defined($s = new SNMP::Session (DestHost => $host, Timeout => $TIMEOUT, Community => $COMM, Retries => $RETRIES))) { $RET = ($RET == 1) ? 1 : 2 ; push (@HOSTS, $host); push (@ERRS, "$host: could not create session: " . $s->{ErrorStr}); return undef; } # First we try to use the Host mib (RFC1514) # supported by net-snmpd on most platforms, see http://www.net-snmp.org # # You can also use the Empire (http://www.empire.com) # SNMP agent to provide hostmib support on UNIX and NT. if ($USEMIB =~ /host/i) { $v = new SNMP::VarList ( ['hrStorageIndex'], ['hrStorageType'], ['hrStorageDescr'], ['hrStorageAllocationUnits'], ['hrStorageSize'], ['hrStorageUsed'], ); while (defined $s->getnext($v)) { last if ($v->[0]->tag !~ /hrStorageIndex/); $Type = $v->[1]->val; $Descr = $v->[2]->val; $AllocationUnits = $v->[3]->val; $Size = $v->[4]->val; $Used = $v->[5]->val; $Freespace = (($Size - $Used) * $AllocationUnits); print STDERR "Found HOST MIB filesystem: Type=$Type, Descr=$Descr, AllocationUnits=$AllocationUnits, Size=$Size, Used=$Used\n" if $DEBUG; # This next check makes sure we're only looking at storage # devices of the "FixedDevice" type (4). For comparison, Physical # RAM is 2, Virtual Memory is 3, Floppy Disk is 6, and CD-ROM is 7 # Using the Empire agent, this will eliminate drive types other # than hard disks. The UCD agent is not as good as determining # drive types under the HOST mib. next if ($Type !~ /\.1\.3\.6\.1\.2\.1\.25\.2\.1\.4/); if ($Size != 0) { $Percent= ($Used / $Size) * 100.0; } else { $Percent=0; }; push (@disklist,[$Freespace,$Percent,$Descr, "N/A"]); print STDERR "Using HOST MIB filesystem: $Descr ($Type)\n" if $DEBUG; }; if (@disklist) { return @disklist; }; }; # Then we test the perfmib from M$ NT resource kit # I'm using the agent/mib-defs from # http://www.wtcs.org/snmp4tpc/ # for somereason every second request fails, # so we fetch the variables twice and discards # the bad ones if ($USEMIB =~ /perf/i) { $v = new SNMP::VarList ( ['ldisklogicalDiskIndex'], ['ldiskPercentFreeSpace'], ['ldiskPercentFreeSpace'], ['ldiskFreeMegabytes'], ['ldiskFreeMegabytes'], ); while (defined $s->getnext($v)) { # Make sure we are still in relevant portion of MIB last if ($v->[1]->val !~ /^\.1\.3\.6\.1\.2\.1\.25\.2\.1\.4/); last if ($v->[0]->val =~ /Total/); $Descr = ( $v->[0]->val =~ /.*:.*:(\w+:)$/gi)[-1] ; $Percent = $v->[2]->val; $Freespace = $v->[4]->val * 1024 * 1024; push (@disklist,[$Freespace,$Percent,$Descr, "N/A"]); print STDERR "Using PERF MIB filesystem: $Descr, $Freespace,$Percent\n" if $DEBUG; }; if (@disklist) { return @disklist; } } #Try UCD-SNMP .enterprises.ucdavis.dskTable.dskEntry MIB extrnsion # Comes with UCD-SNMP / net-snmp if ($USEMIB =~ /ucd/i) { $v = new SNMP::VarList ( ['dskIndex'], ['dskPath'], ['dskPercent'], ['dskAvail'], ['dskDevice'], ['dskPercentNode'], ); while (defined $s->getnext($v)) { last if ($v->[0]->tag !~ /dskIndex/); # end of MIB? my $instancenum= $v->[0]->iid; # what instance number? # check for partial fetches (like swap partition) that won't # return all the MIB entries if ($v->[2]->iid != $instancenum or $v->[3]->iid != $instancenum or $v->[5]->iid != $instancenum) { # ignore this instance and try to move on to next # we wouldn't need this if use-dummy-values really worked $v = new SNMP::VarList ( ['dskIndex', $instancenum], ['dskPath', $instancenum], ['dskPercent', $instancenum], ['dskAvail', $instancenum], ['dskDevice', $instancenum], ['dskPercentNode', $instancenum], ); next; } $Descr = $v->[1]->val; $Percent = $v->[2]->val; $Freespace = $v->[3]->val; $Freespace *= 1024; #Convert from kbytes to bytes to make consistent $Type = $v->[4]->val; $InodePercent = $v->[5]->val; print STDERR "Found UCD MIB filesystem: Type=$Type, Descr=$Descr, Percent=$Percent, Freespace=$Freespace, InodePercent=$InodePercent\n" if $DEBUG; # Try to catch only local filesystems. This covers the # the basics, but probably should be configurable next unless ( $Type =~ m/\b(md|hd|wd|sd|ida|raid)/ ) ; print STDERR "Using UCD MIB filesystem: $Descr ($Type)\n" if $DEBUG; push (@disklist,[$Freespace,$Percent,$Descr, $InodePercent]); }; if (@disklist) { return @disklist; } } #Check for errors if ($s->{ErrorNum}) { push (@HOSTS, $host); push (@ERRS, "$host: could not get SNMP info: " . $s->{ErrorStr}); $RET = ($RET == 1) ? 1 : 2 ; return undef; } # Check for OID not found push (@HOSTS, $host); push (@ERRS, "$host: Disk space OIDs not found in MIB(s): $USEMIB"); $RET = ($RET == 1) ? 1 : 2 ; return undef; } # format specifications, should be able to cut, paste and edit into a config file format STDOUT_TOP = System Description % Used Free space Inode% ------------------------------------------------------------------------------- . format STDOUT = @<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<< @###.# % @#######.# mb @>>>>>> $host, $disk->[2], $disk->[1], $disk->[0]/1024/1024, ( $disk->[3] ne "N/A" ? ($disk->[3] + 0) . "%" : "N/A") . etbemon-1.3.6/mon.d/snmpvar.monitor0000755000000000000000000004137010146140377014165 0ustar #!/usr/bin/perl # ############################################################################ ## ## ## snmpvar.monitor Version 1.6.0 ## ## 2003-05-21 ## ## Copyright (C) 2000-2003 ## ## Peter Holzleitner (peter@holzleitner.com) ## ## ## ############################################################################ # # A MON plug-in monitor to test numeric values retrieved via SNMP # against configured limits. # # Arguments: # # [--community=cmn] [--group=groups] [--timeout=n] [--retries=n] [--debug] # [--varconf=filename] [--config=filename] [--snmpconf=filename] # [--mibs='mib1:mib2:mibn'] [--list[=linesperpage]] host [host ...] # # For every host name passed on the command line, snmpval.monitor looks # up the list of variables and corresponding limits in the configuration # file (snmpmon.cf). # # If a --groups option is present, only those variables are checked # which are in one of the specified groups. To specify more than one # group, separate group names with commas. You can also exclude groups # by prefixing the group name(s) with '-'. Don't mix in- and exclusion. # Examples: # --groups=Power only vars in the Power group # --groups=Power,Env vars in the Power or Env group # --groups=-Power,-Env all vars except those in Power or Env groups # --groups=Power,-Env won't work (only the exclusions) # # For every such variable, it looks up the OID, description etc. from # the variable definition file (snmpvar.def). # # This monitor looks for configuration files in the current directory, # in /etc/mon and /usr/lib/mon/etc. Command line option --varconf # overrides the location of the variable definition file, option # --config sets the configuration file name. # # For formats, please refer to the sample configuration files. # # By default, this monitor does not load any MIB, and OIDs are specified # numerically in the configuration files. Use the option --mibs # to force certain MIBs to be loaded. # # When invoked with the --list option, the output format is changed # into a more human-readable form used to check and troubleshoot the # configuration. This option must not be used from within MON. # # # Exit values: # 0 if everything is OK # 1 if any observed value is outside the specified interval # 2 in case of an SNMP error (e.g. no response from host) # # Requirements: # # UCD SNMP library (3.6.2 or higher) # G.S. Marzot's Perl SNMP module (from CPAN). # # # License: # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software Foundation, # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA # # # History: # # 1.6.0 21 May 2003 Equal and Non-Equal tests in addition to < and > (P.H.) # 1.5.1 09 Apr 2003 change \w to ^\s in FriendlyName detection to allow # indices containing "." like IP Addresses # 1.5.0 04 Dec 2002 per-host SNMP options (Ryan VanderBijl + P.H.) # --list shows all hosts if none specified (Ryan V.) # more output with --debug option (P.H.) # 1.4.0 10 Sep 2002 extended SNMP configuration (Dan Urist) # 1.3.0 15 May 2002 added GROUP option (Dave Alden) # added DEFAULTGROUP, group exclusion (P.H.) # decimals OK in limits (britcey) # added DefaultMin/Max (P.H.) # 1.2.0 21 Mar 2001 added FriendlyName option (P.H.) # 1.1.2 10 Jul 2000 fixed -l output with plausibility checks (P.H.) # 1.1.1 04 Apr 2000 automatically add dot between OID and index (P.H.) # 1.1.0 30 Mar 2000 added upper and lower plausibility limits (P.H.) # 1.0.1 24 Jan 2000 bugfix: reading Decode definitions (P.H.) # 1.0.0 13 Jan 2000 initial release (P.H.) # use SNMP; use Getopt::Long; use Sys::Syslog; sub ReadVarDef; sub ReadVarList; sub ReadSNMPConf; sub GetSNMPArgs; sub Decode; GetOptions (\%opt, "config=s", "groups=s", "varconf=s", "snmpconf=s", "community=s", "port=i", "timeout=i", "retries=i", "mibs=s", "list:i", "debug"); die "no host arguments\n" if ( (@ARGV == 0) && !exists($opt{'list'}) ); $RET = 0; @ERRS = (); @HOSTS = (); ($^O eq "linux" || $^O eq "openbsd") && Sys::Syslog::setlogsock('unix'); openlog('snmpvar.mon', 'cons,pid', 'daemon'); # find config files $CF1 = '/etc/mon'; $CF2 = '/usr/lib/mon/etc'; $VARCONF_FILE = (-d $CF1 ? $CF1 : $CF2) . '/snmpvar.def'; $MONCONF_FILE = (-d $CF1 ? $CF1 : $CF2) . '/snmpvar.cf'; $SNMPCONF_FILE = (-d $CF1 ? $CF1 : $CF2) . '/snmpopt.cf'; # pick up local config files for testing $VARCONF_FILE = './snmpvar.def' if -e './snmpvar.def'; $MONCONF_FILE = './snmpvar.cf' if -e './snmpvar.cf'; $SNMPCONF_FILE = './snmpopt.cf' if -e './snmpopt.cf'; # commandline ovverides ini any case $VARCONF_FILE = $opt{'varconf'} || $VARCONF_FILE; $MONCONF_FILE = $opt{'config'} || $MONCONF_FILE; $SNMPCONF_FILE = $opt{'snmpconf'} || $SNMPCONF_FILE; print STDERR "\nsnmpvar.monitor: configured from $VARCONF_FILE, $MONCONF_FILE\n\n" if $opt{'debug'}; ReadVarDef($VARCONF_FILE) || die "could not read variable definition: $!\n"; ReadVarList($MONCONF_FILE) || die "could not read config: $!\n"; ReadSNMPConf($SNMPCONF_FILE); # this is optional stuff # load only the necessary MIBs: $ENV{'MIBS'} = $opt{'mibs'} || ''; $FORMAT_LINES_PER_PAGE = $opt{'list'} || 25; $GROUPS = "," . $opt{'groups'} . "," if ($opt{'groups'}); @ARGV = keys %VARLIST if ( exists($opt{'list'}) && @ARGV == 0 ); foreach $host (@ARGV) { $VARS = $VARLIST{$host}; # %VARLIST{$host}{$var}{'MIN'|'MAX'} next unless $VARS; my $SNMPARGS = &GetSNMPArgs($host); if($opt{'debug'}) { print STDERR "$host SNMP Parameters:\n"; foreach $so (keys %SNMPARGS) { print " $so = $SNMPARGS{$so}\n"; } print STDERR "\n"; } if (!defined($s = new SNMP::Session(DestHost => $host, %SNMPARGS))) { $RET = 2 unless $RET > 2; $errmsg = "could not create session to $host: " . $SNMP::Session::ErrorStr; print STDERR "$errmsg\n" if $opt{'debug'}; push (@HOSTS, $host); push (@ERRS, $errmsg); next; } @HE = (); # list of errors for THIS host foreach $var (sort keys %$VARS) { # skip vars that are not in selected group, if any: if($GROUPS ne '') { $g = $$VARS{$var}{'GROUP'}; # assigned group of this variable next if $GROUPS =~ /,-$g,/i; # excluded group next if !($GROUPS =~ /-/) && !($GROUPS =~ /,$g,/i); # included group } $oid = $VARDEF{$var}{'OID'}; @IDX = split(/ +/, $$VARS{$var}{'IDX'}); if(@IDX == ()) { @IDX = (''); } else { $oid .= '.' unless $oid =~ /.+\.$/; } foreach $i (@IDX) { $ioid = $oid . $i; $pi = $i ne '' ? " [$i]" : ''; $descr = $VARDEF{$var}{'DESCR'}; $fn = $FRIENDLYNAME{$host}{$var}{$i} || $VARDEF{$var}{'FNAME'}{$i}; $fn =~ s/^@/$descr /; $vardescr = $fn || $descr . $pi; $rawval = $s->get($ioid); if ($s->{ErrorNum}) { $RET = 2 unless $RET > 2; $errmsg = "error retrieving $host:$var$pi($ioid): " . $s->{ErrorStr}; print STDERR "$errmsg\n" if $opt{'debug'}; push (@HE, $errmsg); next; } $val = eval ($rawval . $VARDEF{$var}{'SCALE'}); $min = $$VARS{$var}{'MIN'}; $max = $$VARS{$var}{'MAX'}; $eq = $$VARS{$var}{'EQ'}; $neq = $$VARS{$var}{'NEQ'}; $minvalid = $$VARS{$var}{'MINVALID'}; $maxvalid = $$VARS{$var}{'MAXVALID'}; $stat = 'OK'; $DEC = $VARDEF{$var}{'DEC'}; $pval = Decode($DEC, $val); $pmin = Decode($DEC, $min); $pmax = Decode($DEC, $max); $peq = Decode($DEC, $eq); $pneq = Decode($DEC, $neq); $pmin = $pmax = $peq if defined($eq); $pmin = $pmax = '!' . $pneq if defined($neq); if(defined($minvalid) && ($val < $minvalid)) { $stat = 'INV<'; syslog('warning', "$host: $vardescr less than lower plausibility limit: $pval"); write if defined $opt{'list'}; next; } if(defined($maxvalid) && ($val > $maxvalid)) { $stat = 'INV>'; syslog('warning', "$host: $vardescr larger than upper plausibility limit: $pval"); write if defined $opt{'list'}; next; } if(defined($min) && ($val < $min)) { $stat = 'FAIL<'; push (@HE, "$vardescr LOW: $pval $VARDEF{$var}{'UNIT'} (<$pmin)"); } if(defined($max) && ($val > $max)) { $stat = 'FAIL>'; push (@HE, "$vardescr HIGH: $pval $VARDEF{$var}{'UNIT'} (>$pmax)"); } if(defined($eq) && ($val != $eq)) { $stat = 'FAIL<>'; push (@HE, "$vardescr: $pval $VARDEF{$var}{'UNIT'} (<> $peq)"); } if(defined($neq) && ($val == $neq)) { $stat = 'FAIL='; push (@HE, "$vardescr: $pval $VARDEF{$var}{'UNIT'} (== $pneq)"); } write if defined $opt{'list'}; } # foreach(index) } # foreach(var) if (@HE) { push (@HOSTS, $host); push (@ERRS, $host . ":\n" . join("\n", @HE)); $RET = 1 unless $RET > 1; # previous error level 2 takes precedence } } # foreach(host) # in case of list output, suppress error listing by exiting here: exit 0 if defined $opt{'list'}; if ($RET) { print "@HOSTS\n\n"; print join("\n", @ERRS), "\n"; } exit $RET; # ---------------------------------------------------------------------- # subroutines begin # ---------------------------------------------------------------------- # # decode enumerations # sub Decode { my ($D, $v) = @_; my $dv; return $v unless $D; # can only decode with valid decoder hash $dv = $$D{$v} || '?'; # look up value return "$dv($v)"; } # # read variable definitions from file # sub ReadVarDef { my ($f) = @_; my ($curvar, $keyword, $param); $curvar = ''; open (CF, $f) || return undef; while () { next if (/^\s*#/ || /^\s*$/); chomp; /^\s*(\w*)\s*(.*)/; $keyword = $1; $param = $2; $curvar = $param if $keyword =~ /Variable/i; if($curvar ne '') { $VARDEF{$curvar}{'OID'} = $param if $keyword =~ /OID/i; $VARDEF{$curvar}{'DESCR'} = $param if $keyword =~ /Descr.*/i; $VARDEF{$curvar}{'UNIT'} = $param if $keyword =~ /Unit/i; $VARDEF{$curvar}{'SCALE'} = $param if $keyword =~ /Scale/i; $VARDEF{$curvar}{'DEFIDX'} = $param if $keyword =~ /DefaultIndex/i; $VARDEF{$curvar}{'DEFGRP'} = $param if $keyword =~ /DefaultGroup/i; $VARDEF{$curvar}{'DEFMIN'} = $param if $keyword =~ /DefaultMin/i; $VARDEF{$curvar}{'DEFMAX'} = $param if $keyword =~ /DefaultMax/i; $VARDEF{$curvar}{'DEFEQ'} = $param if $keyword =~ /DefaultEq/i; $VARDEF{$curvar}{'DEFNEQ'} = $param if $keyword =~ /DefaultNEq/i; $VARDEF{$curvar}{'DEFMINVAL'} = $param if $keyword =~ /DefaultMinValid/i; $VARDEF{$curvar}{'DEFMAXVAL'} = $param if $keyword =~ /DefaultMaxValid/i; if($keyword =~ /Decode/i) { $param =~ /\s*([^\s]+)\s+(.*)$/; $VARDEF{$curvar}{'DEC'}{$1} = $2; } if($keyword =~ /FriendlyName/i) { $param =~ /\s*([^\s]+)\s+(.*)$/; $VARDEF{$curvar}{'FNAME'}{$1} = $2; } } } # while() close (CF); return 1; } # # read list of variables to be monitored # sub ReadVarList { my ($f) = @_; my ($curhost, $curvar, $var, $param); $curhost = ''; open (CF, $f) || return undef; while () { next if (/^\s*#/ || /^\s*$/); chomp; if(/Host\s+(\S+)/i) { $curhost = $1; $curvar = ''; next; } if(/\s+SNMP\s+(\S+)\s+(.+)/i) { next unless $curhost; print "READVARLIST($curhost): SNMP: $1 $2\n"; $SNMP{$curhost}{lc $1} = $2; next; } if(/\s+FriendlyName\s+([^\s]+)\s+(.+)/i) { next unless $curhost; next unless $curvar; $FRIENDLYNAME{$curhost}{$curvar}{$1} = $2; next; } /^\s+(\S+)\s*(.*)$/; $curvar = $1; $param = $2; if($curhost) { $VARLIST{$curhost}{$curvar}{'MIN'} = $VARDEF{$curvar}{'DEFMIN'}; $VARLIST{$curhost}{$curvar}{'MIN'} = $1 if $param =~ /Min\s+([\d\.]+)/i; $VARLIST{$curhost}{$curvar}{'MAX'} = $VARDEF{$curvar}{'DEFMAX'}; $VARLIST{$curhost}{$curvar}{'MAX'} = $1 if $param =~ /Max\s+([\d\.]+)/i; $VARLIST{$curhost}{$curvar}{'EQ'} = $VARDEF{$curvar}{'DEFEQ'}; $VARLIST{$curhost}{$curvar}{'EQ'} = $1 if $param =~ /Eq\s+([\d\.]+)/i; $VARLIST{$curhost}{$curvar}{'NEQ'} = $VARDEF{$curvar}{'DEFNEQ'}; $VARLIST{$curhost}{$curvar}{'NEQ'} = $1 if $param =~ /NEq\s+([\d\.]+)/i; $VARLIST{$curhost}{$curvar}{'MINVALID'} = $VARDEF{$curvar}{'DEFMINVAL'}; $VARLIST{$curhost}{$curvar}{'MINVALID'} = $1 if $param =~ /MinValid\s+([\d\.]+)/i; $VARLIST{$curhost}{$curvar}{'MAXVALID'} = $VARDEF{$curvar}{'DEFMAXVAL'}; $VARLIST{$curhost}{$curvar}{'MAXVALID'} = $1 if $param =~ /MaxValid\s+([\d\.]+)/i; $VARLIST{$curhost}{$curvar}{'IDX'} = $VARDEF{$curvar}{'DEFIDX'}; $VARLIST{$curhost}{$curvar}{'IDX'} = $1 if $param =~ /Index\s+(.+)$/i; $VARLIST{$curhost}{$curvar}{'GROUP'} = $VARDEF{$curvar}{'DEFGRP'}; $VARLIST{$curhost}{$curvar}{'GROUP'} = $1 if $param =~ /Group\s+(.+)$/i; } } # while() close (CF); return 1; } sub ReadSNMPConf { my ($f) = @_; my $tag; my $val; if (-r $f) { print STDERR "\nsnmpvar.monitor: reading SNMP options from $f\n" if $opt{'debug'}; open(SNMPCONF, $f) or die "Huh? $f readable but open fails?"; while() { chomp; next if (/^\s*#/ || /^\s*$/); next unless /^\s*(\S+)\s*=\s*(.+)$/; $SNMPDEF{ lc $1 } = $2; print STDERR "snmpvar.monitor: $1 = $2\n" if $opt{'debug'}; } close SNMPCONF; } print STDERR "\n\n" if $opt{'debug'}; } sub GetSNMPArgs { my ($host) = @_; my $SNMPARGS; # Common options $SNMPARGS{Version} = $SNMP{$host}{version} || $SNMPDEF{version} || 1; $SNMPARGS{RemotePort} = $SNMP{$host}{port} || $opt{'port'} || $SNMPDEF{remoteport} || 161; $SNMPARGS{Retries} = $SNMP{$host}{retries} || $opt{'retries'} || $SNMPDEF{retries} || 8; $SNMPARGS{Timeout} = $SNMP{$host}{timeout} || $opt{'timeout'} || $SNMPDEF{timeout} || 5; # some people may prefer microseconds, but small values should mean seconds: $SNMPARGS{Timeout} *= 1000000 if $SNMPARGS{Timeout} < 1000; # SNMP v.1/v.2 options if ($SNMPARGS{Version} < 3) { $SNMPARGS{Community} = $SNMP{$host}{community} || $opt{'community'} || $SNMPDEF{community} || 'public'; } # SNMP v.3 options if ($SNMPARGS{Version} == 3) { $SNMPARGS{SecName} = $SNMP{$host}{secname} || $SNMPDEF{secname} || 'initial'; $SNMPARGS{SecLevel} = $SNMP{$host}{seclevel} || $SNMPDEF{seclevel} || 'noAuthNoPriv'; $SNMPARGS{AuthPass} = $SNMP{$host}{authpass} || $SNMPDEF{authpass} || ''; $SNMPARGS{SecEngineId} = $SNMP{$host}{secengineid} || $SNMPDEF{secengineid} || ''; $SNMPARGS{ContextEngineId} = $SNMP{$host}{contextengineid} || $SNMPDEF{contextengineid} || ''; $SNMPARGS{Context} = $SNMP{$host}{context} || $SNMPDEF{context} || ''; $SNMPARGS{AuthProto} = $SNMP{$host}{authproto} || $SNMPDEF{authproto} || 'MD5'; $SNMPARGS{PrivProto} = $SNMP{$host}{privproto} || $SNMPDEF{privproto} || 'DES'; $SNMPARGS{PrivPass} = $SNMP{$host}{privpass} || $SNMPDEF{privpass} || ''; } return %SNMPARGS; } format STDOUT_TOP = Host Variable min value max stat ---------------------------------------------------------------------------- . format STDOUT = @<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<< @>>>>> @>>>>>> @<<< @>>>>> @<<<<< $host, $vardescr, $pmin, $pval, $VARDEF{$var}{'UNIT'}, $pmax, $stat . etbemon-1.3.6/mon.d/sslcert.monitor0000700000000000000000000001161714170643320014142 0ustar #!/usr/bin/perl use strict; use warnings; use Getopt::Std; use Data::Dumper; use IO::Socket::INET; use Net::SSLeay qw/XN_FLAG_RFC2253 ASN1_STRFLGS_ESC_MSB/; use Time::Piece; use Net::DNS; Net::SSLeay::randomize(); Net::SSLeay::load_error_strings(); Net::SSLeay::ERR_load_crypto_strings(); Net::SSLeay::SSLeay_add_ssl_algorithms(); # --- commandline options and global variables # -p port - default 443 # -s [0|1] - use HTTPS with SNI (default 1 for port 443) # -4 only use IPv4 our $opt_4; our $opt_p; our $opt_s; getopts ("4p:s:"); my $port = $opt_p || 443; my $sni = 0; my $ipv4_only = 0; if(defined $opt_4) { $ipv4_only = 1; } if(defined $opt_s) { $sni = $opt_s; } elsif($port == 443) { $sni = 1; } # check for less than 2 weeks remaining my $check = time() + 2*7*24*3600; my $summary = ""; my $fullmessage = ""; my $oksummary; my $okmessage = ""; # --- subroutines sub check_cert { my $host = shift; my $addr = shift; my $x509 = shift; my $cnmatch = 0; my $flag_rfc22536_utf8 = (XN_FLAG_RFC2253) & (~ ASN1_STRFLGS_ESC_MSB); if(!$cnmatch) { my @arr = Net::SSLeay::X509_get_subjectAltNames($x509); foreach (@arr) { if($_ eq $host) { $cnmatch = 1; last; } } } my $notbeftmp = Net::SSLeay::P_ASN1_TIME_get_isotime(Net::SSLeay::X509_get_notBefore($x509)); my $notbef = Time::Piece->strptime($notbeftmp, "%Y-%m-%dT%H:%M:%SZ"); if($notbef->epoch > time()) { $summary .= "$host(post dated) "; $fullmessage .= "$host has not before date $notbeftmp in future.\n"; } my $notafttmp = Net::SSLeay::P_ASN1_TIME_get_isotime(Net::SSLeay::X509_get_notAfter($x509)); my $notaft = Time::Piece->strptime($notafttmp, "%Y-%m-%dT%H:%M:%SZ"); if($notaft->epoch < time()) { $summary .= "$host(expired) "; $fullmessage .= "$host($addr) expired at $notafttmp.\n"; } elsif($notaft->epoch < $check) { $summary .= "$host(expires soon) "; $fullmessage .= "$host($addr) expires at $notafttmp.\n"; } else { my $truncdate = substr($notafttmp, 0, 10); if(not $oksummary or 1 == ($oksummary cmp $truncdate)) { $oksummary = $truncdate; } my $okline .= "$host expires " . substr($notafttmp, 0, 10); if(not $okmessage =~ /$okline/) { $okmessage .= $okline . "\n"; } } my $ext_count = Net::SSLeay::X509_get_ext_count($x509); for my $i (0..$ext_count-1) { my $ext = Net::SSLeay::X509_get_ext($x509,$i); my $asn1_object = Net::SSLeay::X509_EXTENSION_get_object($ext); my $nid = Net::SSLeay::OBJ_obj2nid($asn1_object); if(Net::SSLeay::OBJ_nid2ln($nid) eq "commonName" && Net::SSLeay::X509V3_EXT_print($ext) eq $host) { $cnmatch = 1; } } if(not $cnmatch) { $summary .= "$host(no commonName in cert) "; $fullmessage .= "$host doesn't have it's name as a commonName or altName\n"; } } foreach my $host (@ARGV) { my $res = Net::DNS::Resolver->new; my $query = $res->query($host, "A"); my $rr; my @addresses; if($query) { foreach $rr (grep { $_->type eq 'A' } $query->answer) { push(@addresses, $rr->address); } } if($ipv4_only != 1) { $query = $res->query($host, "AAAA"); if($query) { foreach $rr (grep { $_->type eq 'AAAA' } $query->answer) { push(@addresses, $rr->address); } } } if(scalar(@addresses) == 0) { $summary .= "$host(not found) "; $fullmessage .= "No A or AAAA record for $host.\n"; next; } foreach my $addr (@addresses) { my $sock = IO::Socket::IP->new(PeerAddr => $addr, PeerPort => $port, Proto => 'tcp'); if(!$sock) { if(not $summary =~ /$host.unavailable/) { $summary .= "$host(unavailable) "; } $fullmessage .= "Can't connect to $host($addr) port $port via TCP.\n"; next; } my $ctx = Net::SSLeay::CTX_new() or die "ERROR: CTX_new failed"; my $ssl; if(not $ctx or not Net::SSLeay::CTX_set_options($ctx, &Net::SSLeay::OP_ALL) or not ($ssl = Net::SSLeay::new($ctx))) { print "Internal error\nCan't create SSL context\n"; exit(1); } if($sni && not Net::SSLeay::set_tlsext_host_name($ssl, $host)) { print "Internal error\nCan't set SNI for $host\n"; exit(1); } if(not Net::SSLeay::set_fd($ssl, fileno($sock))) { print "Internal error\nCan't set fd for SSL\n"; exit(1); } if(not Net::SSLeay::connect($ssl)) { $summary .= "$host(Can't connect SSL) "; $fullmessage .= "Can't connect SSL for $host, internal error?\n"; next; } my $x509 = Net::SSLeay::get_peer_certificate($ssl); if(not $x509) { $summary .= "$host(no SSL cert) "; $fullmessage .= "$host port $port doesn't give certificate, not SSL server?\n"; next; } check_cert($host, $addr, $x509); } } if($summary) { print "$summary\n"; print $fullmessage; exit(1); } else { print "Expiry $oksummary\n"; print "$okmessage"; } etbemon-1.3.6/mon.d/tcp.monitor0000755000000000000000000000462410230411543013254 0ustar #!/usr/bin/perl -w # # try to connect to a particular # port on a bunch of hosts. For use with "mon". # # Arguments are "-p port host [host...]" # # Jim Trocki, trockij@arctic.org # # $Id: tcp.monitor,v 1.2 2005/04/17 07:42:27 trockij Exp $ # # Copyright (C) 1998, Jim Trocki # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # use Getopt::Std; use Socket; my %opt; getopts ("p:t:", \%opt); my $PORT = $opt{"p"} || 23; my $TIMEOUT = $opt{"t"} || 10; my @failures = (); my @detail = (); my $ALARM = 0; foreach my $host (@ARGV) { my $pro = getprotobyname ('tcp'); if (!defined $pro) { die "could not getprotobyname\n"; } if (!defined socket (S, PF_INET, SOCK_STREAM, $pro)) { die "could not create socket: $!\n"; } my $a = inet_aton ($host); if (!defined $a) { push @failures, $host; push @detail, "$host could not inet_aton"; close (S); next; } my $sin = sockaddr_in ($PORT, $a); if (!defined $sin) { push @failures, $host; push @detail, "$host could not sockaddr_in"; close (S); next; } my $r; eval { local $SIG{"ALRM"} = sub { die "alarm\n" }; alarm $TIMEOUT; $r = connect (S, $sin); alarm 0; }; if ($@) { push @failures, $host; if ($@ eq "alarm\n") { push @detail, "$host timeout"; } else { push @detail, "$host interrupted syscall: $!"; } close (S); next; } if (!defined $r) { push @failures, $host; push @detail, "$host could not connect: $!"; close (S); next; } if (!defined close (S)) { push @failures, $host; push @detail, "$host could not close socket: $!"; next; } } if (@failures == 0) { exit 0; } print join (" ", sort @failures), "\n"; print "\n", join ("\n", @detail), "\n"; exit 1; etbemon-1.3.6/mon.d/telnet.monitor0000755000000000000000000000373610230411543013764 0ustar #!/usr/bin/perl # # Use Net::Telnet to connect to a list of hosts. # # -p port connect to 'port' (defaults to 23) # -t secs set timeout to 'secs' (defaults to 10) # -l '/regex/' wait for /regex/, (defaults to "/ogin:/i") # # Arguments are "host [host...]" # # Jim Trocki, trockij@arctic.org # # $Id: telnet.monitor,v 1.2 2005/04/17 07:42:27 trockij Exp $ # # Copyright (C) 1998, Jim Trocki # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # use Net::Telnet; use Getopt::Std; getopts ("l:p:t:"); $TIMEOUT = $opt_t || 10; $PORT = $opt_p || 23; $LOGIN = $opt_l || "/ogin:/i"; @failures = (); foreach my $host (@ARGV) { my $t = new Net::Telnet ( Timeout => $TIMEOUT, Port => $PORT, ); if (!defined $t) { push @failures, [$host, "could not create new Net::Telnet object"]; next; } $t->errmode ("return"); if (!defined $t->open ($host)) { push @failures, [$host, $t->errmsg]; next; } my $ok = $t->waitfor ( Match => $LOGIN, Timeout => $TIMEOUT, ); if (!defined $ok) { push @failures, [$host, "did not get prompt: ". $t->errmsg]; } $t->close; } if (@failures == 0) { exit 0; } for (@failures) { push @l, $_->[0]; } print join (" ", sort @l), "\n"; for (@failures) { print "$_->[0]: $_->[1]\n"; } exit 1; etbemon-1.3.6/mon.d/trace.monitor0000755000000000000000000003103510146140377013572 0ustar #!/usr/bin/perl # # trace.monitor # # trace the route to an address, record previous routes, # compare newest path to last path and report divergences # while considering load-balanced hops, and log paths # historically. # # for use with mon # # use "trace.monitor -h" for help # # Jim Trocki # # $Id: trace.monitor,v 1.2 2004/11/15 14:45:19 vitroth Exp $ # # Copyright (C) 2001-2003, Jim Trocki # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # use strict; use Getopt::Std; use Data::Dumper; sub traceroute; sub print_path; sub load_last; sub path_to_string; sub debug; sub path_to_hash; sub test; sub append_log; sub print_hop; sub usage; sub process_hosts; my %opt; getopts ('hLs:l:d:t:m:', \%opt); if ($opt{"h"}) { usage; exit; } die "must supply host\n" if (@ARGV == 0); my $TIMEOUT = $opt{"t"} || 30; my $DEBUG = $opt{"d"} || 0; my $METHOD = "m"; if ($opt{"m"} ne "" && $opt{"m"} !~ /^[mn]$/) { die "method must be one of 'n' or 'm'\n"; } if ($opt{"m"}) { $METHOD = $opt{"m"}; } #my $LOGDIR = "/var/lib/mon/log.d"; #my $STATEDIR = "/var/lib/mon/state.d"; my $LOGDIR = "."; my $STATEDIR = "."; if (-d $opt{"l"}) { $LOGDIR = $opt{"l"}; } elsif (-d $ENV{"MON_LOGDIR"}) { $LOGDIR = $ENV{"MON_LOGDIR"}; } if (-d $opt{"s"}) { $STATEDIR = $opt{"s"}; } elsif (-d $ENV{"MON_STATEDIR"}) { $STATEDIR = $ENV{"MON_STATEDIR"}; } # # do the testing on each host # my ($failures, $failure_detail, $successes, $success_detail) = process_hosts (@ARGV); # # all the testing/logging is done, # now report the successes and failures # my $num_failures = @{$failures}; if ($num_failures) { print "@{$failures}\n"; } else { print "\n"; } for (my $i = 0; $i < @{$failures}; $i++) { print "$failures->[$i]\n--------------------\n"; print "$failure_detail->[$i]\n"; print "\n"; } if ($num_failures) { print "\n"; } for (my $i = 0; $i < @{$successes}; $i++) { print "$successes->[$i]\n---------------------------\n"; print "$success_detail->[$i]\n"; print "\n"; } exit $num_failures; # # print path # # if second arg is true, return the string # instead of printing it # sub print_path { my ($path, $str) = @_; my $string = ""; for (my $i= 0; $i < @{$path->{"path"}}; $i++) { my $hop = $path->{"path"}->[$i]; my @h = (); foreach my $list (@{$hop}) { push @h, sprintf ('%-15s %-10s', $list->[0], $list->[1]); } if ($str) { $string .= sprintf ("%02d %s\n", $i, "@h"); } else { printf ("%02d %s\n", $i, "@h"); } } $string; } sub print_hop { my ($path, $hopnum) = @_; my $hop = $path->{"path"}->[$hopnum]; my @h = (); foreach my $list (@{$hop}) { push @h, sprintf ('%-15s %-10s', $list->[0], $list->[1]); } sprintf ("%02d %s\n", $hopnum, "@h"); } sub save_last { my ($f, $p) = @_; if (!open (OUT, ">$f")) { return "$!"; } if (!$p->{"time"}) { print OUT time . " "; } else { print OUT "$p->{time} "; } print OUT "$p->{to} "; print OUT path_to_string ($p), "\n"; close (OUT); ""; } sub append_log { my ($f, $p) = @_; if (!open (OUT, ">>$f")) { return "$!"; } if (!$p->{"time"}) { print OUT time . " "; } else { print OUT "$p->{time} "; } print OUT "$p->{to} "; print OUT path_to_string ($p), "\n"; close (OUT); ""; } sub load_last { my ($f) = @_; if (!open (IN, $f)) { return "$!"; } my ($time, $path, $to); while () { next if (/^\s*#/ || /^\s*$/); chomp; next if (!/^\d+\s/); ($time, $to, $path) = split (/\s+/, $_); last; } close (IN); if ($path eq "") { return ("no path found in file"); } my %p; $p{"time"} = $time; $p{"to"} = $to; $p{"path"} = string_to_path ($path); $p{"hpath"} = path_to_hash ($p{"path"}); ("", { %p }); } sub path_to_string { my ($path) = @_; my @formatted_path; foreach my $hop (@{$path->{"path"}}) { my @tries = (); foreach my $hop_try (@{$hop}) { push @tries, "$hop_try->[0]/$hop_try->[1]"; } push @formatted_path, join (",", @tries); } join ("-", @formatted_path); } sub string_to_path { my ($string) = @_; my @path; foreach my $hop (split (/-/, $string)) { my @tries = (); foreach my $try (split (/,/, $hop)) { push @tries, [split (/\//, $try)]; } push @path, [@tries]; } [@path]; } sub save_path { my ($file, $path) = @_; } # # returns -1 if paths do not diverge, # or the index into @{$path1} where they do. # sub compare_paths { my ($path1, $path2, $behavior) = @_; # # $behavior is one of: # "n" normal # "m" mux mode, treat all routes on the same hop as # equals # my $i = 0; my $diverge = -1; while ($i < @{$path1->{"path"}} && $diverge == -1) { debug ("comparing hop $i"); # # path1 is longer than path2 # if ($i >= @{$path2->{"path"}}) { debug ("path1 longer than path2"); $diverge = $i; last; } else { # # MUX method # # no divergence if at least one of the routers for this # hop matches with the last sample. this is an attempt # to consider load-balanced hops. # # if ($behavior eq "m") { debug ("comparing using mux"); my $found = 0; foreach my $ip (keys %{$path1->{"hpath"}->[$i]}) { if ($path2->{"hpath"}->[$i]->{$ip} > 0) { debug ("found matching route at $i"); $found = 1; last; } } if (!$found) { debug ("did not find matching router at pos $i"); $diverge = $i; last; } } # # DEFAULT method # # default is to compare all routers for each hop # between path samples, and if they differ at all, # then consider it a divergence. # else { debug ("comparing using default"); # # hop tries differ # if (@{$path1->{"path"}->[$i]} != @{$path2->{"path"}->[$i]}) { $diverge = $i; last; } else { for (my $j = 0; $j < @{$path1->{"path"}->[$i]}; $j++) { if ($path1->{"path"}->[$i]->[$j]->[0] ne $path2->{"path"}->[$i]->[$j]->[0]) { debug ("found divergence index $j"); $diverge = $i; last; } else { debug ("no divergence index $j"); } } } } } $i++; } if ($diverge != -1 && @{$path1->{"path"}} != @{$path2->{"path"}}) { debug ("path lengths differ"); return $#{$path1->{"path"}}; } return $diverge; } # # traceroute to a host and return a data structure of the hops # and timings # # returns the list: # ( # "error msg, empty string if no error", # { # "path" => # [ # [["hop1 try1", ms], ["hop1 try2", ms], ["hop1 try3", ms]], # [["hop2 try2", ms], ...], # ... # ], # "hpath" => # [ # {"ipaddr" => count, ...}, # ], # } # ) # sub traceroute { my ($host, $timeout, $traceroute_args) = @_; my $pid; if (!($pid = open (IN, "traceroute -n $traceroute_args $host 2>/dev/null |"))) { return ($!, []); } my $hop = 0; my @hops = (); my @hash_hops = (); if ($timeout) { $SIG{"ALRM"} = sub {die "timeout" }; } eval { if ($timeout) { alarm ($timeout); } while () { if (!/^\s*\d+/) { debug ("skipping $_"); next; } my $line = $_; chomp $line; $line =~ s/^\s*//; debug ($line, 5); my @l = split (/\s+/, $line); $hop = shift @l; my @hoplist = (); my %hophash = (); my $i = 0; my $router = ""; while ($i < @l) { if ($l[$i] =~ /^\d+\.\d+\.\d+\.\d+$/) { $router = $l[$i]; $i++; } # # timeout # elsif ($l[$i] eq "*") { push @hoplist, ["*", 0]; $hophash{"*"}++; $i++; next; } # # a real router reply # if ($router ne "") { if ($l[$i+1] ne "ms") { close (IN); return ("expecting ms [$line]", []); } my $time = $l[$i]; $i += 2; push @hoplist, [$router, $time]; $hophash{$router}++; # # skip over failures # if ($l[$i] =~ /^!/) { $i++; } } else { close (IN); return ("don't know [$line]", []); } } push @hops, [@hoplist]; push @hash_hops, {%hophash}; } if ($timeout) { alarm (0); } }; close (IN); if ($@ && $timeout && $@ =~ /timeout/) { kill 9, $pid; push @hops, [["timeout", $timeout]]; return ("timeout", [@hops]); } my $t = time; ("", { "path" => [@hops], "hpath" => [@hash_hops], "time" => $t, "to" => $host, }); } sub debug { my ($msg, $level) = @_; if ($DEBUG && $level <= $DEBUG) { print STDERR "$msg\n"; } } sub path_to_hash { my $path = shift; my @new_path = (); for (my $i = 0; $i < @{$path}; $i++) { my $hop = $path->[$i]; for (my $j = 0; $j < @{$hop}; $j++) { $new_path[$i]->{$hop->[$j]->[0]}++; } } [@new_path]; } sub test { my ($msg, $path1, $path2) = @_; $path1->{"hpath"} = path_to_hash ($path1->{"path"}); $path2->{"hpath"} = path_to_hash ($path2->{"path"}); print "BEGIN: $msg\n"; my $r = compare_paths ($path1, $path2, "m"); if ($r == -1) { print "END: $msg no divergence\n"; } else { print "END: $msg divergence at $r\n"; } } sub usage { print <{"path"}}; $i++) { my $l_hop = print_hop ($last, $i); my $n_hop = print_hop ($p, $i); my $s = " "; if ($i == $diverge) { $s = "* "; } $l_hop = "$s$l_hop"; $n_hop = "$s$n_hop"; $old_pathstr .= "$l_hop"; $new_pathstr .= "$n_hop"; } push @failure_detail, "divergence at hop $diverge\n" . "old: " . print_hop ($last, $diverge) . "new: " . print_hop ($p, $diverge) . "\n" . "was: " . localtime ($last->{"time"}) . "\n$old_pathstr\n" . "is: " . localtime ($p->{"time"}) . "\n$new_pathstr\n"; } } if ($diverge == -1 || !defined $diverge) { push @successes, $host; push @success_detail, "at " . localtime ($p->{"time"}) . "\n" . print_path ($p, 1) . "\n"; } } ([@failures], [@failure_detail], [@successes], [@success_detail]); } etbemon-1.3.6/mon.d/traceroute.monitor0000755000000000000000000004300310630536553014652 0ustar #!/usr/bin/perl # # mon monitor to watch for route changes # # There is currently a hardcoded path to the traceroute binary, see $TRACEROUTE # but it can be overriden in the config file. # # Jon Meek - 31-May-1999 (original code) # # # Jon Meek # Lawrenceville, NJ # meekj at ieee.org # # $Id: traceroute.monitor,v 1.2.2.1 2007/06/03 13:08:59 trockij Exp $ # # Copyright (C) 2001-2005, Jon Meek # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # =head1 NAME B - Route monitor for mon. =head1 DESCRIPTION Monitor routes from monitor machine to a remote system using traceroute. Alarm and log when changes are detected. =head1 SYNOPSIS B The logfile template is usually specified in the configuration file. =head1 OPTIONS =over 5 =item B<-d> Debug/Test =item B<-c config.cfg> Configuration file for this monitor, see example below =item B<-t timeout> Timeout for traceroute to run in seconds default is 20s =item B<-l log_file_template> /path/to/logs/internet_web_YYYYMM.log Current year & month are substituted for YYYYMM, that is the only possible template at this time. =item B<-u> Fail On Unexpected Hop Only - An alert will be triggered if any of the IP addresses specified using the UnexpectedHop item in the configuration file are observed. Any other route change will not create an alert. This option is useful for alerting when a backup circuit becomes part of a default route. This option causes traceroute.monitor to act more like a traditional mon monitor because an alert will be triggered on every monitor run if an UnexpectedHop appears in the path. The use of mon's alertafter N directive can be used to filter out short term glitches that might cause a route to change for just one monitor cycle. =back =head1 MON CONFIGURATION EXAMPLE hostgroup route1 rt-tb-paris-26 rt-tb-london-18 rt-tta-pr01r00-4 rt-cam-cer001-5 rt-tta-pn01r00-4 watch route1 service traceroute interval 15m monitor traceroute.monitor -c /usr/local/mon/traceroute.cf period wd {Sun-Sat} alert mail.alert meekj alertevery 1h summary =head1 CONFIGURATION FILE EXAMPLE # traceroute.monitor Config File RouteLogFile /usr/local/mon/logs/routes_YYYYMM.log RouterList /usr/local/mon/rt.list Traceroute /usr/sbin/traceroute TracerouteOptions -I StateDir /usr/local/mon/state.d EquivIP 10.22.4.254 10.22.5.254 10.22.6.254 EquivIP 10.28.4.254 10.28.5.254 10.28.6.254 StopAt 172.30.124.17 A firewall StopAt 172.31.124.17 Another firewall UnexpectedHop 10.22.249.2 S2S VPN Tunnel AlertMessage For more details see: http://$HOSTNAME/cgi-bin/network/traceroute.anal EndAlertMessage Lines with '#' in the first column are ignored. RouteLogFile - A new log file will be created each month in the above example the files will be of the form routes_199810.log The YYYYMM format is the only date string possible in the current version The logs contain time stamped route changes. RouterList - Optional IP address to router name translation in /etc/hosts format (IP_address router_name). Supplying this list will provide considerably more meaningful alarm messages, especially if the router names contain geographical information. Without this list, or DNS records, the extended alarm is just a list of interface IP addresses. DNS results take precedence over this list. Traceroute - Overrides the default of /usr/sbin/traceroute TracerouteOptions - Supply additional options to traceroute. -I tells traceroute to use ICMP rather than UDP on some systems. Note that -n is always supplied so that no DNS lookups are performed. StateDir - Overrides the default path of the mon environment variable MON_STATEDIR. Files named F contain the last observed route. EquivIP - A space separated list of IP addresses that should be considered equivalent for the purposes of determining route changes. Likely used where there are secondary addresses on router or switch interfaces. StopAt - A single IP address followed by an optional comment. The traceroute will be terminated when this address is seen. This allows a route check to a system on another network, such as the Internet, without tracking the route on a network that you do not control. A common use would be to put your firewall address in a StopAt directive. There can be multiple StopAt lines. UnexpectedHop - See the description of the -u option above. The presence of an UnexpectedHop in a path will trigger an alarm regardless of whether the -u option is set, or not. AlertMessage - A message that is appended to the alert details starts on the next line. $HOSTNAME, if present in the message, is converted to the name of the machine on which the monitor is running. EndAlertMessage - The AlertMessage can be terminated by this directive, but it is not required if the message is at the end of the configuration file. =head1 BUGS There probably are some. =head1 AUTHOR Jon Meek, meekj@ieee.org =head1 SEE ALSO F - A CGI script to display route change information. =cut use Getopt::Long; use Sys::Hostname; use POSIX qw(:signal_h WNOHANG strftime); use Socket; #getopts ("vdt:l:c:"); GetOptions ('v' => \$opt_v, 'd' => \$opt_d, 'debug' => \$opt_d, 't=i' => \$opt_t, 'l=s' => \$opt_l, 'c=s' => \$opt_c, 'u' => \$FailOnUnexpectedHopOnly, 'unexpectedhoponly' => \$FailOnUnexpectedHopOnly, ); # -l file Log file name with optional YYYYMM part that will be transformed to current month $TimeOut = $opt_t || 20; # Set default timeout in seconds # Usual Linux config $TRACEROUTE = '/bin/traceroute'; #$STATE_DIR = '/usr/local/mon/state.d'; if (defined $ENV{MON_STATEDIR}) { # Are we running under mon? $STATE_DIR = $ENV{MON_STATEDIR}; $RunningUnderMon = 1; } else { $RunningUnderMon = 0; } if ($opt_c) { # Read configuration file $ConfigFile = $opt_c; if (open(C, $ConfigFile)) { while ($in = ) { last if ($in =~ /^Exit/i); next if ($in =~ /^\#/); # Comments chomp $in; if ($in =~ /^RouteLogFile\s+/i) { ($tag, $LogFile) = split(' ', $in, 2); next; } if ($in =~ /^Traceroute\s+/i) { # Need whitespace to distinguish this option ($tag, $TRACEROUTE) = split(' ', $in, 2); next; } if ($in =~ /^TracerouteOptions\s+/i) { ($tag, $TracerouteOptions) = split(' ', $in, 2); next; } if ($in =~ /^RouterList\s+/i) { ($tag, $RouterListFile) = split(' ', $in, 2); next; } if ($in =~ /^StateDir\s+/i) { # If the mon environment variable needs to be overriden ($tag, $STATE_DIR) = split(' ', $in, 2); next; } if ($in =~ /^EquivIP\s+/i) { ($tag, $ips) = split(' ', $in, 2); (@ip_list) = split(' ', $ips); # $ip_string = " $ips "; # Each IP is surrounded by whitespace foreach $ip (@ip_list) { $EquivIP{$ip} = [ @ip_list ]; } next; } if ($in =~ /^StopAt\s+/i) { ($tag, $stop_addr, $stop_comment) = split(' ', $in, 3); $StopAddress{$stop_addr}++; $StopComment{$stop_addr} = $stop_comment; next; } if ($in =~ /^UnexpectedHop\s+/i) { ($tag, $ip, $name) = split(' ', $in, 3); print "UnexpectedHop $ip, $name
\n" if $opt_d; $UnexpectedHop{$ip}++; $UnexpectedHopName{$ip} = $name; } if ($in =~ /^AlertMessage/i) { # Extra text to add to an alert starts on next line while ($in = ) { last if ($in =~ /^EndAlertMessage/i); $AlertMessage .= $in; } $MonitorHostname = hostname; $AlertMessage =~ s/\$HOSTNAME/$MonitorHostname/; } } } else { print "traceroute.monitor: Couldn't open $ConfigFile configuration file\n"; exit 1; } } if ($opt_l) { # Command line overrides config file $LogFile = $opt_l; } if ((defined $RouterListFile) && $opt_v) { # Read the router names now open(F, $RouterListFile); while ($in = ) { chomp $in; ($ip, $name) = split(' ', $in, 2); $RouterByIP{$ip} = $name; } close F; } @Failures = (); @Hosts = @ARGV; # Host names are left on the command line after Getopt if ($TestOnly) { foreach $h (@Hosts) { $name = &HopName($h); print "Host: $h $name\n"; if (defined $EquivIP{$h}) { print " Has equivalent IP\n"; } } $ip1 = $Hosts[0]; $ip2 = $Hosts[1]; $equiv_check = grep /^$ip2$/, @{ $EquivIP{$ip1} }; print "$ip1 $ip2 $equiv_check\n"; @equiv_arr = grep /^$ip2$/, @{ $EquivIP{$ip1} }; print "$ip1 $ip2 @equiv_arr\n"; foreach $ip (@equiv_arr) { print " $ip\n"; } exit; } # # Reap children to avoid defunct processes / zombies # See "Network Programming with Perl" by Lincoln Stein # sub Reaper { while ((my $child_pid = waitpid(-1, WNOHANG)) > 0) { print "Reaped child: $child_pid\n" if $opt_d; } } sub OtherSIGs { print "traceroute.monitor Exiting on Signal\n"; exit 1; } $SIG{CHLD} = \&Reaper; $SIG{HUP} = $SIG{INT} = $SIG{QUIT} = $SIG{TERM} = \&OtherSIGs; # # Run traceroute for each destination, collect route # foreach $TargetHost (@Hosts) { $TimeOfDay = time; $FmtTimeOfDay = strftime("%A %d-%b-%Y %H:%M:%S %Z", localtime($TimeOfDay)); @HopList = (); # Initialize hop list for this traceroute to $TargetHost $cmd = qq{$TRACEROUTE -n $TracerouteOptions $TargetHost 2>/dev/null |}; print "Options: ->$TracerouteOptions<-\nCommand: $cmd\n" if $opt_d; eval { $SIG{ALRM} = sub {die "timeout" }; print "Setting timeout to $TimeOut s\n" if $opt_d; alarm($TimeOut); eval { # discard STDERR data from traceroute $pid = open(TR, $cmd) || die "Couldn't run traceroute\n"; print "$FmtTimeOfDay Traceroute to $TargetHost pid: $pid\n" if $opt_d; while ($in = ) { print $in if $opt_d; if ($in =~ /\*\s+\*\s+\*/) { # Get * * * then give up push(@HopList, '*'); # Indicate that the traceroute did not complete kill 13, $pid; # 13 = PIPE, prevents Broken Pipe Error, at least on Solaris last; } # We will only pick up the first IP address listed on a line for now # Get IP address into $1 $in =~ /\s+(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s+/; $ThisHopIP = $1; push(@HopList, $ThisHopIP); # Build route hop list if ($UnexpectedHop{$ThisHopIP}) { $UnexpectedHopSeen{$TargetHost}++; } if ($opt_v) { chomp $in; $name = &HopName($h); print "$in $name $RouterByIP{$ThisHopIP}\n"; } if (exists $StopAddress{$ThisHopIP}) { print "Stopping at $ThisHopIP $StopComment{$ThisHopIP}\n\n" if $opt_v; kill 'TERM', $pid; # Terminate the traceroute alarm(0); return; # May be correct way to leave eval, instead of last } } alarm(0); }; alarm(0); }; if ($@) { # Check for SIG if ($@ =~ /timeout/) { # It was a traceroute timeout print "Traceroute timeout\n" if $opt_d; push(@HopList, '*'); # Indicate that the traceroute did not complete kill 13, $pid; # 13 = PIPE, prevents Broken Pipe Error, at least on Solaris } else { print "Exiting due to some other alarm\n" if $opt_d; die; # Some other problem } } close TR; $route =~ s/\-$//; # Remove trailing '-' from route string $previous_hop = ''; $route = ''; foreach $h (@HopList) { $route .= "$h-" unless ($h eq $previous_hop); $previous_hop = $h; } $route =~ s/\-$//; # Remove trailing '-' from route string $ResultString{$TargetHost} = "$TimeOfDay $TargetHost $route"; if ($opt_d) { print "$TargetHost: $ResultString{$TargetHost}\n"; print " $route\n"; } } $FmtTimeOfDay = strftime("%A %d-%b-%Y %H:%M:%S %Z", localtime(time)); print "$FmtTimeOfDay finish $TargetHost pid: $pid\n\n" if $opt_d; # # Compare just measured routes with previous route stored in state file # or just make the state file if this is the first time for a destination # # TODO: if new destination (no state file), then log route to log file # add IP to name translation for mail messages foreach $k (sort keys %ResultString) { print "$ResultString{$k}\n" if $opt_d; $state_file = "$STATE_DIR/lastroute.$k"; if (-e $state_file) { # We have checked this route before, compare current ($t2, $host2, $current_route) = split(' ', $ResultString{$k}); open(S, $state_file) || warn "Can't open $state_file for reading\n"; $in = ; chomp $in; ($t1, $host1, $prev_route) = split(' ', $in); close S; if ($opt_d) { print "Previous route for $host1 -$prev_route-\n"; print "Current route for $host2 -$current_route-\n"; } $ThisTargetFailed = 0; $ThisTargetFailed++ if $UnexpectedHopSeen{$k}; if (&RouteChanged($current_route, $prev_route)) { # Route changed, record, alarm if not using only unexpected hops $ThisTargetFailed++ unless $FailOnUnexpectedHopOnly; $LogString{$k} = $ResultString{$k}; # Use separate string for logging route changes so that we don't always log unexpected hops if ($RunningUnderMon) { # Write results open(S, ">$state_file") || warn "Can't open $state_file for writing\n"; print S "$ResultString{$k}\n"; close S; } } if ($ThisTargetFailed) { push (@Failures, $k); print " Alarm\n" if $opt_d; } } else { # The state file does not yet exist, so make it if ($RunningUnderMon) { # Write results open(S, ">$state_file") || warn "Can't open $state_file for writing\n"; print S "$ResultString{$k}\n"; close S; } # $LogString{$k} = $ResultString{$k}; # Always log the first instance push (@Failures, $k); # Call it a failure so it will be logged and notification will be sent print " New route added to check: $k\n" if $opt_d; } } # # Write results to logfile # if ($LogFile) { ($sec,$min,$hour,$mday,$Month,$Year,$wday,$yday,$isdst) = localtime($TimeOfDay); $Month++; $Year += 1900; $YYYYMM = sprintf('%04d%02d', $Year, $Month); $LogFile =~ s/YYYYMM/$YYYYMM/; # Fill in current year and month if (-e $LogFile) { # Check for existing log file $NewLogFile = 0; } else { $NewLogFile = 1; } if ($NewLogFile || (@Failures > 0)) { # Only log if new log file, or if route changes open(LOG, ">>$LogFile") || warn "$0 Can't open logfile: $LogFile\n"; if ($NewLogFile) { # New log file, record all routes being tested foreach $host (sort keys %ResultString) { print LOG "$ResultString{$host}\n"; } } if (($NewLogFile == 0) && (@Failures > 0)) { # Just record changes, not repeated unexpected hops foreach $host (sort keys %LogString) { print LOG "$LogString{$host}\n"; } } close LOG; } } if (@Failures == 0) { # Exit if there were no failures exit 0; } # Note that we might have already read this file if --v was specified # if (defined $RouterListFile) { # Read the router names if we have a failure open(F, $RouterListFile); while ($in = ) { chomp $in; ($ip, $name) = split(' ', $in, 2); $RouterByIP{$ip} = $name; } close F; } @SortedFailures = sort @Failures; # To make summary mode in mon happy print "@SortedFailures\n"; foreach $host (@SortedFailures) { print "$host:\n"; ($t, $target, $rest) = split(' ', $ResultString{$host}); (@hop_ips) = split(/\-/, $rest); foreach $hop_ip (@hop_ips) { $name = &HopName($hop_ip); printf " %-15s %s", $hop_ip, $name; print " Unexpected Hop: $UnexpectedHopName{$hop_ip}" if ($UnexpectedHop{$hop_ip}); print "\n"; } print "\n"; } if (defined $AlertMessage) { print "\n$AlertMessage\n"; } exit 1; sub RouteChanged { my ($current_route, $prev_route) = @_; my(@current_ips, @prev_ips); if ($current_route eq $prev_route) { # Simple case, same string, no change return 0; } (@current_ips) = split(/\-/, $current_route); (@prev_ips) = split(/\-/, $prev_route); if ($#current_ips != $#prev_ips) { # Another simple case, different number of hops return 1; # Fail } for ($i = 0; $i <= $#current_ips; $i++) { $ip1 = $current_ips[$i]; $ip2 = $prev_ips[$i]; next if ($ip1 eq $ip2); $equiv_check = grep /^$ip2$/, @{ $EquivIP{$ip1} }; if ($equiv_check == 0) { # Not same, or equivalent, route different, fail return 1; } print "$i $ip1 $ip2 $equiv_check\n" if $opt_d; } return 0; # Good, no route change } sub HopName { my ($h_ip) = @_; my ($lookupname, $ha); # print "HopName: $h_ip
\n" if $opt_d; if ($h_ip =~ /^\*/) { $name = 'Not reached'; return $name; } if (exists $HopNameCache{$h_ip}) { # Already have the name $name = $HopNameCache{$h_ip}; return $name; } $name = ''; $ha = inet_aton($h_ip); $lookupname = gethostbyaddr($ha, &AF_INET); if (length($lookupname) > 0) { # Attempt lookup of address via "normal" system methods (DNS, hosts, etc) $name = $lookupname; } elsif ($UseRouterList) { $name = $RouterByIP{$h_ip} if (exists $RouterByIP{$h_ip}); } # Have an auxilliary name? such as "London Internet Router", prepend it # $name = qq{$RouteHopName{$h_ip} $name} if (exists $RouteHopName{$h_ip}); $HopNameCache{$h_ip} = $name; # print "$h_ip -- $name
\n" if $opt_d; return $name; } etbemon-1.3.6/mon.d/up_rtt.monitor0000755000000000000000000001706110146140377014014 0ustar #!/usr/bin/perl # # mon monitor to check for circuit up and measure RTT # # # Jon Meek - 09-May-1998 # # Requires Perl Modules "Time::HiRes" and "Statistics::Descriptive" # # # # $Id: up_rtt.monitor,v 1.2 2004/11/15 14:45:19 vitroth Exp $ # # Copyright (C) 1998, Jon Meek, meekj@ieee.org # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # mon config file watch entry: #watch frame-relay # service up_rtt # interval 5m # monitor up_rtt.monitor -T 2 -l /my/log_directory/logs/wan/fr_rtt_YYYYMM.log # period wd {Sun-Sat} # alert mail.alert meekj # alertevery 1h # A new log file will be created each month in the above example the files will # be of the form fr_rtt_199810.log # The YYYYMM format is the only date string possible in the current version use Getopt::Std; use Socket; use IO::Socket; use Time::HiRes qw( gettimeofday tv_interval ); use Statistics::Descriptive; getopts ("drt:T:l:U:"); # -d Debug mode # -p # -t n Number of seconds to wait for a packet to be echoed back # -T n Alarm if the minimum measured RTT is greater than n seconds # -l file Log file name with optional YYYYMM part that will be transformed to current month # -U num Number of UDP packets to send # -r Log individual raw RTTs $TimeOut = $opt_t || 10; # Timeout in seconds $NUM_UDP_TRYS = $opt_U || 5; # Number of UDP packets to send # Solaris MSG_WAITALL 0x40 /* Wait for complete recv or error */ #linux/socket.h:#define MSG_WAITALL 0x100 /* Wait for a full request */ # $RecvRet = recv($S, $Echo, $DataLength, 64); # Solaris & older versions of Linux #$RecvFlags = 0; # May work on all systems due to small packets used here #$RecvFlags = 64; # Hardcode for Solaris #$RecvFlags = 256; # Hardcode for Linux 2.2.x $RecvFlags = &MSG_WAITALL; # Requires that h2ph was run on the appropriate include directory print "MSG_WAITALL: $RecvFlags\n" if $opt_d; @Failures = (); @Hosts = @ARGV; # Host names are left on the command line after Getopt $GoodPackets = 0; foreach $TargetHost (@Hosts) { undef @RawRTT; $stat = Statistics::Descriptive::Full->new(); $TimeOfDay = time; $ReturnedPackets = &UDPcheck($TargetHost); # Try UDP echo first if ($ReturnedPackets == 0) { # If the UDP ping failed, then try TCP ($ReturnedPackets, $RTT) = &TCPcheck($TargetHost); $ResultString{$TargetHost} = sprintf "%d %s %0.4f T", $TimeOfDay, $TargetHost, $RTT; if ($opt_d) { print "$ResultString{$TargetHost}\n"; } } else { $min = $stat->min(); $mean = $stat->mean(); $max = $stat->max(); $count = $stat->count(); if ($opt_r && (defined @RawRTT)) { $ResultString{$TargetHost} = sprintf "%d %s", $TimeOfDay, $TargetHost; foreach $rtt (@RawRTT) { $ResultString{$TargetHost} .= sprintf " %0.4f", $rtt; } } else { $ResultString{$TargetHost} = sprintf "%d %s %0.4f %0.4f %0.4f %d", $TimeOfDay, $TargetHost, $min, $mean, $max, $count; } if ($opt_T) { # Check minimum RTT for alarm limit if ($min > $opt_T) { print "Minimum RTT pushing $host\n" if $opt_d; push (@Failures, $TargetHost); } } if ($opt_d) { print "$ResultString{$TargetHost}\n"; } } } # Write results to logfile, if -l if ($opt_l) { $LogFile = $opt_l; ($sec,$min,$hour,$mday,$Month,$Year,$wday,$yday,$isdst) = localtime($TimeOfDay); $Month++; $Year += 1900; $YYYYMM = sprintf('%04d%02d', $Year, $Month); $LogFile =~ s/YYYYMM/$YYYYMM/; # Fill in current year and month open(LOG, ">>$LogFile") || warn "$0 Can't open logfile: $LogFile\n"; foreach $host (sort keys %ResultString) { print LOG "$ResultString{$host}\n"; } close LOG; } if (@Failures == 0) { # Indicate "all OK" to mon print "\n--------- No Failures ---------\n" if $opt_d; exit 0; } print "\n--------- Have Failures - mon Data Below ---------\n" if $opt_d; @SortedFailures = sort @Failures; print "@SortedFailures\n"; foreach $host (@SortedFailures) { print "$ResultString{$host}\n"; } print "\n"; exit 1; # Indicate failure to mon # # Subroutines below # sub UDPcheck { # Send multiple UDP packets my($TargetHost) = @_; my($DroppedPackets, $GoodPackets); $DroppedPackets = 0; $GoodPackets = 0; $dt = -1; # Will report -1 on failure $S = new IO::Socket::INET (PeerAddr => $TargetHost, PeerPort => 7, Proto => 'udp', ); do { &udpLeaveError($TargetHost, "Can't open UDP socket to $TargetHost\n"); return 0; } unless ($S); $TimeNow = time; for ($i = 1; $i <= $NUM_UDP_TRYS; $i++) { $Out = "UDP$i"; # Number the packets # $Out .= ' 'x52; # Make a 56+ byte packet $DataLength = length($Out); $Echo = ''; # Clear input buffer $t1 = [gettimeofday]; $BytesSent = send($S, $Out, 0); # Send the data $SIG{ALRM} = \&ReadTimeOut; eval { alarm($TimeOut); $RecvRet = recv($S, $Echo, $DataLength, $RecvFlags); $t2 = [gettimeofday]; alarm(0); }; if ($@ =~ /Read Timeout/) { $DroppedPackets++; if ($opt_d) { print " Dropped packet $i, waited $TimeOut s\n"; } } else { $dt = tv_interval ($t1, $t2); if ($Echo eq $Out) { $stat->add_data($dt); push(@RawRTT, $dt); if ($opt_d) { print "$i - $DataLength - $dt -$Echo-\n"; } $GoodPackets++; } else { if ($opt_d) { print "$i - $DataLength - $dt Bad Packet\n"; } } } } $S->close(); return $GoodPackets; } sub TCPcheck { # Send a single TCP packet my($TargetHost) = @_; my($DroppedPackets, $GoodPackets, $dt); $GoodPackets = 0; $i = 1; $dt = -1; # Will report -1 on failure $S = new IO::Socket::INET (PeerAddr => $TargetHost, PeerPort => 7, Proto => 'tcp', ); do { &tcpLeaveError($TargetHost, "Can't open TCP socket to $TargetHost\n"); return $GoodPackets, $dt; } unless ($S); $Out = "TCP$i"; $DataLength = length($Out); $t1 = [gettimeofday]; $BytesSent = send($S, $Out, 0); # Send the data $SIG{ALRM} = \&ReadTimeOut; eval { alarm($TimeOut); $RecvRet = recv($S, $Echo, $DataLength, $RecvFlags); $t2 = [gettimeofday]; alarm(0); }; if ($@ =~ /Read Timeout/) { $DroppedPackets++; if ($opt_d) { print " No Echo from TCP packet $i, waited $TimeOut s\n"; } } else { $dt = tv_interval ($t1, $t2); if ($Echo eq $Out) { if ($opt_d) { print "TCP $i - $DataLength - $dt -$Echo-\n"; } $GoodPackets++; } else { if ($opt_d) { print "TCP $i - $DataLength - $dt Bad Packet\n"; } } } $S->close(); return $GoodPackets, $dt; } sub udpLeaveError { # Don't call this one a failure, TCP might work my ($host, $reason) = @_; print "udpLeaveError $host\n" if $opt_d; } sub tcpLeaveError { # If we get here, it was a failure my ($host, $reason) = @_; print "tcpLeaveError pushing $host\n" if $opt_d; push (@Failures, $host); } sub ReadTimeOut { # For alarm/timeout signal die 'Read Timeout'; } etbemon-1.3.6/mon.d/xedia-ipsec-tunnel.monitor0000755000000000000000000001502013135636631016172 0ustar #!/usr/bin/perl # # "mon" monitor to detect dropped tunnels # on a Xedia (Lucent) AccessPoint gateway # # arguments are "[-c community] [-h] [-t] host [host...]" # # -c community SNMP community # -r display PTR records for RemoteAddr # -t display # # Jim Trocki # # $Id: xedia-ipsec-tunnel.monitor,v 1.1.1.1 2004/06/09 05:18:05 trockij Exp $ # # Copyright (C) 2000, Jim Trocki # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # use Mon::SNMP; use Getopt::Std; use Socket; use strict; sub get_status; sub get_table; sub get_vars; sub fancy_psu_table; sub bitmask_len; sub rev_lookup; $ENV{"MIBS"} = "RFC1213-MIB:XEDIA-IPSEC-MIB"; my %opt; getopts ('c:rt', \%opt); my $COMM = $opt{"c"} || "public"; my @failures = (); my $detail; my %tunnels; my @HOSTS; my @TUNNELS; my %RESOLVE_CACHE; @HOSTS = @ARGV; if ($opt{"t"}) { @TUNNELS = @ARGV; } foreach my $host (@HOSTS) { my %status = get_status ($host, $COMM); if ($status{"error"} ne "") { push (@failures, $host); $detail .= "could not retrieve status from $host: $status{error}\n\n"; next; } elsif ($status{"failure"}) { if ($opt{"t"}) { foreach my $addr (@{$status{"failed_tunnels"}}) { if ($opt{"r"}) { my $r = rev_lookup ($addr->[0]); push (@failures, $r eq "unknown" ? "$addr->[0]/$addr->[1]" : $r) } else { push (@failures, "$addr->[0]/$addr->[1]"); } } } else { push (@failures, $host); } $detail .= $status{"failure_summary"}; } $tunnels{$host} = $status{"tunnel_table"}; } # # output returned to mon # if (@failures != 0) { print join (" ", @failures), "\n"; print "$detail\n"; } else { print "no problems\n"; } print <{"ipsecTunnelAdminStatus"}, $r->{"ipsecTunnelOperStatus"}, $r->{"ipsecTunnelCurSAs"}, $r->{"ipsecTunnelRemoteGateway"}, $r->{"ipsecTunnelRemoteAddress"} . "/" . bitmask_len ($r->{"ipsecTunnelRemoteAddressMask"}), ); if ($opt{"r"}) { print " " x 62 . rev_lookup ($r->{"ipsecTunnelRemoteAddress"}) . "\n"; } } print "\n"; } exit 1 if (@failures != 0); exit 0; # # params: (hostname, community) # # returns: # ( # "error" => "error name, empty string means no error", # ) # sub get_status { my ($host, $comm) = @_; my $s; if (!defined ($s = new SNMP::Session ( "DestHost" => $host, "Community" => $comm, "Version" => 2, "UseEnums" => 1, ))) { return ("error" => "cannot create session"); } my $error; my $failure_detected = 0; my $failure_summary = ""; my $tunnel_table; my $failed_tunnels; # # is this really a xedia router? # my $sys_oid = $s->get (["sysObjectID", 0]); return ("error" => $s->{"ErrorStr"}) if ($s->{"ErrorStr"} ne ""); return ("error" => "not Xedia AP") if ($sys_oid !~ /^\.1\.3\.6\.1\.4\.1\.838\.5.(1|450|1000)/); # # tunnel table # ($error, $tunnel_table) = get_table ($s, ["ipsecTunnelType"], ["ipsecTunnelAdminStatus"], ["ipsecTunnelOperStatus"], ["ipsecTunnelCurSAs"], ["ipsecTunnelRemoteGateway"], ["ipsecTunnelRemoteAddress"], ["ipsecTunnelRemoteAddressMask"], ); return ("error" => $error) if ($error ne ""); my $pruned_tunnel_table; foreach my $r (@{$tunnel_table}) { next if ($r->{"ipsecTunnelType"} ne "siteToSiteDynamic"); push (@{$pruned_tunnel_table}, $r); next if ($r->{"ipsecTunnelAdminStatus"} eq "up" && $r->{"ipsecTunnelOperStatus"} eq "up"); next if ($r->{"ipsecTunnelAdminStatus"} eq "down"); push @{$failed_tunnels}, [$r->{"ipsecTunnelRemoteAddress"}, bitmask_len ($r->{"ipsecTunnelRemoteAddressMask"})]; $failure_summary .= "$host tunnel failure for $r->{ipsecTunnelRemoteAddress}/" . bitmask_len ($r->{"ipsecTunnelRemoteAddressMask"}) . " gw $r->{ipsecTunnelRemoteGateway}\n"; $failure_detected++; } ( "error" => "", "failure" => $failure_detected, "failure_summary" => $failure_summary, "failed_tunnels" => $failed_tunnels, "tunnel_table" => $pruned_tunnel_table, ); } sub get_table { my ($s, @tbl) = @_; my $table = []; my $tblid = $tbl[0]->[0]; my $i = 0; my $row = new SNMP::VarList (@tbl); return ("MIB problem") if (!defined $row); while (defined ($s->getnext ($row))) { last if ($s->{"ErrorStr"} ne ""); my $r = $row->[0]->[0]; last if ($r ne $tblid); foreach my $col (@{$row}) { $table->[$i]->{"iid"} = $col->[1]; $table->[$i]->{$col->[0]} = $col->[2]; } $i++; } return ($s->{"ErrorStr"}) if ($s->{"ErrorStr"} ne ""); ( "", $table, ); } sub get_vars { my ($s, @vars) = @_; my $r = new SNMP::VarList ( @vars ); return ("MIB problem") if (!defined $r); return ($s->ErrorStr) if (!defined ($s->get ($r))); my $v; foreach my $element (@{$r}) { $v->{$element->[0]} = $element->[2]; } ("", $v); } sub bitmask_len { my $bitmask = shift; my $len = 0; foreach my $octet (split /\./, $bitmask) { for (my $i = 0; $i < 8; $i++) { $len += $octet & 1; $octet >>= 1; } } $len; } sub rev_lookup { my $addr = shift; return $RESOLVE_CACHE{$addr} if ($RESOLVE_CACHE{$addr}); my $h = gethostbyaddr (inet_aton ($addr), AF_INET); if (!defined $h) { $h = "unknown"; } else { $h =~ s/\..*$//; } $RESOLVE_CACHE{$addr} = $h; $h; } etbemon-1.3.6/mon.spec0000644000000000000000000002026013731654630011515 0ustar # # spec file for package mon (Version 1.3.4-3) # # Copyright (c) 2004 SUSE LINUX AG, Nuernberg, Germany. # This file and all modifications and additions to the pristine # package are under the same license as the package itself. # # Please submit bugfixes or comments via http://www.suse.de/feedback/ # BuildRequires: bash bzip2 cpio cpp diffutils file filesystem findutils grep groff gzip info m4 make man patch sed tar texinfo autoconf automake binutils gcc libtool perl rpm gcc-c++ systemd Name: etbemon Version: 1.3.4 Release: 3 Summary: The etbemon network monitoring system License: GPL Group: System/Monitoring URL: https://doc.coker.com.au/projects/etbe-mon/ Source: http://www.coker.com.au/etbemon/etbemon_%{version}.tgz Requires: perl Requires: perl(Time::Period) Requires: perl-Convert-BER Requires: fping Requires: perl-libwww-perl Requires: systemd Requires: perl-BSD-Resource BuildRoot: %{_tmppath}/%{name}-%{version}-build %define filelist %{name}-%{version}-filelist %description "etbemon" is a tool for monitoring the availability of services. Services may be network-related, environmental conditions, or nearly anything that can be tested with software. It is extremely useful for system administrators, but not limited to use by them. It was designed to be a general-purpose problem alerting system, separating the tasks of testing services for availability and sending alerts when things fail. To achieve this, "etbemon" is implemented as a scheduler which runs the programs which do the testing, and triggering alert programs when these scripts detect failure. None of the actual service testing or reporting is actually handled by "etbemon". These functions are handled by auxillary programs. %{?systemd_ordering} Authors: -------- Russell Coker Jim Trocki %prep ################################################################### %setup -q %setup -T -D ################################################################### %build make -C mon.d CFLAGS="-g -O2" LDFLAGS="-Wl,-z,relro" CPPFLAGS="" make -C bin make -C mon-local.d ################################################################### %install rm -rf %{buildroot} mkdir -p %{buildroot}/%{_libdir}/mon/bin mkdir -p %{buildroot}/%{_libdir}/mon/alert.d mkdir -p %{buildroot}/%{_sbindir} mkdir -p %{buildroot}/%{_mandir}/man1 mkdir -p %{buildroot}/%{_libdir}/mon/mon.d mkdir -p %{buildroot}/%{_libdir}/mon/mon-local.d mkdir -p %{buildroot}/%{_localstatedir}/lib/mon mkdir -p %{buildroot}/%{_libdir}/mon/utils mkdir -p %{buildroot}/%{_sysconfdir}/mon mkdir -p %{buildroot}/%{_sysconfdir}/init.d mkdir -p %{buildroot}/%{_sysconfdir}/logrotate.d mkdir -p %{buildroot}%{_unitdir} cp mon %{buildroot}/%{_sbindir}/ cp bin/*.helper %{buildroot}/%{_libdir}/mon/bin cp alert.d/*.alert %{buildroot}/%{_libdir}/mon/alert.d chmod 755 %{buildroot}/%{_libdir}/mon/alert.d/* rm %{buildroot}/%{_libdir}/mon/alert.d/snpp.alert cp ./clients/moncmd %{buildroot}/%{_sbindir}/moncmd cp ./clients/monshow %{buildroot}/%{_sbindir}/monshow cp mon.d/*.monitor %{buildroot}/%{_libdir}/mon/mon.d cp mon-local.d/*.monitor mon-local.d/*.monitor.real -p %{buildroot}/%{_libdir}/mon/mon-local.d cp -a ./doc/*.1 %{buildroot}/%{_mandir}/man1/ cp ./etc/mon.cf %{buildroot}/%{_sysconfdir}/mon/mon.cf mv ./etc/auth.cf %{buildroot}/%{_sysconfdir}/mon cp -a ./utils/ %{buildroot}/%{_libdir}/mon/ mkdir -p %{buildroot}/sbin cp systemd/mon.service %{buildroot}%{_unitdir}/etbemon.service # clean up after perl module install - remove special files find %{buildroot} -name "perllocal.pod" -o -name ".packlist" -o -name "*.bs" |xargs -i rm -f {} # build filelist echo "%defattr(-,root,root)" > %filelist find %{buildroot} -type f -printf "/%%P\n" | sed -e s/1$/1.gz/ >> %filelist [ -z %filelist ] && { echo "ERROR: EMPTY FILE LIST" exit -1 } ################################################################### %files -f %filelist %doc doc/* %doc CHANGES COPYING COPYRIGHT CREDITS INSTALL KNOWN-PROBLEMS README %doc TODO VERSION ################################################################### %clean if [ -z "${RPM_BUILD_ROOT}" -a "${RPM_BUILD_ROOT}" != "/" ] then rm -rf $RPM_BUILD_ROOT fi rm -rf $RPM_BUILD_ROOT ################################################################### %preun /usr/bin/systemctl --no-reload disable %{pkgname}.service >/dev/null 2>&1 || : /usr/bin/systemctl stop %{pkgname}.service >/dev/null 2>&1 ||: if [ -r %{_localstatedir}/run/mon.pid ]; then /etc/init.d/mon stop fi ################################################################### %post /usr/bin/systemctl preset %{pkgname}.service >/dev/null 2>&1 ||: if [ -d %{_localstatedir}/log -a ! -f %{_localstatedir}/log/mon_history.log ]; then touch %{_localstatedir}/log/mon_history.log fi if [ $1 = 1 ]; then /sbin/chkconfig --add mon fi ################################################################### %postun /usr/bin/systemctl daemon-reload >/dev/null 2>&1 ||: if [ "$1" = "0" -a -f %{_localstatedir}/log/mon_history.log ]; then rm -f %{_localstatedir}/log/mon_history.log fi %changelog -n mon * Sun Sep 20 2020 - russell@coker.com.au - Update to 1.3.4 * Wed Jul 07 2004 - eric@transmeta.com - update to 1.0.0pre2, remove suse-ness * Mon Mar 01 2004 - hmacht@suse.de - building as nonroot-user * Fri Feb 27 2004 - kukuk@suse.de - Cleanup neededforbuild - fix compiler warnings * Mon Feb 10 2003 - lmb@suse.de - Fixed path to comply with FHS. * Fri Oct 18 2002 - lmb@suse.de - Fix for Bugzilla #21086: init script had a broken path and syntax error. * Tue Aug 20 2002 - lmb@suse.de - Fix for Bugzilla # 17936; PreRequires corrected. * Mon Aug 12 2002 - lmb@suse.de - Perl dependencies updated for Perl 5.8.0 * Fri Jul 26 2002 - lmb@suse.de - Perl dependencies adjusted to comply with SuSE naming scheme * Fri Jul 26 2002 - lmb@suse.de - Adapted from Conectiva to UnitedLinux - init script cleanup * Wed Jul 24 2002 - Fbio Oliv Leite - Version: mon-0.99.2-1ul - Adapted for United Linux * Sat Jul 20 2002 - Claudio Matsuoka - Version: mon-0.99.2-3cl - updated dependencies on perl modules to lowercase names * Thu May 16 2002 - Fbio Oliv Leite - Version: mon-0.99.2-2cl - Added %%attr to %%{_libdir}/mon/*, so that the helper scripts are executable Closes: #5522 (aparente problema com as permisses) - Changed initscript to use gprintf Closes: #4172 (Internacionalizao (?)) * Fri Dec 28 2001 - Ricardo Erbano - Version: mon-0.99.2-1cl - New upstream relase 0.99.2 * Sat Nov 17 2001 - Claudio Matsuoka - Version: mon-0.38.20-6cl - fixed doc permissions * Thu Jun 21 2001 - Eliphas Levy Theodoro - Version: mon-0.38.20-5cl - fixed initscript - /usr/lib/mon -> /usr/sbin (Closes: #3792) - added requires for perl-Convert-BER - added post{,un} scripts to handle logfile mon_history.log * Fri Mar 23 2001 - Luis Claudio R. Gonalves - Version: mon-0.38.20-4cl - fixed the initscript (it was missing a "-f" switch) * Tue Oct 31 2000 - Arnaldo Carvalho de Melo - %%{_sysconfdir}/mon is part of this package - small cleanups * Thu Sep 28 2000 - Fbio Oliv Leite - Wrong version in the mon-perl dependency... * Thu Sep 21 2000 - Fbio Oliv Leite - Updated to 0.38.20. * Fri Jun 16 2000 - Fbio Oliv Leite - Fixed TIM alert, added history file, added logrotate script * Mon Jun 12 2000 - Fbio Oliv Leite - Added an alert via TIM Celular cellphones * Thu Jun 08 2000 - Fbio Oliv Leite - Made the %%preun nicer * Thu Jun 01 2000 - Fbio Oliv Leite - New spec format * Mon Apr 17 2000 - Fbio Oliv Leite - Added a new monitor (initscript.monitor) * Fri Apr 14 2000 - Fbio Oliv Leite - Added proxy support to http.monitor * Thu Apr 13 2000 - Fbio Oliv Leite - Fixed a small bug in the init script - Added scripts to alert via Mobi pagers and Global Telecom cellphones * Mon Apr 10 2000 - Fbio Oliv Leite - Initial RPM packaging etbemon-1.3.6/muxpect/0000755000000000000000000000000010640450347011530 5ustar etbemon-1.3.6/muxpect/Makefile0000644000000000000000000000031510061516614013164 0ustar CC=gcc CFLAGS=-O2 -Wall -g OBJS = muxpect.o setup.o io.o all: muxpect muxpect.o : muxpect.h setup.o : muxpect.h io.o : muxpect.h muxpect: $(OBJS) $(CC) -o $@ $(OBJS) clean: rm -f *.o muxpect core etbemon-1.3.6/muxpect/README0000644000000000000000000000066510230411543012405 0ustar $Id: README,v 1.2 2005/04/17 07:42:27 trockij Exp $ muxpect is not yet complete. It is a work-in-progress. The purpose is to have a monitor which can multiplex TCP connections on the same port to multiple destinations and do chat-style interaction on them all in parallel. Given this functionality, many of the TCP-based monitors in mon.d can be replaced by this code, making things much more efficient. Jim Trocki trockij@arctic.org etbemon-1.3.6/muxpect/io.c0000644000000000000000000000666210061516614012312 0ustar /* * $Id: io.c,v 1.1.1.1 2004/06/09 05:18:04 trockij Exp $ */ /* * Copyright (C) 1998 Jim Trocki * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "muxpect.h" int setup_connect (muxconn_t *muxlist, char *muxerr, int muxerrsiz) { muxconn_t *c; int s, fl; int err; struct protoent *pe; c = muxlist; err = 0; if ((pe = getprotobyname ("tcp")) == NULL) { snprintf (muxerr, muxerrsiz, "could not look up tcp proto"); return 0; } while (c != NULL) { s = socket (AF_INET, SOCK_STREAM, pe->p_proto); if (s < 0) { snprintf (muxerr, muxerrsiz, "could not create socket: %s", sys_errlist[errno]); return 0; } /* * set nonblocking */ c->fd = s; if ( (fl = fcntl (s, F_GETFL, 0)) < 0) { snprintf (muxerr, muxerrsiz, "could not get flags: %s", sys_errlist[errno]); return 0; } fl |= O_NONBLOCK; if ( (fl = fcntl (s, F_SETFL, fl)) < 0) { snprintf (muxerr, muxerrsiz, "could not set flags: %s", sys_errlist[errno]); return 0; } /* * connect */ c->saddr.sin_port = htons (c->port); if (connect (s, &c->saddr, sizeof (c->saddr)) == -1 && errno != EINPROGRESS) { c->status = MUXCONN_FAILURE; snprintf (c->detail, sizeof (c->detail), "could not connect: %s", sys_errlist[errno]); snprintf (c->summ, sizeof (c->summ), "%s", c->hostname); } else { c->status = MUXCONN_INPROGRESS; } c = c->next; } return 1; } /* * main IO loop */ int io_loop (muxconn_t *muxlist, int timeout, char *err, int errsiz) { fd_set r_fd, w_fd; struct timeval tval, t0, t1; muxconn_t *c; int d; FD_ZERO (&r_fd); FD_ZERO (&w_fd); d = 0; c = muxlist; while (c->next != NULL) { if (c->status != MUXCONN_INPROGRESS) { c = c->next; continue; } FD_SET (c->fd, &r_fd); FD_SET (c->fd, &w_fd); if (c->fd > d) d = c->fd; } timerclear (&tval); timerclear (&t0); timerclear (&t1); if (gettimeofday (&t0, NULL) == -1) { snprintf (err, errsiz, "could not gettimeofday: %s", sys_errlist[errno]); return 0; } while (timerisset (&tval)) { #if 0 select (); #endif if (gettimeofday (&t1, NULL) < 0) { snprintf (err, errsiz, "could not gettimeofday: %s", sys_errlist[errno]); return 0; } } c = muxlist; while (c->next != NULL) { if (c->status == MUXCONN_INPROGRESS) c->status = MUXCONN_TIMEOUT; c = c->next; } return 1; } etbemon-1.3.6/muxpect/muxpect.c0000644000000000000000000000536110061516614013363 0ustar /* * $Id: muxpect.c,v 1.1.1.1 2004/06/09 05:18:04 trockij Exp $ */ /* * Copyright (C) 1998 Jim Trocki * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include "muxpect.h" int debug; /* * main */ int main (int argc, char **argv) { char fname[200], errbuf[100]; chat_sess_t *sess; int c, help; unsigned short port; help = 0; debug = 0; memset (fname, 0, sizeof (fname)); optind = 0; port = 0; while ((c = getopt (argc, argv, "dhf:p:")) != EOF) { switch (c) { case 'h': help++; break; case 'd': debug++; break; case 'f': strncpy (fname, optarg, sizeof(fname)); break; case 'p': port = (unsigned short) strtol (optarg, (char **)NULL, 10); break; } } if (help) usage(); if (fname[0] == '\0') usage(); /* * read config file */ sess = read_expect (fname); if (sess == NULL) { fprintf (stderr, "could not read\n"); exit (1); } if (debug) dump_chat_sess (sess); if (setup_muxconn_struct (argv, optind, sess, port, errbuf, sizeof(errbuf)) == NULL) { printf ("could not setup sessions: %s\n", errbuf); exit (-1); } exit (0); } /* * do a regex against a buffer, returning true or fals */ int match_buffer (regex_t *preg, char *pat, char *buf, char *errbuf, int errbuflen) { int r; r = regcomp (preg, pat, REG_EXTENDED | REG_ICASE | REG_NOSUB); if (r) { regerror (r, preg, errbuf, errbuflen); fprintf (stderr, "error in regcomp: %s\n", errbuf); exit (1); } r = regexec (preg, buf, 0, 0, 0); if (r == REG_NOMATCH) { fprintf (stderr, "no match\n"); } else if (r != REG_NOERROR) { regerror (r, preg, errbuf, errbuflen); fprintf (stderr, "error in regexec: %s\n", errbuf); return (-1); } printf ("match\n"); return (0); } etbemon-1.3.6/muxpect/muxpect.h0000644000000000000000000000400610061516614013363 0ustar /* * $Id: muxpect.h,v 1.1.1.1 2004/06/09 05:18:04 trockij Exp $ */ /* * Copyright (C) 1998 Jim Trocki * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _MUXPECT_H #define _MUXPECT_H struct chat_sess { char expect[BUFSIZ]; char send[BUFSIZ]; struct chat_sess *next; }; typedef struct chat_sess chat_sess_t; struct muxconn { int fd; char hostname[80]; struct sockaddr_in saddr; unsigned short port; time_t timeout; char buf[8192]; int buf_offset; chat_sess_t *ch_sess; regex_t re_preg; char re_errbuf[100]; int status; char summ[80]; char detail[8192]; struct muxconn *next; }; typedef struct muxconn muxconn_t; /* status values */ #define MUXCONN_FAILURE 0 /* chat failure */ #define MUXCONN_SUCCESS 1 /* chat success */ #define MUXCONN_TIMEOUT 2 /* chat timeout */ #define MUXCONN_INPROGRESS 3 /* in progress (not complete) */ #define MUXCONN_SETUP 4 /* setup state */ int match_buffer (regex_t *, char *, char *, char *, int); struct chat_sess *read_expect (char *file); void dump_chat_sess (chat_sess_t *); void usage (void); muxconn_t * setup_muxconn_struct (char **, int, chat_sess_t *, unsigned short port, char *, int); int setup_connect (muxconn_t *, char *, int); int io_loop (muxconn_t *, int, char *, int); #endif /* _MUXPECT_H */ etbemon-1.3.6/muxpect/setup.c0000644000000000000000000001023510061516614013032 0ustar /* * $Id: setup.c,v 1.1.1.1 2004/06/09 05:18:04 trockij Exp $ */ /* * Copyright (C) 1998 Jim Trocki * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include "muxpect.h" /* * read expect/send file */ struct chat_sess * read_expect (char *file) { FILE *f; char buf[BUFSIZ]; chat_sess_t *first, *cur, *ncur; int send_expect; int lnum; if ((f = fopen (file, "r")) == NULL) return ((chat_sess_t *)NULL); send_expect = 1; first = cur = (chat_sess_t *) calloc (1, sizeof (chat_sess_t)); if (first == NULL) return ((chat_sess_t *) NULL); first->next = (chat_sess_t *) NULL; cur->next = (chat_sess_t *) NULL; lnum = 0; while (fgets (buf, BUFSIZ, f) != NULL) { lnum++; if (strchr (buf, '#') == buf) continue; buf[strlen (buf) -1] = '\0'; if (send_expect) { strncpy (cur->expect, buf, BUFSIZ); send_expect--; } else { strncpy (cur->send, buf, BUFSIZ); send_expect++; ncur = (chat_sess_t *) calloc (1, sizeof (chat_sess_t)); if (ncur == NULL) { fclose (f); return ((chat_sess_t *) NULL); } ncur->next = (chat_sess_t *) NULL; cur->next = ncur; cur = ncur; } } cur->next = (chat_sess_t *) NULL; if (ferror (f)) { fclose (f); return ((chat_sess_t *)NULL); } fclose (f); return (first); } /* * debugging */ void dump_chat_sess (chat_sess_t *c) { chat_sess_t *p; p = c; while (p->next != NULL) { printf ("exp: %s\n", p->expect); printf ("snd: %s\n", p->send); p = p->next; } printf ("done\n"); } /* * help */ void usage (void) { printf ("usage:\n"); printf (" muxpect [-d] [-h] -f file\n"); printf (" -d debug\n"); printf (" -h show this help\n"); printf (" -f file chat script filename\n"); printf ("\n"); exit (0); } /* * create list of muxconns for all hosts */ muxconn_t * setup_muxconn_struct (char **hosts, int ind, chat_sess_t *sess, unsigned short port, char *errbuf, int errbufsiz) { muxconn_t *c, *l, *n; int i; struct hostent *hent; i = ind; l = (muxconn_t *)NULL; c = (muxconn_t *)NULL; while (hosts[i] != NULL) { n = calloc (1, sizeof (muxconn_t)); if (n == NULL) { strncpy (errbuf, "could not alloc memory", errbufsiz); return ((muxconn_t *) NULL); } n->next = (muxconn_t *) NULL; if (c == (muxconn_t *) NULL) c = n; else l->next = n; n->fd = 0; strncpy (n->hostname, hosts[i], sizeof (n->hostname)); n->timeout = 0; n->buf_offset = 0; n->ch_sess = sess; n->status = MUXCONN_INPROGRESS; n->next = (muxconn_t *) NULL; n->port = port; if (hosts[i][0] >= '0' && hosts[i][0] <= '9') { if (inet_aton (hosts[i], &n->saddr.sin_addr) == 0) { snprintf (errbuf, errbufsiz, "invalid IP address supplied, %s", hosts[i]); return ((muxconn_t *) NULL); } } else { if ((hent = gethostbyname (hosts[i])) == NULL) { snprintf (errbuf, errbufsiz, "could not resolve host %s", hosts[i]); return ((muxconn_t *) NULL); } memcpy (&n->saddr.sin_addr, hent->h_addr_list[0], hent->h_length); } l = n; i++; } if (i == ind) { snprintf (errbuf, errbufsiz, "no hosts supplied"); return ((muxconn_t *) NULL); } return (c); } etbemon-1.3.6/state.d/0000755000000000000000000000000010640450347011405 5ustar etbemon-1.3.6/state.d/README0000644000000000000000000000003510061516614012260 0ustar This is the state directory. etbemon-1.3.6/systemd/0000755000000000000000000000000013151436601011530 5ustar etbemon-1.3.6/systemd/mon.service0000644000000000000000000000035513151436601013706 0ustar [Unit] Description=System monitoring daemon Documentation=man:mon(8) After=network.target [Service] User=mon ExecStart=/usr/sbin/mon IgnoreSIGPIPE=false KillMode=process RestartSec=2 Restart=always [Install] WantedBy=multi-user.target etbemon-1.3.6/systemd/tmpfiles.d/0000755000000000000000000000000013151432105013570 5ustar etbemon-1.3.6/systemd/tmpfiles.d/mon.conf0000644000000000000000000000004413064177453015245 0ustar d /run/mon 0755 mon mon etbemon-1.3.6/utils/0000755000000000000000000000000010640450347011203 5ustar etbemon-1.3.6/utils/cf-to-hosts0000755000000000000000000000535110230411543013271 0ustar #!/usr/bin/perl # # Convert hostgroup entries in a mon configuration file # into a local hosts file # # Jim Trocki, trockij@arctic.org # # $Id: cf-to-hosts,v 1.2 2005/04/17 07:42:27 trockij Exp $ # # Copyright (C) 1998, Jim Trocki # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA use strict; sub resolve_hosts; sub print_hosts; sub read_cf; use Getopt::Std; use Socket; my %resolved; my %opt; getopts ("hM", \%opt); if ($opt{"h"}) { print <)); next if $linepart =~ /^\s*#/; # # accumulate multi-line lines (ones which are \-escaped) # if (!defined $acc_line) { $linepart =~ s/^\s*//; } if ($linepart =~ /^(.*)\\\s*$/) { $acc_line .= $1; chomp $acc_line; next; } else { $acc_line .= $linepart; } $l = $acc_line; $acc_line = undef; chomp $l; $l =~ s/^\s*//; $l =~ s/\s*$//; $linepart = ""; if ($l eq "") { $ingroup = 0; next; } if ($l =~ /^hostgroup\s+(\S+)\s+(.*)/) { $ingroup = 1; resolve_hosts ($2); next; } elsif ($ingroup) { resolve_hosts ($l); next; } } close (IN); return ""; } etbemon-1.3.6/utils/syslog.monitor0000755000000000000000000005045010146140377014143 0ustar #!/usr/bin/perl -w # # syslog.monitor - monitors incoming syslog packets and reports to mon # # Author: Lars Marowsky-Bre, lars@marowsky-bree.de # # Copyright (C) 1999 Lars Marowsky-Bre # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # ### Nothing to see below this line. ### Abandon hope all ye who enter here ### Here be dragons! ############################################################################# # Me, use modules? no, me never use modules package main; use strict; use Socket; use Net::hostent; use Time::HiRes qw (time alarm sleep gettimeofday); use Mon::Client; use POSIX qw(setsid strftime); # automagically inserted by CVS my $VERSION = '$Id: syslog.monitor,v 1.2 2004/11/15 14:45:19 vitroth Exp $'; ############################################################################# # Global variables # Map syslog facility numbers to names my %Num2Facility = ( 0 => 'kern', 1 => 'user', 2 => 'mail', 3 => 'daemon', 4 => 'auth', 5 => 'syslog', 6 => 'lpr', 7 => 'news', 8 => 'uucp', 9 => 'cron', 10 => 'authpriv', 11 => 'ftp', 12 => 'reserved-12', 13 => 'reserved-13', 14 => 'reserved-14', 15 => 'reserved-15', 16 => 'local0', 17 => 'local1', 18 => 'local2', 19 => 'local3', 20 => 'local4', 21 => 'local5', 22 => 'local6', 23 => 'local7', ); # Map syslog level numbers to names my %Num2Level = ( 0 => 'emerg', 1 => 'alert', 2 => 'crit', 3 => 'err', 4 => 'warn', 5 => 'notice', 6 => 'info', 7 => 'debug' ); # Contains a list of LogEntry object init params my %Checks = (); # Hash of hostgroup members hostnames, indexed by hostgroup name my %GROUP_MEMBERS; # IP -> hostname resolving my %IP2Host; # IP -> hostgroup resolving my %IP2Group; # array of references to LogEntry objects, indexed by hostname my %ChecksPerHost; # array of references to LogEntry objects per hostgroup my %ChecksPerGroup; # Global Mon::Client object my $mon; # The configuration is read into this hash my %CONF; ############################################################################# # Setup my ($conf_file) = @ARGV; if (!defined($conf_file) || $conf_file eq "") { die "No configuration file given"; } &ReadConf($conf_file); if ($CONF{'daemon_mode'} == 1) { if ($CONF{'logfile'} ne '') { &daemonize; } else { &Log(2,"You can't summon a daemon while talking to the public"); } } # We need some information from the mon server now... &ChatMonServer; # Parse the hosts, resolve them etc &ParseHosts; # Build the cache, precompile the checks &BuildChecks; # Open listener port my $proto = getprotobyname('udp'); socket(SOCKET, Socket::PF_INET, Socket::SOCK_DGRAM, $proto) || die "Could not create listening socket: $!"; bind(SOCKET, scalar Socket::sockaddr_in($CONF{'bind_port'}, Socket::inet_aton($CONF{'bind_ip'}))) || die "Could not bind authentication socket: $!"; # prepare to select my ($whence,$line,$rin,$rout); $rin = ''; vec($rin, fileno(SOCKET), 1) = 1; # At which time we did the last full walk of the chains my $last_full_walk = time; # Msg - contains the currently processed message # LastMsg - contains the last Msg hash, per host my (%LastMsg,%Msg); ############################################################################# LOOP: while (1) { if (!select($rout = $rin, undef, undef, $CONF{'select_timeout'})) { &Log(7,"select timeout"); next LOOP; } # Read the incoming UDP packet if (!($whence = recv(SOCKET, $line, 8192, 0) )) { &Log(3,"recv error: $!"); next LOOP; } # Parse the incoming UDP packet envelope my ($src_port,$src_ip) = sockaddr_in($whence); $src_ip = inet_ntoa($src_ip); chomp($line); &Log(7,"Received syslog message from $src_ip"); # If this IP does not resolve to a hostname, it is bogus if (!defined($IP2Host{$src_ip})) { &Log(3,"Received unauthorized message from $src_ip, ignoring"); next LOOP; } my ($level,$facility,$msg); if ($line =~ /^\<(\d+)\>([^:]+): (.*)$/o) { # Decode the message %Msg = (); $Msg{'src_port'} = $src_port; $Msg{'src_ip'} = $src_ip; $Msg{'host'} = $IP2Host{$src_ip}; $Msg{'level'} = $1 & 7; $Msg{'Level'} = $Num2Level{$1 & 7}; $Msg{'facility'} = $Num2Facility{$1 >> 3}; $Msg{'msg'} = $3; $Msg{'time'} = time; $Msg{'group'} = $IP2Group{$src_ip}; # Log the message if necessary &OwnLog(\%Msg); # Walk through the processing hooks here... my $check; PER_HOST: foreach $check (@{$ChecksPerHost{ $Msg{'host'} }}) { if ($check->check(\%Msg) == 1) { last PER_HOST; } } PER_GROUP: foreach $check (@{$ChecksPerGroup{ $Msg{'group'}}}) { if ($check->check(\%Msg) == 1) { last PER_GROUP; } } # Store message for further reference %{$LastMsg{$src_ip}} = %Msg; } elsif ($line =~ /^last message repeated (\d+) times$/o) { my $count = $1; # Handle repetition - last msg from the host is still available # in %LastMsg{$src_ip} &Log(7,"Last message repeated $count times"); } else { &Log(2,"Unknown input ignored: $line"); } } continue { # Before continuing, always check if the checks need to be run, # so that the low threshold can be triggered if ($last_full_walk - time > $CONF{'full_walk_timeout'}) { &Log(7,"Full walk triggered after $CONF{'full_walk_timeout'} seconds"); my ($check_ary); foreach $check_ary (@ChecksPerHost{keys %ChecksPerHost}, @ChecksPerGroup{keys %ChecksPerGroup} ) { my ($check); foreach $check (@$check_ary) { &Log(7,"Running for ".$check->{'group'}."/".$check->{'host'}); $check->check({'level' => 7, 'Level' => $Num2Level{7}, 'msg' => 'SYSLOG.MONITOR: SELECT TIMEOUT', 'time' => time, }); } # foreach $check } # foreach $check_ary } # if } # continue ############################################################################# sub BuildChecks { &Log(6,"Building check cache, precompiling objects"); # First, build the per-host cache my ($group); foreach $group (keys %{$CONF{'checks-per-host'}}) { if (defined($GROUP_MEMBERS{$group})) { # Build the "per-host" checks my ($host); foreach $host (@{$GROUP_MEMBERS{$group}}) { &Log(6,"Building per host checks for $group/$host"); my ($check); CHECK: foreach $check (@{$CONF{'on-host'}{$group}{$host}},@{$CONF{'checks-per-host'}{$group}}) { if (!defined($Checks{$check})) { &Log(3,"Undefined check $check for $host, ignoring"); next CHECK; } push @{$ChecksPerHost{$host}},LogEntry->new($Checks{$check},$group,$host); } } } else { &Log(3,"Unknown hostgroup $group referenced in config file"); } } # Second, build the per-group cache foreach $group (keys %{$CONF{'checks-per-group'}}) { if (defined($GROUP_MEMBERS{$group})) { &Log(6,"Building per group checks for $group"); my $check; CHECK: foreach $check (@{$CONF{'checks-per-group'}{$group}}) { if (!defined($Checks{$check})) { &Log(3,"Undefined check $check for group $group, ignoring"); next CHECK; } push @{$ChecksPerGroup{$group}},LogEntry->new($Checks{$check},$group,'ALL'); } } else { &Log(3,"undefined group $group, ignoring"); next GROUP; } } &Log(6,"Finished building check cache"); } sub FormatTime { # Prints the time like a proper Cisco my ($time) = @_; return strftime("%b %e %H:%M:%S", localtime($time)) .sprintf(".%03d",($time - int($time)) * 1000 ); } # Log a message if the priority is high enough sub Log { my ($prio,$msg) = @_; if ($prio <= $CONF{'loglevel'}) { my $line = &FormatTime(time). sprintf(": %- 6.6s: %s\n", $Num2Level{$prio},$msg); if ($CONF{'logfile'} ne "") { open(LOG,">>$CONF{'logfile'}") || die "Could not open logfile!"; print LOG $line; close(LOG); } else { print $line; } } } sub OwnLog { # Log the message to the file specified in syslog.conf my ($r) = @_; return if ($CONF{'syslogfile'} eq ""); my $f = $CONF{'syslogfile'}; # Ok, logfile is defined. do the substitutions my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($$r{'time'}); $year += 1900; print $f."\n"; $f =~ s/\%H/$$r{host}/; $f =~ s/\%L/$$r{Level}/; $f =~ s/\%l/$$r{level}/; $f =~ s/\%F/$$r{facility}/; $f =~ s/\%G/$$r{group}/; $f =~ s/\%D/sprintf "%04d-%02d-%02d",$year,$mon,$mday/e; # Make sure everything is still okay $f =~ s/[^A-Za-z0-9\.\-\/]//og; open(F,">>$f"); print F &FormatTime($$r{'time'}).sprintf(" %s %s.%s: %s\n", $$r{'host'}, $$r{'facility'},$$r{'Level'},$$r{'msg'}); close(F); } sub ChatMonServer { # Setup the mon connection $mon = Mon::Client->new( host => $CONF{'mon_host'}, username => $CONF{'mon_user'}, password => $CONF{'mon_pass'}); &Log(6,"Connecting to mon host $CONF{'mon_host'}"); # Retrieve information from the mon server about hostgroups if (!defined ($mon->connect)) { &Log(2,"Could not connect to server: " . $mon->error); die; } my %opstatus; if (!(%opstatus = $mon->list_opstatus)) { &Log(2,"could not get opstatus: " . $mon->error); $mon->disconnect; die; } # We are only interested in hostgroups which have the "syslog" service # defined, and thus are able to process our traps my ($group); foreach $group (keys %opstatus) { if (defined($opstatus{$group}{'syslog'})) { my (@hosts) = $mon->list_group($group); @{$GROUP_MEMBERS{$group}} = @hosts; } } # We don't need the TCP connection anymore from here on. # This might change in the future if Mon::Client ever sends # traps via tcp $mon->disconnect; } # Parse the hostnames, and fill in the %IP2Host / %IP2Group sub ParseHosts { my ($group,$host); &Log(6,"Resolving hostnames and building cache"); foreach $group (keys %GROUP_MEMBERS) { HOST: foreach $host (@{$GROUP_MEMBERS{$group}}) { my $h = gethostbyname($host); if (!defined($h)) { &Log(3,"Failed to resolve $host, ignoring"); next HOST; } if (@{$h->addr_list} > 1 ) { my $addr; for $addr ( @{$h->addr_list} ) { $IP2Host{inet_ntoa($addr)} = $host; $IP2Group{inet_ntoa($addr)} = $group; } } else { $IP2Host{inet_ntoa($h->addr)} = $host; $IP2Group{inet_ntoa($h->addr)} = $group; } } } } # Send a trap to the mon server sub SendTrap { my ($l) = @_; my ($typ,$opstatus,$sum,$dtl); if ($l->{status} == 0) { $opstatus = 'ok'; $sum = $l->{host}.": ".$l->{desc}." ok since " .localtime($l->{status_time}); $dtl = "\nHappened ".scalar(@{$l->{matches}})." within " .$l->{period}."s"; } elsif ($l->{status} == -1) { $opstatus = 'fail'; $sum = $l->{host}.": ".$l->{desc}." occured too seldom since " .localtime($l->{status_time}); $dtl = "\nLast time was " .localtime($l->{last_match}); } elsif ($l->{status} == 1) { $opstatus = 'fail'; $sum = $l->{host}.": ".$l->{desc}." occured too often since " .localtime($l->{status_time}); $dtl = "\nHappened ".scalar(@{$l->{matches}})." within " .$l->{period}."s\n"; # Include copy of the line which triggered the trap $dtl .= ${$l->{'last_matched_msg'}}{'msg'}."\n"; } else { &Log(0,"BUG: Unknown status in SendTrap"); return undef; } &Log(4,"Sending trap: ".$l->{'group'}." $opstatus $sum"); # Send the trap $mon->send_trap( group => $l->{'group'}, service => 'syslog', retval => 1, opstatus => $opstatus, summary => $sum, detail => $dtl) || &Log(2, "trap sending failed: ".$mon->error); } sub ReadConf { my ($conf) = @_; if ($conf !~ /^[a-z0-9\.\-\/]+$/oi) { &Log(1,"Security violation: $conf contains illegal characters"); die; } # Setup defaults %CONF = ( 'select_timeout' => 10, 'full_walk_timeout' => 30, 'bind_ip' => '0.0.0.0', 'bind_port' => 514, 'logfile' => '', 'daemon_mode' => 0, 'syslogfile' => "", ); if (!open(CONF,"<$conf")) { &Log(2,"Failed to open configuration file"); die; } my ($l,$lineno); my $level = 'global'; my ($CHECKNAME,$GROUPNAME); while (defined($l = )) { chomp $l; $l =~ s/^\s*//; $l =~ s/\s*$//; $lineno++; next if $l =~ /^#/; if ($level eq 'global') { if ($l =~ /^full_walk_timeout\s+(.*)$/o) { $CONF{'full_walk_timeout'} = &dhmstos($1); next; } elsif ($l =~ /^select_timeout\s+(.*)$/o) { $CONF{'select_timeout'} = &dhmstos($1); next; } elsif ($l =~ /^loglevel\s+(\d)$/o) { $CONF{'loglevel'} = $1; next; } elsif ($l =~ /^logfile\s+([a-z0-9\.\-\/]*)$/io) { $CONF{'logfile'} = $1; next; } elsif ($l =~ /^syslogfile\s+([\%a-z0-9\.\-\/]+)$/io) { $CONF{'syslogfile'} = $1; next; } elsif ($l =~ /^daemon_mode\s*$/o) { $CONF{'daemon_mode'} = 1; next; } elsif ($l =~ /^bind_ip\s+(\d+\.\d+\.\d+\.\d+)$/o) { $CONF{'bind_ip'} = $1; next; } elsif ($l =~ /^bind_port\s+(\d+)$/o) { $CONF{'bind_port'} = $1; next; } elsif ($l =~ /^mon_host\s+(\S+)$/o) { $CONF{'mon_host'} = $1; next; } elsif ($l =~ /^mon_user\s+(\S+)$/o) { $CONF{'mon_user'} = $1; next; } elsif ($l =~ /^mon_pass\s+(\S+)$/o) { $CONF{'mon_pass'} = $1; next; } elsif ($l =~ /^check\s+(\S+)$/o) { $level = 'check'; $CHECKNAME = lc($1); $Checks{$CHECKNAME} = { 'name' => lc($1), 'period' => 300, 'min' => -1, 'max' => 1, 'final' => 0, 'desc' => 'I was too lazy to write a proper configuration file', }; next; } elsif ($l =~ /^group\s+(.*)$/o) { $level = 'group'; $GROUPNAME = $1; next; } elsif ($l eq "") { next; } ################ END GLOBAL CONFIGURATION FILE OPTIONS } elsif ($level eq 'check') { if ($l =~ /^period\s+(.*)$/o) { $Checks{$CHECKNAME}{'period'} = &dhmstos($1); next; } elsif ($l =~ /^min\s+(\-?\d+)$/o) { $Checks{$CHECKNAME}{'min'} = $1; next; } elsif ($l =~ /^max\s+(\-?\d+)$/o) { $Checks{$CHECKNAME}{'max'} = $1; next; } elsif ($l =~ /^desc\s+(.*)$/o) { $Checks{$CHECKNAME}{'desc'} = $1; next; } elsif ($l =~ /^pattern\s+(.*)$/o) { $Checks{$CHECKNAME}{'pattern'} = $1; next; } elsif ($l =~ /^final\s*$/o) { $Checks{$CHECKNAME}{'final'} = 1; next; } elsif ($l eq "") { # blank line indicates end of check block $level = 'global'; $CHECKNAME = ''; next; } #### END OF "CHECK" part } elsif ($level eq 'group') { if ($l =~ /^per-host\s+(.*)$/o) { @{$CONF{'checks-per-host'}{$GROUPNAME}} = split(/\s+/,$1); next; } elsif ($l =~ /^per-group\s+(.*)$/o) { @{$CONF{'checks-per-group'}{$GROUPNAME}} = split(/\s+/,$1); next; } elsif ($l =~ /^on-host\s+(\S+)\s+(.*)$/o) { @{$CONF{'on-host'}{$GROUPNAME}{$1}} = split(/\s+/,$2); next; } elsif ($l eq "") { $level = 'global'; $GROUPNAME = ''; next; } } &Log(3,"Error while parsing configuration file, line $lineno: $l"); } } # # convert a string like "20m" into seconds # sub dhmstos { my ($str) = @_; my ($s); if ($str =~ /^\s*(\d+(?:\.\d+)?)([dhms])\s*$/i) { if ($2 eq "m") { $s = $1 * 60; } elsif ($2 eq "h") { $s = $1 * 60 * 60; } elsif ($2 eq "d") { $s = $1 * 60 * 60 * 24; } else { $s = $1; } } else { return undef; } $s; } sub daemonize { chdir '/' or die "Can't chdir to /: $!"; open STDIN, '/dev/null' or die "Can't read /dev/null: $!"; open STDOUT, '>/dev/null' or die "Can't write to /dev/null: $!"; defined(my $pid = fork) or die "Can't fork: $!"; exit if $pid; setsid or die "Can't start a new session: $!"; open STDERR, '>&STDOUT' or die "Can't dup stdout: $!"; } ############################################################################## package LogEntry; # Some of the more important stuff happens here use strict; use Time::HiRes qw (time alarm sleep); BEGIN { use Exporter (); use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); # set the version for version checking $VERSION = 0.01; @ISA = qw(Exporter); @EXPORT = qw(); %EXPORT_TAGS = ( ); # eg: TAG => [ qw!name1 name2! ], # your exported package globals go here, # as well as any optionally exported functions @EXPORT_OK = qw(); } use vars @EXPORT_OK; # non-exported package globals go here use vars qw(); sub new { my $proto = shift; my $class = ref($proto) || $proto; my $self = { }; bless ($self, $class); # Initialise with remaining arguments if (@_) { $self->init(@_); } return $self; } sub init (\%$$) { my ($self,$INIT,$group,$host) = @_; # We load some values from the INIT hash %{$self} = %{$INIT}; # After changing the pattern, it is sensible to reset our counters @{$self->{matches}} = (); $self->{group} = $group; $self->{host} = $host; # 0 : did not trigger # -1 : triggered because of too few matches # 1 : triggered because of too many matches $self->{status} = 0; $self->{status_time} = time; $self->{last_match} = 0; # The checkitem is a piece of code which we precompile here. my $code = 'sub { my ($r)=@_; if ('.$$INIT{'pattern'} .') { return 1; } else { return 0 } }'; &::Log(7,"Compiling: $code"); $self->{matcher} = eval $code; if ($@) { &::Log(2,"Error while compiling ".$$INIT{'name'}." ignoring"); $self->{matcher} = sub { return 0; }; } return $self->{matcher}; } sub check { my ($self,$msg) = @_; &::Log(7,"Checking ".$self->{desc}); my $code; eval { $code = &{$self->{matcher}}($msg); }; if ($@) { &::Log(2,"$self->{desc}: Fatal error while matching: $@"); return 0; } my $t = time; # Trim our data backlog while ( (scalar(@{$self->{matches}})>0) && ($t-$self->{matches}[0] > $self->{period})) { shift @{$self->{matches}} } if ($code == 1) { &::Log(7,"$self->{desc}: Matched"); # Pattern matched. Record timestamp. push @{$self->{matches}},$t; $self->{last_match} = $t; # Keep a copy of the last match %{$self->{last_matched_msg}} = %{$msg}; } my $count = scalar(@{$self->{matches}}); my $age = $t-$self->{status_time}; # First, we check if we matched too often. We don't check for # the age here since nothing is going to magically lower the match # counter. if (($count > $self->{max})) { &::Log(7,"$self->{desc}: Matched too often within period"); $self->trigger(1); # if we are below the threshold, and our age is at least # period (we need to check for the age - otherwise, we might # later on receive more messages and be alright / too high) } elsif (($count < $self->{min}) && ($age >= $self->{period})) { &::Log(7,"$self->{desc}: Matched too seldom within period"); $self->trigger(-1); # same in blue for the "ok" condition } elsif (($count > $self->{min}) && ($age >= $self->{period})) { &::Log(7,"$self->{desc}: Roger"); $self->trigger(0); } &::Log(7,"$self->{desc}: Current counter: $count"); # Abort processing if we are a final check and matched if ( ($code == 1) && ($self->{'final'} == 1) ) { &::Log(7,"$self->{desc}: Terminating walk due to final check"); return 1; } else { return 0; } &::Log(0,"Here are dragons"); die; } sub trigger { my ($self,$status) = @_; return if ($status == $self->{status}); &::Log(6,"$self->{desc}: Status change: ".$self->{status}."->".$status ." Counter: ".scalar(@{$self->{matches}})); $self->{status} = $status; $self->{status_since} = time; # We had a status change and need to send the right trap &::SendTrap($self); }